Select Git revision
GitlabManager.ts
Forked from
Dojo Project (HES-SO) / Projects / Backend / DojoBackendAPI
Source project has a limited visibility.
GitlabManager.ts 10.49 KiB
import Config from '../config/Config';
import { StatusCodes } from 'http-status-codes';
import GitlabVisibility from '../shared/types/Gitlab/GitlabVisibility';
import express from 'express';
import SharedConfig from '../shared/config/SharedConfig';
import { CommitSchema, ExpandedUserSchema, Gitlab, MemberSchema, ProjectBadgeSchema, ProjectSchema, ReleaseSchema, RepositoryFileExpandedSchema, RepositoryFileSchema, RepositoryTreeSchema } from '@gitbeaker/rest';
import logger from '../shared/logging/WinstonLogger';
import { AccessLevel, EditProjectOptions, ProjectVariableSchema, ProtectedBranchAccessLevel, ProtectedBranchSchema } from '@gitbeaker/core';
import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode';
import SharedGitlabManager from '../shared/managers/SharedGitlabManager';
class GitlabManager extends SharedGitlabManager {
constructor() {
super(Config.gitlab.account.token);
}
getUserProfile(token: string): Promise<ExpandedUserSchema> | undefined {
try {
const profileApi = new Gitlab({
host : SharedConfig.gitlab.URL,
oauthToken: token
});
return profileApi.Users.showCurrentUser();
} catch ( e ) {
return undefined;
}
}
getRepositoryMembers(idOrNamespace: string): Promise<Array<MemberSchema>> {
return this.api.ProjectMembers.all(idOrNamespace, { includeInherited: true });
}
getRepositoryReleases(repoId: number): Promise<Array<ReleaseSchema>> {
return this.api.ProjectReleases.all(repoId);
}
async getRepositoryLastCommit(repoId: number, branch: string = 'main'): Promise<CommitSchema | undefined> {
try {
const commits = await this.api.Commits.all(repoId, {
refName : branch,
maxPages: 1,
perPage : 1
});
return commits.length > 0 ? commits[0] : undefined;
} catch ( e ) {
logger.error(JSON.stringify(e));
return undefined;
}
}
createRepository(name: string, description: string, visibility: 'public' | 'internal' | 'private', initializeWithReadme: boolean, namespace: number, sharedRunnersEnabled: boolean, wikiEnabled: boolean, importUrl: string): Promise<ProjectSchema> {
return this.api.Projects.create({
name : name,
description : description,
importUrl : importUrl,
initializeWithReadme: initializeWithReadme,
namespaceId : namespace,
sharedRunnersEnabled: sharedRunnersEnabled,
visibility : visibility,
wikiAccessLevel : wikiEnabled ? 'enabled' : 'disabled'
});
}
deleteRepository(repoId: number): Promise<void> {
return this.api.Projects.remove(repoId);
}
forkRepository(forkId: number, name: string, path: string, description: string, visibility: 'public' | 'internal' | 'private', namespace: number): Promise<ProjectSchema> {
return this.api.Projects.fork(forkId, {
name : name,
path : path,
description: description,
namespaceId: namespace,
visibility : visibility
});
}
editRepository(repoId: number, newAttributes: EditProjectOptions): Promise<ProjectSchema> {
return this.api.Projects.edit(repoId, newAttributes);
}
changeRepositoryVisibility(repoId: number, visibility: GitlabVisibility): Promise<ProjectSchema> {
return this.editRepository(repoId, { visibility: visibility });
}
addRepositoryMember(repoId: number, userId: number, accessLevel: Exclude<AccessLevel, AccessLevel.ADMIN>): Promise<MemberSchema> {
return this.api.ProjectMembers.add(repoId, userId, accessLevel);
}
addRepositoryVariable(repoId: number, key: string, value: string, isProtected: boolean, isMasked: boolean): Promise<ProjectVariableSchema> {
return this.api.ProjectVariables.create(repoId, key, value, {
variableType: 'env_var',
protected : isProtected,
masked : isMasked
});
}
addRepositoryBadge(repoId: number, linkUrl: string, imageUrl: string, name: string): Promise<ProjectBadgeSchema> {
return this.api.ProjectBadges.add(repoId, linkUrl, imageUrl, {
name: name
});
}
async checkTemplateAccess(projectIdOrNamespace: string, req: express.Request, res?: express.Response): Promise<boolean> {
// Get the Gitlab project and check if it have public or internal visibility
try {
const project: ProjectSchema = await this.getRepository(projectIdOrNamespace);
if ( [ 'public', 'internal' ].includes(project.visibility) ) {
req.session.sendResponse(res, StatusCodes.OK);
return true;
}
} catch ( e ) {
req.session.sendResponse(res, StatusCodes.NOT_FOUND, undefined, 'Template not found', DojoStatusCode.GITLAB_TEMPLATE_NOT_FOUND);
return false;
}
// Check if the user and dojo are members (with at least reporter access) of the project
const members = await this.getRepositoryMembers(projectIdOrNamespace);
const isUsersAtLeastReporter = {
user: false,
dojo: false
};
members.forEach(member => {
if ( member.access_level >= AccessLevel.REPORTER ) {
if ( member.id === req.session.profile.id ) {
isUsersAtLeastReporter.user = true;
} else if ( member.id === Config.gitlab.account.id ) {
isUsersAtLeastReporter.dojo = true;
}
}
});
if ( isUsersAtLeastReporter.user && isUsersAtLeastReporter.dojo ) {
req.session.sendResponse(res, StatusCodes.OK);
return true;
} else {
req.session.sendResponse(res, StatusCodes.UNAUTHORIZED, undefined, 'Template access unauthorized', DojoStatusCode.GITLAB_TEMPLATE_ACCESS_UNAUTHORIZED);
return false;
}
}
protectBranch(repoId: number, branchName: string, allowForcePush: boolean, allowedToMerge: ProtectedBranchAccessLevel, allowedToPush: ProtectedBranchAccessLevel, allowedToUnprotect: ProtectedBranchAccessLevel): Promise<ProtectedBranchSchema> {
return this.api.ProtectedBranches.protect(repoId, branchName, {
allowForcePush : allowForcePush,
mergeAccessLevel : allowedToMerge,
pushAccessLevel : allowedToPush,
unprotectAccessLevel: allowedToUnprotect
});
}
getRepositoryTree(repoId: number, recursive: boolean = true, branch: string = 'main'): Promise<Array<RepositoryTreeSchema>> {
return this.api.Repositories.allRepositoryTrees(repoId, {
recursive: recursive,
ref : branch
});
}
getFile(repoId: number, filePath: string, branch: string = 'main'): Promise<RepositoryFileExpandedSchema> {
return this.api.RepositoryFiles.show(repoId, filePath, branch);
}
private createUpdateFile(create: boolean, repoId: number, filePath: string, fileBase64: string, commitMessage: string, branch: string = 'main', authorName: string = 'Dojo', authorMail: string | undefined = undefined): Promise<RepositoryFileSchema> {
const gitFunction = create ? this.api.RepositoryFiles.create.bind(this.api) : this.api.RepositoryFiles.edit.bind(this.api);
return gitFunction(repoId, filePath, branch, fileBase64, commitMessage, {
encoding : 'base64',
authorName : authorName,
authorEmail: authorMail
});
}
createFile(repoId: number, filePath: string, fileBase64: string, commitMessage: string, branch: string = 'main', authorName: string = 'Dojo', authorMail: string | undefined = undefined): Promise<RepositoryFileSchema> {
return this.createUpdateFile(true, repoId, filePath, fileBase64, commitMessage, branch, authorName, authorMail);
}
updateFile(repoId: number, filePath: string, fileBase64: string, commitMessage: string, branch: string = 'main', authorName: string = 'Dojo', authorMail: string | undefined = undefined): Promise<RepositoryFileSchema> {
return this.createUpdateFile(false, repoId, filePath, fileBase64, commitMessage, branch, authorName, authorMail);
}
deleteFile(repoId: number, filePath: string, commitMessage: string, branch: string = 'main', authorName: string = 'Dojo', authorMail: string | undefined = undefined): Promise<void> {
return this.api.RepositoryFiles.remove(repoId, filePath, branch, commitMessage, {
authorName : authorName,
authorEmail: authorMail
});
}
}
export default new GitlabManager();