| 116 | 116 | | } |
| 117 | 117 | | |
| 118 | 118 | | function membershipRole(user: User, membership: Membership): RepoRole | null { |
| 119 | | − | // A workspace's own token, and g1t acting in the workspace, do what an |
| 120 | | − | // owner can on its repositories. |
| 119 | + | // A workspace's own token has Write, or Admin when an owner gave it that; |
| 120 | + | // g1t, and a service acting as the workspace, do what an owner can. |
| 121 | + | if (user.kind === "workspace" && user.token) return user.token.admin ? "admin" : "write"; |
| 121 | 122 | | if (user.kind === "workspace" || user.kind === "system") return "admin"; |
| 122 | 123 | | return membership.role === "owner" ? "admin" : baseRole(membership.base_permission); |
| 123 | 124 | | } |
| 124 | 125 | | |
| 125 | 126 | | /** The user's role on the repository, not counting that it may be public. */ |
| 126 | 127 | | export function granted(user: User, repo: RepoRef): RepoRole | null { |
| 128 | + | // A fine-grained token outside its resource owner or selection: no role. |
| 129 | + | const reach = user.token?.fine_grained; |
| 130 | + | if (reach) { |
| 131 | + | const inside = |
| 132 | + | !!reach.workspace && |
| 133 | + | reach.workspace.toLowerCase() === repo.namespace.toLowerCase() && |
| 134 | + | (reach.repositories === "all" || (reach.repositories === "selected" && (reach.repo_ids ?? []).includes(repo.id))); |
| 135 | + | if (!inside) return null; |
| 136 | + | } |
| 127 | 137 | | const namespace = repo.namespace.toLowerCase(); |
| 128 | 138 | | const membership = user.workspaces?.find((m) => m.slug.toLowerCase() === namespace); |
| 129 | 139 | | let role = membership ? membershipRole(user, membership) : null; |