mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
feat(server): expose fields for managing access tokens via the public API (#6710)
This commit is contained in:
parent
a3f1ea9edd
commit
916e5799c2
21 changed files with 267 additions and 226 deletions
|
|
@ -843,7 +843,7 @@ export function initSeed() {
|
|||
userId: input.userId,
|
||||
roleId: input.roleId,
|
||||
resources: input.resources ?? {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
projects: [],
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ test.concurrent('create: success', async () => {
|
|||
},
|
||||
title: 'a access token',
|
||||
description: 'Some description',
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentMode.All },
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentModeType.All },
|
||||
permissions: [],
|
||||
},
|
||||
},
|
||||
|
|
@ -118,7 +118,7 @@ test.concurrent('create: failure invalid title', async ({ expect }) => {
|
|||
},
|
||||
title: ' ',
|
||||
description: 'Some description',
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentMode.All },
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentModeType.All },
|
||||
permissions: [],
|
||||
},
|
||||
},
|
||||
|
|
@ -149,7 +149,7 @@ test.concurrent('create: failure invalid description', async ({ expect }) => {
|
|||
},
|
||||
title: 'a access token',
|
||||
description: new Array(300).fill('A').join(''),
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentMode.All },
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentModeType.All },
|
||||
permissions: [],
|
||||
},
|
||||
},
|
||||
|
|
@ -181,7 +181,7 @@ test.concurrent('create: failure because no access to organization', async ({ ex
|
|||
},
|
||||
title: 'a access token',
|
||||
description: 'Some description',
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentMode.All },
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentModeType.All },
|
||||
permissions: [],
|
||||
},
|
||||
},
|
||||
|
|
@ -213,7 +213,7 @@ test.concurrent('query GraphQL API on resources with access', async ({ expect })
|
|||
},
|
||||
title: 'a access token',
|
||||
description: 'a description',
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentMode.All },
|
||||
resources: { mode: GraphQLSchema.ResourceAssignmentModeType.All },
|
||||
permissions: ['organization:describe', 'project:describe'],
|
||||
},
|
||||
},
|
||||
|
|
@ -263,11 +263,11 @@ test.concurrent('query GraphQL API on resources without access', async ({ expect
|
|||
title: 'a access token',
|
||||
description: 'a description',
|
||||
resources: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.Granular,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.Granular,
|
||||
projects: [
|
||||
{
|
||||
projectId: project1.project.id,
|
||||
targets: { mode: GraphQLSchema.ResourceAssignmentMode.All },
|
||||
targets: { mode: GraphQLSchema.ResourceAssignmentModeType.All },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -327,7 +327,7 @@ test.concurrent('pagination', async ({ expect }) => {
|
|||
title: 'first access token',
|
||||
description: 'a description',
|
||||
resources: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
},
|
||||
permissions: ['organization:describe'],
|
||||
},
|
||||
|
|
@ -345,7 +345,7 @@ test.concurrent('pagination', async ({ expect }) => {
|
|||
title: 'second access token',
|
||||
description: 'a description',
|
||||
resources: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
},
|
||||
permissions: ['organization:describe'],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ProjectType, ResourceAssignmentMode } from 'testkit/gql/graphql';
|
||||
import { ProjectType, ResourceAssignmentModeType } from 'testkit/gql/graphql';
|
||||
import { updateProjectSlug } from '../../../testkit/flow';
|
||||
import { initSeed } from '../../../testkit/seed';
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ test.concurrent('prevent access to projects with assigned resources on member',
|
|||
roleId: member.role.id,
|
||||
userId: member.user.id,
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
projects: [],
|
||||
},
|
||||
});
|
||||
|
|
@ -246,11 +246,11 @@ test.concurrent('restrict access to single project with assigned resources on me
|
|||
roleId: member.role.id,
|
||||
userId: member.user.id,
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
projects: [
|
||||
{
|
||||
projectId: firstProject.id,
|
||||
targets: { mode: ResourceAssignmentMode.All },
|
||||
targets: { mode: ResourceAssignmentModeType.All },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import {
|
||||
ProjectType,
|
||||
ResourceAssignmentMode,
|
||||
ResourceAssignmentModeType,
|
||||
RuleInstanceSeverityLevel,
|
||||
} from 'testkit/gql/graphql';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
|
|
@ -1370,7 +1370,7 @@ test.concurrent(
|
|||
await assignMemberRole({
|
||||
roleId: member.role.id,
|
||||
userId: member.user.id,
|
||||
resources: { mode: ResourceAssignmentMode.Granular, projects: [] },
|
||||
resources: { mode: ResourceAssignmentModeType.Granular, projects: [] },
|
||||
});
|
||||
|
||||
// Attempt approving the failed schema check
|
||||
|
|
@ -1448,7 +1448,7 @@ test.concurrent(
|
|||
await assignMemberRole({
|
||||
roleId: memberRole.id,
|
||||
userId: member.user.id,
|
||||
resources: { mode: ResourceAssignmentMode.Granular, projects: [] },
|
||||
resources: { mode: ResourceAssignmentModeType.Granular, projects: [] },
|
||||
});
|
||||
|
||||
// Attempt approving the failed schema check
|
||||
|
|
@ -1529,12 +1529,12 @@ test.concurrent(
|
|||
roleId: memberRole.id,
|
||||
userId: member.user.id,
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
projects: [
|
||||
{
|
||||
projectId: project.id,
|
||||
targets: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
targets: [],
|
||||
},
|
||||
},
|
||||
|
|
@ -1618,17 +1618,17 @@ test.concurrent(
|
|||
roleId: memberRole.id,
|
||||
userId: member.user.id,
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
projects: [
|
||||
{
|
||||
projectId: project.id,
|
||||
targets: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
targets: [
|
||||
{
|
||||
targetId: target.id,
|
||||
appDeployments: { mode: ResourceAssignmentMode.All },
|
||||
services: { mode: ResourceAssignmentMode.All },
|
||||
appDeployments: { mode: ResourceAssignmentModeType.All },
|
||||
services: { mode: ResourceAssignmentModeType.All },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -770,7 +770,7 @@ test('schema:check without `--target` flag fails for organization access token',
|
|||
const privateKey = await createOrganizationAccessToken({
|
||||
permissions: ['schemaCheck:create', 'project:describe'],
|
||||
resources: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -809,7 +809,7 @@ test('schema:check with `--target` flag succeeds for organization access token',
|
|||
const privateKey = await createOrganizationAccessToken({
|
||||
permissions: ['schemaCheck:create', 'project:describe'],
|
||||
resources: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -841,7 +841,7 @@ test('schema:publish without `--target` flag fails for organization access token
|
|||
const privateKey = await createOrganizationAccessToken({
|
||||
permissions: ['project:describe', 'schemaVersion:publish'],
|
||||
resources: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -881,7 +881,7 @@ test('schema:publish with `--target` flag succeeds for organization access token
|
|||
const privateKey = await createOrganizationAccessToken({
|
||||
permissions: ['project:describe', 'schemaVersion:publish'],
|
||||
resources: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { initSeed } from 'testkit/seed';
|
||||
import { ResourceAssignmentMode } from '../../testkit/gql/graphql';
|
||||
import { ResourceAssignmentModeType } from '../../testkit/gql/graphql';
|
||||
import { getServiceHost } from '../../testkit/utils';
|
||||
|
||||
test('/:targetId > operation is accepted with wildcard access token', async () => {
|
||||
|
|
@ -12,7 +12,7 @@ test('/:targetId > operation is accepted with wildcard access token', async () =
|
|||
const accessToken = await createOrganizationAccessToken({
|
||||
permissions: ['usage:report'],
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.All,
|
||||
mode: ResourceAssignmentModeType.All,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -71,12 +71,12 @@ test('/:targetId > operation is denied without access to target', async () => {
|
|||
const accessToken = await createOrganizationAccessToken({
|
||||
permissions: ['usage:report'],
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
projects: [
|
||||
{
|
||||
projectId: project.id,
|
||||
targets: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
targets: [],
|
||||
},
|
||||
},
|
||||
|
|
@ -133,22 +133,22 @@ test('/:targetId > operation is accepted with specific access to target', async
|
|||
const accessToken = await createOrganizationAccessToken({
|
||||
permissions: ['usage:report'],
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
projects: [
|
||||
{
|
||||
projectId: project.id,
|
||||
targets: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
targets: [
|
||||
{
|
||||
targetId: target.id,
|
||||
services: {
|
||||
services: [],
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
},
|
||||
appDeployments: {
|
||||
appDeployments: [],
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
@ -213,7 +213,7 @@ test('/:orgSlug/:projectSlug/:targetSlug > operation is accepted with wildcard a
|
|||
const accessToken = await createOrganizationAccessToken({
|
||||
permissions: ['usage:report'],
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.All,
|
||||
mode: ResourceAssignmentModeType.All,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -275,12 +275,12 @@ test('/:orgSlug/:projectSlug/:targetSlug > operation is denied without access to
|
|||
const accessToken = await createOrganizationAccessToken({
|
||||
permissions: ['usage:report'],
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
projects: [
|
||||
{
|
||||
projectId: project.id,
|
||||
targets: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
targets: [],
|
||||
},
|
||||
},
|
||||
|
|
@ -340,22 +340,22 @@ test('/:orgSlug/:projectSlug/:targetSlug > operation is accepted with specific a
|
|||
const accessToken = await createOrganizationAccessToken({
|
||||
permissions: ['usage:report'],
|
||||
resources: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
projects: [
|
||||
{
|
||||
projectId: project.id,
|
||||
targets: {
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
targets: [
|
||||
{
|
||||
targetId: target.id,
|
||||
services: {
|
||||
services: [],
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
},
|
||||
appDeployments: {
|
||||
appDeployments: [],
|
||||
mode: ResourceAssignmentMode.Granular,
|
||||
mode: ResourceAssignmentModeType.Granular,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@ export default gql`
|
|||
me: User!
|
||||
}
|
||||
|
||||
interface Error {
|
||||
message: String!
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
updateMe(input: UpdateMeInput!): UpdateMeResult!
|
||||
}
|
||||
|
|
@ -97,19 +93,19 @@ export default gql`
|
|||
TOKENS_WRITE
|
||||
}
|
||||
|
||||
enum PermissionLevel {
|
||||
organization
|
||||
project
|
||||
target
|
||||
service
|
||||
appDeployment
|
||||
enum PermissionLevelType {
|
||||
ORGANIZATION
|
||||
PROJECT
|
||||
TARGET
|
||||
SERVICE
|
||||
APP_DEPLOYMENT
|
||||
}
|
||||
|
||||
type Permission {
|
||||
id: ID!
|
||||
title: String!
|
||||
description: String!
|
||||
level: PermissionLevel!
|
||||
level: PermissionLevelType!
|
||||
dependsOnId: ID
|
||||
isReadOnly: Boolean!
|
||||
warning: String
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { getPermissionGroup } from '../lib/authz';
|
||||
import { getPermissionGroup, type ResourceLevel } from '../lib/authz';
|
||||
import type { PermissionResolvers } from './../../../__generated__/types';
|
||||
|
||||
/*
|
||||
|
|
@ -18,9 +18,24 @@ export const Permission: PermissionResolvers = {
|
|||
return permission.isReadOnly ?? false;
|
||||
},
|
||||
level: async (permission, _arg, _ctx) => {
|
||||
return getPermissionGroup(permission.id);
|
||||
return resourceLevelToResourceLevelType(getPermissionGroup(permission.id));
|
||||
},
|
||||
warning: async (permission, _arg, _ctx) => {
|
||||
return permission.warning ?? null;
|
||||
},
|
||||
};
|
||||
|
||||
function resourceLevelToResourceLevelType(resourceLevel: ResourceLevel) {
|
||||
switch (resourceLevel) {
|
||||
case 'target':
|
||||
return 'TARGET' as const;
|
||||
case 'service':
|
||||
return 'SERVICE' as const;
|
||||
case 'project':
|
||||
return 'PROJECT' as const;
|
||||
case 'organization':
|
||||
return 'ORGANIZATION' as const;
|
||||
case 'appDeployment':
|
||||
return 'APP_DEPLOYMENT' as const;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,17 @@ export const permissionGroups: Array<PermissionGroup> = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'access-tokens',
|
||||
title: 'Access Tokens',
|
||||
permissions: [
|
||||
{
|
||||
id: 'accessToken:modify',
|
||||
title: 'Manage access tokens',
|
||||
description: 'Fetch, create and delete access tokens.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'project',
|
||||
title: 'Project',
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ export default gql`
|
|||
deleteMemberRole(input: DeleteMemberRoleInput!): DeleteMemberRoleResult!
|
||||
assignMemberRole(input: AssignMemberRoleInput!): AssignMemberRoleResult!
|
||||
createOrganizationAccessToken(
|
||||
input: CreateOrganizationAccessTokenInput!
|
||||
): CreateOrganizationAccessTokenResult!
|
||||
input: CreateOrganizationAccessTokenInput! @tag(name: "public")
|
||||
): CreateOrganizationAccessTokenResult! @tag(name: "public")
|
||||
deleteOrganizationAccessToken(
|
||||
input: DeleteOrganizationAccessTokenInput!
|
||||
): DeleteOrganizationAccessTokenResult!
|
||||
input: DeleteOrganizationAccessTokenInput! @tag(name: "public")
|
||||
): DeleteOrganizationAccessTokenResult! @tag(name: "public")
|
||||
}
|
||||
|
||||
input OrganizationReferenceInput @oneOf {
|
||||
|
|
@ -54,64 +54,68 @@ export default gql`
|
|||
}
|
||||
|
||||
input CreateOrganizationAccessTokenInput {
|
||||
organization: OrganizationReferenceInput!
|
||||
title: String!
|
||||
description: String
|
||||
permissions: [String!]!
|
||||
resources: ResourceAssignmentInput!
|
||||
organization: OrganizationReferenceInput! @tag(name: "public")
|
||||
title: String! @tag(name: "public")
|
||||
description: String @tag(name: "public")
|
||||
permissions: [String!]! @tag(name: "public")
|
||||
resources: ResourceAssignmentInput! @tag(name: "public")
|
||||
}
|
||||
|
||||
type CreateOrganizationAccessTokenResult {
|
||||
ok: CreateOrganizationAccessTokenResultOk
|
||||
error: CreateOrganizationAccessTokenResultError
|
||||
ok: CreateOrganizationAccessTokenResultOk @tag(name: "public")
|
||||
error: CreateOrganizationAccessTokenResultError @tag(name: "public")
|
||||
}
|
||||
|
||||
type CreateOrganizationAccessTokenResultOk {
|
||||
createdOrganizationAccessToken: OrganizationAccessToken!
|
||||
privateAccessKey: String!
|
||||
privateAccessKey: String! @tag(name: "public")
|
||||
}
|
||||
|
||||
type CreateOrganizationAccessTokenResultError implements Error {
|
||||
message: String!
|
||||
details: CreateOrganizationAccessTokenResultErrorDetails
|
||||
type CreateOrganizationAccessTokenResultError {
|
||||
message: String! @tag(name: "public")
|
||||
details: CreateOrganizationAccessTokenResultErrorDetails @tag(name: "public")
|
||||
}
|
||||
|
||||
type CreateOrganizationAccessTokenResultErrorDetails {
|
||||
"""
|
||||
Error message for the input title.
|
||||
"""
|
||||
title: String
|
||||
title: String @tag(name: "public")
|
||||
"""
|
||||
Error message for the input description.
|
||||
"""
|
||||
description: String
|
||||
description: String @tag(name: "public")
|
||||
}
|
||||
|
||||
type OrganizationAccessToken {
|
||||
id: ID!
|
||||
title: String!
|
||||
description: String
|
||||
permissions: [String!]!
|
||||
resources: ResourceAssignment!
|
||||
firstCharacters: String!
|
||||
createdAt: DateTime!
|
||||
id: ID! @tag(name: "public")
|
||||
title: String! @tag(name: "public")
|
||||
description: String @tag(name: "public")
|
||||
permissions: [String!]! @tag(name: "public")
|
||||
resources: ResourceAssignment! @tag(name: "public")
|
||||
firstCharacters: String! @tag(name: "public")
|
||||
createdAt: DateTime! @tag(name: "public")
|
||||
}
|
||||
|
||||
input DeleteOrganizationAccessTokenInput {
|
||||
organizationAccessTokenId: ID!
|
||||
organizationAccessToken: OrganizationAccessTokenReference! @tag(name: "public")
|
||||
}
|
||||
|
||||
input OrganizationAccessTokenReference @oneOf @tag(name: "public") {
|
||||
byId: ID @tag(name: "public")
|
||||
}
|
||||
|
||||
type DeleteOrganizationAccessTokenResult {
|
||||
ok: DeleteOrganizationAccessTokenResultOk
|
||||
error: DeleteOrganizationAccessTokenResultError
|
||||
ok: DeleteOrganizationAccessTokenResultOk @tag(name: "public")
|
||||
error: DeleteOrganizationAccessTokenResultError @tag(name: "public")
|
||||
}
|
||||
|
||||
type DeleteOrganizationAccessTokenResultOk {
|
||||
deletedOrganizationAccessTokenId: ID!
|
||||
deletedOrganizationAccessTokenId: ID! @tag(name: "public")
|
||||
}
|
||||
|
||||
type DeleteOrganizationAccessTokenResultError implements Error {
|
||||
message: String!
|
||||
type DeleteOrganizationAccessTokenResultError {
|
||||
message: String! @tag(name: "public")
|
||||
}
|
||||
|
||||
type UpdateOrganizationSlugResult {
|
||||
|
|
@ -338,21 +342,24 @@ export default gql`
|
|||
"""
|
||||
Paginated organization access tokens.
|
||||
"""
|
||||
accessTokens(first: Int, after: String): OrganizationAccessTokenConnection!
|
||||
accessTokens(
|
||||
first: Int @tag(name: "public")
|
||||
after: String @tag(name: "public")
|
||||
): OrganizationAccessTokenConnection! @tag(name: "public")
|
||||
"""
|
||||
Get organization access token by id.
|
||||
"""
|
||||
accessToken(id: ID!): OrganizationAccessToken
|
||||
accessToken(id: ID! @tag(name: "public")): OrganizationAccessToken @tag(name: "public")
|
||||
}
|
||||
|
||||
type OrganizationAccessTokenEdge {
|
||||
node: OrganizationAccessToken!
|
||||
cursor: String!
|
||||
node: OrganizationAccessToken! @tag(name: "public")
|
||||
cursor: String! @tag(name: "public")
|
||||
}
|
||||
|
||||
type OrganizationAccessTokenConnection {
|
||||
pageInfo: PageInfo!
|
||||
edges: [OrganizationAccessTokenEdge!]!
|
||||
pageInfo: PageInfo! @tag(name: "public")
|
||||
edges: [OrganizationAccessTokenEdge!]! @tag(name: "public")
|
||||
}
|
||||
|
||||
type OrganizationConnection {
|
||||
|
|
@ -566,9 +573,15 @@ export default gql`
|
|||
viewerCanRemove: Boolean!
|
||||
}
|
||||
|
||||
enum ResourceAssignmentMode {
|
||||
all
|
||||
granular
|
||||
enum ResourceAssignmentModeType {
|
||||
"""
|
||||
Apply to all subresouces of the resource.
|
||||
"""
|
||||
ALL @tag(name: "public")
|
||||
"""
|
||||
Apply to specific subresouces of the resource.
|
||||
"""
|
||||
GRANULAR @tag(name: "public")
|
||||
}
|
||||
|
||||
type MemberConnection {
|
||||
|
|
@ -577,98 +590,98 @@ export default gql`
|
|||
}
|
||||
|
||||
input AppDeploymentResourceAssignmentInput {
|
||||
appDeployment: String!
|
||||
appDeployment: String! @tag(name: "public")
|
||||
}
|
||||
|
||||
input TargetAppDeploymentsResourceAssignmentInput {
|
||||
"""
|
||||
Whether the permissions should apply for all app deployments within the target.
|
||||
"""
|
||||
mode: ResourceAssignmentMode!
|
||||
mode: ResourceAssignmentModeType! @tag(name: "public")
|
||||
"""
|
||||
Specific app deployments within the target for which the permissions should be applied.
|
||||
"""
|
||||
appDeployments: [AppDeploymentResourceAssignmentInput!]
|
||||
appDeployments: [AppDeploymentResourceAssignmentInput!] @tag(name: "public")
|
||||
}
|
||||
|
||||
input ServiceResourceAssignmentInput {
|
||||
serviceName: String!
|
||||
serviceName: String! @tag(name: "public")
|
||||
}
|
||||
|
||||
input TargetServicesResourceAssignmentInput {
|
||||
"""
|
||||
Whether the permissions should apply for all services within the target or only selected ones.
|
||||
"""
|
||||
mode: ResourceAssignmentMode!
|
||||
mode: ResourceAssignmentModeType! @tag(name: "public")
|
||||
"""
|
||||
Specific services within the target for which the permissions should be applied.
|
||||
"""
|
||||
services: [ServiceResourceAssignmentInput!]
|
||||
services: [ServiceResourceAssignmentInput!] @tag(name: "public")
|
||||
}
|
||||
|
||||
input TargetResourceAssignmentInput {
|
||||
targetId: ID!
|
||||
services: TargetServicesResourceAssignmentInput!
|
||||
appDeployments: TargetAppDeploymentsResourceAssignmentInput!
|
||||
targetId: ID! @tag(name: "public")
|
||||
services: TargetServicesResourceAssignmentInput! @tag(name: "public")
|
||||
appDeployments: TargetAppDeploymentsResourceAssignmentInput! @tag(name: "public")
|
||||
}
|
||||
|
||||
input ProjectTargetsResourceAssignmentInput {
|
||||
"""
|
||||
Whether the permissions should apply for all targets within the project or only selected ones.
|
||||
"""
|
||||
mode: ResourceAssignmentMode!
|
||||
mode: ResourceAssignmentModeType! @tag(name: "public")
|
||||
"""
|
||||
Specific targets within the projects for which the permissions should be applied.
|
||||
"""
|
||||
targets: [TargetResourceAssignmentInput!]
|
||||
targets: [TargetResourceAssignmentInput!] @tag(name: "public")
|
||||
}
|
||||
|
||||
input ProjectResourceAssignmentInput {
|
||||
projectId: ID!
|
||||
targets: ProjectTargetsResourceAssignmentInput!
|
||||
projectId: ID! @tag(name: "public")
|
||||
targets: ProjectTargetsResourceAssignmentInput! @tag(name: "public")
|
||||
}
|
||||
|
||||
input ResourceAssignmentInput {
|
||||
"""
|
||||
Whether the permissions should apply for all projects within the organization or only selected ones.
|
||||
"""
|
||||
mode: ResourceAssignmentMode!
|
||||
mode: ResourceAssignmentModeType! @tag(name: "public")
|
||||
"""
|
||||
Specific projects within the organization for which the permissions should be applied.
|
||||
"""
|
||||
projects: [ProjectResourceAssignmentInput!]
|
||||
projects: [ProjectResourceAssignmentInput!] @tag(name: "public")
|
||||
}
|
||||
|
||||
type TargetServicesResourceAssignment {
|
||||
mode: ResourceAssignmentMode!
|
||||
services: [String!]
|
||||
mode: ResourceAssignmentModeType! @tag(name: "public")
|
||||
services: [String!] @tag(name: "public")
|
||||
}
|
||||
|
||||
type TargetAppDeploymentsResourceAssignment {
|
||||
mode: ResourceAssignmentMode!
|
||||
appDeployments: [String!]
|
||||
mode: ResourceAssignmentModeType! @tag(name: "public")
|
||||
appDeployments: [String!] @tag(name: "public")
|
||||
}
|
||||
|
||||
type TargetResouceAssignment {
|
||||
targetId: ID!
|
||||
target: Target!
|
||||
services: TargetServicesResourceAssignment!
|
||||
appDeployments: TargetAppDeploymentsResourceAssignment!
|
||||
targetId: ID! @tag(name: "public")
|
||||
target: Target! @tag(name: "public")
|
||||
services: TargetServicesResourceAssignment! @tag(name: "public")
|
||||
appDeployments: TargetAppDeploymentsResourceAssignment! @tag(name: "public")
|
||||
}
|
||||
|
||||
type ProjectTargetsResourceAssignment {
|
||||
mode: ResourceAssignmentMode!
|
||||
targets: [TargetResouceAssignment!]
|
||||
mode: ResourceAssignmentModeType! @tag(name: "public")
|
||||
targets: [TargetResouceAssignment!] @tag(name: "public")
|
||||
}
|
||||
|
||||
type ProjectResourceAssignment {
|
||||
projectId: ID!
|
||||
project: Project!
|
||||
targets: ProjectTargetsResourceAssignment!
|
||||
projectId: ID! @tag(name: "public")
|
||||
project: Project! @tag(name: "public")
|
||||
targets: ProjectTargetsResourceAssignment! @tag(name: "public")
|
||||
}
|
||||
|
||||
type ResourceAssignment {
|
||||
mode: ResourceAssignmentMode!
|
||||
projects: [ProjectResourceAssignment!]
|
||||
mode: ResourceAssignmentModeType! @tag(name: "public")
|
||||
projects: [ProjectResourceAssignment!] @tag(name: "public")
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ export class OrganizationAccessTokens {
|
|||
const assignedResources =
|
||||
await this.resourceAssignments.transformGraphQLResourceAssignmentInputToResourceAssignmentGroup(
|
||||
organizationId,
|
||||
args.assignedResources ?? { mode: 'granular' },
|
||||
args.assignedResources ?? { mode: 'GRANULAR' },
|
||||
);
|
||||
|
||||
const permissions = Array.from(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export class ResourceAssignments {
|
|||
resources: ResourceAssignmentGroup;
|
||||
}): Promise<GraphQLSchema.ResolversTypes['ResourceAssignment']> {
|
||||
if (args.resources.mode === '*') {
|
||||
return { mode: 'all' };
|
||||
return { mode: 'ALL' };
|
||||
}
|
||||
const projects = await this.storage.findProjectsByIds({
|
||||
projectIds: args.resources.projects.map(project => project.id),
|
||||
|
|
@ -54,7 +54,7 @@ export class ResourceAssignments {
|
|||
});
|
||||
|
||||
return {
|
||||
mode: 'granular' as const,
|
||||
mode: 'GRANULAR' as const,
|
||||
projects: filteredProjects
|
||||
.map(projectAssignment => {
|
||||
const project = projects.get(projectAssignment.id);
|
||||
|
|
@ -67,9 +67,9 @@ export class ResourceAssignments {
|
|||
project,
|
||||
targets:
|
||||
projectAssignment.targets.mode === '*'
|
||||
? { mode: 'all' as const }
|
||||
? { mode: 'ALL' as const }
|
||||
: {
|
||||
mode: 'granular' as const,
|
||||
mode: 'GRANULAR' as const,
|
||||
targets: projectAssignment.targets.targets
|
||||
.map(targetAssignment => {
|
||||
const target = targets.get(targetAssignment.id);
|
||||
|
|
@ -80,18 +80,18 @@ export class ResourceAssignments {
|
|||
target,
|
||||
services:
|
||||
targetAssignment.services.mode === '*'
|
||||
? { mode: 'all' as const }
|
||||
? { mode: 'ALL' as const }
|
||||
: {
|
||||
mode: 'granular' as const,
|
||||
mode: 'GRANULAR' as const,
|
||||
services: targetAssignment.services.services.map(
|
||||
service => service.serviceName,
|
||||
),
|
||||
},
|
||||
appDeployments:
|
||||
targetAssignment.appDeployments.mode === '*'
|
||||
? { mode: 'all' as const }
|
||||
? { mode: 'ALL' as const }
|
||||
: {
|
||||
mode: 'granular' as const,
|
||||
mode: 'GRANULAR' as const,
|
||||
appDeployments:
|
||||
targetAssignment.appDeployments.appDeployments.map(
|
||||
deployment => deployment.appName,
|
||||
|
|
@ -124,7 +124,7 @@ export class ResourceAssignments {
|
|||
!input.projects ||
|
||||
// No need to resolve the projects if mode "all" is used.
|
||||
// We will not store the selection in the database.
|
||||
input.mode === 'all'
|
||||
input.mode === 'ALL'
|
||||
) {
|
||||
return {
|
||||
mode: '*',
|
||||
|
|
@ -171,14 +171,14 @@ export class ResourceAssignments {
|
|||
type: 'project',
|
||||
id: project.id,
|
||||
targets: {
|
||||
mode: record.targets.mode === 'all' ? '*' : 'granular',
|
||||
mode: record.targets.mode === 'ALL' ? '*' : 'granular',
|
||||
targets: projectTargets,
|
||||
},
|
||||
});
|
||||
|
||||
// No need to resolve the projects if mode "a;ll" is used.
|
||||
// We will not store the selection in the database.
|
||||
if (record.targets.mode === 'all') {
|
||||
if (record.targets.mode === 'ALL') {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ export class ResourceAssignments {
|
|||
services:
|
||||
// monolith schemas do not have services.
|
||||
record.project.type === GraphQLSchema.ProjectType.SINGLE ||
|
||||
targetRecord.services.mode === 'all'
|
||||
targetRecord.services.mode === 'ALL'
|
||||
? { mode: '*' }
|
||||
: {
|
||||
mode: 'granular',
|
||||
|
|
@ -229,7 +229,7 @@ export class ResourceAssignments {
|
|||
})) ?? [],
|
||||
},
|
||||
appDeployments:
|
||||
targetRecord.appDeployments.mode === 'all'
|
||||
targetRecord.appDeployments.mode === 'ALL'
|
||||
? { mode: '*' }
|
||||
: {
|
||||
mode: 'granular',
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export const deleteOrganizationAccessToken: NonNullable<
|
|||
MutationResolvers['deleteOrganizationAccessToken']
|
||||
> = async (_parent, args, { injector }) => {
|
||||
const result = await injector.get(OrganizationAccessTokens).delete({
|
||||
organizationAccessTokenId: args.input.organizationAccessTokenId,
|
||||
organizationAccessTokenId: args.input.organizationAccessToken.byId,
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -52,4 +52,8 @@ export default gql`
|
|||
startCursor: String! @tag(name: "public")
|
||||
endCursor: String! @tag(name: "public")
|
||||
}
|
||||
|
||||
interface Error {
|
||||
message: String!
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ function MemberRole(props: {
|
|||
return (
|
||||
<>
|
||||
{member.role.name}
|
||||
{member.resourceAssignment.mode === GraphQLSchema.ResourceAssignmentMode.All ? (
|
||||
{member.resourceAssignment.mode === GraphQLSchema.ResourceAssignmentModeType.All ? (
|
||||
' (all resources)'
|
||||
) : member.resourceAssignment.projects?.length ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ export function ResourceSelector(props: {
|
|||
const [serviceAppsState, setServiceAppsState] = useState(ServicesAppsState.service);
|
||||
|
||||
const projectState = useMemo(() => {
|
||||
if (props.selection.mode === GraphQLSchema.ResourceAssignmentMode.All) {
|
||||
if (props.selection.mode === GraphQLSchema.ResourceAssignmentModeType.All) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +190,7 @@ export function ResourceSelector(props: {
|
|||
projectId: item.id,
|
||||
projectSlug: item.slug,
|
||||
targets: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.Granular,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.Granular,
|
||||
targets: [],
|
||||
},
|
||||
});
|
||||
|
|
@ -235,7 +235,7 @@ export function ResourceSelector(props: {
|
|||
|
||||
if (
|
||||
projectState.activeProject.projectSelection.targets.mode ===
|
||||
GraphQLSchema.ResourceAssignmentMode.All
|
||||
GraphQLSchema.ResourceAssignmentModeType.All
|
||||
) {
|
||||
return {
|
||||
selection: '*',
|
||||
|
|
@ -244,7 +244,7 @@ export function ResourceSelector(props: {
|
|||
produce(props.selection, state => {
|
||||
const project = state.projects?.find(project => project.projectId === projectId);
|
||||
if (!project) return;
|
||||
project.targets.mode = GraphQLSchema.ResourceAssignmentMode.Granular;
|
||||
project.targets.mode = GraphQLSchema.ResourceAssignmentModeType.Granular;
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
|
@ -311,15 +311,15 @@ export function ResourceSelector(props: {
|
|||
targetId: item.id,
|
||||
targetSlug: item.slug,
|
||||
appDeployments: {
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.Granular,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.Granular,
|
||||
appDeployments: [],
|
||||
},
|
||||
services: {
|
||||
mode:
|
||||
// for single projects we choose "All" by default as there is no granular selection available
|
||||
projectType === GraphQLSchema.ProjectType.Single
|
||||
? GraphQLSchema.ResourceAssignmentMode.All
|
||||
: GraphQLSchema.ResourceAssignmentMode.Granular,
|
||||
? GraphQLSchema.ResourceAssignmentModeType.All
|
||||
: GraphQLSchema.ResourceAssignmentModeType.Granular,
|
||||
services: [],
|
||||
},
|
||||
});
|
||||
|
|
@ -353,7 +353,7 @@ export function ResourceSelector(props: {
|
|||
produce(props.selection, state => {
|
||||
const project = state.projects?.find(project => project.projectId === projectId);
|
||||
if (!project) return;
|
||||
project.targets.mode = GraphQLSchema.ResourceAssignmentMode.All;
|
||||
project.targets.mode = GraphQLSchema.ResourceAssignmentModeType.All;
|
||||
}),
|
||||
);
|
||||
setBreadcrumb({ projectId });
|
||||
|
|
@ -397,7 +397,7 @@ export function ResourceSelector(props: {
|
|||
|
||||
if (
|
||||
targetState.activeTarget.targetSelection.services.mode ===
|
||||
GraphQLSchema.ResourceAssignmentMode.All
|
||||
GraphQLSchema.ResourceAssignmentModeType.All
|
||||
) {
|
||||
return {
|
||||
selection: '*' as const,
|
||||
|
|
@ -408,7 +408,7 @@ export function ResourceSelector(props: {
|
|||
if (!project) return;
|
||||
const target = project.targets.targets?.find(target => target.targetId === targetId);
|
||||
if (!target) return;
|
||||
target.services.mode = GraphQLSchema.ResourceAssignmentMode.Granular;
|
||||
target.services.mode = GraphQLSchema.ResourceAssignmentModeType.Granular;
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
|
@ -449,7 +449,7 @@ export function ResourceSelector(props: {
|
|||
const target = project.targets.targets?.find(target => target.targetId === targetId);
|
||||
|
||||
if (!target) return;
|
||||
target.services.mode = GraphQLSchema.ResourceAssignmentMode.All;
|
||||
target.services.mode = GraphQLSchema.ResourceAssignmentModeType.All;
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
|
@ -512,7 +512,7 @@ export function ResourceSelector(props: {
|
|||
|
||||
if (
|
||||
targetState.activeTarget.targetSelection.services.mode ===
|
||||
GraphQLSchema.ResourceAssignmentMode.All
|
||||
GraphQLSchema.ResourceAssignmentModeType.All
|
||||
) {
|
||||
return {
|
||||
selection: '*' as const,
|
||||
|
|
@ -523,7 +523,7 @@ export function ResourceSelector(props: {
|
|||
if (!project) return;
|
||||
const target = project.targets.targets?.find(target => target.targetId === targetId);
|
||||
if (!target) return;
|
||||
target.appDeployments.mode = GraphQLSchema.ResourceAssignmentMode.Granular;
|
||||
target.appDeployments.mode = GraphQLSchema.ResourceAssignmentModeType.Granular;
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
|
@ -549,7 +549,7 @@ export function ResourceSelector(props: {
|
|||
const target = project.targets.targets?.find(target => target.targetId === targetId);
|
||||
|
||||
if (!target) return;
|
||||
target.appDeployments.mode = GraphQLSchema.ResourceAssignmentMode.All;
|
||||
target.appDeployments.mode = GraphQLSchema.ResourceAssignmentModeType.All;
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
|
@ -603,7 +603,7 @@ export function ResourceSelector(props: {
|
|||
<Tabs
|
||||
defaultValue="granular"
|
||||
value={
|
||||
props.selection.mode === GraphQLSchema.ResourceAssignmentMode.All ? 'full' : 'granular'
|
||||
props.selection.mode === GraphQLSchema.ResourceAssignmentModeType.All ? 'full' : 'granular'
|
||||
}
|
||||
>
|
||||
<TabsList variant="content" className="mt-1">
|
||||
|
|
@ -613,7 +613,7 @@ export function ResourceSelector(props: {
|
|||
onClick={() => {
|
||||
props.onSelectionChange({
|
||||
...props.selection,
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
});
|
||||
setBreadcrumb(null);
|
||||
}}
|
||||
|
|
@ -626,7 +626,7 @@ export function ResourceSelector(props: {
|
|||
onClick={() => {
|
||||
props.onSelectionChange({
|
||||
...props.selection,
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.Granular,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.Granular,
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
|
@ -744,7 +744,7 @@ export function ResourceSelector(props: {
|
|||
title={
|
||||
selection.project.slug +
|
||||
(selection.projectSelection.targets.mode ===
|
||||
GraphQLSchema.ResourceAssignmentMode.All
|
||||
GraphQLSchema.ResourceAssignmentModeType.All
|
||||
? ' (all targets, all services)'
|
||||
: ` (${selection.projectSelection.targets.targets?.length ?? 0} target${selection.projectSelection.targets.targets?.length === 1 ? '' : 's'})`)
|
||||
}
|
||||
|
|
@ -802,7 +802,7 @@ export function ResourceSelector(props: {
|
|||
GraphQLSchema.ProjectType.Single
|
||||
? ' (full access)'
|
||||
: selection.targetSelection.services.mode ===
|
||||
GraphQLSchema.ResourceAssignmentMode.All
|
||||
GraphQLSchema.ResourceAssignmentModeType.All
|
||||
? ' (all services)'
|
||||
: ` (${selection.targetSelection.services.services?.length ?? 0} service${selection.targetSelection.services?.services?.length === 1 ? '' : 's'})`)
|
||||
}
|
||||
|
|
@ -850,7 +850,7 @@ export function ResourceSelector(props: {
|
|||
{serviceAppsState === ServicesAppsState.service && (
|
||||
<div className="flex flex-1 flex-col border-y border-r pt-2">
|
||||
{projectState.activeProject?.projectSelection.targets.mode ===
|
||||
GraphQLSchema.ResourceAssignmentMode.All ? (
|
||||
GraphQLSchema.ResourceAssignmentModeType.All ? (
|
||||
<div className="text-muted-foreground px-2 text-xs">
|
||||
Access to all services of projects targets granted.
|
||||
</div>
|
||||
|
|
@ -927,7 +927,7 @@ export function ResourceSelector(props: {
|
|||
{serviceAppsState === ServicesAppsState.apps && (
|
||||
<div className="flex flex-1 flex-col border-y border-r pt-2">
|
||||
{projectState.activeProject?.projectSelection.targets.mode ===
|
||||
GraphQLSchema.ResourceAssignmentMode.All ? (
|
||||
GraphQLSchema.ResourceAssignmentModeType.All ? (
|
||||
<div className="text-muted-foreground px-2 text-xs">
|
||||
Access to all apps of projects targets granted.
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
import { Badge } from '@/components/ui/badge';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { PermissionLevel } from '@/gql/graphql';
|
||||
import { PermissionLevelType } from '@/gql/graphql';
|
||||
import { ResultOf } from '@graphql-typed-document-node/core';
|
||||
|
||||
export const SelectedPermissionOverview_PermissionGroupFragment = graphql(`
|
||||
|
|
@ -34,7 +34,7 @@ export type SelectedPermissionOverviewProps = {
|
|||
/** default: true */
|
||||
isExpanded?: boolean;
|
||||
/** option for injecting additional content within a permission group. */
|
||||
additionalGroupContent?: (group: { level: PermissionLevel }) => React.ReactNode;
|
||||
additionalGroupContent?: (group: { level: PermissionLevelType }) => React.ReactNode;
|
||||
};
|
||||
|
||||
export function SelectedPermissionOverview(props: SelectedPermissionOverviewProps) {
|
||||
|
|
@ -49,23 +49,23 @@ export function SelectedPermissionOverview(props: SelectedPermissionOverviewProp
|
|||
|
||||
return [
|
||||
{
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Organization',
|
||||
},
|
||||
{
|
||||
level: PermissionLevel.Project,
|
||||
level: PermissionLevelType.Project,
|
||||
title: 'Project',
|
||||
},
|
||||
{
|
||||
level: PermissionLevel.Target,
|
||||
level: PermissionLevelType.Target,
|
||||
title: 'Target',
|
||||
},
|
||||
{
|
||||
level: PermissionLevel.Service,
|
||||
level: PermissionLevelType.Service,
|
||||
title: 'Service',
|
||||
},
|
||||
{
|
||||
level: PermissionLevel.AppDeployment,
|
||||
level: PermissionLevelType.AppDeployment,
|
||||
title: 'App Deployment',
|
||||
},
|
||||
].map(group => (
|
||||
|
|
@ -90,7 +90,7 @@ type MembershipPermissionGroup = AvailableMembershipPermissions[number];
|
|||
|
||||
function PermissionLevelGroup(props: {
|
||||
title: string;
|
||||
permissionLevel: PermissionLevel;
|
||||
permissionLevel: PermissionLevelType;
|
||||
memberPermissionGroups: AvailableMembershipPermissions;
|
||||
activePermissionIds: ReadonlySet<string>;
|
||||
/** whether only allowed permissions should be shown */
|
||||
|
|
|
|||
|
|
@ -206,7 +206,9 @@ function DeleteAccessTokenConfirmationDialogue(props: DeleteAccessTokenConfirmat
|
|||
onClick={() =>
|
||||
mutate({
|
||||
input: {
|
||||
organizationAccessTokenId: props.accessTokenId,
|
||||
organizationAccessToken: {
|
||||
byId: props.accessTokenId,
|
||||
},
|
||||
},
|
||||
}).then(result => {
|
||||
if (result.error) {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ export function CreateAccessTokenSheetContent(
|
|||
props.organization,
|
||||
);
|
||||
const [resourceSelection, setResourceSelection] = useState<ResourceSelection>(() => ({
|
||||
mode: GraphQLSchema.ResourceAssignmentMode.All,
|
||||
mode: GraphQLSchema.ResourceAssignmentModeType.All,
|
||||
projects: [],
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -7,57 +7,57 @@ import type { ResourceSelection } from '../../members/resource-selector';
|
|||
export function resolveResources(
|
||||
organizationSlug: string,
|
||||
resources: ResourceSelection,
|
||||
): null | Record<GraphQLSchema.PermissionLevel, Array<string>> {
|
||||
if (resources.mode === GraphQLSchema.ResourceAssignmentMode.All || !resources.projects) {
|
||||
): null | Record<GraphQLSchema.PermissionLevelType, Array<string>> {
|
||||
if (resources.mode === GraphQLSchema.ResourceAssignmentModeType.All || !resources.projects) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const resolvedResources: Record<GraphQLSchema.PermissionLevel, Array<string>> = {
|
||||
[GraphQLSchema.PermissionLevel.Organization]: [organizationSlug],
|
||||
[GraphQLSchema.PermissionLevel.Project]: [],
|
||||
[GraphQLSchema.PermissionLevel.Target]: [],
|
||||
[GraphQLSchema.PermissionLevel.AppDeployment]: [],
|
||||
[GraphQLSchema.PermissionLevel.Service]: [],
|
||||
const resolvedResources: Record<GraphQLSchema.PermissionLevelType, Array<string>> = {
|
||||
[GraphQLSchema.PermissionLevelType.Organization]: [organizationSlug],
|
||||
[GraphQLSchema.PermissionLevelType.Project]: [],
|
||||
[GraphQLSchema.PermissionLevelType.Target]: [],
|
||||
[GraphQLSchema.PermissionLevelType.AppDeployment]: [],
|
||||
[GraphQLSchema.PermissionLevelType.Service]: [],
|
||||
};
|
||||
|
||||
for (const project of resources.projects) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.Project].push(
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.Project].push(
|
||||
`${organizationSlug}/${project.projectSlug}`,
|
||||
);
|
||||
if (project.targets.mode === GraphQLSchema.ResourceAssignmentMode.All) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.Target].push(
|
||||
if (project.targets.mode === GraphQLSchema.ResourceAssignmentModeType.All) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.Target].push(
|
||||
`${organizationSlug}/${project.projectSlug}/*`,
|
||||
);
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.Service].push(
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.Service].push(
|
||||
`${organizationSlug}/${project.projectSlug}/*/service/*`,
|
||||
);
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.AppDeployment].push(
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.AppDeployment].push(
|
||||
`${organizationSlug}/${project.projectSlug}/*/appDeployment/*`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
for (const target of project.targets.targets) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.Target].push(
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.Target].push(
|
||||
`${organizationSlug}/${project.projectSlug}/${target.targetSlug}`,
|
||||
);
|
||||
if (target.services.mode === GraphQLSchema.ResourceAssignmentMode.All) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.Service].push(
|
||||
if (target.services.mode === GraphQLSchema.ResourceAssignmentModeType.All) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.Service].push(
|
||||
`${organizationSlug}/${project.projectSlug}/${target.targetSlug}/service/*`,
|
||||
);
|
||||
} else if (target.services.services) {
|
||||
for (const service of target.services.services) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.Service].push(
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.Service].push(
|
||||
`${organizationSlug}/${project.projectSlug}/${target.targetSlug}/service/${service.serviceName}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (target.appDeployments.mode === GraphQLSchema.ResourceAssignmentMode.All) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.AppDeployment].push(
|
||||
if (target.appDeployments.mode === GraphQLSchema.ResourceAssignmentModeType.All) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.AppDeployment].push(
|
||||
`${organizationSlug}/${project.projectSlug}/${target.targetSlug}/appDeployment/*`,
|
||||
);
|
||||
} else if (target.appDeployments.appDeployments) {
|
||||
for (const appDeployment of target.appDeployments.appDeployments) {
|
||||
resolvedResources[GraphQLSchema.PermissionLevel.AppDeployment].push(
|
||||
resolvedResources[GraphQLSchema.PermissionLevelType.AppDeployment].push(
|
||||
`${organizationSlug}/${project.projectSlug}/${target.targetSlug}/appDeployment/${appDeployment.appDeployment}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -68,21 +68,21 @@ export function resolveResources(
|
|||
return resolvedResources;
|
||||
}
|
||||
|
||||
export function permissionLevelToResourceName(level: GraphQLSchema.PermissionLevel) {
|
||||
export function permissionLevelToResourceName(level: GraphQLSchema.PermissionLevelType) {
|
||||
switch (level) {
|
||||
case GraphQLSchema.PermissionLevel.Organization: {
|
||||
case GraphQLSchema.PermissionLevelType.Organization: {
|
||||
return 'organizations';
|
||||
}
|
||||
case GraphQLSchema.PermissionLevel.Project: {
|
||||
case GraphQLSchema.PermissionLevelType.Project: {
|
||||
return 'projects';
|
||||
}
|
||||
case GraphQLSchema.PermissionLevel.Target: {
|
||||
case GraphQLSchema.PermissionLevelType.Target: {
|
||||
return 'targets';
|
||||
}
|
||||
case GraphQLSchema.PermissionLevel.Service: {
|
||||
case GraphQLSchema.PermissionLevelType.Service: {
|
||||
return 'services';
|
||||
}
|
||||
case GraphQLSchema.PermissionLevel.AppDeployment: {
|
||||
case GraphQLSchema.PermissionLevelType.AppDeployment: {
|
||||
return 'app deployments';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Organization, PermissionLevel } from '@/gql/graphql';
|
||||
import { Organization, PermissionLevelType } from '@/gql/graphql';
|
||||
|
||||
export const availableMemberPermissionGroups: Organization['availableMemberPermissionGroups'] = [
|
||||
{
|
||||
|
|
@ -12,7 +12,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'organization:describe',
|
||||
dependsOnId: null,
|
||||
description: 'Member can see the organization. Permission can not be modified.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'View organization',
|
||||
},
|
||||
{
|
||||
|
|
@ -21,7 +21,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'support:manageTickets',
|
||||
dependsOnId: null,
|
||||
description: 'Member can access, create and reply to support tickets.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Access support tickets',
|
||||
},
|
||||
{
|
||||
|
|
@ -30,7 +30,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'organization:modifySlug',
|
||||
dependsOnId: null,
|
||||
description: 'Member can modify the organization slug.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Update organization slug',
|
||||
},
|
||||
{
|
||||
|
|
@ -39,7 +39,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'auditLog:export',
|
||||
dependsOnId: null,
|
||||
description: 'Member can access and export the audit log.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Export audit log',
|
||||
},
|
||||
{
|
||||
|
|
@ -48,7 +48,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'organization:delete',
|
||||
dependsOnId: null,
|
||||
description: 'Member can delete the Organization.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Delete organization',
|
||||
},
|
||||
],
|
||||
|
|
@ -64,7 +64,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'member:describe',
|
||||
dependsOnId: null,
|
||||
description: 'Member can access the organization member overview.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'View members',
|
||||
},
|
||||
{
|
||||
|
|
@ -73,7 +73,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'member:modify',
|
||||
dependsOnId: 'member:describe',
|
||||
description: 'Member can assign roles to users.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Assign member role',
|
||||
warning:
|
||||
'Granting a role the ability to assign roles enables it to elevate its own permissions.',
|
||||
|
|
@ -91,7 +91,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'billing:describe',
|
||||
dependsOnId: null,
|
||||
description: 'Member can view the billing information.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'View billing',
|
||||
},
|
||||
{
|
||||
|
|
@ -100,7 +100,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'billing:update',
|
||||
dependsOnId: 'billing:describe',
|
||||
description: 'Member can change the organization plan.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Update billing',
|
||||
},
|
||||
],
|
||||
|
|
@ -116,7 +116,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'oidc:modify',
|
||||
dependsOnId: null,
|
||||
description: 'Member can connect, modify, and remove an OIDC provider to the connection.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Manage OpenID Connect integration',
|
||||
},
|
||||
],
|
||||
|
|
@ -133,7 +133,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
dependsOnId: null,
|
||||
description:
|
||||
'Member can connect, modify, and remove access for the GitHub integration and repository access.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Manage GitHub integration',
|
||||
},
|
||||
],
|
||||
|
|
@ -150,7 +150,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
dependsOnId: null,
|
||||
description:
|
||||
'Member can connect, modify, and remove access for the Slack integration and repository access.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Manage Slack integration',
|
||||
},
|
||||
],
|
||||
|
|
@ -166,7 +166,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'project:create',
|
||||
dependsOnId: null,
|
||||
description: 'Member can create new projects.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Create project',
|
||||
},
|
||||
{
|
||||
|
|
@ -175,7 +175,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'project:describe',
|
||||
dependsOnId: null,
|
||||
description: 'Member can access the specified projects.',
|
||||
level: PermissionLevel.Project,
|
||||
level: PermissionLevelType.Project,
|
||||
title: 'View project',
|
||||
},
|
||||
{
|
||||
|
|
@ -184,7 +184,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'project:delete',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Member can access the specified projects.',
|
||||
level: PermissionLevel.Project,
|
||||
level: PermissionLevelType.Project,
|
||||
title: 'Delete project',
|
||||
},
|
||||
{
|
||||
|
|
@ -193,7 +193,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'project:modifySettings',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Member can access the specified projects.',
|
||||
level: PermissionLevel.Project,
|
||||
level: PermissionLevelType.Project,
|
||||
title: 'Modify Settings',
|
||||
},
|
||||
],
|
||||
|
|
@ -209,7 +209,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'schemaLinting:modifyOrganizationRules',
|
||||
dependsOnId: null,
|
||||
description: 'Member can view and modify the organization schema linting rules.',
|
||||
level: PermissionLevel.Organization,
|
||||
level: PermissionLevelType.Organization,
|
||||
title: 'Manage organization level schema linting',
|
||||
},
|
||||
{
|
||||
|
|
@ -218,7 +218,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'schemaLinting:modifyProjectRules',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Member can view and modify the projects schema linting rules.',
|
||||
level: PermissionLevel.Project,
|
||||
level: PermissionLevelType.Project,
|
||||
title: 'Manage project level schema linting',
|
||||
},
|
||||
],
|
||||
|
|
@ -234,7 +234,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'target:create',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Member can create new projects.',
|
||||
level: PermissionLevel.Project,
|
||||
level: PermissionLevelType.Project,
|
||||
title: 'Create target',
|
||||
},
|
||||
{
|
||||
|
|
@ -243,7 +243,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'target:delete',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Member can access the specified projects.',
|
||||
level: PermissionLevel.Target,
|
||||
level: PermissionLevelType.Target,
|
||||
title: 'Delete target',
|
||||
},
|
||||
{
|
||||
|
|
@ -252,7 +252,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'target:modifySettings',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Member can access the specified projects.',
|
||||
level: PermissionLevel.Target,
|
||||
level: PermissionLevelType.Target,
|
||||
title: 'Modify settings',
|
||||
},
|
||||
{
|
||||
|
|
@ -261,7 +261,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'alert:modify',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Can create alerts for schema versions.',
|
||||
level: PermissionLevel.Project,
|
||||
level: PermissionLevelType.Project,
|
||||
title: 'Modify alerts',
|
||||
},
|
||||
{
|
||||
|
|
@ -270,7 +270,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'targetAccessToken:modify',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Allow managing access tokens for CLI and Usage Reporting.',
|
||||
level: PermissionLevel.Target,
|
||||
level: PermissionLevelType.Target,
|
||||
title: 'Manage registry access tokens',
|
||||
},
|
||||
{
|
||||
|
|
@ -279,7 +279,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'cdnAccessToken:modify',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Allow managing access tokens for the CDN.',
|
||||
level: PermissionLevel.Target,
|
||||
level: PermissionLevelType.Target,
|
||||
title: 'Manage CDN access tokens',
|
||||
},
|
||||
],
|
||||
|
|
@ -295,7 +295,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'laboratory:describe',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Member can access the laboratory, view and execute GraphQL documents.',
|
||||
level: PermissionLevel.Target,
|
||||
level: PermissionLevelType.Target,
|
||||
title: 'View laboratory',
|
||||
},
|
||||
{
|
||||
|
|
@ -305,7 +305,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
dependsOnId: 'laboratory:describe',
|
||||
description:
|
||||
'Member can create, delete and update collections and documents in the laboratory.',
|
||||
level: PermissionLevel.Target,
|
||||
level: PermissionLevelType.Target,
|
||||
title: 'Modify laboratory',
|
||||
},
|
||||
{
|
||||
|
|
@ -314,7 +314,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'laboratory:modifyPreflightScript',
|
||||
dependsOnId: 'laboratory:describe',
|
||||
description: 'Member can update the laboratory preflight script.',
|
||||
level: PermissionLevel.Target,
|
||||
level: PermissionLevelType.Target,
|
||||
title: 'Modify the laboratory preflight script',
|
||||
},
|
||||
],
|
||||
|
|
@ -330,7 +330,7 @@ export const availableMemberPermissionGroups: Organization['availableMemberPermi
|
|||
id: 'schemaCheck:approve',
|
||||
dependsOnId: 'project:describe',
|
||||
description: 'Member can approve failed schema checks.',
|
||||
level: PermissionLevel.Service,
|
||||
level: PermissionLevelType.Service,
|
||||
title: 'Approve schema check',
|
||||
},
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in a new issue