diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts index 922c126c5d7205de5de12136b80fcc980686ddcc..96989cbd46486fe444202534c21fa35bd091faac 100644 --- a/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts +++ b/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts @@ -36,7 +36,6 @@ class AssignmentCreateCommand extends CommanderCommand { if ( !await AccessesHelper.checkTeachingStaff() ) { throw new Error(); } - this.members = await GitlabManager.fetchMembers(options); if ( !this.members ) { throw new Error(); diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentExportCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentExportCommand.ts index 0aaf0ae71749233a24d2d87ef01ff90bdacedc86..90c755e6ce65468a2c99e05701eb99b67331a6e2 100644 --- a/NodeApp/src/commander/assignment/subcommands/AssignmentExportCommand.ts +++ b/NodeApp/src/commander/assignment/subcommands/AssignmentExportCommand.ts @@ -1,23 +1,74 @@ import CommanderCommand from '../../CommanderCommand.js'; -// import ExerciseRunHelper from '../../../helpers/Dojo/ExerciseRunHelper.js'; -// import GlobalHelper from '../../../helpers/GlobalHelper.js'; import DojoBackendManager from '../../../managers/DojoBackendManager.js'; +import AccessesHelper from '../../../helpers/AccessesHelper.js'; +import ora from 'ora'; +import GitlabManager from '../../../managers/GitlabManager.js'; +import TextStyle from '../../../types/TextStyle.js'; +import Assignment from '../../../sharedByClients/models/Assignment.js'; +// import User from '../../../sharedByClients/models/User.js'; +type CommandOptions = { name : string, clone? : string | boolean } class AssignmentExportCommand extends CommanderCommand { protected commandName: string = 'export'; - + + private assignment!: Assignment | undefined; + protected defineCommand() { this.command - .description('create a new repository for an assignment') - .argument('<id or namespace>', 'name or url (http/s or ssh) of the assignment') - .action(this.commandAction.bind(this)); + .description('export a repository in an archive') + .argument('<userId>', 'name or url (http/s or ssh) of the assignment') + // .argument('<full>', 'export full') + .action(this.commandAction.bind(this)); } - - protected async commandAction(idOrNamespace: string): Promise<void> { - const tmp = DojoBackendManager.exportAssignment(idOrNamespace); - console.log(tmp); + + private async cloneRepository(idOrNamespace : string) { + console.log(TextStyle.BLOCK('Please wait while we are cloning the repository...')); + this.assignment = await DojoBackendManager.getAssignment(idOrNamespace); + console.log(this.assignment); + await GitlabManager.cloneRepository('./', this.assignment!.gitlabCreationInfo.http_url_to_repo, undefined, true, 0); } + + protected async commandAction(userId : string): Promise<void> { + let user; + let tmp; + + if ( !await AccessesHelper.checkTeachingStaff() ) { + throw new Error(); + } + const spinner: ora.Ora = ora({ + text : 'Archiving all assignments', + indent: 8 + }).start(); + + try { + // this.cloneRepository(idOrNamespace); + user = await DojoBackendManager.getUserAssignments(userId); + if (user && user.assignments && user.assignments.length > 0) { + + const assignmentRequests = user.assignments.map(a => + DojoBackendManager.exportLightAssignment(String(a.name)) + ); + + // Attendre que toutes les promesses soient résolues + const results = await Promise.all(assignmentRequests); + + // Vérifier les résultats et traiter en conséquence + results.forEach(result => { + if (result) { + console.log(result); + } else { + console.error('Failed to archive some assignments\n'); + } + }); + } + // DojoBackendManager.exportLightAssignment(userId); + + spinner.succeed('Archiving successful\n'); + } catch (error) { + spinner.fail(`Failed to create an archive\n`); + } + } } diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts index 07b9e80e2ed2616a7b46cee4080575f06e11c3b7..d395fce7b19b011f199092ebe56f5ae4903651af 100644 --- a/NodeApp/src/managers/DojoBackendManager.ts +++ b/NodeApp/src/managers/DojoBackendManager.ts @@ -223,13 +223,34 @@ class DojoBackendManager { } } - public async exportAssignment(idOrNamespace: string) { + public async exportLightAssignment(idOrNamespace: string) { try { return (await axios.get<DojoBackendResponse<null>>(DojoBackendHelper.getApiUrl(ApiRoute.ASSIGNMENT_ARCHIVE, { assignmentNameOrUrl: idOrNamespace}))).data.data; } catch ( error ) { return undefined; } } + + public async getUserAssignments(id : string, verbose: boolean = true) { + // const spinner: ora.Ora = ora('Fetching user\'s assignments...'); + + // if ( verbose ) { + // spinner.start(); + // } + + try { + return ((await axios.get<DojoBackendResponse<User>>(DojoBackendHelper.getApiUrl(ApiRoute.USER_ASSIGNMENTS, + { + assignmentNameOrUrl : id + }).replace('{{userId}}', id))).data.data); + } catch (error) { + // this.handleApiError(error, spinner, verbose, `Fetching user's assignments error : ${ error }`); + + throw error; + } + // return (await axios.get<DojoBackendResponse<User>>(this.getApiUrl(ApiRoute.USER_ASSIGNMENTS).replace('{{userId}}', id))).data.data; + } + } diff --git a/NodeApp/src/managers/GitlabManager.ts b/NodeApp/src/managers/GitlabManager.ts index 0e6c92e364f91e6cfe1be20508acd20dd2aee73b..bbcd6488d959054fde5dfd2c93fb46759f245606 100644 --- a/NodeApp/src/managers/GitlabManager.ts +++ b/NodeApp/src/managers/GitlabManager.ts @@ -14,33 +14,33 @@ class GitlabManager extends SharedGitlabManager { constructor() { super('', GlobalHelper.refreshGitlabTokenFunction.bind(GlobalHelper)); } - + public async testToken(verbose: boolean = true): Promise<[ boolean, boolean ]> { if ( verbose ) { ora('Checking Gitlab token: ').start().info(); } - + const result: [ boolean, boolean ] = [ false, false ]; - + type NotificationSettings = { level: string } - + let notificationSettings: NotificationSettings = { level: 'error' }; - + // Test read access { const spinnerRead: ora.Ora = ora({ - text : `Read access`, - indent: 4 - }); + text : `Read access`, + indent: 4 + }); if ( verbose ) { spinnerRead.start(); } - + try { notificationSettings = await this.getNotificationSettings(); - + result[0] = true; - + if ( verbose ) { spinnerRead.succeed(); } @@ -50,28 +50,28 @@ class GitlabManager extends SharedGitlabManager { } } } - + // Test write access { const spinnerWrite: ora.Ora = ora({ - text : `Write access`, - indent: 4 - }); + text : `Write access`, + indent: 4 + }); if ( verbose ) { spinnerWrite.start(); } - + const someLevelTypes = [ 'disabled', 'participating' ]; - + try { const oldSettings = notificationSettings; const newSettings = { level: someLevelTypes[someLevelTypes[0] === oldSettings.level ? 1 : 0] }; - + await this.setNotificationSettings(newSettings); await this.setNotificationSettings(oldSettings); - + result[1] = true; - + if ( verbose ) { spinnerWrite.succeed(); } @@ -81,31 +81,31 @@ class GitlabManager extends SharedGitlabManager { } } } - + return result; } - + public getNotificationSettings(): Promise<NotificationSettingSchema> { return this.executeGitlabRequest(() => this.api.NotificationSettings.show()); } - + public setNotificationSettings(newSettings: GitlabCore.EditNotificationSettingsOptions) { return this.executeGitlabRequest(() => this.api.NotificationSettings.edit(newSettings)); } - + private async getGitlabUsers(paramsToSearch: Array<string | number>, searchFunction: getGitlabUser, verbose: boolean = false, verboseIndent: number = 0): Promise<Array<UserSchema | undefined>> { try { return await Promise.all(paramsToSearch.map(async param => { const spinner: ora.Ora = ora({ - text : `Getting user ${ param }`, - indent: verboseIndent - }); + text : `Getting user ${ param }`, + indent: verboseIndent + }); if ( verbose ) { spinner.start(); } - + const user = await searchFunction(param); - + if ( user ) { if ( verbose ) { spinner.succeed(`${ user.username } (${ user.id })`); @@ -115,7 +115,7 @@ class GitlabManager extends SharedGitlabManager { if ( verbose ) { spinner.fail(`${ param }`); } - + return undefined; } })); @@ -123,25 +123,25 @@ class GitlabManager extends SharedGitlabManager { return [ undefined ]; } } - + public async getUsersById(ids: Array<number>, verbose: boolean = false, verboseIndent: number = 0): Promise<Array<UserSchema | undefined>> { return this.getGitlabUsers(ids, this.getUserById.bind(this) as getGitlabUser, verbose, verboseIndent); } - + public async getUsersByUsername(usernames: Array<string>, verbose: boolean = false, verboseIndent: number = 0): Promise<Array<UserSchema | undefined>> { return this.getGitlabUsers(usernames, this.getUserByUsername.bind(this) as getGitlabUser, verbose, verboseIndent); } - + public async fetchMembers(options: { members_id?: Array<number>, members_username?: Array<string> }): Promise<Array<UserSchema> | undefined> { if ( options.members_id || options.members_username ) { ora('Checking Gitlab members:').start().info(); } - + let members: Array<UserSchema> = []; - + async function isUsersExists<T>(context: unknown, functionName: string, paramsToSearch: Array<T>): Promise<boolean> { const users = await ((context as { [functionName: string]: (arg: Array<T>, verbose: boolean, verboseIndent: number) => Promise<Array<UserSchema | undefined>> })[functionName])(paramsToSearch, true, 8); - + if ( users.every(user => user) ) { members = members.concat(users as Array<UserSchema>); return true; @@ -149,58 +149,58 @@ class GitlabManager extends SharedGitlabManager { return false; } } - + let result = true; - + if ( options.members_id ) { ora({ - text : 'Fetching members by id:', - indent: 4 - }).start().info(); - + text : 'Fetching members by id:', + indent: 4 + }).start().info(); + result = await isUsersExists(this, 'getUsersById', options.members_id); } - + if ( options.members_username ) { ora({ - text : 'Fetching members by username:', - indent: 4 - }).start().info(); - + text : 'Fetching members by username:', + indent: 4 + }).start().info(); + result = result && await isUsersExists(this, 'getUsersByUsername', options.members_username); } - + return result ? members.removeObjectDuplicates(gitlabUser => gitlabUser.id) : undefined; } - + public async cloneRepository(clonePath: string | boolean, repositorySshUrl: string, folderName?: string, verbose: boolean = false, verboseIndent: number = 0) { let path = './'; if ( typeof clonePath === 'string' ) { path = clonePath; - + fs.mkdirSync(path, { recursive: true }); } - + let cloningSpinner!: ora.Ora; if ( verbose ) { cloningSpinner = ora({ - text : 'Cloning the repository...', - indent: verboseIndent - }).start(); + text : 'Cloning the repository...', + indent: verboseIndent + }).start(); } - + try { await new Promise<void>((resolve, reject) => { const gitClone = spawn(`git clone ${ repositorySshUrl } "${ folderName?.replace(' ', '_') ?? '' }"`, { cwd : path, shell: true }); - + gitClone.on('exit', code => { code !== null && code === 0 ? resolve() : reject(); }); }); - + if ( verbose ) { cloningSpinner.succeed('Repository cloned'); } diff --git a/NodeApp/src/sharedByClients b/NodeApp/src/sharedByClients index 4011aa146ae4b808da599b8eb0cca2d36e82a52c..1232b31c642007409232e9244a7173265cf1f0b8 160000 --- a/NodeApp/src/sharedByClients +++ b/NodeApp/src/sharedByClients @@ -1 +1 @@ -Subproject commit 4011aa146ae4b808da599b8eb0cca2d36e82a52c +Subproject commit 1232b31c642007409232e9244a7173265cf1f0b8