Skip to content

Commit

Permalink
support permissions for projects
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiago Posse committed Sep 28, 2023
1 parent 7bb84f9 commit e364e60
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 19 deletions.
58 changes: 42 additions & 16 deletions src/gitlab/api.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { GitlabGroup, GitlabApiUser, GitlabAccessUpdate, GitlabMembership, GitlabAccessUpdateOperation } from "./types"
import { Gitlab } from './index';
import { GitlabGroup, GitlabApiUser, GitlabAccessUpdate, GitlabMembership, GitlabAccessUpdateOperation, GitlabPathType } from "./types"
import { Gitlab, NotFoundError } from './index';
import { getSecretFromAws } from "../utils/aws";
import { FormData } from "node-fetch";
import fs from 'fs';
import { logger } from "../utils/logging";

const GITLAB_API_TOKEN = await resolveGitlabApiToken()

Expand All @@ -25,20 +25,24 @@ async function resolveGitlabApiToken(): Promise<string> {
throw Error("gitlab api token was not provided.")
}



export class GitlabApi extends Gitlab {
headers: { "PRIVATE-TOKEN": string }
groupOrProjects: { [key: string]: GitlabPathType }

constructor() {
super()

this.url = `${this.url}/v4/groups`
this.url = `${this.url}/v4`
this.headers = {
"PRIVATE-TOKEN": GITLAB_API_TOKEN,
}
this.groupOrProjects = {}
}

async listUserMembership(userId: string): Promise<GitlabMembership[]> {
let membership = await this.request(`/${this.group}/billable_members/${userId}/memberships`, {}, [200, 404]) as GitlabMembership[]
let membership = await this.request(`/groups/${this.group}/billable_members/${userId}/memberships`, {}, [200, 404]) as GitlabMembership[]

if (Array.isArray(membership)) {
membership.forEach(value => { value.source_full_name = value.source_full_name.replaceAll(" ", ""); return value })
Expand Down Expand Up @@ -78,7 +82,7 @@ export class GitlabApi extends Gitlab {
}

while (page !== -1) {
const resp = await this.rawRequest(`/${groupName}/members?page=${page}`, {})
const resp = await this.rawRequest(`/groups/${groupName}/members?page=${page}`, {})
if (resp.headers.get("x-next-page") !== null && resp.headers.get("x-next-page") !== undefined && resp.headers.get("x-next-page") !== "") {
page = +resp.headers.get("x-next-page")!
} else {
Expand All @@ -100,26 +104,48 @@ export class GitlabApi extends Gitlab {
}

async changeUserAccessLevel(change: GitlabAccessUpdate) {
if (this.groupOrProjects[change.group] === undefined) {
try {
await this.rawRequest(`/groups/${change.group.replaceAll("/", "%2F")}`, {})
this.groupOrProjects[change.group] = GitlabPathType.GROUP
} catch (e) {
if (e instanceof NotFoundError) {
this.groupOrProjects[change.group] = GitlabPathType.PROJECT
} else {
throw e
}
}
}

let pathPrefix = ""
switch (this.groupOrProjects[change.group]) {
case GitlabPathType.PROJECT:
pathPrefix = "projects"
break;
case GitlabPathType.GROUP:
pathPrefix = "groups"
break;
}

console.log(`/${pathPrefix}/${change.group.replaceAll("/", "%2F")}/invitations`)
switch (change.op) {
case GitlabAccessUpdateOperation.ADD:
await this.rawRequest(`/${change.group.replace("/", "%2F")}/invitations`, {
const form = new FormData();
form.set("email", change.user)
form.set("access_level", change.role.toString())

await this.rawRequest(`/${pathPrefix}/${change.group.replaceAll("/", "%2F")}/invitations`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: JSON.stringify({
email: change.user,
access_level: change.role
})
body: form
})
break;
case GitlabAccessUpdateOperation.REMOVE:
await this.rawRequest(`/${change.group.replace("/", "%2F")}/members/${change.user}`, {
await this.rawRequest(`/${pathPrefix}/${change.group.replaceAll("/", "%2F")}/members/${change.user}`, {
method: "DELETE"
})
break;
case GitlabAccessUpdateOperation.UPDATE:
await this.rawRequest(`/${change.group.replace("/", "%2F")}/members/${change.user}?access_level=${change.role}`, {
await this.rawRequest(`/${pathPrefix}/${change.group.replaceAll("/", "%2F")}/members/${change.user}?access_level=${change.role}`, {
method: "PUT"
})
break;
Expand Down
13 changes: 10 additions & 3 deletions src/gitlab/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export abstract class Gitlab {
return await (await this.rawRequest(url, config, accepted)).json()
}

async rawRequest(url: string, config: RequestInit, accepted?: number[]): Promise<Response> {
async rawRequest(suffix: string, config: RequestInit, accepted?: number[]): Promise<Response> {
if (accepted === undefined) {
accepted = [201, 204, 200]
}
Expand All @@ -40,13 +40,20 @@ export abstract class Gitlab {

config.headers = { ...this.headers, ...config.headers }

const req = new Request(`${this.url}${url}`, config)
const req = new Request(`${this.url}${suffix}`, config)
const resp = await fetch(req)

if (!accepted.includes(resp.status)) {
throw Error(`Could not execute gitlab request ${config.method} to ${this.url}${url} (${resp.status}): ${resp.statusText}`)
const message = `Could not execute gitlab request ${config.method} to ${this.url}${suffix} (${resp.status}): ${resp.statusText}`
if (resp.status === 404) {
throw new NotFoundError(message)
} else {
throw Error(message)
}
}

return resp
}
}

export class NotFoundError extends Error { }
5 changes: 5 additions & 0 deletions src/gitlab/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@ export type GitlabUserUpdate = {
op: GitlabUserUpdateOperation
notes?: string
}

export enum GitlabPathType {
GROUP = "group",
PROJECT = "project"
}

0 comments on commit e364e60

Please sign in to comment.