diff --git a/api/src/graphql/generated/api/operations.ts b/api/src/graphql/generated/api/operations.ts index 1532d9ac2..0021fef98 100755 --- a/api/src/graphql/generated/api/operations.ts +++ b/api/src/graphql/generated/api/operations.ts @@ -94,10 +94,8 @@ export function AccessUrlInputSchema(): z.ZodObject> export function AddPermissionInputSchema(): z.ZodObject> { return z.object({ - action: z.string(), - possession: z.string(), - resource: ResourceSchema, - role: RoleSchema + actions: z.array(z.string()), + resource: ResourceSchema }) } @@ -326,7 +324,8 @@ export function CreateApiKeyInputSchema(): z.ZodObject AddPermissionInputSchema())).nullish(), + roles: z.array(RoleSchema).nullish() }) } @@ -1230,7 +1229,8 @@ export function VmDomainSchema(): z.ZodObject> { export function VmsSchema(): z.ZodObject> { return z.object({ __typename: z.literal('Vms').optional(), - domain: z.array(VmDomainSchema()).nullish() + domain: z.array(VmDomainSchema()).nullish(), + id: z.string() }) } diff --git a/api/src/graphql/generated/api/types.ts b/api/src/graphql/generated/api/types.ts index fb6fcb9df..409040334 100644 --- a/api/src/graphql/generated/api/types.ts +++ b/api/src/graphql/generated/api/types.ts @@ -40,10 +40,8 @@ export type AccessUrlInput = { }; export type AddPermissionInput = { - action: Scalars['String']['input']; - possession: Scalars['String']['input']; + actions: Array; resource: Resource; - role: Role; }; export type AddRoleForApiKeyInput = { @@ -350,7 +348,8 @@ export enum ContainerState { export type CreateApiKeyInput = { description?: InputMaybe; name: Scalars['String']['input']; - roles: Array; + permissions?: InputMaybe>; + roles?: InputMaybe>; }; export type Devices = { @@ -1682,6 +1681,7 @@ export enum VmState { export type Vms = { __typename?: 'Vms'; domain?: Maybe>; + id: Scalars['ID']['output']; }; export enum WAN_ACCESS_TYPE { @@ -3090,6 +3090,7 @@ export type VmDomainResolvers = ResolversObject<{ domain?: Resolver>, ParentType, ContextType>; + id?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; diff --git a/api/src/graphql/schema/types/auth/auth.graphql b/api/src/graphql/schema/types/auth/auth.graphql index 52de60e8a..a498c48c8 100644 --- a/api/src/graphql/schema/types/auth/auth.graphql +++ b/api/src/graphql/schema/types/auth/auth.graphql @@ -25,14 +25,13 @@ type ApiKeyWithSecret { input CreateApiKeyInput { name: String! description: String - roles: [Role!]! + roles: [Role!] + permissions: [AddPermissionInput!] } input AddPermissionInput { - role: Role! resource: Resource! - action: String! - possession: String! + actions: [String!]! } input AddRoleForUserInput { diff --git a/api/src/unraid-api/auth/api-key.service.ts b/api/src/unraid-api/auth/api-key.service.ts index d0c244276..215015bdf 100644 --- a/api/src/unraid-api/auth/api-key.service.ts +++ b/api/src/unraid-api/auth/api-key.service.ts @@ -13,12 +13,12 @@ import { ZodError } from 'zod'; import { environment } from '@app/environment'; import { ApiKeySchema, ApiKeyWithSecretSchema } from '@app/graphql/generated/api/operations'; import { + AddPermissionInput, ApiKey, ApiKeyWithSecret, Permission, Resource, Role, - UserAccount, } from '@app/graphql/generated/api/types'; import { getters, store } from '@app/store'; import { updateUserConfig } from '@app/store/modules/config'; @@ -107,7 +107,7 @@ export class ApiKeyService implements OnModuleInit { name: string; description: string | undefined; roles?: Role[]; - permissions?: Permission[]; + permissions?: Permission[] | AddPermissionInput[]; overwrite?: boolean; }): Promise { const trimmedName = name?.trim(); diff --git a/api/src/unraid-api/exceptions/graphql-exceptions.filter.ts b/api/src/unraid-api/exceptions/graphql-exceptions.filter.ts index d1f17f905..0f5700c33 100644 --- a/api/src/unraid-api/exceptions/graphql-exceptions.filter.ts +++ b/api/src/unraid-api/exceptions/graphql-exceptions.filter.ts @@ -1,28 +1,26 @@ -import { - Catch, - type ArgumentsHost, - type ExceptionFilter, -} from '@nestjs/common'; -import { GraphQLError } from 'graphql'; +import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common'; +import { Catch } from '@nestjs/common'; + import { type FastifyReply } from 'fastify'; +import { GraphQLError } from 'graphql'; @Catch(GraphQLError) -export class GraphQLExceptionsFilter - implements ExceptionFilter -{ +export class GraphQLExceptionsFilter implements ExceptionFilter { catch(exception: T, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response: FastifyReply = ctx.getResponse(); - response.code(200).send({ - data: null, - errors: [ - { - message: exception.message, - locations: exception.locations, - path: exception.path, - }, - ], - }); + if (response.code) { + response.code(200).send({ + data: null, + errors: [ + { + message: exception.message, + locations: exception.locations, + path: exception.path, + }, + ], + }); + } } } diff --git a/api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts b/api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts index 55b3a91fc..74b21a636 100644 --- a/api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts +++ b/api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts @@ -56,11 +56,12 @@ export class AuthResolver { @Args('input') input: CreateApiKeyInput ): Promise { - const apiKey = await this.apiKeyService.create( - input.name, - input.description ?? undefined, - input.roles - ); + const apiKey = await this.apiKeyService.create({ + name: input.name, + description: input.description ?? undefined, + roles: input.roles ?? [], + permissions: input.permissions ?? [], + }); await this.authService.syncApiKeyRoles(apiKey.id, apiKey.roles);