Skip to content

Commit 9141019

Browse files
....
> 50 | fetchDocumentsAction, | ^^^^^^^^^^^^^^^^^^^^^ > 51 |
1 parent 3499562 commit 9141019

1 file changed

Lines changed: 31 additions & 37 deletions

File tree

src/app/(app)/projects/[id]/actions.ts

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
deleteProjectAnnouncement as dbDeleteProjectAnnouncement,
3333
updateProjectGithubRepo as dbUpdateProjectGithubRepo,
3434
getUserGithubOAuthToken as dbGetUserGithubOAuthToken,
35-
// getUserGithubInstallation, // Not used directly, part of GitHub client
3635
} from '@/lib/db';
3736
import { z } from 'zod';
3837
import { auth } from '@/lib/authEdge';
@@ -565,8 +564,8 @@ async function updateReadmeOnGithub(octokit: Octokit, owner: string, repo: strin
565564
message: 'Update README.md from FlowUp',
566565
content: Buffer.from(content).toString('base64'),
567566
committer: {
568-
name: 'FlowUp Bot', // Or use the user's GitHub name if available
569-
email: 'bot@flowup.app', // Or user's email if allowed and consented
567+
name: 'FlowUp Bot',
568+
email: 'bot@flowup.app',
570569
},
571570
};
572571
if (existingSha) {
@@ -614,7 +613,7 @@ export async function saveProjectReadmeAction(prevState: SaveProjectReadmeFormSt
614613
if (!userRole || !['owner', 'co-owner', 'editor'].includes(userRole)) {
615614
return { error: "You do not have permission to edit the README for this project." };
616615
}
617-
616+
618617
const updatedProject = await dbUpdateProjectReadme(projectUuid, readmeContent);
619618
if (!updatedProject) {
620619
return { error: "Failed to save README in FlowUp." };
@@ -624,7 +623,7 @@ export async function saveProjectReadmeAction(prevState: SaveProjectReadmeFormSt
624623
const oauthToken = await dbGetUserGithubOAuthToken(session.user.uuid);
625624
if (oauthToken?.accessToken) {
626625
const octokit = new Octokit({ auth: oauthToken.accessToken });
627-
626+
628627
const repoParts = updatedProject.githubRepoName.split('/');
629628
if (repoParts.length !== 2) {
630629
console.error(`[saveProjectReadmeAction] Invalid githubRepoName format: ${updatedProject.githubRepoName}`);
@@ -635,23 +634,23 @@ export async function saveProjectReadmeAction(prevState: SaveProjectReadmeFormSt
635634
console.error(`[saveProjectReadmeAction] Invalid owner or repo after splitting githubRepoName: ${updatedProject.githubRepoName}`);
636635
return { message: "README saved in FlowUp, but GitHub owner or repo name is invalid for GitHub update.", project: updatedProject };
637636
}
638-
637+
639638
let existingSha: string | null = null;
640639
try {
641640
const { data: readmeData } = await octokit.rest.repos.getContent({
642641
owner,
643642
repo,
644643
path: 'README.md',
645644
});
646-
if ('sha' in readmeData && readmeData.type === 'file') {
645+
if ('sha' in readmeData && readmeData.type === 'file') {
647646
existingSha = readmeData.sha;
648647
}
649648
} catch (error: any) {
650-
if (error.status !== 404) {
649+
if (error.status !== 404) {
651650
console.warn(`[saveProjectReadmeAction] Could not fetch existing README SHA for ${owner}/${repo}:`, error.message);
652651
}
653652
}
654-
653+
655654
await updateReadmeOnGithub(octokit, owner, repo, readmeContent, existingSha);
656655
return { message: "README saved in FlowUp and updated on GitHub.", project: updatedProject };
657656
} else {
@@ -733,7 +732,7 @@ export async function toggleProjectVisibilityAction(prevState: ToggleProjectVisi
733732
if (userRole !== 'owner' && globalUser?.role !== 'admin') {
734733
return { error: `Only project owners or admins can change project visibility. Your project role: ${userRole || 'not a member'}, global role: ${globalUser?.role || 'unknown'}. UUID: ${session.user.uuid}` };
735734
}
736-
735+
737736
const updatedProjectInDb = await dbUpdateProjectVisibility(projectUuid, isPrivate);
738737
if (!updatedProjectInDb) {
739738
return { error: "Failed to update project visibility in FlowUp." };
@@ -1105,7 +1104,6 @@ export async function deleteProjectAnnouncementAction(
11051104
}
11061105

11071106
// GitHub OAuth and Repo Actions
1108-
11091107
export async function fetchUserGithubOAuthTokenAction(): Promise<UserGithubOAuthToken | null> {
11101108
const session = await auth();
11111109
if (!session?.user?.uuid) {
@@ -1122,7 +1120,7 @@ export async function fetchUserGithubOAuthTokenAction(): Promise<UserGithubOAuth
11221120
}
11231121

11241122
function sanitizeRepoName(name: string | null | undefined): string {
1125-
if (!name) {
1123+
if (!name) {
11261124
return '';
11271125
}
11281126
const trimmedName = name.trim();
@@ -1131,13 +1129,13 @@ function sanitizeRepoName(name: string | null | undefined): string {
11311129
}
11321130

11331131
let sanitized = trimmedName
1134-
.replace(/\s+/g, '-') // Replace spaces with hyphens
1135-
.replace(/[^a-zA-Z0-9_.-]/g, '') // Remove invalid characters
1136-
.replace(/-+/g, '-') // Replace multiple hyphens with a single one
1137-
.replace(/^\.+|\.$/g, '') // Remove leading/trailing dots
1138-
.replace(/^-+|-+$/g, ''); // Remove leading/trailing hyphens
1139-
1140-
return sanitized.substring(0, 100); // GitHub repo name max length is 100
1132+
.replace(/\s+/g, '-')
1133+
.replace(/[^a-zA-Z0-9_.-]/g, '')
1134+
.replace(/-+/g, '-')
1135+
.replace(/^\.+|\.$/g, '')
1136+
.replace(/^-+|-+$/g, '');
1137+
1138+
return sanitized.substring(0, 100);
11411139
}
11421140

11431141

@@ -1165,7 +1163,7 @@ export async function linkProjectToGithubAction(
11651163

11661164
if (useDefaultRepoName) {
11671165
if (typeof flowUpProjectNameValue === 'string' && flowUpProjectNameValue.trim() !== '') {
1168-
nameForRepoCreation = `FlowUp-${flowUpProjectNameValue}`;
1166+
nameForRepoCreation = `FlowUp - ${flowUpProjectNameValue}`;
11691167
} else {
11701168
return { error: "FlowUp Project Name is required to generate the default repository name." };
11711169
}
@@ -1176,7 +1174,7 @@ export async function linkProjectToGithubAction(
11761174
return { error: "Custom repository name cannot be empty." };
11771175
}
11781176
}
1179-
1177+
11801178
const repoSlug = sanitizeRepoName(nameForRepoCreation);
11811179
if (!repoSlug) {
11821180
return { error: "Resulting repository name is invalid after sanitization. Please provide a valid name." };
@@ -1210,24 +1208,23 @@ export async function linkProjectToGithubAction(
12101208
name: repoSlug,
12111209
private: repoIsPrivate,
12121210
description: `Repository for FlowUp project: ${projectFromDb.name}`,
1213-
auto_init: true,
1211+
auto_init: true,
12141212
});
12151213
console.log(`Successfully created repository: ${createdRepo.data.html_url}`);
12161214

12171215
if (projectFromDb.readmeContent && projectFromDb.readmeContent.trim() !== '') {
1218-
// Fetch existing README's SHA to avoid errors if it was created by auto_init
12191216
let existingReadmeSha: string | undefined = undefined;
12201217
try {
12211218
const { data: readmeData } = await octokit.rest.repos.getContent({
12221219
owner: createdRepo.data.owner.login,
12231220
repo: createdRepo.data.name,
12241221
path: 'README.md',
12251222
});
1226-
if ('sha' in readmeData && readmeData.type === 'file') { // Check if readmeData is a file object
1223+
if ('sha' in readmeData && readmeData.type === 'file') {
12271224
existingReadmeSha = readmeData.sha;
12281225
}
12291226
} catch (getContentError: any) {
1230-
if (getContentError.status !== 404) { // Log error if not a "file not found"
1227+
if (getContentError.status !== 404) {
12311228
console.warn(`[linkProjectToGithubAction] Could not fetch existing README SHA for ${createdRepo.data.owner.login}/${createdRepo.data.name}:`, getContentError.message);
12321229
}
12331230
}
@@ -1237,14 +1234,17 @@ export async function linkProjectToGithubAction(
12371234
} catch (apiError: any) {
12381235
console.error(`GitHub API error creating repository: ${apiError.status} ${apiError.message}`, apiError.response?.data);
12391236
const errorMessage = apiError.response?.data?.message || apiError.message || 'Unknown GitHub API error.';
1240-
if (apiError.status === 422) { // Unprocessable Entity (e.g., repo already exists)
1237+
if (apiError.status === 403) {
1238+
return { error: `GitHub Permission Denied: ${errorMessage}. Ensure your GitHub account has permissions to create repositories and the FlowUp OAuth App has the 'repo' scope.`};
1239+
}
1240+
if (apiError.status === 422) {
12411241
return { error: `Failed to create GitHub repository '${repoSlug}'. It might already exist or there's a naming conflict. GitHub's message: ${errorMessage}` };
12421242
}
12431243
return { error: `GitHub API Error (${apiError.status || 'unknown'}): ${errorMessage} - ${apiError.documentation_url || ''}` };
12441244
}
12451245

12461246
const repoUrl = createdRepo.data.html_url;
1247-
const actualRepoName = createdRepo.data.full_name;
1247+
const actualRepoName = createdRepo.data.full_name;
12481248

12491249
const updatedProject = await dbUpdateProjectGithubRepo(projectUuid, repoUrl, actualRepoName);
12501250

@@ -1260,13 +1260,9 @@ export async function linkProjectToGithubAction(
12601260
}
12611261
}
12621262

1263-
/*
1264-
// This function might be needed if we switch back to GitHub App installation flow for repo creation
1265-
// For now, with OAuth flow, it's not directly used for creating repos but good for fetching installation details
1266-
// if we need to interact with the app installation itself.
1267-
export async function fetchUserGithubAccessDetailsAction(userUuid: string): Promise<{
1263+
async function fetchUserGithubAccessDetailsAction(userUuid: string): Promise<{
12681264
oauthToken: UserGithubOAuthToken | null;
1269-
installation: UserGithubInstallation | null; // Placeholder, not fully implemented for OAuth flow
1265+
installation: UserGithubInstallation | null;
12701266
}> {
12711267
const session = await auth();
12721268
if (!session?.user?.uuid || session.user.uuid !== userUuid) {
@@ -1275,13 +1271,11 @@ export async function fetchUserGithubAccessDetailsAction(userUuid: string): Prom
12751271
}
12761272
try {
12771273
const oauthToken = await dbGetUserGithubOAuthToken(userUuid);
1278-
// const installation = await getUserGithubInstallation(userUuid); // This is for GitHub App installs
1279-
return { oauthToken, installation: null }; // Return null for installation in pure OAuth flow
1274+
return { oauthToken, installation: null };
12801275
} catch (error) {
12811276
console.error("[fetchUserGithubAccessDetailsAction] Error fetching GitHub access details:", error);
12821277
return { oauthToken: null, installation: null };
12831278
}
12841279
}
1285-
*/
12861280

1287-
```
1281+

0 commit comments

Comments
 (0)