Skip to content
Snippets Groups Projects
Commit 7b8cbcdb authored by michael.minelli's avatar michael.minelli Committed by michael.minelli
Browse files

Move to Gitbeaker

parent 26d51c85
No related branches found
No related tags found
No related merge requests found
import GitlabVisibility from '../shared/types/Gitlab/GitlabVisibility';
import path from 'path';
import fs from 'fs';
import { Exercise } from '../types/DatabaseTypes';
import JSON5 from 'json5';
import GitlabVisibility from '../shared/types/Gitlab/GitlabVisibility';
type ConfigGitlabBadge = {
......@@ -52,13 +52,13 @@ class Config {
public readonly assignment: {
default: {
description: string; initReadme: boolean; sharedRunnersEnabled: boolean; visibility: string; wikiEnabled: boolean; template: string
description: string; initReadme: boolean; sharedRunnersEnabled: boolean; visibility: GitlabVisibility; wikiEnabled: boolean; template: string
}; baseFiles: Array<string>; filename: string
};
public readonly exercise: {
maxSameName: number; maxPerAssignment: number; resultsFolder: string, pipelineResultsFolder: string; default: {
description: string; visibility: string;
description: string; visibility: GitlabVisibility;
};
};
......@@ -116,7 +116,7 @@ class Config {
description : process.env.ASSIGNMENT_DEFAULT_DESCRIPTION?.convertWithEnvVars() ?? '',
initReadme : process.env.ASSIGNMENT_DEFAULT_INIT_README?.toBoolean() ?? false,
sharedRunnersEnabled: process.env.ASSIGNMENT_DEFAULT_SHARED_RUNNERS_ENABLED?.toBoolean() ?? true,
visibility : process.env.ASSIGNMENT_DEFAULT_VISIBILITY || GitlabVisibility.PRIVATE,
visibility : process.env.ASSIGNMENT_DEFAULT_VISIBILITY as GitlabVisibility || 'private',
wikiEnabled : process.env.ASSIGNMENT_DEFAULT_WIKI_ENABLED?.toBoolean() ?? false,
template : process.env.ASSIGNMENT_DEFAULT_TEMPLATE?.replace('{{USERNAME}}', this.gitlab.account.username).replace('{{TOKEN}}', this.gitlab.account.token) ?? ''
},
......@@ -131,7 +131,7 @@ class Config {
pipelineResultsFolder: process.env.EXERCISE_PIPELINE_RESULTS_FOLDER ?? '', //Do not use convertWithEnvVars() because it is used in the exercise creation and muste be interpreted at exercise runtime
default : {
description: process.env.EXERCISE_DEFAULT_DESCRIPTION?.convertWithEnvVars() ?? '',
visibility : process.env.EXERCISE_DEFAULT_VISIBILITY || GitlabVisibility.PRIVATE
visibility : process.env.EXERCISE_DEFAULT_VISIBILITY as GitlabVisibility || 'private'
}
};
}
......
import Config from '../config/Config';
import GitlabRelease from '../shared/types/Gitlab/GitlabRelease';
import GitlabManager from '../managers/GitlabManager';
import * as Gitlab from '@gitbeaker/rest';
class DojoCliVersionHelper {
......@@ -8,7 +8,7 @@ class DojoCliVersionHelper {
private latestVersion: string | undefined;
private async updateVersion(): Promise<void> {
const releases: Array<GitlabRelease> = await GitlabManager.getRepositoryReleases(Config.dojoCLI.repositoryId);
const releases: Array<Gitlab.ReleaseSchema> = await GitlabManager.getRepositoryReleases(Config.dojoCLI.repositoryId);
for ( const release of releases ) {
if ( !isNaN(+release.tag_name.replace('.', '')) ) {
this.latestVersion = release.tag_name;
......
import express from 'express';
import GitlabRepository from '../shared/types/Gitlab/GitlabRepository';
import logger from '../shared/logging/WinstonLogger';
import GitlabManager from '../managers/GitlabManager';
import { AxiosError } from 'axios';
import { StatusCodes } from 'http-status-codes';
import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode';
import SharedGitlabManager from '../shared/managers/SharedGitlabManager';
import Config from '../config/Config';
import * as Gitlab from '@gitbeaker/rest';
class GlobalHelper {
async repositoryCreationError(message: string, error: unknown, req: express.Request, res: express.Response, gitlabError: DojoStatusCode, internalError: DojoStatusCode, repositoryToRemove?: GitlabRepository): Promise<void> {
readonly sharedGitlabManager = new SharedGitlabManager(Config.gitlab.account.token);
async repositoryCreationError(message: string, error: unknown, req: express.Request, res: express.Response, gitlabError: DojoStatusCode, internalError: DojoStatusCode, repositoryToRemove?: Gitlab.ProjectSchema): Promise<void> {
logger.error(message);
logger.error(error);
......
import { Prisma, UserRole } from '@prisma/client';
import LazyVal from '../../../shared/helpers/LazyVal';
import GitlabUser from '../../../shared/types/Gitlab/GitlabUser';
import GitlabManager from '../../../managers/GitlabManager';
import * as Gitlab from '@gitbeaker/rest';
export default Prisma.defineExtension(client => {
......@@ -26,7 +26,7 @@ export default Prisma.defineExtension(client => {
},
gitlabProfile : {
compute(user) {
return new LazyVal<GitlabUser | undefined>(() => GitlabManager.getUserById(user.id));
return new LazyVal<Gitlab.UserSchema | undefined>(() => GitlabManager.getUserById(user.id));
}
}
}
......
This diff is collapsed.
import axios, { AxiosError, AxiosRequestHeaders } from 'axios';
import Config from '../config/Config';
import FormData from 'form-data';
import logger from '../shared/logging/WinstonLogger';
import SharedConfig from '../shared/config/SharedConfig';
class HttpManager {
......@@ -16,19 +14,6 @@ class HttpManager {
if ( config.data instanceof FormData ) {
config.headers = { ...config.headers, ...(config.data as FormData).getHeaders() } as AxiosRequestHeaders;
}
if ( config.url && config.url.indexOf(SharedConfig.gitlab.apiURL) !== -1 && !config.headers.DojoOverrideAuthorization ) {
config.headers['PRIVATE-TOKEN'] = Config.gitlab.account.token;
}
if ( config.headers.DojoOverrideAuthorization && 'DojoAuthorizationHeader' in config.headers && 'DojoAuthorizationValue' in config.headers ) {
config.headers[config.headers.DojoAuthorizationHeader] = config.headers.DojoAuthorizationValue;
delete config.headers.DojoOverrideAuthorization;
delete config.headers.DojoAuthorizationHeader;
delete config.headers.DojoAuthorizationValue;
}
return config;
});
}
......
import GitlabUser from '../shared/types/Gitlab/GitlabUser';
import { Prisma } from '@prisma/client';
import db from '../helpers/DatabaseHelper';
import GitlabProfile from '../shared/types/Gitlab/GitlabProfile';
import { User } from '../types/DatabaseTypes';
import * as Gitlab from '@gitbeaker/rest';
class UserManager {
......@@ -24,7 +23,7 @@ class UserManager {
}) as unknown as User ?? undefined;
}
async getUpdateFromGitlabProfile(gitlabProfile: GitlabProfile): Promise<User> {
async getUpdateFromGitlabProfile(gitlabProfile: Gitlab.ExpandedUserSchema): Promise<User> {
await db.user.upsert({
where : {
id: gitlabProfile.id
......@@ -46,7 +45,7 @@ class UserManager {
return (await this.getById(gitlabProfile.id))!;
}
async getFromGitlabUser(gitlabUser: GitlabUser, createIfNotExist: boolean = false, include: Prisma.UserInclude | undefined = undefined): Promise<User | number | undefined> {
async getFromGitlabUser(gitlabUser: Gitlab.UserSchema, createIfNotExist: boolean = false, include: Prisma.UserInclude | undefined = undefined): Promise<User | number | undefined> {
let user = await this.getById(gitlabUser.id, include) ?? gitlabUser.id;
if ( typeof user === 'number' && createIfNotExist ) {
......@@ -61,7 +60,7 @@ class UserManager {
return user;
}
async getFromGitlabUsers(gitlabUsers: Array<GitlabUser>, createIfNotExist: boolean = false, include: Prisma.UserInclude | undefined = undefined): Promise<Array<User | number | undefined>> {
async getFromGitlabUsers(gitlabUsers: Array<Gitlab.UserSchema>, createIfNotExist: boolean = false, include: Prisma.UserInclude | undefined = undefined): Promise<Array<User | number | undefined>> {
return Promise.all(gitlabUsers.map(gitlabUser => this.getFromGitlabUser(gitlabUser, createIfNotExist, include)));
}
}
......
......@@ -6,12 +6,8 @@ import RoutesManager from '../express/RoutesManager';
import ParamsValidatorMiddleware from '../middlewares/ParamsValidatorMiddleware';
import SecurityMiddleware from '../middlewares/SecurityMiddleware';
import SecurityCheckType from '../types/SecurityCheckType';
import GitlabUser from '../shared/types/Gitlab/GitlabUser';
import GitlabManager from '../managers/GitlabManager';
import Config from '../config/Config';
import GitlabMember from '../shared/types/Gitlab/GitlabMember';
import GitlabAccessLevel from '../shared/types/Gitlab/GitlabAccessLevel';
import GitlabRepository from '../shared/types/Gitlab/GitlabRepository';
import { AxiosError, HttpStatusCode } from 'axios';
import logger from '../shared/logging/WinstonLogger';
import DojoValidators from '../helpers/DojoValidators';
......@@ -19,13 +15,13 @@ import { Prisma } from '@prisma/client';
import db from '../helpers/DatabaseHelper';
import { Assignment } from '../types/DatabaseTypes';
import AssignmentManager from '../managers/AssignmentManager';
import GitlabVisibility from '../shared/types/Gitlab/GitlabVisibility';
import fs from 'fs';
import path from 'path';
import SharedAssignmentHelper from '../shared/helpers/Dojo/SharedAssignmentHelper';
import GlobalHelper from '../helpers/GlobalHelper';
import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode';
import DojoModelsHelper from '../helpers/DojoModelsHelper';
import * as Gitlab from '@gitbeaker/rest';
class AssignmentRoutes implements RoutesManager {
......@@ -84,13 +80,13 @@ class AssignmentRoutes implements RoutesManager {
private async createAssignment(req: express.Request, res: express.Response) {
const params: {
name: string, members: Array<GitlabUser>, template: string
name: string, members: Array<Gitlab.UserSchema>, template: string
} = req.body;
params.members = [ await req.session.profile.gitlabProfile.value, ...params.members ];
params.members = params.members.removeObjectDuplicates(gitlabUser => gitlabUser.id);
let repository: GitlabRepository;
let repository: Gitlab.ProjectSchema;
try {
repository = await GitlabManager.createRepository(params.name, Config.assignment.default.description.replace('{{ASSIGNMENT_NAME}}', params.name), Config.assignment.default.visibility, Config.assignment.default.initReadme, Config.gitlab.group.assignments, Config.assignment.default.sharedRunnersEnabled, Config.assignment.default.wikiEnabled, params.template);
} catch ( error ) {
......@@ -111,7 +107,7 @@ class AssignmentRoutes implements RoutesManager {
await new Promise(resolve => setTimeout(resolve, Config.gitlab.repository.timeoutAfterCreation));
try {
await GitlabManager.protectBranch(repository.id, '*', true, GitlabAccessLevel.DEVELOPER, GitlabAccessLevel.DEVELOPER, GitlabAccessLevel.OWNER);
await GitlabManager.protectBranch(repository.id, '*', true, Gitlab.AccessLevel.DEVELOPER, Gitlab.AccessLevel.DEVELOPER, Gitlab.AccessLevel.ADMIN);
await GitlabManager.addRepositoryBadge(repository.id, Config.gitlab.badges.pipeline.link, Config.gitlab.badges.pipeline.imageUrl, 'Pipeline Status');
} catch ( error ) {
......@@ -129,9 +125,9 @@ class AssignmentRoutes implements RoutesManager {
}
try {
await Promise.all(params.members.map(member => member.id).map(async (memberId: number): Promise<GitlabMember | false> => {
await Promise.all(params.members.map(member => member.id).map(async (memberId: number): Promise<Gitlab.MemberSchema | false> => {
try {
return await GitlabManager.addRepositoryMember(repository.id, memberId, GitlabAccessLevel.DEVELOPER);
return await GitlabManager.addRepositoryMember(repository.id, memberId, Gitlab.AccessLevel.DEVELOPER);
} catch ( error ) {
logger.error('Add member error');
logger.error(error);
......@@ -180,7 +176,7 @@ class AssignmentRoutes implements RoutesManager {
}
try {
await GitlabManager.changeRepositoryVisibility(req.boundParams.assignment!.gitlabId, publish ? GitlabVisibility.INTERNAL : GitlabVisibility.PRIVATE);
await GitlabManager.changeRepositoryVisibility(req.boundParams.assignment!.gitlabId, publish ? 'internal' : 'private');
await db.assignment.update({
where: {
......
......@@ -5,23 +5,16 @@ import { StatusCodes } from 'http-status-codes';
import RoutesManager from '../express/RoutesManager';
import ParamsValidatorMiddleware from '../middlewares/ParamsValidatorMiddleware';
import SecurityMiddleware from '../middlewares/SecurityMiddleware';
import GitlabUser from '../shared/types/Gitlab/GitlabUser';
import GitlabManager from '../managers/GitlabManager';
import Config from '../config/Config';
import GitlabRepository from '../shared/types/Gitlab/GitlabRepository';
import { AxiosError } from 'axios';
import logger from '../shared/logging/WinstonLogger';
import DojoValidators from '../helpers/DojoValidators';
import { v4 as uuidv4 } from 'uuid';
import GitlabMember from '../shared/types/Gitlab/GitlabMember';
import GitlabAccessLevel from '../shared/types/Gitlab/GitlabAccessLevel';
import { Prisma } from '@prisma/client';
import { Assignment, Exercise } from '../types/DatabaseTypes';
import db from '../helpers/DatabaseHelper';
import SecurityCheckType from '../types/SecurityCheckType';
import GitlabTreeFile from '../shared/types/Gitlab/GitlabTreeFile';
import GitlabFile from '../shared/types/Gitlab/GitlabFile';
import GitlabTreeFileType from '../shared/types/Gitlab/GitlabTreeFileType';
import JSON5 from 'json5';
import fs from 'fs';
import path from 'path';
......@@ -31,6 +24,8 @@ import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode';
import GlobalHelper from '../helpers/GlobalHelper';
import { IFileDirStat } from '../shared/helpers/recursiveFilesStats/RecursiveFilesStats';
import ExerciseManager from '../managers/ExerciseManager';
import * as Gitlab from '@gitbeaker/rest';
import GitlabTreeFileType from '../shared/types/Gitlab/GitlabTreeFileType';
class ExerciseRoutes implements RoutesManager {
......@@ -77,19 +72,19 @@ class ExerciseRoutes implements RoutesManager {
backend.post('/exercises/:exerciseIdOrUrl/results', SecurityMiddleware.check(false, SecurityCheckType.EXERCISE_SECRET), ParamsValidatorMiddleware.validate(this.resultValidator), this.createResult.bind(this));
}
private getExerciseName(assignment: Assignment, members: Array<GitlabUser>, suffix: number): string {
private getExerciseName(assignment: Assignment, members: Array<Gitlab.UserSchema>, suffix: number): string {
const memberNames: string = members.map(member => member.username).sort((a, b) => a.localeCompare(b)).join(' + ');
const suffixString: string = suffix > 0 ? ` - ${ suffix }` : '';
return `DojoEx - ${ assignment.name } - ${ memberNames }${ suffixString }`;
}
private getExercisePath(assignment: Assignment, exerciseId: string): string {
return `dojo-ex_${ (assignment.gitlabLastInfo as unknown as GitlabRepository).path }_${ exerciseId }`;
return `dojo-ex_${ (assignment.gitlabLastInfo as unknown as Gitlab.ProjectSchema).path }_${ exerciseId }`;
}
private async checkExerciseLimit(assignment: Assignment, members: Array<GitlabUser>): Promise<Array<GitlabUser>> {
const exercises: Array<Exercise> = await ExerciseManager.getFromAssignment(assignment.name, { members: true });
const reachedLimitUsers: Array<GitlabUser> = [];
private async checkExerciseLimit(assignment: Assignment, members: Array<Gitlab.UserSchema>): Promise<Array<Gitlab.UserSchema>> {
const exercises: Array<Exercise> | undefined = await ExerciseManager.getFromAssignment(assignment.name, { members: true });
const reachedLimitUsers: Array<Gitlab.UserSchema> = [];
if ( exercises.length > 0 ) {
for ( const member of members ) {
const exerciseCount: number = exercises.filter(exercise => exercise.members.findIndex(exerciseMember => exerciseMember.id === member.id) !== -1).length;
......@@ -102,13 +97,13 @@ class ExerciseRoutes implements RoutesManager {
return reachedLimitUsers;
}
private async createExerciseRepository(assignment: Assignment, members: Array<GitlabUser>, exerciseId: string, req: express.Request, res: express.Response): Promise<GitlabRepository | undefined> {
let repository!: GitlabRepository;
private async createExerciseRepository(assignment: Assignment, members: Array<Gitlab.UserSchema>, exerciseId: string, req: express.Request, res: express.Response): Promise<Gitlab.ProjectSchema | undefined> {
let repository!: Gitlab.ProjectSchema;
let suffix: number = 0;
do {
try {
repository = await GitlabManager.forkRepository((assignment.gitlabCreationInfo as unknown as GitlabRepository).id, this.getExerciseName(assignment, members, suffix), this.getExercisePath(req.boundParams.assignment!, exerciseId), Config.exercise.default.description.replace('{{ASSIGNMENT_NAME}}', assignment.name), Config.exercise.default.visibility, Config.gitlab.group.exercises);
repository = await GitlabManager.forkRepository((assignment.gitlabCreationInfo as unknown as Gitlab.ProjectSchema).id, this.getExerciseName(assignment, params.members, suffix), this.getExercisePath(req.boundParams.assignment!, exerciseId), Config.exercise.default.description.replace('{{ASSIGNMENT_NAME}}', assignment.name), Config.exercise.default.visibility, Config.gitlab.group.exercises);
break;
} catch ( error ) {
logger.error('Repo creation error');
......@@ -161,7 +156,7 @@ class ExerciseRoutes implements RoutesManager {
await new Promise(resolve => setTimeout(resolve, Config.gitlab.repository.timeoutAfterCreation));
try {
await GitlabManager.protectBranch(repository.id, '*', false, GitlabAccessLevel.DEVELOPER, GitlabAccessLevel.DEVELOPER, GitlabAccessLevel.OWNER);
await GitlabManager.protectBranch(repository.id, '*', false, Gitlab.AccessLevel.DEVELOPER, Gitlab.AccessLevel.DEVELOPER, Gitlab.AccessLevel.ADMIN);
await GitlabManager.addRepositoryVariable(repository.id, 'DOJO_EXERCISE_ID', exerciseId, false, true);
await GitlabManager.addRepositoryVariable(repository.id, 'DOJO_SECRET', secret, false, true);
......@@ -181,9 +176,9 @@ class ExerciseRoutes implements RoutesManager {
}
try {
await Promise.all([ ...new Set([ ...assignment.staff.map(user => user.id), ...params.members.map(member => member.id) ]) ].map(async (memberId: number): Promise<GitlabMember | false> => {
await Promise.all([ ...new Set([ ...assignment.staff.map(user => user.id), ...params.members.map(member => member.id) ]) ].map(async (memberId: number): Promise<Gitlab.MemberSchema | false> => {
try {
return await GitlabManager.addRepositoryMember(repository.id, memberId, GitlabAccessLevel.DEVELOPER);
return await GitlabManager.addRepositoryMember(repository.id, memberId, Gitlab.AccessLevel.DEVELOPER);
} catch ( error ) {
logger.error('Add member error');
logger.error(error);
......@@ -227,10 +222,10 @@ class ExerciseRoutes implements RoutesManager {
}
private async getAssignment(req: express.Request, res: express.Response) {
const repoTree: Array<GitlabTreeFile> = await GitlabManager.getRepositoryTree(req.boundParams.exercise!.assignment.gitlabId);
const repoTree: Array<Gitlab.RepositoryTreeSchema> = await GitlabManager.getRepositoryTree(req.boundParams.exercise!.assignment.gitlabId);
let assignmentHjsonFile!: GitlabFile;
const immutableFiles: Array<GitlabFile> = await Promise.all(Config.assignment.baseFiles.map(async (baseFile: string) => {
let assignmentHjsonFile!: Gitlab.RepositoryFileExpandedSchema;
const immutableFiles: Array<Gitlab.RepositoryFileExpandedSchema> = await Promise.all(Config.assignment.baseFiles.map(async (baseFile: string) => {
const file = await GitlabManager.getFile(req.boundParams.exercise!.assignment.gitlabId, baseFile);
if ( baseFile === Config.assignment.filename ) {
......
......@@ -8,8 +8,8 @@ import SecurityMiddleware from '../middlewares/SecurityMiddleware';
import GitlabManager from '../managers/GitlabManager';
import UserManager from '../managers/UserManager';
import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode';
import SharedGitlabManager from '../shared/managers/SharedGitlabManager';
import Config from '../config/Config';
import GlobalHelper from '../helpers/GlobalHelper';
class SessionRoutes implements RoutesManager {
......@@ -64,7 +64,7 @@ class SessionRoutes implements RoutesManager {
refreshToken: string
} = req.body;
const gitlabTokens = await SharedGitlabManager.getTokens(params.refreshToken, true, Config.login.gitlab.client.secret);
const gitlabTokens = await GlobalHelper.sharedGitlabManager.getTokens(params.refreshToken, true, Config.login.gitlab.client.secret);
req.session.sendResponse(res, StatusCodes.OK, gitlabTokens);
} catch ( error ) {
......
Subproject commit 985c0b6a5dcb640404e5cf5fc91978215f961e3b
Subproject commit 47b289f99ef88df993f5977efa6a53e4bd0abe85
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment