mirror of
https://github.com/unraid/api.git
synced 2025-12-31 13:39:52 -06:00
feat: session issues
This commit is contained in:
@@ -19,5 +19,5 @@ dynamicRemoteAccessType="DISABLED"
|
||||
ssoSubIds=""
|
||||
allowedOrigins="/var/run/unraid-notifications.sock, /var/run/unraid-php.sock, /var/run/unraid-cli.sock, http://localhost:8080, https://localhost:4443, https://tower.local:4443, https://192.168.1.150:4443, https://tower:4443, https://192-168-1-150.thisisfourtyrandomcharacters012345678900.myunraid.net:4443, https://85-121-123-122.thisisfourtyrandomcharacters012345678900.myunraid.net:8443, https://10-252-0-1.hash.myunraid.net:4443, https://10-252-1-1.hash.myunraid.net:4443, https://10-253-3-1.hash.myunraid.net:4443, https://10-253-4-1.hash.myunraid.net:4443, https://10-253-5-1.hash.myunraid.net:4443, https://10-100-0-1.hash.myunraid.net:4443, https://10-100-0-2.hash.myunraid.net:4443, https://10-123-1-2.hash.myunraid.net:4443, https://221-123-121-112.hash.myunraid.net:4443, https://google.com, https://test.com, https://connect.myunraid.net, https://connect-staging.myunraid.net, https://dev-my.myunraid.net:4000, https://studio.apollographql.com"
|
||||
[connectionStatus]
|
||||
minigraph="PRE_INIT"
|
||||
minigraph="ERROR_RETRYING"
|
||||
upnpStatus=""
|
||||
|
||||
@@ -323,7 +323,9 @@ export function ContainerPortSchema(): z.ZodObject<Properties<ContainerPort>> {
|
||||
export function CreateApiKeyInputSchema(): z.ZodObject<Properties<CreateApiKeyInput>> {
|
||||
return z.object({
|
||||
description: z.string().nullish(),
|
||||
memory: z.boolean().nullish(),
|
||||
name: z.string(),
|
||||
overwrite: z.boolean().nullish(),
|
||||
permissions: z.array(z.lazy(() => AddPermissionInputSchema())).nullish(),
|
||||
roles: z.array(RoleSchema).nullish()
|
||||
})
|
||||
|
||||
@@ -347,7 +347,11 @@ export enum ContainerState {
|
||||
|
||||
export type CreateApiKeyInput = {
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
/** Whether to create the key in memory only (true), or on disk (false) - memory only keys will not persist through reboots of the API */
|
||||
memory?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
name: Scalars['String']['input'];
|
||||
/** This will replace the existing key if one already exists with the same name, otherwise returns the existing key */
|
||||
overwrite?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
permissions?: InputMaybe<Array<AddPermissionInput>>;
|
||||
roles?: InputMaybe<Array<Role>>;
|
||||
};
|
||||
|
||||
@@ -27,6 +27,10 @@ input CreateApiKeyInput {
|
||||
description: String
|
||||
roles: [Role!]
|
||||
permissions: [AddPermissionInput!]
|
||||
""" This will replace the existing key if one already exists with the same name, otherwise returns the existing key """
|
||||
overwrite: Boolean
|
||||
""" Whether to create the key in memory only (true), or on disk (false) - memory only keys will not persist through reboots of the API """
|
||||
memory: Boolean
|
||||
}
|
||||
|
||||
input AddPermissionInput {
|
||||
@@ -103,12 +103,14 @@ export class ApiKeyService implements OnModuleInit {
|
||||
roles,
|
||||
permissions,
|
||||
overwrite = false,
|
||||
memory = false,
|
||||
}: {
|
||||
name: string;
|
||||
description: string | undefined;
|
||||
roles?: Role[];
|
||||
permissions?: Permission[] | AddPermissionInput[];
|
||||
overwrite?: boolean;
|
||||
memory?: boolean;
|
||||
}): Promise<ApiKeyWithSecret> {
|
||||
const trimmedName = name?.trim();
|
||||
const sanitizedName = this.sanitizeName(trimmedName);
|
||||
@@ -127,7 +129,7 @@ export class ApiKeyService implements OnModuleInit {
|
||||
|
||||
const existingKey = this.findByField('name', sanitizedName);
|
||||
if (!overwrite && existingKey) {
|
||||
throw new GraphQLError('API key name already exists, use overwrite flag to update');
|
||||
return existingKey;
|
||||
}
|
||||
const apiKey: Partial<ApiKeyWithSecret> = {
|
||||
id: uuidv4(),
|
||||
@@ -142,7 +144,11 @@ export class ApiKeyService implements OnModuleInit {
|
||||
// Update createdAt date
|
||||
apiKey.createdAt = new Date().toISOString();
|
||||
|
||||
await this.saveApiKey(apiKey as ApiKeyWithSecret);
|
||||
if (memory) {
|
||||
this.memoryApiKeys.push(apiKey as ApiKeyWithSecret)
|
||||
} else {
|
||||
await this.saveApiKey(apiKey as ApiKeyWithSecret);
|
||||
}
|
||||
|
||||
return apiKey as ApiKeyWithSecret;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ import { ApiKeyService } from '@app/unraid-api/auth/api-key.service';
|
||||
import { AuthService } from '@app/unraid-api/auth/auth.service';
|
||||
import { CookieService } from '@app/unraid-api/auth/cookie.service';
|
||||
|
||||
import { AuthResolver } from './auth.resolver';
|
||||
import { ApiKeyResolver } from './api-key.resolver';
|
||||
|
||||
describe('AuthResolver', () => {
|
||||
let resolver: AuthResolver;
|
||||
describe('ApiKeyResolver', () => {
|
||||
let resolver: ApiKeyResolver;
|
||||
let authService: AuthService;
|
||||
let apiKeyService: ApiKeyService;
|
||||
let authzService: AuthZService;
|
||||
@@ -45,7 +45,7 @@ describe('AuthResolver', () => {
|
||||
authzService = new AuthZService(enforcer);
|
||||
cookieService = new CookieService();
|
||||
authService = new AuthService(cookieService, apiKeyService, authzService);
|
||||
resolver = new AuthResolver(authService, apiKeyService);
|
||||
resolver = new ApiKeyResolver(authService, apiKeyService);
|
||||
});
|
||||
|
||||
describe('apiKeys', () => {
|
||||
@@ -6,7 +6,6 @@ import { AuthActionVerb, AuthPossession, UsePermissions } from 'nest-authz';
|
||||
|
||||
import type {
|
||||
AddRoleForApiKeyInput,
|
||||
AddRoleForUserInput,
|
||||
ApiKey,
|
||||
ApiKeyWithSecret,
|
||||
CreateApiKeyInput,
|
||||
@@ -17,10 +16,10 @@ import { ApiKeyService } from '@app/unraid-api/auth/api-key.service';
|
||||
import { GraphqlAuthGuard } from '@app/unraid-api/auth/auth.guard';
|
||||
import { AuthService } from '@app/unraid-api/auth/auth.service';
|
||||
|
||||
@Resolver('Auth')
|
||||
@Resolver('ApiKey')
|
||||
@UseGuards(GraphqlAuthGuard)
|
||||
@Throttle({ default: { limit: 100, ttl: 60000 } }) // 100 requests per minute
|
||||
export class AuthResolver {
|
||||
export class ApiKeyResolver {
|
||||
constructor(
|
||||
private authService: AuthService,
|
||||
private apiKeyService: ApiKeyService
|
||||
@@ -61,6 +60,8 @@ export class AuthResolver {
|
||||
description: input.description ?? undefined,
|
||||
roles: input.roles ?? [],
|
||||
permissions: input.permissions ?? [],
|
||||
memory: input.memory ?? false,
|
||||
overwrite: input.overwrite ?? false
|
||||
});
|
||||
|
||||
await this.authService.syncApiKeyRoles(apiKey.id, apiKey.roles);
|
||||
@@ -4,13 +4,14 @@ import { AuthModule } from '@app/unraid-api/auth/auth.module';
|
||||
import { ArrayResolver } from '@app/unraid-api/graph/resolvers/array/array.resolver';
|
||||
import { DockerResolver } from '@app/unraid-api/graph/resolvers/docker/docker.resolver';
|
||||
|
||||
import { AuthResolver } from './auth/auth.resolver';
|
||||
import { ApiKeyResolver } from './api-key/api-key.resolver';
|
||||
import { CloudResolver } from './cloud/cloud.resolver';
|
||||
import { ConfigResolver } from './config/config.resolver';
|
||||
import { DisksResolver } from './disks/disks.resolver';
|
||||
import { DisplayResolver } from './display/display.resolver';
|
||||
import { FlashResolver } from './flash/flash.resolver';
|
||||
import { InfoResolver } from './info/info.resolver';
|
||||
import { MeResolver } from './me/me.resolver';
|
||||
import { NotificationsResolver } from './notifications/notifications.resolver';
|
||||
import { NotificationsService } from './notifications/notifications.service';
|
||||
import { OnlineResolver } from './online/online.resolver';
|
||||
@@ -19,13 +20,12 @@ import { RegistrationResolver } from './registration/registration.resolver';
|
||||
import { ServerResolver } from './servers/server.resolver';
|
||||
import { VarsResolver } from './vars/vars.resolver';
|
||||
import { VmsResolver } from './vms/vms.resolver';
|
||||
import { MeResolver } from './me/me.resolver';
|
||||
|
||||
@Module({
|
||||
imports: [AuthModule],
|
||||
providers: [
|
||||
ArrayResolver,
|
||||
AuthResolver,
|
||||
ApiKeyResolver,
|
||||
CloudResolver,
|
||||
ConfigResolver,
|
||||
DisksResolver,
|
||||
@@ -43,6 +43,6 @@ import { MeResolver } from './me/me.resolver';
|
||||
NotificationsService,
|
||||
MeResolver,
|
||||
],
|
||||
exports: [AuthModule, AuthResolver],
|
||||
exports: [AuthModule, ApiKeyResolver],
|
||||
})
|
||||
export class ResolversModule {}
|
||||
|
||||
Reference in New Issue
Block a user