Skip to content

Commit cfe9a31

Browse files
committed
Add repository permissions to repo context
1 parent 6dbeb38 commit cfe9a31

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/git/repository-permissions.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export type RepositoryPermission = "admin" | "write" | "read";
2+
3+
// https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#get-a-repository
4+
// This should always be set for authenticated requests
5+
type RepositoryPermissionResponse = {
6+
admin: boolean;
7+
maintain?: boolean;
8+
push: boolean;
9+
triage?: boolean;
10+
pull: boolean;
11+
};
12+
13+
export function getRepositoryPermission(permissions: RepositoryPermissionResponse | undefined): RepositoryPermission {
14+
return permissions?.admin ? "admin" : permissions?.push ? "write" : "read";
15+
}
16+
17+
export function hasAdminPermission(permission: RepositoryPermission): boolean {
18+
return permission === "admin";
19+
}
20+
21+
export function hasWritePermission(permission: RepositoryPermission): boolean {
22+
return permission === "admin" || permission === "write";
23+
}
24+
25+
export function hasReadPermission(permission: RepositoryPermission): boolean {
26+
return permission === "admin" || permission === "write" || permission === "read";
27+
}

src/git/repository.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {Protocol} from "../external/protocol";
77
import {logDebug, logError} from "../log";
88
import {API, GitExtension, RefType, RepositoryState} from "../typings/git";
99
import {canReachGitHubAPI} from "../util";
10+
import {getUsername} from "./username";
11+
import {RepositoryPermission, getRepositoryPermission} from "./repository-permissions";
1012

1113
interface GitHubUrls {
1214
workspaceUri: vscode.Uri;
@@ -127,13 +129,14 @@ export interface GitHubRepoContext {
127129
name: string;
128130

129131
organizationOwned: boolean;
130-
131132
defaultBranch: string;
133+
permissionLevel: RepositoryPermission;
132134
}
133135

134136
export interface GitHubContext {
135137
repos: GitHubRepoContext[];
136138
reposByUri: Map<string, GitHubRepoContext>;
139+
username: string;
137140
}
138141

139142
let gitHubContext: Promise<GitHubContext | undefined> | undefined;
@@ -159,6 +162,10 @@ export async function getGitHubContext(): Promise<GitHubContext | undefined> {
159162

160163
logDebug("Found protocol infos", protocolInfos.length.toString());
161164

165+
const username = await handleSamlError(async (client: Octokit) => {
166+
return getUsername(client);
167+
});
168+
162169
const repos = await handleSamlError(async (client: Octokit) => {
163170
return await Promise.all(
164171
protocolInfos.map(async (protocolInfo): Promise<GitHubRepoContext> => {
@@ -179,15 +186,17 @@ export async function getGitHubContext(): Promise<GitHubContext | undefined> {
179186
owner: protocolInfo.protocol.owner,
180187
id: repoInfo.data.id,
181188
defaultBranch: `refs/heads/${repoInfo.data.default_branch}`,
182-
organizationOwned: repoInfo.data.owner.type === "Organization"
189+
organizationOwned: repoInfo.data.owner.type === "Organization",
190+
permissionLevel: getRepositoryPermission(repoInfo.data.permissions)
183191
};
184192
})
185193
);
186194
});
187195

188196
gitHubContext = Promise.resolve({
189197
repos,
190-
reposByUri: new Map(repos.map(r => [r.workspaceUri.toString(), r]))
198+
reposByUri: new Map(repos.map(r => [r.workspaceUri.toString(), r])),
199+
username
191200
});
192201
} catch (e) {
193202
// Reset the context so the next attempt will try this flow again

src/git/username.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {Octokit} from "@octokit/rest";
2+
import {logError} from "../log";
3+
4+
export async function getUsername(octokit: Octokit): Promise<string> {
5+
try {
6+
return (await octokit.users.getAuthenticated()).data.login;
7+
} catch (e) {
8+
logError(e as Error, "Failure to retrieve username");
9+
throw e;
10+
}
11+
}

0 commit comments

Comments
 (0)