import axios from 'axios'; import Config from '../config/Config'; import GitlabRepository from '../shared/types/Gitlab/GitlabRepository'; import GitlabAccessLevel from '../shared/types/Gitlab/GitlabAccessLevel'; import GitlabMember from '../shared/types/Gitlab/GitlabMember'; import { StatusCodes } from 'http-status-codes'; import GitlabVisibility from '../shared/types/Gitlab/GitlabVisibility'; import ApiRequest from '../types/ApiRequest'; import GitlabUser from '../shared/types/Gitlab/GitlabUser'; import GitlabRoutes from '../shared/types/Gitlab/GitlabRoutes'; class GitlabManager { private getApiUrl(route: GitlabRoutes): string { return `${ Config.gitlab.apiURL }${ route }`; } private async getGitlabUser(paramToSearch: string | number, paramName: string): Promise<GitlabUser | undefined> { try { const params: any = {}; params[paramName] = paramToSearch; return (await axios.get<Array<GitlabUser>>(this.getApiUrl(GitlabRoutes.USERS_GET), { params: params })).data[0]; } catch ( e ) { } return undefined; } public async getUserById(id: number): Promise<GitlabUser | undefined> { return await this.getGitlabUser(id, 'id'); } public async getUserByUsername(username: string): Promise<GitlabUser | undefined> { return await this.getGitlabUser(username, 'search'); } async getRepository(idOrNamespace: string): Promise<GitlabRepository> { const response = await axios.get<GitlabRepository>(this.getApiUrl(GitlabRoutes.REPOSITORY_GET).replace('{{id}}', encodeURIComponent(idOrNamespace))); return response.data; } async getRepositoryMembers(idOrNamespace: string): Promise<Array<GitlabMember>> { const response = await axios.get<Array<GitlabMember>>(this.getApiUrl(GitlabRoutes.REPOSITORY_MEMBERS_GET).replace('{{id}}', encodeURIComponent(idOrNamespace))); return response.data; } async createRepository(name: string, description: string, visibility: string, initializeWithReadme: boolean, namespace: number, sharedRunnersEnabled: boolean, wikiEnabled: boolean, import_url: string): Promise<GitlabRepository> { const response = await axios.post<GitlabRepository>(this.getApiUrl(GitlabRoutes.REPOSITORY_CREATE), { name : name, description : description, import_url : import_url, initialize_with_readme: initializeWithReadme, namespace_id : namespace, shared_runners_enabled: sharedRunnersEnabled, visibility : visibility, wiki_enabled : wikiEnabled }); return response.data; } async forkRepository(forkId: number, name: string, path: string, description: string, visibility: string, namespace: number): Promise<GitlabRepository> { const response = await axios.post<GitlabRepository>(this.getApiUrl(GitlabRoutes.REPOSITORY_FORK).replace('{{id}}', String(forkId)), { name : name, path : path, description : description, namespace_id: namespace, visibility : visibility }); return response.data; } async addRepositoryMember(repoId: number, userId: number, accessLevel: GitlabAccessLevel): Promise<GitlabMember> { const response = await axios.post<GitlabMember>(this.getApiUrl(GitlabRoutes.REPOSITORY_MEMBER_ADD).replace('{{id}}', String(repoId)), { user_id : userId, access_level: accessLevel }); return response.data; } async checkTemplateAccess(idOrNamespace: string, req: ApiRequest): Promise<StatusCodes> { // Get the Gitlab project and check if it have public or internal visibility try { const project: GitlabRepository = await this.getRepository(idOrNamespace); if ( [ GitlabVisibility.Public.valueOf(), GitlabVisibility.Internal.valueOf() ].includes(project.visibility) ) { return StatusCodes.OK; } } catch ( e ) { return StatusCodes.NOT_FOUND; } // Check if the user and dojo are members (with at least reporter access) of the project const members = await this.getRepositoryMembers(idOrNamespace); const isUsersAtLeastReporter = { user: false, dojo: false }; members.forEach(member => { if ( member.access_level >= GitlabAccessLevel.REPORTER ) { if ( member.id === req.session.profile.gitlabId ) { isUsersAtLeastReporter.user = true; } else if ( member.id === Config.gitlab.account.id ) { isUsersAtLeastReporter.dojo = true; } } }); return isUsersAtLeastReporter.user && isUsersAtLeastReporter.dojo ? StatusCodes.OK : StatusCodes.UNAUTHORIZED; } } export default new GitlabManager();