diff --git a/helpers/Dojo/SharedAssignmentHelper.ts b/helpers/Dojo/SharedAssignmentHelper.ts index f7547cc97f51c4d13d15a95f80a6bd8844ef29bc..ce7bb63aa624415204a467e96e2871d72837dd66 100644 --- a/helpers/Dojo/SharedAssignmentHelper.ts +++ b/helpers/Dojo/SharedAssignmentHelper.ts @@ -1,9 +1,9 @@ import AssignmentFile from '../../types/Dojo/AssignmentFile'; -import GitlabPipelineStatus from '../../types/Gitlab/GitlabPipelineStatus'; import DojoStatusCode from '../../types/Dojo/DojoStatusCode'; -import GitlabPipeline from '../../types/Gitlab/GitlabPipeline'; -import SharedGitlabManager from '../../managers/SharedGitlabManager'; import Json5FileValidator from '../Json5FileValidator'; +import * as Gitlab from '@gitbeaker/rest'; +import GitlabPipelineStatus from '../../types/Gitlab/GitlabPipelineStatus'; +import GitlabManager from '../../../managers/GitlabManager'; class SharedAssignmentHelper { @@ -19,11 +19,11 @@ class SharedAssignmentHelper { } } - async isPublishable(repositoryId: number): Promise<{ isPublishable: boolean, lastPipeline: GitlabPipeline | null, status?: { code: DojoStatusCode, message: string } }> { - const pipelines = await SharedGitlabManager.getRepositoryPipelines(repositoryId, 'main'); + async isPublishable(repositoryId: number): Promise<{ isPublishable: boolean, lastPipeline: Gitlab.PipelineSchema | null, status?: { code: DojoStatusCode, message: string } }> { + const pipelines = await GitlabManager.getRepositoryPipelines(repositoryId, 'main'); if ( pipelines.length > 0 ) { const lastPipeline = pipelines[0]; - if ( lastPipeline.status !== GitlabPipelineStatus.SUCCESS ) { + if ( lastPipeline.status !== GitlabPipelineStatus.SUCCESS.valueOf() ) { return { isPublishable: false, lastPipeline : lastPipeline, diff --git a/helpers/Dojo/SharedExerciseHelper.ts b/helpers/Dojo/SharedExerciseHelper.ts deleted file mode 100644 index 97ccf7c9a39682ba8b14fa65b54a89d9898ebf3c..0000000000000000000000000000000000000000 --- a/helpers/Dojo/SharedExerciseHelper.ts +++ /dev/null @@ -1,4 +0,0 @@ -class SharedExerciseHelper {} - - -export default new SharedExerciseHelper(); \ No newline at end of file diff --git a/managers/SharedGitlabManager.ts b/managers/SharedGitlabManager.ts index 68ff699a036044872cb7f33ead08782afbbdb830..48f556e13e058d16afa61fbd705cf4ea08852bb0 100644 --- a/managers/SharedGitlabManager.ts +++ b/managers/SharedGitlabManager.ts @@ -1,13 +1,38 @@ -import axios from 'axios'; -import GitlabPipeline from '../types/Gitlab/GitlabPipeline'; -import GitlabRoute from '../types/Gitlab/GitlabRoute'; -import SharedConfig from '../config/SharedConfig'; -import GitlabToken from '../types/Gitlab/GitlabToken'; +import axios from 'axios'; +import SharedConfig from '../config/SharedConfig'; +import * as GitlabCore from '@gitbeaker/core'; +import { GitbeakerRequestError } from '@gitbeaker/requester-utils'; +import { Gitlab, PipelineSchema, ProjectSchema, UserSchema } from '@gitbeaker/rest'; +import GitlabToken from '../types/Gitlab/GitlabToken'; -class GitlabManager { - private getApiUrl(route: GitlabRoute): string { - return `${ SharedConfig.gitlab.apiURL }${ route }`; +class SharedGitlabManager { + protected api!: GitlabCore.Gitlab<false>; + private readonly refreshTokenFunction?: () => Promise<string>; + + setToken(token: string) { + this.api = new Gitlab(Object.assign({ + host: SharedConfig.gitlab.URL + }, this.refreshTokenFunction ? { oauthToken: token } : { token: token })); + } + + constructor(token: string, refreshTokenFunction?: () => Promise<string>) { + this.refreshTokenFunction = refreshTokenFunction; + this.setToken(token); + } + + protected async executeGitlabRequest<T>(request: () => Promise<T>, refreshTokenIfNeeded: boolean = true): Promise<T> { + try { + return await request(); + } catch ( error ) { + if ( this.refreshTokenFunction && refreshTokenIfNeeded && error instanceof GitbeakerRequestError ) { + this.setToken(await this.refreshTokenFunction()); + + return this.executeGitlabRequest(request, false); + } else { + throw error; + } + } } async getTokens(codeOrRefresh: string, isRefresh: boolean = false, clientSecret: string = ''): Promise<GitlabToken> { @@ -23,16 +48,43 @@ class GitlabManager { return response.data; } - async getRepositoryPipelines(repoId: number, branch: string = 'main'): Promise<Array<GitlabPipeline>> { - const response = await axios.get<Array<GitlabPipeline>>(this.getApiUrl(GitlabRoute.REPOSITORY_PIPELINES).replace('{{id}}', String(repoId)), { - params: { - ref: branch - } - }); + public async getUserById(id: number): Promise<UserSchema | undefined> { + try { + return await this.executeGitlabRequest(async () => { + const user = await this.api.Users.show(id); - return response.data; + return user.id === id ? user : undefined; + }); + } catch ( e ) { + return undefined; + } + } + + public async getUserByUsername(username: string): Promise<UserSchema | undefined> { + try { + return await this.executeGitlabRequest(async () => { + const user = await this.api.Users.all({ + username: username, + maxPages: 1, + perPage : 1 + }); + + + return user.length > 0 && user[0].username === username ? user[0] : undefined; + }); + } catch ( e ) { + return undefined; + } + } + + async getRepository(projectIdOrNamespace: string): Promise<ProjectSchema> { + return this.executeGitlabRequest(() => this.api.Projects.show(projectIdOrNamespace)); + } + + async getRepositoryPipelines(repoId: number, branch: string = 'main'): Promise<Array<PipelineSchema>> { + return this.executeGitlabRequest(() => this.api.Pipelines.all(repoId, { ref: branch })); } } -export default new GitlabManager(); +export default SharedGitlabManager; diff --git a/types/Dojo/DojoStatusCode.ts b/types/Dojo/DojoStatusCode.ts index e7124ae4475bd565bd0813fa087a0cf0ac2da46c..76ed11746a292ccb238cead51f6f994885aa9bbd 100644 --- a/types/Dojo/DojoStatusCode.ts +++ b/types/Dojo/DojoStatusCode.ts @@ -1,22 +1,22 @@ enum DojoStatusCode { - LOGIN_FAILED = 1, - REFRESH_TOKENS_FAILED = 2, - CLIENT_NOT_SUPPORTED = 100, - CLIENT_VERSION_NOT_SUPPORTED = 110, - ASSIGNMENT_PUBLISH_NO_PIPELINE = 200, - ASSIGNMENT_PUBLISH_PIPELINE_FAILED = 201, - ASSIGNMENT_CREATION_GITLAB_ERROR = 202, - ASSIGNMENT_CREATION_INTERNAL_ERROR = 203, - ASSIGNMENT_EXERCISE_NOT_RELATED = 204, - ASSIGNMENT_NOT_PUBLISHED = 205, - EXERCISE_CORRECTION_NOT_EXIST = 206, - EXERCISE_CORRECTION_ALREADY_EXIST = 207, - ASSIGNMENT_NAME_CONFLICT = 208, - EXERCISE_CREATION_GITLAB_ERROR = 302, - EXERCISE_CREATION_INTERNAL_ERROR = 303, - MAX_EXERCISE_PER_ASSIGNMENT_REACHED = 304, - GITLAB_TEMPLATE_NOT_FOUND = 401, - GITLAB_TEMPLATE_ACCESS_UNAUTHORIZED = 402, + LOGIN_FAILED = 10001, + REFRESH_TOKENS_FAILED = 10002, + CLIENT_NOT_SUPPORTED = 10100, + CLIENT_VERSION_NOT_SUPPORTED = 10110, + ASSIGNMENT_PUBLISH_NO_PIPELINE = 10200, + ASSIGNMENT_PUBLISH_PIPELINE_FAILED = 10201, + ASSIGNMENT_CREATION_GITLAB_ERROR = 10202, + ASSIGNMENT_CREATION_INTERNAL_ERROR = 10203, + ASSIGNMENT_EXERCISE_NOT_RELATED = 10204, + ASSIGNMENT_NOT_PUBLISHED = 10205, + EXERCISE_CORRECTION_NOT_EXIST = 10206, + EXERCISE_CORRECTION_ALREADY_EXIST = 10207, + ASSIGNMENT_NAME_CONFLICT = 10208, + EXERCISE_CREATION_GITLAB_ERROR = 10302, + EXERCISE_CREATION_INTERNAL_ERROR = 10303, + MAX_EXERCISE_PER_ASSIGNMENT_REACHED = 10304, + GITLAB_TEMPLATE_NOT_FOUND = 10401, + GITLAB_TEMPLATE_ACCESS_UNAUTHORIZED = 10402, } diff --git a/types/Gitlab/GitlabAccessLevel.ts b/types/Gitlab/GitlabAccessLevel.ts deleted file mode 100644 index be06ffd009103feb9f30a4e18250c2fcf978527b..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabAccessLevel.ts +++ /dev/null @@ -1,11 +0,0 @@ -enum GitlabAccessLevel { - GUEST = 10, - REPORTER = 20, - DEVELOPER = 30, - MAINTAINER = 40, - OWNER = 50, - ADMIN = 60 -} - - -export default GitlabAccessLevel; diff --git a/types/Gitlab/GitlabCommit.ts b/types/Gitlab/GitlabCommit.ts deleted file mode 100644 index 5f94c2e431b220b4247e0dc3bf0222fba14f2a1c..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabCommit.ts +++ /dev/null @@ -1,17 +0,0 @@ -interface GitlabCommit { - id: string; - short_id: string; - created_at: string; - parent_ids: Array<string>; - title: string; - message: string; - author_name: string; - author_email: string; - authored_date: string; - committer_name: string; - committer_email: string; - committed_date: string; -} - - -export default GitlabCommit; \ No newline at end of file diff --git a/types/Gitlab/GitlabFile.ts b/types/Gitlab/GitlabFile.ts deleted file mode 100644 index 05205d4f1e28d5d04e60ae304acb02f3ddcb0d02..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabFile.ts +++ /dev/null @@ -1,16 +0,0 @@ -interface GitlabFile { - file_name: string, - file_path: string, - size: number, - encoding: string, - content_sha256: string, - ref: string, - blob_id: string, - commit_id: string, - last_commit_id: string, - execute_filemode: boolean, - content: string, -} - - -export default GitlabFile; \ No newline at end of file diff --git a/types/Gitlab/GitlabGroup.ts b/types/Gitlab/GitlabGroup.ts deleted file mode 100644 index 812f8838b5e00eb50cea0a282e3e26dc20344fef..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabGroup.ts +++ /dev/null @@ -1,10 +0,0 @@ -interface GitlabGroup { - group_id: number, - group_name: string, - group_full_path: string, - group_access_level: number, - expires_at: string -} - - -export default GitlabGroup; \ No newline at end of file diff --git a/types/Gitlab/GitlabMember.ts b/types/Gitlab/GitlabMember.ts deleted file mode 100644 index 6c7c7163f73104221de918af4ceb09d4a55c98e2..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabMember.ts +++ /dev/null @@ -1,12 +0,0 @@ -import GitlabUser from './GitlabUser'; - - -interface GitlabMember extends GitlabUser { - access_level: number, - created_at: string, - created_by: GitlabUser, - expires_at: string | null -} - - -export default GitlabMember; \ No newline at end of file diff --git a/types/Gitlab/GitlabMilestone.ts b/types/Gitlab/GitlabMilestone.ts deleted file mode 100644 index a7285cd9ee3683aeaf4ebc1ea85ab778af1e970c..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabMilestone.ts +++ /dev/null @@ -1,19 +0,0 @@ -interface GitlabMilestone { - id: number; - iid: number; - project_id: number; - title: string; - description: string; - state: string; - created_at: string; - updated_at: string; - due_date: string; - start_date: string; - web_url: string; - issue_stats: { - total: number; closed: number; - }; -} - - -export default GitlabMilestone; \ No newline at end of file diff --git a/types/Gitlab/GitlabNamespace.ts b/types/Gitlab/GitlabNamespace.ts deleted file mode 100644 index 4d892afb58d81138a6b204124fc5b2ed6526eeca..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabNamespace.ts +++ /dev/null @@ -1,13 +0,0 @@ -interface GitlabNamespace { - id: number, - name: string, - path: string, - kind: string, - full_path: string, - parent_id: number, - avatar_url: string, - web_url: string -} - - -export default GitlabNamespace; \ No newline at end of file diff --git a/types/Gitlab/GitlabPipeline.ts b/types/Gitlab/GitlabPipeline.ts deleted file mode 100644 index 1ee75b643b458b1f0c924f5d47f7ae0f0f88ddb0..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabPipeline.ts +++ /dev/null @@ -1,31 +0,0 @@ -import GitlabPipelineStatus from './GitlabPipelineStatus'; -import GitlabPipelineSource from './GitlabPipelineSource'; -import GitlabUser from './GitlabUser'; - - -interface GitlabPipeline { - id: number, - iid: number, - project_id: number, - status: GitlabPipelineStatus, - source: GitlabPipelineSource, - ref: string, - sha: string, - before_sha: string, - tag: boolean, - name: string, - yaml_errors: string | null, - user: GitlabUser, - web_url: string, - created_at: string, - updated_at: string, - started_at: string | null, - finished_at: string | null, - committed_at: string | null, - duration: number | null, - queued_duration: number | null, - coverage: string | null, -} - - -export default GitlabPipeline; \ No newline at end of file diff --git a/types/Gitlab/GitlabProfile.ts b/types/Gitlab/GitlabProfile.ts deleted file mode 100644 index aa7506dbddcf7051a29c118d69fc26d1f7fb55bb..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabProfile.ts +++ /dev/null @@ -1,40 +0,0 @@ -import GitlabUser from './GitlabUser'; - - -interface GitlabProfile extends GitlabUser { - created_at: string, - bio: string, - location: string, - public_email: string, - skype: string, - linkedin: string, - twitter: string, - discord: string, - website_url: string, - organization: string, - job_title: string, - pronouns: string, - bot: boolean, - work_information: string, - local_time: string, - last_sign_in_at: string, - confirmed_at: string, - last_activity_on: string, - email: string, - theme_id: number, - color_scheme_id: number, - projects_limit: number, - current_sign_in_at: string, - identities: Array<{ - provider: string, extern_uid: string - }>, - can_create_group: boolean, - can_create_project: boolean, - two_factor_enabled: boolean, - external: boolean, - private_profile: boolean, - commit_email: string -} - - -export default GitlabProfile; \ No newline at end of file diff --git a/types/Gitlab/GitlabRelease.ts b/types/Gitlab/GitlabRelease.ts deleted file mode 100644 index a7c68d770e4e88c7acd2f6f6eb1305329c42f61d..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabRelease.ts +++ /dev/null @@ -1,29 +0,0 @@ -import GitlabUser from './GitlabUser'; -import GitlabCommit from './GitlabCommit'; -import GitlabMilestone from './GitlabMilestone'; - - -interface GitlabRelease { - tag_name: string; - description: string; - created_at: string; - released_at: string; - author: GitlabUser; - commit: GitlabCommit; - milestones: Array<GitlabMilestone>; - commit_path: string; - tag_path: string; - assets: { - count: number; sources: Array<{ - format: string; url: string; - }>; links: Array<{ - id: number; name: string; url: string; link_type: string; - }>; evidence_file_path: string; - }; - evidences: Array<{ - sha: string; filepath: string; collected_at: string; - }>; -} - - -export default GitlabRelease; \ No newline at end of file diff --git a/types/Gitlab/GitlabRepository.ts b/types/Gitlab/GitlabRepository.ts deleted file mode 100644 index 0aa260287cc95030231761b2781a31a1b203f22b..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabRepository.ts +++ /dev/null @@ -1,106 +0,0 @@ -import GitlabGroup from './GitlabGroup'; -import GitlabNamespace from './GitlabNamespace'; - - -interface GitlabRepository { - id: number, - description: string, - name: string, - name_with_namespace: string, - path: string, - path_with_namespace: string, - created_at: string, - default_branch: string, - tag_list: Array<string>, - topics: Array<string>, - ssh_url_to_repo: string, - http_url_to_repo: string, - web_url: string, - readme_url: string, - forks_count: number, - avatar_url: string, - star_count: number, - last_activity_at: string, - namespace: GitlabNamespace, - _links: { - self: string, issues: string, merge_requests: string, repo_branches: string, labels: string, events: string, members: string, cluster_agents: string - }, - packages_enabled: boolean, - empty_repo: boolean, - archived: boolean, - visibility: string, - resolve_outdated_diff_discussions: boolean, - container_expiration_policy: { - cadence: string, enabled: boolean, keep_n: number, older_than: string, name_regex: string, name_regex_keep: string, next_run_at: string - }, - issues_enabled: boolean, - merge_requests_enabled: boolean, - wiki_enabled: boolean, - jobs_enabled: boolean, - snippets_enabled: boolean, - container_registry_enabled: boolean, - service_desk_enabled: boolean, - service_desk_address: string, - can_create_merge_request_in: boolean, - issues_access_level: string, - repository_access_level: string, - merge_requests_access_level: string, - forking_access_level: string, - wiki_access_level: string, - builds_access_level: string, - snippets_access_level: string, - pages_access_level: string, - operations_access_level: string, - analytics_access_level: string, - container_registry_access_level: string, - security_and_compliance_access_level: string, - releases_access_level: string, - environments_access_level: string, - feature_flags_access_level: string, - infrastructure_access_level: string, - monitor_access_level: string, - emails_disabled: boolean, - shared_runners_enabled: boolean, - lfs_enabled: boolean, - creator_id: number, - import_url: string, - import_type: string, - import_status: string, - import_error: string, - open_issues_count: number, - runners_token: string, - ci_default_git_depth: number, - ci_forward_deployment_enabled: boolean, - ci_job_token_scope_enabled: boolean, - ci_separated_caches: boolean, - ci_opt_in_jwt: boolean, - ci_allow_fork_pipelines_to_run_in_parent_project: boolean, - public_jobs: boolean, - build_git_strategy: string, - build_timeout: number, - auto_cancel_pending_pipelines: string, - ci_config_path: string, - shared_with_groups: Array<GitlabGroup>, - only_allow_merge_if_pipeline_succeeds: boolean, - allow_merge_on_skipped_pipeline: boolean, - restrict_user_defined_variables: boolean, - request_access_enabled: boolean, - only_allow_merge_if_all_discussions_are_resolved: boolean, - remove_source_branch_after_merge: boolean, - printing_merge_request_link_enabled: boolean, - merge_method: string, - squash_option: string, - enforce_auth_checks_on_uploads: boolean, - suggestion_commit_message: string, - merge_commit_template: string, - squash_commit_template: string, - issue_branch_template: string, - auto_devops_enabled: boolean, - auto_devops_deploy_strategy: string, - autoclose_referenced_issues: boolean, - keep_latest_artifact: boolean, - runner_token_expiration_interval: number, -} - - -export default GitlabRepository; \ No newline at end of file diff --git a/types/Gitlab/GitlabRoute.ts b/types/Gitlab/GitlabRoute.ts deleted file mode 100644 index 15f066174f3483f149fbaa164c9176cec2b43993..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabRoute.ts +++ /dev/null @@ -1,25 +0,0 @@ -const projectIdRoute = '/projects/{{id}}'; - - -enum GitlabRoute { - NOTIFICATION_SETTINGS = '/notification_settings', - PROFILE_GET = '/user', - USERS_GET = '/users', - REPOSITORY_GET = '/projects/{{id}}', - REPOSITORY_CREATE = '/projects', // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values - REPOSITORY_DELETE = projectIdRoute, // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values - REPOSITORY_EDIT = projectIdRoute, - REPOSITORY_FORK = '/projects/{{id}}/fork', - REPOSITORY_MEMBER_ADD = '/projects/{{id}}/members', - REPOSITORY_MEMBERS_GET = '/projects/{{id}}/members/all', - REPOSITORY_RELEASES_GET = '/projects/{{id}}/releases', - REPOSITORY_BADGES_ADD = '/projects/{{id}}/badges', - REPOSITORY_VARIABLES_ADD = '/projects/{{id}}/variables', - REPOSITORY_BRANCHES_PROTECT = '/projects/{{id}}/protected_branches', - REPOSITORY_TREE = '/projects/{{id}}/repository/tree', - REPOSITORY_FILE = '/projects/{{id}}/repository/files/{{filePath}}', - REPOSITORY_PIPELINES = '/projects/{{id}}/pipelines', -} - - -export default GitlabRoute; \ No newline at end of file diff --git a/types/Gitlab/GitlabTreeFile.ts b/types/Gitlab/GitlabTreeFile.ts deleted file mode 100644 index b2cf67ecb1d636838ff2e48cbc6ce62e11248476..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabTreeFile.ts +++ /dev/null @@ -1,13 +0,0 @@ -import GitlabTreeFileType from './GitlabTreeFileType'; - - -interface GitlabTreeFile { - id: number, - name: string, - type: GitlabTreeFileType, - path: string, - mode: string -} - - -export default GitlabTreeFile; \ No newline at end of file diff --git a/types/Gitlab/GitlabUser.ts b/types/Gitlab/GitlabUser.ts deleted file mode 100644 index bbb759264764020b1dd80cca050392371b8e87b7..0000000000000000000000000000000000000000 --- a/types/Gitlab/GitlabUser.ts +++ /dev/null @@ -1,11 +0,0 @@ -interface GitlabUser { - id: number, - username: string, - name: string, - state: string, - avatar_url: string, - web_url: string, -} - - -export default GitlabUser; \ No newline at end of file diff --git a/types/Gitlab/GitlabVisibility.ts b/types/Gitlab/GitlabVisibility.ts index 842ff168e274cb6cfb2a39ef7a952cdb5248c1b9..1eaf63640d08ae3c3bac00f74922ce7d0c2fcbbd 100644 --- a/types/Gitlab/GitlabVisibility.ts +++ b/types/Gitlab/GitlabVisibility.ts @@ -1,8 +1,4 @@ -enum GitlabVisibility { - PUBLIC = 'public', - INTERNAL = 'internal', - PRIVATE = 'private' -} +type GitlabVisibility = 'public' | 'internal' | 'private'; export default GitlabVisibility;