diff --git a/src/controllers/ioc/keystoneInjector.ts b/src/controllers/ioc/keystoneInjector.ts index 1d6e4b41f..a29f9dd4c 100644 --- a/src/controllers/ioc/keystoneInjector.ts +++ b/src/controllers/ioc/keystoneInjector.ts @@ -41,12 +41,14 @@ export class KeystoneService { public createContext(request: any, skipAccessControl: boolean = false): any { const _scopes = scopes(request.user.scope); + const identityProvider = request.user.identity_provider; + const identity = { id: null, name: resolveName(request.user), username: resolveUsername(request.user), namespace: request.params.ns, - roles: JSON.stringify(scopesToRoles(null, _scopes)), + roles: JSON.stringify(scopesToRoles(identityProvider, _scopes)), scopes: _scopes, userId: null, } as any; diff --git a/src/controllers/v2/NamespaceController.ts b/src/controllers/v2/NamespaceController.ts index 66a067afa..b8fe3c652 100644 --- a/src/controllers/v2/NamespaceController.ts +++ b/src/controllers/v2/NamespaceController.ts @@ -147,14 +147,15 @@ export class NamespaceController extends Controller { */ @Post() @OperationId('create-namespace') + @Security('jwt', []) public async create( @Request() request: any, - @Query() name?: String - ): Promise { + @Query() namespace?: String + ): Promise { const result = await this.keystone.executeGraphQL({ context: this.keystone.createContext(request), query: createNS, - variables: { name }, + variables: { namespace }, }); logger.debug('Result %j', result); if (result.errors) { @@ -164,7 +165,7 @@ export class NamespaceController extends Controller { }); throw new ValidateError(errors, 'Unable to create namespace'); } - return result.data.createNamespace.name; + return { name: result.data.createNamespace.name }; } /** @@ -267,8 +268,8 @@ const deleteNS = gql` `; const createNS = gql` - mutation CreateNamespace($name: String) { - createNamespace(name: $name) { + mutation CreateNamespace($namespace: String) { + createNamespace(namespace: $namespace) { name } } diff --git a/src/controllers/v2/openapi.yaml b/src/controllers/v2/openapi.yaml index 338ac8ae0..3b09dac42 100644 --- a/src/controllers/v2/openapi.yaml +++ b/src/controllers/v2/openapi.yaml @@ -1185,6 +1185,29 @@ paths: - jwt: [] parameters: [] + post: + operationId: create-namespace + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Namespace' + description: 'Create a namespace' + summary: 'Create Namespace' + tags: + - Namespaces + security: + - + jwt: [] + parameters: + - + in: query + name: namespace + required: false + schema: + type: string '/namespaces/{ns}': get: operationId: namespace-profile diff --git a/src/controllers/v2/routes.ts b/src/controllers/v2/routes.ts index 4baa2c8b2..2e6c3236e 100644 --- a/src/controllers/v2/routes.ts +++ b/src/controllers/v2/routes.ts @@ -1062,6 +1062,36 @@ export function RegisterRoutes(app: express.Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + app.post('/ds/api/v2/namespaces', + authenticateMiddleware([{"jwt":[]}]), + + async function NamespaceController_create(request: any, response: any, next: any) { + const args = { + request: {"in":"request","name":"request","required":true,"dataType":"object"}, + namespace: {"in":"query","name":"namespace","dataType":"string"}, + }; + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request, response); + + const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer; + + const controller: any = await container.get(NamespaceController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + + const promise = controller.create.apply(controller, validatedArgs as any); + promiseHandler(controller, promise, response, undefined, next); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa app.delete('/ds/api/v2/namespaces/:ns', authenticateMiddleware([{"jwt":["Namespace.Manage"]}]), diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index 4a3db56d8..e283ed4f0 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -426,9 +426,11 @@ module.exports = { ) => { const namespaceValidationRule = '^[a-z][a-z0-9-]{4,14}$'; + const newNS = args.namespace ? args.namespace : newNamespaceID(); + regExprValidation( namespaceValidationRule, - args.namespace ? args.namespace : newNamespaceID(), + newNS, 'Namespace name must be between 5 and 15 alpha-numeric lowercase characters and begin with an alphabet.' ); @@ -452,7 +454,7 @@ module.exports = { envCtx.issuerEnvConfig.clientId, envCtx.issuerEnvConfig.clientSecret ); - await nsService.checkNamespaceAvailable(args.namespace); + await nsService.checkNamespaceAvailable(newNS); // This function gets all resources but also sets the accessToken in envCtx // which we need to create the resource set @@ -472,7 +474,7 @@ module.exports = { 'CredentialIssuer.Admin', ]; const res = { - name: args.namespace, + name: newNS, type: 'namespace', resource_scopes: scopes, ownerManagedAccess: true, @@ -501,27 +503,24 @@ module.exports = { envCtx.issuerEnvConfig.clientSecret ); - await kcGroupService.createIfMissing('ns', args.namespace); + await kcGroupService.createIfMissing('ns', newNS); await recordActivity( context.sudo(), 'create', 'Namespace', - args.namespace, - `Created ${args.namespace} namespace`, + newNS, + `Created ${newNS} namespace`, 'success', JSON.stringify({ message: '{actor} created {ns} namespace', params: { actor: context.authedItem.name, - ns: args.namespace, + ns: newNS, }, }), - args.namespace, - [ - `Namespace:${args.namespace}`, - `actor:${context.authedItem.name}`, - ] + newNS, + [`Namespace:${newNS}`, `actor:${context.authedItem.name}`] ); return rset; diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index d34a32302..814e0a347 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -5326,7 +5326,7 @@ export type MutationUpdateCurrentNamespaceArgs = { export type MutationCreateNamespaceArgs = { - namespace: Scalars['String']; + namespace?: Maybe; }; diff --git a/src/services/keystone/types.ts b/src/services/keystone/types.ts index d34a32302..814e0a347 100644 --- a/src/services/keystone/types.ts +++ b/src/services/keystone/types.ts @@ -5326,7 +5326,7 @@ export type MutationUpdateCurrentNamespaceArgs = { export type MutationCreateNamespaceArgs = { - namespace: Scalars['String']; + namespace?: Maybe; };