From 30bc4da056aec5cc30bb1ad5296d977f2d8a08a4 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Mon, 3 Jul 2023 15:08:08 -0700 Subject: [PATCH 01/81] upd controllers --- src/api-openapi.js | 23 ++++------ src/controllers/v2/GatewayController.ts | 14 ++++++ src/controllers/v2/openapi.yaml | 57 +++++++++++++++++++++--- src/controllers/v2/routes.ts | 59 +++++++++++++++++++++---- src/controllers/v2/types-extra.ts | 9 ++++ src/controllers/v2/types.ts | 12 +++-- 6 files changed, 143 insertions(+), 31 deletions(-) diff --git a/src/api-openapi.js b/src/api-openapi.js index bcf052c44..b2d1f99a2 100644 --- a/src/api-openapi.js +++ b/src/api-openapi.js @@ -23,13 +23,6 @@ class ApiOpenapiApp { RegisterRoutes(app); - // RFC 8631 service-desc link relation - // https://datatracker.ietf.org/doc/html/rfc8631 - app.get('/ds/api', (req, res) => { - res.setHeader('Link', '; rel="service-desc"'); - res.status(204).end(); - }); - app.get('/ds/api/openapi.yaml', (req, res) => { res.setHeader('Content-Type', 'application/yaml'); res.send(spec); @@ -54,14 +47,9 @@ class ApiOpenapiApp { */ specObject.components.securitySchemes.jwt.flows.clientCredentials.tokenUrl = `${process.env.OIDC_ISSUER}/protocol/openid-connect/token`; - RegisterRoutes(app); + specObject.components.securitySchemes.openid.openIdConnectUrl = `${process.env.OIDC_ISSUER}/.well-known/openid-configuration`; - // RFC 8631 service-desc link relation - // https://datatracker.ietf.org/doc/html/rfc8631 - app.get('/ds/api/v2', (req, res) => { - res.setHeader('Link', '; rel="service-desc"'); - res.status(204).end(); - }); + RegisterRoutes(app); app.get('/ds/api/v2/openapi.yaml', (req, res) => { res.setHeader('Content-Type', 'application/yaml'); @@ -86,6 +74,13 @@ class ApiOpenapiApp { this.prepareV2(app); this.prepareV1(app); + // RFC 8631 service-desc link relation + // https://datatracker.ietf.org/doc/html/rfc8631 + app.get('/ds/api', (req, res) => { + res.setHeader('Link', '; rel="service-desc"'); + res.status(204).end(); + }); + app.use(function errorHandler(err, req, res, next) { if (err instanceof UnauthorizedError) { return res.status(err.status).json({ diff --git a/src/controllers/v2/GatewayController.ts b/src/controllers/v2/GatewayController.ts index 94a7f5c1c..79b0b7a54 100644 --- a/src/controllers/v2/GatewayController.ts +++ b/src/controllers/v2/GatewayController.ts @@ -9,6 +9,8 @@ import { Security, Body, Tags, + FormField, + UploadedFile, } from 'tsoa'; import { KeystoneService } from '../ioc/keystoneInjector'; import { inject, injectable } from 'tsyringe'; @@ -20,6 +22,7 @@ import { removeKeys, } from '../../batch/feed-worker'; import { GatewayRoute } from './types'; +import { PublishResult } from './types-extra'; @injectable() @Route('/namespaces/{ns}/gateway') @@ -31,6 +34,17 @@ export class GatewayController extends Controller { this.keystone = _keystone; } + @Put() + @OperationId('publish-gateway-config') + @Security('jwt', ['Gateway.Config']) + public async put( + @FormField() dryRun: boolean, + @UploadedFile() configFile: Express.Multer.File + ): Promise { + // stub - gwa-api implements this + return { error: 'Stub - not implemented' }; + } + /** * Get a summary of your Gateway Services * > `Required Scope:` Namespace.Manage diff --git a/src/controllers/v2/openapi.yaml b/src/controllers/v2/openapi.yaml index 5c6ad39cd..338ac8ae0 100644 --- a/src/controllers/v2/openapi.yaml +++ b/src/controllers/v2/openapi.yaml @@ -188,6 +188,16 @@ components: - tag2 organization: ministry-of-citizens-services organizationUnit: databc + PublishResult: + properties: + message: + type: string + results: + type: string + error: + type: string + type: object + additionalProperties: false GatewayServiceRefID: type: string GatewayRouteRefID: @@ -277,9 +287,7 @@ components: clientRegistration: managed clientId: a-client-id clientSecret: a-client-secret - CredentialIssuerRefID: - type: string - UserRefID: + undefinedRefID: type: string CredentialIssuer: properties: @@ -338,9 +346,9 @@ components: type: string type: array inheritFrom: - $ref: '#/components/schemas/CredentialIssuerRefID' + $ref: '#/components/schemas/undefinedRefID' owner: - $ref: '#/components/schemas/UserRefID' + $ref: '#/components/schemas/undefinedRefID' type: object additionalProperties: false example: @@ -350,7 +358,7 @@ components: clientAuthenticator: client-secret mode: auto environmentDetails: [] - owner: acope@idir + owner: janis@gov.bc.ca Maybe_Scalars-at-String_: type: string nullable: true @@ -539,6 +547,8 @@ components: type: string LegalRefID: type: string + CredentialIssuerRefID: + type: string Environment: properties: appId: @@ -621,6 +631,10 @@ components: description: 'Authz Portal Login' scheme: bearer bearerFormat: JWT + openid: + type: openIdConnect + description: 'OIDC Login' + openIdConnectUrl: 'https://well_known_endpoint' info: title: 'APS Directory API' version: 1.1.0 @@ -961,6 +975,37 @@ paths: schema: type: string '/namespaces/{ns}/gateway': + put: + operationId: publish-gateway-config + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/PublishResult' + tags: + - 'Gateway Services' + security: + - + jwt: + - Gateway.Config + parameters: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + dryRun: + type: string + configFile: + type: string + format: binary + required: + - dryRun + - configFile get: operationId: get-gateway-routes responses: diff --git a/src/controllers/v2/routes.ts b/src/controllers/v2/routes.ts index 21bb4b1ec..4baa2c8b2 100644 --- a/src/controllers/v2/routes.ts +++ b/src/controllers/v2/routes.ts @@ -34,6 +34,8 @@ const promiseAny = require('promise.any'); import { iocContainer } from './../ioc'; import { IocContainer, IocContainerFactory } from '@tsoa/runtime'; import * as express from 'express'; +const multer = require('multer'); +const upload = multer(); // 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 @@ -128,6 +130,16 @@ const models: TsoaRoute.Models = { "additionalProperties": false, }, // 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 + "PublishResult": { + "dataType": "refObject", + "properties": { + "message": {"dataType":"string"}, + "results": {"dataType":"string"}, + "error": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // 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 "GatewayServiceRefID": { "dataType": "refAlias", "type": {"dataType":"string","validators":{}}, @@ -185,12 +197,7 @@ const models: TsoaRoute.Models = { "additionalProperties": false, }, // 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 - "CredentialIssuerRefID": { - "dataType": "refAlias", - "type": {"dataType":"string","validators":{}}, - }, - // 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 - "UserRefID": { + "undefinedRefID": { "dataType": "refAlias", "type": {"dataType":"string","validators":{}}, }, @@ -215,8 +222,8 @@ const models: TsoaRoute.Models = { "resourceScopes": {"dataType":"array","array":{"dataType":"string"}}, "clientRoles": {"dataType":"array","array":{"dataType":"string"}}, "clientMappers": {"dataType":"array","array":{"dataType":"string"}}, - "inheritFrom": {"ref":"CredentialIssuerRefID"}, - "owner": {"ref":"UserRefID"}, + "inheritFrom": {"ref":"undefinedRefID"}, + "owner": {"ref":"undefinedRefID"}, }, "additionalProperties": false, }, @@ -355,6 +362,11 @@ const models: TsoaRoute.Models = { "type": {"dataType":"string","validators":{}}, }, // 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 + "CredentialIssuerRefID": { + "dataType": "refAlias", + "type": {"dataType":"string","validators":{}}, + }, + // 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 "Environment": { "dataType": "refObject", "properties": { @@ -780,6 +792,37 @@ 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.put('/ds/api/v2/namespaces/:ns/gateway', + authenticateMiddleware([{"jwt":["Gateway.Config"]}]), + upload.single('configFile'), + + async function GatewayController_put(request: any, response: any, next: any) { + const args = { + dryRun: {"in":"formData","name":"dryRun","required":true,"dataType":"string"}, + configFile: {"in":"formData","name":"configFile","required":true,"dataType":"file"}, + }; + + // 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(GatewayController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + + const promise = controller.put.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.get('/ds/api/v2/namespaces/:ns/gateway', authenticateMiddleware([{"jwt":["Namespace.Manage"]}]), diff --git a/src/controllers/v2/types-extra.ts b/src/controllers/v2/types-extra.ts index ecc3eede2..438ddde0d 100644 --- a/src/controllers/v2/types-extra.ts +++ b/src/controllers/v2/types-extra.ts @@ -10,3 +10,12 @@ export interface ActivityDetail { activityAt: Scalars['DateTime']; blob?: any; } + +/** + * @tsoaModel + */ +export interface PublishResult { + message?: string; + results?: string; + error?: string; +} diff --git a/src/controllers/v2/types.ts b/src/controllers/v2/types.ts index 7e4c9839c..2573e41d3 100644 --- a/src/controllers/v2/types.ts +++ b/src/controllers/v2/types.ts @@ -315,7 +315,7 @@ export interface Environment { * "clientAuthenticator": "client-secret", * "mode": "auto", * "environmentDetails": [], - * "owner": "acope@idir" + * "owner": "janis@gov.bc.ca" * } */ export interface CredentialIssuer { @@ -336,8 +336,8 @@ export interface CredentialIssuer { resourceScopes?: string[]; clientRoles?: string[]; clientMappers?: string[]; - inheritFrom?: CredentialIssuerRefID; - owner?: UserRefID; + inheritFrom?: undefinedRefID; + owner?: undefinedRefID; } @@ -477,6 +477,7 @@ export interface User { name?: string; email?: string; legalsAgreed?: UserLegalsAgreed[]; + provider?: string; } @@ -554,3 +555,8 @@ export type OrganizationUnitRefID = string * @tsoaModel */ export type UserRefID = string + +/** + * @tsoaModel + */ +export type undefinedRefID = string From af0e5c5e29fb42465f211218ea0050e2b295b7fb Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Mon, 3 Jul 2023 16:46:05 -0700 Subject: [PATCH 02/81] add openid as api auth --- src/tsoa-v2.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tsoa-v2.json b/src/tsoa-v2.json index f121dff89..5046af3f3 100644 --- a/src/tsoa-v2.json +++ b/src/tsoa-v2.json @@ -24,6 +24,11 @@ "description": "Authz Portal Login", "scheme": "bearer", "bearerFormat": "JWT" + }, + "openid": { + "type": "openIdConnect", + "description": "OIDC Login", + "openIdConnectUrl": "https://well_known_endpoint" } }, "tags": [ From add25e221ab3e4373fc0f93d9cde3d842341dd96 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Mon, 3 Jul 2023 17:05:41 -0700 Subject: [PATCH 03/81] add namespace creation --- src/controllers/v2/NamespaceController.ts | 40 +++++++++++++++++++++++ src/lists/extensions/Namespace.ts | 12 ++++--- src/services/identifiers.ts | 10 ++++-- src/services/utils.ts | 1 - src/test/services/identifiers.test.js | 11 +++++++ 5 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 src/test/services/identifiers.test.js diff --git a/src/controllers/v2/NamespaceController.ts b/src/controllers/v2/NamespaceController.ts index 5a1007aff..758e47cfd 100644 --- a/src/controllers/v2/NamespaceController.ts +++ b/src/controllers/v2/NamespaceController.ts @@ -9,6 +9,7 @@ import { Tags, Delete, Query, + Post, } from 'tsoa'; import { ValidateError, FieldErrors } from 'tsoa'; import { KeystoneService } from '../ioc/keystoneInjector'; @@ -136,6 +137,37 @@ export class NamespaceController extends Controller { return result.data.namespace; } + /** + * Create a namespace + * + * @summary Create Namespace + * @param ns + * @param request + * @returns + */ + @Post() + @OperationId('create-namespace') + @Security('jwt', []) + public async create( + @Query() name: String, + @Request() request: any + ): Promise { + const result = await this.keystone.executeGraphQL({ + context: this.keystone.createContext(request), + query: createNS, + variables: { name }, + }); + logger.debug('Result %j', result); + if (result.errors) { + const errors: FieldErrors = {}; + result.errors.forEach((err: any, ind: number) => { + errors[`d${ind}`] = { message: err.message }; + }); + throw new ValidateError(errors, 'Unable to create namespace'); + } + return result.data.createNamespace.name; + } + /** * Delete the namespace * > `Required Scope:` Namespace.Manage @@ -234,3 +266,11 @@ const deleteNS = gql` forceDeleteNamespace(namespace: $ns, force: $force) } `; + +const createNS = gql` + mutation CreateNamespace($name: String) { + createNamespace(name: $name) { + name + } + } +`; diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index 9bb8b4e7c..007954bf1 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -34,6 +34,7 @@ import { import { GWAService } from '../../services/gwaapi'; import { camelCaseAttributes, + regExprValidation, transformSingleValueAttributes, } from '../../services/utils'; import getSubjectToken from '../../auth/auth-token'; @@ -54,6 +55,7 @@ import { getResource, transformOrgAndOrgUnit, } from '../../services/keycloak/namespace-details'; +import { newNamespaceID } from '@/services/identifiers'; const logger = Logger('ext.Namespace'); @@ -422,7 +424,7 @@ module.exports = { }, }, { - schema: 'createNamespace(namespace: String!): Namespace', + schema: 'createNamespace(namespace: String): Namespace', resolver: async ( item: any, args: any, @@ -431,10 +433,10 @@ module.exports = { { query, access }: any ) => { const namespaceValidationRule = '^[a-z][a-z0-9-]{4,14}$'; - const re = new RegExp(namespaceValidationRule); - assert.strictEqual( - re.test(args.namespace), - true, + + regExprValidation( + namespaceValidationRule, + args.namespace ? args.namespace : newNamespaceID(), 'Namespace name must be between 5 and 15 alpha-numeric lowercase characters and begin with an alphabet.' ); diff --git a/src/services/identifiers.ts b/src/services/identifiers.ts index ab3f01f97..24af1f39b 100644 --- a/src/services/identifiers.ts +++ b/src/services/identifiers.ts @@ -11,11 +11,15 @@ export function isEnvironmentID(id: string): boolean { } export function newProductID(): string { - return uuidv4().replace(/-/g, '').toUpperCase().substr(0, 12); + return uuidv4().replace(/-/g, '').toUpperCase().substring(0, 12); } export function newApplicationID(): string { - return uuidv4().replace(/-/g, '').toUpperCase().substr(0, 11); + return uuidv4().replace(/-/g, '').toUpperCase().substring(0, 11); } export function newEnvironmentID(): string { - return uuidv4().replace(/-/g, '').toUpperCase().substr(0, 8); + return uuidv4().replace(/-/g, '').toUpperCase().substring(0, 8); +} + +export function newNamespaceID(): string { + return 'gw-' + uuidv4().replace(/-/g, '').toLowerCase().substring(0, 5); } diff --git a/src/services/utils.ts b/src/services/utils.ts index 278f42367..ee8b8e195 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -57,7 +57,6 @@ export function regExprValidation( value: string, errorMessage: string ) { - const namespaceValidationRule = '^[a-z][a-z0-9-]{4,14}$'; const re = new RegExp(rule); assert.strictEqual(re.test(value), true, errorMessage); } diff --git a/src/test/services/identifiers.test.js b/src/test/services/identifiers.test.js new file mode 100644 index 000000000..c288d9c84 --- /dev/null +++ b/src/test/services/identifiers.test.js @@ -0,0 +1,11 @@ +import fetch from 'node-fetch'; +import { newNamespaceID } from '../../services/identifiers'; + +describe('Identifiers', function () { + it('it should be a valid namespace', async function () { + const result = newNamespaceID(); + expect(result).toHaveLength(8); + expect(result.startsWith('gw-')).toBeTruthy(); + console.log(result); + }); +}); From 4ffeca3d20b20dd2d0f178e20feabaecc1b19ddc Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Mon, 3 Jul 2023 17:16:35 -0700 Subject: [PATCH 04/81] fix build error --- src/lists/extensions/Namespace.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index 007954bf1..4a3db56d8 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -7,7 +7,6 @@ import { ResourceSetInput, } from '../../services/uma2'; import { - getOrganizationUnit, lookupProductEnvironmentServicesBySlug, lookupUsersByUsernames, recordActivity, @@ -18,7 +17,6 @@ import { getNamespaceResourceSets, isUserBasedResourceOwners, doClientLoginForCredentialIssuer, - EnvironmentContext, getOrgPoliciesForResource, } from './Common'; import type { TokenExchangeResult } from './Common'; @@ -32,18 +30,12 @@ import { DeleteNamespaceValidate, } from '../../services/workflow/delete-namespace'; import { GWAService } from '../../services/gwaapi'; -import { - camelCaseAttributes, - regExprValidation, - transformSingleValueAttributes, -} from '../../services/utils'; +import { regExprValidation } from '../../services/utils'; import getSubjectToken from '../../auth/auth-token'; import { GroupAccessService, NamespaceService, } from '../../services/org-groups'; -import { IssuerEnvironmentConfig } from '../../services/workflow/types'; -import { Keystone } from '@keystonejs/keystone'; import { Logger } from '../../logger'; import { getGwaProductEnvironment } from '../../services/workflow'; import { NotificationService } from '../../services/notification/notification.service'; @@ -55,7 +47,7 @@ import { getResource, transformOrgAndOrgUnit, } from '../../services/keycloak/namespace-details'; -import { newNamespaceID } from '@/services/identifiers'; +import { newNamespaceID } from '../../services/identifiers'; const logger = Logger('ext.Namespace'); From 7be103d04592142cf12bebaf837b26dd7a8c9185 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Mon, 3 Jul 2023 18:23:34 -0700 Subject: [PATCH 05/81] fix required field for create namespace --- src/controllers/v2/NamespaceController.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/controllers/v2/NamespaceController.ts b/src/controllers/v2/NamespaceController.ts index 758e47cfd..66a067afa 100644 --- a/src/controllers/v2/NamespaceController.ts +++ b/src/controllers/v2/NamespaceController.ts @@ -147,10 +147,9 @@ export class NamespaceController extends Controller { */ @Post() @OperationId('create-namespace') - @Security('jwt', []) public async create( - @Query() name: String, - @Request() request: any + @Request() request: any, + @Query() name?: String ): Promise { const result = await this.keystone.executeGraphQL({ context: this.keystone.createContext(request), From ff83bb728ead6ace08569908dcb643589eb74b65 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 4 Jul 2023 09:15:06 -0700 Subject: [PATCH 06/81] upd roles for tsoa user --- src/controllers/ioc/keystoneInjector.ts | 4 ++- src/controllers/v2/NamespaceController.ts | 13 +++++----- src/controllers/v2/openapi.yaml | 23 +++++++++++++++++ src/controllers/v2/routes.ts | 30 +++++++++++++++++++++++ src/lists/extensions/Namespace.ts | 23 +++++++++-------- src/nextapp/shared/types/query.types.ts | 2 +- src/services/keystone/types.ts | 2 +- 7 files changed, 76 insertions(+), 21 deletions(-) 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; }; From ce74539f476be84c66938885d0b6edf45acd207b Mon Sep 17 00:00:00 2001 From: Elson9 Date: Wed, 5 Jul 2023 16:06:13 -0700 Subject: [PATCH 07/81] filter out inactive environments from drop down (#825) --- .../httplocalhost4180managerconsumers-386f4b.gql | 1 + src/nextapp/components/access-request/grant-access-dialog.tsx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/authz/graphql-whitelist/httplocalhost4180managerconsumers-386f4b.gql b/src/authz/graphql-whitelist/httplocalhost4180managerconsumers-386f4b.gql index 3d77859e8..46dd37827 100644 --- a/src/authz/graphql-whitelist/httplocalhost4180managerconsumers-386f4b.gql +++ b/src/authz/graphql-whitelist/httplocalhost4180managerconsumers-386f4b.gql @@ -6,6 +6,7 @@ environments { id name + active flow credentialIssuer { name diff --git a/src/nextapp/components/access-request/grant-access-dialog.tsx b/src/nextapp/components/access-request/grant-access-dialog.tsx index 5e7cc2eb9..17b39fda5 100644 --- a/src/nextapp/components/access-request/grant-access-dialog.tsx +++ b/src/nextapp/components/access-request/grant-access-dialog.tsx @@ -181,7 +181,7 @@ const GrantAccessDialog: React.FC = ({ {product && data?.allProductsByNamespace .find((p) => p.id === product) - ?.environments.map((e) => ( + ?.environments.filter((e) => e.active).map((e) => ( @@ -272,6 +272,7 @@ const query = gql` environments { id name + active flow credentialIssuer { name From 93bce6afc50f0b7a39116ba377b4937db39c7b18 Mon Sep 17 00:00:00 2001 From: ike thecoder Date: Wed, 5 Jul 2023 16:43:11 -0700 Subject: [PATCH 08/81] Fix BCDC Datasets out of sync (#837) --------- Co-authored-by: James Elson Co-authored-by: Elson9 --- feeds/README.md | 3 +++ feeds/ckan/index.js | 16 ++++------------ feeds/index.js | 2 ++ feeds/utils/transfers.js | 26 ++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/feeds/README.md b/feeds/README.md index 9bb780906..30860e2c7 100644 --- a/feeds/README.md +++ b/feeds/README.md @@ -39,11 +39,14 @@ ## Configuration ``` +export LOG_FEEDS=ON export DESTINATION_URL=https://aps-portal-feature-sprint13-poc.apps.silver.devops.gov.bc.ca export WORKING_PATH=`pwd`/_tmp export KONG_ADMIN_URL=https://adminapi-264e6f-dev.apps.silver.devops.gov.bc.ca export CKAN_URL=https://catalog.data.gov.bc.ca export PROM_URL=https://prom-264e6f-dev.apps.silver.devops.gov.bc.ca + +npm run start ``` #### GatewayService diff --git a/feeds/ckan/index.js b/feeds/ckan/index.js index 1176f6417..81e1805a1 100644 --- a/feeds/ckan/index.js +++ b/feeds/ckan/index.js @@ -83,23 +83,15 @@ async function sync({ url, workingPath, destinationUrl }) { const xfer = transfers(workingPath, url, exceptions); await xfer.copy('/api/action/group_list?limit=100&offset=0', 'group-keys'); - await xfer.copy( - '/api/action/package_list?limit=100&offset=0', - 'package-keys' + await xfer.copySearch( + '/api/action/package_search?fq=groups:(bc-government-api-registry)', + 'packages/' ); await xfer.concurrentWork( getCkanDataProducer(xfer, 'group-keys', '/api/action/group_show', 'groups/') ); - await xfer.concurrentWork( - getCkanDataProducer( - xfer, - 'package-keys', - '/api/action/package_show', - 'packages/' - ), - 10 - ); + console.log('Exceptions? ' + (exceptions.length == 0 ? 'NO' : 'YES!')); console.log(JSON.stringify(exceptions, null, 4)); diff --git a/feeds/index.js b/feeds/index.js index 33adc525c..7b619e444 100644 --- a/feeds/index.js +++ b/feeds/index.js @@ -171,6 +171,8 @@ if (process.env.SCHEDULE == 'true') { runTimedJob('prometheus', 120, { numDays: 1 }); runTimedJob('prometheus', 24 * 60 + 5, { numDays: 5 }); runTimedJob('kong', 1 * 60, {}); + runTimedJob('ckan', (24 * 60) + 30, {}); + runTimedJob('ckan_org', 24 * 60, {}); } const server = app.listen(port, () => { diff --git a/feeds/utils/transfers.js b/feeds/utils/transfers.js index 3f14f5305..22efd0fd1 100644 --- a/feeds/utils/transfers.js +++ b/feeds/utils/transfers.js @@ -71,6 +71,32 @@ function transfers(workingPath, baseUrl, exceptions) { }); }, + copySearch: async function (_url, filename, index = 0) { + log.debug('[copySearch] %s%s', baseUrl, _url); + return fetch(baseUrl + _url) + .then(checkStatus) + .then((data) => data.json()) + .then((json) => { + for (const item of json.result.results) { + const out = + workingPath + '/' + filename + item.name + '-' + index + '.json'; + fs.writeFileSync( + out, + JSON.stringify({ result: item }, null, 4), + null + ); + } + }) + .catch((err) => { + log.error('[copySearch] %s, %s', filename, err); + exceptions.push({ + relativeUrl: url, + filename: filename, + error: '' + err, + }); + }); + }, + read: function (filename) { const infile = workingPath + '/' + filename + '.json'; return JSON.parse(fs.readFileSync(infile)); From 47428273e18c376b74631b2a9b4d710c38af690a Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 7 Jul 2023 14:58:44 -0700 Subject: [PATCH 09/81] add description to namespace --- src/controllers/v2/NamespaceController.ts | 11 +++++++---- src/lists/extensions/Namespace.ts | 14 ++++++++++---- src/services/keycloak/namespace-details.ts | 1 + src/services/org-groups/namespace.ts | 10 ++++++++++ src/services/report/data/namespaces.ts | 2 ++ 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/controllers/v2/NamespaceController.ts b/src/controllers/v2/NamespaceController.ts index b8fe3c652..8ef8254e6 100644 --- a/src/controllers/v2/NamespaceController.ts +++ b/src/controllers/v2/NamespaceController.ts @@ -150,12 +150,13 @@ export class NamespaceController extends Controller { @Security('jwt', []) public async create( @Request() request: any, - @Query() namespace?: String + @Query() namespace?: String, + @Query() description?: String ): Promise { const result = await this.keystone.executeGraphQL({ context: this.keystone.createContext(request), query: createNS, - variables: { namespace }, + variables: { namespace, description }, }); logger.debug('Result %j', result); if (result.errors) { @@ -246,6 +247,7 @@ const item = gql` query Namespace($ns: String!) { namespace(ns: $ns) { name + description scopes { name } @@ -268,9 +270,10 @@ const deleteNS = gql` `; const createNS = gql` - mutation CreateNamespace($namespace: String) { - createNamespace(namespace: $namespace) { + mutation CreateNamespace($namespace: String, $description: String) { + createNamespace(namespace: $namespace, description: $description) { name + description } } `; diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index e283ed4f0..5a0ede0fb 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -63,6 +63,7 @@ const typeNamespace = ` type Namespace { id: String name: String!, + description: String!, scopes: [UMAScope], prodEnvId: String, permDomains: [String], @@ -416,7 +417,7 @@ module.exports = { }, }, { - schema: 'createNamespace(namespace: String): Namespace', + schema: 'createNamespace(name: String): Namespace', resolver: async ( item: any, args: any, @@ -424,14 +425,15 @@ module.exports = { info: any, { query, access }: any ) => { - const namespaceValidationRule = '^[a-z][a-z0-9-]{4,14}$'; + const namespaceValidationRule = + '(([A-Za-z0-9][-A-Za-z0-9]*)?[A-Za-z0-9])?'; - const newNS = args.namespace ? args.namespace : newNamespaceID(); + const newNS = args.name ? args.name : newNamespaceID(); regExprValidation( namespaceValidationRule, newNS, - 'Namespace name must be between 5 and 15 alpha-numeric lowercase characters and begin with an alphabet.' + 'Namespace name must be between 5 and 15 alpha-numeric lowercase characters and start and end with an alphabet.' ); const noauthContext = context.createContext({ @@ -505,6 +507,10 @@ module.exports = { await kcGroupService.createIfMissing('ns', newNS); + if (args.description) { + await nsService.updateDescription(newNS, args.description); + } + await recordActivity( context.sudo(), 'create', diff --git a/src/services/keycloak/namespace-details.ts b/src/services/keycloak/namespace-details.ts index 7823d4ad2..171f3afeb 100644 --- a/src/services/keycloak/namespace-details.ts +++ b/src/services/keycloak/namespace-details.ts @@ -68,6 +68,7 @@ export async function backfillGroupAttributes( const nsPermissions = await kcGroupService.getGroup('ns', ns); transformSingleValueAttributes(nsPermissions.attributes, [ + 'description', 'perm-data-plane', 'perm-protected-ns', 'org', diff --git a/src/services/org-groups/namespace.ts b/src/services/org-groups/namespace.ts index 958eb93c2..960a70823 100644 --- a/src/services/org-groups/namespace.ts +++ b/src/services/org-groups/namespace.ts @@ -26,6 +26,16 @@ export class NamespaceService { await this.groupService.updateGroup(group); } + async updateDescription(ns: string, description: string): Promise { + const group = await this.groupService.getGroup('ns', ns); + + group.attributes['description'] = [description]; + + logger.debug('[updateDescription] %s - %s', ns, description); + + await this.groupService.updateGroup(group); + } + /* Update the Group attributes for org and org-unit */ diff --git a/src/services/report/data/namespaces.ts b/src/services/report/data/namespaces.ts index c5d10c914..7fd0184ac 100644 --- a/src/services/report/data/namespaces.ts +++ b/src/services/report/data/namespaces.ts @@ -13,6 +13,7 @@ import { GWAService } from '../../gwaapi'; export interface ReportOfNamespaces { resource_id: string; name: string; + description?: string; permProtectedNs?: string; permDomains?: string[]; permDataPlane?: string; @@ -49,6 +50,7 @@ export async function getNamespaces( const nsPermissions = await kcGroupService.getGroup('ns', ns.name); transformSingleValueAttributes(nsPermissions.attributes, [ + 'description', 'perm-data-plane', 'perm-protected-ns', 'org', From 34cab4a0fdcb9c3960e2b61cf71f32e5a0bc5da3 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 7 Jul 2023 15:23:23 -0700 Subject: [PATCH 10/81] use name for namespace --- src/batch/data-rules.js | 2 +- src/controllers/v2/NamespaceController.ts | 13 ++++++++----- src/controllers/v2/openapi.yaml | 11 ++++++++++- src/controllers/v2/routes.ts | 5 +++-- src/controllers/v2/types.ts | 1 + src/lists/extensions/Namespace.ts | 5 +++-- .../components/new-namespace/new-namespace.tsx | 2 +- src/nextapp/shared/types/query.types.ts | 4 +++- src/services/keystone/types.ts | 4 +++- 9 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/batch/data-rules.js b/src/batch/data-rules.js index 847310919..f541d7b83 100644 --- a/src/batch/data-rules.js +++ b/src/batch/data-rules.js @@ -198,7 +198,7 @@ const metadata = { Namespace: { query: 'allNamespaces', refKey: 'extRefId', - sync: ['name'], + sync: ['name', 'description'], transformations: { // members: { // name: 'connectExclusiveList', diff --git a/src/controllers/v2/NamespaceController.ts b/src/controllers/v2/NamespaceController.ts index 8ef8254e6..184a80488 100644 --- a/src/controllers/v2/NamespaceController.ts +++ b/src/controllers/v2/NamespaceController.ts @@ -150,13 +150,13 @@ export class NamespaceController extends Controller { @Security('jwt', []) public async create( @Request() request: any, - @Query() namespace?: String, + @Query() name?: String, @Query() description?: String ): Promise { const result = await this.keystone.executeGraphQL({ context: this.keystone.createContext(request), query: createNS, - variables: { namespace, description }, + variables: { name, description }, }); logger.debug('Result %j', result); if (result.errors) { @@ -166,7 +166,10 @@ export class NamespaceController extends Controller { }); throw new ValidateError(errors, 'Unable to create namespace'); } - return { name: result.data.createNamespace.name }; + return { + name: result.data.createNamespace.name, + description: result.data.createNamespace.description, + }; } /** @@ -270,8 +273,8 @@ const deleteNS = gql` `; const createNS = gql` - mutation CreateNamespace($namespace: String, $description: String) { - createNamespace(namespace: $namespace, description: $description) { + mutation CreateNamespace($name: String, $description: String) { + createNamespace(name: $name, description: $description) { name description } diff --git a/src/controllers/v2/openapi.yaml b/src/controllers/v2/openapi.yaml index 3b09dac42..f2afcc520 100644 --- a/src/controllers/v2/openapi.yaml +++ b/src/controllers/v2/openapi.yaml @@ -422,6 +422,8 @@ components: $ref: '#/components/schemas/Maybe_Scalars-at-String_' scopes: $ref: '#/components/schemas/Maybe_Array_Maybe_UmaScope___' + description: + type: string name: type: string id: @@ -432,6 +434,7 @@ components: - Namespace nullable: false required: + - description - name type: object ActivityDetail: @@ -1204,7 +1207,13 @@ paths: parameters: - in: query - name: namespace + name: name + required: false + schema: + type: string + - + in: query + name: description required: false schema: type: string diff --git a/src/controllers/v2/routes.ts b/src/controllers/v2/routes.ts index 2e6c3236e..b00ef9b39 100644 --- a/src/controllers/v2/routes.ts +++ b/src/controllers/v2/routes.ts @@ -270,7 +270,7 @@ const models: TsoaRoute.Models = { // 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 "Namespace": { "dataType": "refAlias", - "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"orgAdmins":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"orgNoticeViewed":{"ref":"Maybe_Scalars-at-Boolean_"},"orgEnabled":{"ref":"Maybe_Scalars-at-Boolean_"},"orgUpdatedAt":{"ref":"Maybe_Scalars-at-Float_"},"orgUnit":{"ref":"Maybe_Scalars-at-JSON_"},"org":{"ref":"Maybe_Scalars-at-JSON_"},"permProtectedNs":{"ref":"Maybe_Scalars-at-String_"},"permDataPlane":{"ref":"Maybe_Scalars-at-String_"},"permDomains":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"prodEnvId":{"ref":"Maybe_Scalars-at-String_"},"scopes":{"ref":"Maybe_Array_Maybe_UmaScope___"},"name":{"dataType":"string","required":true},"id":{"ref":"Maybe_Scalars-at-String_"},"__typename":{"dataType":"enum","enums":["Namespace"]}},"validators":{}}, + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"orgAdmins":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"orgNoticeViewed":{"ref":"Maybe_Scalars-at-Boolean_"},"orgEnabled":{"ref":"Maybe_Scalars-at-Boolean_"},"orgUpdatedAt":{"ref":"Maybe_Scalars-at-Float_"},"orgUnit":{"ref":"Maybe_Scalars-at-JSON_"},"org":{"ref":"Maybe_Scalars-at-JSON_"},"permProtectedNs":{"ref":"Maybe_Scalars-at-String_"},"permDataPlane":{"ref":"Maybe_Scalars-at-String_"},"permDomains":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"prodEnvId":{"ref":"Maybe_Scalars-at-String_"},"scopes":{"ref":"Maybe_Array_Maybe_UmaScope___"},"description":{"dataType":"string","required":true},"name":{"dataType":"string","required":true},"id":{"ref":"Maybe_Scalars-at-String_"},"__typename":{"dataType":"enum","enums":["Namespace"]}},"validators":{}}, }, // 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 "ActivityDetail": { @@ -1068,7 +1068,8 @@ export function RegisterRoutes(app: express.Router) { 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"}, + name: {"in":"query","name":"name","dataType":"string"}, + description: {"in":"query","name":"description","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 diff --git a/src/controllers/v2/types.ts b/src/controllers/v2/types.ts index 2573e41d3..0eeff2211 100644 --- a/src/controllers/v2/types.ts +++ b/src/controllers/v2/types.ts @@ -134,6 +134,7 @@ export interface Alert { export interface Namespace { extRefId?: string; // Primary Key name?: string; + description?: string; } diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index 5a0ede0fb..00e98c7aa 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -63,7 +63,7 @@ const typeNamespace = ` type Namespace { id: String name: String!, - description: String!, + description: String, scopes: [UMAScope], prodEnvId: String, permDomains: [String], @@ -417,7 +417,8 @@ module.exports = { }, }, { - schema: 'createNamespace(name: String): Namespace', + schema: + 'createNamespace(name: String, description: String): Namespace', resolver: async ( item: any, args: any, diff --git a/src/nextapp/components/new-namespace/new-namespace.tsx b/src/nextapp/components/new-namespace/new-namespace.tsx index 9ed28b46b..bc376436a 100644 --- a/src/nextapp/components/new-namespace/new-namespace.tsx +++ b/src/nextapp/components/new-namespace/new-namespace.tsx @@ -133,7 +133,7 @@ export default NewNamespace; const mutation = gql` mutation CreateNamespace($name: String!) { - createNamespace(namespace: $name) { + createNamespace(name: $name) { id name } diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index 814e0a347..d2c52cfd1 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -5326,7 +5326,8 @@ export type MutationUpdateCurrentNamespaceArgs = { export type MutationCreateNamespaceArgs = { - namespace?: Maybe; + name?: Maybe; + description?: Maybe; }; @@ -5415,6 +5416,7 @@ export type Namespace = { __typename?: 'Namespace'; id?: Maybe; name: Scalars['String']; + description?: Maybe; scopes?: Maybe>>; prodEnvId?: Maybe; permDomains?: Maybe>>; diff --git a/src/services/keystone/types.ts b/src/services/keystone/types.ts index 814e0a347..d2c52cfd1 100644 --- a/src/services/keystone/types.ts +++ b/src/services/keystone/types.ts @@ -5326,7 +5326,8 @@ export type MutationUpdateCurrentNamespaceArgs = { export type MutationCreateNamespaceArgs = { - namespace?: Maybe; + name?: Maybe; + description?: Maybe; }; @@ -5415,6 +5416,7 @@ export type Namespace = { __typename?: 'Namespace'; id?: Maybe; name: Scalars['String']; + description?: Maybe; scopes?: Maybe>>; prodEnvId?: Maybe; permDomains?: Maybe>>; From 9de26a88f8bfd48c95172f775bb83f2b4adc18ab Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 17 Jul 2023 10:19:57 -0700 Subject: [PATCH 11/81] gwa-cli for namespace, login and config --- e2e/cypress/fixtures/test_data/gwa-cli.json | 12 ++ e2e/cypress/support/auth-commands.ts | 6 +- e2e/cypress/support/global.d.ts | 4 +- e2e/cypress/support/util-commands.ts | 6 + .../02-client-credential-flow/cli-demo.ts | 137 ++++++++++++++++++ 5 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 e2e/cypress/fixtures/test_data/gwa-cli.json create mode 100644 e2e/cypress/tests/02-client-credential-flow/cli-demo.ts diff --git a/e2e/cypress/fixtures/test_data/gwa-cli.json b/e2e/cypress/fixtures/test_data/gwa-cli.json new file mode 100644 index 000000000..10ffdc27c --- /dev/null +++ b/e2e/cypress/fixtures/test_data/gwa-cli.json @@ -0,0 +1,12 @@ +{ + "content": { + "help": "You can login via device login or by using client credentials\n\nTo use device login, simply run the command like so:\n $ gwa login\n\nTo use your credentials you must supply both a client-id and client-secret:\n $ gwa login --client-id --client-secret \n\nUsage:\n gwa login [flags]\n\nFlags:\n --client-id string Your gateway's client ID\n --client-secret string Your gateway's client secret\n -h, --help help for login\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --namespace string Assign the namespace you would like to use\n --scheme string Use to override default https", + "login_help": "Log in to your IDIR account\n\nUsage:\n gwa login [flags]\n\nFlags:\n --client-id string Your gateway's client ID\n --client-secret string Your gateway's client secret\n -h, --help help for login\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --scheme string Use to override default https", + "namespace_help" : "Longer explanation to come...\n\nUsage:\n gwa namespace [command]\n\nAvailable Commands:\n create Create a new namespace\n list List all your managed namespaces\n\nFlags:\n -h, --help help for namespace\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --namespace string Assign the namespace you would like to use\n --scheme string Use to override default https\n\nUse \"gwa namespace [command] --help\" for more information about a command.", + "config_help":"Configuration commands\n\nUsage:\n gwa config [command]\n\nAvailable Commands:\n set Write a specific global setting\n\nFlags:\n -h, --help help for config\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --namespace string Assign the namespace you would like to use\n --scheme string Use to override default https\n\nUse \"gwa config [command] --help\" for more information about a command." + }, + "credentials":{ + "clientID" :"gwa-api", + "clientSecret" :"18900468-3db1-43f7-a8af-e75f079eb742" + } +} diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts index 23f266765..48920a087 100644 --- a/e2e/cypress/support/auth-commands.ts +++ b/e2e/cypress/support/auth-commands.ts @@ -112,7 +112,7 @@ Cypress.Commands.add('resetCredential', (accessRole: string) => { }) }) -Cypress.Commands.add('getUserSessionTokenValue', (namespace: string) => { +Cypress.Commands.add('getUserSessionTokenValue', (namespace: string, isNamespaceSelected?:true) => { const login = new LoginPage() const home = new HomePage() const na = new NamespaceAccessPage() @@ -128,7 +128,9 @@ Cypress.Commands.add('getUserSessionTokenValue', (namespace: string) => { cy.login(user.credentials.username, user.credentials.password) cy.log('Logged in!') // home.useNamespace(apiTest.namespace) - home.useNamespace(namespace) + if(isNamespaceSelected){ + home.useNamespace(namespace) + } cy.get('@login').then(function (xhr: any) { userSession = xhr.response.headers['x-auth-request-access-token'] return userSession diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts index 53ece714d..ed1769008 100644 --- a/e2e/cypress/support/global.d.ts +++ b/e2e/cypress/support/global.d.ts @@ -61,7 +61,7 @@ declare namespace Cypress { compareJSONObjects(actualResponse: any, expectedResponse:any, indexFlag?: boolean) : Chainable> - getUserSessionTokenValue(namespace: string): Chainable> + getUserSessionTokenValue(namespace: string, isNamespaceSelected?:boolean): Chainable> getUserSessionResponse(): Chainable> @@ -89,5 +89,7 @@ declare namespace Cypress { updateKongPluginForJSONRequest(jsonBody: string, endPoint: string, verb?: string): Chainable> forceVisit (url:string): Chainable + + executeCliCommand (command: string) : Chainable } } diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts index ad61b4fb5..0dd525fad 100644 --- a/e2e/cypress/support/util-commands.ts +++ b/e2e/cypress/support/util-commands.ts @@ -113,4 +113,10 @@ Cypress.Commands.add('updateJsonValue', (jsonBody: any, jsonPath: string, newVal jsonpath.apply(jsonContent, jsonPath, () => newValue); updatedFileContent = JSON.stringify(jsonContent, null, 2); return updatedFileContent +}) + +Cypress.Commands.add('executeCliCommand', (command: string) => { + cy.exec(command, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + return response + }); }) \ No newline at end of file diff --git a/e2e/cypress/tests/02-client-credential-flow/cli-demo.ts b/e2e/cypress/tests/02-client-credential-flow/cli-demo.ts new file mode 100644 index 000000000..3c8ba7d5a --- /dev/null +++ b/e2e/cypress/tests/02-client-credential-flow/cli-demo.ts @@ -0,0 +1,137 @@ +import LoginPage from '../../pageObjects/login' +import ApplicationPage from '../../pageObjects/applications' +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import MyAccessPage from '../../pageObjects/myAccess' +const YAML = require('yamljs'); +let userSession: any +let cli = require("../../fixtures/test_data/gwa-cli.json") + +const jose = require('node-jose') + +describe('Verify CLI commands', () => { + const login = new LoginPage() + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const ma = new MyAccessPage() + let namespace : string + + before(() => { + // cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) + }) +}) + + it('Check for gwa help', () => { + cy.executeCliCommand('gwa help').then((response) => { + debugger + assert.equal(response.stdout, cli.content.help) + }); + }) + + it('Check gwa command for login help', () => { + cy.executeCliCommand('gwa login -h').then((response) => { + debugger + assert.equal(response.stdout, cli.content.login_help) + }); + }) + + it('Check gwa command to login with client ID and secret', () => { + let url = "oauth2proxy.localtest.me:4180" + let clientID = cli.credentials.clientID + let clientSecret = cli.credentials.clientSecret + cy.log('gwa login --host ${url} --scheme http') + cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http').then((response) => { + assert.equal(response.stdout, "Logged in") + }); + }) + + it('Check gwa command for login with invalid client id', () => { + let url = "oauth2proxy.localtest.me:4180" + let clientID = "dummy-client" + let clientSecret = cli.credentials.clientSecret + cy.exec('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stderr, "Error: INVALID_CREDENTIALS: Invalid client credentials") + }); + }) + + it('Check gwa command for login with invalid client secret', () => { + let url = "oauth2proxy.localtest.me:4180" + let clientID = cli.credentials.clientID + let clientSecret = "dummy-client-secret" + cy.exec('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stderr, "Error: Invalid client secret") + }); + }) + + it('Check gwa command for config help', () => { + cy.exec('gwa config -h', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + debugger + assert.equal(response.stdout, cli.content.config_help) + }); + }) + + it('Check gwa config command to set environment', () => { + cy.exec('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa config command to set token', () => { + cy.exec('gwa config set --token '+userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa command for namespace help', () => { + cy.exec('gwa namespace -h', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + debugger + assert.equal(response.stdout, cli.content.namespace_help) + }); + }) + + it('Check gwa command to create namespace', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host '+url+' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + }); + }) + + it('Check gwa namespace list command and verify the created namespace in the list', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace list --host '+url+' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + expect(response.stdout).to.contain(namespace); + }); + }) + + it('Check Env Variable', () => { + // let variable = "BC Government" + // cy.exec('yq ".api_key=\"$variable\"" ~/.gwa-config.yaml',{ timeout: 3000, failOnNonZeroExit: false }).then((response) => { + // const output = response.stdout; + // cy.log('Command output:', output); + // // Perform assertions or other actions with the output + // }); + cy.readFile('/Users/nirajpatel/.gwa-config.yaml').then((content: any) => { + debugger + let obj = YAML.parse(content) + const keys = Object.keys(obj); + obj.api_key = "Test1234" + const yamlString = YAML.stringify(obj, 'utf8'); + cy.writeFile('/Users/nirajpatel/.gwa-config.yaml', yamlString) + }) + }) +}) \ No newline at end of file From 4a4eac5855a3beb85803a734d7ea92acdd2426ea Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Mon, 17 Jul 2023 14:15:40 -0700 Subject: [PATCH 12/81] upg http-proxy --- src/package-lock.json | 199 +++++++++++++++++++++++++++--------------- src/package.json | 2 +- 2 files changed, 131 insertions(+), 70 deletions(-) diff --git a/src/package-lock.json b/src/package-lock.json index bd8cafbc2..3e70e7aa5 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -50,7 +50,7 @@ "graphql": "^15.4.0", "graphql-request": "^3.4.0", "graphql-tools": "^7.0.2", - "http-proxy-middleware": "^1.1.2", + "http-proxy-middleware": "^2.0.6", "isomorphic-unfetch": "^3.1.0", "js-yaml": "^4.1.0", "json-stable-stringify": "^1.0.2", @@ -15831,9 +15831,9 @@ "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==" }, "node_modules/@types/http-proxy": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.5.tgz", - "integrity": "sha512-GNkDE7bTv6Sf8JbV2GksknKOsk7OznNYHSdrtvPJXO0qJ9odZig6IZKUi5RFGi6d1bf6dgIAe4uXi3DBc7069Q==", + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", "dependencies": { "@types/node": "*" } @@ -28528,18 +28528,26 @@ } }, "node_modules/http-proxy-middleware": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.1.2.tgz", - "integrity": "sha512-YRFUeOG3q85FJjAaYVJUoNRW9a73SDlOtAyQOS5PHLr18QeZ/vEhxywNoOPiEO8BxCegz4RXzTHcvyLEGB78UA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", "dependencies": { - "@types/http-proxy": "^1.17.5", + "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", "is-glob": "^4.0.1", "is-plain-obj": "^3.0.0", "micromatch": "^4.0.2" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } } }, "node_modules/http2-wrapper": { @@ -49255,7 +49263,8 @@ "@apollographql/apollo-tools": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.3.tgz", - "integrity": "sha512-VcsXHfTFoCodDAgJZxN04GdFK1kqOhZQnQY/9Fa147P+I8xfvOSz5d+lKAPB+hwSgBNyd7ncAKGIs4+utbL+yA==" + "integrity": "sha512-VcsXHfTFoCodDAgJZxN04GdFK1kqOhZQnQY/9Fa147P+I8xfvOSz5d+lKAPB+hwSgBNyd7ncAKGIs4+utbL+yA==", + "requires": {} }, "@apollographql/graphql-playground-html": { "version": "1.6.29", @@ -51676,7 +51685,8 @@ "@chakra-ui/css-reset": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-1.0.0.tgz", - "integrity": "sha512-UaPsImGHvCgFO3ayp6Ugafu2/3/EG8wlW/8Y9Ihfk1UFv8cpV+3BfWKmuZ7IcmxcBL9dkP6E8p3/M1T0FB92hg==" + "integrity": "sha512-UaPsImGHvCgFO3ayp6Ugafu2/3/EG8wlW/8Y9Ihfk1UFv8cpV+3BfWKmuZ7IcmxcBL9dkP6E8p3/M1T0FB92hg==", + "requires": {} }, "@chakra-ui/descendant": { "version": "2.0.0", @@ -53410,7 +53420,8 @@ "@graphql-typed-document-node/core": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.0.tgz", - "integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==" + "integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==", + "requires": {} }, "@hapi/accept": { "version": "5.0.1", @@ -57575,7 +57586,8 @@ "slate-react-placeholder": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/slate-react-placeholder/-/slate-react-placeholder-0.2.9.tgz", - "integrity": "sha512-YSJ9Gb4tGpbzPje3eNKtu26hWM8ApxTk9RzjK+6zfD5V/RMTkuWONk24y6c9lZk0OAYNZNUmrnb/QZfU3j9nag==" + "integrity": "sha512-YSJ9Gb4tGpbzPje3eNKtu26hWM8ApxTk9RzjK+6zfD5V/RMTkuWONk24y6c9lZk0OAYNZNUmrnb/QZfU3j9nag==", + "requires": {} } } }, @@ -57655,7 +57667,8 @@ "react-codemirror2": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-7.2.1.tgz", - "integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==" + "integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==", + "requires": {} } } }, @@ -58302,7 +58315,8 @@ "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "dev": true + "dev": true, + "requires": {} }, "@mdx-js/util": { "version": "1.6.22", @@ -58358,7 +58372,8 @@ "@n1ru4l/graphql-live-query": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@n1ru4l/graphql-live-query/-/graphql-live-query-0.9.0.tgz", - "integrity": "sha512-BTpWy1e+FxN82RnLz4x1+JcEewVdfmUhV1C6/XYD5AjS7PQp9QFF7K8bCD6gzPTr2l+prvqOyVueQhFJxB1vfg==" + "integrity": "sha512-BTpWy1e+FxN82RnLz4x1+JcEewVdfmUhV1C6/XYD5AjS7PQp9QFF7K8bCD6gzPTr2l+prvqOyVueQhFJxB1vfg==", + "requires": {} }, "@next/env": { "version": "9.5.5", @@ -58546,7 +58561,8 @@ "@primer/octicons-react": { "version": "11.3.0", "resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-11.3.0.tgz", - "integrity": "sha512-4sVhkrBKuj3h+PFw69yOyO/l3nQB/mm95V+Kz7LRSlIrbZr6hZarZD5Ft4ewdONPROkIHQM/6KSK90+OAimxsQ==" + "integrity": "sha512-4sVhkrBKuj3h+PFw69yOyO/l3nQB/mm95V+Kz7LRSlIrbZr6hZarZD5Ft4ewdONPROkIHQM/6KSK90+OAimxsQ==", + "requires": {} }, "@prisma/bar": { "version": "0.0.1", @@ -59851,7 +59867,8 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -60202,7 +60219,8 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -61128,9 +61146,9 @@ "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==" }, "@types/http-proxy": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.5.tgz", - "integrity": "sha512-GNkDE7bTv6Sf8JbV2GksknKOsk7OznNYHSdrtvPJXO0qJ9odZig6IZKUi5RFGi6d1bf6dgIAe4uXi3DBc7069Q==", + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", "requires": { "@types/node": "*" } @@ -62358,7 +62376,8 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "requires": {} }, "acorn-node": { "version": "1.8.2", @@ -62479,12 +62498,14 @@ "ajv-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "requires": {} }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} }, "ally.js": { "version": "1.4.1", @@ -62782,7 +62803,8 @@ "apollo-server-errors": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.5.0.tgz", - "integrity": "sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA==" + "integrity": "sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA==", + "requires": {} }, "apollo-server-express": { "version": "2.25.3", @@ -63660,7 +63682,8 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.7.tgz", "integrity": "sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw==", - "dev": true + "dev": true, + "requires": {} }, "babel-plugin-polyfill-corejs2": { "version": "0.3.1", @@ -66072,7 +66095,8 @@ "create-react-context": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.1.6.tgz", - "integrity": "sha512-eCnYYEUEc5i32LHwpE/W7NlddOB9oHwsPaWtWzYtflNkkwa3IfindIcoXdVWs12zCbwaMCavKNu84EXogVIWHw==" + "integrity": "sha512-eCnYYEUEc5i32LHwpE/W7NlddOB9oHwsPaWtWzYtflNkkwa3IfindIcoXdVWs12zCbwaMCavKNu84EXogVIWHw==", + "requires": {} }, "create-require": { "version": "1.1.1", @@ -66235,7 +66259,8 @@ "icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "requires": {} }, "lru-cache": { "version": "7.8.0", @@ -66255,7 +66280,8 @@ "postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -67877,7 +67903,8 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz", "integrity": "sha512-9sm5/PxaFG7qNJvJzTROMM1Bk1ozXVTKI0buKOyb0Bsr1hrwi0H/TzxF/COtf1uxikIK8SwhX7K6zg78jAzbeA==", - "dev": true + "dev": true, + "requires": {} }, "eslint-plugin-jest": { "version": "24.1.3", @@ -67942,7 +67969,8 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", - "dev": true + "dev": true, + "requires": {} }, "eslint-scope": { "version": "5.1.1", @@ -70061,7 +70089,8 @@ "graphql-executor": { "version": "0.0.22", "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.22.tgz", - "integrity": "sha512-WbKSnSHFn6REKKH4T6UAwDM3mLUnYMQlQLNG0Fw+Lkb3ilCnL3m5lkJ7411LAI9sF7BvPbthovVZhsEUh9Xfag==" + "integrity": "sha512-WbKSnSHFn6REKKH4T6UAwDM3mLUnYMQlQLNG0Fw+Lkb3ilCnL3m5lkJ7411LAI9sF7BvPbthovVZhsEUh9Xfag==", + "requires": {} }, "graphql-extensions": { "version": "0.15.0", @@ -70192,7 +70221,8 @@ "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} } } }, @@ -70272,7 +70302,8 @@ "graphql-ws": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.7.0.tgz", - "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==" + "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==", + "requires": {} }, "minimatch": { "version": "4.2.1", @@ -70444,7 +70475,8 @@ "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} } } }, @@ -70524,7 +70556,8 @@ "graphql-ws": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.7.0.tgz", - "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==" + "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==", + "requires": {} }, "minimatch": { "version": "4.2.1", @@ -70607,7 +70640,8 @@ "graphql-sse": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/graphql-sse/-/graphql-sse-1.1.0.tgz", - "integrity": "sha512-xE8AGPJa5X+g7iFmRQw/8H+7lXIDJvSkW6lou/XSSq17opPQl+dbKOMiqraHMx52VrDgS061ZVx90OSuqS6ykA==" + "integrity": "sha512-xE8AGPJa5X+g7iFmRQw/8H+7lXIDJvSkW6lou/XSSq17opPQl+dbKOMiqraHMx52VrDgS061ZVx90OSuqS6ykA==", + "requires": {} }, "graphql-subscriptions": { "version": "1.1.0", @@ -70668,7 +70702,8 @@ "graphql-type-json": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.2.tgz", - "integrity": "sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==" + "integrity": "sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==", + "requires": {} }, "graphql-upload": { "version": "11.0.0", @@ -70692,7 +70727,8 @@ "graphql-ws": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-4.9.0.tgz", - "integrity": "sha512-sHkK9+lUm20/BGawNEWNtVAeJzhZeBg21VmvmLoT5NdGVeZWv5PdIhkcayQIAgjSyyQ17WMKmbDijIPG2On+Ag==" + "integrity": "sha512-sHkK9+lUm20/BGawNEWNtVAeJzhZeBg21VmvmLoT5NdGVeZWv5PdIhkcayQIAgjSyyQ17WMKmbDijIPG2On+Ag==", + "requires": {} }, "gray-percentage": { "version": "2.0.0", @@ -71295,11 +71331,11 @@ } }, "http-proxy-middleware": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.1.2.tgz", - "integrity": "sha512-YRFUeOG3q85FJjAaYVJUoNRW9a73SDlOtAyQOS5PHLr18QeZ/vEhxywNoOPiEO8BxCegz4RXzTHcvyLEGB78UA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", "requires": { - "@types/http-proxy": "^1.17.5", + "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", "is-glob": "^4.0.1", "is-plain-obj": "^3.0.0", @@ -72202,7 +72238,8 @@ "isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==" + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "requires": {} }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -73616,7 +73653,8 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true + "dev": true, + "requires": {} }, "jest-regex-util": { "version": "26.0.0", @@ -74800,7 +74838,8 @@ "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -76025,7 +76064,8 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz", "integrity": "sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w==", - "dev": true + "dev": true, + "requires": {} }, "match-sorter": { "version": "6.1.0", @@ -76334,7 +76374,8 @@ "meros": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/meros/-/meros-1.1.4.tgz", - "integrity": "sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ==" + "integrity": "sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ==", + "requires": {} }, "mersenne-twister": { "version": "1.1.0", @@ -76762,7 +76803,8 @@ "mongoose-legacy-pluralize": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "requires": {} }, "move-concurrently": { "version": "1.0.1", @@ -77338,7 +77380,8 @@ "@next/react-refresh-utils": { "version": "9.5.5", "resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-9.5.5.tgz", - "integrity": "sha512-Gz5z0+ID+KAGto6Tkgv1a340damEw3HG6ANLKwNi5/QSHqQ3JUAVxMuhz3qnL54505I777evpzL89ofWEMIWKw==" + "integrity": "sha512-Gz5z0+ID+KAGto6Tkgv1a340damEw3HG6ANLKwNi5/QSHqQ3JUAVxMuhz3qnL54505I777evpzL89ofWEMIWKw==", + "requires": {} }, "acorn": { "version": "6.4.2", @@ -79693,7 +79736,8 @@ "pg-pool": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", - "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==" + "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", + "requires": {} }, "pg-protocol": { "version": "1.5.0", @@ -80583,7 +80627,8 @@ "version": "5.5.1", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz", "integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==", - "dev": true + "dev": true, + "requires": {} }, "react-copy-to-clipboard": { "version": "5.0.4", @@ -80597,7 +80642,8 @@ "react-day-picker": { "version": "8.0.0-beta.3", "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.0.0-beta.3.tgz", - "integrity": "sha512-qvasG5iH6M+Ix3HAtCiSum6xbngG5re5F2bZN3VRof7FAl3LJbNcq+5geEITSLRt5uo3IsXF5eFvG6Ggpzw8og==" + "integrity": "sha512-qvasG5iH6M+Ix3HAtCiSum6xbngG5re5F2bZN3VRof7FAl3LJbNcq+5geEITSLRt5uo3IsXF5eFvG6Ggpzw8og==", + "requires": {} }, "react-display-name": { "version": "0.2.5", @@ -80729,12 +80775,14 @@ "react-icons": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz", - "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==" + "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==", + "requires": {} }, "react-image": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/react-image/-/react-image-4.0.3.tgz", - "integrity": "sha512-19MUK9u1qaw9xys8XEsVkSpVhHctEBUeYFvrLTe1PN+4w5Co13AN2WA7xtBshPM6SthsOj77SlDrEAeOaJpf7g==" + "integrity": "sha512-19MUK9u1qaw9xys8XEsVkSpVhHctEBUeYFvrLTe1PN+4w5Co13AN2WA7xtBshPM6SthsOj77SlDrEAeOaJpf7g==", + "requires": {} }, "react-immutable-proptypes": { "version": "2.2.0", @@ -80766,7 +80814,8 @@ "react-intersection-observer": { "version": "8.31.0", "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.31.0.tgz", - "integrity": "sha512-XraIC/tkrD9JtrmVA7ypEN1QIpKc52mXBH1u/bz/aicRLo8QQEJQAMUTb8mz4B6dqpPwyzgjrr7Ljv/2ACDtqw==" + "integrity": "sha512-XraIC/tkrD9JtrmVA7ypEN1QIpKc52mXBH1u/bz/aicRLo8QQEJQAMUTb8mz4B6dqpPwyzgjrr7Ljv/2ACDtqw==", + "requires": {} }, "react-is": { "version": "17.0.2", @@ -80852,12 +80901,14 @@ "react-prop-toggle": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/react-prop-toggle/-/react-prop-toggle-1.0.2.tgz", - "integrity": "sha512-JmerjAXs7qJ959+d0Ygt7Cb2+4fG+n3I2VXO6JO0AcAY1vkRN/JpZKAN67CMXY889xEJcfylmMPhzvf6nWO68Q==" + "integrity": "sha512-JmerjAXs7qJ959+d0Ygt7Cb2+4fG+n3I2VXO6JO0AcAY1vkRN/JpZKAN67CMXY889xEJcfylmMPhzvf6nWO68Q==", + "requires": {} }, "react-pseudo-state": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/react-pseudo-state/-/react-pseudo-state-2.2.2.tgz", - "integrity": "sha512-czJNP0MpcqJISnFwxYz8IlJklsUbWyuSqWJWLbXi/MUQWIEu2t6PbOGHIVvtpw9i0N3hHZ50nSNCDMLp4fpenQ==" + "integrity": "sha512-czJNP0MpcqJISnFwxYz8IlJklsUbWyuSqWJWLbXi/MUQWIEu2t6PbOGHIVvtpw9i0N3hHZ50nSNCDMLp4fpenQ==", + "requires": {} }, "react-query": { "version": "3.5.11", @@ -81423,7 +81474,8 @@ "redux-immutable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz", - "integrity": "sha1-Ohoy32Y2ZGK2NpHw4dw15HK7yfM= sha512-SchSn/DWfGb3oAejd+1hhHx01xUoxY+V7TeK0BKqpkLKiQPVFf7DYzEaKmrEVxsWxielKfSK9/Xq66YyxgR1cg==" + "integrity": "sha1-Ohoy32Y2ZGK2NpHw4dw15HK7yfM= sha512-SchSn/DWfGb3oAejd+1hhHx01xUoxY+V7TeK0BKqpkLKiQPVFf7DYzEaKmrEVxsWxielKfSK9/Xq66YyxgR1cg==", + "requires": {} }, "redux-localstorage": { "version": "1.0.0-rc5", @@ -83077,12 +83129,14 @@ "slate-plain-serializer": { "version": "0.7.13", "resolved": "https://registry.npmjs.org/slate-plain-serializer/-/slate-plain-serializer-0.7.13.tgz", - "integrity": "sha512-TtrlaslxQBEMV0LYdf3s7VAbTxRPe1xaW10WNNGAzGA855/0RhkaHjKkQiRjHv5rvbRleVf7Nxr9fH+4uErfxQ==" + "integrity": "sha512-TtrlaslxQBEMV0LYdf3s7VAbTxRPe1xaW10WNNGAzGA855/0RhkaHjKkQiRjHv5rvbRleVf7Nxr9fH+4uErfxQ==", + "requires": {} }, "slate-prop-types": { "version": "0.5.44", "resolved": "https://registry.npmjs.org/slate-prop-types/-/slate-prop-types-0.5.44.tgz", - "integrity": "sha512-JS0iW7uaciE/W3ADuzeN1HOnSjncQhHPXJ65nZNQzB0DF7mXVmbwQKI6cmCo/xKni7XRJT0JbWSpXFhEdPiBUA==" + "integrity": "sha512-JS0iW7uaciE/W3ADuzeN1HOnSjncQhHPXJ65nZNQzB0DF7mXVmbwQKI6cmCo/xKni7XRJT0JbWSpXFhEdPiBUA==", + "requires": {} }, "slice-ansi": { "version": "3.0.0", @@ -83940,7 +83994,8 @@ "stylis-rule-sheet": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", - "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", + "requires": {} } } }, @@ -84005,7 +84060,8 @@ "stylis-rule-sheet": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", - "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", + "requires": {} } } }, @@ -85724,19 +85780,22 @@ "use-callback-ref": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.4.tgz", - "integrity": "sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ==" + "integrity": "sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ==", + "requires": {} }, "use-composed-ref": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz", "integrity": "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==", - "dev": true + "dev": true, + "requires": {} }, "use-isomorphic-layout-effect": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", - "dev": true + "dev": true, + "requires": {} }, "use-latest": { "version": "1.2.0", @@ -86715,7 +86774,8 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz", "integrity": "sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg==", - "dev": true + "dev": true, + "requires": {} }, "webpack-hot-middleware": { "version": "2.25.1", @@ -86974,7 +87034,8 @@ "ws": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", - "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==" + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "requires": {} }, "xdg-basedir": { "version": "4.0.0", diff --git a/src/package.json b/src/package.json index a27c830bb..c71395fa5 100644 --- a/src/package.json +++ b/src/package.json @@ -96,7 +96,7 @@ "graphql": "^15.4.0", "graphql-request": "^3.4.0", "graphql-tools": "^7.0.2", - "http-proxy-middleware": "^1.1.2", + "http-proxy-middleware": "^2.0.6", "isomorphic-unfetch": "^3.1.0", "json-stable-stringify": "^1.0.2", "js-yaml": "^4.1.0", From b54d82a25940db9eddd193a4d9956450ab40ab63 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Mon, 17 Jul 2023 14:48:03 -0700 Subject: [PATCH 13/81] move around proxy --- src/api-proxy.js | 52 +++++++++++++++++++++++++++--------------------- src/server.ts | 4 ++-- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/api-proxy.js b/src/api-proxy.js index 3c7d89558..8540c1521 100644 --- a/src/api-proxy.js +++ b/src/api-proxy.js @@ -1,4 +1,3 @@ - const express = require('express'); const pathModule = require('path'); @@ -11,31 +10,38 @@ class ApiProxyApp { prepareMiddleware({ keystone }) { const app = express(); - - const apiProxy = createProxyMiddleware({ - target: this._gwaApiUrl, - changeOrigin: true, - pathRewrite: { '^/gw/api/': '/v2/' }, - onProxyReq: (proxyReq, req) => { - // console.log(req.headers) - // proxyReq.removeHeader("cookie"); - proxyReq.removeHeader("cookie"); - proxyReq.setHeader('Accept', 'application/json') - proxyReq.setHeader('Authorization', `Bearer ${req.header('x-forwarded-access-token')}`) }, - onError:(err, req, res, target) => { - console.log(err) - res.writeHead(400, { - 'Content-Type': 'text/plain', - }); - res.end('error reaching api'); - } - }) - app.all(/^\/gw\/api\//, apiProxy) + + const apiProxy = createProxyMiddleware({ + target: this._gwaApiUrl, + changeOrigin: true, + logLevel: 'debug', + pathRewrite: { '^/gw/api/': '/v2/' }, + onProxyReq: (proxyReq, req) => { + //console.log(req.headers) + // proxyReq.removeHeader("cookie"); + proxyReq.removeHeader('cookie'); + proxyReq.setHeader('Accept', 'application/json'); + proxyReq.setHeader( + 'Authorization', + 'authorization' in req.headers + ? req.header('authorization') + : `Bearer ${req.header('x-forwarded-access-token')}` + ); + }, + onError: (err, req, res, target) => { + console.log(err); + res.writeHead(400, { + 'Content-Type': 'text/plain', + }); + res.end('error reaching api'); + }, + }); + app.all(/^\/gw\/api\//, apiProxy); return app; } } module.exports = { - ApiProxyApp, -}; \ No newline at end of file + ApiProxyApp, +}; diff --git a/src/server.ts b/src/server.ts index fa44b6009..5ad25937c 100644 --- a/src/server.ts +++ b/src/server.ts @@ -242,6 +242,8 @@ const apps = [ new ApiHealthApp(state), new ApiOpenapiApp(), new MaintenanceApp(), + new ApiDSProxyApp({ url: process.env.SSR_API_ROOT }), + new ApiProxyApp({ gwaApiUrl: process.env.GWA_API_URL }), new ApiGraphqlWhitelistApp({ apiPath, apollo: { @@ -270,8 +272,6 @@ const apps = [ pages: pages, enableDefaultRoute: false, }), - new ApiDSProxyApp({ url: process.env.SSR_API_ROOT }), - new ApiProxyApp({ gwaApiUrl: process.env.GWA_API_URL }), new NextApp({ dir: 'nextapp' }), ]; From e804de973ccaa70b5fab0580a858d3e43042d323 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Tue, 18 Jul 2023 11:19:02 -0700 Subject: [PATCH 14/81] Update oauth2-proxy config --- local/oauth2-proxy/oauth2-proxy-local.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local/oauth2-proxy/oauth2-proxy-local.cfg b/local/oauth2-proxy/oauth2-proxy-local.cfg index 749890067..2c7281267 100644 --- a/local/oauth2-proxy/oauth2-proxy-local.cfg +++ b/local/oauth2-proxy/oauth2-proxy-local.cfg @@ -21,7 +21,7 @@ set_xauthrequest="true" skip_jwt_bearer_tokens="false" set_authorization_header="false" pass_authorization_header="false" -skip_auth_regex="/login|/health|/public|/docs|/redirect|/_next|/images|/devportal|/manager|/about|/maintenance|/admin/session|/ds/api|/feed/|/signout|^[/]$" +skip_auth_regex="/login|/health|/public|/docs|/redirect|/_next|/images|/devportal|/manager|/about|/maintenance|/admin/session|/ds/api|/gw/api|/feed/|/signout|^[/]$" whitelist_domains="keycloak.localtest.me:9080" upstreams=["http://apsportal.localtest.me:3000"] skip_provider_button='true' From 03d70279fafe15344cc3d068b799a0759f78e690 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Wed, 19 Jul 2023 15:50:30 -0700 Subject: [PATCH 15/81] use displayName for namespace --- .../httplocalhost4180managernamespaces-85071c.gql | 7 +++++++ src/batch/data-rules.js | 2 +- src/controllers/v2/NamespaceController.ts | 14 +++++++------- src/controllers/v2/openapi.yaml | 7 +++---- src/controllers/v2/routes.ts | 4 ++-- src/controllers/v2/types.ts | 2 +- src/lists/extensions/Namespace.ts | 12 ++++-------- src/nextapp/shared/types/query.types.ts | 4 ++-- src/services/keycloak/namespace-details.ts | 1 + src/services/keystone/types.ts | 4 ++-- src/services/org-groups/namespace.ts | 10 ---------- src/services/report/data/namespaces.ts | 3 +-- src/services/report/output/structure.ts | 5 +++++ src/services/uma2/resource-registration-service.ts | 3 +++ src/services/workflow/get-namespaces.ts | 2 ++ src/test/integrated/uma2/resource.ts | 11 +++++++---- 16 files changed, 48 insertions(+), 43 deletions(-) create mode 100644 src/authz/graphql-whitelist/httplocalhost4180managernamespaces-85071c.gql diff --git a/src/authz/graphql-whitelist/httplocalhost4180managernamespaces-85071c.gql b/src/authz/graphql-whitelist/httplocalhost4180managernamespaces-85071c.gql new file mode 100644 index 000000000..5fdb60eee --- /dev/null +++ b/src/authz/graphql-whitelist/httplocalhost4180managernamespaces-85071c.gql @@ -0,0 +1,7 @@ + + mutation CreateNamespace($name: String!) { + createNamespace(name: $name) { + id + name + } + } diff --git a/src/batch/data-rules.js b/src/batch/data-rules.js index f541d7b83..a34147ce3 100644 --- a/src/batch/data-rules.js +++ b/src/batch/data-rules.js @@ -198,7 +198,7 @@ const metadata = { Namespace: { query: 'allNamespaces', refKey: 'extRefId', - sync: ['name', 'description'], + sync: ['name', 'displayName'], transformations: { // members: { // name: 'connectExclusiveList', diff --git a/src/controllers/v2/NamespaceController.ts b/src/controllers/v2/NamespaceController.ts index 184a80488..9edc61cf5 100644 --- a/src/controllers/v2/NamespaceController.ts +++ b/src/controllers/v2/NamespaceController.ts @@ -151,12 +151,12 @@ export class NamespaceController extends Controller { public async create( @Request() request: any, @Query() name?: String, - @Query() description?: String + @Query() displayName?: String ): Promise { const result = await this.keystone.executeGraphQL({ context: this.keystone.createContext(request), query: createNS, - variables: { name, description }, + variables: { name, displayName }, }); logger.debug('Result %j', result); if (result.errors) { @@ -168,7 +168,7 @@ export class NamespaceController extends Controller { } return { name: result.data.createNamespace.name, - description: result.data.createNamespace.description, + displayName: result.data.createNamespace.displayName, }; } @@ -250,7 +250,7 @@ const item = gql` query Namespace($ns: String!) { namespace(ns: $ns) { name - description + displayName scopes { name } @@ -273,10 +273,10 @@ const deleteNS = gql` `; const createNS = gql` - mutation CreateNamespace($name: String, $description: String) { - createNamespace(name: $name, description: $description) { + mutation CreateNamespace($name: String, $displayName: String) { + createNamespace(name: $name, displayName: $displayName) { name - description + displayName } } `; diff --git a/src/controllers/v2/openapi.yaml b/src/controllers/v2/openapi.yaml index f2afcc520..8681f5b90 100644 --- a/src/controllers/v2/openapi.yaml +++ b/src/controllers/v2/openapi.yaml @@ -422,8 +422,8 @@ components: $ref: '#/components/schemas/Maybe_Scalars-at-String_' scopes: $ref: '#/components/schemas/Maybe_Array_Maybe_UmaScope___' - description: - type: string + displayName: + $ref: '#/components/schemas/Maybe_Scalars-at-String_' name: type: string id: @@ -434,7 +434,6 @@ components: - Namespace nullable: false required: - - description - name type: object ActivityDetail: @@ -1213,7 +1212,7 @@ paths: type: string - in: query - name: description + name: displayName required: false schema: type: string diff --git a/src/controllers/v2/routes.ts b/src/controllers/v2/routes.ts index b00ef9b39..003794580 100644 --- a/src/controllers/v2/routes.ts +++ b/src/controllers/v2/routes.ts @@ -270,7 +270,7 @@ const models: TsoaRoute.Models = { // 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 "Namespace": { "dataType": "refAlias", - "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"orgAdmins":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"orgNoticeViewed":{"ref":"Maybe_Scalars-at-Boolean_"},"orgEnabled":{"ref":"Maybe_Scalars-at-Boolean_"},"orgUpdatedAt":{"ref":"Maybe_Scalars-at-Float_"},"orgUnit":{"ref":"Maybe_Scalars-at-JSON_"},"org":{"ref":"Maybe_Scalars-at-JSON_"},"permProtectedNs":{"ref":"Maybe_Scalars-at-String_"},"permDataPlane":{"ref":"Maybe_Scalars-at-String_"},"permDomains":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"prodEnvId":{"ref":"Maybe_Scalars-at-String_"},"scopes":{"ref":"Maybe_Array_Maybe_UmaScope___"},"description":{"dataType":"string","required":true},"name":{"dataType":"string","required":true},"id":{"ref":"Maybe_Scalars-at-String_"},"__typename":{"dataType":"enum","enums":["Namespace"]}},"validators":{}}, + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"orgAdmins":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"orgNoticeViewed":{"ref":"Maybe_Scalars-at-Boolean_"},"orgEnabled":{"ref":"Maybe_Scalars-at-Boolean_"},"orgUpdatedAt":{"ref":"Maybe_Scalars-at-Float_"},"orgUnit":{"ref":"Maybe_Scalars-at-JSON_"},"org":{"ref":"Maybe_Scalars-at-JSON_"},"permProtectedNs":{"ref":"Maybe_Scalars-at-String_"},"permDataPlane":{"ref":"Maybe_Scalars-at-String_"},"permDomains":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"prodEnvId":{"ref":"Maybe_Scalars-at-String_"},"scopes":{"ref":"Maybe_Array_Maybe_UmaScope___"},"displayName":{"ref":"Maybe_Scalars-at-String_"},"name":{"dataType":"string","required":true},"id":{"ref":"Maybe_Scalars-at-String_"},"__typename":{"dataType":"enum","enums":["Namespace"]}},"validators":{}}, }, // 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 "ActivityDetail": { @@ -1069,7 +1069,7 @@ export function RegisterRoutes(app: express.Router) { const args = { request: {"in":"request","name":"request","required":true,"dataType":"object"}, name: {"in":"query","name":"name","dataType":"string"}, - description: {"in":"query","name":"description","dataType":"string"}, + displayName: {"in":"query","name":"displayName","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 diff --git a/src/controllers/v2/types.ts b/src/controllers/v2/types.ts index 0eeff2211..366bbdbfb 100644 --- a/src/controllers/v2/types.ts +++ b/src/controllers/v2/types.ts @@ -134,7 +134,7 @@ export interface Alert { export interface Namespace { extRefId?: string; // Primary Key name?: string; - description?: string; + displayName?: string; } diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index 00e98c7aa..dfb9752dd 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -63,7 +63,7 @@ const typeNamespace = ` type Namespace { id: String name: String!, - description: String, + displayName: String, scopes: [UMAScope], prodEnvId: String, permDomains: [String], @@ -418,7 +418,7 @@ module.exports = { }, { schema: - 'createNamespace(name: String, description: String): Namespace', + 'createNamespace(name: String, displayName: String): Namespace', resolver: async ( item: any, args: any, @@ -426,8 +426,7 @@ module.exports = { info: any, { query, access }: any ) => { - const namespaceValidationRule = - '(([A-Za-z0-9][-A-Za-z0-9]*)?[A-Za-z0-9])?'; + const namespaceValidationRule = '^[a-z][a-z0-9-]{4,14}$'; const newNS = args.name ? args.name : newNamespaceID(); @@ -478,6 +477,7 @@ module.exports = { ]; const res = { name: newNS, + displayName: args.displayName, type: 'namespace', resource_scopes: scopes, ownerManagedAccess: true, @@ -508,10 +508,6 @@ module.exports = { await kcGroupService.createIfMissing('ns', newNS); - if (args.description) { - await nsService.updateDescription(newNS, args.description); - } - await recordActivity( context.sudo(), 'create', diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index d2c52cfd1..bf5519e95 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -5327,7 +5327,7 @@ export type MutationUpdateCurrentNamespaceArgs = { export type MutationCreateNamespaceArgs = { name?: Maybe; - description?: Maybe; + displayName?: Maybe; }; @@ -5416,7 +5416,7 @@ export type Namespace = { __typename?: 'Namespace'; id?: Maybe; name: Scalars['String']; - description?: Maybe; + displayName?: Maybe; scopes?: Maybe>>; prodEnvId?: Maybe; permDomains?: Maybe>>; diff --git a/src/services/keycloak/namespace-details.ts b/src/services/keycloak/namespace-details.ts index 171f3afeb..ece22c7f2 100644 --- a/src/services/keycloak/namespace-details.ts +++ b/src/services/keycloak/namespace-details.ts @@ -162,6 +162,7 @@ export async function getResource( .map((ns: ResourceSet) => ({ id: ns.id, name: ns.name, + displayName: ns.displayName, scopes: ns.resource_scopes, })) .pop(); diff --git a/src/services/keystone/types.ts b/src/services/keystone/types.ts index d2c52cfd1..bf5519e95 100644 --- a/src/services/keystone/types.ts +++ b/src/services/keystone/types.ts @@ -5327,7 +5327,7 @@ export type MutationUpdateCurrentNamespaceArgs = { export type MutationCreateNamespaceArgs = { name?: Maybe; - description?: Maybe; + displayName?: Maybe; }; @@ -5416,7 +5416,7 @@ export type Namespace = { __typename?: 'Namespace'; id?: Maybe; name: Scalars['String']; - description?: Maybe; + displayName?: Maybe; scopes?: Maybe>>; prodEnvId?: Maybe; permDomains?: Maybe>>; diff --git a/src/services/org-groups/namespace.ts b/src/services/org-groups/namespace.ts index 960a70823..958eb93c2 100644 --- a/src/services/org-groups/namespace.ts +++ b/src/services/org-groups/namespace.ts @@ -26,16 +26,6 @@ export class NamespaceService { await this.groupService.updateGroup(group); } - async updateDescription(ns: string, description: string): Promise { - const group = await this.groupService.getGroup('ns', ns); - - group.attributes['description'] = [description]; - - logger.debug('[updateDescription] %s - %s', ns, description); - - await this.groupService.updateGroup(group); - } - /* Update the Group attributes for org and org-unit */ diff --git a/src/services/report/data/namespaces.ts b/src/services/report/data/namespaces.ts index 7fd0184ac..ab0e9b1fa 100644 --- a/src/services/report/data/namespaces.ts +++ b/src/services/report/data/namespaces.ts @@ -13,7 +13,7 @@ import { GWAService } from '../../gwaapi'; export interface ReportOfNamespaces { resource_id: string; name: string; - description?: string; + displayName?: string; permProtectedNs?: string; permDomains?: string[]; permDataPlane?: string; @@ -50,7 +50,6 @@ export async function getNamespaces( const nsPermissions = await kcGroupService.getGroup('ns', ns.name); transformSingleValueAttributes(nsPermissions.attributes, [ - 'description', 'perm-data-plane', 'perm-protected-ns', 'org', diff --git a/src/services/report/output/structure.ts b/src/services/report/output/structure.ts index bc289503c..1fa93e723 100644 --- a/src/services/report/output/structure.ts +++ b/src/services/report/output/structure.ts @@ -18,6 +18,11 @@ export const reportStructure: any = { key: 'name', width: 32, }, + { + header: 'Display Name', + key: 'displayName', + width: 32, + }, { header: 'Privileged', key: 'permProtectedNs', diff --git a/src/services/uma2/resource-registration-service.ts b/src/services/uma2/resource-registration-service.ts index 4fdb76b6a..eb7b20ae8 100644 --- a/src/services/uma2/resource-registration-service.ts +++ b/src/services/uma2/resource-registration-service.ts @@ -14,6 +14,7 @@ export interface ResourceSetQuery { scope?: string; first?: number; max?: number; + deep?: boolean; } export interface ResourceScope { @@ -27,6 +28,7 @@ export interface ResourceOwner { export interface ResourceSet { id: string; name: string; + displayName?: string; type: string; uris?: string[]; icon_uri?: string; @@ -37,6 +39,7 @@ export interface ResourceSet { export interface ResourceSetInput { name: string; + displayName?: string; type: string; uris?: string[]; icon_uri?: string; diff --git a/src/services/workflow/get-namespaces.ts b/src/services/workflow/get-namespaces.ts index d43a83ac6..4132462b9 100644 --- a/src/services/workflow/get-namespaces.ts +++ b/src/services/workflow/get-namespaces.ts @@ -59,6 +59,7 @@ export async function getMyNamespaces( return namespaces.map((ns: ResourceSet) => ({ id: ns.id, name: ns.name, + displayName: ns.displayName, scopes: ns.resource_scopes, prodEnvId: envCtx.prodEnv.id, })); @@ -269,6 +270,7 @@ export interface ResourceServerContext { export interface NamespaceSummary { id: string; name: string; + displayName: string; scopes: ResourceScope[]; prodEnvId: string; } diff --git a/src/test/integrated/uma2/resource.ts b/src/test/integrated/uma2/resource.ts index 170dc1bda..f7f81d3bc 100644 --- a/src/test/integrated/uma2/resource.ts +++ b/src/test/integrated/uma2/resource.ts @@ -32,15 +32,18 @@ import { token ); - if (false) { + if (true) { await svc.createResourceSet({ name: 'sample2', - type: 'organization', + displayName: 'Sample Number 2', + type: 'integration_test', resource_scopes: ['Organization.Manage'], ownerManagedAccess: true, }); } - console.log(await svc.listResources({ type: 'organization' })); + console.log( + await svc.listResources({ type: 'integration_test', deep: true }) + ); - console.log(await svc.findResourceByName('sample33')); + console.log(await svc.findResourceByName('sample2')); })(); From 569fb1a4899374cfce9cf3a515e371e6391fa3f7 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Thu, 20 Jul 2023 13:02:44 -0700 Subject: [PATCH 16/81] have create namespace using application json --- src/controllers/v2/NamespaceController.ts | 9 ++++---- src/controllers/v2/openapi.yaml | 27 ++++++++++++----------- src/controllers/v2/routes.ts | 8 +++++-- src/lists/extensions/Namespace.ts | 3 ++- src/nextapp/shared/types/query.types.ts | 3 ++- src/services/keystone/types.ts | 3 ++- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/controllers/v2/NamespaceController.ts b/src/controllers/v2/NamespaceController.ts index 9edc61cf5..4ee53d207 100644 --- a/src/controllers/v2/NamespaceController.ts +++ b/src/controllers/v2/NamespaceController.ts @@ -10,13 +10,14 @@ import { Delete, Query, Post, + Body, } from 'tsoa'; import { ValidateError, FieldErrors } from 'tsoa'; import { KeystoneService } from '../ioc/keystoneInjector'; import { inject, injectable } from 'tsyringe'; import { gql } from 'graphql-request'; import { WorkbookService } from '../../services/report/workbook.service'; -import { Namespace } from '../../services/keystone/types'; +import { Namespace, NamespaceInput } from '../../services/keystone/types'; import { Readable } from 'stream'; import { @@ -34,6 +35,7 @@ import { Activity } from './types'; import { getActivity } from '../../services/keystone/activity'; import { transformActivity } from '../../services/workflow'; import { ActivityDetail } from './types-extra'; + const logger = Logger('controllers.Namespace'); /** @@ -150,13 +152,12 @@ export class NamespaceController extends Controller { @Security('jwt', []) public async create( @Request() request: any, - @Query() name?: String, - @Query() displayName?: String + @Body() vars: NamespaceInput ): Promise { const result = await this.keystone.executeGraphQL({ context: this.keystone.createContext(request), query: createNS, - variables: { name, displayName }, + variables: vars, }); logger.debug('Result %j', result); if (result.errors) { diff --git a/src/controllers/v2/openapi.yaml b/src/controllers/v2/openapi.yaml index 8681f5b90..306e8d3ac 100644 --- a/src/controllers/v2/openapi.yaml +++ b/src/controllers/v2/openapi.yaml @@ -436,6 +436,13 @@ components: required: - name type: object + NamespaceInput: + properties: + displayName: + $ref: '#/components/schemas/Maybe_Scalars-at-String_' + name: + $ref: '#/components/schemas/Maybe_Scalars-at-String_' + type: object ActivityDetail: properties: id: @@ -1203,19 +1210,13 @@ paths: security: - jwt: [] - parameters: - - - in: query - name: name - required: false - schema: - type: string - - - in: query - name: displayName - required: false - schema: - type: string + parameters: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NamespaceInput' '/namespaces/{ns}': get: operationId: namespace-profile diff --git a/src/controllers/v2/routes.ts b/src/controllers/v2/routes.ts index 003794580..9f05c5aee 100644 --- a/src/controllers/v2/routes.ts +++ b/src/controllers/v2/routes.ts @@ -273,6 +273,11 @@ const models: TsoaRoute.Models = { "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"orgAdmins":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"orgNoticeViewed":{"ref":"Maybe_Scalars-at-Boolean_"},"orgEnabled":{"ref":"Maybe_Scalars-at-Boolean_"},"orgUpdatedAt":{"ref":"Maybe_Scalars-at-Float_"},"orgUnit":{"ref":"Maybe_Scalars-at-JSON_"},"org":{"ref":"Maybe_Scalars-at-JSON_"},"permProtectedNs":{"ref":"Maybe_Scalars-at-String_"},"permDataPlane":{"ref":"Maybe_Scalars-at-String_"},"permDomains":{"ref":"Maybe_Array_Maybe_Scalars-at-String___"},"prodEnvId":{"ref":"Maybe_Scalars-at-String_"},"scopes":{"ref":"Maybe_Array_Maybe_UmaScope___"},"displayName":{"ref":"Maybe_Scalars-at-String_"},"name":{"dataType":"string","required":true},"id":{"ref":"Maybe_Scalars-at-String_"},"__typename":{"dataType":"enum","enums":["Namespace"]}},"validators":{}}, }, // 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 + "NamespaceInput": { + "dataType": "refAlias", + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"displayName":{"ref":"Maybe_Scalars-at-String_"},"name":{"ref":"Maybe_Scalars-at-String_"}},"validators":{}}, + }, + // 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 "ActivityDetail": { "dataType": "refObject", "properties": { @@ -1068,8 +1073,7 @@ export function RegisterRoutes(app: express.Router) { async function NamespaceController_create(request: any, response: any, next: any) { const args = { request: {"in":"request","name":"request","required":true,"dataType":"object"}, - name: {"in":"query","name":"name","dataType":"string"}, - displayName: {"in":"query","name":"displayName","dataType":"string"}, + vars: {"in":"body","name":"vars","required":true,"ref":"NamespaceInput"}, }; // 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 diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index dfb9752dd..93883984f 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -80,7 +80,8 @@ type Namespace { const typeNamespaceInput = ` input NamespaceInput { - name: String!, + name: String, + displayName: String } `; diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index bf5519e95..5d5de8201 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -5431,7 +5431,8 @@ export type Namespace = { }; export type NamespaceInput = { - name: Scalars['String']; + name?: Maybe; + displayName?: Maybe; }; /** A keystone list */ diff --git a/src/services/keystone/types.ts b/src/services/keystone/types.ts index bf5519e95..5d5de8201 100644 --- a/src/services/keystone/types.ts +++ b/src/services/keystone/types.ts @@ -5431,7 +5431,8 @@ export type Namespace = { }; export type NamespaceInput = { - name: Scalars['String']; + name?: Maybe; + displayName?: Maybe; }; /** A keystone list */ From b7754d91730c68b6d040ba0dbae6e0284f93c78e Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 21 Jul 2023 00:45:37 -0700 Subject: [PATCH 17/81] change from lodash to just-kebab-case for shared idp client id --- src/lists/CredentialIssuer.js | 2 +- src/package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lists/CredentialIssuer.js b/src/lists/CredentialIssuer.js index 1b51a1103..4791d1d9d 100644 --- a/src/lists/CredentialIssuer.js +++ b/src/lists/CredentialIssuer.js @@ -28,7 +28,7 @@ const { addClientsToSharedIdP, } = require('../services/workflow'); const { Logger } = require('../logger'); -const { kebabCase } = require('lodash'); +const kebabCase = require('just-kebab-case'); const logger = Logger('lists.credentialissuer'); module.exports = { diff --git a/src/package.json b/src/package.json index c71395fa5..d8f6d2ba5 100644 --- a/src/package.json +++ b/src/package.json @@ -98,8 +98,9 @@ "graphql-tools": "^7.0.2", "http-proxy-middleware": "^2.0.6", "isomorphic-unfetch": "^3.1.0", - "json-stable-stringify": "^1.0.2", "js-yaml": "^4.1.0", + "json-stable-stringify": "^1.0.2", + "just-kebab-case": "^4.2.0", "jwks-rsa": "^2.0.5", "jwt-decode": "^3.1.2", "keycloak-connect": "^17.0.1", From afc5c123d6e464bc976607639fe2f4db7b6fdffc Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 21 Jul 2023 01:06:47 -0700 Subject: [PATCH 18/81] change from lodash to just-kebab-case for shared idp client id --- src/lists/extensions/CredentialIssuerExt.ts | 2 +- src/lists/extensions/UserExt.ts | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/lists/extensions/CredentialIssuerExt.ts b/src/lists/extensions/CredentialIssuerExt.ts index f44463ff1..5913f0e27 100644 --- a/src/lists/extensions/CredentialIssuerExt.ts +++ b/src/lists/extensions/CredentialIssuerExt.ts @@ -1,5 +1,5 @@ const { EnforcementPoint } = require('../../authz/enforcement'); -import { kebabCase } from 'lodash'; +import kebabCase from 'just-kebab-case'; import { generateEnvDetails, lookupSharedIssuers, diff --git a/src/lists/extensions/UserExt.ts b/src/lists/extensions/UserExt.ts index 76b33e03d..6d3784ab4 100644 --- a/src/lists/extensions/UserExt.ts +++ b/src/lists/extensions/UserExt.ts @@ -1,16 +1,6 @@ const { EnforcementPoint } = require('../../authz/enforcement'); import { lookupProviderUserByEmail } from '../../services/keystone/user'; -import { kebabCase } from 'lodash'; -import { - generateEnvDetails, - lookupSharedIssuers, -} from '../../services/keystone'; -import { - CredentialIssuer, - CredentialIssuerWhereInput, - User, - UserWhereInput, -} from '../../services/keystone/types'; +import { User, UserWhereInput } from '../../services/keystone/types'; module.exports = { extensions: [ From 33bcfcfcbacf724a723f8fe32ddabe01e066806c Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 25 Jul 2023 10:47:38 -0700 Subject: [PATCH 19/81] service account failing with cannot read properties of null --- src/lists/extensions/ServiceAccount.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lists/extensions/ServiceAccount.ts b/src/lists/extensions/ServiceAccount.ts index f2aa9917e..ed50e19ee 100644 --- a/src/lists/extensions/ServiceAccount.ts +++ b/src/lists/extensions/ServiceAccount.ts @@ -81,11 +81,13 @@ module.exports = { info: any, { query, access }: any ) => { - context.skipAccessControl = true; + const noauthContext = context.createContext({ + skipAccessControl: true, + }); const productEnvironmentSlug = process.env.GWA_PROD_ENV_SLUG; const { newCredentials } = await CreateServiceAccount( - context, + noauthContext, productEnvironmentSlug, context.req.user.namespace, args.resourceId, From dbafb35e7cf8e7cfcc9003f9303474a5022e98d4 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 25 Jul 2023 12:08:17 -0700 Subject: [PATCH 20/81] order the namespaces in the api --- src/controllers/v2/NamespaceController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/v2/NamespaceController.ts b/src/controllers/v2/NamespaceController.ts index 4ee53d207..1ef0715d6 100644 --- a/src/controllers/v2/NamespaceController.ts +++ b/src/controllers/v2/NamespaceController.ts @@ -110,7 +110,7 @@ export class NamespaceController extends Controller { query: list, }); logger.debug('Result %j', result); - return result.data.allNamespaces.map((ns: Namespace) => ns.name); + return result.data.allNamespaces.map((ns: Namespace) => ns.name).sort(); } /** From 586f1e151922844a9be7ff590e48c28aba5451cd Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 25 Jul 2023 15:01:42 -0700 Subject: [PATCH 21/81] upd feed worker put bubble up child results --- src/batch/feed-worker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/batch/feed-worker.ts b/src/batch/feed-worker.ts index 76122ea68..e6f6a6ff0 100644 --- a/src/batch/feed-worker.ts +++ b/src/batch/feed-worker.ts @@ -476,9 +476,12 @@ export const syncRecords = async function ( } if (Object.keys(data).length === 0) { logger.debug('[%s] [%s] no update', entity, localRecord.id); + const firstChildResult = childResults + .filter((r) => r.result != 'no-change') + .pop(); return { status: 200, - result: 'no-change', + result: firstChildResult ? firstChildResult.result : 'no-change', id: localRecord['id'], childResults, ownedBy: From 879789180877ae5a2e3e019fa3c799652bc1f9d2 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 25 Jul 2023 15:02:22 -0700 Subject: [PATCH 22/81] upd feed worker put bubble up child results --- src/batch/feed-worker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/batch/feed-worker.ts b/src/batch/feed-worker.ts index e6f6a6ff0..b33db0978 100644 --- a/src/batch/feed-worker.ts +++ b/src/batch/feed-worker.ts @@ -481,7 +481,9 @@ export const syncRecords = async function ( .pop(); return { status: 200, - result: firstChildResult ? firstChildResult.result : 'no-change', + result: firstChildResult + ? firstChildResult.result + '-child' + : 'no-change', id: localRecord['id'], childResults, ownedBy: From f4fc4d42cdfac490363e60cc7ba128cb09697820 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Tue, 25 Jul 2023 15:21:15 -0700 Subject: [PATCH 23/81] Added scenarios for GWA-CLI and update existing scenarios as per new gateway layout --- e2e/cypress.config.ts | 1 + e2e/cypress/fixtures/apiowner.json | 506 ++++++++++-------- e2e/cypress/fixtures/cc-service-gwa.yml | 19 + e2e/cypress/fixtures/service-gwa.yml | 38 ++ e2e/cypress/fixtures/test_data/gwa-cli.json | 10 +- e2e/cypress/support/auth-commands.ts | 63 +-- e2e/cypress/support/global.d.ts | 48 +- e2e/cypress/support/util-commands.ts | 46 +- .../tests/01-api-key/01-create-api.cy.ts | 46 +- ...quest-without-collecting-credentials.cy.ts | 10 +- .../01-api-key/06-approve-pending-rqst.cy.ts | 8 +- .../tests/01-api-key/07-grant-access.cy.ts | 8 +- .../01-client-cred-team-access.cy.ts | 35 +- ...client-cred-create-api-prod-auth-pro.cy.ts | 43 +- .../05-cids-access-approve-api-rqst.cy.ts | 10 +- ...07-jwt-genkp-access-approve-api-rqst.cy.ts | 9 +- ...09-jwks-url-access-approval-api-rqst.cy.ts | 9 +- ...t-publlicKey-access-approve-api-rqst.cy.ts | 75 +-- .../02-client-credential-flow/cli-demo.ts | 137 ----- ...approve-pending-rqst-for-labels.spec.cy.ts | 10 +- .../03-manage-labels/03-filter-labels.cy.ts | 10 +- .../03-manage-labels/04-manage-labels.cy.ts | 12 +- .../03-manage-labels/05-link-consumers.ts | 21 +- .../01-gateway-service-details.cy.ts | 11 +- .../01-migrate-user-access.cy.ts | 24 +- .../02-client-credentials.cy.ts | 4 + .../07-manage-control/01-ip-restriction.cy.ts | 24 +- .../07-manage-control/02-rate-limiting.cy.ts | 305 +++++------ ...03-kong-api-only-apply-rate-limiting.cy.ts | 22 +- e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts | 126 +++++ e2e/package-lock.json | 181 +++++-- e2e/package.json | 1 + 32 files changed, 1093 insertions(+), 779 deletions(-) create mode 100644 e2e/cypress/fixtures/cc-service-gwa.yml create mode 100644 e2e/cypress/fixtures/service-gwa.yml delete mode 100644 e2e/cypress/tests/02-client-credential-flow/cli-demo.ts create mode 100644 e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index 150628ffc..e632cddcc 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -11,6 +11,7 @@ export default defineConfig({ // // It's IMPORTANT to return the config object // // with any changed environment variables config.specPattern=[ + './cypress/tests/18-*/*.ts', './cypress/tests/01-*/*.ts', './cypress/tests/02-*/*.ts', './cypress/tests/06-*/*.ts', diff --git a/e2e/cypress/fixtures/apiowner.json b/e2e/cypress/fixtures/apiowner.json index c7b0844b3..3a4983496 100644 --- a/e2e/cypress/fixtures/apiowner.json +++ b/e2e/cypress/fixtures/apiowner.json @@ -2,14 +2,22 @@ "user": { "credentials": { "username": "janis@idir", - "email":"janis@testmail.com", + "email": "janis@testmail.com", "password": "awsummer" } }, - "namespace": "newplatform", - "invalid_namespace": ["test_1234", "New_napespace", "Government"], + "namespace": "gw-9be47", + "invalid_namespace": [ + "test_1234", + "New_napespace", + "Government" + ], "serviceAccount": { - "scopes": ["GatewayConfig.Publish", "Namespace.Manage", "Content.Publish"] + "scopes": [ + "GatewayConfig.Publish", + "Namespace.Manage", + "Content.Publish" + ] }, "deleteResources": { "namespace": "deleteplatform", @@ -26,7 +34,9 @@ } } }, - "namespaceAccessPermissions": ["CredentialIssuer.Admin"], + "namespaceAccessPermissions": [ + "CredentialIssuer.Admin" + ], "product": { "name": "Auto Test Product", "orgName": "Ministry of Health", @@ -37,7 +47,7 @@ "terms": "Terms of Use for API Gateway", "authorization": "Kong API Key with ACL Flow", "optionalInstructions": "This is a automation test", - "serviceName": "a-service-for-newplatform" + "serviceName": "a-service-for-gw-9be47" } }, "test_environment": { @@ -46,22 +56,26 @@ "terms": "Terms of Use for API Gateway", "authorization": "Kong API Key with ACL Flow", "optionalInstructions": "This is a automation test", - "serviceName": "a-service-for-newplatform-test" + "serviceName": "a-service-for-gw-9be47-test" } } }, "clientCredentials": { - "namespace": "ccplatform", + "namespace": "gw-a2fe3", "serviceName": "cc-service-for-platform", "Mark": { "userName": "mark", - "email":"mark@gmail.com", - "accessRole": ["Access.Manage"] + "email": "mark@gmail.com", + "accessRole": [ + "Access.Manage" + ] }, "Wendy": { "userName": "wendy", - "email":"wendy@test.com", - "accessRole": ["CredentialIssuer.Admin"] + "email": "wendy@test.com", + "accessRole": [ + "CredentialIssuer.Admin" + ] }, "jwtKeyPair": { "authProfile": { @@ -161,7 +175,9 @@ "name": "cy-client-id-secret-auth", "flow": "Client Credential Flow", "element": "cc-id-secret", - "scopes":["System.Write"], + "scopes": [ + "System.Write" + ], "clientAuthenticator": "Client ID and Secret", "environmentConfig": { "environment": "Test", @@ -238,7 +254,9 @@ "name": "cy-client-id-secret-auth-updated", "flow": "Client Credential Flow", "element": "cc-id-secret", - "scopes":["System.Write"], + "scopes": [ + "System.Write" + ], "clientAuthenticator": "Client ID and Secret", "environmentConfig": { "environment": "Test", @@ -256,7 +274,7 @@ "element": "cc-id-secret", "clientAuthenticator": "Client ID and Secret", "environmentConfig": { - "isShardIDP":true + "isShardIDP": true } } } @@ -264,7 +282,10 @@ "namespacePreview": { "namespace": "previewmode", "serviceAccount": { - "scopes": ["GatewayConfig.Publish", "Namespace.Manage"] + "scopes": [ + "GatewayConfig.Publish", + "Namespace.Manage" + ] }, "product": { "name": "Namespace Preview Test Product", @@ -284,11 +305,16 @@ "serviceName": "a-service-for-orgassignment", "Mark": { "userName": "mark", - "email":"mark@gmail.com", - "accessRole": ["Access.Manage"] + "email": "mark@gmail.com", + "accessRole": [ + "Access.Manage" + ] }, "serviceAccount": { - "scopes": ["GatewayConfig.Publish", "Namespace.Manage"] + "scopes": [ + "GatewayConfig.Publish", + "Namespace.Manage" + ] }, "product": { "name": "Org Assignment Product", @@ -302,9 +328,9 @@ } } }, - "orgAdminNotification":{ - "parent" : "Your Organization Administrator has been notified to enable API Publishing to the Directory for the orgassignment namespace.", - "child" : "New namespaces must be reviewed by your Organization Administrator before you can publish APIs to the Directory. Your APIs are still in preview mode. For status inquiries, contact your Organization Administrator benny@test.com." + "orgAdminNotification": { + "parent": "Your Organization Administrator has been notified to enable API Publishing to the Directory for the orgassignment namespace.", + "child": "New namespaces must be reviewed by your Organization Administrator before you can publish APIs to the Directory. Your APIs are still in preview mode. For status inquiries, contact your Organization Administrator benny@test.com." } }, "orgAssignmentMultipleAdmin": { @@ -312,13 +338,17 @@ "serviceName": "a-service-for-orgassignment1", "Mark": { "userName": "mark", - "email":"mark@gmail.com", - "accessRole": ["Access.Manage"] + "email": "mark@gmail.com", + "accessRole": [ + "Access.Manage" + ] }, "GroupAccess": { - "members": ["benny@test.com", "wendy@test.com"] + "members": [ + "benny@test.com", + "wendy@test.com" + ] }, - "product": { "name": "Org Assignment Product", "environment": { @@ -331,9 +361,9 @@ } } }, - "orgAdminNotification":{ - "parent" : "Your Organization Administrator has been notified to enable API Publishing to the Directory for the orgassignment namespace.", - "child" : "New namespaces must be reviewed by your Organization Administrator before you can publish APIs to the Directory. Your APIs are still in preview mode. For status inquiries, contact your Organization Administrator benny@test.com." + "orgAdminNotification": { + "parent": "Your Organization Administrator has been notified to enable API Publishing to the Directory for the orgassignment namespace.", + "child": "New namespaces must be reviewed by your Organization Administrator before you can publish APIs to the Directory. Your APIs are still in preview mode. For status inquiries, contact your Organization Administrator benny@test.com." } }, "orgAssignmentOrgUnit": { @@ -341,13 +371,16 @@ "serviceName": "a-service-for-orgassign-unit", "Mark": { "userName": "mark", - "email":"mark@gmail.com", - "accessRole": ["Access.Manage"] + "email": "mark@gmail.com", + "accessRole": [ + "Access.Manage" + ] }, "GroupAccess": { - "members": ["benny@test.com"] + "members": [ + "benny@test.com" + ] }, - "product": { "name": "Org Assignment Unit Product", "environment": { @@ -360,15 +393,18 @@ } } }, - "orgAdminNotification":{ - "parent" : "Your Organization Administrator has been notified to enable API Publishing to the Directory for the orgassignment namespace.", - "child" : "New namespaces must be reviewed by your Organization Administrator before you can publish APIs to the Directory. Your APIs are still in preview mode. For status inquiries, contact your Organization Administrator benny@test.com." + "orgAdminNotification": { + "parent": "Your Organization Administrator has been notified to enable API Publishing to the Directory for the orgassignment namespace.", + "child": "New namespaces must be reviewed by your Organization Administrator before you can publish APIs to the Directory. Your APIs are still in preview mode. For status inquiries, contact your Organization Administrator benny@test.com." } }, "checkPermission": { "namespace": "permission", "serviceAccount": { - "scopes": ["GatewayConfig.Publish", "Namespace.Manage"] + "scopes": [ + "GatewayConfig.Publish", + "Namespace.Manage" + ] }, "product": { "name": "New-Auto Test Product", @@ -385,59 +421,88 @@ "grantPermission": { "Mark": { "userName": "Mark F Mark L", - "email":"mark@gmail.com", - "accessRole": ["Access.Manage"] + "email": "mark@gmail.com", + "accessRole": [ + "Access.Manage" + ] }, "Mark_NV": { "userName": "Mark F Mark L", - "email":"mark@gmail.com", - "accessRole": ["Namespace.View"] + "email": "mark@gmail.com", + "accessRole": [ + "Namespace.View" + ] }, "Wendy": { "userName": "Wendy F Wendy L", - "email":"wendy@test.com", - "accessRole": ["Namespace.Manage", "CredentialIssuer.Admin"] + "email": "wendy@test.com", + "accessRole": [ + "Namespace.Manage", + "CredentialIssuer.Admin" + ] }, "Wendy_NM": { "userName": "Wendy F Wendy L", - "email":"wendy@test.com", - "accessRole": ["Namespace.Manage"] + "email": "wendy@test.com", + "accessRole": [ + "Namespace.Manage" + ] }, "Wendy_CA": { "userName": "Wendy F Wendy L", - "email":"wendy@test.com", - "accessRole": ["CredentialIssuer.Admin"] + "email": "wendy@test.com", + "accessRole": [ + "CredentialIssuer.Admin" + ] }, "Wendy_GC": { "userName": "Wendy F Wendy L", - "email":"wendy@test.com", - "accessRole": ["GatewayConfig.Publish", "Namespace.View"] + "email": "wendy@test.com", + "accessRole": [ + "GatewayConfig.Publish", + "Namespace.View" + ] }, "Janis": { "userName": "Janis Smith", - "email":"janis@testmail.com", - "accessRole": ["Namespace.Manage", "CredentialIssuer.Admin"] + "email": "janis@testmail.com", + "accessRole": [ + "Namespace.Manage", + "CredentialIssuer.Admin" + ] } }, "revokePermission": { "Mark": { "userName": "mark", - "accessRole": ["Namespace.View", "Access.Manage"] + "accessRole": [ + "Namespace.View", + "Access.Manage" + ] }, "Mark_AM": { "userName": "mark", - "accessRole": ["Access.Manage"] + "accessRole": [ + "Access.Manage" + ] }, "Wendy": { "userName": "wendy", - "accessRole": ["Namespace.Manage"] + "accessRole": [ + "Namespace.Manage" + ] }, "Wendy_ci": { "userName": "wendy", - "accessRole": ["CredentialIssuer.Admin"] + "accessRole": [ + "CredentialIssuer.Admin" + ] }, "serviceAccount": { - "scopes": ["Namespace.Manage", "Content.Publish"] + "scopes": [ + "Namespace.Manage", + "Content.Publish" + ] } } }, @@ -445,23 +510,36 @@ "Mark": { "userName": "mark", "email": "mark@gmail.com", - "accessRole": ["Access.Manage", "Namespace.View"] + "accessRole": [ + "Access.Manage", + "Namespace.View" + ] }, "Janis": { "userName": "Janis Smith", "email": "janis@testmail.com", - "accessRole": ["CredentialIssuer.Admin","Namespace.Manage"] + "accessRole": [ + "CredentialIssuer.Admin", + "Namespace.Manage" + ] }, "OldUser": { "userName": "olduser@idir", "email": "olduser@testmail.com", - "accessRole": ["Access.Manage", "Namespace.View","Namespace.Manage"] + "accessRole": [ + "Access.Manage", + "Namespace.View", + "Namespace.Manage" + ] } }, "permission": { "Mark": { "userName": "mark", - "accessRole": ["Access.Manage", "Namespace.View"] + "accessRole": [ + "Access.Manage", + "Namespace.View" + ] } }, "apiTest": { @@ -480,197 +558,197 @@ } } }, - "expectedActivitiesResponse":[ + "expectedActivitiesResponse": [ { - "result": "success", - "message": "{actor} {action} {entity} for {application} ({consumer}) to access {product} {environment}", - "params": { - "actor": "Mark F Mark L", - "action": "approved", - "entity": "access request", - "accessRequest": "2", - "environment": "dev", - "product": "Auto Test Product", - "application": "Auto Test App to check labels", - "consumer": "9C3EFC92-8F3DE9D3B74" - }, - "activityAt": "2022-09-20T20:39:05.318Z" + "result": "success", + "message": "{actor} {action} {entity} for {application} ({consumer}) to access {product} {environment}", + "params": { + "actor": "Mark F Mark L", + "action": "approved", + "entity": "access request", + "accessRequest": "2", + "environment": "dev", + "product": "Auto Test Product", + "application": "Auto Test App to check labels", + "consumer": "9C3EFC92-8F3DE9D3B74" + }, + "activityAt": "2022-09-20T20:39:05.318Z" }, { - "result": "success", - "message": "{actor} {action} for {application} ({consumer}) to access {product} {environment} ({note})", - "params": { - "actor": "Harley Jones", - "action": "received credentials", - "entity": "access", - "note": "access pending approval", - "accessRequest": "2", - "environment": "dev", - "product": "Auto Test Product", - "application": "Auto Test App to check labels", - "consumer": "9C3EFC92-8F3DE9D3B73" - }, - "activityAt": "2022-09-20T20:38:40.857Z" + "result": "success", + "message": "{actor} {action} for {application} ({consumer}) to access {product} {environment} ({note})", + "params": { + "actor": "Harley Jones", + "action": "received credentials", + "entity": "access", + "note": "access pending approval", + "accessRequest": "2", + "environment": "dev", + "product": "Auto Test Product", + "application": "Auto Test App to check labels", + "consumer": "9C3EFC92-8F3DE9D3B73" + }, + "activityAt": "2022-09-20T20:38:40.857Z" }, { - "result": "success", - "message": "{actor} {action} {entity} for {consumer}", - "params": { - "actor": "Mark F Mark L", - "action": "update", - "entity": "consumer control" - }, - "activityAt": "2022-09-20T20:38:19.732Z" + "result": "success", + "message": "{actor} {action} {entity} for {consumer}", + "params": { + "actor": "Mark F Mark L", + "action": "update", + "entity": "consumer control" + }, + "activityAt": "2022-09-20T20:38:19.732Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:38:19.678Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:38:19.678Z" }, { - "result": "success", - "message": "{actor} {action} {entity} for {consumer}", - "params": { - "actor": "Mark F Mark L", - "action": "update", - "entity": "consumer control" - }, - "activityAt": "2022-09-20T20:38:14.706Z" + "result": "success", + "message": "{actor} {action} {entity} for {consumer}", + "params": { + "actor": "Mark F Mark L", + "action": "update", + "entity": "consumer control" + }, + "activityAt": "2022-09-20T20:38:14.706Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:38:12.664Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:38:12.664Z" }, { - "result": "success", - "message": "{actor} {action} {entity} for {consumer}", - "params": { - "actor": "Mark F Mark L", - "action": "update", - "entity": "consumer control" - }, - "activityAt": "2022-09-20T20:38:08.054Z" + "result": "success", + "message": "{actor} {action} {entity} for {consumer}", + "params": { + "actor": "Mark F Mark L", + "action": "update", + "entity": "consumer control" + }, + "activityAt": "2022-09-20T20:38:08.054Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:38:07.996Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:38:07.996Z" }, { - "result": "success", - "message": "{actor} {action} {entity} for {consumer}", - "params": { - "actor": "Mark F Mark L", - "action": "update", - "entity": "consumer control" - }, - "activityAt": "2022-09-20T20:38:00.947Z" + "result": "success", + "message": "{actor} {action} {entity} for {consumer}", + "params": { + "actor": "Mark F Mark L", + "action": "update", + "entity": "consumer control" + }, + "activityAt": "2022-09-20T20:38:00.947Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:38:00.899Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:38:00.899Z" }, { - "result": "success", - "message": "{actor} {action} {entity} for {consumer}", - "params": { - "actor": "Mark F Mark L", - "action": "update", - "entity": "consumer control" - }, - "activityAt": "2022-09-20T20:37:56.316Z" + "result": "success", + "message": "{actor} {action} {entity} for {consumer}", + "params": { + "actor": "Mark F Mark L", + "action": "update", + "entity": "consumer control" + }, + "activityAt": "2022-09-20T20:37:56.316Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:37:56.252Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:37:56.252Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:37:56.192Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:37:56.192Z" }, { - "result": "success", - "message": "{actor} {action} {entity} for {consumer}", - "params": { - "actor": "Mark F Mark L", - "action": "update", - "entity": "consumer control" - }, - "activityAt": "2022-09-20T20:37:47.630Z" + "result": "success", + "message": "{actor} {action} {entity} for {consumer}", + "params": { + "actor": "Mark F Mark L", + "action": "update", + "entity": "consumer control" + }, + "activityAt": "2022-09-20T20:37:47.630Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:37:47.574Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:37:47.574Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:37:47.516Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:37:47.516Z" }, { - "result": "success", - "message": "{actor} {action} {entity} for {consumer}", - "params": { - "actor": "Mark F Mark L", - "action": "update", - "entity": "consumer control" - }, - "activityAt": "2022-09-20T20:37:38.815Z" + "result": "success", + "message": "{actor} {action} {entity} for {consumer}", + "params": { + "actor": "Mark F Mark L", + "action": "update", + "entity": "consumer control" + }, + "activityAt": "2022-09-20T20:37:38.815Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:37:38.763Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:37:38.763Z" }, { - "result": "completed", - "message": "GatewayConsumerPlugin Update", - "params": { - "actor": "Unknown Actor" - }, - "activityAt": "2022-09-20T20:37:38.696Z" + "result": "completed", + "message": "GatewayConsumerPlugin Update", + "params": { + "actor": "Unknown Actor" + }, + "activityAt": "2022-09-20T20:37:38.696Z" }, { - "result": "success", - "message": "{actor} {action} {entity} for {consumer}", - "params": { - "actor": "Mark F Mark L", - "action": "update", - "entity": "consumer control" - }, - "activityAt": "2022-09-20T20:37:30.570Z" + "result": "success", + "message": "{actor} {action} {entity} for {consumer}", + "params": { + "actor": "Mark F Mark L", + "action": "update", + "entity": "consumer control" + }, + "activityAt": "2022-09-20T20:37:30.570Z" } -] -} + ] +} \ No newline at end of file diff --git a/e2e/cypress/fixtures/cc-service-gwa.yml b/e2e/cypress/fixtures/cc-service-gwa.yml new file mode 100644 index 000000000..77b815834 --- /dev/null +++ b/e2e/cypress/fixtures/cc-service-gwa.yml @@ -0,0 +1,19 @@ +services: +- name: cc-service-for-platform + host: httpbin.org + tags: [ns.ccplatform] + port: 443 + protocol: https + retries: 0 + routes: + - name: cc-service-for-platform-route + tags: [ns.ccplatform] + hosts: + - cc-service-for-platform.api.gov.bc.ca + paths: + - / + methods: + - GET + strip_path: false + https_redirect_status_code: 426 + path_handling: v0 \ No newline at end of file diff --git a/e2e/cypress/fixtures/service-gwa.yml b/e2e/cypress/fixtures/service-gwa.yml new file mode 100644 index 000000000..77ddda761 --- /dev/null +++ b/e2e/cypress/fixtures/service-gwa.yml @@ -0,0 +1,38 @@ +services: +- name: a-service-for-newplatform + host: httpbin.org + tags: [ns.newplatform] + port: 443 + protocol: https + retries: 0 + routes: + - name: a-service-for-newplatform-route + tags: [ns.newplatform] + hosts: + - a-service-for-newplatform.api.gov.bc.ca + paths: + - / + methods: + - GET + strip_path: false + https_redirect_status_code: 426 + path_handling: v0 + +- name: a-service-for-newplatform-test + host: httpbin.org + tags: [ns.newplatform] + port: 443 + protocol: https + retries: 0 + routes: + - name: a-service-for-newplatform-test-route + tags: [ns.newplatform] + hosts: + - a-service-for-newplatform-test.api.gov.bc.ca + paths: + - / + methods: + - GET + strip_path: false + https_redirect_status_code: 426 + path_handling: v0 \ No newline at end of file diff --git a/e2e/cypress/fixtures/test_data/gwa-cli.json b/e2e/cypress/fixtures/test_data/gwa-cli.json index 10ffdc27c..a993bc254 100644 --- a/e2e/cypress/fixtures/test_data/gwa-cli.json +++ b/e2e/cypress/fixtures/test_data/gwa-cli.json @@ -2,11 +2,11 @@ "content": { "help": "You can login via device login or by using client credentials\n\nTo use device login, simply run the command like so:\n $ gwa login\n\nTo use your credentials you must supply both a client-id and client-secret:\n $ gwa login --client-id --client-secret \n\nUsage:\n gwa login [flags]\n\nFlags:\n --client-id string Your gateway's client ID\n --client-secret string Your gateway's client secret\n -h, --help help for login\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --namespace string Assign the namespace you would like to use\n --scheme string Use to override default https", "login_help": "Log in to your IDIR account\n\nUsage:\n gwa login [flags]\n\nFlags:\n --client-id string Your gateway's client ID\n --client-secret string Your gateway's client secret\n -h, --help help for login\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --scheme string Use to override default https", - "namespace_help" : "Longer explanation to come...\n\nUsage:\n gwa namespace [command]\n\nAvailable Commands:\n create Create a new namespace\n list List all your managed namespaces\n\nFlags:\n -h, --help help for namespace\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --namespace string Assign the namespace you would like to use\n --scheme string Use to override default https\n\nUse \"gwa namespace [command] --help\" for more information about a command.", - "config_help":"Configuration commands\n\nUsage:\n gwa config [command]\n\nAvailable Commands:\n set Write a specific global setting\n\nFlags:\n -h, --help help for config\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --namespace string Assign the namespace you would like to use\n --scheme string Use to override default https\n\nUse \"gwa config [command] --help\" for more information about a command." + "namespace_help": "Longer explanation to come...\n\nUsage:\n gwa namespace [command]\n\nAvailable Commands:\n create Create a new namespace\n list List all your managed namespaces\n\nFlags:\n -h, --help help for namespace\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --namespace string Assign the namespace you would like to use\n --scheme string Use to override default https\n\nUse \"gwa namespace [command] --help\" for more information about a command.", + "config_help": "Configuration commands\n\nUsage:\n gwa config [command]\n\nAvailable Commands:\n set Write a specific global setting\n\nFlags:\n -h, --help help for config\n\nGlobal Flags:\n --host string Set the default host to use for the API\n --namespace string Assign the namespace you would like to use\n --scheme string Use to override default https\n\nUse \"gwa config [command] --help\" for more information about a command." }, - "credentials":{ - "clientID" :"gwa-api", - "clientSecret" :"18900468-3db1-43f7-a8af-e75f079eb742" + "credentials": { + "clientID": "gwa-api", + "clientSecret": "18900468-3db1-43f7-a8af-e75f079eb742" } } diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts index 48920a087..1014f455f 100644 --- a/e2e/cypress/support/auth-commands.ts +++ b/e2e/cypress/support/auth-commands.ts @@ -1,9 +1,6 @@ import * as jwt from 'jsonwebtoken' import HomePage from '../pageObjects/home' import LoginPage from '../pageObjects/login' -import request = require('request') -import { method } from 'cypress/types/bluebird' -import { url } from 'inspector' import NamespaceAccessPage from '../pageObjects/namespaceAccess' import _ = require('cypress/types/lodash') import { checkElementExists } from './e2e' @@ -82,9 +79,9 @@ Cypress.Commands.add('keycloakLogin', (username: string, password: string) => { cy.get(login.loginSubmitButton).click() }) -Cypress.Commands.add('getLastConsumerID',() =>{ - let id : any - cy.get('[data-testid="all-consumer-control-tbl"]').find('tr').last().find('td').first().find('a').then(($text)=>{ +Cypress.Commands.add('getLastConsumerID', () => { + let id: any + cy.get('[data-testid="all-consumer-control-tbl"]').find('tr').last().find('td').first().find('a').then(($text) => { id = $text.text() return id }) @@ -112,7 +109,7 @@ Cypress.Commands.add('resetCredential', (accessRole: string) => { }) }) -Cypress.Commands.add('getUserSessionTokenValue', (namespace: string, isNamespaceSelected?:true) => { +Cypress.Commands.add('getUserSessionTokenValue', (namespace: string, isNamespaceSelected?: true) => { const login = new LoginPage() const home = new HomePage() const na = new NamespaceAccessPage() @@ -128,7 +125,7 @@ Cypress.Commands.add('getUserSessionTokenValue', (namespace: string, isNamespace cy.login(user.credentials.username, user.credentials.password) cy.log('Logged in!') // home.useNamespace(apiTest.namespace) - if(isNamespaceSelected){ + if (isNamespaceSelected || undefined) { home.useNamespace(namespace) } cy.get('@login').then(function (xhr: any) { @@ -236,7 +233,7 @@ Cypress.Commands.add('getAccessToken', (client_id: string, client_secret: string cy.log('> Get Token') }) -Cypress.Commands.add('getServiceOrRouteID', (configType: string) => { +Cypress.Commands.add('getServiceOrRouteID', (configType: string, host: string) => { const config = configType.toLowerCase() cy.request({ method: 'GET', @@ -244,10 +241,10 @@ Cypress.Commands.add('getServiceOrRouteID', (configType: string) => { }).then((res) => { expect(res.status).to.eq(200) if (config === 'routes') { - cy.saveState(config + 'ID', Cypress._.get((Cypress._.filter(res.body.data, ["hosts", ["a-service-for-newplatform.api.gov.bc.ca"]]))[0], 'id')) + cy.saveState(config + 'ID', Cypress._.get((Cypress._.filter(res.body.data, ["hosts", [host+".api.gov.bc.ca"]]))[0], 'id')) } else { - cy.saveState(config + 'ID', Cypress._.get((Cypress._.filter(res.body.data, ["name", "a-service-for-newplatform"]))[0], 'id')) + cy.saveState(config + 'ID', Cypress._.get((Cypress._.filter(res.body.data, ["name", host]))[0], 'id')) } }) }) @@ -262,17 +259,19 @@ Cypress.Commands.add('publishApi', (fileName: string, namespace: string, flag?: () => { cy.wait(3000) cy.get('@accessTokenResponse').then((res: any) => { - const options = { - method: 'PUT', - url: Cypress.env('GWA_API_URL') + '/namespaces/' + namespace + '/gateway', - } - formDataRequest(options, res.body.access_token, fileName, requestName) - cy.wait(`@${requestName}`).then((res: any) => { - cy.wrap(res.response).as('publishAPIResponse') + cy.executeCliCommand('gwa config set --namespace ' + namespace).then((response) => { + cy.executeCliCommand('gwa config set --token ' + res.body.access_token).then((response) => { + { + assert.equal(response.stdout, "Config settings saved") + cy.executeCliCommand('gwa pg ./cypress/fixtures/' + fileName).then((response) => { + debugger + expect(response.stdout).to.contain("Gateway config published") + }) + } + }) }) }) - } - ) + }) }) }) @@ -297,8 +296,7 @@ Cypress.Commands.add('makeKongRequest', (serviceName: string, methodType: string cy.fixture('state/regen').then((creds: any) => { cy.wait(5000) let token = key - if (key==undefined) - { + if (key == undefined) { token = creds.apikey } const service = serviceName @@ -363,7 +361,7 @@ Cypress.Commands.add('updateKongPlugin', (pluginName: string, name: string, endP let endpoint if (pluginName == '') endpoint = 'plugins' - else if(id !== undefined) + else if (id !== undefined) endpoint = pluginName.toLowerCase() + '/' + id.toString() + '/' + 'plugins' endpoint = (typeof endPoint !== 'undefined') ? endPoint : endpoint body = config[name] @@ -381,7 +379,7 @@ Cypress.Commands.add('updateKongPlugin', (pluginName: string, name: string, endP Cypress.Commands.add('updateKongPluginForJSONRequest', (jsonBody: string, endPoint: string, verb = 'POST') => { cy.fixture('state/store').then((creds: any) => { let body = {} - let headers = {"content-type": "application/json", "accept": "application/json"} + let headers = { "content-type": "application/json", "accept": "application/json" } body = jsonBody return cy.request({ url: Cypress.env('KONG_CONFIG_URL') + '/' + endPoint, @@ -506,14 +504,7 @@ Cypress.Commands.add('updatePropertiesOfPluginFile', (filename: string, property obj.plugins[0].config.anonymous = propertyValue } else { - Object.keys(obj.services).forEach(function (key, index) { - if (propertyName == "methods") { - obj.services[0].routes[0].methods = propertyValue - } - else { - obj.services[0].plugins[0].config[propertyName] = propertyValue - } - }); + obj.plugins[0][propertyName] = propertyValue } const yamlString = YAML.stringify(obj, 'utf8'); cy.writeFile('cypress/fixtures/' + filename, yamlString) @@ -564,14 +555,14 @@ Cypress.Commands.add("generateKeyPair", () => { cy.writeFile('cypress/fixtures/state/jwtReGenPrivateKey_new.pem', privateKeyPem) cy.writeFile('cypress/fixtures/state/jwtReGenPublicKey_new.pub', publicKeyPem) - + }) -Cypress.Commands.add('forceVisit', (url:string) => { +Cypress.Commands.add('forceVisit', (url: string) => { cy.window().then(win => { - return win.open(url, '_self'); + return win.open(url, '_self'); }); -}); +}); const formDataRequest = ( options: formDataRequestOptions, diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts index ed1769008..a363bd272 100644 --- a/e2e/cypress/support/global.d.ts +++ b/e2e/cypress/support/global.d.ts @@ -19,7 +19,7 @@ declare namespace Cypress { preserveCookies(): void - makeKongRequest(serviceName : string, methodType : string, key?: string): Chainable + makeKongRequest(serviceName: string, methodType: string, key?: string): Chainable makeKongGatewayRequestUsingClientIDSecret(hostURL: string, methodType?: string): Chainable @@ -36,44 +36,44 @@ declare namespace Cypress { client_secret: string ): Chainable> - publishApi(fileName: string, namespace: string, flag?:boolean): Chainable> - - getServiceOrRouteID(configType: string + publishApi(fileName: string, namespace: string, flag?: boolean): Chainable> + + getServiceOrRouteID(configType: string, host: string ): Chainable> - updateKongPlugin(pluginName : string, name : string, endPoint?: string, verb?: string): Chainable> + updateKongPlugin(pluginName: string, name: string, endPoint?: string, verb?: string): Chainable> - makeKongGatewayRequest(endpoint: string, requestName:string, methodType: string): Chainable> + makeKongGatewayRequest(endpoint: string, requestName: string, methodType: string): Chainable> // generateKeystore() : Chainable - generateKeystore() : void + generateKeystore(): void - setHeaders(headerValues : any) : void + setHeaders(headerValues: any): void - setRequestBody(requestBody : any) : void + setRequestBody(requestBody: any): void - setAuthorizationToken (token : string) : void + setAuthorizationToken(token: string): void - makeAPIRequest(endPoint: string,methodType: string): Chainable> + makeAPIRequest(endPoint: string, methodType: string): Chainable> getUserSession(): Chainable> - compareJSONObjects(actualResponse: any, expectedResponse:any, indexFlag?: boolean) : Chainable> + compareJSONObjects(actualResponse: any, expectedResponse: any, indexFlag?: boolean): Chainable> - getUserSessionTokenValue(namespace: string, isNamespaceSelected?:boolean): Chainable> + getUserSessionTokenValue(namespace: string, isNamespaceSelected?: boolean): Chainable> getUserSessionResponse(): Chainable> - getTokenUsingJWKCredentials(credential: any, privateKey: any):Chainable> + getTokenUsingJWKCredentials(credential: any, privateKey: any): Chainable> - verifyToastMessage(msg: string):Chainable> + verifyToastMessage(msg: string): Chainable> - updatePluginFile (filename: string, serviceName: string, pluginFileName: string):Chainable> + updatePluginFile(filename: string, serviceName: string, pluginFileName: string): Chainable> - updateElementsInPluginFile(filename: string, elementName: string, elementValue: string):Chainable> + updateElementsInPluginFile(filename: string, elementName: string, elementValue: string): Chainable> - updatePropertiesOfPluginFile(filename: string, propertyName: any, propertyValue: any):Chainable> + updatePropertiesOfPluginFile(filename: string, propertyName: any, propertyValue: any): Chainable> keycloakLogin(username: string, password: string): Chainable @@ -81,15 +81,17 @@ declare namespace Cypress { getLastConsumerID(): Chainable - generateKeyPair() : void + generateKeyPair(): void // isProductDisplay(productName: string, expResult : boolean) :Chainable> - updateJsonValue(jsonBody: any, jsonPath: string, newValue: string, index?: number): Chainable + updateJsonValue(filePath: string, jsonPath: string, newValue: string, index?: any): Chainable updateKongPluginForJSONRequest(jsonBody: string, endPoint: string, verb?: string): Chainable> - - forceVisit (url:string): Chainable - executeCliCommand (command: string) : Chainable + forceVisit(url: string): Chainable + + executeCliCommand(command: string): Chainable + + replaceWordInJsonObject(targetWord: string, replacement: string, fileName: string): Chainable> } } diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts index 0dd525fad..b8eb2231a 100644 --- a/e2e/cypress/support/util-commands.ts +++ b/e2e/cypress/support/util-commands.ts @@ -1,5 +1,8 @@ import 'cypress-v10-preserve-cookie' import jsonpath = require('jsonpath'); +const fs = require('fs'); +const YAML = require('yamljs'); + const listOfCookies = [ 'AUTH_SESSION_ID_LEGACY', 'KC_RESTART', @@ -107,16 +110,47 @@ Cypress.Commands.add('resetState', () => { cy.log('Test state was reset') }) -Cypress.Commands.add('updateJsonValue', (jsonBody: any, jsonPath: string, newValue: string, index?: any) => { - let updatedFileContent: any - const jsonContent = JSON.parse(jsonBody); - jsonpath.apply(jsonContent, jsonPath, () => newValue); - updatedFileContent = JSON.stringify(jsonContent, null, 2); - return updatedFileContent +Cypress.Commands.add('updateJsonValue', (filePath: string, jsonPath: string, newValue: string, index?: any) => { + debugger + cy.readFile('cypress/fixtures/' + filePath).then(currState => { + debugger + + const keys = jsonPath.split('.'); // Split the keyPath using dot notation + let currentObj = currState; + + for (let i = 0; i < keys.length - 1; i++) { + const key = keys[i]; + if (!currentObj.hasOwnProperty(key) || typeof currentObj[key] !== 'object') { + return; // If any intermediate key doesn't exist or is not an object, return without updating + } + currentObj = currentObj[key]; + } + + const lastKey = keys[keys.length - 1]; + currentObj[lastKey] = newValue; + + cy.writeFile('cypress/fixtures/' + filePath, currState) + }) + + }) Cypress.Commands.add('executeCliCommand', (command: string) => { cy.exec(command, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { return response }); +}) + +Cypress.Commands.add('replaceWordInJsonObject', (targetWord: string, replacement: string, fileName: string) => { + debugger + cy.readFile('cypress/fixtures/' + fileName).then((content: any) => { + let regex = new RegExp(targetWord, 'g'); + let modifiedString = content.replace(regex, replacement); + + let obj = YAML.parse(modifiedString) + + const yamlString = YAML.stringify(obj, 'utf8'); + cy.writeFile('cypress/fixtures/' + fileName, yamlString) + }) + }) \ No newline at end of file diff --git a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts index 5e1abba9c..bdb35fc8a 100644 --- a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts +++ b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts @@ -36,7 +36,8 @@ describe('Create API Spec', () => { cy.getUserSession().then(() => { cy.get('@apiowner').then(({ namespace }: any) => { nameSpace = namespace - home.createNamespace(namespace) + // home.createNamespace(namespace) + home.useNamespace(namespace) cy.get('@login').then(function (xhr: any) { userSession = xhr.response.headers['x-auth-request-access-token'] }) @@ -44,12 +45,6 @@ describe('Create API Spec', () => { }) }) - it('Verify for invalid namespace name', () => { - cy.get('@apiowner').then(({ invalid_namespace }: any) => { - home.validateNamespaceName(invalid_namespace) - }) - }) - it('creates a new service account', () => { cy.visit(sa.path) cy.get('@apiowner').then(({ serviceAccount }: any) => { @@ -61,10 +56,10 @@ describe('Create API Spec', () => { it('publishes a new API for Dev environment to Kong Gateway', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.publishApi('service.yml', namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - }) + cy.publishApi('service-gwa.yml', namespace).then(() => { + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // }) }) }) }) @@ -89,7 +84,7 @@ describe('Create API Spec', () => { it('Verify the message when no dataset is linked to BCDC', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ product }: any) => { - pd.checkMessageForNoDataset(product.name,"health") + pd.checkMessageForNoDataset(product.name, "health") }) }) @@ -116,17 +111,19 @@ describe('Create API Spec', () => { pd.addEnvToProduct(product.name, product.test_environment.name) pd.editProductEnvironment(product.name, product.test_environment.name) pd.editProductEnvironmentConfig(product.test_environment.config) - pd.generateKongPluginConfig(product.name, product.test_environment.name,'service.yml', true) + pd.generateKongPluginConfig(product.name, product.test_environment.name, 'service.yml', true) }) }) it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ namespace }: any) => { + cy.replaceWordInJsonObject('newplatform', namespace, 'service-plugin.yml') + cy.wait(2000) cy.publishApi('service-plugin.yml', namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) @@ -134,7 +131,7 @@ describe('Create API Spec', () => { it('activate the service for Test environment', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ product }: any) => { - pd.activateService(product.name, product.test_environment.name,product.test_environment.config) + pd.activateService(product.name, product.test_environment.name, product.test_environment.config) cy.wait(3000) }) }) @@ -143,11 +140,22 @@ describe('Create API Spec', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ product }: any) => { // pd.editProductEnvironment(product.name, product.environment.name) - pd.activateService(product.name, product.environment.name,product.environment.config) + pd.activateService(product.name, product.environment.name, product.environment.config) cy.wait(3000) }) }) + it('verify status of the services using "gwa status" command', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.executeCliCommand('gwa status').then((response) => { + expect(response.stdout).to.contain(product.environment.config.serviceName); + expect(response.stdout).to.contain(product.test_environment.config.serviceName); + const wordOccurrences = (response.stdout.match(/\b200 Response\b/g) || []).length; + expect(wordOccurrences).to.equal(2) + }) + }) + }) + after(() => { cy.logout() cy.clearLocalStorage({ log: true }) diff --git a/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts b/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts index 06a133037..1769508bb 100644 --- a/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts +++ b/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts @@ -25,9 +25,11 @@ describe('Approve Pending Request without collecting credentials Spec', () => { }) it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@apiowner').then(({ namespace }: any) => { + cy.get('@access-manager').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) @@ -45,5 +47,5 @@ describe('Approve Pending Request without collecting credentials Spec', () => { cy.clearLocalStorage({ log: true }) cy.deleteAllCookies() }) - + }) \ No newline at end of file diff --git a/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts b/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts index e0a21c595..3ec9e47f0 100644 --- a/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts +++ b/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts @@ -35,9 +35,11 @@ describe('Approve Pending Request Spec', () => { }) it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@apiowner').then(({ namespace }: any) => { + cy.get('@access-manager').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) diff --git a/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts b/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts index 5658cfebc..1c4309cd6 100644 --- a/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts +++ b/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts @@ -25,9 +25,11 @@ describe('Grant Access Spec', () => { }) it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@apiowner').then(({ namespace }: any) => { + cy.get('@access-manager').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) diff --git a/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts b/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts index 8c87f4696..54cf79367 100644 --- a/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts @@ -7,6 +7,8 @@ describe('Grant appropriate permissions to team members for client credential fl const login = new LoginPage() const home = new HomePage() const na = new NamespaceAccessPage() + let userSession: any + let namespace: string before(() => { cy.visit('/') @@ -20,18 +22,37 @@ describe('Grant appropriate permissions to team members for client credential fl cy.visit(login.path) }) - it('Authenticates api owner', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) - it('Creates and activates new namespace', () => { - cy.get('@apiowner').then(({ clientCredentials }: any) => { - home.createNamespace(clientCredentials.namespace) - }) + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('create namespace using gwa cli command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.replaceWordInJsonObject('ccplatform', namespace, 'cc-service-gwa.yml') + cy.updateJsonValue('apiowner.json', 'clientCredentials.namespace', namespace) + // cy.updateJsonValue('apiowner.json', 'clientCredentials.clientIdSecret.product.environment.name.config.serviceName', 'cc-service-for-' + namespace) + cy.executeCliCommand("gwa config set --namespace " + namespace) + }); }) + it('activates new namespace', () => { + home.useNamespace(namespace) + }) + + it('Grant namespace access to access manager(Mark)', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { cy.visit(na.path) diff --git a/e2e/cypress/tests/02-client-credential-flow/03-client-cred-create-api-prod-auth-pro.cy.ts b/e2e/cypress/tests/02-client-credential-flow/03-client-cred-create-api-prod-auth-pro.cy.ts index 84170a63d..7766994a2 100644 --- a/e2e/cypress/tests/02-client-credential-flow/03-client-cred-create-api-prod-auth-pro.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/03-client-cred-create-api-prod-auth-pro.cy.ts @@ -13,7 +13,8 @@ describe('Create API, Product, and Authorization Profiles; Apply Auth Profiles t const pd = new Products() const authProfile = new AuthorizationProfile() var nameSpace: string - let userSession: string + let userSession: any + let namespace : string before(() => { cy.visit('/') @@ -27,11 +28,15 @@ describe('Create API, Product, and Authorization Profiles; Apply Auth Profiles t cy.fixture('api').as('api') cy.visit(login.path) }) - it('Authenticates api owner', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) + it('Activates namespace for client credential flow tests', () => { cy.getUserSession().then(() => { cy.get('@apiowner').then(({ clientCredentials }: any) => { @@ -54,11 +59,11 @@ describe('Create API, Product, and Authorization Profiles; Apply Auth Profiles t it('Publishes a new API to Kong Gateway', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { - cy.publishApi('cc-service.yml', clientCredentials.namespace, true).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + cy.publishApi('cc-service-gwa.yml', clientCredentials.namespace, true).then(() => { + // cy.get('@publishAPIResponse').then((res: any) => { + // // cy.log(JSON.stringify(res.body)) + // // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) @@ -107,11 +112,13 @@ describe('Create API, Product, and Authorization Profiles; Apply Auth Profiles t it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.replaceWordInJsonObject('ccplatform', clientCredentials.namespace, 'cc-service-plugin.yml') + cy.wait(2000) cy.publishApi('cc-service-plugin.yml', clientCredentials.namespace,true).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // // cy.log(JSON.stringify(res.body)) + // // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) @@ -147,11 +154,13 @@ describe('Create API, Product, and Authorization Profiles; Apply Auth Profiles t it('Applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.replaceWordInJsonObject('ccplatform', clientCredentials.namespace, 'cc-service-plugin.yml') + cy.wait(2000) cy.publishApi('cc-service-plugin.yml', clientCredentials.namespace, true).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // // cy.log(JSON.stringify(res.body)) + // // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) diff --git a/e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts index cce000c6f..29edef349 100644 --- a/e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts @@ -21,9 +21,11 @@ describe('Access manager approves developer access request for Client ID/Secret }) it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, clientCredentials }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(clientCredentials.namespace) + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.get('@access-manager').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(clientCredentials.namespace) + }) }) }) @@ -56,7 +58,7 @@ describe('Make an API request using Client ID, Secret, and Access Token', () => cy.readFile('cypress/fixtures/state/store.json').then((store_res) => { let cc = JSON.parse(store_res.clientidsecret) - + cy.getAccessToken(cc.clientId, cc.clientSecret).then(() => { cy.get('@accessTokenResponse').then((token_res: any) => { let token = token_res.body.access_token diff --git a/e2e/cypress/tests/02-client-credential-flow/07-jwt-genkp-access-approve-api-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/07-jwt-genkp-access-approve-api-rqst.cy.ts index 24adf4d1a..6ee1c408a 100644 --- a/e2e/cypress/tests/02-client-credential-flow/07-jwt-genkp-access-approve-api-rqst.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/07-jwt-genkp-access-approve-api-rqst.cy.ts @@ -18,13 +18,16 @@ describe('Access manager approves developer access request for JWT - Generated K beforeEach(() => { cy.preserveCookies() cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') // cy.visit(login.path) }) it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, clientCredentials }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(clientCredentials.namespace) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(clientCredentials.namespace) + }) }) }) diff --git a/e2e/cypress/tests/02-client-credential-flow/09-jwks-url-access-approval-api-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/09-jwks-url-access-approval-api-rqst.cy.ts index bdbf8b860..e44f75b99 100644 --- a/e2e/cypress/tests/02-client-credential-flow/09-jwks-url-access-approval-api-rqst.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/09-jwks-url-access-approval-api-rqst.cy.ts @@ -19,13 +19,16 @@ describe('Access manager approves developer access request for JWKS URL flow', ( beforeEach(() => { cy.preserveCookies() cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') // cy.visit(login.path) }) it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, clientCredentials }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(clientCredentials.namespace) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(clientCredentials.namespace) + }) }) }) diff --git a/e2e/cypress/tests/02-client-credential-flow/11-jwt-publlicKey-access-approve-api-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/11-jwt-publlicKey-access-approve-api-rqst.cy.ts index f4917dcbe..bf0886830 100644 --- a/e2e/cypress/tests/02-client-credential-flow/11-jwt-publlicKey-access-approve-api-rqst.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/11-jwt-publlicKey-access-approve-api-rqst.cy.ts @@ -4,48 +4,51 @@ import ConsumersPage from '../../pageObjects/consumers' const njwt = require('njwt') -describe('Access manager approves developer access request for JWT - Generated Key Pair authenticator', () => { - const home = new HomePage() - const login = new LoginPage() - const consumers = new ConsumersPage() +// describe('Access manager approves developer access request for JWT - Generated Key Pair authenticator', () => { +// const home = new HomePage() +// const login = new LoginPage() +// const consumers = new ConsumersPage() - before(() => { - cy.visit('/') - cy.deleteAllCookies() - cy.reload() - }) +// before(() => { +// cy.visit('/') +// cy.deleteAllCookies() +// cy.reload() +// }) - beforeEach(() => { - cy.preserveCookies() - cy.fixture('access-manager').as('access-manager') - // cy.visit(login.path) - }) +// beforeEach(() => { +// cy.preserveCookies() +// cy.fixture('access-manager').as('access-manager') +// cy.fixture('apiowner').as('apiowner') +// // cy.visit(login.path) +// }) - it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, clientCredentials }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(clientCredentials.namespace) - }) - }) +// it('Access Manager logs in', () => { +// cy.get('@access-manager').then(({ user }: any) => { +// cy.get('@apiowner').then(({ clientCredentials }: any) => { +// cy.login(user.credentials.username, user.credentials.password) +// home.useNamespace(clientCredentials.namespace) +// }) +// }) +// }) - it('Access Manager approves developer access request', () => { - cy.get('@access-manager').then(() => { - cy.visit(consumers.path) - cy.wait(5000) - consumers.reviewThePendingRequest() - }) - }) +// it('Access Manager approves developer access request', () => { +// cy.get('@access-manager').then(() => { +// cy.visit(consumers.path) +// cy.wait(5000) +// consumers.reviewThePendingRequest() +// }) +// }) - it('approves an access request', () => { - consumers.approvePendingRequest() - }) +// it('approves an access request', () => { +// consumers.approvePendingRequest() +// }) - after(() => { - cy.logout() - cy.clearLocalStorage({ log: true }) - cy.deleteAllCookies() - }) -}) +// after(() => { +// cy.logout() +// cy.clearLocalStorage({ log: true }) +// cy.deleteAllCookies() +// }) +// }) describe('Make an API request using JWT signed with private key', () => { it('Get access token using JWT key pair; make sure API calls successfully', () => { diff --git a/e2e/cypress/tests/02-client-credential-flow/cli-demo.ts b/e2e/cypress/tests/02-client-credential-flow/cli-demo.ts deleted file mode 100644 index 3c8ba7d5a..000000000 --- a/e2e/cypress/tests/02-client-credential-flow/cli-demo.ts +++ /dev/null @@ -1,137 +0,0 @@ -import LoginPage from '../../pageObjects/login' -import ApplicationPage from '../../pageObjects/applications' -import ApiDirectoryPage from '../../pageObjects/apiDirectory' -import MyAccessPage from '../../pageObjects/myAccess' -const YAML = require('yamljs'); -let userSession: any -let cli = require("../../fixtures/test_data/gwa-cli.json") - -const jose = require('node-jose') - -describe('Verify CLI commands', () => { - const login = new LoginPage() - const apiDir = new ApiDirectoryPage() - const app = new ApplicationPage() - const ma = new MyAccessPage() - let namespace : string - - before(() => { - // cy.visit('/') - cy.deleteAllCookies() - cy.reload() - }) - - beforeEach(() => { - cy.preserveCookies() - cy.fixture('apiowner').as('apiowner') - // cy.visit(login.path) - }) - - it('authenticates Janis (api owner) to get the user session token', () => { - cy.get('@apiowner').then(({ apiTest }: any) => { - cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { - userSession = value - }) - }) -}) - - it('Check for gwa help', () => { - cy.executeCliCommand('gwa help').then((response) => { - debugger - assert.equal(response.stdout, cli.content.help) - }); - }) - - it('Check gwa command for login help', () => { - cy.executeCliCommand('gwa login -h').then((response) => { - debugger - assert.equal(response.stdout, cli.content.login_help) - }); - }) - - it('Check gwa command to login with client ID and secret', () => { - let url = "oauth2proxy.localtest.me:4180" - let clientID = cli.credentials.clientID - let clientSecret = cli.credentials.clientSecret - cy.log('gwa login --host ${url} --scheme http') - cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http').then((response) => { - assert.equal(response.stdout, "Logged in") - }); - }) - - it('Check gwa command for login with invalid client id', () => { - let url = "oauth2proxy.localtest.me:4180" - let clientID = "dummy-client" - let clientSecret = cli.credentials.clientSecret - cy.exec('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stderr, "Error: INVALID_CREDENTIALS: Invalid client credentials") - }); - }) - - it('Check gwa command for login with invalid client secret', () => { - let url = "oauth2proxy.localtest.me:4180" - let clientID = cli.credentials.clientID - let clientSecret = "dummy-client-secret" - cy.exec('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stderr, "Error: Invalid client secret") - }); - }) - - it('Check gwa command for config help', () => { - cy.exec('gwa config -h', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - debugger - assert.equal(response.stdout, cli.content.config_help) - }); - }) - - it('Check gwa config command to set environment', () => { - cy.exec('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") - }); - }) - - it('Check gwa config command to set token', () => { - cy.exec('gwa config set --token '+userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") - }); - }) - - it('Check gwa command for namespace help', () => { - cy.exec('gwa namespace -h', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - debugger - assert.equal(response.stdout, cli.content.namespace_help) - }); - }) - - it('Check gwa command to create namespace', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace create --host '+url+' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.isNotNaN(response.stdout) - namespace = response.stdout - }); - }) - - it('Check gwa namespace list command and verify the created namespace in the list', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace list --host '+url+' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - expect(response.stdout).to.contain(namespace); - }); - }) - - it('Check Env Variable', () => { - // let variable = "BC Government" - // cy.exec('yq ".api_key=\"$variable\"" ~/.gwa-config.yaml',{ timeout: 3000, failOnNonZeroExit: false }).then((response) => { - // const output = response.stdout; - // cy.log('Command output:', output); - // // Perform assertions or other actions with the output - // }); - cy.readFile('/Users/nirajpatel/.gwa-config.yaml').then((content: any) => { - debugger - let obj = YAML.parse(content) - const keys = Object.keys(obj); - obj.api_key = "Test1234" - const yamlString = YAML.stringify(obj, 'utf8'); - cy.writeFile('/Users/nirajpatel/.gwa-config.yaml', yamlString) - }) - }) -}) \ No newline at end of file diff --git a/e2e/cypress/tests/03-manage-labels/02-approve-pending-rqst-for-labels.spec.cy.ts b/e2e/cypress/tests/03-manage-labels/02-approve-pending-rqst-for-labels.spec.cy.ts index 576bc21f6..acd3830b3 100644 --- a/e2e/cypress/tests/03-manage-labels/02-approve-pending-rqst-for-labels.spec.cy.ts +++ b/e2e/cypress/tests/03-manage-labels/02-approve-pending-rqst-for-labels.spec.cy.ts @@ -12,8 +12,6 @@ describe('Approve Pending Request Spec', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') }) beforeEach(() => { @@ -26,9 +24,11 @@ describe('Approve Pending Request Spec', () => { }) it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) diff --git a/e2e/cypress/tests/03-manage-labels/03-filter-labels.cy.ts b/e2e/cypress/tests/03-manage-labels/03-filter-labels.cy.ts index 15670cb68..d79910e41 100644 --- a/e2e/cypress/tests/03-manage-labels/03-filter-labels.cy.ts +++ b/e2e/cypress/tests/03-manage-labels/03-filter-labels.cy.ts @@ -12,8 +12,6 @@ describe('Filter Manage labels Spec', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') }) beforeEach(() => { @@ -27,9 +25,11 @@ describe('Filter Manage labels Spec', () => { it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) diff --git a/e2e/cypress/tests/03-manage-labels/04-manage-labels.cy.ts b/e2e/cypress/tests/03-manage-labels/04-manage-labels.cy.ts index eacbab194..e6bee8d2f 100644 --- a/e2e/cypress/tests/03-manage-labels/04-manage-labels.cy.ts +++ b/e2e/cypress/tests/03-manage-labels/04-manage-labels.cy.ts @@ -12,8 +12,6 @@ describe('Manage/Edit labels spec', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') }) beforeEach(() => { @@ -25,9 +23,11 @@ describe('Manage/Edit labels spec', () => { }) it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) @@ -57,5 +57,5 @@ describe('Manage/Edit labels spec', () => { cy.logout() cy.clearLocalStorage({ log: true }) cy.deleteAllCookies() -}) + }) }) \ No newline at end of file diff --git a/e2e/cypress/tests/03-manage-labels/05-link-consumers.ts b/e2e/cypress/tests/03-manage-labels/05-link-consumers.ts index 8bfb50601..97eea0365 100644 --- a/e2e/cypress/tests/03-manage-labels/05-link-consumers.ts +++ b/e2e/cypress/tests/03-manage-labels/05-link-consumers.ts @@ -13,8 +13,6 @@ describe('Link Consumers to Namespace', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') }) beforeEach(() => { @@ -27,9 +25,11 @@ describe('Link Consumers to Namespace', () => { }) it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) @@ -39,12 +39,9 @@ describe('Link Consumers to Namespace', () => { }) it('Get the consumer ID from the list', () => { - cy.getLastConsumerID().then((title)=>{ - consumerID = title - }) - // cy.wrap(consumers).its('inputValue').then(inputValue => { - // consumerID = inputValue.text() - // }) + cy.getLastConsumerID().then((title) => { + consumerID = title + }) }) it('Delete the consumer ID from the list', () => { @@ -61,7 +58,7 @@ describe('Link Consumers to Namespace', () => { }) it('Verify that the consumer is linked to the namespace', () => { - cy.getLastConsumerID().then((title)=>{ + cy.getLastConsumerID().then((title) => { expect(title).to.equal(consumerID) }) }) diff --git a/e2e/cypress/tests/04-gateway-services/01-gateway-service-details.cy.ts b/e2e/cypress/tests/04-gateway-services/01-gateway-service-details.cy.ts index 07401a29f..37134dcb8 100644 --- a/e2e/cypress/tests/04-gateway-services/01-gateway-service-details.cy.ts +++ b/e2e/cypress/tests/04-gateway-services/01-gateway-service-details.cy.ts @@ -6,11 +6,8 @@ import MyAccessPage from '../../pageObjects/myAccess' import NamespaceAccessPage from '../../pageObjects/namespaceAccess' describe('Verify Gateway Service details', () => { - const login = new LoginPage() - const apiDir = new ApiDirectoryPage() - const myAccessPage = new MyAccessPage() + const home = new HomePage() - const na = new NamespaceAccessPage() const gs = new GatewayServicePage() before(() => { @@ -52,7 +49,7 @@ describe('Verify Gateway Service details', () => { it('Verify the routes details ', () => { cy.get('@apiowner').then(({ product }: any) => { - gs.verifyRouteName(product.environment.config.serviceName, 'https://a-service-for-newplatform.api.gov.bc.ca/') + gs.verifyRouteName(product.environment.config.serviceName, 'https://'+product.environment.config.serviceName+'.api.gov.bc.ca/') }) }) @@ -61,7 +58,9 @@ describe('Verify Gateway Service details', () => { }) it('Verify the Tags details ', () => { - gs.verifyTagsName('ns.newplatform') + cy.get('@apiowner').then(({ namespace }: any) => { + gs.verifyTagsName('ns.'+namespace) + }) }) after(() => { diff --git a/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts b/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts index d8b566044..dcdb802a6 100644 --- a/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts +++ b/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts @@ -65,10 +65,12 @@ describe('Authernticate with old user to initiate migration', () => { }) it('authenticates with old user', () => { - cy.get('@usermigration').then(({ oldUser, namespace }: any) => { - cy.login(oldUser.credentials.username, oldUser.credentials.password) - cy.log('Logged in!') - home.useNamespace(namespace) + cy.get('@usermigration').then(({ oldUser }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(oldUser.credentials.username, oldUser.credentials.password) + cy.log('Logged in!') + home.useNamespace(namespace) + }) }) }) @@ -99,10 +101,12 @@ describe('Verify that permission of old user is migrated to new user', () => { }) it('authenticates with new user', () => { - cy.get('@usermigration').then(({ newUser, namespace }: any) => { - cy.login(newUser.credentials.username, newUser.credentials.password) - cy.log('Logged in!') - // home.useNamespace(namespace) + cy.get('@usermigration').then(({ newUser }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(newUser.credentials.username, newUser.credentials.password) + cy.log('Logged in!') + // home.useNamespace(namespace) + }) }) }) @@ -150,8 +154,8 @@ describe('Verify that old user is no longer able to sign in', () => { }) it('authenticates with old user', () => { - cy.get('@usermigration').then(({ oldUser}: any) => { - cy.login(oldUser.credentials.username, oldUser.credentials.password,true) + cy.get('@usermigration').then(({ oldUser }: any) => { + cy.login(oldUser.credentials.username, oldUser.credentials.password, true) }) }) diff --git a/e2e/cypress/tests/06-refresh-credential/02-client-credentials.cy.ts b/e2e/cypress/tests/06-refresh-credential/02-client-credentials.cy.ts index ca841ee5f..327508156 100644 --- a/e2e/cypress/tests/06-refresh-credential/02-client-credentials.cy.ts +++ b/e2e/cypress/tests/06-refresh-credential/02-client-credentials.cy.ts @@ -127,6 +127,10 @@ describe('Regenerate Credential for Client Credentials- Client ID/Secret', () => }) after(() => { + cy.get('@apiowner').then(({ product }: any) => { + cy.getServiceOrRouteID('services', product.environment.config.serviceName) + cy.getServiceOrRouteID('routes', product.environment.config.serviceName) + }) cy.logout() cy.clearLocalStorage({ log: true }) cy.deleteAllCookies() diff --git a/e2e/cypress/tests/07-manage-control/01-ip-restriction.cy.ts b/e2e/cypress/tests/07-manage-control/01-ip-restriction.cy.ts index 94d7b1c94..aed31e1d2 100644 --- a/e2e/cypress/tests/07-manage-control/01-ip-restriction.cy.ts +++ b/e2e/cypress/tests/07-manage-control/01-ip-restriction.cy.ts @@ -6,7 +6,7 @@ describe('Manage Control-IP Restriction Spec', () => { const login = new LoginPage() const home = new HomePage() const consumers = new ConsumersPage() - + before(() => { cy.visit('/') cy.deleteAllCookies() @@ -21,9 +21,11 @@ describe('Manage Control-IP Restriction Spec', () => { }) it('authenticates Mark (Access Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password).then(() => { - home.useNamespace(namespace); + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password).then(() => { + home.useNamespace(namespace); + }) }) }) }) @@ -44,7 +46,7 @@ describe('Manage Control-IP Restriction Spec', () => { consumers.setAllowedIPAddress(ipRestriction.ipRange_inValid, 'Route') }) }) - + it('verify IP Restriction error when the API calls other than the allowed IP', () => { cy.get('@apiowner').then(({ product }: any) => { cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { @@ -58,7 +60,7 @@ describe('Manage Control-IP Restriction Spec', () => { cy.get('@access-manager').then(() => { cy.visit(consumers.path); consumers.clickOnTheFirstConsumerID() - cy.get('@manage-control-config-setting').then(({ipRestriction} : any) => { + cy.get('@manage-control-config-setting').then(({ ipRestriction }: any) => { consumers.setAllowedIPAddress(ipRestriction.ipRange_inValid) }) }) @@ -77,7 +79,7 @@ describe('Manage Control-IP Restriction Spec', () => { cy.get('@access-manager').then(() => { cy.visit(consumers.path); consumers.clickOnTheFirstConsumerID() - cy.get('@manage-control-config-setting').then(({ipRestriction} : any) => { + cy.get('@manage-control-config-setting').then(({ ipRestriction }: any) => { consumers.setAllowedIPAddress(ipRestriction.ipRange_valid, "Route") }) }) @@ -95,7 +97,7 @@ describe('Manage Control-IP Restriction Spec', () => { cy.get('@access-manager').then(() => { cy.visit(consumers.path); consumers.clickOnTheFirstConsumerID() - cy.get('@manage-control-config-setting').then(({ipRestriction} : any) => { + cy.get('@manage-control-config-setting').then(({ ipRestriction }: any) => { consumers.setAllowedIPAddress(ipRestriction.ipRange_valid) }) }) @@ -151,7 +153,7 @@ describe('Manage Control -Apply IP Restriction to Global and Consumer at Service cy.get('@access-manager').then(({ user, namespace }: any) => { cy.visit(consumers.path); consumers.clickOnTheFirstConsumerID() - cy.get('@manage-control-config-setting').then(({ipRestriction} : any) => { + cy.get('@manage-control-config-setting').then(({ ipRestriction }: any) => { consumers.setAllowedIPAddress(ipRestriction.ipRange_inValid) }) }) @@ -186,7 +188,7 @@ describe('Manage Control -Apply IP Restriction to Global and Consumer at Route l consumers.filterConsumerByTypeAndValue('Products', product.name) }) }) - + it('set api ip-restriction to global service level', () => { cy.visit(consumers.path); consumers.clickOnTheFirstConsumerID() @@ -208,7 +210,7 @@ describe('Manage Control -Apply IP Restriction to Global and Consumer at Route l cy.get('@access-manager').then(({ user, namespace }: any) => { cy.visit(consumers.path); consumers.clickOnTheFirstConsumerID() - cy.get('@manage-control-config-setting').then(({ipRestriction} : any) => { + cy.get('@manage-control-config-setting').then(({ ipRestriction }: any) => { consumers.setAllowedIPAddress(ipRestriction.ipRange_inValid) }) }) diff --git a/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts b/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts index da7b5c1a4..27f15be08 100644 --- a/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts +++ b/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts @@ -24,9 +24,11 @@ describe('Manage Control-Rate Limiting Spec for Service as Scope and Local Polic }) it('authenticates Mark (Access Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password).then(() => { - home.useNamespace(namespace); + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password).then(() => { + home.useNamespace(namespace); + }) }) }) }) @@ -79,6 +81,7 @@ describe('Manage Control-Rate Limiting Spec for Route as Scope and Local Policy' cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { cy.visit(consumers.path); consumers.clickOnTheFirstConsumerID() + consumers.clearRateLimitControl() consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Route") }) }) @@ -96,175 +99,175 @@ describe('Manage Control-Rate Limiting Spec for Route as Scope and Local Policy' }) }) -describe('Manage Control-Rate Limiting Spec for Service as Scope and Redis Policy', () => { - const login = new LoginPage() - const home = new HomePage() - const consumers = new ConsumersPage() +// describe('Manage Control-Rate Limiting Spec for Service as Scope and Redis Policy', () => { +// const login = new LoginPage() +// const home = new HomePage() +// const consumers = new ConsumersPage() - beforeEach(() => { - cy.preserveCookies() - cy.fixture('access-manager').as('access-manager') - cy.fixture('apiowner').as('apiowner') - cy.fixture('manage-control-config-setting').as('manage-control-config-setting') - cy.visit(login.path) - }) - it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { - cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { - cy.visit(consumers.path); - consumers.clickOnTheFirstConsumerID() - consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Service", "Redis") - }) - }) +// beforeEach(() => { +// cy.preserveCookies() +// cy.fixture('access-manager').as('access-manager') +// cy.fixture('apiowner').as('apiowner') +// cy.fixture('manage-control-config-setting').as('manage-control-config-setting') +// cy.visit(login.path) +// }) +// it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { +// cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { +// cy.visit(consumers.path); +// consumers.clickOnTheFirstConsumerID() +// consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Service", "Redis") +// }) +// }) - it('verify rate limit error when the API calls beyond the limit', () => { - cy.get('@apiowner').then(({ product }: any) => { - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - }) - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(429) - expect(response.body.message).to.be.contain('API rate limit exceeded') - }) - }) - }) -}) +// it('verify rate limit error when the API calls beyond the limit', () => { +// cy.get('@apiowner').then(({ product }: any) => { +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(200) +// }) +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(429) +// expect(response.body.message).to.be.contain('API rate limit exceeded') +// }) +// }) +// }) +// }) -describe('Manage Control-Rate Limiting Spec for Route as Scope and Redis Policy', () => { - const login = new LoginPage() - const home = new HomePage() - const consumers = new ConsumersPage() +// describe('Manage Control-Rate Limiting Spec for Route as Scope and Redis Policy', () => { +// const login = new LoginPage() +// const home = new HomePage() +// const consumers = new ConsumersPage() - beforeEach(() => { - cy.preserveCookies() - cy.fixture('access-manager').as('access-manager') - cy.fixture('apiowner').as('apiowner') - cy.fixture('manage-control-config-setting').as('manage-control-config-setting') - cy.visit(login.path) - }) - it('set api rate limit as per the test config, Redis Policy and Scope as Route', () => { - cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { - cy.visit(consumers.path); - consumers.clickOnTheFirstConsumerID() - consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Route", "Redis") - }) - }) +// beforeEach(() => { +// cy.preserveCookies() +// cy.fixture('access-manager').as('access-manager') +// cy.fixture('apiowner').as('apiowner') +// cy.fixture('manage-control-config-setting').as('manage-control-config-setting') +// cy.visit(login.path) +// }) +// it('set api rate limit as per the test config, Redis Policy and Scope as Route', () => { +// cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { +// cy.visit(consumers.path); +// consumers.clickOnTheFirstConsumerID() +// consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Route", "Redis") +// }) +// }) - it('verify rate limit error when the API calls beyond the limit', () => { - cy.get('@apiowner').then(({ product }: any) => { - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - }) - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(429) - expect(response.body.message).to.be.contain('API rate limit exceeded') - }) - }) - }) -}) +// it('verify rate limit error when the API calls beyond the limit', () => { +// cy.get('@apiowner').then(({ product }: any) => { +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(200) +// }) +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(429) +// expect(response.body.message).to.be.contain('API rate limit exceeded') +// }) +// }) +// }) +// }) -describe('Manage Control-Apply Rate limiting to Global and Consumer at Service level ', () => { - const login = new LoginPage() - const home = new HomePage() - const consumers = new ConsumersPage() +// describe('Manage Control-Apply Rate limiting to Global and Consumer at Service level ', () => { +// const login = new LoginPage() +// const home = new HomePage() +// const consumers = new ConsumersPage() - beforeEach(() => { - cy.preserveCookies() - cy.fixture('access-manager').as('access-manager') - cy.fixture('apiowner').as('apiowner') - cy.fixture('manage-control-config-setting').as('manage-control-config-setting') - cy.visit(login.path) - }) +// beforeEach(() => { +// cy.preserveCookies() +// cy.fixture('access-manager').as('access-manager') +// cy.fixture('apiowner').as('apiowner') +// cy.fixture('manage-control-config-setting').as('manage-control-config-setting') +// cy.visit(login.path) +// }) - it('set api rate limit to global service level', () => { - cy.visit(consumers.path); - consumers.clickOnTheFirstConsumerID() - consumers.clearRateLimitControl() - cy.updateKongPlugin('services', 'rateLimiting').then((response) => { - expect(response.status).to.be.equal(201) - }) - }) +// it('set api rate limit to global service level', () => { +// cy.visit(consumers.path); +// consumers.clickOnTheFirstConsumerID() +// consumers.clearRateLimitControl() +// cy.updateKongPlugin('services', 'rateLimiting').then((response) => { +// expect(response.status).to.be.equal(201) +// }) +// }) - it('Verify that Rate limiting is set at global service level', () => { - cy.get('@apiowner').then(({ product }: any) => { - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.within(16,18) - }) - }) - }) +// it('Verify that Rate limiting is set at global service level', () => { +// cy.get('@apiowner').then(({ product }: any) => { +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(200) +// expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.within(16, 18) +// }) +// }) +// }) - it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { - cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { - cy.visit(consumers.path); - consumers.clickOnTheFirstConsumerID() - consumers.setRateLimiting(rateLimiting.requestPerHour_Global, "Service", "Redis") - }) - }) +// it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { +// cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { +// cy.visit(consumers.path); +// consumers.clickOnTheFirstConsumerID() +// consumers.setRateLimiting(rateLimiting.requestPerHour_Global, "Service", "Redis") +// }) +// }) - it('verify rate limit error when the API calls beyond the limit', () => { - cy.get('@apiowner').then(({ product }: any) => { - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - }) - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(429) - expect(response.body.message).to.be.contain('API rate limit exceeded') - }) - }) - }) -}) +// it('verify rate limit error when the API calls beyond the limit', () => { +// cy.get('@apiowner').then(({ product }: any) => { +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(200) +// }) +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(429) +// expect(response.body.message).to.be.contain('API rate limit exceeded') +// }) +// }) +// }) +// }) describe('Manage Control-Apply Rate limiting to Global and Consumer at Route level ', () => { const login = new LoginPage() const home = new HomePage() const consumers = new ConsumersPage() - beforeEach(() => { - cy.preserveCookies() - cy.fixture('access-manager').as('access-manager') - cy.fixture('apiowner').as('apiowner') - cy.fixture('manage-control-config-setting').as('manage-control-config-setting') - cy.visit(login.path) - }) +// beforeEach(() => { +// cy.preserveCookies() +// cy.fixture('access-manager').as('access-manager') +// cy.fixture('apiowner').as('apiowner') +// cy.fixture('manage-control-config-setting').as('manage-control-config-setting') +// cy.visit(login.path) +// }) - it('set api rate limit to global service level', () => { - cy.visit(consumers.path); - consumers.clickOnTheFirstConsumerID() - consumers.clearRateLimitControl() - cy.updateKongPlugin('routes', 'rateLimiting').then((response) => { - expect(response.status).to.be.equal(201) - }) - }) +// it('set api rate limit to global service level', () => { +// cy.visit(consumers.path); +// consumers.clickOnTheFirstConsumerID() +// consumers.clearRateLimitControl() +// cy.updateKongPlugin('routes', 'rateLimiting').then((response) => { +// expect(response.status).to.be.equal(201) +// }) +// }) - it('Verify that Rate limiting is set at global service level', () => { - cy.get('@apiowner').then(({ product }: any) => { - cy.wait(5000) - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.equal(18) - }) - }) - }) +// it('Verify that Rate limiting is set at global service level', () => { +// cy.get('@apiowner').then(({ product }: any) => { +// cy.wait(5000) +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(200) +// expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.equal(18) +// }) +// }) +// }) - it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { - cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { - cy.visit(consumers.path); - consumers.clickOnTheFirstConsumerID() - consumers.setRateLimiting(rateLimiting.requestPerHour_Global, "Route", "Redis") - }) - }) +// it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { +// cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { +// cy.visit(consumers.path); +// consumers.clickOnTheFirstConsumerID() +// consumers.setRateLimiting(rateLimiting.requestPerHour_Global, "Route", "Redis") +// }) +// }) - it('verify rate limit error when the API calls beyond the limit', () => { - cy.get('@apiowner').then(({ product }: any) => { - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - }) - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(429) - expect(response.body.message).to.be.contain('API rate limit exceeded') - }) - }) - }) +// it('verify rate limit error when the API calls beyond the limit', () => { +// cy.get('@apiowner').then(({ product }: any) => { +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(200) +// }) +// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { +// expect(response.status).to.be.equal(429) +// expect(response.body.message).to.be.contain('API rate limit exceeded') +// }) +// }) +// }) after(() => { cy.logout() diff --git a/e2e/cypress/tests/07-manage-control/03-kong-api-only-apply-rate-limiting.cy.ts b/e2e/cypress/tests/07-manage-control/03-kong-api-only-apply-rate-limiting.cy.ts index f3d0f283b..4c0b63f0d 100644 --- a/e2e/cypress/tests/07-manage-control/03-kong-api-only-apply-rate-limiting.cy.ts +++ b/e2e/cypress/tests/07-manage-control/03-kong-api-only-apply-rate-limiting.cy.ts @@ -64,6 +64,8 @@ describe('Apply Kong API key only plugin', () => { }) it('Set Consumer ID to key auth anonymous config', () => { + const arr_namespace = ['ns.' + nameSpace]; + cy.updatePropertiesOfPluginFile('service-plugin-key-auth-only.yml', 'tags', arr_namespace) cy.updatePropertiesOfPluginFile('service-plugin-key-auth-only.yml', 'config.anonymous', consumerID) }) @@ -80,9 +82,9 @@ describe('Apply Kong API key only plugin', () => { cy.get('@apiowner').then(({ namespace, product }: any) => { cy.updatePluginFile('service-plugin.yml', product.environment.config.serviceName, 'service-plugin-key-auth-only.yml') cy.publishApi('service-plugin.yml', namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // }) }) }) }) @@ -97,7 +99,7 @@ describe('Apply Kong API key only plugin', () => { }) it('Apply Rate limiting on free access', () => { - cy.updateKongPlugin('consumers', 'rateLimitingConsumer', 'consumers/'+consumerID+'/plugins').then((response) => { + cy.updateKongPlugin('consumers', 'rateLimitingConsumer', 'consumers/' + consumerID + '/plugins').then((response) => { expect(response.status).to.be.equal(201) }) }) @@ -115,7 +117,7 @@ describe('Check the API key for free access', () => { cy.get('@apiowner').then(async ({ product }: any) => { cy.fixture('state/store').then((creds: any) => { const key = creds.consumerKey - cy.makeKongRequest(product.environment.config.serviceName, 'GET','').then((response) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET', '').then((response) => { expect(response.status).to.be.equal(200) expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.equal(99) }) @@ -185,8 +187,6 @@ describe('Approve Pending Request Spec', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') }) beforeEach(() => { @@ -200,9 +200,11 @@ describe('Approve Pending Request Spec', () => { }) it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts new file mode 100644 index 000000000..feb7a40f2 --- /dev/null +++ b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts @@ -0,0 +1,126 @@ +import LoginPage from '../../pageObjects/login' +import ApplicationPage from '../../pageObjects/applications' +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import MyAccessPage from '../../pageObjects/myAccess' +const YAML = require('yamljs'); +let userSession: any +let cli = require("../../fixtures/test_data/gwa-cli.json") + +const jose = require('node-jose') + +describe('Verify CLI commands', () => { + const login = new LoginPage() + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const ma = new MyAccessPage() + let namespace : string + + before(() => { + // cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) + }) +}) + + // it('Check for gwa help', () => { + // cy.executeCliCommand('gwa help').then((response) => { + // debugger + // assert.equal(response.stdout, cli.content.help) + // }); + // }) + + // it('Check gwa command for login help', () => { + // cy.executeCliCommand('gwa login -h').then((response) => { + // debugger + // assert.equal(response.stdout, cli.content.login_help) + // }); + // }) + + it('Check gwa command to login with client ID and secret', () => { + let url = "oauth2proxy.localtest.me:4180" + let clientID = cli.credentials.clientID + let clientSecret = cli.credentials.clientSecret + cy.log('gwa login --host ${url} --scheme http') + cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http').then((response) => { + assert.equal(response.stdout, "Logged in") + }); + }) + + // it('Check gwa command for login with invalid client id', () => { + // let url = "oauth2proxy.localtest.me:4180" + // let clientID = "dummy-client" + // let clientSecret = cli.credentials.clientSecret + // cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http').then((response) => { + // assert.equal(response.stderr, "Error: INVALID_CREDENTIALS: Invalid client credentials") + // }); + // }) + + // it('Check gwa command for login with invalid client secret', () => { + // let url = "oauth2proxy.localtest.me:4180" + // let clientID = cli.credentials.clientID + // let clientSecret = "dummy-client-secret" + // cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http').then((response) => { + // assert.equal(response.stderr, "Error: Invalid client secret") + // }); + // }) + + // it('Check gwa command for config help', () => { + // cy.executeCliCommand('gwa config -h').then((response) => { + // debugger + // assert.equal(response.stdout, cli.content.config_help) + // }); + // }) + + it('Check gwa config command to set environment', () => { + cy.executeCliCommand('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http').then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa config command to set token', () => { + cy.executeCliCommand('gwa config set --token '+userSession).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa command for namespace help', () => { + cy.executeCliCommand('gwa namespace -h').then((response) => { + debugger + assert.equal(response.stdout, cli.content.namespace_help) + }); + }) + + it('Check gwa command to create namespace', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.executeCliCommand('gwa namespace create --host '+url+' --scheme http').then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.replaceWordInJsonObject('newplatform',namespace,'service-gwa.yml') + cy.updateJsonValue('apiowner.json','namespace' , namespace) + cy.updateJsonValue('apiowner.json','product.environment.config.serviceName' , 'a-service-for-'+namespace) + cy.updateJsonValue('apiowner.json','product.test_environment.config.serviceName' , 'a-service-for-'+namespace+'-test') + cy.executeCliCommand("gwa config set --namespace "+namespace) + }); + }) + + it('Check gwa namespace list command and verify the created namespace in the list', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.executeCliCommand('gwa namespace list --host '+url+' --scheme http').then((response) => { + expect(response.stdout).to.contain(namespace); + }); + }) + +}) \ No newline at end of file diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 01b3db0b0..5df9ae714 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -14,6 +14,7 @@ "cypress-ntlm-auth": "^4.1.2", "cypress-xpath": "^1.6.2", "dotenv": "^10.0.0", + "js-yaml": "^4.1.0", "jsonwebtoken": "^8.5.1", "lodash": "^4.17.21", "mochawesome": "^7.1.3", @@ -83,6 +84,18 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" }, + "node_modules/@atomist/yaml-updater/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -1892,6 +1905,19 @@ } } }, + "node_modules/@cypress/code-coverage/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@cypress/code-coverage/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2085,6 +2111,20 @@ "node": ">= 4" } }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -2140,6 +2180,18 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -4976,6 +5028,20 @@ "node": ">= 4" } }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/eslint/node_modules/semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -6662,17 +6728,21 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -7404,12 +7474,6 @@ "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "peer": true - }, "node_modules/mocha/node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -7426,18 +7490,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "peer": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/mocha/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -10714,6 +10766,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } } } }, @@ -12007,6 +12068,16 @@ "ms": "2.1.2" } }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -12169,6 +12240,17 @@ "dev": true, "peer": true }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -12212,6 +12294,17 @@ "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" + }, + "dependencies": { + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } } }, "@istanbuljs/schema": { @@ -14200,6 +14293,17 @@ "dev": true, "peer": true }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -15629,12 +15733,18 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + } } }, "jsbn": { @@ -16203,12 +16313,6 @@ "yargs-unparser": "2.0.0" }, "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "peer": true - }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -16219,15 +16323,6 @@ "path-exists": "^4.0.0" } }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "peer": true, - "requires": { - "argparse": "^2.0.1" - } - }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", diff --git a/e2e/package.json b/e2e/package.json index 6e1eca52b..1726f71fc 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -50,6 +50,7 @@ "cypress-ntlm-auth": "^4.1.2", "cypress-xpath": "^1.6.2", "dotenv": "^10.0.0", + "js-yaml": "^4.1.0", "jsonwebtoken": "^8.5.1", "lodash": "^4.17.21", "mochawesome": "^7.1.3", From 55ab761043d0af3933879921bd07214ba51eabb7 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 25 Jul 2023 18:03:08 -0700 Subject: [PATCH 24/81] make issuer env details optional --- src/batch/data-rules.js | 2 +- .../transformations/toStringDefaultArray.ts | 6 ++++-- src/lists/extensions/Namespace.ts | 18 ++++++++++++------ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/batch/data-rules.js b/src/batch/data-rules.js index a34147ce3..241e38969 100644 --- a/src/batch/data-rules.js +++ b/src/batch/data-rules.js @@ -474,7 +474,7 @@ const metadata = { resourceScopes: { name: 'toStringDefaultArray' }, clientRoles: { name: 'toStringDefaultArray' }, clientMappers: { name: 'toStringDefaultArray' }, - environmentDetails: { name: 'toString' }, + environmentDetails: { name: 'toStringDefaultArray' }, inheritFrom: { name: 'connectOne', list: 'allSharedIdPs', diff --git a/src/batch/transformations/toStringDefaultArray.ts b/src/batch/transformations/toStringDefaultArray.ts index 41973c2ae..1b89849e3 100644 --- a/src/batch/transformations/toStringDefaultArray.ts +++ b/src/batch/transformations/toStringDefaultArray.ts @@ -7,8 +7,10 @@ export function toStringDefaultArray( inputData: any, key: string ) { - return inputData[key] == null || - (currentData != null && currentData[key] === stringify(inputData[key])) + if (inputData[key] == null) { + return '[]'; + } + return currentData != null && currentData[key] === stringify(inputData[key]) ? null : stringify(inputData[key]); } diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index 93883984f..6523150b6 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -491,12 +491,18 @@ module.exports = { envCtx.issuerEnvConfig.issuerUrl, envCtx.accessToken ); - await permissionApi.createPermission( - rset.id, - envCtx.subjectUuid, - true, - 'Namespace.Manage' - ); + for (const scope in [ + 'Namespace.Manage', + 'CredentialIssuer.Admin', + 'GatewayConfig.Publish', + ]) { + await permissionApi.createPermission( + rset.id, + envCtx.subjectUuid, + true, + scope + ); + } } const kcGroupService = new KeycloakGroupService( From f2b94c767653bc3dfd13b5b4a52e26d8dc104962 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 25 Jul 2023 18:28:44 -0700 Subject: [PATCH 25/81] make issuer env details optional --- src/lists/extensions/Namespace.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lists/extensions/Namespace.ts b/src/lists/extensions/Namespace.ts index 6523150b6..59c815c5c 100644 --- a/src/lists/extensions/Namespace.ts +++ b/src/lists/extensions/Namespace.ts @@ -491,7 +491,7 @@ module.exports = { envCtx.issuerEnvConfig.issuerUrl, envCtx.accessToken ); - for (const scope in [ + for (const scope of [ 'Namespace.Manage', 'CredentialIssuer.Admin', 'GatewayConfig.Publish', From 805b8810ce7a9f17f08a95b1b92477b679a11735 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 25 Jul 2023 21:06:56 -0700 Subject: [PATCH 26/81] upd the batch default array --- src/batch/transformations/toStringDefaultArray.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/batch/transformations/toStringDefaultArray.ts b/src/batch/transformations/toStringDefaultArray.ts index 1b89849e3..a07fa9214 100644 --- a/src/batch/transformations/toStringDefaultArray.ts +++ b/src/batch/transformations/toStringDefaultArray.ts @@ -7,10 +7,12 @@ export function toStringDefaultArray( inputData: any, key: string ) { - if (inputData[key] == null) { + // if new and not passed, then set an empty array as a default + if (inputData[key] == null && currentData == null) { return '[]'; } - return currentData != null && currentData[key] === stringify(inputData[key]) + return inputData[key] == null || + (currentData != null && currentData[key] === stringify(inputData[key])) ? null : stringify(inputData[key]); } From 2610fa86c272dfe3be36e856b1c75c4bf1674e1b Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Wed, 26 Jul 2023 00:32:56 -0700 Subject: [PATCH 27/81] upds for handling delete namespace --- src/lists/CredentialIssuer.js | 7 ++ src/services/keycloak/client-service.ts | 5 ++ src/services/keycloak/group-service.ts | 2 +- src/services/keycloak/namespace-details.ts | 25 ++++--- src/services/workflow/client-shared-idp.ts | 76 ++++++++++++++++++++-- src/services/workflow/index.ts | 6 +- 6 files changed, 106 insertions(+), 15 deletions(-) diff --git a/src/lists/CredentialIssuer.js b/src/lists/CredentialIssuer.js index 4791d1d9d..6147b2c5b 100644 --- a/src/lists/CredentialIssuer.js +++ b/src/lists/CredentialIssuer.js @@ -26,6 +26,7 @@ const { const { syncSharedIdp, addClientsToSharedIdP, + DeleteClientsFromSharedIdP, } = require('../services/workflow'); const { Logger } = require('../logger'); const kebabCase = require('just-kebab-case'); @@ -249,6 +250,12 @@ module.exports = { }, afterDelete: async function ({ existingItem, context }) { + await DeleteClientsFromSharedIdP( + context, + existingItem.clientId, + `${existingItem.inheritFrom}` + ); + await new StructuredActivityService( context, context.authedItem['namespace'] diff --git a/src/services/keycloak/client-service.ts b/src/services/keycloak/client-service.ts index 0c8f1133b..353b44d0e 100644 --- a/src/services/keycloak/client-service.ts +++ b/src/services/keycloak/client-service.ts @@ -103,6 +103,11 @@ export class KeycloakClientService { return lkup[0]; } + public async deleteClient(id: string): Promise { + await this.kcAdminClient.clients.del({ id }); + logger.debug('[deleteClient] CID=%s SUCCESS', id); + } + public async regenerateSecret(id: string): Promise { const cred = await this.kcAdminClient.clients.generateNewClientSecret({ id, diff --git a/src/services/keycloak/group-service.ts b/src/services/keycloak/group-service.ts index db8b45b17..3e9127369 100644 --- a/src/services/keycloak/group-service.ts +++ b/src/services/keycloak/group-service.ts @@ -175,7 +175,7 @@ export class KeycloakGroupService { (group: GroupRepresentation) => group.name == groupName ).length == 0 ) { - logger.debug('[getGroup] MISSING %s', groupName); + logger.error('[getGroup] MISSING %s', groupName); return null; } else { logger.debug('[getGroup] FOUND %s', groupName); diff --git a/src/services/keycloak/namespace-details.ts b/src/services/keycloak/namespace-details.ts index ece22c7f2..d7afeafd6 100644 --- a/src/services/keycloak/namespace-details.ts +++ b/src/services/keycloak/namespace-details.ts @@ -12,6 +12,7 @@ import { getOrgPoliciesForResource, } from '../../lists/extensions/Common'; import { GWAService } from '../gwaapi'; +import { strict as assert } from 'assert'; const logger = Logger('kc.nsdetails'); @@ -35,16 +36,20 @@ export async function getAllNamespaces(envCtx: EnvironmentContext) { const client = new GWAService(process.env.GWA_API_URL); const defaultSettings = await client.getDefaultNamespaceSettings(); - return await Promise.all( - nsList.map(async (nsdata: any) => { - return backfillGroupAttributes( - nsdata.name, - nsdata, - defaultSettings, - kcGroupService - ); + return ( + await Promise.all( + nsList.map(async (nsdata: any) => { + return backfillGroupAttributes( + nsdata.name, + nsdata, + defaultSettings, + kcGroupService + ); + }) + ).catch((err: any) => { + throw err; }) - ); + ).filter((x) => Boolean(x)); } export async function getKeycloakGroupApi( @@ -67,6 +72,8 @@ export async function backfillGroupAttributes( ): Promise { const nsPermissions = await kcGroupService.getGroup('ns', ns); + assert.strictEqual(Boolean(nsPermissions), true, 'Invalid namespace'); + transformSingleValueAttributes(nsPermissions.attributes, [ 'description', 'perm-data-plane', diff --git a/src/services/workflow/client-shared-idp.ts b/src/services/workflow/client-shared-idp.ts index ac3c97138..984ee1b1e 100644 --- a/src/services/workflow/client-shared-idp.ts +++ b/src/services/workflow/client-shared-idp.ts @@ -96,10 +96,7 @@ async function addClientToSharedIdP( const environment = issuerEnvConfig.environment; - const clientId = - environment == 'prod' - ? `ap-${profileClientId}` - : `ap-${profileClientId}-${environment}`; + const clientId = genClientId(environment, profileClientId); // If there are any custom client Mappers, then include them const clientMappers: any[] = []; @@ -137,6 +134,77 @@ async function addClientToSharedIdP( }; } +/** + * When a CredentialIssuer is deleted where the inheritFrom is set + * then call this to delete the client ID on the shared IdP + * + * @param context + * @param credentialIssuerPK + */ +export async function DeleteClientsFromSharedIdP( + context: any, + profileClientId: string, + inheritFromIssuerPK: string +) { + // Find the credential issuer and based on its type, go do the appropriate action + const inheritFromIssuer: CredentialIssuer = await lookupCredentialIssuerById( + context, + inheritFromIssuerPK + ); + + assert.strictEqual( + inheritFromIssuer.isShared, + true, + 'Invalid IdP for Sharing' + ); + + const envConfigs = getAllIssuerEnvironmentConfigs(inheritFromIssuer); + + for (const issuerEnvConfig of envConfigs) { + await deleteClientFromSharedIdP(profileClientId, issuerEnvConfig); + } +} + +async function deleteClientFromSharedIdP( + profileClientId: string, + issuerEnvConfig: IssuerEnvironmentConfig +): Promise { + const openid = await getOpenidFromIssuer(issuerEnvConfig.issuerUrl); + + // token is NULL if 'iat' + // token is retrieved from doing a /token login using the provided client ID and secret if 'managed' + // issuer.initialAccessToken if 'iat' + const kctoksvc = new KeycloakTokenService(openid.token_endpoint); + + const token = + issuerEnvConfig.clientRegistration == 'anonymous' + ? null + : issuerEnvConfig.clientRegistration == 'managed' + ? await kctoksvc.getKeycloakSession( + issuerEnvConfig.clientId, + issuerEnvConfig.clientSecret + ) + : issuerEnvConfig.initialAccessToken; + + const environment = issuerEnvConfig.environment; + + const clientId = genClientId(environment, profileClientId); + + // Find the Client ID for the ProductEnvironment - that will be used to associated the clientRoles + + const cliApi = await new KeycloakClientService(issuerEnvConfig.issuerUrl); + await cliApi.login(issuerEnvConfig.clientId, issuerEnvConfig.clientSecret); + + const exists = await cliApi.isClient(clientId); + + if (exists) { + const client = await cliApi.findByClientId(clientId); + assert.strictEqual(client.clientId, clientId); + + await cliApi.deleteClient(client.id); + } +} + /** * Whenever the CredentialIssuer is updated, and inheritFrom is set, * then sync the Roles and Authz settings in the Client Registration diff --git a/src/services/workflow/index.ts b/src/services/workflow/index.ts index fb2335ac4..bb5b8627b 100644 --- a/src/services/workflow/index.ts +++ b/src/services/workflow/index.ts @@ -2,7 +2,11 @@ export { Apply } from './apply'; export { CreateServiceAccount } from './create-service-account'; -export { addClientsToSharedIdP, syncSharedIdp } from './client-shared-idp'; +export { + addClientsToSharedIdP, + DeleteClientsFromSharedIdP, + syncSharedIdp, +} from './client-shared-idp'; export { allConsumerGroupLabels, From df24602d62fefa22a152085467849ce21fa9e38d Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Wed, 26 Jul 2023 01:30:47 -0700 Subject: [PATCH 28/81] upd delete ns for issuers --- src/services/workflow/delete-namespace.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/services/workflow/delete-namespace.ts b/src/services/workflow/delete-namespace.ts index 0bfc895fd..52fe47ce0 100644 --- a/src/services/workflow/delete-namespace.ts +++ b/src/services/workflow/delete-namespace.ts @@ -130,8 +130,8 @@ export const DeleteNamespace = async ( const activity = await DeleteNamespaceRecordActivity(context, ns); - const gwaService = new GWAService(process.env.GWA_API_URL); - await gwaService.deleteAllGatewayConfiguration(subjectToken, ns); + //const gwaService = new GWAService(process.env.GWA_API_URL); + //await gwaService.deleteAllGatewayConfiguration(subjectToken, ns); const envs = await lookupEnvironmentsByNS(context, ns); const ids = envs.map((e: Environment) => e.id); @@ -146,5 +146,9 @@ export const DeleteNamespace = async ( await deleteRecords(context, 'Product', { namespace: ns }, true, ['id']); + await deleteRecords(context, 'CredentialIssuer', { namespace: ns }, true, [ + 'id', + ]); + await updateActivity(context.sudo(), activity.id, 'success', undefined); }; From aad41dda7b4ed47400c749be7b4535eb6ac4327d Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Wed, 26 Jul 2023 01:53:07 -0700 Subject: [PATCH 29/81] chg delete ns put back gw deletion --- src/services/workflow/delete-namespace.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/workflow/delete-namespace.ts b/src/services/workflow/delete-namespace.ts index 52fe47ce0..0d63d9704 100644 --- a/src/services/workflow/delete-namespace.ts +++ b/src/services/workflow/delete-namespace.ts @@ -130,8 +130,8 @@ export const DeleteNamespace = async ( const activity = await DeleteNamespaceRecordActivity(context, ns); - //const gwaService = new GWAService(process.env.GWA_API_URL); - //await gwaService.deleteAllGatewayConfiguration(subjectToken, ns); + const gwaService = new GWAService(process.env.GWA_API_URL); + await gwaService.deleteAllGatewayConfiguration(subjectToken, ns); const envs = await lookupEnvironmentsByNS(context, ns); const ids = envs.map((e: Environment) => e.id); From 1f2cb9fef0b54162d59ffad0a4d1d466cb500c7d Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 2 Aug 2023 09:54:12 -0700 Subject: [PATCH 30/81] Updated/added scenarios for GWA command and as per new namespace creation workflow --- e2e/cypress.config.ts | 2 +- e2e/cypress/fixtures/api.json | 59 +++++++--- e2e/cypress/fixtures/apiowner.json | 18 +-- .../fixtures/service-clear-resources-gwa.yml | 19 ++++ .../fixtures/service-permission-gwa.yml | 19 ++++ .../fixtures/service-plugin-key-auth-only.yml | 4 +- .../fixtures/test_data/gwa-dataset.yaml | 15 +++ .../fixtures/test_data/gwa-issuer.yaml | 12 ++ .../fixtures/test_data/gwa-product.yaml | 8 ++ e2e/cypress/pageObjects/activity.ts | 18 ++- e2e/cypress/pageObjects/apiDirectory.ts | 6 +- e2e/cypress/pageObjects/consumers.ts | 17 ++- e2e/cypress/support/auth-commands.ts | 12 +- e2e/cypress/support/global.d.ts | 4 + e2e/cypress/support/util-commands.ts | 17 +++ .../tests/01-api-key/01-create-api.cy.ts | 7 +- ...t-publlicKey-access-approve-api-rqst.cy.ts | 78 ++++++------- .../01-migrate-user-access.cy.ts | 18 +-- .../02-add-roles-authorization-profile.ts | 2 +- .../08-client-role/03-read-client-role.ts | 18 +-- .../08-client-role/04-write-client-role.ts | 16 +-- .../08-client-role/05-check-without-role.ts | 9 +- ...01-client-credential-to-kong-acl-api.cy.ts | 20 ++-- ...02-kong-acl-api-to-client-credential.cy.ts | 65 ++++++----- .../03-apply-multiple-services.cy.ts | 90 ++++++++------- .../05-keycloak-shared-IDP-config.cy.ts | 2 +- .../07-kong-public-auth.ts | 7 +- .../10-clear-resources/01-create-api.cy.ts | 68 +++++++----- .../11-activity-feed/01-activity-feed.cy.ts | 15 ++- .../02-activity-feed-failure.cy.ts | 4 + .../12-access-permission/01-create-api.cy.ts | 67 ++++++----- .../04-access-manager.cy.ts | 24 ++-- .../05-namespace-manage.cy.ts | 14 ++- .../06-credential-issuer.cy.ts | 15 ++- .../07-namespace-view.cy.ts | 15 ++- .../08-gateway-config.cy.ts | 24 ++-- ...te-application-with-approved-request.cy.ts | 12 +- .../01-create-api.cy.ts | 62 +++++------ .../01-client-cred-team-access.ts | 71 +++++++----- .../02-multiple-org-admin.ts | 38 +++++-- .../03-multiple-org-admin-org-unit.ts | 37 ++++-- .../tests/16-aps-api/01-create-api.cy.ts | 36 ++++-- .../tests/16-aps-api/02-organization.cy.ts | 2 + .../tests/16-aps-api/03-documentation.cy.ts | 50 ++++----- .../16-aps-api/05-authorizationProfiles.cy.ts | 35 +++--- .../tests/16-aps-api/06-products.cy.ts | 30 +++-- .../tests/16-aps-api/07-api-directory.cy.ts | 105 ++++++++---------- e2e/gw-config.yml | 99 +++++++++++++++++ 48 files changed, 877 insertions(+), 508 deletions(-) create mode 100644 e2e/cypress/fixtures/service-clear-resources-gwa.yml create mode 100644 e2e/cypress/fixtures/service-permission-gwa.yml create mode 100644 e2e/cypress/fixtures/test_data/gwa-dataset.yaml create mode 100644 e2e/cypress/fixtures/test_data/gwa-issuer.yaml create mode 100644 e2e/cypress/fixtures/test_data/gwa-product.yaml create mode 100644 e2e/gw-config.yml diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index e632cddcc..f5ec6c6e9 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -11,7 +11,7 @@ export default defineConfig({ // // It's IMPORTANT to return the config object // // with any changed environment variables config.specPattern=[ - './cypress/tests/18-*/*.ts', + './cypress/tests/18*/*.ts', './cypress/tests/01-*/*.ts', './cypress/tests/02-*/*.ts', './cypress/tests/06-*/*.ts', diff --git a/e2e/cypress/fixtures/api.json b/e2e/cypress/fixtures/api.json index 5ae336805..a0c0ab6fa 100644 --- a/e2e/cypress/fixtures/api.json +++ b/e2e/cypress/fixtures/api.json @@ -10,10 +10,15 @@ "title": "Planning and Innovation Division" }, "orgName": "ministry-of-health", - "expectedScope": ["Dataset.Manage", "GroupAccess.Manage", "Namespace.Assign"], + "expectedScope": [ + "Dataset.Manage", + "GroupAccess.Manage", + "Namespace.Assign" + ], "expectedNamespace": { - "name": "newplatform", - "orgUnit": "planning-and-innovation-division" + "name": "gw-6d884", + "orgUnit": "planning-and-innovation-division", + "enabled": true }, "body": { "name": "ministry-of-health", @@ -24,7 +29,9 @@ "id": "janis@idir", "email": "janis@testmail.com" }, - "roles": ["organization-admin"] + "roles": [ + "organization-admin" + ] } ] } @@ -44,7 +51,10 @@ "order": 0, "isPublic": true, "isComplete": true, - "tags": ["tag1", "tag2"] + "tags": [ + "tag1", + "tag2" + ] } }, "apiDirectory": { @@ -65,7 +75,10 @@ "title": "Dataset for Test API", "isInCatalog": "false", "isDraft": "false", - "tags": ["gateway", "kong"], + "tags": [ + "gateway", + "kong" + ], "organization": "ministry-of-health", "organizationUnit": "planning-and-innovation-division" }, @@ -76,7 +89,11 @@ "license_title": "Access Only", "view_audience": "Government", "security_class": "LOW-PUBLIC", - "tags": ["gateway", "kong", "openapi"], + "tags": [ + "gateway", + "kong", + "openapi" + ], "organization": { "name": "ministry-of-health", "title": "Ministry of Health" @@ -105,7 +122,11 @@ "license_title": "Access Only", "view_audience": "Government", "security_class": "LOW-PUBLIC", - "tags": ["gateway", "kong", "openapi"], + "tags": [ + "gateway", + "kong", + "openapi" + ], "organization": { "name": "ministry-of-health", "title": "Ministry of Health" @@ -194,8 +215,12 @@ "shared_IDP_inheritFrom": { "environmentDetails": [], "mode": "auto", - "clientRoles": ["administrator"], - "clientMappers": ["test-audience"], + "clientRoles": [ + "administrator" + ], + "clientMappers": [ + "test-audience" + ], "flow": "client-credentials", "clientAuthenticator": "client-secret", "name": "my-auth-client-secret-1", @@ -218,8 +243,12 @@ "clientId": "ap-my-auth-client-secret-1-test" } ], - "clientRoles": ["administrator"], - "clientMappers": ["test-audience"], + "clientRoles": [ + "administrator" + ], + "clientMappers": [ + "test-audience" + ], "isShared": false, "apiKeyName": "X-API-KEY", "inheritFrom": { @@ -282,11 +311,13 @@ "name": "CredentialIssuer.Admin" } ], - "permDomains": [".api.gov.bc.ca"], + "permDomains": [ + ".api.gov.bc.ca" + ], "permDataPlane": "local.dataplane", "permProtectedNs": "deny", "org": "ministry-of-health", "orgUnit": "planning-and-innovation-division" } } -} +} \ No newline at end of file diff --git a/e2e/cypress/fixtures/apiowner.json b/e2e/cypress/fixtures/apiowner.json index 3a4983496..1c37f28ad 100644 --- a/e2e/cypress/fixtures/apiowner.json +++ b/e2e/cypress/fixtures/apiowner.json @@ -6,7 +6,7 @@ "password": "awsummer" } }, - "namespace": "gw-9be47", + "namespace": "gw-79851", "invalid_namespace": [ "test_1234", "New_napespace", @@ -20,7 +20,7 @@ ] }, "deleteResources": { - "namespace": "deleteplatform", + "namespace": "gw-99365", "product": { "name": "Delete-Auto Test Product", "environment": { @@ -47,7 +47,7 @@ "terms": "Terms of Use for API Gateway", "authorization": "Kong API Key with ACL Flow", "optionalInstructions": "This is a automation test", - "serviceName": "a-service-for-gw-9be47" + "serviceName": "a-service-for-gw-79851" } }, "test_environment": { @@ -56,12 +56,12 @@ "terms": "Terms of Use for API Gateway", "authorization": "Kong API Key with ACL Flow", "optionalInstructions": "This is a automation test", - "serviceName": "a-service-for-gw-9be47-test" + "serviceName": "a-service-for-gw-79851-test" } } }, "clientCredentials": { - "namespace": "gw-a2fe3", + "namespace": "gw-2d6e6", "serviceName": "cc-service-for-platform", "Mark": { "userName": "mark", @@ -280,7 +280,7 @@ } }, "namespacePreview": { - "namespace": "previewmode", + "namespace": "gw-f04b0", "serviceAccount": { "scopes": [ "GatewayConfig.Publish", @@ -301,7 +301,7 @@ } }, "orgAssignment": { - "namespace": "orgassignment", + "namespace": "gw-a9ee0", "serviceName": "a-service-for-orgassignment", "Mark": { "userName": "mark", @@ -399,7 +399,7 @@ } }, "checkPermission": { - "namespace": "permission", + "namespace": "gw-f9d48", "serviceAccount": { "scopes": [ "GatewayConfig.Publish", @@ -543,7 +543,7 @@ } }, "apiTest": { - "namespace": "apiplatform", + "namespace": "gw-6d884", "delete_namespace": "testplatform", "product": { "name": "API Auto Test Product", diff --git a/e2e/cypress/fixtures/service-clear-resources-gwa.yml b/e2e/cypress/fixtures/service-clear-resources-gwa.yml new file mode 100644 index 000000000..11a83ad3d --- /dev/null +++ b/e2e/cypress/fixtures/service-clear-resources-gwa.yml @@ -0,0 +1,19 @@ +services: +- name: service-for-deleteplatform + host: httpbin.org + tags: [ns.deleteplatform] + port: 443 + protocol: https + retries: 0 + routes: + - name: service-for-deleteplatform-route + tags: [ns.deleteplatform] + hosts: + - service-for-deleteplatform.api.gov.bc.ca + paths: + - / + methods: + - GET + strip_path: false + https_redirect_status_code: 426 + path_handling: v0 \ No newline at end of file diff --git a/e2e/cypress/fixtures/service-permission-gwa.yml b/e2e/cypress/fixtures/service-permission-gwa.yml new file mode 100644 index 000000000..cbcf1e7c7 --- /dev/null +++ b/e2e/cypress/fixtures/service-permission-gwa.yml @@ -0,0 +1,19 @@ +services: +- name: service-for-permission + host: httpbin.org + tags: [ns.permission] + port: 443 + protocol: https + retries: 0 + routes: + - name: service-for-permission-route + tags: [ns.permission] + hosts: + - service-for-permission.api.gov.bc.ca + paths: + - / + methods: + - GET + strip_path: false + https_redirect_status_code: 426 + path_handling: v0 diff --git a/e2e/cypress/fixtures/service-plugin-key-auth-only.yml b/e2e/cypress/fixtures/service-plugin-key-auth-only.yml index 897d275a7..fb4cf9c10 100644 --- a/e2e/cypress/fixtures/service-plugin-key-auth-only.yml +++ b/e2e/cypress/fixtures/service-plugin-key-auth-only.yml @@ -2,11 +2,11 @@ plugins: - name: key-auth tags: - - ns.newplatform + - ns.gw-00479 protocols: - http - https config: key_names: - x-api-key - anonymous: 1aaf2351-0622-4cc4-8d14-32e78771e620 + anonymous: e3940e13-6231-48c5-a39a-a55dd80e8df7 diff --git a/e2e/cypress/fixtures/test_data/gwa-dataset.yaml b/e2e/cypress/fixtures/test_data/gwa-dataset.yaml new file mode 100644 index 000000000..28eb9d201 --- /dev/null +++ b/e2e/cypress/fixtures/test_data/gwa-dataset.yaml @@ -0,0 +1,15 @@ +name: gwa-auto-test-product +license_title: Open Government Licence - British Columbia +security_class: PUBLIC +view_audience: Public +download_audience: Public +record_publish_date: '2017-09-05' +notes: For Test Purpose +title: GWA Auto Test Product +tags: + - tag1 + - tag2 +organization: ministry-of-health +organizationUnit: planning-and-innovation-division +isInCatalog: true +isDraft: false \ No newline at end of file diff --git a/e2e/cypress/fixtures/test_data/gwa-issuer.yaml b/e2e/cypress/fixtures/test_data/gwa-issuer.yaml new file mode 100644 index 000000000..fb1c7a992 --- /dev/null +++ b/e2e/cypress/fixtures/test_data/gwa-issuer.yaml @@ -0,0 +1,12 @@ +name: Gold Shared IdP +description: A Shared IdP for Teams to use +flow: client-credentials +clientAuthenticator: client-secret +mode: auto +environmentDetails: + - environment: test + issuerUrl: http://keycloak.localtest.me:9080/auth/realms/master + clientRegistration: managed + clientId: gwa-api + clientSecret: 18900468-3db1-43f7-a8af-e75f079eb742 +isShared: true \ No newline at end of file diff --git a/e2e/cypress/fixtures/test_data/gwa-product.yaml b/e2e/cypress/fixtures/test_data/gwa-product.yaml new file mode 100644 index 000000000..7f233dcb7 --- /dev/null +++ b/e2e/cypress/fixtures/test_data/gwa-product.yaml @@ -0,0 +1,8 @@ +name: Auto Test Product +appId: '000000000000' +environments: + - name: dev + active: false + approval: false + flow: public + appId: '00000000' \ No newline at end of file diff --git a/e2e/cypress/pageObjects/activity.ts b/e2e/cypress/pageObjects/activity.ts index 2d1f17774..357ff8d3f 100644 --- a/e2e/cypress/pageObjects/activity.ts +++ b/e2e/cypress/pageObjects/activity.ts @@ -31,12 +31,11 @@ class ActivityPage { responseText = responseText.replaceAll("{", "${filteredResponse[index].params.") const regexp = /\${([^{]+)}/g; if (!(record.result === 'failed')) { - result = responseText.replace(regexp, function (ignore: any, key: any) { + result = responseText.replace(regexp, function (ignore: any, key: any) { return eval(key); }); } - else if(responseText.includes("Failed to Apply Workflow - IssuerMisconfigError")) - { + else if (responseText.includes("Failed to Apply Workflow - IssuerMisconfigError")) { result = 'Failed to Apply Workflow - IssuerMisconfigError: undefined' } if (result === activityText) { @@ -61,12 +60,25 @@ class ActivityPage { } loadMoreRecords() { + // cy.get(this.loadButton) + // .then(($button) => { + // cy.wrap($button).click() + // cy.wait(2000) + // debugger + // if ($button.is(':visible')) { + // // If the button is still visible, call the function again + // debugger + // this.loadMoreRecords(); + // } + // }); cy.get("body").then($body => { if ($body.find(this.loadButton).length > 0) { cy.get(this.loadButton).click({ force: true }) cy.wait(2000) + this.loadMoreRecords() } }) } + } export default ActivityPage \ No newline at end of file diff --git a/e2e/cypress/pageObjects/apiDirectory.ts b/e2e/cypress/pageObjects/apiDirectory.ts index 984129983..338b278fa 100644 --- a/e2e/cypress/pageObjects/apiDirectory.ts +++ b/e2e/cypress/pageObjects/apiDirectory.ts @@ -105,14 +105,14 @@ class ApiDirectoryPage { cy.get(this.addOrganizationBtn).click({ force: true }) } - checkOrgAdminNotificationBanner(notification: any) { + checkOrgAdminNotificationBanner(notification: any, childMessage: string) { cy.get('[data-testid="org-assignment-notification-parent"]').invoke('text').then((text) => { text = this.getPlainText(text) - assert.equal(text, notification.parent) + assert.equal(text, notification) cy.contains('button', 'Learn More').click() cy.get('[data-testid="org-assignment-notification-child"]').invoke('text').then((text) => { text = this.getPlainText(text) - assert.equal(text, notification.child) + assert.equal(text, childMessage) }) }) } diff --git a/e2e/cypress/pageObjects/consumers.ts b/e2e/cypress/pageObjects/consumers.ts index 95e50f454..445afabb0 100644 --- a/e2e/cypress/pageObjects/consumers.ts +++ b/e2e/cypress/pageObjects/consumers.ts @@ -156,8 +156,13 @@ export default class ConsumersPage { cy.get(this.consumerDialogSaveBtn, { timeout: 2000 }).should('not.exist') } - approvePendingRequest() { - cy.get(this.approveBtn).click({ force: true }) + approvePendingRequest(flag?: boolean) { + if (flag) { + cy.get(this.approveBtn).click({ force: true, multiple : true }) + } + else { + cy.get(this.approveBtn).click({ force: true }) + } cy.wait(1000) cy.verifyToastMessage("Access request approved") } @@ -339,21 +344,21 @@ export default class ConsumersPage { cy.log($row.find('td:nth-child(1)').text()) if ($row.find('td:nth-child(1)').text() == consumerID) { cy.wrap($row).find('button').first().click() - cy.get('[data-testid="consumer-delete-menuitem"]').last().click({force:true}) + cy.get('[data-testid="consumer-delete-menuitem"]').last().click({ force: true }) } }) } clickOnLinkConsumerToNamespaceBtn() { - cy.get(this.linkConsumerToNamespaceBtn).click({force:true}) + cy.get(this.linkConsumerToNamespaceBtn).click({ force: true }) } linkTheConsumerToNamespace(consumerID: any) { cy.get(this.userNameTxt).type(consumerID) - cy.get(this.linkBtn).click({force:true}) + cy.get(this.linkBtn).click({ force: true }) } - getText(){ + getText() { cy.get('[data-testid="all-consumer-control-tbl"]').find('tr').last().find('td').first().find('a').as('inputValue') } } \ No newline at end of file diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts index 1014f455f..f79ab4561 100644 --- a/e2e/cypress/support/auth-commands.ts +++ b/e2e/cypress/support/auth-commands.ts @@ -503,9 +503,19 @@ Cypress.Commands.add('updatePropertiesOfPluginFile', (filename: string, property if (propertyName === "config.anonymous") { obj.plugins[0].config.anonymous = propertyValue } - else { + else if (propertyName === "tags"){ obj.plugins[0][propertyName] = propertyValue } + else { + Object.keys(obj.services).forEach(function (key, index) { + if (propertyName == "methods") { + obj.services[0].routes[0].methods = propertyValue + } + else { + obj.services[0].plugins[0].config[propertyName] = propertyValue + } + }); + } const yamlString = YAML.stringify(obj, 'utf8'); cy.writeFile('cypress/fixtures/' + filename, yamlString) }) diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts index a363bd272..51390b46f 100644 --- a/e2e/cypress/support/global.d.ts +++ b/e2e/cypress/support/global.d.ts @@ -93,5 +93,9 @@ declare namespace Cypress { executeCliCommand(command: string): Chainable replaceWordInJsonObject(targetWord: string, replacement: string, fileName: string): Chainable> + + gwaPublish(type: string, fileName: string): Chainable> + + replaceWord(originalString: string, wordToReplace: string, replacementWord: string): Chainable } } diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts index b8eb2231a..920ba91c1 100644 --- a/e2e/cypress/support/util-commands.ts +++ b/e2e/cypress/support/util-commands.ts @@ -153,4 +153,21 @@ Cypress.Commands.add('replaceWordInJsonObject', (targetWord: string, replacement cy.writeFile('cypress/fixtures/' + fileName, yamlString) }) +}) + +Cypress.Commands.add('gwaPublish', (type: string, fileName: string) => { + cy.exec('gwa publish '+type+' --input ./cypress/fixtures/test_data/'+fileName, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + return response + }); +}) + +Cypress.Commands.add('replaceWord', (originalString: string, wordToReplace: string, replacementWord: string)=> { + // Create a regular expression with the 'g' flag for global search + let replacedString : any + const regex = new RegExp(wordToReplace, 'g'); + + // Use the 'replace()' method to replace all occurrences of the word + replacedString = originalString.replace(regex, replacementWord); + + return replacedString; }) \ No newline at end of file diff --git a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts index bdb35fc8a..606baf44e 100644 --- a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts +++ b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts @@ -64,10 +64,9 @@ describe('Create API Spec', () => { }) }) - it('creates as new product in the directory', () => { - cy.visit(pd.path) - cy.get('@apiowner').then(({ product }: any) => { - pd.createNewProduct(product.name, product.environment.name) + it('creates as new product in the directory through GWA Cli command', () => { + cy.gwaPublish('product','gwa-product.yaml').then((response:any) => { + expect(response.stdout).to.contain('Product successfully published'); }) }) diff --git a/e2e/cypress/tests/02-client-credential-flow/11-jwt-publlicKey-access-approve-api-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/11-jwt-publlicKey-access-approve-api-rqst.cy.ts index bf0886830..a0818d6f5 100644 --- a/e2e/cypress/tests/02-client-credential-flow/11-jwt-publlicKey-access-approve-api-rqst.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/11-jwt-publlicKey-access-approve-api-rqst.cy.ts @@ -4,51 +4,51 @@ import ConsumersPage from '../../pageObjects/consumers' const njwt = require('njwt') -// describe('Access manager approves developer access request for JWT - Generated Key Pair authenticator', () => { -// const home = new HomePage() -// const login = new LoginPage() -// const consumers = new ConsumersPage() +describe('Access manager approves developer access request for JWT - Generated Key Pair authenticator', () => { + const home = new HomePage() + const login = new LoginPage() + const consumers = new ConsumersPage() -// before(() => { -// cy.visit('/') -// cy.deleteAllCookies() -// cy.reload() -// }) + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('access-manager').as('access-manager') -// cy.fixture('apiowner').as('apiowner') -// // cy.visit(login.path) -// }) + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) -// it('Access Manager logs in', () => { -// cy.get('@access-manager').then(({ user }: any) => { -// cy.get('@apiowner').then(({ clientCredentials }: any) => { -// cy.login(user.credentials.username, user.credentials.password) -// home.useNamespace(clientCredentials.namespace) -// }) -// }) -// }) + it('Access Manager logs in', () => { + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(clientCredentials.namespace) + }) + }) + }) -// it('Access Manager approves developer access request', () => { -// cy.get('@access-manager').then(() => { -// cy.visit(consumers.path) -// cy.wait(5000) -// consumers.reviewThePendingRequest() -// }) -// }) + it('Access Manager approves developer access request', () => { + cy.get('@access-manager').then(() => { + cy.visit(consumers.path) + cy.wait(5000) + consumers.reviewThePendingRequest() + }) + }) -// it('approves an access request', () => { -// consumers.approvePendingRequest() -// }) + it('approves an access request', () => { + consumers.approvePendingRequest() + }) -// after(() => { -// cy.logout() -// cy.clearLocalStorage({ log: true }) -// cy.deleteAllCookies() -// }) -// }) + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) describe('Make an API request using JWT signed with private key', () => { it('Get access token using JWT key pair; make sure API calls successfully', () => { diff --git a/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts b/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts index dcdb802a6..029ee9fd8 100644 --- a/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts +++ b/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts @@ -61,6 +61,7 @@ describe('Authernticate with old user to initiate migration', () => { beforeEach(() => { cy.preserveCookies() cy.fixture('usermigration').as('usermigration') + cy.fixture('apiowner').as('apiowner') // cy.visit(login.path) }) @@ -97,22 +98,25 @@ describe('Verify that permission of old user is migrated to new user', () => { cy.preserveCookies() cy.fixture('usermigration').as('usermigration') cy.fixture('apiowner').as('apiowner') - // cy.visit(login.path) + cy.visit(login.path) }) it('authenticates with new user', () => { cy.get('@usermigration').then(({ newUser }: any) => { - cy.get('@apiowner').then(({ namespace }: any) => { - cy.login(newUser.credentials.username, newUser.credentials.password) - cy.log('Logged in!') - // home.useNamespace(namespace) - }) + cy.login(newUser.credentials.username, newUser.credentials.password) + cy.log('Logged in!') }) }) + // it('activates new namespace', () => { + // cy.get('@apiowner').then(({ namespace }: any) => { + // home.useNamespace(namespace) + // }) + // }) + it('Get the permission of the user', () => { cy.getUserSession().then(() => { - cy.get('@usermigration').then(({ namespace }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { home.useNamespace(namespace) cy.get('@login').then(function (xhr: any) { userScopes = xhr.response.body.user.scopes diff --git a/e2e/cypress/tests/08-client-role/02-add-roles-authorization-profile.ts b/e2e/cypress/tests/08-client-role/02-add-roles-authorization-profile.ts index 4a24b1262..b3094ced3 100644 --- a/e2e/cypress/tests/08-client-role/02-add-roles-authorization-profile.ts +++ b/e2e/cypress/tests/08-client-role/02-add-roles-authorization-profile.ts @@ -31,7 +31,7 @@ describe('Apply client roles to the Authorization Profile', () => { }) it('Select the namespace created for client credential ', () => { - cy.get('@credential-issuer').then(({ clientCredentials }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { home.useNamespace(clientCredentials.namespace) }) }) diff --git a/e2e/cypress/tests/08-client-role/03-read-client-role.ts b/e2e/cypress/tests/08-client-role/03-read-client-role.ts index 04cb10b6c..44d50fd85 100644 --- a/e2e/cypress/tests/08-client-role/03-read-client-role.ts +++ b/e2e/cypress/tests/08-client-role/03-read-client-role.ts @@ -79,9 +79,11 @@ describe('Access manager apply "Read" role and approves developer access request }) it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, clientCredentials }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(clientCredentials.namespace) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(clientCredentials.namespace) + }) }) }) @@ -99,7 +101,7 @@ describe('Access manager apply "Read" role and approves developer access request }) it('approves an access request', () => { - consumers.approvePendingRequest() + consumers.approvePendingRequest(true) }) after(() => { @@ -142,10 +144,10 @@ describe('Update Kong plugin and verify that only only GET method is allowed for it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { cy.publishApi('cc-service-plugin.yml', clientCredentials.namespace, true).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) diff --git a/e2e/cypress/tests/08-client-role/04-write-client-role.ts b/e2e/cypress/tests/08-client-role/04-write-client-role.ts index edbfcfcd4..060933ec4 100644 --- a/e2e/cypress/tests/08-client-role/04-write-client-role.ts +++ b/e2e/cypress/tests/08-client-role/04-write-client-role.ts @@ -79,9 +79,11 @@ describe('Access manager apply "Write" role and approves developer access reques }) it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, clientCredentials }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(clientCredentials.namespace) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(clientCredentials.namespace) + }) }) }) @@ -133,10 +135,10 @@ describe('Update Kong plugin and verify that only only PUT and POST methods are it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { cy.publishApi('cc-service-plugin.yml', clientCredentials.namespace, true).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) diff --git a/e2e/cypress/tests/08-client-role/05-check-without-role.ts b/e2e/cypress/tests/08-client-role/05-check-without-role.ts index 0a2d04402..e159768ea 100644 --- a/e2e/cypress/tests/08-client-role/05-check-without-role.ts +++ b/e2e/cypress/tests/08-client-role/05-check-without-role.ts @@ -58,11 +58,12 @@ describe('Reset Authorization profile to default (without any role)', () => { it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.replaceWordInJsonObject('ccplatform', nameSpace, 'cc-service-plugin.yml') cy.publishApi('cc-service-plugin.yml', clientCredentials.namespace,true).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) diff --git a/e2e/cypress/tests/09-update-product-env/01-client-credential-to-kong-acl-api.cy.ts b/e2e/cypress/tests/09-update-product-env/01-client-credential-to-kong-acl-api.cy.ts index 0b8e547ba..3d42867b8 100644 --- a/e2e/cypress/tests/09-update-product-env/01-client-credential-to-kong-acl-api.cy.ts +++ b/e2e/cypress/tests/09-update-product-env/01-client-credential-to-kong-acl-api.cy.ts @@ -72,10 +72,10 @@ describe('Change Authorization profile', () => { it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { cy.publishApi('cc-service-plugin.yml', clientCredentials.namespace,true).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) @@ -105,7 +105,7 @@ describe('Change Authorization profile', () => { }) }) }) - + after(() => { cy.logout() cy.clearLocalStorage({ log: true }) @@ -185,9 +185,11 @@ describe('Access manager approves developer access request for Kong API ACL auth }) it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, clientCredentials }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(clientCredentials.namespace) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(clientCredentials.namespace) + }) }) }) @@ -206,7 +208,7 @@ describe('Access manager approves developer access request for Kong API ACL auth cy.readFile('cypress/fixtures/state/store.json').then((store_cred) => { cy.get('@apiowner').then(({ clientCredentials }: any) => { let product = clientCredentials.clientIdSecret_authProfile.product - cy.makeKongRequest(product.environment.config.serviceName, 'GET',store_cred.apikey).then((response) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET', store_cred.apikey).then((response) => { cy.log(response) expect(response.status).to.be.equal(200) }) diff --git a/e2e/cypress/tests/09-update-product-env/02-kong-acl-api-to-client-credential.cy.ts b/e2e/cypress/tests/09-update-product-env/02-kong-acl-api-to-client-credential.cy.ts index 64e5684f4..dd50eed3e 100644 --- a/e2e/cypress/tests/09-update-product-env/02-kong-acl-api-to-client-credential.cy.ts +++ b/e2e/cypress/tests/09-update-product-env/02-kong-acl-api-to-client-credential.cy.ts @@ -62,7 +62,7 @@ describe('Change Authorization profile from Kong ACL-API to Client Credential', it('Deactivate the service for Test environment', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ product }: any) => { - pd.deactivateService(product.name, product.test_environment.name,product.test_environment.config) + pd.deactivateService(product.name, product.test_environment.name, product.test_environment.config) cy.wait(3000) }) }) @@ -77,27 +77,25 @@ describe('Change Authorization profile from Kong ACL-API to Client Credential', prod.environment.config.authIssuer = authProfile.name prod.environment.config.authIssuerEnv = authProfile.environmentConfig.environment pd.editProductEnvironmentConfig(prod.environment.config) - pd.generateKongPluginConfigForAuthScope(product.name, product.test_environment.name, 'service-plugin.yml',product.test_environment.config.serviceName) + pd.generateKongPluginConfigForAuthScope(product.name, product.test_environment.name, 'service-plugin.yml', product.test_environment.config.serviceName) // pd.generateKongPluginConfig(product.name, product.test_environment.name,'service-test.yml') }) }) }) it('applies authorization plugin to service published to Kong Gateway', () => { - cy.get('@apiowner').then(({ namespace }: any) => { - cy.publishApi('service-plugin.yml', nameSpace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) - }) + cy.publishApi('service-plugin.yml', nameSpace).then(() => { + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // expect(res.body.message).to.contains("Sync successful") + // }) }) }) it('activate the service for Test environment', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ product }: any) => { - pd.activateService(product.name, product.test_environment.name,product.test_environment.config) + pd.activateService(product.name, product.test_environment.name, product.test_environment.config) cy.wait(3000) }) }) @@ -193,9 +191,11 @@ describe('Access manager approves developer access request for Client ID/Secret }) it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace) + }) }) }) @@ -218,25 +218,30 @@ describe('Access manager approves developer access request for Client ID/Secret }) describe('Make an API request using Client ID, Secret, and Access Token', () => { + beforeEach(() => { + cy.fixture('apiowner').as('apiowner') + }) it('Get access token using client ID and secret; make API request', () => { cy.readFile('cypress/fixtures/state/store.json').then((store_res) => { - - let cc = JSON.parse(store_res.clientidsecret) - // let cc = JSON.parse(Cypress.env('clientidsecret')) - cy.log('cc-->' + cc.clientSecret) - cy.getAccessToken(cc.clientId, cc.clientSecret).then(() => { - cy.get('@accessTokenResponse').then((token_res: any) => { - let token = token_res.body.access_token - cy.request({ - url: Cypress.env('KONG_URL'), - headers: { - Host: 'a-service-for-newplatform-test.api.gov.bc.ca', - }, - auth: { - bearer: token, - }, - }).then((res) => { - expect(res.status).to.eq(200) + cy.get('@apiowner').then(({ product }: any) => { + let host = product.test_environment.config.serviceName+'.api.gov.bc.ca' + let cc = JSON.parse(store_res.clientidsecret) + // let cc = JSON.parse(Cypress.env('clientidsecret')) + cy.log('cc-->' + cc.clientSecret) + cy.getAccessToken(cc.clientId, cc.clientSecret).then(() => { + cy.get('@accessTokenResponse').then((token_res: any) => { + let token = token_res.body.access_token + cy.request({ + url: Cypress.env('KONG_URL'), + headers: { + Host: host, + }, + auth: { + bearer: token, + }, + }).then((res) => { + expect(res.status).to.eq(200) + }) }) }) }) diff --git a/e2e/cypress/tests/09-update-product-env/03-apply-multiple-services.cy.ts b/e2e/cypress/tests/09-update-product-env/03-apply-multiple-services.cy.ts index eff4e4eaa..6de9001f0 100644 --- a/e2e/cypress/tests/09-update-product-env/03-apply-multiple-services.cy.ts +++ b/e2e/cypress/tests/09-update-product-env/03-apply-multiple-services.cy.ts @@ -6,7 +6,8 @@ import HomePage from '../../pageObjects/home' import LoginPage from '../../pageObjects/login' import MyAccessPage from '../../pageObjects/myAccess' import Products from '../../pageObjects/products' - +let host_test: string +let host: string describe('Apply multiple services to the product environment', () => { const login = new LoginPage() @@ -60,7 +61,7 @@ describe('Apply multiple services to the product environment', () => { let authProfile = clientCredentials.clientIdSecret_KongKeyToCC.authProfile prod.environment.config.authIssuer = authProfile.name prod.environment.config.authIssuerEnv = authProfile.environmentConfig.environment - pd.editProductEnvironmentConfig(prod.environment.config, false ,false) + pd.editProductEnvironmentConfig(prod.environment.config, false, false) pd.generateKongPluginConfigForAuthScope(product.name, product.test_environment.name, 'service-plugin.yml', product.environment.config.serviceName) // pd.generateKongPluginConfig(product.name, product.test_environment.name,'service-test.yml') }) @@ -70,10 +71,10 @@ describe('Apply multiple services to the product environment', () => { it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ namespace }: any) => { cy.publishApi('service-plugin.yml', namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + // cy.get('@publishAPIResponse').then((res: any) => { + // cy.log(JSON.stringify(res.body)) + // expect(res.body.message).to.contains("Sync successful") + // }) }) }) }) @@ -96,45 +97,50 @@ describe('Apply multiple services to the product environment', () => { describe('Verify that the service is accessible using existing Client ID, Secret, and Access Token', () => { let token: string + beforeEach(() => { + cy.fixture('apiowner').as('apiowner') + }) it('Get access token using client ID and secret; make API request for test', () => { cy.readFile('cypress/fixtures/state/store.json').then((store_res) => { - - let cc = JSON.parse(store_res.clientidsecret) - // let cc = JSON.parse(Cypress.env('clientidsecret')) - cy.log('cc-->' + cc.clientSecret) - cy.getAccessToken(cc.clientId, cc.clientSecret).then(() => { - cy.get('@accessTokenResponse').then((token_res: any) => { - token = token_res.body.access_token - cy.request({ - url: Cypress.env('KONG_URL'), - headers: { - Host: 'a-service-for-newplatform-test.api.gov.bc.ca', - }, - auth: { - bearer: token, - }, - }).then((res) => { - expect(res.status).to.eq(200) + cy.get('@apiowner').then(({ product }: any) => { + host_test = product.test_environment.config.serviceName + '.api.gov.bc.ca' + host = product.environment.config.serviceName + '.api.gov.bc.ca' + let cc = JSON.parse(store_res.clientidsecret) + // let cc = JSON.parse(Cypress.env('clientidsecret')) + cy.log('cc-->' + cc.clientSecret) + cy.getAccessToken(cc.clientId, cc.clientSecret).then(() => { + cy.get('@accessTokenResponse').then((token_res: any) => { + token = token_res.body.access_token + cy.request({ + url: Cypress.env('KONG_URL'), + headers: { + Host: host_test, + }, + auth: { + bearer: token, + }, + }).then((res) => { + expect(res.status).to.eq(200) + }) }) }) }) }) - }) - it('Get access token using client ID and secret; make API request for Dev', () => { - cy.request({ - url: Cypress.env('KONG_URL'), - headers: { - Host: 'a-service-for-newplatform.api.gov.bc.ca', - }, - auth: { - bearer: token, - }, - }).then((res) => { - expect(res.status).to.eq(200) + it('Get access token using client ID and secret; make API request for Dev', () => { + cy.request({ + url: Cypress.env('KONG_URL'), + headers: { + Host: host, + }, + auth: { + bearer: token, + }, + }).then((res) => { + expect(res.status).to.eq(200) + }) }) }) - }) @@ -212,9 +218,11 @@ describe('Access manager approves developer access request for Client ID/Secret }) it('Access Manager logs in', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace) + }) }) }) @@ -250,7 +258,7 @@ describe('Verify that the service is accessible using new Client ID, Secret, and cy.request({ url: Cypress.env('KONG_URL'), headers: { - Host: 'a-service-for-newplatform-test.api.gov.bc.ca', + Host: host_test, }, auth: { bearer: token, @@ -267,7 +275,7 @@ describe('Verify that the service is accessible using new Client ID, Secret, and cy.request({ url: Cypress.env('KONG_URL'), headers: { - Host: 'a-service-for-newplatform.api.gov.bc.ca', + Host: host, }, auth: { bearer: token, diff --git a/e2e/cypress/tests/09-update-product-env/05-keycloak-shared-IDP-config.cy.ts b/e2e/cypress/tests/09-update-product-env/05-keycloak-shared-IDP-config.cy.ts index 48e92d978..7b38cefae 100644 --- a/e2e/cypress/tests/09-update-product-env/05-keycloak-shared-IDP-config.cy.ts +++ b/e2e/cypress/tests/09-update-product-env/05-keycloak-shared-IDP-config.cy.ts @@ -42,7 +42,7 @@ describe('Apply Shared IDP config at Keycloak user group', () => { }) it('Edit the namespace from the tree view', () => { - cy.get('@admin').then(({ namespace }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { cy.contains(namespace).click() userGroups.clickOnEditButton() }) diff --git a/e2e/cypress/tests/09-update-product-env/07-kong-public-auth.ts b/e2e/cypress/tests/09-update-product-env/07-kong-public-auth.ts index 12a48b816..39115b439 100644 --- a/e2e/cypress/tests/09-update-product-env/07-kong-public-auth.ts +++ b/e2e/cypress/tests/09-update-product-env/07-kong-public-auth.ts @@ -70,11 +70,8 @@ describe('Verify for Kong Public Auth', () => { it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ clientCredentials }: any) => { - cy.publishApi('cc-service.yml', clientCredentials.namespace,true).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) + cy.publishApi('cc-service-gwa.yml', clientCredentials.namespace,true).then((response:any) => { + expect(response.stdout).to.contain('Sync successful'); }) }) }) diff --git a/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts b/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts index d531bc523..c1b826d7c 100644 --- a/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts +++ b/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts @@ -8,8 +8,8 @@ describe('Create API Spec for Delete Resources', () => { const home = new HomePage() const sa = new ServiceAccountsPage() const pd = new Products() - var nameSpace: string - let userSession: string + let userSession: any + let namespace: string before(() => { cy.visit('/') @@ -22,25 +22,37 @@ describe('Create API Spec for Delete Resources', () => { cy.preserveCookies() cy.fixture('apiowner').as('apiowner') cy.fixture('api').as('api') - // cy.visit(login.path) + cy.visit(login.path) }) - it('authenticates Janis (api owner)', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) - it('creates and activates new namespace', () => { - cy.getUserSession().then(() => { - cy.get('@apiowner').then(({ deleteResources }: any) => { - nameSpace = deleteResources.namespace - home.createNamespace(deleteResources.namespace) - cy.get('@login').then(function (xhr: any) { - userSession = xhr.response.headers['x-auth-request-access-token'] - }) - }) - }) + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('create namespace using gwa cli command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.replaceWordInJsonObject('ns.deleteplatform', 'ns.' + namespace, 'service-clear-resources-gwa.yml') + cy.updateJsonValue('apiowner.json', 'deleteResources.namespace', namespace) + // cy.updateJsonValue('apiowner.json', 'clientCredentials.clientIdSecret.product.environment.name.config.serviceName', 'cc-service-for-' + namespace) + cy.executeCliCommand("gwa config set --namespace " + namespace) + }); + }) + + it('activates new namespace', () => { + home.useNamespace(namespace) }) it('creates a new service account', () => { @@ -53,13 +65,12 @@ describe('Create API Spec for Delete Resources', () => { it('publishes a new API to Kong Gateway', () => { cy.get('@apiowner').then(({ deleteResources }: any) => { - cy.publishApi('service-clear-resources.yml', deleteResources.namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - }) + cy.publishApi('service-clear-resources-gwa.yml', namespace).then((response: any) => { + expect(response.stdout).to.contain('Sync successful'); }) }) }) + it('creates as new product in the directory', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ deleteResources }: any) => { @@ -71,7 +82,7 @@ describe('Create API Spec for Delete Resources', () => { cy.get('@api').then(({ organization }: any) => { cy.setHeaders(organization.headers) cy.setAuthorizationToken(userSession) - cy.makeAPIRequest(organization.endPoint + '/' + organization.orgName + '/' + organization.orgExpectedList.name + '/namespaces/' + nameSpace, 'PUT').then((response) => { + cy.makeAPIRequest(organization.endPoint + '/' + organization.orgName + '/' + organization.orgExpectedList.name + '/namespaces/' + namespace, 'PUT').then((response) => { expect(response.status).to.be.equal(200) }) }) @@ -84,23 +95,22 @@ describe('Create API Spec for Delete Resources', () => { pd.updateDatasetNameToCatelogue(deleteResources.product.name, deleteResources.product.environment.name) }) }) - + it('publish product to directory', () => { cy.visit(sa.path) cy.visit(pd.path) cy.get('@apiowner').then(({ deleteResources }: any) => { pd.editProductEnvironment(deleteResources.product.name, deleteResources.product.environment.name) pd.editProductEnvironmentConfig(deleteResources.product.environment.config) - pd.generateKongPluginConfig(deleteResources.product.name, deleteResources.product.environment.name,'service-clear-resources.yml') + pd.generateKongPluginConfig(deleteResources.product.name, deleteResources.product.environment.name, 'service-clear-resources.yml') }) }) it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ deleteResources }: any) => { - cy.publishApi('service-clear-resources-plugin.yml', deleteResources.namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - }) + cy.replaceWordInJsonObject('ns.deleteplatform', 'ns.' + namespace, 'service-clear-resources-plugin.yml') + cy.publishApi('service-clear-resources-plugin.yml', namespace).then((response: any) => { + expect(response.stdout).to.contain('Sync successful'); }) }) }) @@ -108,14 +118,14 @@ describe('Create API Spec for Delete Resources', () => { it('activate the service for Dev environment', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ deleteResources }: any) => { - pd.activateService(deleteResources.product.name, deleteResources.product.environment.name,deleteResources.product.environment.config) + pd.activateService(deleteResources.product.name, deleteResources.product.environment.name, deleteResources.product.environment.config) cy.wait(3000) }) }) after(() => { cy.logout() - cy.clearLocalStorage({log:true}) + cy.clearLocalStorage({ log: true }) cy.deleteAllCookies() }) }) diff --git a/e2e/cypress/tests/11-activity-feed/01-activity-feed.cy.ts b/e2e/cypress/tests/11-activity-feed/01-activity-feed.cy.ts index 83c376ebb..58bbff630 100644 --- a/e2e/cypress/tests/11-activity-feed/01-activity-feed.cy.ts +++ b/e2e/cypress/tests/11-activity-feed/01-activity-feed.cy.ts @@ -106,26 +106,33 @@ describe('Verify the Activity filter for users', () => { // cy.visit(login.path) }) + it('activates new namespace', () => { + cy.get('@apiowner').then(({ namespace }: any) => { + home.useNamespace(namespace) + }) + }) + + it('Navigate to activity page', () => { cy.visit(activity.path) }) it('Verify Activity filter for "Janis Smith" user', () => { - activity.checkActivityFilter("User","Janis Smith", response) + activity.checkActivityFilter("User", "Janis Smith", response) }) it('Verify Activity filter for "Harley Jones" user', () => { - activity.checkActivityFilter("User","Harley Jones", response) + activity.checkActivityFilter("User", "Harley Jones", response) }) it('Verify Activity filter for "Mark F Mark L" user', () => { - activity.checkActivityFilter("User","Mark F Mark L", response) + activity.checkActivityFilter("User", "Mark F Mark L", response) }) it('Verify Activities filter for consumer', () => { cy.readFile('cypress/fixtures/state/regen.json').then((store) => { let consumerID = store.consumernumber - activity.checkActivityFilter("Consumer",consumerID, response) + activity.checkActivityFilter("Consumer", consumerID, response) }) }) }) \ No newline at end of file diff --git a/e2e/cypress/tests/11-activity-feed/02-activity-feed-failure.cy.ts b/e2e/cypress/tests/11-activity-feed/02-activity-feed-failure.cy.ts index a7c69dc4e..d1535a836 100644 --- a/e2e/cypress/tests/11-activity-feed/02-activity-feed-failure.cy.ts +++ b/e2e/cypress/tests/11-activity-feed/02-activity-feed-failure.cy.ts @@ -112,6 +112,10 @@ describe('Create API, Product, and Authorization Profiles; Apply Auth Profiles t cy.visit(activity.path) }) + it('Load all the records by click on "Load More" button', () => { + activity.loadMoreRecords() + }) + it('Verify Activity filter foe all the listed activities', () => { activity.checkActivityFilter("User", "", response) }) diff --git a/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts b/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts index ed7f07ab5..e42411a3f 100644 --- a/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts +++ b/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts @@ -8,8 +8,8 @@ describe('Create API Spec', () => { const home = new HomePage() const sa = new ServiceAccountsPage() const pd = new Products() - var nameSpace: string - let userSession: string + let userSession: any + let namespace: string before(() => { cy.visit('/') @@ -25,22 +25,34 @@ describe('Create API Spec', () => { cy.visit(login.path) }) - it('authenticates Janis (api owner)', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) - it('creates and activates new namespace', () => { - cy.getUserSession().then(() => { - cy.get('@apiowner').then(({ checkPermission }: any) => { - nameSpace = checkPermission.namespace - home.createNamespace(checkPermission.namespace) - cy.get('@login').then(function (xhr: any) { - userSession = xhr.response.headers['x-auth-request-access-token'] - }) - }) - }) + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('create namespace using gwa cli command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.replaceWordInJsonObject('ns.permission', 'ns.' + namespace, 'service-permission-gwa.yml') + cy.updateJsonValue('apiowner.json', 'checkPermission.namespace', namespace) + // cy.updateJsonValue('apiowner.json', 'clientCredentials.clientIdSecret.product.environment.name.config.serviceName', 'cc-service-for-' + namespace) + cy.executeCliCommand("gwa config set --namespace " + namespace) + }); + }) + + it('activates new namespace', () => { + home.useNamespace(namespace) }) it('creates a new service account', () => { @@ -52,12 +64,8 @@ describe('Create API Spec', () => { }) it('publishes a new API to Kong Gateway', () => { - cy.get('@apiowner').then(({ checkPermission }: any) => { - cy.publishApi('service-permission.yml', checkPermission.namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - }) - }) + cy.publishApi('service-permission-gwa.yml', namespace).then((response: any) => { + expect(response.stdout).to.contain('Sync successful'); }) }) @@ -72,7 +80,7 @@ describe('Create API Spec', () => { cy.get('@api').then(({ organization }: any) => { cy.setHeaders(organization.headers) cy.setAuthorizationToken(userSession) - cy.makeAPIRequest(organization.endPoint + '/' + organization.orgName + '/' + organization.orgExpectedList.name + '/namespaces/' + nameSpace, 'PUT').then((response) => { + cy.makeAPIRequest(organization.endPoint + '/' + organization.orgName + '/' + organization.orgExpectedList.name + '/namespaces/' + namespace, 'PUT').then((response) => { expect(response.status).to.be.equal(200) }) }) @@ -84,28 +92,27 @@ describe('Create API Spec', () => { pd.updateDatasetNameToCatelogue(checkPermission.product.name, checkPermission.product.environment.name) }) }) - + it('publish product to directory', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ checkPermission }: any) => { pd.editProductEnvironment(checkPermission.product.name, checkPermission.product.environment.name) pd.editProductEnvironmentConfig(checkPermission.product.environment.config) - pd.generateKongPluginConfig(checkPermission.product.name, checkPermission.product.environment.name,'service-permission.yml') + pd.generateKongPluginConfig(checkPermission.product.name, checkPermission.product.environment.name, 'service-permission.yml') }) }) it('applies authorization plugin to service published to Kong Gateway', () => { - cy.get('@apiowner').then(({ checkPermission }: any) => { - cy.publishApi('service-permission.yml', checkPermission.namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - }) - }) + cy.replaceWordInJsonObject('ns.permission', 'ns.' + namespace, 'service-permission-plugin.yml') + cy.replaceWordInJsonObject('ns.permission', 'ns.' + namespace, 'service-permission.yml') + cy.publishApi('service-permission-plugin.yml', namespace).then((res: any) => { + expect(res.stdout).to.contain('Sync successful'); }) }) after(() => { cy.logout() - cy.clearLocalStorage({log:true}) + cy.clearLocalStorage({ log: true }) cy.deleteAllCookies() }) }) diff --git a/e2e/cypress/tests/12-access-permission/04-access-manager.cy.ts b/e2e/cypress/tests/12-access-permission/04-access-manager.cy.ts index cb8a1166e..47a0a6668 100644 --- a/e2e/cypress/tests/12-access-permission/04-access-manager.cy.ts +++ b/e2e/cypress/tests/12-access-permission/04-access-manager.cy.ts @@ -51,7 +51,7 @@ describe('Verify that Mark is able to view the pending request', () => { const consumers = new ConsumersPage() const mp = new MyProfilePage() const na = new NamespaceAccessPage() - + before(() => { cy.visit('/') @@ -62,24 +62,28 @@ describe('Verify that Mark is able to view the pending request', () => { beforeEach(() => { cy.preserveCookies() cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') }) it('Authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, checkPermission }: any) => { - cy.visit(login.path) - cy.login(user.credentials.username, user.credentials.password) - cy.log('Logged in!') - home.useNamespace(checkPermission.namespace) - cy.visit(mp.path) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({checkPermission}: any) => { + cy.visit(login.path) + cy.login(user.credentials.username, user.credentials.password) + cy.log('Logged in!') + debugger + home.useNamespace(checkPermission.namespace) + cy.visit(mp.path) + }) }) }) - it('Navigate to Consumer Page to see the Approve Request option', ()=> { + it('Navigate to Consumer Page to see the Approve Request option', () => { cy.visit(consumers.path) }) - it('Verify that the option to approve request is displayed', ()=> { - consumers.isApproveAccessEnabled(true) + it('Verify that the option to approve request is displayed', () => { + consumers.isApproveAccessEnabled(true) }) after(() => { diff --git a/e2e/cypress/tests/12-access-permission/05-namespace-manage.cy.ts b/e2e/cypress/tests/12-access-permission/05-namespace-manage.cy.ts index 6453ed1ed..cb489c8e8 100644 --- a/e2e/cypress/tests/12-access-permission/05-namespace-manage.cy.ts +++ b/e2e/cypress/tests/12-access-permission/05-namespace-manage.cy.ts @@ -72,12 +72,14 @@ describe('Verify that Wendy is able to see all the options for the Namespace', ( }) it('Authenticates Wendy (Credential-Issuer)', () => { - cy.get('@credential-issuer').then(({ user, checkPermission }: any) => { - cy.visit(login.path) - cy.login(user.credentials.username, user.credentials.password) - cy.log('Logged in!') - home.useNamespace(checkPermission.namespace) - cy.visit(mp.path) + cy.get('@credential-issuer').then(({ user }: any) => { + cy.get('@apiowner').then(({ checkPermission }: any) => { + cy.visit(login.path) + cy.login(user.credentials.username, user.credentials.password) + cy.log('Logged in!') + home.useNamespace(checkPermission.namespace) + cy.visit(mp.path) + }) }) }) diff --git a/e2e/cypress/tests/12-access-permission/06-credential-issuer.cy.ts b/e2e/cypress/tests/12-access-permission/06-credential-issuer.cy.ts index aae608930..24efcdd65 100644 --- a/e2e/cypress/tests/12-access-permission/06-credential-issuer.cy.ts +++ b/e2e/cypress/tests/12-access-permission/06-credential-issuer.cy.ts @@ -66,15 +66,18 @@ describe('Verify that Wendy is able to generate authorization profile', () => { beforeEach(() => { cy.preserveCookies() cy.fixture('credential-issuer').as('credential-issuer') + cy.fixture('apiowner').as('apiowner') }) it('Authenticates Wendy (Credential-Issuer)', () => { - cy.get('@credential-issuer').then(({ user, checkPermission }: any) => { - cy.visit(login.path) - cy.login(user.credentials.username, user.credentials.password) - cy.log('Logged in!') - home.useNamespace(checkPermission.namespace) - cy.visit(mp.path) + cy.get('@credential-issuer').then(({ user }: any) => { + cy.get('@apiowner').then(({ checkPermission }: any) => { + cy.visit(login.path) + cy.login(user.credentials.username, user.credentials.password) + cy.log('Logged in!') + home.useNamespace(checkPermission.namespace) + cy.visit(mp.path) + }) }) }) diff --git a/e2e/cypress/tests/12-access-permission/07-namespace-view.cy.ts b/e2e/cypress/tests/12-access-permission/07-namespace-view.cy.ts index 1155bd1ab..f97827918 100644 --- a/e2e/cypress/tests/12-access-permission/07-namespace-view.cy.ts +++ b/e2e/cypress/tests/12-access-permission/07-namespace-view.cy.ts @@ -65,15 +65,18 @@ describe('Verify that Mark is unable to create service account', () => { cy.preserveCookies() cy.fixture('credential-issuer').as('credential-issuer') cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') }) it('authenticates Mark', () => { - cy.get('@access-manager').then(({ user, checkPermission }: any) => { - cy.visit(login.path) - cy.login(user.credentials.username, user.credentials.password) - cy.log('Logged in!') - home.useNamespace(checkPermission.namespace) - cy.visit(mp.path) + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ checkPermission }: any) => { + cy.visit(login.path) + cy.login(user.credentials.username, user.credentials.password) + cy.log('Logged in!') + home.useNamespace(checkPermission.namespace) + cy.visit(mp.path) + }) }) }) diff --git a/e2e/cypress/tests/12-access-permission/08-gateway-config.cy.ts b/e2e/cypress/tests/12-access-permission/08-gateway-config.cy.ts index 7f41fefd0..c10b06cb7 100644 --- a/e2e/cypress/tests/12-access-permission/08-gateway-config.cy.ts +++ b/e2e/cypress/tests/12-access-permission/08-gateway-config.cy.ts @@ -68,25 +68,25 @@ describe('Verify that Wendy is able to generate authorization profile', () => { beforeEach(() => { cy.preserveCookies() cy.fixture('credential-issuer').as('credential-issuer') + cy.fixture('apiowner').as('apiowner') }) it('Authenticates Wendy (Credential-Issuer)', () => { - cy.get('@credential-issuer').then(({ user, checkPermission }: any) => { - cy.visit(login.path) - cy.login(user.credentials.username, user.credentials.password) - cy.log('Logged in!') - home.useNamespace(checkPermission.namespace) - cy.visit(mp.path) + cy.get('@credential-issuer').then(({ user }: any) => { + cy.get('@apiowner').then(({ checkPermission }: any) => { + cy.visit(login.path) + cy.login(user.credentials.username, user.credentials.password) + cy.log('Logged in!') + home.useNamespace(checkPermission.namespace) + cy.visit(mp.path) + }) }) }) it('Verify that GWA API allows user to publish the API to Kong gateway', () => { - cy.get('@credential-issuer').then(({ checkPermission }: any) => { - cy.publishApi('service-permission.yml', checkPermission.namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - expect(JSON.stringify(res.body.message)).to.be.contain('Sync successful.') - expect(res.statusCode).to.be.equal(200) - }) + cy.get('@apiowner').then(({ checkPermission }: any) => { + cy.publishApi('service-permission.yml', checkPermission.namespace).then((response: any) => { + expect(response.stdout).to.contain('Sync successful'); }) }) }) diff --git a/e2e/cypress/tests/13-delete-application/03-delete-application-with-approved-request.cy.ts b/e2e/cypress/tests/13-delete-application/03-delete-application-with-approved-request.cy.ts index b1c91207c..ad189ce02 100644 --- a/e2e/cypress/tests/13-delete-application/03-delete-application-with-approved-request.cy.ts +++ b/e2e/cypress/tests/13-delete-application/03-delete-application-with-approved-request.cy.ts @@ -62,8 +62,8 @@ describe('Approve Pending Request Spec', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') + // cy.getServiceOrRouteID('services') + // cy.getServiceOrRouteID('routes') }) beforeEach(() => { @@ -76,9 +76,11 @@ describe('Approve Pending Request Spec', () => { }) it('authenticates Mark (Access-Manager)', () => { - cy.get('@access-manager').then(({ user, namespace }: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(namespace); + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) }) }) diff --git a/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts b/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts index 7011be473..67319b24f 100644 --- a/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts +++ b/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts @@ -8,8 +8,8 @@ describe('Create API Spec', () => { const home = new HomePage() const sa = new ServiceAccountsPage() const pd = new Products() - var nameSpace: string - let userSession: string + let userSession: any + let namespace: string before(() => { cy.visit('/') @@ -25,22 +25,33 @@ describe('Create API Spec', () => { cy.visit(login.path) }) - it('authenticates Janis (api owner)', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) - it('creates and activates new namespace', () => { - cy.getUserSession().then(() => { - cy.get('@apiowner').then(({ namespacePreview }: any) => { - nameSpace = namespacePreview.namespace - home.createNamespace(namespacePreview.namespace) - cy.get('@login').then(function (xhr: any) { - userSession = xhr.response.headers['x-auth-request-access-token'] - }) - }) - }) + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('create namespace using gwa cli command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.updateJsonValue('apiowner.json', 'namespacePreview.namespace', namespace) + // cy.updateJsonValue('apiowner.json', 'clientCredentials.clientIdSecret.product.environment.name.config.serviceName', 'cc-service-for-' + namespace) + cy.executeCliCommand("gwa config set --namespace " + namespace) + }); + }) + + it('activates new namespace', () => { + home.useNamespace(namespace) }) it('creates a new service account', () => { @@ -51,16 +62,6 @@ describe('Create API Spec', () => { sa.saveServiceAcctCreds() }) - it('publishes a new API to Kong Gateway', () => { - cy.get('@apiowner').then(({ namespacePreview }: any) => { - cy.publishApi('service-permission.yml', namespacePreview.namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - }) - }) - }) - }) - it('creates as new product in the directory', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ namespacePreview }: any) => { @@ -75,18 +76,9 @@ describe('Create API Spec', () => { }) }) - it('applies authorization plugin to service published to Kong Gateway', () => { - cy.get('@apiowner').then(({ namespacePreview }: any) => { - cy.publishApi('service-permission.yml', namespacePreview.namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - }) - }) - }) - }) - after(() => { cy.logout() - cy.clearLocalStorage({log:true}) + cy.clearLocalStorage({ log: true }) cy.deleteAllCookies() }) }) diff --git a/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts b/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts index 6ac09b0c5..0cb0c509d 100644 --- a/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts +++ b/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts @@ -8,6 +8,7 @@ import Products from '../../pageObjects/products' import ServiceAccountsPage from '../../pageObjects/serviceAccounts' import MyAccessPage from '../../pageObjects/myAccess' import ConsumersPage from '../../pageObjects/consumers' +let namespace: string describe('Add Organization to publish API', () => { const login = new LoginPage() @@ -16,6 +17,8 @@ describe('Add Organization to publish API', () => { const pd = new Products() const sa = new ServiceAccountsPage() const apiDir = new ApiDirectoryPage() + let userSession: any + before(() => { cy.visit('/') @@ -27,20 +30,36 @@ describe('Add Organization to publish API', () => { beforeEach(() => { cy.preserveCookies() cy.fixture('apiowner').as('apiowner') - // cy.visit(login.path) + cy.visit(login.path) }) - it('Authenticates api owner', () => { - cy.get('@apiowner').then(({ user, orgAssignment }: any) => { - cy.login(user.credentials.username, user.credentials.password) - // home.useNamespace(orgAssignment.namespace) + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) - it('Creates and activates new namespace', () => { - cy.get('@apiowner').then(({ orgAssignment }: any) => { - home.createNamespace(orgAssignment.namespace) - }) + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('create namespace using gwa cli command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.updateJsonValue('apiowner.json', 'orgAssignment.namespace', namespace) + // cy.updateJsonValue('apiowner.json', 'clientCredentials.clientIdSecret.product.environment.name.config.serviceName', 'cc-service-for-' + namespace) + cy.executeCliCommand("gwa config set --namespace " + namespace) + }); + }) + + it('activates new namespace', () => { + home.useNamespace(namespace) }) it('creates a new service account', () => { @@ -76,13 +95,9 @@ describe('Add Organization to publish API', () => { }) it('applies authorization plugin to service published to Kong Gateway', () => { - cy.get('@apiowner').then(({ orgAssignment }: any) => { - cy.publishApi('org-service-plugin.yml', orgAssignment.namespace).then(() => { - cy.get('@publishAPIResponse').then((res: any) => { - cy.log(JSON.stringify(res.body)) - expect(res.body.message).to.contains("Sync successful") - }) - }) + cy.replaceWordInJsonObject('ns.orgassignment', 'ns.' + namespace, 'org-service-plugin.yml') + cy.publishApi('org-service-plugin.yml', namespace).then((response: any) => { + expect(response.stdout).to.contain('Sync successful'); }) }) @@ -107,7 +122,9 @@ describe('Add Organization to publish API', () => { it('Verify Organization Administrator notification banner', () => { cy.visit(apiDir.path) cy.get('@apiowner').then(({ orgAssignment }: any) => { - apiDir.checkOrgAdminNotificationBanner(orgAssignment.orgAdminNotification) + cy.replaceWord(orgAssignment.orgAdminNotification.parent, 'orgassignment', namespace).then((updatedNotification: string) => { + apiDir.checkOrgAdminNotificationBanner(updatedNotification, orgAssignment.orgAdminNotification.child) + }) }) }) @@ -138,15 +155,13 @@ describe('Org Admin approves the request', () => { }) it('Authenticates Product Owner', () => { - cy.get('@product-owner').then(({ user, namespace }: any) => { + cy.get('@product-owner').then(({ user }: any) => { cy.login(user.credentials.username, user.credentials.password) }) }) it('Select the namespace', () => { - cy.get('@product-owner').then(({ namespace }: any) => { - home.useNamespace(namespace) - }) + home.useNamespace(namespace) }) it('Clik on Enable Publishing option from Namespace Page', () => { @@ -188,9 +203,9 @@ describe('Activate the API to make it visible in API Directory', () => { }) it('Authenticates api owner', () => { - cy.get('@apiowner').then(({ user, orgAssignment }: any) => { + cy.get('@apiowner').then(({ user }: any) => { cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(orgAssignment.namespace) + home.useNamespace(namespace) }) }) @@ -217,7 +232,7 @@ describe('Activate the API to make it visible in API Directory', () => { cy.get('@apiowner').then(({ orgAssignment }: any) => { let product = orgAssignment.product.name // cy.contains('button').click() - apiDir.isProductDisplay(product,true) + apiDir.isProductDisplay(product, true) }) }) @@ -299,11 +314,9 @@ describe('Access manager approves developer access request for Kong API ACL auth }) it('Access Manager logs in', () => { - cy.get('@apiowner').then(({ orgAssignment }: any) => { - cy.get('@access-manager').then(({ user}: any) => { - cy.login(user.credentials.username, user.credentials.password) - home.useNamespace(orgAssignment.namespace) - }) + cy.get('@access-manager').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace) }) }) diff --git a/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts b/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts index ecf53ccb7..5e5a0d6e1 100644 --- a/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts +++ b/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts @@ -64,6 +64,9 @@ describe('Multiple Org Adming for the organization', () => { const pd = new Products() const sa = new ServiceAccountsPage() const apiDir = new ApiDirectoryPage() + const login = new LoginPage() + let userSession: any + let namespace: any before(() => { cy.visit('/') @@ -75,21 +78,40 @@ describe('Multiple Org Adming for the organization', () => { beforeEach(() => { cy.preserveCookies() cy.fixture('apiowner').as('apiowner') - // cy.visit(login.path) + cy.visit(login.path) }) - it('Authenticates api owner', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) - it('Creates and activates new namespace', () => { - cy.get('@apiowner').then(({ orgAssignmentMultipleAdmin }: any) => { - home.createNamespace(orgAssignmentMultipleAdmin.namespace) - }) + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('create namespace using gwa cli command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.updateJsonValue('apiowner.json', 'orgAssignment.namespace', namespace) + // cy.updateJsonValue('apiowner.json', 'clientCredentials.clientIdSecret.product.environment.name.config.serviceName', 'cc-service-for-' + namespace) + cy.executeCliCommand("gwa config set --namespace " + namespace) + }); + }) + + it('activates new namespace', () => { + home.useNamespace(namespace) }) + it('creates a new service account', () => { cy.visit(sa.path) cy.get('@apiowner').then(({ serviceAccount }: any) => { diff --git a/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts b/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts index 512a0987a..bcb4d214d 100644 --- a/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts +++ b/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts @@ -81,6 +81,9 @@ describe('Multiple Org Admin for the organization', () => { const pd = new Products() const sa = new ServiceAccountsPage() const apiDir = new ApiDirectoryPage() + const login = new LoginPage() + let userSession: any + let namespace: any before(() => { cy.visit('/') @@ -92,20 +95,36 @@ describe('Multiple Org Admin for the organization', () => { beforeEach(() => { cy.preserveCookies() cy.fixture('apiowner').as('apiowner') - // cy.visit(login.path) + cy.visit(login.path) }) - it('Authenticates api owner', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) - it('Creates and activates new namespace', () => { - cy.get('@apiowner').then(({ orgAssignmentOrgUnit }: any) => { - home.createNamespace(orgAssignmentOrgUnit.namespace) - // home.useNamespace(orgAssignmentMultipleAdmin.namespace) - }) + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('create namespace using gwa cli command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.updateJsonValue('apiowner.json', 'orgAssignment.namespace', namespace) + // cy.updateJsonValue('apiowner.json', 'clientCredentials.clientIdSecret.product.environment.name.config.serviceName', 'cc-service-for-' + namespace) + cy.executeCliCommand("gwa config set --namespace " + namespace) + }); + }) + + it('activates new namespace', () => { + home.useNamespace(namespace) }) it('creates a new service account', () => { diff --git a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts b/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts index 3f314bd82..8e3deac24 100644 --- a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts +++ b/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts @@ -8,6 +8,8 @@ describe('Create API Spec', () => { const home = new HomePage() const sa = new ServiceAccountsPage() const pd = new Products() + let userSession: any + let namespace: any before(() => { cy.visit('/') @@ -22,20 +24,36 @@ describe('Create API Spec', () => { cy.visit(login.path) }) - it('authenticates Janis (api owner)', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) }) - it('creates and activates new namespace', () => { - cy.get('@apiowner').then(({ apiTest }: any) => { - home.createNamespace(apiTest.namespace) - // home.createNamespace(apiTest.delete_namespace) - }) + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('create namespace using gwa cli command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.updateJsonValue('apiowner.json', 'apiTest.namespace', namespace) + cy.updateJsonValue('api.json', 'organization.expectedNamespace.name', namespace) + // cy.updateJsonValue('apiowner.json', 'clientCredentials.clientIdSecret.product.environment.name.config.serviceName', 'cc-service-for-' + namespace) + cy.executeCliCommand("gwa config set --namespace " + namespace) + }); + }) + + it('activates new namespace', () => { + home.useNamespace(namespace) }) - after(() => { cy.logout() cy.clearLocalStorage({log:true}) diff --git a/e2e/cypress/tests/16-aps-api/02-organization.cy.ts b/e2e/cypress/tests/16-aps-api/02-organization.cy.ts index feb5a92a4..73056e444 100644 --- a/e2e/cypress/tests/16-aps-api/02-organization.cy.ts +++ b/e2e/cypress/tests/16-aps-api/02-organization.cy.ts @@ -145,6 +145,7 @@ describe('Get the Namespace associated with the organization', () => { it('Get the resource and verify the success code in the response', () => { cy.get('@api').then(({ organization }: any) => { cy.makeAPIRequest(organization.endPoint + '/' + organization.orgName + '/namespaces', 'GET').then((res) => { + debugger expect(res.status).to.be.equal(200) response = res.body nameSpace = response[0].name @@ -156,6 +157,7 @@ describe('Get the Namespace associated with the organization', () => { cy.get('@api').then(({ organization }: any) => { expectedResponse = organization.expectedNamespace // assert.isTrue(Cypress._.isEqual(response, expectedResponse)) + debugger cy.compareJSONObjects(response, expectedResponse, true) }) }) diff --git a/e2e/cypress/tests/16-aps-api/03-documentation.cy.ts b/e2e/cypress/tests/16-aps-api/03-documentation.cy.ts index b41c52f69..9f749ba12 100644 --- a/e2e/cypress/tests/16-aps-api/03-documentation.cy.ts +++ b/e2e/cypress/tests/16-aps-api/03-documentation.cy.ts @@ -2,7 +2,8 @@ import HomePage from "../../pageObjects/home" import LoginPage from "../../pageObjects/login" let userSession: any let slugValue: string - +let namespace: string +let updatedDocumentEndPoint: string describe('Get the user session token', () => { const login = new LoginPage() @@ -24,6 +25,7 @@ describe('Get the user session token', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.getUserSessionTokenValue(apiTest.namespace).then((value) => { userSession = value + namespace = apiTest.namespace }) }) }) @@ -48,8 +50,11 @@ describe('API Tests for Updating documentation', () => { it('Put the resource and verify the success code in the response', () => { cy.get('@api').then(({ documentation }: any) => { - cy.makeAPIRequest(documentation.endPoint, 'PUT').then((response) => { - expect(response.status).to.be.equal(200) + cy.replaceWord(documentation.endPoint, 'apiplatform', namespace).then((updatedEndPoint: string) => { + updatedDocumentEndPoint = updatedEndPoint + cy.makeAPIRequest(updatedDocumentEndPoint, 'PUT').then((response) => { + expect(response.status).to.be.equal(200) + }) }) }) }) @@ -74,12 +79,10 @@ describe('API Tests for Fetching documentation', () => { }) it('Get the resource and verify the success code in the response', () => { - cy.get('@api').then(({ documentation }: any) => { - cy.makeAPIRequest(documentation.endPoint, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - slugValue = res.body[0].slug - response = res.body[0] - }) + cy.makeAPIRequest(updatedDocumentEndPoint, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + slugValue = res.body[0].slug + response = res.body[0] }) }) @@ -109,19 +112,16 @@ describe('API Tests for Deleting documentation', () => { }) it('Verify the status code and response message for invalid slugvalue', () => { - cy.get('@api').then(({ documentation }: any) => { - cy.makeAPIRequest(documentation.endPoint + '/platform_test', 'DELETE').then((response) => { - expect(response.status).to.be.oneOf([404, 422]) - expect(response.body.message).to.be.equal("Content not found") - }) + cy.makeAPIRequest(updatedDocumentEndPoint + '/platform_test', 'DELETE').then((response) => { + expect(response.status).to.be.oneOf([404, 422]) + expect(response.body.message).to.be.equal("Content not found") }) }) + it('Delete the documentation', () => { - cy.get('@api').then(({ documentation }: any) => { - cy.makeAPIRequest(documentation.endPoint + '/' + slugValue, 'DELETE').then((response) => { - expect(response.status).to.be.equal(200) - }) + cy.makeAPIRequest(updatedDocumentEndPoint + '/' + slugValue, 'DELETE').then((response) => { + expect(response.status).to.be.equal(200) }) }) }) @@ -144,11 +144,9 @@ describe('API Tests to verify no value in Get call after deleting document conte }) it('Delete the documentation', () => { - cy.get('@api').then(({ documentation }: any) => { - cy.makeAPIRequest(documentation.endPoint, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - expect(response.body).to.be.empty - }) + cy.makeAPIRequest(updatedDocumentEndPoint, 'GET').then((response) => { + expect(response.status).to.be.equal(200) + expect(response.body).to.be.empty }) }) }) @@ -180,10 +178,8 @@ describe('API Tests to verify Get documentation content', () => { }) it('Put the resource and verify the success code in the response', () => { - cy.get('@api').then(({ documentation }: any) => { - cy.makeAPIRequest(documentation.endPoint, 'PUT').then((response) => { - expect(response.status).to.be.equal(200) - }) + cy.makeAPIRequest(updatedDocumentEndPoint, 'PUT').then((response) => { + expect(response.status).to.be.equal(200) }) }) diff --git a/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts b/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts index a75bd2580..6261b1e47 100644 --- a/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts +++ b/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts @@ -2,6 +2,8 @@ import HomePage from "../../pageObjects/home" import LoginPage from "../../pageObjects/login" let userSession: any let testData = require("../../fixtures/test_data/authorizationProfile.json") +let namespace: string +let updatedAuthProfileEndPoint: string describe('Get the user session token', () => { @@ -24,6 +26,7 @@ describe('Get the user session token', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.getUserSessionTokenValue(apiTest.namespace).then((value) => { userSession = value + namespace = apiTest.namespace }) }) }) @@ -50,18 +53,19 @@ testData.forEach((testCase: any) => { it('Put the resource and verify the success code in the response', () => { cy.get('@api').then(({ authorizationProfiles }: any) => { - cy.makeAPIRequest(authorizationProfiles.endPoint, 'PUT').then((response) => { - expect(response.status).to.be.equal(200) + cy.replaceWord(authorizationProfiles.endPoint, 'apiplatform', namespace).then((updatedEndPoint: string) => { + updatedAuthProfileEndPoint = updatedEndPoint + cy.makeAPIRequest(updatedAuthProfileEndPoint, 'PUT').then((response) => { + expect(response.status).to.be.equal(200) + }) }) }) }) it('Get the resource and verify the success code in the response', () => { - cy.get('@api').then(({ authorizationProfiles }: any) => { - cy.makeAPIRequest(authorizationProfiles.endPoint, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - response = res.body - }) + cy.makeAPIRequest(updatedAuthProfileEndPoint, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body }) }) @@ -74,19 +78,16 @@ testData.forEach((testCase: any) => { }) it('Delete the authorization profile', () => { - cy.get('@api').then(({ authorizationProfiles }: any) => { - cy.makeAPIRequest(authorizationProfiles.endPoint + '/' + testCase.body.name, 'DELETE').then((response) => { - expect(response.status).to.be.equal(200) - }) + cy.makeAPIRequest(updatedAuthProfileEndPoint + '/' + testCase.body.name, 'DELETE').then((response) => { + expect(response.status).to.be.equal(200) }) }) + it('Verify that the authorization profile is deleted', () => { - cy.get('@api').then(({ authorizationProfiles }: any) => { - cy.makeAPIRequest(authorizationProfiles.endPoint, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - expect(response.body.length).to.be.equal(0) - }) + cy.makeAPIRequest(updatedAuthProfileEndPoint, 'GET').then((response) => { + expect(response.status).to.be.equal(200) + expect(response.body.length).to.be.equal(0) }) }) }) @@ -100,7 +101,7 @@ testData.forEach((testCase: any) => { describe('API Tests for Authorization Profiles created with inheritFrom attribute set to a valid shared Issuer', () => { let response: any - let actualResponse: any + let actualResponse: any let expectedResponse: any beforeEach(() => { diff --git a/e2e/cypress/tests/16-aps-api/06-products.cy.ts b/e2e/cypress/tests/16-aps-api/06-products.cy.ts index f9e69a7f5..0b9053cb1 100644 --- a/e2e/cypress/tests/16-aps-api/06-products.cy.ts +++ b/e2e/cypress/tests/16-aps-api/06-products.cy.ts @@ -4,6 +4,8 @@ import Products from "../../pageObjects/products" let userSession: any let productID: string let envID: string +let updatedProductEndPoint: string +let namespace: string describe('Get the user session token to check ', () => { @@ -27,6 +29,7 @@ describe('Get the user session token to check ', () => { cy.get('@apiowner').then(({ user, apiTest }: any) => { cy.login(user.credentials.username, user.credentials.password) home.useNamespace(apiTest.namespace) + namespace = apiTest.namespace cy.get('@login').then(function (xhr: any) { userSession = xhr.response.headers['x-auth-request-access-token'] }) @@ -56,20 +59,24 @@ describe('API Tests for Updating Products', () => { it('Put the resource and verify the success code in the response', () => { cy.get('@api').then(({ products }: any) => { - cy.makeAPIRequest(products.endPoint, 'PUT').then((response) => { - expect(response.status).to.be.equal(200) + cy.replaceWord(products.endPoint, 'apiplatform', namespace).then((updatedEndPoint: string) => { + updatedProductEndPoint = updatedEndPoint + cy.makeAPIRequest(updatedProductEndPoint, 'PUT').then((response) => { + expect(response.status).to.be.equal(200) + }) }) }) }) it('Get the resource and verify the success code and product name in the response', () => { cy.get('@api').then(({ products }: any) => { - cy.makeAPIRequest(products.endPoint, 'GET').then((res) => { + cy.makeAPIRequest(updatedProductEndPoint, 'GET').then((res) => { expect(res.status).to.be.equal(200) let index = res.body.findIndex((x: { name: string }) => x.name === products.body.name) response = res.body[index] productID = res.body[index].appId envID = res.body[index].environments[0].appId + debugger }) }) }) @@ -102,6 +109,7 @@ describe('Verify that created Product is displayed in UI', () => { it('authenticates Janis (api owner) to get the user session token', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.getUserSessionTokenValue(apiTest.namespace).then((value) => { + home.useNamespace(apiTest.namespace) userSession = value }) }) @@ -134,15 +142,17 @@ describe('API Tests for Delete Products', () => { it('Delete the product environment and verify the success code in the response', () => { cy.get('@api').then(({ products }: any) => { - cy.makeAPIRequest(products.deleteEnvironmentEndPoint + '/' + envID, 'Delete').then((response) => { - expect(response.status).to.be.equal(200) + cy.replaceWord(products.deleteEnvironmentEndPoint, 'apiplatform', namespace).then((updatedEndPoint: string) => { + cy.makeAPIRequest(updatedEndPoint + '/' + envID, 'Delete').then((response) => { + expect(response.status).to.be.equal(200) + }) }) }) }) it('Get the resource and verify that product environment is deleted', () => { cy.get('@api').then(({ products }: any) => { - cy.makeAPIRequest(products.endPoint, 'GET').then((res) => { + cy.makeAPIRequest(updatedProductEndPoint, 'GET').then((res) => { expect(res.status).to.be.equal(200) let index = res.body.findIndex((x: { name: string }) => x.name === products.body.name) expect(res.body[index].environments).to.be.empty @@ -151,16 +161,14 @@ describe('API Tests for Delete Products', () => { }) it('Delete the product and verify the success code in the response', () => { - cy.get('@api').then(({ products }: any) => { - cy.makeAPIRequest(products.endPoint + '/' + productID, 'Delete').then((response) => { - expect(response.status).to.be.equal(200) - }) + cy.makeAPIRequest(updatedProductEndPoint + '/' + productID, 'Delete').then((response) => { + expect(response.status).to.be.equal(200) }) }) it('Get the resource and verify that product is deleted', () => { cy.get('@api').then(({ products }: any) => { - cy.makeAPIRequest(products.endPoint, 'GET').then((res) => { + cy.makeAPIRequest(updatedProductEndPoint, 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body assert.equal(response.findIndex((x: { name: string }) => x.name === products.body.name), -1) diff --git a/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts b/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts index ce6c1311f..57f84b8d4 100644 --- a/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts +++ b/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts @@ -2,7 +2,8 @@ import HomePage from "../../pageObjects/home" import LoginPage from "../../pageObjects/login" let userSession: any let slugValue: string - +let namespace: string +let updatedApiDirectoryEndPoint: string describe('Get the user session token', () => { const login = new LoginPage() @@ -24,6 +25,7 @@ describe('Get the user session token', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.getUserSessionTokenValue(apiTest.namespace).then((value) => { userSession = value + namespace = apiTest.namespace }) }) }) @@ -53,8 +55,11 @@ describe('API Tests for Updating dataset', () => { it('Put the resource (/organization/{org}/datasets) and verify the success code in the response', () => { cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets', 'PUT').then((response) => { - expect(response.status).to.be.equal(200) + cy.replaceWord(apiDirectory.endPoint, 'apiplatform', namespace).then((updatedEndPoint: string) => { + updatedApiDirectoryEndPoint = updatedEndPoint + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets', 'PUT').then((response) => { + expect(response.status).to.be.equal(200) + }) }) }) }) @@ -62,7 +67,7 @@ describe('API Tests for Updating dataset', () => { it('Get the resource (/organization/{org}/datasets/{name}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + apiTest.namespace + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body }) @@ -78,10 +83,8 @@ describe('API Tests for Updating dataset', () => { it('Put the resource (/namespaces/{ns}/datasets/{name}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ apiTest }: any) => { - cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/datasets', 'PUT').then((response) => { - expect(response.status).to.be.equal(200) - }) + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + apiTest.namespace + '/datasets', 'PUT').then((response) => { + expect(response.status).to.be.equal(200) }) }) }) @@ -89,7 +92,7 @@ describe('API Tests for Updating dataset', () => { it('Get the resource (/namespaces/{ns}/datasets/{name}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + apiTest.namespace + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body }) @@ -104,12 +107,10 @@ describe('API Tests for Updating dataset', () => { }) it('Get the resource (/organizations/{org}/datasets/{name}) and verify the success code in the response', () => { - cy.get('@apiowner').then(({ apiTest }: any) => { - cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - response = res.body - }) + cy.get('@api').then(({ apiDirectory, organization }: any) => { + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body }) }) }) @@ -121,12 +122,10 @@ describe('API Tests for Updating dataset', () => { }) it('Get the resource (/organizations/{org}/datasets) and verify the success code in the response', () => { - cy.get('@apiowner').then(({ apiTest }: any) => { - cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/', 'GET').then((res) => { - expect(res.status).to.be.equal(200) - response = res.body - }) + cy.get('@api').then(({ organization }: any) => { + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets/', 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body }) }) }) @@ -138,13 +137,11 @@ describe('API Tests for Updating dataset', () => { }) it('Get the directory details (/directory) and verify the success code in the response', () => { - cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.directoryEndPoint, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - response = res.body - directoryID = res.body[0].id - directoryName = res.body[0].name - }) + cy.makeAPIRequest(updatedApiDirectoryEndPoint, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body + directoryID = res.body[0].id + directoryName = res.body[0].name }) }) @@ -155,34 +152,28 @@ describe('API Tests for Updating dataset', () => { }) it('Get the directory details by its ID (/directory/{id}) and verify the success code in the response', () => { - cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.directoryEndPoint + '/' + directoryID, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - expect(res.body.name).to.be.equal(directoryName) - }) + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + directoryID, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body.name).to.be.equal(directoryName) }) }) it('Get the namespace directory details (/namespaces/{ns}/directory) and verify the success code and empty response for the namespace with no directory', () => { cy.get('@apiowner').then(({ apiTest }: any) => { - cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/directory', 'GET').then((res) => { - expect(res.status).to.be.equal(200) - expect(res.body).to.be.empty - }) + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + apiTest.namespace + '/directory', 'GET').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body).to.be.empty }) }) }) it('Get the namespace directory details (/namespaces/{ns}/directory) and verify the success code in the response', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory', 'GET').then((res) => { - expect(res.status).to.be.equal(200) - response = res.body[0] - directoryID = res.body[0].id - directoryName = res.body[0].name - }) + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + namespace + '/directory', 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body[0] + directoryID = res.body[0].id + directoryName = res.body[0].name }) }) }) @@ -195,38 +186,32 @@ describe('API Tests for Updating dataset', () => { it('Get the namespace directory details by its ID (/namespaces/{ns}/directory/{id}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory' + '/' + directoryID, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - expect(res.body.name).to.be.equal(directoryName) - }) + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + namespace + '/directory' + '/' + directoryID, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body.name).to.be.equal(directoryName) }) }) }) it('Get the namespace directory details (/namespaces/{ns}/directory/{id}) for non exist directory ID and verify the response code', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory' + '/99', 'GET').then((res) => { - expect(res.status).to.be.oneOf([404, 422]) - }) + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + namespace + '/directory' + '/99', 'GET').then((res) => { + expect(res.status).to.be.oneOf([404, 422]) }) }) }) it('Delete the dataset (/organizations/{org}/datasets/{name}) and verify the success code in the response', () => { - cy.get('@apiowner').then(({ apiTest }: any) => { - cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'DELETE').then((res) => { - expect(res.status).to.be.equal(200) - }) + cy.get('@api').then(({ apiDirectory, organization }: any) => { + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'DELETE').then((res) => { + expect(res.status).to.be.equal(200) }) }) }) it('Verify that deleted dataset does not display in Get dataset list', () => { cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/', 'GET').then((res) => { + cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets/', 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body expect(response).to.not.contain(apiDirectory.body.name) diff --git a/e2e/gw-config.yml b/e2e/gw-config.yml new file mode 100644 index 000000000..71a68a0b8 --- /dev/null +++ b/e2e/gw-config.yml @@ -0,0 +1,99 @@ +kind: Namespace +name: gw-6d884 +displayName: gw-6d884 Display Name +--- +kind: GatewayService +name: my-service-dev +tags: [ns.gw-6d884] +host: httpbin.org +port: 443 +protocol: https +retries: 0 +routes: + - name: my-service-dev + tags: [ns.gw-6d884] + hosts: + - my-service.dev.api.gov.bc.ca + methods: + - GET + strip_path: false + https_redirect_status_code: 426 + path_handling: v0 + request_buffering: true + response_buffering: true +plugins: + - name: jwt-keycloak + tags: [ns.gw-6d884] + enabled: true + config: + allowed_iss: + - https://dev.loginproxy.gov.bc.ca/auth/realms/apigw + allowed_aud: ap-gw-6d884-default-dev + run_on_preflight: true + iss_key_grace_period: 10 + maximum_expiration: 0 + algorithm: RS256 + claims_to_verify: + - exp + uri_param_names: + - jwt + cookie_names: [] + scope: null + roles: null + realm_roles: null + client_roles: null + anonymous: null + consumer_match: true + consumer_match_claim: azp + consumer_match_claim_custom_id: true + consumer_match_ignore_not_found: false + - name: request-transformer + tags: [ns.gw-6d884] + enabled: true + config: + http_method: null +--- +kind: CredentialIssuer +name: gw-6d884 default +description: Default Authorization Profile for gw-6d884 Gateway +flow: client-credentials +mode: auto +authPlugin: jwt-keycloak +clientAuthenticator: client-secret +clientRoles: [] +inheritFrom: Gold Shared IdP +--- +kind: DraftDataset +name: my-service-dataset +title: my-service +organization: ministry-of-health +organizationUnit: planning-and-innovation-division +notes: Some information about the my-service service +tags: [my-service, openapi] +license_title: Access Only +view_audience: Government +security_class: LOW-PUBLIC +record_publish_date: '2021-05-27' +--- +kind: Product +appId: '55A771FFE69A' +name: my-service API +dataset: my-service-dataset +environments: + - name: dev + appId: 'C6D5D55B' + active: false + approval: false + flow: client-credentials + credentialIssuer: gw-6d884 default + services: [my-service-dev] +# --- +# kind: ProductEnvironment +# name: dev +# product: my-service API +# appId: 'C3D732A2' +# active: false +# approval: true +# flow: client-credentials +# credentialIssuer: gw-6d884 default +# services: [my-service-dev] From dbd65fa5bc302d3c89aad16993c5bb14d105bc5e Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 16:07:18 -0700 Subject: [PATCH 31/81] Updated Cypress Tests as per GWA CLI and new namespace creation logic --- e2e/cypress/fixtures/api.json | 25 +- e2e/cypress/fixtures/apiowner.json | 20 +- .../fixtures/service-plugin-key-auth-only.yml | 4 +- .../fixtures/test_data/gwa-product.yaml | 6 +- e2e/cypress/support/util-commands.ts | 2 +- .../tests/01-api-key/01-create-api.cy.ts | 59 ++-- .../tests/01-api-key/02-team-access.cy.ts | 9 - ...quest-without-collecting-credentials.cy.ts | 2 - .../01-api-key/06-approve-pending-rqst.cy.ts | 2 - .../tests/01-api-key/07-grant-access.cy.ts | 2 - e2e/cypress/tests/01-api-key/08-gwa-get.ts | 85 +++++ .../07-manage-control/02-rate-limiting.cy.ts | 296 +++++++++--------- .../04-delete-namespace-gwa.ts | 82 +++++ .../tests/16-aps-api/01-create-api.cy.ts | 11 + .../tests/16-aps-api/02-organization.cy.ts | 1 - .../16-aps-api/05-authorizationProfiles.cy.ts | 42 +++ .../tests/16-aps-api/07-api-directory.cy.ts | 91 +++--- .../tests/16-aps-api/08-namespaces.cy.ts | 112 +++---- e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts | 13 + local/feeder-init/init.sh | 2 +- 20 files changed, 566 insertions(+), 300 deletions(-) create mode 100644 e2e/cypress/tests/01-api-key/08-gwa-get.ts create mode 100644 e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts diff --git a/e2e/cypress/fixtures/api.json b/e2e/cypress/fixtures/api.json index a0c0ab6fa..d058b9ee6 100644 --- a/e2e/cypress/fixtures/api.json +++ b/e2e/cypress/fixtures/api.json @@ -16,7 +16,7 @@ "Namespace.Assign" ], "expectedNamespace": { - "name": "gw-6d884", + "name": "gw-fd05f", "orgUnit": "planning-and-innovation-division", "enabled": true }, @@ -195,6 +195,29 @@ ], "isShared": true }, + "shared_gwa_publish": { + "name": "Gold Shared IdP", + "description": "A Shared IdP for Teams to use", + "flow": "client-credentials", + "mode": "auto", + "clientAuthenticator": "client-secret", + "environmentDetails": [ + { + "clientId": "gwa-api", + "clientRegistration": "managed", + "clientSecret": "****", + "environment": "test", + "issuerUrl": "http://keycloak.localtest.me:9080/auth/realms/master", + "exists": true + } + ], + "clientRoles": [], + "clientMappers": [], + "availableScopes": [], + "resourceScopes": [], + "isShared": true, + "apiKeyName": "X-API-KEY" + }, "shared_IDP_body": { "name": "Sample Shared IdP new", "description": "A Shared IdP for Teams to use", diff --git a/e2e/cypress/fixtures/apiowner.json b/e2e/cypress/fixtures/apiowner.json index 1c37f28ad..e95862d85 100644 --- a/e2e/cypress/fixtures/apiowner.json +++ b/e2e/cypress/fixtures/apiowner.json @@ -6,7 +6,7 @@ "password": "awsummer" } }, - "namespace": "gw-79851", + "namespace": "newplatform", "invalid_namespace": [ "test_1234", "New_napespace", @@ -20,7 +20,7 @@ ] }, "deleteResources": { - "namespace": "gw-99365", + "namespace": "gw-4722b", "product": { "name": "Delete-Auto Test Product", "environment": { @@ -38,7 +38,7 @@ "CredentialIssuer.Admin" ], "product": { - "name": "Auto Test Product", + "name": "GWA Auto Test Product", "orgName": "Ministry of Health", "orgUnitName": "Planning and Innovation Division", "environment": { @@ -47,7 +47,7 @@ "terms": "Terms of Use for API Gateway", "authorization": "Kong API Key with ACL Flow", "optionalInstructions": "This is a automation test", - "serviceName": "a-service-for-gw-79851" + "serviceName": "a-service-for-newplatform" } }, "test_environment": { @@ -56,12 +56,12 @@ "terms": "Terms of Use for API Gateway", "authorization": "Kong API Key with ACL Flow", "optionalInstructions": "This is a automation test", - "serviceName": "a-service-for-gw-79851-test" + "serviceName": "a-service-for-newplatform-test" } } }, "clientCredentials": { - "namespace": "gw-2d6e6", + "namespace": "gw-6faa0", "serviceName": "cc-service-for-platform", "Mark": { "userName": "mark", @@ -280,7 +280,7 @@ } }, "namespacePreview": { - "namespace": "gw-f04b0", + "namespace": "", "serviceAccount": { "scopes": [ "GatewayConfig.Publish", @@ -301,7 +301,7 @@ } }, "orgAssignment": { - "namespace": "gw-a9ee0", + "namespace": "", "serviceName": "a-service-for-orgassignment", "Mark": { "userName": "mark", @@ -399,7 +399,7 @@ } }, "checkPermission": { - "namespace": "gw-f9d48", + "namespace": "gw-25d58", "serviceAccount": { "scopes": [ "GatewayConfig.Publish", @@ -543,7 +543,7 @@ } }, "apiTest": { - "namespace": "gw-6d884", + "namespace": "gw-fd05f", "delete_namespace": "testplatform", "product": { "name": "API Auto Test Product", diff --git a/e2e/cypress/fixtures/service-plugin-key-auth-only.yml b/e2e/cypress/fixtures/service-plugin-key-auth-only.yml index fb4cf9c10..69ad7b220 100644 --- a/e2e/cypress/fixtures/service-plugin-key-auth-only.yml +++ b/e2e/cypress/fixtures/service-plugin-key-auth-only.yml @@ -2,11 +2,11 @@ plugins: - name: key-auth tags: - - ns.gw-00479 + - ns.newplatform protocols: - http - https config: key_names: - x-api-key - anonymous: e3940e13-6231-48c5-a39a-a55dd80e8df7 + anonymous: bb2c1e04-96ce-4b1d-baf4-a7e681a862a6 diff --git a/e2e/cypress/fixtures/test_data/gwa-product.yaml b/e2e/cypress/fixtures/test_data/gwa-product.yaml index 7f233dcb7..8b95400a3 100644 --- a/e2e/cypress/fixtures/test_data/gwa-product.yaml +++ b/e2e/cypress/fixtures/test_data/gwa-product.yaml @@ -1,8 +1,8 @@ -name: Auto Test Product -appId: '000000000000' +name: GWA Auto Test Product +appId: 'KFH78YU956RE' environments: - name: dev active: false approval: false flow: public - appId: '00000000' \ No newline at end of file + appId: '406CB7CF' \ No newline at end of file diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts index 920ba91c1..963055675 100644 --- a/e2e/cypress/support/util-commands.ts +++ b/e2e/cypress/support/util-commands.ts @@ -136,7 +136,7 @@ Cypress.Commands.add('updateJsonValue', (filePath: string, jsonPath: string, new }) Cypress.Commands.add('executeCliCommand', (command: string) => { - cy.exec(command, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + cy.exec(command, { timeout: 6000, failOnNonZeroExit: false }).then((response) => { return response }); }) diff --git a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts index 606baf44e..b786afa46 100644 --- a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts +++ b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts @@ -10,7 +10,7 @@ describe('Create API Spec', () => { const sa = new ServiceAccountsPage() const pd = new Products() var nameSpace: string - let userSession: string + let userSession: any before(() => { cy.visit('/') @@ -23,28 +23,44 @@ describe('Create API Spec', () => { cy.preserveCookies() cy.fixture('apiowner').as('apiowner') cy.fixture('api').as('api') - // cy.visit(login.path) + cy.visit(login.path) }) - it('authenticates Janis (api owner)', () => { - cy.get('@apiowner').then(({ user }: any) => { - cy.login(user.credentials.username, user.credentials.password) + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.getUserSessionTokenValue(namespace, false).then((value) => { + userSession = value + }) }) }) - it('creates and activates new namespace', () => { + it('Check gwa config command to set environment', () => { + cy.executeCliCommand('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http').then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa config command to set token', () => { + cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('creates new namespace', () => { cy.getUserSession().then(() => { cy.get('@apiowner').then(({ namespace }: any) => { nameSpace = namespace - // home.createNamespace(namespace) - home.useNamespace(namespace) - cy.get('@login').then(function (xhr: any) { - userSession = xhr.response.headers['x-auth-request-access-token'] + cy.executeCliCommand('gwa namespace create -n ' + namespace).then((response) => { + assert.equal(response.stdout, namespace) }) }) }) }) + it('activates new namespace', () => { + home.useNamespace(nameSpace) + }) + it('creates a new service account', () => { cy.visit(sa.path) cy.get('@apiowner').then(({ serviceAccount }: any) => { @@ -56,20 +72,24 @@ describe('Create API Spec', () => { it('publishes a new API for Dev environment to Kong Gateway', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.publishApi('service-gwa.yml', namespace).then(() => { - // cy.get('@publishAPIResponse').then((res: any) => { - // cy.log(JSON.stringify(res.body)) - // }) + cy.publishApi('service.yml', namespace).then((response: any) => { + expect(response.stdout).to.contain('Sync successful'); }) }) }) it('creates as new product in the directory through GWA Cli command', () => { - cy.gwaPublish('product','gwa-product.yaml').then((response:any) => { + cy.gwaPublish('product', 'gwa-product.yaml').then((response: any) => { expect(response.stdout).to.contain('Product successfully published'); }) }) + it('Upload dataset using GWA Cli command', () => { + cy.gwaPublish('dataset', 'gwa-dataset.yaml').then((response: any) => { + expect(response.stdout).to.contain('Dataset successfully published'); + }) + }) + it('Associate Namespace to the organization Unit', () => { cy.get('@api').then(({ organization }: any) => { cy.setHeaders(organization.headers) @@ -116,13 +136,8 @@ describe('Create API Spec', () => { it('applies authorization plugin to service published to Kong Gateway', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.replaceWordInJsonObject('newplatform', namespace, 'service-plugin.yml') - cy.wait(2000) - cy.publishApi('service-plugin.yml', namespace).then(() => { - // cy.get('@publishAPIResponse').then((res: any) => { - // cy.log(JSON.stringify(res.body)) - // expect(res.body.message).to.contains("Sync successful") - // }) + cy.publishApi('service-plugin.yml', namespace).then((response: any) => { + expect(response.stdout).to.contain('Sync successful'); }) }) }) diff --git a/e2e/cypress/tests/01-api-key/02-team-access.cy.ts b/e2e/cypress/tests/01-api-key/02-team-access.cy.ts index c3dda8ffe..84161c65c 100644 --- a/e2e/cypress/tests/01-api-key/02-team-access.cy.ts +++ b/e2e/cypress/tests/01-api-key/02-team-access.cy.ts @@ -39,17 +39,8 @@ describe('Team Access Spec', () => { }) }) - // it('Grant CredentialIssuer.Admin permission to Janis (API Owner)', () => { - // cy.get('@apiowner').then(({ grantPermission }: any) => { - // na.clickGrantUserAccessButton() - // na.grantPermission(grantPermission.Janis) - // }) - // }) - it('Grant CredentialIssuer.Admin permission to Janis (API Owner)', () => { cy.get('@apiowner').then(({ grantPermission }: any) => { - // na.clickGrantUserAccessButton() - // na.grantPermission(grantPermission.Janis) na.editPermission(grantPermission.Janis) }) }) diff --git a/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts b/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts index 1769508bb..39f89c4c7 100644 --- a/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts +++ b/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts @@ -12,8 +12,6 @@ describe('Approve Pending Request without collecting credentials Spec', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') }) beforeEach(() => { diff --git a/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts b/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts index 3ec9e47f0..1dc6ca499 100644 --- a/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts +++ b/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts @@ -12,8 +12,6 @@ describe('Approve Pending Request Spec', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') }) beforeEach(() => { diff --git a/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts b/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts index 1c4309cd6..7f0ad2b15 100644 --- a/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts +++ b/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts @@ -12,8 +12,6 @@ describe('Grant Access Spec', () => { cy.visit('/') cy.deleteAllCookies() cy.reload() - cy.getServiceOrRouteID('services') - cy.getServiceOrRouteID('routes') }) beforeEach(() => { diff --git a/e2e/cypress/tests/01-api-key/08-gwa-get.ts b/e2e/cypress/tests/01-api-key/08-gwa-get.ts new file mode 100644 index 000000000..183e7da09 --- /dev/null +++ b/e2e/cypress/tests/01-api-key/08-gwa-get.ts @@ -0,0 +1,85 @@ +import ConsumersPage from '../../pageObjects/consumers' +import LoginPage from '../../pageObjects/login' +import HomePage from '../../pageObjects/home' +import ProductPage from '../../pageObjects/products' +const yaml = require('js-yaml'); + +describe('Verify GWA get commands', () => { + const login = new LoginPage() + const consumers = new ConsumersPage() + const home = new HomePage() + var _namespace: string + let userSession: any + let resObj: any + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('api').as('api') + cy.fixture('apiowner').as('apiowner') + }) + + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ namespace }: any) => { + cy.getUserSessionTokenValue(namespace, false).then((value) => { + userSession = value + _namespace = namespace + }) + }) + }) + + it('Check gwa config command to set token', () => { + cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Verify "gwa get" for dataset', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.executeCliCommand('gwa get datasets').then((response) => { + expect(response.stdout).not.to.contain(product); + }) + }) + }) + + it('Verify "gwa get" for dataset in JSON format', () => { + cy.executeCliCommand('gwa get datasets --json').then((response) => { + cy.get('@api').then(({ apiDirectory }: any) => { + cy.setHeaders(apiDirectory.headers) + cy.setAuthorizationToken(userSession) + cy.makeAPIRequest(apiDirectory.endPoint + '/' + _namespace + '/directory', 'GET').then((res) => { + resObj = res.body[0] + Cypress._.isEqual(resObj, JSON.parse(response.stdout)[0]) + }) + }) + }) + }) + + it('Verify "gwa get" for dataset in YAML format', () => { + cy.executeCliCommand('gwa get datasets --yaml').then((response) => { + const yamlObject = yaml.load(response.stdout) + Cypress._.isEqual(resObj, yamlObject) + }) + }) + + it('Verify "gwa get" for products', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.executeCliCommand('gwa get products').then((response) => { + expect(response.stdout).not.to.contain(product); + }) + }) + }) + + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + +}) \ No newline at end of file diff --git a/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts b/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts index 27f15be08..7dd342b09 100644 --- a/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts +++ b/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts @@ -99,175 +99,175 @@ describe('Manage Control-Rate Limiting Spec for Route as Scope and Local Policy' }) }) -// describe('Manage Control-Rate Limiting Spec for Service as Scope and Redis Policy', () => { -// const login = new LoginPage() -// const home = new HomePage() -// const consumers = new ConsumersPage() +describe('Manage Control-Rate Limiting Spec for Service as Scope and Redis Policy', () => { + const login = new LoginPage() + const home = new HomePage() + const consumers = new ConsumersPage() -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('access-manager').as('access-manager') -// cy.fixture('apiowner').as('apiowner') -// cy.fixture('manage-control-config-setting').as('manage-control-config-setting') -// cy.visit(login.path) -// }) -// it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { -// cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { -// cy.visit(consumers.path); -// consumers.clickOnTheFirstConsumerID() -// consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Service", "Redis") -// }) -// }) + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + cy.fixture('manage-control-config-setting').as('manage-control-config-setting') + cy.visit(login.path) + }) + it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { + cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { + cy.visit(consumers.path); + consumers.clickOnTheFirstConsumerID() + consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Service", "Redis") + }) + }) -// it('verify rate limit error when the API calls beyond the limit', () => { -// cy.get('@apiowner').then(({ product }: any) => { -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(200) -// }) -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(429) -// expect(response.body.message).to.be.contain('API rate limit exceeded') -// }) -// }) -// }) -// }) + it('verify rate limit error when the API calls beyond the limit', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(200) + }) + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(429) + expect(response.body.message).to.be.contain('API rate limit exceeded') + }) + }) + }) +}) -// describe('Manage Control-Rate Limiting Spec for Route as Scope and Redis Policy', () => { -// const login = new LoginPage() -// const home = new HomePage() -// const consumers = new ConsumersPage() +describe('Manage Control-Rate Limiting Spec for Route as Scope and Redis Policy', () => { + const login = new LoginPage() + const home = new HomePage() + const consumers = new ConsumersPage() -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('access-manager').as('access-manager') -// cy.fixture('apiowner').as('apiowner') -// cy.fixture('manage-control-config-setting').as('manage-control-config-setting') -// cy.visit(login.path) -// }) -// it('set api rate limit as per the test config, Redis Policy and Scope as Route', () => { -// cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { -// cy.visit(consumers.path); -// consumers.clickOnTheFirstConsumerID() -// consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Route", "Redis") -// }) -// }) + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + cy.fixture('manage-control-config-setting').as('manage-control-config-setting') + cy.visit(login.path) + }) + it('set api rate limit as per the test config, Redis Policy and Scope as Route', () => { + cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { + cy.visit(consumers.path); + consumers.clickOnTheFirstConsumerID() + consumers.setRateLimiting(rateLimiting.requestPerHour_Consumer, "Route", "Redis") + }) + }) -// it('verify rate limit error when the API calls beyond the limit', () => { -// cy.get('@apiowner').then(({ product }: any) => { -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(200) -// }) -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(429) -// expect(response.body.message).to.be.contain('API rate limit exceeded') -// }) -// }) -// }) -// }) + it('verify rate limit error when the API calls beyond the limit', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(200) + }) + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(429) + expect(response.body.message).to.be.contain('API rate limit exceeded') + }) + }) + }) +}) -// describe('Manage Control-Apply Rate limiting to Global and Consumer at Service level ', () => { -// const login = new LoginPage() -// const home = new HomePage() -// const consumers = new ConsumersPage() +describe('Manage Control-Apply Rate limiting to Global and Consumer at Service level ', () => { + const login = new LoginPage() + const home = new HomePage() + const consumers = new ConsumersPage() -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('access-manager').as('access-manager') -// cy.fixture('apiowner').as('apiowner') -// cy.fixture('manage-control-config-setting').as('manage-control-config-setting') -// cy.visit(login.path) -// }) + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + cy.fixture('manage-control-config-setting').as('manage-control-config-setting') + cy.visit(login.path) + }) -// it('set api rate limit to global service level', () => { -// cy.visit(consumers.path); -// consumers.clickOnTheFirstConsumerID() -// consumers.clearRateLimitControl() -// cy.updateKongPlugin('services', 'rateLimiting').then((response) => { -// expect(response.status).to.be.equal(201) -// }) -// }) + it('set api rate limit to global service level', () => { + cy.visit(consumers.path); + consumers.clickOnTheFirstConsumerID() + consumers.clearRateLimitControl() + cy.updateKongPlugin('services', 'rateLimiting').then((response) => { + expect(response.status).to.be.equal(201) + }) + }) -// it('Verify that Rate limiting is set at global service level', () => { -// cy.get('@apiowner').then(({ product }: any) => { -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(200) -// expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.within(16, 18) -// }) -// }) -// }) + it('Verify that Rate limiting is set at global service level', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(200) + expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.within(16, 18) + }) + }) + }) -// it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { -// cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { -// cy.visit(consumers.path); -// consumers.clickOnTheFirstConsumerID() -// consumers.setRateLimiting(rateLimiting.requestPerHour_Global, "Service", "Redis") -// }) -// }) + it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { + cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { + cy.visit(consumers.path); + consumers.clickOnTheFirstConsumerID() + consumers.setRateLimiting(rateLimiting.requestPerHour_Global, "Service", "Redis") + }) + }) -// it('verify rate limit error when the API calls beyond the limit', () => { -// cy.get('@apiowner').then(({ product }: any) => { -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(200) -// }) -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(429) -// expect(response.body.message).to.be.contain('API rate limit exceeded') -// }) -// }) -// }) -// }) + it('verify rate limit error when the API calls beyond the limit', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(200) + }) + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(429) + expect(response.body.message).to.be.contain('API rate limit exceeded') + }) + }) + }) +}) describe('Manage Control-Apply Rate limiting to Global and Consumer at Route level ', () => { const login = new LoginPage() const home = new HomePage() const consumers = new ConsumersPage() -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('access-manager').as('access-manager') -// cy.fixture('apiowner').as('apiowner') -// cy.fixture('manage-control-config-setting').as('manage-control-config-setting') -// cy.visit(login.path) -// }) + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + cy.fixture('manage-control-config-setting').as('manage-control-config-setting') + cy.visit(login.path) + }) -// it('set api rate limit to global service level', () => { -// cy.visit(consumers.path); -// consumers.clickOnTheFirstConsumerID() -// consumers.clearRateLimitControl() -// cy.updateKongPlugin('routes', 'rateLimiting').then((response) => { -// expect(response.status).to.be.equal(201) -// }) -// }) + it('set api rate limit to global service level', () => { + cy.visit(consumers.path); + consumers.clickOnTheFirstConsumerID() + consumers.clearRateLimitControl() + cy.updateKongPlugin('routes', 'rateLimiting').then((response) => { + expect(response.status).to.be.equal(201) + }) + }) -// it('Verify that Rate limiting is set at global service level', () => { -// cy.get('@apiowner').then(({ product }: any) => { -// cy.wait(5000) -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(200) -// expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.equal(18) -// }) -// }) -// }) + it('Verify that Rate limiting is set at global service level', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.wait(5000) + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(200) + expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.equal(18) + }) + }) + }) -// it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { -// cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { -// cy.visit(consumers.path); -// consumers.clickOnTheFirstConsumerID() -// consumers.setRateLimiting(rateLimiting.requestPerHour_Global, "Route", "Redis") -// }) -// }) + it('set api rate limit as per the test config, Redis Policy and Scope as Service', () => { + cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { + cy.visit(consumers.path); + consumers.clickOnTheFirstConsumerID() + consumers.setRateLimiting(rateLimiting.requestPerHour_Global, "Route", "Redis") + }) + }) -// it('verify rate limit error when the API calls beyond the limit', () => { -// cy.get('@apiowner').then(({ product }: any) => { -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(200) -// }) -// cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { -// expect(response.status).to.be.equal(429) -// expect(response.body.message).to.be.contain('API rate limit exceeded') -// }) -// }) -// }) + it('verify rate limit error when the API calls beyond the limit', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(200) + }) + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(429) + expect(response.body.message).to.be.contain('API rate limit exceeded') + }) + }) + }) after(() => { cy.logout() diff --git a/e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts b/e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts new file mode 100644 index 000000000..b193b10fa --- /dev/null +++ b/e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts @@ -0,0 +1,82 @@ +import LoginPage from "../../pageObjects/login" + +describe('Verify namespace delete using gwa command', () => { + const login = new LoginPage() + let _namespace: string + let userSession: any + + before(() => { + // cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + cy.visit(login.path) + }) + + it('Authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) + }) + }) + + it('Set token using gwa config command', () => { + cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Create namespace using gwa cli command', () => { + cy.executeCliCommand('gwa namespace create').then((response) => { + assert.isNotNaN(response.stdout) + _namespace = response.stdout + }); + }) + + it('Check gwa namespace destroy command for soft deleting namespace', () => { + cy.executeCliCommand('gwa namespace destroy ' + _namespace).then((response) => { + expect(response.stdout).to.contain('Namespace destroyed: ' + _namespace); + }); + }) + + it('Check that deleted namespace does not display in gwa namespace list command', () => { + cy.executeCliCommand('gwa namespace list').then((response) => { + expect(response.stdout).not.to.contain(_namespace); + }); + }) + + it('Check gwa namespace destroy command for the namespace associated with services', () => { + cy.get('@apiowner').then(({ namespace }: any) => { + _namespace = namespace + cy.executeCliCommand('gwa config set --namespace ' + namespace).then((response) => { + assert.equal(response.stdout, "Config settings saved") + cy.executeCliCommand('gwa namespace destroy').then((response) => { + expect(response.stderr).to.contain('services have been configured in this namespace'); + }); + }) + }) + }) + + it('Check gwa namespace destroy command for hard deleting namespace', () => { + cy.executeCliCommand('gwa namespace destroy --force').then((response) => { + expect(response.stdout).to.contain('Namespace destroyed: ' + _namespace); + }); + }) + + it('Check that deleted namespace does not display in gwa namespace list command', () => { + cy.executeCliCommand('gwa namespace list').then((response) => { + expect(response.stdout).not.to.contain(_namespace); + }); + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) \ No newline at end of file diff --git a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts b/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts index 8e3deac24..8228c6195 100644 --- a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts +++ b/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts @@ -21,6 +21,7 @@ describe('Create API Spec', () => { beforeEach(() => { cy.preserveCookies() cy.fixture('apiowner').as('apiowner') + cy.fixture('api').as('api') cy.visit(login.path) }) @@ -54,6 +55,16 @@ describe('Create API Spec', () => { home.useNamespace(namespace) }) + it('Associate Namespace to the organization Unit', () => { + cy.get('@api').then(({ organization }: any) => { + cy.setHeaders(organization.headers) + cy.setAuthorizationToken(userSession) + cy.makeAPIRequest(organization.endPoint + '/' + organization.orgName + '/' + organization.orgExpectedList.name + '/namespaces/' + namespace, 'PUT').then((response) => { + expect(response.status).to.be.equal(200) + }) + }) + }) + after(() => { cy.logout() cy.clearLocalStorage({log:true}) diff --git a/e2e/cypress/tests/16-aps-api/02-organization.cy.ts b/e2e/cypress/tests/16-aps-api/02-organization.cy.ts index 73056e444..b8e982ec8 100644 --- a/e2e/cypress/tests/16-aps-api/02-organization.cy.ts +++ b/e2e/cypress/tests/16-aps-api/02-organization.cy.ts @@ -145,7 +145,6 @@ describe('Get the Namespace associated with the organization', () => { it('Get the resource and verify the success code in the response', () => { cy.get('@api').then(({ organization }: any) => { cy.makeAPIRequest(organization.endPoint + '/' + organization.orgName + '/namespaces', 'GET').then((res) => { - debugger expect(res.status).to.be.equal(200) response = res.body nameSpace = response[0].name diff --git a/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts b/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts index 6261b1e47..eb72c6ca4 100644 --- a/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts +++ b/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts @@ -30,6 +30,12 @@ describe('Get the user session token', () => { }) }) }) + + it('Set token with gwa config command', () => { + cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) }) testData.forEach((testCase: any) => { @@ -159,4 +165,40 @@ describe('API Tests for Authorization Profiles created with inheritFrom attribut }) }) +}) + +describe('Verify GWA command to publish issuer and apply generated config', () => { + + let response: any + let actualResponse: any + let expectedResponse: any + + beforeEach(() => { + cy.fixture('api').as('api') + cy.fixture('apiowner').as('apiowner') + }) + + it('Create a credential issuer using gwa publish command', () => { + cy.gwaPublish('issuer', 'gwa-issuer.yaml').then((response: any) => { + expect(response.stdout).to.contain('Issuer successfully published'); + }) + }) + + it('Get list of authorization profile and verify the success code in the response', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.makeAPIRequest('ds/api/v2/namespaces/' + apiTest.namespace + '/issuers', 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body + }) + }) + }) + + it('Compare the values in response against the values passed through gwa command', () => { + cy.get('@api').then(({ authorizationProfiles }: any) => { + actualResponse = response + expectedResponse = authorizationProfiles.shared_gwa_publish + cy.compareJSONObjects(actualResponse, expectedResponse, true) + }) + }) + }) \ No newline at end of file diff --git a/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts b/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts index 57f84b8d4..7554decb5 100644 --- a/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts +++ b/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts @@ -2,8 +2,7 @@ import HomePage from "../../pageObjects/home" import LoginPage from "../../pageObjects/login" let userSession: any let slugValue: string -let namespace: string -let updatedApiDirectoryEndPoint: string + describe('Get the user session token', () => { const login = new LoginPage() @@ -25,7 +24,6 @@ describe('Get the user session token', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.getUserSessionTokenValue(apiTest.namespace).then((value) => { userSession = value - namespace = apiTest.namespace }) }) }) @@ -55,11 +53,8 @@ describe('API Tests for Updating dataset', () => { it('Put the resource (/organization/{org}/datasets) and verify the success code in the response', () => { cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.replaceWord(apiDirectory.endPoint, 'apiplatform', namespace).then((updatedEndPoint: string) => { - updatedApiDirectoryEndPoint = updatedEndPoint - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets', 'PUT').then((response) => { - expect(response.status).to.be.equal(200) - }) + cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets', 'PUT').then((response) => { + expect(response.status).to.be.equal(200) }) }) }) @@ -67,7 +62,7 @@ describe('API Tests for Updating dataset', () => { it('Get the resource (/organization/{org}/datasets/{name}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + apiTest.namespace + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { + cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body }) @@ -83,8 +78,10 @@ describe('API Tests for Updating dataset', () => { it('Put the resource (/namespaces/{ns}/datasets/{name}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ apiTest }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + apiTest.namespace + '/datasets', 'PUT').then((response) => { - expect(response.status).to.be.equal(200) + cy.get('@api').then(({ apiDirectory }: any) => { + cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/datasets', 'PUT').then((response) => { + expect(response.status).to.be.equal(200) + }) }) }) }) @@ -92,7 +89,7 @@ describe('API Tests for Updating dataset', () => { it('Get the resource (/namespaces/{ns}/datasets/{name}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ apiTest }: any) => { cy.get('@api').then(({ apiDirectory }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + apiTest.namespace + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { + cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body }) @@ -108,7 +105,7 @@ describe('API Tests for Updating dataset', () => { it('Get the resource (/organizations/{org}/datasets/{name}) and verify the success code in the response', () => { cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { + cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body }) @@ -122,8 +119,8 @@ describe('API Tests for Updating dataset', () => { }) it('Get the resource (/organizations/{org}/datasets) and verify the success code in the response', () => { - cy.get('@api').then(({ organization }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets/', 'GET').then((res) => { + cy.get('@api').then(({ apiDirectory, organization }: any) => { + cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/', 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body }) @@ -137,11 +134,13 @@ describe('API Tests for Updating dataset', () => { }) it('Get the directory details (/directory) and verify the success code in the response', () => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - response = res.body - directoryID = res.body[0].id - directoryName = res.body[0].name + cy.get('@api').then(({ apiDirectory }: any) => { + cy.makeAPIRequest(apiDirectory.directoryEndPoint, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body + directoryID = res.body[0].id + directoryName = res.body[0].name + }) }) }) @@ -152,28 +151,34 @@ describe('API Tests for Updating dataset', () => { }) it('Get the directory details by its ID (/directory/{id}) and verify the success code in the response', () => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + directoryID, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - expect(res.body.name).to.be.equal(directoryName) + cy.get('@api').then(({ apiDirectory }: any) => { + cy.makeAPIRequest(apiDirectory.directoryEndPoint + '/' + directoryID, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body.name).to.be.equal(directoryName) + }) }) }) it('Get the namespace directory details (/namespaces/{ns}/directory) and verify the success code and empty response for the namespace with no directory', () => { cy.get('@apiowner').then(({ apiTest }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + apiTest.namespace + '/directory', 'GET').then((res) => { - expect(res.status).to.be.equal(200) - expect(res.body).to.be.empty + cy.get('@api').then(({ apiDirectory }: any) => { + cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/directory', 'GET').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body).to.be.empty + }) }) }) }) it('Get the namespace directory details (/namespaces/{ns}/directory) and verify the success code in the response', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + namespace + '/directory', 'GET').then((res) => { - expect(res.status).to.be.equal(200) - response = res.body[0] - directoryID = res.body[0].id - directoryName = res.body[0].name + cy.get('@api').then(({ apiDirectory }: any) => { + cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory', 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body[0] + directoryID = res.body[0].id + directoryName = res.body[0].name + }) }) }) }) @@ -186,32 +191,38 @@ describe('API Tests for Updating dataset', () => { it('Get the namespace directory details by its ID (/namespaces/{ns}/directory/{id}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + namespace + '/directory' + '/' + directoryID, 'GET').then((res) => { - expect(res.status).to.be.equal(200) - expect(res.body.name).to.be.equal(directoryName) + cy.get('@api').then(({ apiDirectory }: any) => { + cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory' + '/' + directoryID, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body.name).to.be.equal(directoryName) + }) }) }) }) it('Get the namespace directory details (/namespaces/{ns}/directory/{id}) for non exist directory ID and verify the response code', () => { cy.get('@apiowner').then(({ namespace }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + namespace + '/directory' + '/99', 'GET').then((res) => { - expect(res.status).to.be.oneOf([404, 422]) + cy.get('@api').then(({ apiDirectory }: any) => { + cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory' + '/99', 'GET').then((res) => { + expect(res.status).to.be.oneOf([404, 422]) + }) }) }) }) it('Delete the dataset (/organizations/{org}/datasets/{name}) and verify the success code in the response', () => { - cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'DELETE').then((res) => { - expect(res.status).to.be.equal(200) + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.get('@api').then(({ apiDirectory, organization }: any) => { + cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'DELETE').then((res) => { + expect(res.status).to.be.equal(200) + }) }) }) }) it('Verify that deleted dataset does not display in Get dataset list', () => { cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(updatedApiDirectoryEndPoint + '/' + organization.orgName + '/datasets/', 'GET').then((res) => { + cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/', 'GET').then((res) => { expect(res.status).to.be.equal(200) response = res.body expect(response).to.not.contain(apiDirectory.body.name) diff --git a/e2e/cypress/tests/16-aps-api/08-namespaces.cy.ts b/e2e/cypress/tests/16-aps-api/08-namespaces.cy.ts index 81bac4693..5e88102bf 100644 --- a/e2e/cypress/tests/16-aps-api/08-namespaces.cy.ts +++ b/e2e/cypress/tests/16-aps-api/08-namespaces.cy.ts @@ -149,59 +149,59 @@ describe('API Tests for Namespace Summary', () => { }) }) -describe('API Tests for Deleting Namespace', () => { - - const login = new LoginPage() - const home = new HomePage() - - - beforeEach(() => { - cy.fixture('api').as('api') - cy.fixture('apiowner').as('apiowner') - }) - - it('Prepare the Request Specification for the API', () => { - cy.get('@api').then(({ namespaces }: any) => { - cy.setHeaders(namespaces.headers) - cy.setAuthorizationToken(userSession) - }) - }) - - it('Delete the namespace and verify the Validation to prevent deleting the namespace', () => { - cy.get('@apiowner').then(({ namespace }: any) => { - cy.get('@api').then(({ namespaces }: any) => { - cy.makeAPIRequest(namespaces.endPoint + "/" + namespace, 'DELETE').then((res) => { - expect(res.status).to.be.equal(422) - }) - }) - }) - }) - - it('Force delete the namespace and verify the success code in the response', () => { - cy.get('@apiowner').then(({ namespace }: any) => { - cy.get('@api').then(({ namespaces }: any) => { - cy.makeAPIRequest(namespaces.endPoint + "/" + namespace + '?force=true', 'DELETE').then((res) => { - expect(res.status).to.be.equal(200) - }) - }) - }) - }) - - //need to confirm with Aidan - service returns 500 status code if there is no any namespaces - // it('Verify that deleted namespace does not display in Get namespace list', () => { - // let response: any - // cy.get('@api').then(({ namespaces }: any) => { - // cy.makeAPIRequest(namespaces.endPoint, 'GET').then((res) => { - // // expect(res.status).to.be.equal(200) - // response = res.body - // expect(response).to.not.contain(nameSpace) - // }) - // }) - // }) - - after(() => { - cy.logout() - cy.clearLocalStorage({ log: true }) - cy.deleteAllCookies() - }) -}) +// describe('API Tests for Deleting Namespace', () => { + +// const login = new LoginPage() +// const home = new HomePage() + + +// beforeEach(() => { +// cy.fixture('api').as('api') +// cy.fixture('apiowner').as('apiowner') +// }) + +// it('Prepare the Request Specification for the API', () => { +// cy.get('@api').then(({ namespaces }: any) => { +// cy.setHeaders(namespaces.headers) +// cy.setAuthorizationToken(userSession) +// }) +// }) + +// it('Delete the namespace and verify the Validation to prevent deleting the namespace', () => { +// cy.get('@apiowner').then(({ namespace }: any) => { +// cy.get('@api').then(({ namespaces }: any) => { +// cy.makeAPIRequest(namespaces.endPoint + "/" + namespace, 'DELETE').then((res) => { +// expect(res.status).to.be.equal(422) +// }) +// }) +// }) +// }) + +// it('Force delete the namespace and verify the success code in the response', () => { +// cy.get('@apiowner').then(({ namespace }: any) => { +// cy.get('@api').then(({ namespaces }: any) => { +// cy.makeAPIRequest(namespaces.endPoint + "/" + namespace + '?force=true', 'DELETE').then((res) => { +// expect(res.status).to.be.equal(200) +// }) +// }) +// }) +// }) + +// //need to confirm with Aidan - service returns 500 status code if there is no any namespaces +// // it('Verify that deleted namespace does not display in Get namespace list', () => { +// // let response: any +// // cy.get('@api').then(({ namespaces }: any) => { +// // cy.makeAPIRequest(namespaces.endPoint, 'GET').then((res) => { +// // // expect(res.status).to.be.equal(200) +// // response = res.body +// // expect(response).to.not.contain(nameSpace) +// // }) +// // }) +// // }) + +// after(() => { +// cy.logout() +// cy.clearLocalStorage({ log: true }) +// cy.deleteAllCookies() +// }) +// }) diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts index feb7a40f2..00e0533bb 100644 --- a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts +++ b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts @@ -123,4 +123,17 @@ describe('Verify CLI commands', () => { }); }) + it('Check gwa namespace destroy command for soft deleting namespace', () => { + cy.executeCliCommand('gwa namespace destroy '+namespace).then((response) => { + expect(response.stdout).to.contain('Namespace destroyed '+namespace); + }); + }) + + it('Check that deleted namespace does not display in gwa namespace list command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.executeCliCommand('gwa namespace list').then((response) => { + expect(response.stdout).not.to.contain(namespace); + }); + }) + }) \ No newline at end of file diff --git a/local/feeder-init/init.sh b/local/feeder-init/init.sh index 8d3536eb5..45c62582b 100755 --- a/local/feeder-init/init.sh +++ b/local/feeder-init/init.sh @@ -15,7 +15,7 @@ while true; do curl http://feeder.localtest.me:6000/push -F yaml=@shared-idp.yaml curl http://feeder.localtest.me:6000/push -F yaml=@platform-gwa-api.yaml curl http://feeder.localtest.me:6000/push -F yaml=@organization-unit.yaml - curl http://feeder.localtest.me:6000/push -F yaml=@dataset-gwa.yaml + # curl http://feeder.localtest.me:6000/push -F yaml=@dataset-gwa.yaml curl http://feeder.localtest.me:6000/push -F yaml=@org-dataset.yaml # curl http://feeder.localtest.me:6000/push -F yaml=@product-initializer.yaml # curl http://feeder.localtest.me:6000/push -F yaml=@product-initializer-permission.yaml From c5c8bc497d5a902aab5fe9fe96fafd4fc3ce39aa Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 16:28:41 -0700 Subject: [PATCH 32/81] Added workflow to install binary file --- .github/workflows/build-gwa-binary.yaml | 32 +++++++++++++ e2e/cypress.config.ts | 34 ++++++------- e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts | 50 ++++++++++---------- 3 files changed, 74 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/build-gwa-binary.yaml diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml new file mode 100644 index 000000000..382252e03 --- /dev/null +++ b/.github/workflows/build-gwa-binary.yaml @@ -0,0 +1,32 @@ +name: Build Executable Binary + +on: + push: + branches: ['dev', 'cypress*'] + +jobs: + cypress-run: + runs-on: ubuntu-latest + steps: + - name: Build GWA API Image + run: | + git clone https://github.com/bcgov/gwa-cli.git -b dev + cd gwa-cli + + - name: Set up Rust + uses: actions/setup-rust@v2 + + - name: Install 'just' + run: cargo install just + + - name: Build Executable Binary + run: just build + + - name: Upload Binary + uses: actions/upload-artifact@v2 + with: + name: gwa + path: /usr/local/bin # Replace with the path to your built binary + + - name: Check GWA help + run: gwa -h \ No newline at end of file diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index f5ec6c6e9..687a2ea1c 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -11,23 +11,23 @@ export default defineConfig({ // // It's IMPORTANT to return the config object // // with any changed environment variables config.specPattern=[ - './cypress/tests/18*/*.ts', - './cypress/tests/01-*/*.ts', - './cypress/tests/02-*/*.ts', - './cypress/tests/06-*/*.ts', - './cypress/tests/07-*/*.ts', - './cypress/tests/03-*/*.ts', - './cypress/tests/04-*/*.ts', - './cypress/tests/05-*/*.ts', - './cypress/tests/08-*/*.ts', - './cypress/tests/09-*/*.ts', - './cypress/tests/10-*/*.ts', - './cypress/tests/11-*/*.ts', - './cypress/tests/12-*/*.ts', - './cypress/tests/13-*/*.ts', - './cypress/tests/14-*/*.ts', - './cypress/tests/15-*/*.ts', - './cypress/tests/16-*/*.ts' + './cypress/tests/18*/*.ts' + // './cypress/tests/01-*/*.ts', + // './cypress/tests/02-*/*.ts', + // './cypress/tests/06-*/*.ts', + // './cypress/tests/07-*/*.ts', + // './cypress/tests/03-*/*.ts', + // './cypress/tests/04-*/*.ts', + // './cypress/tests/05-*/*.ts', + // './cypress/tests/08-*/*.ts', + // './cypress/tests/09-*/*.ts', + // './cypress/tests/10-*/*.ts', + // './cypress/tests/11-*/*.ts', + // './cypress/tests/12-*/*.ts', + // './cypress/tests/13-*/*.ts', + // './cypress/tests/14-*/*.ts', + // './cypress/tests/15-*/*.ts', + // './cypress/tests/16-*/*.ts' ] return config }, diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts index 00e0533bb..86ebffbf2 100644 --- a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts +++ b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts @@ -13,7 +13,7 @@ describe('Verify CLI commands', () => { const apiDir = new ApiDirectoryPage() const app = new ApplicationPage() const ma = new MyAccessPage() - let namespace : string + let namespace: string before(() => { // cy.visit('/') @@ -29,11 +29,11 @@ describe('Verify CLI commands', () => { it('authenticates Janis (api owner) to get the user session token', () => { cy.get('@apiowner').then(({ apiTest }: any) => { - cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { - userSession = value - }) + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) }) -}) + }) // it('Check for gwa help', () => { // cy.executeCliCommand('gwa help').then((response) => { @@ -54,7 +54,7 @@ describe('Verify CLI commands', () => { let clientID = cli.credentials.clientID let clientSecret = cli.credentials.clientSecret cy.log('gwa login --host ${url} --scheme http') - cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http').then((response) => { + cy.executeCliCommand('gwa login --client-id ' + clientID + ' --client-secret ' + clientSecret + ' --host ' + url + ' --scheme http').then((response) => { assert.equal(response.stdout, "Logged in") }); }) @@ -91,43 +91,43 @@ describe('Verify CLI commands', () => { }) it('Check gwa config command to set token', () => { - cy.executeCliCommand('gwa config set --token '+userSession).then((response) => { + cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { assert.equal(response.stdout, "Config settings saved") }); }) - it('Check gwa command for namespace help', () => { - cy.executeCliCommand('gwa namespace -h').then((response) => { - debugger - assert.equal(response.stdout, cli.content.namespace_help) - }); - }) + // it('Check gwa command for namespace help', () => { + // cy.executeCliCommand('gwa namespace -h').then((response) => { + // debugger + // assert.equal(response.stdout, cli.content.namespace_help) + // }); + // }) it('Check gwa command to create namespace', () => { let url = "oauth2proxy.localtest.me:4180" - cy.executeCliCommand('gwa namespace create --host '+url+' --scheme http').then((response) => { + cy.executeCliCommand('gwa namespace create --host ' + url + ' --scheme http').then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout - cy.replaceWordInJsonObject('newplatform',namespace,'service-gwa.yml') - cy.updateJsonValue('apiowner.json','namespace' , namespace) - cy.updateJsonValue('apiowner.json','product.environment.config.serviceName' , 'a-service-for-'+namespace) - cy.updateJsonValue('apiowner.json','product.test_environment.config.serviceName' , 'a-service-for-'+namespace+'-test') - cy.executeCliCommand("gwa config set --namespace "+namespace) + cy.replaceWordInJsonObject('newplatform', namespace, 'service-gwa.yml') + cy.updateJsonValue('apiowner.json', 'namespace', namespace) + cy.updateJsonValue('apiowner.json', 'product.environment.config.serviceName', 'a-service-for-' + namespace) + cy.updateJsonValue('apiowner.json', 'product.test_environment.config.serviceName', 'a-service-for-' + namespace + '-test') + cy.executeCliCommand("gwa config set --namespace " + namespace) }); }) it('Check gwa namespace list command and verify the created namespace in the list', () => { let url = "oauth2proxy.localtest.me:4180" - cy.executeCliCommand('gwa namespace list --host '+url+' --scheme http').then((response) => { + cy.executeCliCommand('gwa namespace list --host ' + url + ' --scheme http').then((response) => { expect(response.stdout).to.contain(namespace); }); }) - it('Check gwa namespace destroy command for soft deleting namespace', () => { - cy.executeCliCommand('gwa namespace destroy '+namespace).then((response) => { - expect(response.stdout).to.contain('Namespace destroyed '+namespace); - }); - }) + // it('Check gwa namespace destroy command for soft deleting namespace', () => { + // cy.executeCliCommand('gwa namespace destroy ' + namespace).then((response) => { + // expect(response.stdout).to.contain('Namespace destroyed ' + namespace); + // }); + // }) it('Check that deleted namespace does not display in gwa namespace list command', () => { let url = "oauth2proxy.localtest.me:4180" From 36af564f35785679e0d38bc5b3b04ce9b36db3d7 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 16:36:25 -0700 Subject: [PATCH 33/81] Update step in the workflow file --- .github/workflows/build-gwa-binary.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index 382252e03..39d11f28d 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -13,8 +13,10 @@ jobs: git clone https://github.com/bcgov/gwa-cli.git -b dev cd gwa-cli - - name: Set up Rust - uses: actions/setup-rust@v2 + - name: Download Go + uses: actions/setup-go@v4 + with: + go-version: '1.20.5' - name: Install 'just' run: cargo install just From 7a3ed79bfe2d905f0b31f5d1ab549797353d55ea Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 16:44:14 -0700 Subject: [PATCH 34/81] update steps in the workflow --- .github/workflows/build-gwa-binary.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index 39d11f28d..69c0dc673 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -22,7 +22,9 @@ jobs: run: cargo install just - name: Build Executable Binary - run: just build + run: | + cd gwa-cli + just build - name: Upload Binary uses: actions/upload-artifact@v2 From b6fb48d5faca91c3f4c2268aad6c9dfb04753bc6 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 17:02:54 -0700 Subject: [PATCH 35/81] Update steps to Build Executable Binary --- .github/workflows/build-gwa-binary.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index 69c0dc673..534ae836a 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -23,7 +23,7 @@ jobs: - name: Build Executable Binary run: | - cd gwa-cli + go mod tidy just build - name: Upload Binary From e266f959f6b3050ce8bc15b5b09ff1989eb2d3a1 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 17:14:17 -0700 Subject: [PATCH 36/81] Update in the workflow file --- .github/workflows/build-gwa-binary.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index 534ae836a..7ae3e7827 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -8,18 +8,19 @@ jobs: cypress-run: runs-on: ubuntu-latest steps: - - name: Build GWA API Image - run: | - git clone https://github.com/bcgov/gwa-cli.git -b dev - cd gwa-cli + - name: Checkout Source Repository + uses: actions/checkout@v2 + with: + repository: https://github.com/bcgov/gwa-cli.git + ref: dev - name: Download Go uses: actions/setup-go@v4 with: go-version: '1.20.5' - - name: Install 'just' - run: cargo install just + # - name: Install 'just' + # run: cargo install just - name: Build Executable Binary run: | From c60719cb3cc0df43f0b3620583e7b77c9795c99b Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 17:22:10 -0700 Subject: [PATCH 37/81] Update step of Checkout souce-repo in the workflow file --- .github/workflows/build-gwa-binary.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index 7ae3e7827..aa746095c 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -11,7 +11,7 @@ jobs: - name: Checkout Source Repository uses: actions/checkout@v2 with: - repository: https://github.com/bcgov/gwa-cli.git + repository: bcgov/https://github.com/bcgov/gwa-cli.git ref: dev - name: Download Go From 0345101c000954a8168e71880367aab50021d92d Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 17:30:23 -0700 Subject: [PATCH 38/81] Update step in the workflow file --- .github/workflows/build-gwa-binary.yaml | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index aa746095c..af7057eb1 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -9,23 +9,17 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Source Repository - uses: actions/checkout@v2 - with: - repository: bcgov/https://github.com/bcgov/gwa-cli.git - ref: dev + run: | + git clone https://github.com/bcgov/gwa-cli.git -b dev + cd gwa-cli - - name: Download Go - uses: actions/setup-go@v4 + - name: Set up Rust and Just + uses: actions-rs/toolchain@v1 with: - go-version: '1.20.5' + toolchain: stable - # - name: Install 'just' - # run: cargo install just - - - name: Build Executable Binary - run: | - go mod tidy - just build + - name: Build Go Binary + run: just build - name: Upload Binary uses: actions/upload-artifact@v2 From 016c7466306dde7f4c114b9234c6b98ab32fceed Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 14 Aug 2023 17:34:01 -0700 Subject: [PATCH 39/81] Update step to install go in the workflow file --- .github/workflows/build-gwa-binary.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index af7057eb1..ef1bcfd82 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -13,10 +13,16 @@ jobs: git clone https://github.com/bcgov/gwa-cli.git -b dev cd gwa-cli - - name: Set up Rust and Just - uses: actions-rs/toolchain@v1 + - name: Set up Go + uses: actions/setup-go@v2 with: - toolchain: stable + go-version: 1.16 # Replace with the desired Go version + + - name: Install just + run: | + wget https://github.com/casey/just/releases/download/v0.10.1/just-v0.10.1-x86_64-unknown-linux-musl -O just + chmod +x just + sudo mv just /usr/local/bin/ - name: Build Go Binary run: just build From 25f346f5ac97d8eea71c9e230a55ddcd40cb041c Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 16 Aug 2023 10:32:50 -0700 Subject: [PATCH 40/81] Code cleanup, update test name, added test for keycloak role and invalid JWK Public key format --- e2e/cypress.config.ts | 34 ++-- e2e/cypress/fixtures/api.json | 21 +++ e2e/cypress/pageObjects/apiDirectory.ts | 19 ++ e2e/cypress/pageObjects/consumers.ts | 23 ++- .../pageObjects/keycloakClientScopes.ts | 23 +++ .../tests/01-api-key/01-create-api.cy.ts | 3 +- .../01-client-cred-team-access.cy.ts | 4 +- .../05-cids-access-approve-api-rqst.cy.ts | 170 +++++++++++++++++- .../10-jwks-publicKey-access-rqst.cy.ts | 15 +- .../10-clear-resources/01-create-api.cy.ts | 4 +- .../12-access-permission/01-create-api.cy.ts | 2 +- .../01-create-api.cy.ts | 4 +- .../01-client-cred-team-access.ts | 4 +- .../02-multiple-org-admin.ts | 4 +- .../03-multiple-org-admin-org-unit.ts | 4 +- .../tests/16-aps-api/01-create-api.cy.ts | 4 +- .../tests/16-aps-api/02-organization.cy.ts | 20 ++- .../tests/18 -gwa-cli/01-cli-commands.ts | 116 ++++++++++++ e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts | 139 -------------- 19 files changed, 426 insertions(+), 187 deletions(-) create mode 100644 e2e/cypress/pageObjects/keycloakClientScopes.ts create mode 100644 e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts delete mode 100644 e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index 687a2ea1c..f5ec6c6e9 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -11,23 +11,23 @@ export default defineConfig({ // // It's IMPORTANT to return the config object // // with any changed environment variables config.specPattern=[ - './cypress/tests/18*/*.ts' - // './cypress/tests/01-*/*.ts', - // './cypress/tests/02-*/*.ts', - // './cypress/tests/06-*/*.ts', - // './cypress/tests/07-*/*.ts', - // './cypress/tests/03-*/*.ts', - // './cypress/tests/04-*/*.ts', - // './cypress/tests/05-*/*.ts', - // './cypress/tests/08-*/*.ts', - // './cypress/tests/09-*/*.ts', - // './cypress/tests/10-*/*.ts', - // './cypress/tests/11-*/*.ts', - // './cypress/tests/12-*/*.ts', - // './cypress/tests/13-*/*.ts', - // './cypress/tests/14-*/*.ts', - // './cypress/tests/15-*/*.ts', - // './cypress/tests/16-*/*.ts' + './cypress/tests/18*/*.ts', + './cypress/tests/01-*/*.ts', + './cypress/tests/02-*/*.ts', + './cypress/tests/06-*/*.ts', + './cypress/tests/07-*/*.ts', + './cypress/tests/03-*/*.ts', + './cypress/tests/04-*/*.ts', + './cypress/tests/05-*/*.ts', + './cypress/tests/08-*/*.ts', + './cypress/tests/09-*/*.ts', + './cypress/tests/10-*/*.ts', + './cypress/tests/11-*/*.ts', + './cypress/tests/12-*/*.ts', + './cypress/tests/13-*/*.ts', + './cypress/tests/14-*/*.ts', + './cypress/tests/15-*/*.ts', + './cypress/tests/16-*/*.ts' ] return config }, diff --git a/e2e/cypress/fixtures/api.json b/e2e/cypress/fixtures/api.json index d058b9ee6..4ebc0da33 100644 --- a/e2e/cypress/fixtures/api.json +++ b/e2e/cypress/fixtures/api.json @@ -20,6 +20,27 @@ "orgUnit": "planning-and-innovation-division", "enabled": true }, + "expectedRoles":{ + "organization-admin": { + "label": "Organization Administrator", + "permissions": [ + { + "resourceType": "organization", + "scopes": [ + "GroupAccess.Manage", + "Namespace.Assign", + "Dataset.Manage" + ] + }, + { + "resourceType": "namespace", + "scopes": [ + "Namespace.View" + ] + } + ] + } + }, "body": { "name": "ministry-of-health", "parent": "/ca.bc.gov", diff --git a/e2e/cypress/pageObjects/apiDirectory.ts b/e2e/cypress/pageObjects/apiDirectory.ts index 338b278fa..f270ccfba 100644 --- a/e2e/cypress/pageObjects/apiDirectory.ts +++ b/e2e/cypress/pageObjects/apiDirectory.ts @@ -17,6 +17,7 @@ class ApiDirectoryPage { orgDropDown: string = '[data-testid="orgDropDown"]' orgUnitDropDown: string = '[data-testid="orgUnitDropDown"]' addOrganizationBtn: string = '[data-testid="addOrganizationBtn"]' + jwksPublicKeyCheckBox: string = '[data-testid="access-rqst-app-env-public-key"]' createAccessRequest(product: any, app: any, accessRqst: any, elevatedAccess?: boolean) { @@ -120,6 +121,24 @@ class ApiDirectoryPage { getPlainText(text: string): string { return text.replace(/[\r\n]/g, '').replace(/\s+/g, " ") } + + enterInvalidJWTKey(product: any, app: any, accessRqst: any) { + cy.contains(product.name).click() + cy.get(this.rqstAccessBtn).click() + cy.get(this.appSelect).select(app.name) + cy.get('[data-testid=access-rqst-app-env-' + product.environment + ']').click() + cy.get('body', { log: false }).then(($body) => { + if ($body.find(this.legatTermCheckBox).length > 0) { + cy.get(this.legatTermCheckBox).first().click() + } + }) + cy.readFile('cypress/fixtures/state/jwtReGenPublicKey_new.pub').then((publicKeyKey) => { + cy.get(this.jwksPublicKeyCheckBox).click() + cy.get('[name="clientCertificate"]').click().type(publicKeyKey + "End of File") + }) + cy.get(this.additionalNotes).type(accessRqst.notes) + cy.get(this.submitBtn).click() + } } export default ApiDirectoryPage diff --git a/e2e/cypress/pageObjects/consumers.ts b/e2e/cypress/pageObjects/consumers.ts index 445afabb0..93887f5b6 100644 --- a/e2e/cypress/pageObjects/consumers.ts +++ b/e2e/cypress/pageObjects/consumers.ts @@ -323,12 +323,20 @@ export default class ConsumersPage { cy.wait(1000) } - selectAuthorizationScope(scopes: any) { + selectAuthorizationScope(scopes: any, isChecked = true) { cy.contains("Authorization").click() - scopes.forEach(function (scope: string) { - cy.get('[data-testid="client-scope-' + scope + '"]').click() - cy.wait(1000) - }) + if (isChecked) { + scopes.forEach(function (scope: string) { + cy.get('[data-testid="client-scope-' + scope + '"]').find('[type="checkbox"]').check({ force: true }); + cy.wait(1000) + }) + } + else { + scopes.forEach(function (scope: string) { + cy.get('[data-testid="client-scope-' + scope + '"]').find('[type="checkbox"]').uncheck({ force: true }); + cy.wait(1000) + }) + } } selectClientRole(roles: any) { @@ -348,6 +356,11 @@ export default class ConsumersPage { } }) } + + saveAppliedConfig(){ + cy.get(this.consumerDialogSaveBtn).click() + cy.wait(1000) + } clickOnLinkConsumerToNamespaceBtn() { cy.get(this.linkConsumerToNamespaceBtn).click({ force: true }) diff --git a/e2e/cypress/pageObjects/keycloakClientScopes.ts b/e2e/cypress/pageObjects/keycloakClientScopes.ts new file mode 100644 index 000000000..cdb96bd90 --- /dev/null +++ b/e2e/cypress/pageObjects/keycloakClientScopes.ts @@ -0,0 +1,23 @@ +import { Assertion } from "chai" + +class keycloakClientScopesPage { + path: string = '/' + + clientTab: string = '[data-ng-controller="ClientTabCtrl"]' + + selectTab(tabName: string){ + cy.get(this.clientTab).contains('a',tabName).click() + } + + verifyAssignedScope(scope: string, expResult:boolean) + { + if(expResult){ + cy.get('[id="assigned"]').find('[title="'+scope+'"]').should('exist'); + } + else{ + cy.get('[id="assigned"]').find('[title="'+scope+'"]').should('not.exist'); + } + } +} + +export default keycloakClientScopesPage diff --git a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts index b786afa46..7ac036f63 100644 --- a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts +++ b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts @@ -35,7 +35,8 @@ describe('Create API Spec', () => { }) it('Check gwa config command to set environment', () => { - cy.executeCliCommand('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http').then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.executeCliCommand('gwa config set --host '+cleanedUrl+' --scheme http').then((response) => { assert.equal(response.stdout, "Config settings saved") }); }) diff --git a/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts b/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts index 54cf79367..89a234fbe 100644 --- a/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts @@ -37,8 +37,8 @@ describe('Grant appropriate permissions to team members for client credential fl }) it('create namespace using gwa cli command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.exec('gwa namespace create --host ' + cleanedUrl + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout cy.replaceWordInJsonObject('ccplatform', namespace, 'cc-service-gwa.yml') diff --git a/e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts index 29edef349..87693de85 100644 --- a/e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts @@ -1,6 +1,10 @@ import HomePage from '../../pageObjects/home' import LoginPage from '../../pageObjects/login' import ConsumersPage from '../../pageObjects/consumers' +import KeycloakUserGroupPage from '../../pageObjects/keycloakUserGroup' +import keycloakGroupPage from '../../pageObjects/keycloakGroup' +import AuthorizationProfile from '../../pageObjects/authProfile' +import keycloakClientScopesPage from '../../pageObjects/keycloakClientScopes' describe('Access manager approves developer access request for Client ID/Secret authenticator', () => { const home = new HomePage() @@ -21,8 +25,8 @@ describe('Access manager approves developer access request for Client ID/Secret }) it('Access Manager logs in', () => { - cy.get('@apiowner').then(({ clientCredentials }: any) => { - cy.get('@access-manager').then(({ user }: any) => { + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { cy.login(user.credentials.username, user.credentials.password) home.useNamespace(clientCredentials.namespace) }) @@ -30,10 +34,8 @@ describe('Access manager approves developer access request for Client ID/Secret }) it('Access Manager approves developer access request', () => { - cy.get('@access-manager').then(() => { - cy.visit(consumers.path) - consumers.reviewThePendingRequest() - }) + cy.visit(consumers.path) + consumers.reviewThePendingRequest() }) it('Select scopes in Authorization Tab', () => { @@ -77,4 +79,160 @@ describe('Make an API request using Client ID, Secret, and Access Token', () => }) }) }) +}) + +describe('Verify the selected client scoped is displayed in assigned default list', () => { + const clientScopes = new keycloakClientScopesPage() + const groups = new keycloakGroupPage() + var nameSpace: string + const home = new HomePage() + const authProfile = new AuthorizationProfile() + + before(() => { + cy.visit(Cypress.env('KEYCLOAK_URL')) + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + cy.fixture('apiowner').as('apiowner') + cy.fixture('state/regen').as('regen') + cy.fixture('admin').as('admin') + }) + + it('Authenticates Admin owner', () => { + cy.get('@admin').then(({ user }: any) => { + cy.contains('Administration Console').click({ force: true }) + cy.keycloakLogin(user.credentials.username, user.credentials.password) + }) + }) + + it('Navigate to Clients page', () => { + cy.contains('Clients').click() + }) + + it('Select the consumer ID', () => { + cy.readFile('cypress/fixtures/state/store.json').then((store_res) => { + let cc = JSON.parse(store_res.clientidsecret) + cy.contains(cc.clientId).click() + }) + }) + + it('Navigate to client scope tab', () => { + clientScopes.selectTab('Client Scopes') + }) + + it('Verify that "System.Write" scope is in assigned default scope', () => { + clientScopes.verifyAssignedScope('System.Write', true) + }) + + after(() => { + cy.keycloakLogout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + +}) + +describe('Deselect the scope from authorization tab', () => { + const login = new LoginPage() + const home = new HomePage() + const consumers = new ConsumersPage() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + cy.fixture('manage-control-config-setting').as('manage-control-config-setting') + // cy.visit(login.path) + }) + + it('authenticates Mark (Access Manager)', () => { + cy.get('@access-manager').then(({ user }: any) => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.login(user.credentials.username, user.credentials.password).then(() => { + home.useNamespace(clientCredentials.namespace); + }) + }) + }) + }) + + it('Navigate to Consumer page ', () => { + cy.visit(consumers.path); + }) + + it('Select the consumer from the list ', () => { + consumers.clickOnTheFirstConsumerID() + }) + + it('Deselect scopes in Authorization Tab', () => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + consumers.editConsumerDialog() + consumers.selectAuthorizationScope(clientCredentials.clientIdSecret.authProfile.scopes, false) + consumers.saveAppliedConfig() + }) + }) +}) + +describe('Verify the selected client scoped is not displayed in assigned default list', () => { + const clientScopes = new keycloakClientScopesPage() + const groups = new keycloakGroupPage() + var nameSpace: string + const home = new HomePage() + const authProfile = new AuthorizationProfile() + + before(() => { + cy.visit(Cypress.env('KEYCLOAK_URL')) + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + cy.fixture('apiowner').as('apiowner') + cy.fixture('state/regen').as('regen') + cy.fixture('admin').as('admin') + }) + + it('Authenticates Admin owner', () => { + cy.get('@admin').then(({ user }: any) => { + cy.contains('Administration Console').click({ force: true }) + cy.keycloakLogin(user.credentials.username, user.credentials.password) + }) + }) + + it('Navigate to Clients page', () => { + cy.contains('Clients').click() + }) + + it('Select the consumer ID', () => { + cy.readFile('cypress/fixtures/state/store.json').then((store_res) => { + let cc = JSON.parse(store_res.clientidsecret) + cy.contains(cc.clientId).click() + }) + }) + + it('Navigate to client scope tab', () => { + clientScopes.selectTab('Client Scopes') + }) + + it('Verify that "System.Write" scope is not in assigned default scope', () => { + clientScopes.verifyAssignedScope('System.Write', false) + }) + + after(() => { + cy.keycloakLogout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + }) \ No newline at end of file diff --git a/e2e/cypress/tests/02-client-credential-flow/10-jwks-publicKey-access-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/10-jwks-publicKey-access-rqst.cy.ts index c3587dc51..798fdaef3 100644 --- a/e2e/cypress/tests/02-client-credential-flow/10-jwks-publicKey-access-rqst.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/10-jwks-publicKey-access-rqst.cy.ts @@ -20,7 +20,7 @@ describe('Generates public/private key and set public key to access request', () beforeEach(() => { cy.preserveCookies() cy.fixture('developer').as('developer') - cy.visit(login.path) + // cy.visit(login.path) }) it('Generate the RS256 key pair', () => { @@ -40,6 +40,19 @@ describe('Generates public/private key and set public key to access request', () }) }) + it('Enter JWT key with invalid format', () => { + cy.visit(apiDir.path) + cy.get('@developer').then(({ clientCredentials, accessRequest }: any) => { + let jwksPublicKey = clientCredentials.jwksPublicKey + apiDir.enterInvalidJWTKey(jwksPublicKey.product, jwksPublicKey.application, accessRequest) + }) + }) + + it('Verify the error popups for invalid JWT key', () => { + cy.wait(3000) + cy.verifyToastMessage("Certificate failed validation") + }) + it('Creates an access request', () => { cy.visit(apiDir.path) cy.get('@developer').then(({ clientCredentials, accessRequest }: any) => { diff --git a/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts b/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts index c1b826d7c..68d052395 100644 --- a/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts +++ b/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts @@ -40,8 +40,8 @@ describe('Create API Spec for Delete Resources', () => { }) it('create namespace using gwa cli command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.exec('gwa namespace create --host ' + cleanedUrl + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout cy.replaceWordInJsonObject('ns.deleteplatform', 'ns.' + namespace, 'service-clear-resources-gwa.yml') diff --git a/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts b/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts index e42411a3f..41b1d970d 100644 --- a/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts +++ b/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts @@ -40,7 +40,7 @@ describe('Create API Spec', () => { }) it('create namespace using gwa cli command', () => { - let url = "oauth2proxy.localtest.me:4180" + cleanedUrl cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout diff --git a/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts b/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts index 67319b24f..9f9ac4455 100644 --- a/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts +++ b/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts @@ -40,8 +40,8 @@ describe('Create API Spec', () => { }) it('create namespace using gwa cli command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.exec('gwa namespace create --host ' + cleanedUrl + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout cy.updateJsonValue('apiowner.json', 'namespacePreview.namespace', namespace) diff --git a/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts b/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts index 0cb0c509d..1bcf051b0 100644 --- a/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts +++ b/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts @@ -48,8 +48,8 @@ describe('Add Organization to publish API', () => { }) it('create namespace using gwa cli command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.exec('gwa namespace create --host ' + cleanedUrl + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout cy.updateJsonValue('apiowner.json', 'orgAssignment.namespace', namespace) diff --git a/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts b/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts index 5e5a0d6e1..0d62f19e5 100644 --- a/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts +++ b/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts @@ -97,8 +97,8 @@ describe('Multiple Org Adming for the organization', () => { }) it('create namespace using gwa cli command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.exec('gwa namespace create --host ' + cleanedUrl + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout cy.updateJsonValue('apiowner.json', 'orgAssignment.namespace', namespace) diff --git a/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts b/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts index bcb4d214d..31462b969 100644 --- a/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts +++ b/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts @@ -113,8 +113,8 @@ describe('Multiple Org Admin for the organization', () => { }) it('create namespace using gwa cli command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.exec('gwa namespace create --host ' + cleanedUrl + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout cy.updateJsonValue('apiowner.json', 'orgAssignment.namespace', namespace) diff --git a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts b/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts index 8228c6195..1da1f8f0a 100644 --- a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts +++ b/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts @@ -40,8 +40,8 @@ describe('Create API Spec', () => { }) it('create namespace using gwa cli command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.exec('gwa namespace create --host ' + cleanedUrl + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout cy.updateJsonValue('apiowner.json', 'apiTest.namespace', namespace) diff --git a/e2e/cypress/tests/16-aps-api/02-organization.cy.ts b/e2e/cypress/tests/16-aps-api/02-organization.cy.ts index b8e982ec8..5b9649af9 100644 --- a/e2e/cypress/tests/16-aps-api/02-organization.cy.ts +++ b/e2e/cypress/tests/16-aps-api/02-organization.cy.ts @@ -54,7 +54,7 @@ describe('Verify /Organization/{Org} end point', () => { it('Verify the status code and response message for invalid organization name', () => { cy.get('@api').then(({ organization }: any) => { - cy.makeAPIRequest(organization.endPoint + '/health' , 'GET').then((response) => { + cy.makeAPIRequest(organization.endPoint + '/health', 'GET').then((response) => { expect(response.status).to.be.oneOf([404, 422]) expect(response.body.message).to.be.equal("Organization not found.") }) @@ -123,6 +123,20 @@ describe('Get the Organization Role', () => { }) }) + it('Get the list of roles and verify the success code in the response', () => { + cy.makeAPIRequest('ds/api/v2/roles', 'GET').then((res) => { + expect(res.status).to.be.equal(200) + response = res.body + }) + }) + + it('Compare the roles values in response against the expected values', () => { + cy.get('@api').then(({ organization }: any) => { + expectedResponse = organization.expectedRoles + cy.compareJSONObjects(response, expectedResponse) + }) + }) + }) describe('Get the Namespace associated with the organization', () => { @@ -247,7 +261,7 @@ describe('Add and Get Organization Access', () => { after(() => { cy.logout() - cy.clearLocalStorage({log:true}) + cy.clearLocalStorage({ log: true }) cy.deleteAllCookies() - }) + }) }) \ No newline at end of file diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts new file mode 100644 index 000000000..4bca4791f --- /dev/null +++ b/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts @@ -0,0 +1,116 @@ +import LoginPage from '../../pageObjects/login' +import ApplicationPage from '../../pageObjects/applications' +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import MyAccessPage from '../../pageObjects/myAccess' +const YAML = require('yamljs'); +let userSession: any +let cli = require("../../fixtures/test_data/gwa-cli.json") +var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); +const jose = require('node-jose') + +describe('Verify CLI commands', () => { + const login = new LoginPage() + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const ma = new MyAccessPage() + let namespace: string + + before(() => { + // cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) + }) + }) + + it('Check for gwa help', () => { + cy.executeCliCommand('gwa help').then((response) => { + debugger + assert.equal(response.stdout, cli.content.help) + }); + }) + + it('Check gwa command for login help', () => { + cy.executeCliCommand('gwa login -h').then((response) => { + assert.equal(response.stdout, cli.content.login_help) + }); + }) + + it('Check gwa command to login with client ID and secret', () => { + let clientID = cli.credentials.clientID + let clientSecret = cli.credentials.clientSecret + cy.log('gwa login --host ${url} --scheme http') + cy.executeCliCommand('gwa login --client-id ' + clientID + ' --client-secret ' + clientSecret + ' --host ' + cleanedUrl + ' --scheme http').then((response) => { + assert.equal(response.stdout, "Logged in") + }); + }) + + it('Check gwa command for login with invalid client id', () => { + let clientID = "dummy-client" + let clientSecret = cli.credentials.clientSecret + cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+cleanedUrl+' --scheme http').then((response) => { + assert.equal(response.stderr, "Error: unauthorized_client\nINVALID_CREDENTIALS: Invalid client credentials") + }); + }) + + it('Check gwa command for login with invalid client secret', () => { + let clientID = cli.credentials.clientID + let clientSecret = "dummy-client-secret" + cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+cleanedUrl+' --scheme http').then((response) => { + assert.equal(response.stderr, "Error: unauthorized_client\nINVALID_CREDENTIALS: Invalid client credentials") + }); + }) + + it('Check gwa command for config help', () => { + cy.executeCliCommand('gwa config -h').then((response) => { + debugger + assert.equal(response.stdout, cli.content.config_help) + }); + }) + + it('Check gwa config command to set environment', () => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.executeCliCommand('gwa config set --host '+cleanedUrl+' --scheme http').then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa config command to set token', () => { + cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa command for namespace help', () => { + cy.executeCliCommand('gwa namespace -h').then((response) => { + debugger + assert.equal(response.stdout, cli.content.namespace_help) + }); + }) + + it('Check gwa command to create namespace', () => { + cy.executeCliCommand('gwa namespace create --host ' + cleanedUrl + ' --scheme http').then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + }); + }) + + it('Check gwa namespace list command and verify the created namespace in the list', () => { + cy.executeCliCommand('gwa namespace list --host ' + cleanedUrl + ' --scheme http').then((response) => { + expect(response.stdout).to.contain(namespace); + }); + }) + +}) \ No newline at end of file diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts deleted file mode 100644 index 86ebffbf2..000000000 --- a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts +++ /dev/null @@ -1,139 +0,0 @@ -import LoginPage from '../../pageObjects/login' -import ApplicationPage from '../../pageObjects/applications' -import ApiDirectoryPage from '../../pageObjects/apiDirectory' -import MyAccessPage from '../../pageObjects/myAccess' -const YAML = require('yamljs'); -let userSession: any -let cli = require("../../fixtures/test_data/gwa-cli.json") - -const jose = require('node-jose') - -describe('Verify CLI commands', () => { - const login = new LoginPage() - const apiDir = new ApiDirectoryPage() - const app = new ApplicationPage() - const ma = new MyAccessPage() - let namespace: string - - before(() => { - // cy.visit('/') - cy.deleteAllCookies() - cy.reload() - }) - - beforeEach(() => { - cy.preserveCookies() - cy.fixture('apiowner').as('apiowner') - // cy.visit(login.path) - }) - - it('authenticates Janis (api owner) to get the user session token', () => { - cy.get('@apiowner').then(({ apiTest }: any) => { - cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { - userSession = value - }) - }) - }) - - // it('Check for gwa help', () => { - // cy.executeCliCommand('gwa help').then((response) => { - // debugger - // assert.equal(response.stdout, cli.content.help) - // }); - // }) - - // it('Check gwa command for login help', () => { - // cy.executeCliCommand('gwa login -h').then((response) => { - // debugger - // assert.equal(response.stdout, cli.content.login_help) - // }); - // }) - - it('Check gwa command to login with client ID and secret', () => { - let url = "oauth2proxy.localtest.me:4180" - let clientID = cli.credentials.clientID - let clientSecret = cli.credentials.clientSecret - cy.log('gwa login --host ${url} --scheme http') - cy.executeCliCommand('gwa login --client-id ' + clientID + ' --client-secret ' + clientSecret + ' --host ' + url + ' --scheme http').then((response) => { - assert.equal(response.stdout, "Logged in") - }); - }) - - // it('Check gwa command for login with invalid client id', () => { - // let url = "oauth2proxy.localtest.me:4180" - // let clientID = "dummy-client" - // let clientSecret = cli.credentials.clientSecret - // cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http').then((response) => { - // assert.equal(response.stderr, "Error: INVALID_CREDENTIALS: Invalid client credentials") - // }); - // }) - - // it('Check gwa command for login with invalid client secret', () => { - // let url = "oauth2proxy.localtest.me:4180" - // let clientID = cli.credentials.clientID - // let clientSecret = "dummy-client-secret" - // cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+url+' --scheme http').then((response) => { - // assert.equal(response.stderr, "Error: Invalid client secret") - // }); - // }) - - // it('Check gwa command for config help', () => { - // cy.executeCliCommand('gwa config -h').then((response) => { - // debugger - // assert.equal(response.stdout, cli.content.config_help) - // }); - // }) - - it('Check gwa config command to set environment', () => { - cy.executeCliCommand('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http').then((response) => { - assert.equal(response.stdout, "Config settings saved") - }); - }) - - it('Check gwa config command to set token', () => { - cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - assert.equal(response.stdout, "Config settings saved") - }); - }) - - // it('Check gwa command for namespace help', () => { - // cy.executeCliCommand('gwa namespace -h').then((response) => { - // debugger - // assert.equal(response.stdout, cli.content.namespace_help) - // }); - // }) - - it('Check gwa command to create namespace', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.executeCliCommand('gwa namespace create --host ' + url + ' --scheme http').then((response) => { - assert.isNotNaN(response.stdout) - namespace = response.stdout - cy.replaceWordInJsonObject('newplatform', namespace, 'service-gwa.yml') - cy.updateJsonValue('apiowner.json', 'namespace', namespace) - cy.updateJsonValue('apiowner.json', 'product.environment.config.serviceName', 'a-service-for-' + namespace) - cy.updateJsonValue('apiowner.json', 'product.test_environment.config.serviceName', 'a-service-for-' + namespace + '-test') - cy.executeCliCommand("gwa config set --namespace " + namespace) - }); - }) - - it('Check gwa namespace list command and verify the created namespace in the list', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.executeCliCommand('gwa namespace list --host ' + url + ' --scheme http').then((response) => { - expect(response.stdout).to.contain(namespace); - }); - }) - - // it('Check gwa namespace destroy command for soft deleting namespace', () => { - // cy.executeCliCommand('gwa namespace destroy ' + namespace).then((response) => { - // expect(response.stdout).to.contain('Namespace destroyed ' + namespace); - // }); - // }) - - it('Check that deleted namespace does not display in gwa namespace list command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.executeCliCommand('gwa namespace list').then((response) => { - expect(response.stdout).not.to.contain(namespace); - }); - }) - -}) \ No newline at end of file From 6c78fa0ccdb2c60b00df813bf5bf8baf4030c32b Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 21 Aug 2023 15:59:47 -0700 Subject: [PATCH 41/81] Added scenarios for gwa generate config and update github action to build, install gwa cli --- .github/workflows/aps-cypress-e2e.yaml | 29 ++++++ .github/workflows/build-gwa-binary.yaml | 6 +- e2e/cypress.config.ts | 2 +- e2e/cypress/pageObjects/myAccess.ts | 1 + e2e/cypress/pageObjects/products.ts | 19 ++++ e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts | 85 ++++++++++++++++ .../18 -gwa-cli/02-cli-generate-config.ts | 86 ++++++++++++++++ e2e/gw-config.yml | 99 ------------------- 8 files changed, 226 insertions(+), 101 deletions(-) create mode 100644 e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts create mode 100644 e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts delete mode 100644 e2e/gw-config.yml diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index ed3e232ed..3a53031d8 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -40,6 +40,35 @@ jobs: export CY_REPO_URL=${{ env.GIT_REPO_URL }} export CY_COMMIT_AUTHOR_EMAIL=$(git --no-pager show -s --format='%ae' ${{ env.GIT_COMMIT_SHA }}) docker-compose up -d + + - name: Checkout Source Repository + run: | + git clone https://github.com/bcgov/gwa-cli.git -b dev + cd gwa-cli + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.16 # Replace with the desired Go version + + - name: Install just + run: | + wget https://github.com/casey/just/releases/download/v0.10.1/just-v0.10.1-x86_64-unknown-linux-musl -O just + chmod +x just + sudo mv just /usr/local/bin/ + + - name: Build Go Binary + run: just build + + - name: Upload Binary + uses: actions/upload-artifact@v2 + with: + name: gwa + path: /usr/local/bin # Replace with the path to your built binary + + - name: Check GWA help + run: gwa -h + - name: Execute Tests & Clean Up run: | while true; do diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index ef1bcfd82..be8755376 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -1,9 +1,13 @@ -name: Build Executable Binary +name: Build GWA Binary on: push: branches: ['dev', 'cypress*'] +on: + repository_dispatch: + types: [build-gwa-binary] + jobs: cypress-run: runs-on: ubuntu-latest diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index f5ec6c6e9..4a2eb84f1 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -24,7 +24,7 @@ export default defineConfig({ './cypress/tests/10-*/*.ts', './cypress/tests/11-*/*.ts', './cypress/tests/12-*/*.ts', - './cypress/tests/13-*/*.ts', + './cypress/tests/13-*/*.ts', './cypress/tests/14-*/*.ts', './cypress/tests/15-*/*.ts', './cypress/tests/16-*/*.ts' diff --git a/e2e/cypress/pageObjects/myAccess.ts b/e2e/cypress/pageObjects/myAccess.ts index 9865f08b4..7a200768a 100644 --- a/e2e/cypress/pageObjects/myAccess.ts +++ b/e2e/cypress/pageObjects/myAccess.ts @@ -166,6 +166,7 @@ class myAccessPage { cy.saveState('clientID', $clientID) }) } + } export default myAccessPage diff --git a/e2e/cypress/pageObjects/products.ts b/e2e/cypress/pageObjects/products.ts index 31f030291..e1b1ff727 100644 --- a/e2e/cypress/pageObjects/products.ts +++ b/e2e/cypress/pageObjects/products.ts @@ -319,6 +319,25 @@ class Products { cy.get(this.messageForNotDataset).should('be.visible'); } + + verifyAuthScope(expAuthValue: string){ + cy.get(this.envCfgAuthzDropdown).find(':selected').invoke('text').then(($auth: any) => { + assert.equal($auth,expAuthValue ) + }) + } + + verifyIssuer(expIssuerValue: string){ + cy.get('[name="credentialIssuer"]').find(':selected').invoke('text').then(($issuer: any) => { + assert.equal($issuer,expIssuerValue ) + }) + } + + verifyDataset(expDatasetValue: string, product: string){ + this.editProduct(product) + cy.get(this.catelogueDropDown).invoke('val').then(($dataset: any) => { + assert.equal($dataset,expDatasetValue) + }) + } } export default Products diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts new file mode 100644 index 000000000..95680db17 --- /dev/null +++ b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts @@ -0,0 +1,85 @@ +import LoginPage from '../../pageObjects/login' +import ApplicationPage from '../../pageObjects/applications' +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import MyAccessPage from '../../pageObjects/myAccess' +const YAML = require('yamljs'); +let userSession: any +let cli = require("../../fixtures/test_data/gwa-cli.json") + +const jose = require('node-jose') + +describe('Verify CLI commands', () => { + const login = new LoginPage() + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const ma = new MyAccessPage() + let namespace: string + + before(() => { + // cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) + }) + }) + + it('Check gwa command to login with client ID and secret', () => { + let url = "oauth2proxy.localtest.me:4180" + let clientID = cli.credentials.clientID + let clientSecret = cli.credentials.clientSecret + cy.log('gwa login --host ${url} --scheme http') + cy.executeCliCommand('gwa login --client-id ' + clientID + ' --client-secret ' + clientSecret + ' --host ' + url + ' --scheme http').then((response) => { + assert.equal(response.stdout, "Logged in") + }); + }) + + + it('Check gwa config command to set environment', () => { + cy.executeCliCommand('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http').then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa config command to set token', () => { + cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { + assert.equal(response.stdout, "Config settings saved") + }); + }) + + it('Check gwa command to create namespace', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.executeCliCommand('gwa namespace create --host ' + url + ' --scheme http').then((response) => { + assert.isNotNaN(response.stdout) + namespace = response.stdout + cy.replaceWordInJsonObject('newplatform', namespace, 'service-gwa.yml') + cy.updateJsonValue('apiowner.json', 'namespace', namespace) + }); + }) + + it('Check gwa namespace list command and verify the created namespace in the list', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.executeCliCommand('gwa namespace list --host ' + url + ' --scheme http').then((response) => { + expect(response.stdout).to.contain(namespace); + }); + }) + + it('Check that deleted namespace does not display in gwa namespace list command', () => { + let url = "oauth2proxy.localtest.me:4180" + cy.executeCliCommand('gwa namespace list').then((response) => { + expect(response.stdout).not.to.contain(namespace); + }); + }) + +}) \ No newline at end of file diff --git a/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts b/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts new file mode 100644 index 000000000..22a35f443 --- /dev/null +++ b/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts @@ -0,0 +1,86 @@ +import LoginPage from '../../pageObjects/login' +import ApplicationPage from '../../pageObjects/applications' +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import MyAccessPage from '../../pageObjects/myAccess' +import HomePage from '../../pageObjects/home'; +import Products from '../../pageObjects/products'; +const YAML = require('yamljs'); +let userSession: any +let cli = require("../../fixtures/test_data/gwa-cli.json") + +const jose = require('node-jose') + +describe('Verify CLI commands', () => { + const login = new LoginPage() + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const ma = new MyAccessPage() + const pd = new Products() + let namespace: string + const home = new HomePage() + + before(() => { + // cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + it('authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { + userSession = value + }) + }) + }) + + // it('Check gwa config command to set token', () => { + // cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { + // assert.equal(response.stdout, "Config settings saved") + // }); + // }) + + // it('Check gwa command to generate config', () => { + // cy.executeCliCommand('gwa generate-config --template client-credentials-shared-idp --service my-service --upstream https://httpbin.org --org ministry-of-health --org-unit planning-and-innovation-division').then((response) => { + // assert.equal(response.stdout, "File gw-config.yml created") + // }); + // }) + + // it('Check gwa command to apply generated config', () => { + // cy.executeCliCommand('gwa apply').then((response) => { + // let wordOccurrences = (response.stdout.match(/\bcreated\b/g) || []).length; + // expect(wordOccurrences).to.equal(3) + // wordOccurrences = (response.stdout.match(/\published\b/g) || []).length; + // expect(wordOccurrences).to.equal(1) + // }); + // }) + + it('activates new namespace', () => { + cy.get('@apiowner').then(({ namespace }: any) => { + home.useNamespace(namespace) + }) + }) + + it('Verify that the product created through gwa command is displayed in the portal', () => { + cy.visit(pd.path) + pd.editProductEnvironment('my-service API', 'dev') + }) + + it('Verify the Authorization scope and issuer details for the product', () => { + pd.verifyAuthScope('Oauth2 Client Credentials Flow') + }) + + it('Verify the issuer details for the product', () => { + pd.verifyIssuer('gw-d4ed4 default (test)') + }) + + it('Verify that the dataset created through GWA comand is assocuated with the product', () => { + cy.visit(pd.path) + pd.verifyDataset('my-service','my-service API') + }) +}) \ No newline at end of file diff --git a/e2e/gw-config.yml b/e2e/gw-config.yml deleted file mode 100644 index 71a68a0b8..000000000 --- a/e2e/gw-config.yml +++ /dev/null @@ -1,99 +0,0 @@ -kind: Namespace -name: gw-6d884 -displayName: gw-6d884 Display Name ---- -kind: GatewayService -name: my-service-dev -tags: [ns.gw-6d884] -host: httpbin.org -port: 443 -protocol: https -retries: 0 -routes: - - name: my-service-dev - tags: [ns.gw-6d884] - hosts: - - my-service.dev.api.gov.bc.ca - methods: - - GET - strip_path: false - https_redirect_status_code: 426 - path_handling: v0 - request_buffering: true - response_buffering: true -plugins: - - name: jwt-keycloak - tags: [ns.gw-6d884] - enabled: true - config: - allowed_iss: - - https://dev.loginproxy.gov.bc.ca/auth/realms/apigw - allowed_aud: ap-gw-6d884-default-dev - run_on_preflight: true - iss_key_grace_period: 10 - maximum_expiration: 0 - algorithm: RS256 - claims_to_verify: - - exp - uri_param_names: - - jwt - cookie_names: [] - scope: null - roles: null - realm_roles: null - client_roles: null - anonymous: null - consumer_match: true - consumer_match_claim: azp - consumer_match_claim_custom_id: true - consumer_match_ignore_not_found: false - - name: request-transformer - tags: [ns.gw-6d884] - enabled: true - config: - http_method: null ---- -kind: CredentialIssuer -name: gw-6d884 default -description: Default Authorization Profile for gw-6d884 Gateway -flow: client-credentials -mode: auto -authPlugin: jwt-keycloak -clientAuthenticator: client-secret -clientRoles: [] -inheritFrom: Gold Shared IdP ---- -kind: DraftDataset -name: my-service-dataset -title: my-service -organization: ministry-of-health -organizationUnit: planning-and-innovation-division -notes: Some information about the my-service service -tags: [my-service, openapi] -license_title: Access Only -view_audience: Government -security_class: LOW-PUBLIC -record_publish_date: '2021-05-27' ---- -kind: Product -appId: '55A771FFE69A' -name: my-service API -dataset: my-service-dataset -environments: - - name: dev - appId: 'C6D5D55B' - active: false - approval: false - flow: client-credentials - credentialIssuer: gw-6d884 default - services: [my-service-dev] -# --- -# kind: ProductEnvironment -# name: dev -# product: my-service API -# appId: 'C3D732A2' -# active: false -# approval: true -# flow: client-credentials -# credentialIssuer: gw-6d884 default -# services: [my-service-dev] From c74e640afc8c1c6176d468e2e046955a89e4f0a8 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 21 Aug 2023 16:03:54 -0700 Subject: [PATCH 42/81] Update the workflow file to build gwa binary --- .github/workflows/build-gwa-binary.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml index be8755376..718b4f941 100644 --- a/.github/workflows/build-gwa-binary.yaml +++ b/.github/workflows/build-gwa-binary.yaml @@ -2,11 +2,7 @@ name: Build GWA Binary on: push: - branches: ['dev', 'cypress*'] - -on: - repository_dispatch: - types: [build-gwa-binary] + branches: ['cypress/*'] jobs: cypress-run: From fd298bc36e2b8923a6c99b938b8e1a91b7d72770 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 21 Aug 2023 16:05:48 -0700 Subject: [PATCH 43/81] Add cypress as branch regex to trigger the execution on the feature branch --- .github/workflows/aps-cypress-e2e.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 3a53031d8..5357d10ef 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -2,7 +2,7 @@ name: Build and Deploy Cypress and Execute Tests on: push: - branches: ['test', 'cypress/*'] + branches: ['test', 'cypress*'] env: DASHBOARD_PROJECT_ID: ${{ secrets.CY_DASHBOARD_PRJ_ID }} @@ -68,7 +68,7 @@ jobs: - name: Check GWA help run: gwa -h - + - name: Execute Tests & Clean Up run: | while true; do From e34da3fc3fb7b6e6d9ca5c7a7a99b54e86af8137 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 21 Aug 2023 16:10:51 -0700 Subject: [PATCH 44/81] update branch for GWA API step --- .github/workflows/aps-cypress-e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 5357d10ef..a3e871a0b 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -20,7 +20,7 @@ jobs: steps: - name: Build GWA API Image run: | - git clone https://github.com/bcgov/gwa-api.git -b master + git clone https://github.com/bcgov/gwa-api.git -b dev cd gwa-api/microservices/gatewayApi docker build -t gwa-api:e2e . - name: Checkout Portal From 331f46259a9acbef34df84630742470353a121ce Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 21 Aug 2023 16:41:46 -0700 Subject: [PATCH 45/81] Update steps in the workflow to build and install gwa cli --- .github/workflows/aps-cypress-e2e.yaml | 61 ++++++++++++++------------ 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index a3e871a0b..8835ff5e9 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -23,11 +23,44 @@ jobs: git clone https://github.com/bcgov/gwa-api.git -b dev cd gwa-api/microservices/gatewayApi docker build -t gwa-api:e2e . + + - name: Checkout Source Repository + run: | + git clone https://github.com/bcgov/gwa-cli.git -b dev + cd gwa-cli + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.20.5' + + - name: create .env file + run: | + echo "GWA_API_HOST=api-services-portal-feature-gwa-cli-v2.apps.silver.devops.gov.bc.ca" >> .env + echo "GWA_CLIENT_ID=gwa-cli" >> .env + + - name: set up Just + uses: extractions/setup-just@v1 + with: + just-version: 1.14.0 + + - name: Build + run: | + cd gwa-cli + just build + + - name: Move file to /usr/local/bin + run: | + cd gwa-cli + sudo mv gwa /usr/local/bin/ + - name: Checkout Portal uses: actions/checkout@v2 + - name: Build Docker Images run: | docker-compose build + - name: Spin up API Services Portal and Run E2E Tests run: | export CY_EXECUTION_ENV=${{ env.EXECUTION_ENV }} @@ -41,34 +74,6 @@ jobs: export CY_COMMIT_AUTHOR_EMAIL=$(git --no-pager show -s --format='%ae' ${{ env.GIT_COMMIT_SHA }}) docker-compose up -d - - name: Checkout Source Repository - run: | - git clone https://github.com/bcgov/gwa-cli.git -b dev - cd gwa-cli - - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: 1.16 # Replace with the desired Go version - - - name: Install just - run: | - wget https://github.com/casey/just/releases/download/v0.10.1/just-v0.10.1-x86_64-unknown-linux-musl -O just - chmod +x just - sudo mv just /usr/local/bin/ - - - name: Build Go Binary - run: just build - - - name: Upload Binary - uses: actions/upload-artifact@v2 - with: - name: gwa - path: /usr/local/bin # Replace with the path to your built binary - - - name: Check GWA help - run: gwa -h - - name: Execute Tests & Clean Up run: | while true; do From ac14ec617c0e4aed6eb480f323a593b148bbe82b Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 21 Aug 2023 21:55:21 -0700 Subject: [PATCH 46/81] Corrected steps for access permission --- e2e/cypress.config.ts | 5 ++--- e2e/cypress/tests/12-access-permission/01-create-api.cy.ts | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index 4a2eb84f1..d35d0bffe 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -11,7 +11,6 @@ export default defineConfig({ // // It's IMPORTANT to return the config object // // with any changed environment variables config.specPattern=[ - './cypress/tests/18*/*.ts', './cypress/tests/01-*/*.ts', './cypress/tests/02-*/*.ts', './cypress/tests/06-*/*.ts', @@ -24,10 +23,10 @@ export default defineConfig({ './cypress/tests/10-*/*.ts', './cypress/tests/11-*/*.ts', './cypress/tests/12-*/*.ts', - './cypress/tests/13-*/*.ts', './cypress/tests/14-*/*.ts', './cypress/tests/15-*/*.ts', - './cypress/tests/16-*/*.ts' + './cypress/tests/16-*/*.ts', + './cypress/tests/13-*/*.ts', ] return config }, diff --git a/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts b/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts index 41b1d970d..7c9c82f68 100644 --- a/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts +++ b/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts @@ -40,8 +40,8 @@ describe('Create API Spec', () => { }) it('create namespace using gwa cli command', () => { - cleanedUrl - cy.exec('gwa namespace create --host ' + url + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { + var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); + cy.exec('gwa namespace create --host ' + cleanedUrl + ' --scheme http', { timeout: 3000, failOnNonZeroExit: false }).then((response) => { assert.isNotNaN(response.stdout) namespace = response.stdout cy.replaceWordInJsonObject('ns.permission', 'ns.' + namespace, 'service-permission-gwa.yml') From 6547e3a833c4ff3fb55e1d79903c3de01915e1f4 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Tue, 22 Aug 2023 17:21:40 -0700 Subject: [PATCH 47/81] Add GWA help step in workflow and update api.json test file --- .github/workflows/aps-cypress-e2e.yaml | 3 +++ e2e/cypress/fixtures/api.json | 34 +++++++++++++------------- e2e/cypress/fixtures/apiowner.json | 20 +++++++-------- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 8835ff5e9..754026538 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -54,6 +54,9 @@ jobs: cd gwa-cli sudo mv gwa /usr/local/bin/ + - name: Check GWA help + run: gwa -h + - name: Checkout Portal uses: actions/checkout@v2 diff --git a/e2e/cypress/fixtures/api.json b/e2e/cypress/fixtures/api.json index 4ebc0da33..38ce371fc 100644 --- a/e2e/cypress/fixtures/api.json +++ b/e2e/cypress/fixtures/api.json @@ -16,30 +16,30 @@ "Namespace.Assign" ], "expectedNamespace": { - "name": "gw-fd05f", + "name": "gw-65590", "orgUnit": "planning-and-innovation-division", "enabled": true }, - "expectedRoles":{ + "expectedRoles": { "organization-admin": { "label": "Organization Administrator", "permissions": [ - { - "resourceType": "organization", - "scopes": [ - "GroupAccess.Manage", - "Namespace.Assign", - "Dataset.Manage" - ] - }, - { - "resourceType": "namespace", - "scopes": [ - "Namespace.View" - ] - } + { + "resourceType": "organization", + "scopes": [ + "GroupAccess.Manage", + "Namespace.Assign", + "Dataset.Manage" + ] + }, + { + "resourceType": "namespace", + "scopes": [ + "Namespace.View" + ] + } ] - } + } }, "body": { "name": "ministry-of-health", diff --git a/e2e/cypress/fixtures/apiowner.json b/e2e/cypress/fixtures/apiowner.json index e95862d85..fdd261d0e 100644 --- a/e2e/cypress/fixtures/apiowner.json +++ b/e2e/cypress/fixtures/apiowner.json @@ -20,7 +20,7 @@ ] }, "deleteResources": { - "namespace": "gw-4722b", + "namespace": "gw-2a3ef", "product": { "name": "Delete-Auto Test Product", "environment": { @@ -61,7 +61,7 @@ } }, "clientCredentials": { - "namespace": "gw-6faa0", + "namespace": "gw-e9cd4", "serviceName": "cc-service-for-platform", "Mark": { "userName": "mark", @@ -222,7 +222,7 @@ }, "KongApiOnly": { "product": { - "name": "Auto Test Product", + "name": "GWA Auto Test Product", "orgName": "Ministry of Health", "orgUnitName": "Planning and Innovation Division", "environment": { @@ -238,7 +238,7 @@ }, "clientIdSecret_KongKeyToCC": { "product": { - "name": "Auto Test Product", + "name": "GWA Auto Test Product", "orgName": "Ministry of Health", "orgUnitName": "Planning and Innovation Division", "environment": { @@ -280,7 +280,7 @@ } }, "namespacePreview": { - "namespace": "", + "namespace": "gw-07034", "serviceAccount": { "scopes": [ "GatewayConfig.Publish", @@ -301,7 +301,7 @@ } }, "orgAssignment": { - "namespace": "", + "namespace": "gw-57421", "serviceName": "a-service-for-orgassignment", "Mark": { "userName": "mark", @@ -399,7 +399,7 @@ } }, "checkPermission": { - "namespace": "gw-25d58", + "namespace": "gw-e9cca", "serviceAccount": { "scopes": [ "GatewayConfig.Publish", @@ -543,7 +543,7 @@ } }, "apiTest": { - "namespace": "gw-fd05f", + "namespace": "gw-65590", "delete_namespace": "testplatform", "product": { "name": "API Auto Test Product", @@ -568,7 +568,7 @@ "entity": "access request", "accessRequest": "2", "environment": "dev", - "product": "Auto Test Product", + "product": "GWA Auto Test Product", "application": "Auto Test App to check labels", "consumer": "9C3EFC92-8F3DE9D3B74" }, @@ -584,7 +584,7 @@ "note": "access pending approval", "accessRequest": "2", "environment": "dev", - "product": "Auto Test Product", + "product": "GWA Auto Test Product", "application": "Auto Test App to check labels", "consumer": "9C3EFC92-8F3DE9D3B73" }, From adcabd7d8810337d420b9521e0846cc9153dc3f1 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Tue, 22 Aug 2023 21:23:19 -0700 Subject: [PATCH 48/81] Check for gwa command through cypress --- e2e/cypress.config.ts | 33 ++++++++--------- e2e/cypress/tests/19-gwa-test/01-cli-demo.ts | 37 ++++++++++++++++++++ 2 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 e2e/cypress/tests/19-gwa-test/01-cli-demo.ts diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index d35d0bffe..81fd35f71 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -11,22 +11,23 @@ export default defineConfig({ // // It's IMPORTANT to return the config object // // with any changed environment variables config.specPattern=[ - './cypress/tests/01-*/*.ts', - './cypress/tests/02-*/*.ts', - './cypress/tests/06-*/*.ts', - './cypress/tests/07-*/*.ts', - './cypress/tests/03-*/*.ts', - './cypress/tests/04-*/*.ts', - './cypress/tests/05-*/*.ts', - './cypress/tests/08-*/*.ts', - './cypress/tests/09-*/*.ts', - './cypress/tests/10-*/*.ts', - './cypress/tests/11-*/*.ts', - './cypress/tests/12-*/*.ts', - './cypress/tests/14-*/*.ts', - './cypress/tests/15-*/*.ts', - './cypress/tests/16-*/*.ts', - './cypress/tests/13-*/*.ts', + // './cypress/tests/01-*/*.ts', + // './cypress/tests/02-*/*.ts', + // './cypress/tests/06-*/*.ts', + // './cypress/tests/07-*/*.ts', + // './cypress/tests/03-*/*.ts', + // './cypress/tests/04-*/*.ts', + // './cypress/tests/05-*/*.ts', + // './cypress/tests/08-*/*.ts', + // './cypress/tests/09-*/*.ts', + // './cypress/tests/10-*/*.ts', + // './cypress/tests/11-*/*.ts', + // './cypress/tests/12-*/*.ts', + // './cypress/tests/14-*/*.ts', + // './cypress/tests/15-*/*.ts', + // './cypress/tests/16-*/*.ts', + // './cypress/tests/13-*/*.ts', + './cypress/tests/19-*/*.ts' ] return config }, diff --git a/e2e/cypress/tests/19-gwa-test/01-cli-demo.ts b/e2e/cypress/tests/19-gwa-test/01-cli-demo.ts new file mode 100644 index 000000000..a51ddd82d --- /dev/null +++ b/e2e/cypress/tests/19-gwa-test/01-cli-demo.ts @@ -0,0 +1,37 @@ +import LoginPage from '../../pageObjects/login' +import ApplicationPage from '../../pageObjects/applications' +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import MyAccessPage from '../../pageObjects/myAccess' +const YAML = require('yamljs'); +let userSession: any +let cli = require("../../fixtures/test_data/gwa-cli.json") + +const jose = require('node-jose') + +describe('Verify CLI commands', () => { + const login = new LoginPage() + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const ma = new MyAccessPage() + let namespace: string + + before(() => { + // cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + + it('Check gwa command for config help', () => { + cy.executeCliCommand('gwa config -h').then((response) => { + expect(response.stdout).to.contain("Configuration commands"); + }); + }) + +}) \ No newline at end of file From de6e6741656f1c4117e0d0f9996b5ac468df93cc Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 23 Aug 2023 15:01:52 -0700 Subject: [PATCH 49/81] Update workflow and e2e dockerfile --- .github/workflows/aps-cypress-e2e.yaml | 17 +++++++++++------ e2e/Dockerfile | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 754026538..05cda19c8 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -49,17 +49,22 @@ jobs: cd gwa-cli just build - - name: Move file to /usr/local/bin - run: | - cd gwa-cli - sudo mv gwa /usr/local/bin/ + # - name: Move file to /usr/local/bin + # run: | + # cd gwa-cli + # sudo mv gwa /usr/local/bin/ - - name: Check GWA help - run: gwa -h + # - name: Check GWA help + # run: gwa -h - name: Checkout Portal uses: actions/checkout@v2 + - name: Move file to e2e folder + run: | + cd gwa-cli + sudo mv gwa ${{ github.workspace }}/e2e + - name: Build Docker Images run: | docker-compose build diff --git a/e2e/Dockerfile b/e2e/Dockerfile index 46e1ec3bc..a77289f4a 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -3,14 +3,15 @@ FROM cypress/included:12.4.0 WORKDIR /e2e RUN apt-get -y update; apt-get -y install curl - COPY cypress.config.ts /e2e COPY tsconfig.json /e2e COPY package.json /e2e COPY package-lock.json /e2e COPY entrypoint.sh /tmp +COPY gwa /usr/local/bin ADD cypress /e2e/cypress RUN npm install + ENTRYPOINT ["npm", "run", "cy:run:html"] \ No newline at end of file From d10aa97481be6402367525ef94920c0298286d3a Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 23 Aug 2023 15:13:32 -0700 Subject: [PATCH 50/81] Update workflow file --- .github/workflows/aps-cypress-e2e.yaml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 05cda19c8..987630812 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -49,21 +49,20 @@ jobs: cd gwa-cli just build - # - name: Move file to /usr/local/bin - # run: | - # cd gwa-cli - # sudo mv gwa /usr/local/bin/ + - name: Move file to /usr/local/bin + run: | + cd gwa-cli + sudo mv gwa /usr/local/bin/ - # - name: Check GWA help - # run: gwa -h + - name: Check GWA help + run: gwa -h - name: Checkout Portal uses: actions/checkout@v2 - name: Move file to e2e folder run: | - cd gwa-cli - sudo mv gwa ${{ github.workspace }}/e2e + sudo mv /usr/local/bin/gwa ${{ github.workspace }}/e2e - name: Build Docker Images run: | From affa2bc0e34381f532523e1388aa790be98690ef Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 23 Aug 2023 17:17:49 -0700 Subject: [PATCH 51/81] Modified step to build go binary file --- .github/workflows/aps-cypress-e2e.yaml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 987630812..111749087 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -44,10 +44,17 @@ jobs: with: just-version: 1.14.0 - - name: Build - run: | - cd gwa-cli - just build + # - name: Build + # run: | + # cd gwa-cli + # just build + - name: Build GO binary file + uses: actions/checkout@v3 + uses: wangyoucao577/go-release-action@v1 + with: + goos: linux + goarch: amd64 + binary_name: "gwa" - name: Move file to /usr/local/bin run: | From 1a086160bd27784cc7efe65597e3ece3fda4c619 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 23 Aug 2023 17:22:19 -0700 Subject: [PATCH 52/81] Corrected error in the workflow file --- .github/workflows/aps-cypress-e2e.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 111749087..014314bd0 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -49,7 +49,6 @@ jobs: # cd gwa-cli # just build - name: Build GO binary file - uses: actions/checkout@v3 uses: wangyoucao577/go-release-action@v1 with: goos: linux From 587ebcae3e375a3913a00f7bb2419b6761daf78d Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 23 Aug 2023 17:31:45 -0700 Subject: [PATCH 53/81] Updated step to build go binary file --- .github/workflows/aps-cypress-e2e.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 014314bd0..9c12df626 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -49,10 +49,11 @@ jobs: # cd gwa-cli # just build - name: Build GO binary file - uses: wangyoucao577/go-release-action@v1 + uses: wangyoucao577/go-release-action@v1.16 with: goos: linux goarch: amd64 + project_path: "gwa-cli" binary_name: "gwa" - name: Move file to /usr/local/bin From ff2e3a0bddfa361908c650c70f3ec8eca14f86b9 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 23 Aug 2023 21:47:45 -0700 Subject: [PATCH 54/81] Update step to build go binary --- .github/workflows/aps-cypress-e2e.yaml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 9c12df626..75e81b0a9 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -44,17 +44,11 @@ jobs: with: just-version: 1.14.0 - # - name: Build - # run: | - # cd gwa-cli - # just build - - name: Build GO binary file - uses: wangyoucao577/go-release-action@v1.16 - with: - goos: linux - goarch: amd64 - project_path: "gwa-cli" - binary_name: "gwa" + - name: Build + run: | + cd gwa-cli + env GOOS=linux GOARCH=arm64 go build -o gwa + - name: Move file to /usr/local/bin run: | From 9b3f8d00e5d95480826c149ee297b5c378ae459f Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 23 Aug 2023 21:51:04 -0700 Subject: [PATCH 55/81] Commented the GWA help step --- .github/workflows/aps-cypress-e2e.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 75e81b0a9..b5ed1d551 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -55,8 +55,8 @@ jobs: cd gwa-cli sudo mv gwa /usr/local/bin/ - - name: Check GWA help - run: gwa -h + # - name: Check GWA help + # run: gwa -h - name: Checkout Portal uses: actions/checkout@v2 From 4c413d8651fb0658e4d7391dd9509efd6f6f1180 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 23 Aug 2023 22:57:45 -0700 Subject: [PATCH 56/81] Commented step to set up just and create issue in github --- .github/workflows/aps-cypress-e2e.yaml | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index b5ed1d551..74dba9295 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -39,10 +39,10 @@ jobs: echo "GWA_API_HOST=api-services-portal-feature-gwa-cli-v2.apps.silver.devops.gov.bc.ca" >> .env echo "GWA_CLIENT_ID=gwa-cli" >> .env - - name: set up Just - uses: extractions/setup-just@v1 - with: - just-version: 1.14.0 + # - name: set up Just + # uses: extractions/setup-just@v1 + # with: + # just-version: 1.14.0 - name: Build run: | @@ -114,15 +114,15 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - - name: Check for failed tests and create Issue - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - FAILURE_COUNT=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.stats.failures') - if [[ "$FAILURE_COUNT" -gt 0 ]]; then - FAILED_TESTS=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.results | .[] | .suites | .[].tests | .[] | select(.fail==true) | .title') - STATS=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.stats') - echo -e "Stats: $STATS\n\nFailed Tests:\n$FAILED_TESTS\n\nRun Link: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" > msg - export MSG=$(cat msg) - gh issue create --title "FAILED: Automated Tests($FAILURE_COUNT)" --body "$MSG" --label "automation" --assignee "${{ env.GIT_COMMIT_AUTHOR }}" - fi + # - name: Check for failed tests and create Issue + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # run: | + # FAILURE_COUNT=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.stats.failures') + # if [[ "$FAILURE_COUNT" -gt 0 ]]; then + # FAILED_TESTS=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.results | .[] | .suites | .[].tests | .[] | select(.fail==true) | .title') + # STATS=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.stats') + # echo -e "Stats: $STATS\n\nFailed Tests:\n$FAILED_TESTS\n\nRun Link: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" > msg + # export MSG=$(cat msg) + # gh issue create --title "FAILED: Automated Tests($FAILURE_COUNT)" --body "$MSG" --label "automation" --assignee "${{ env.GIT_COMMIT_AUTHOR }}" + # fi From 0a540dc62c9ee885cc78c5c9b4c1db3eff5dbe75 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Thu, 24 Aug 2023 08:19:58 -0700 Subject: [PATCH 57/81] update command to build go binary file in the workflow file --- .github/workflows/aps-cypress-e2e.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 74dba9295..b22bdb05c 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -47,13 +47,13 @@ jobs: - name: Build run: | cd gwa-cli - env GOOS=linux GOARCH=arm64 go build -o gwa + env GOOS=linux GOARCH=arm64 go build -o bin/gwa - name: Move file to /usr/local/bin run: | cd gwa-cli - sudo mv gwa /usr/local/bin/ + sudo mv bin/gwa /usr/local/bin/ # - name: Check GWA help # run: gwa -h From 4e63f46e8625036d206f7ef0f686edde91af8dbe Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Thu, 24 Aug 2023 11:31:19 -0700 Subject: [PATCH 58/81] Update steps to download and build go --- .github/workflows/aps-cypress-e2e.yaml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index b22bdb05c..73945a350 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -29,10 +29,10 @@ jobs: git clone https://github.com/bcgov/gwa-cli.git -b dev cd gwa-cli - - name: Set up Go + - name: Setup Go uses: actions/setup-go@v4 with: - go-version: '1.20.5' + go-version: '1.16.x' - name: create .env file run: | @@ -45,15 +45,10 @@ jobs: # just-version: 1.14.0 - name: Build - run: | - cd gwa-cli - env GOOS=linux GOARCH=arm64 go build -o bin/gwa - + run: env GOOS=linux GOARCH=arm64 go build -o bin/gwa - name: Move file to /usr/local/bin - run: | - cd gwa-cli - sudo mv bin/gwa /usr/local/bin/ + run: sudo mv bin/gwa /usr/local/bin/ # - name: Check GWA help # run: gwa -h From 6634f6d08e5598cab310df713869438e0a4f412e Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Thu, 24 Aug 2023 11:35:27 -0700 Subject: [PATCH 59/81] Added go tidy command --- .github/workflows/aps-cypress-e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 73945a350..d75c831c9 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -45,7 +45,7 @@ jobs: # just-version: 1.14.0 - name: Build - run: env GOOS=linux GOARCH=arm64 go build -o bin/gwa + run: go mod tidy && env GOOS=linux GOARCH=arm64 go build -o bin/gwa - name: Move file to /usr/local/bin run: sudo mv bin/gwa /usr/local/bin/ From 61baf2ff7fb39ab801390ccc319b864cf903dc7b Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Thu, 24 Aug 2023 11:39:33 -0700 Subject: [PATCH 60/81] Updated the build file in the workflow file --- .github/workflows/aps-cypress-e2e.yaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index d75c831c9..e83a673f8 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -45,10 +45,16 @@ jobs: # just-version: 1.14.0 - name: Build - run: go mod tidy && env GOOS=linux GOARCH=arm64 go build -o bin/gwa + run: | + cd gwa-cli + go mod tidy + env GOOS=linux GOARCH=arm64 go build -o bin/gwa + - name: Move file to /usr/local/bin - run: sudo mv bin/gwa /usr/local/bin/ + run: | + cd gwa-cli + sudo mv bin/gwa /usr/local/bin/ # - name: Check GWA help # run: gwa -h From d4a5813138184027040ef7b106ea1c416262d852 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Thu, 24 Aug 2023 11:53:42 -0700 Subject: [PATCH 61/81] Downgrade go to 1.16 --- .github/workflows/aps-cypress-e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index e83a673f8..f072f2e67 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -32,7 +32,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v4 with: - go-version: '1.16.x' + go-version: '1.16' - name: create .env file run: | From eb322d2bba498695e7df1d0429ec6dd669505d25 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Thu, 24 Aug 2023 12:00:21 -0700 Subject: [PATCH 62/81] Update action go setup --- .github/workflows/aps-cypress-e2e.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index f072f2e67..ba1cfbbec 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -30,9 +30,9 @@ jobs: cd gwa-cli - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v2 with: - go-version: '1.16' + go-version: '1.20' - name: create .env file run: | From ca62aa4029c8e8b560d60dc6a96fce606a487722 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 30 Aug 2023 15:11:13 -0700 Subject: [PATCH 63/81] Updated Github action workflow to install GWA CLI executable binary and run cypress test --- .github/workflows/aps-cypress-e2e.yaml | 51 ++++++++++---------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index ba1cfbbec..6f72ad86b 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -32,40 +32,27 @@ jobs: - name: Setup Go uses: actions/setup-go@v2 with: - go-version: '1.20' + go-version: '1.19.x' - name: create .env file run: | echo "GWA_API_HOST=api-services-portal-feature-gwa-cli-v2.apps.silver.devops.gov.bc.ca" >> .env echo "GWA_CLIENT_ID=gwa-cli" >> .env - # - name: set up Just - # uses: extractions/setup-just@v1 - # with: - # just-version: 1.14.0 - - name: Build run: | cd gwa-cli - go mod tidy - env GOOS=linux GOARCH=arm64 go build -o bin/gwa - - - - name: Move file to /usr/local/bin - run: | - cd gwa-cli - sudo mv bin/gwa /usr/local/bin/ + go clean + go build -o ${{ github.workspace }}/e2e/gwa - # - name: Check GWA help - # run: gwa -h + - uses: actions/upload-artifact@v2 + with: + name: binary-artifact + path: ${{ github.workspace }}/e2e - name: Checkout Portal uses: actions/checkout@v2 - - name: Move file to e2e folder - run: | - sudo mv /usr/local/bin/gwa ${{ github.workspace }}/e2e - - name: Build Docker Images run: | docker-compose build @@ -115,15 +102,15 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - # - name: Check for failed tests and create Issue - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # run: | - # FAILURE_COUNT=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.stats.failures') - # if [[ "$FAILURE_COUNT" -gt 0 ]]; then - # FAILED_TESTS=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.results | .[] | .suites | .[].tests | .[] | select(.fail==true) | .title') - # STATS=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.stats') - # echo -e "Stats: $STATS\n\nFailed Tests:\n$FAILED_TESTS\n\nRun Link: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" > msg - # export MSG=$(cat msg) - # gh issue create --title "FAILED: Automated Tests($FAILURE_COUNT)" --body "$MSG" --label "automation" --assignee "${{ env.GIT_COMMIT_AUTHOR }}" - # fi + - name: Check for failed tests and create Issue + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + FAILURE_COUNT=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.stats.failures') + if [[ "$FAILURE_COUNT" -gt 0 ]]; then + FAILED_TESTS=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.results | .[] | .suites | .[].tests | .[] | select(.fail==true) | .title') + STATS=$(cat ${{ github.workspace }}/e2e/results/bcgov-aps-e2e-report.json | jq '.stats') + echo -e "Stats: $STATS\n\nFailed Tests:\n$FAILED_TESTS\n\nRun Link: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" > msg + export MSG=$(cat msg) + gh issue create --title "FAILED: Automated Tests($FAILURE_COUNT)" --body "$MSG" --label "automation" --assignee "${{ env.GIT_COMMIT_AUTHOR }}" + fi From 8a33311b8e06fa6ac7b43d36a7b6fa43df11ed7d Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 30 Aug 2023 15:24:27 -0700 Subject: [PATCH 64/81] Update the workflow file --- .github/workflows/aps-cypress-e2e.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 6f72ad86b..f2b852b4b 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -29,6 +29,9 @@ jobs: git clone https://github.com/bcgov/gwa-cli.git -b dev cd gwa-cli + - name: Checkout Portal + uses: actions/checkout@v2 + - name: Setup Go uses: actions/setup-go@v2 with: @@ -50,9 +53,6 @@ jobs: name: binary-artifact path: ${{ github.workspace }}/e2e - - name: Checkout Portal - uses: actions/checkout@v2 - - name: Build Docker Images run: | docker-compose build From 835d2216cf1f56a5765f7aceaeb2f5a9f0eb3b1b Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 30 Aug 2023 15:54:46 -0700 Subject: [PATCH 65/81] Update in the workflow step and removed unused code --- .github/workflows/aps-cypress-e2e.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index f2b852b4b..23b5db5ca 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -24,14 +24,14 @@ jobs: cd gwa-api/microservices/gatewayApi docker build -t gwa-api:e2e . + - name: Checkout Portal + uses: actions/checkout@v2 + - name: Checkout Source Repository run: | git clone https://github.com/bcgov/gwa-cli.git -b dev cd gwa-cli - - name: Checkout Portal - uses: actions/checkout@v2 - - name: Setup Go uses: actions/setup-go@v2 with: @@ -39,9 +39,13 @@ jobs: - name: create .env file run: | + cd gwa-cli echo "GWA_API_HOST=api-services-portal-feature-gwa-cli-v2.apps.silver.devops.gov.bc.ca" >> .env echo "GWA_CLIENT_ID=gwa-cli" >> .env + - name: Debug + run: echo ${{ github.workspace }} + - name: Build run: | cd gwa-cli @@ -52,7 +56,7 @@ jobs: with: name: binary-artifact path: ${{ github.workspace }}/e2e - + - name: Build Docker Images run: | docker-compose build From ba9743be6f2cf5b1b40ae5c2a4a39358c3f60c30 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 30 Aug 2023 18:11:59 -0700 Subject: [PATCH 66/81] Uncomment test in cypress config file --- e2e/cypress.config.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index 81fd35f71..97d36458a 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -11,22 +11,22 @@ export default defineConfig({ // // It's IMPORTANT to return the config object // // with any changed environment variables config.specPattern=[ - // './cypress/tests/01-*/*.ts', - // './cypress/tests/02-*/*.ts', - // './cypress/tests/06-*/*.ts', - // './cypress/tests/07-*/*.ts', - // './cypress/tests/03-*/*.ts', - // './cypress/tests/04-*/*.ts', - // './cypress/tests/05-*/*.ts', - // './cypress/tests/08-*/*.ts', - // './cypress/tests/09-*/*.ts', - // './cypress/tests/10-*/*.ts', - // './cypress/tests/11-*/*.ts', - // './cypress/tests/12-*/*.ts', - // './cypress/tests/14-*/*.ts', - // './cypress/tests/15-*/*.ts', - // './cypress/tests/16-*/*.ts', - // './cypress/tests/13-*/*.ts', + './cypress/tests/01-*/*.ts', + './cypress/tests/02-*/*.ts', + './cypress/tests/06-*/*.ts', + './cypress/tests/07-*/*.ts', + './cypress/tests/03-*/*.ts', + './cypress/tests/04-*/*.ts', + './cypress/tests/05-*/*.ts', + './cypress/tests/08-*/*.ts', + './cypress/tests/09-*/*.ts', + './cypress/tests/10-*/*.ts', + './cypress/tests/11-*/*.ts', + './cypress/tests/12-*/*.ts', + './cypress/tests/14-*/*.ts', + './cypress/tests/15-*/*.ts', + './cypress/tests/16-*/*.ts', + './cypress/tests/13-*/*.ts', './cypress/tests/19-*/*.ts' ] return config From 352919fbbaefd70fe0923849349ca3ddd07fba08 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Thu, 31 Aug 2023 10:40:33 -0700 Subject: [PATCH 67/81] Change assertion type from equals to contains --- e2e/cypress/support/auth-commands.ts | 2 +- e2e/cypress/tests/01-api-key/01-create-api.cy.ts | 4 ++-- e2e/cypress/tests/01-api-key/08-gwa-get.ts | 2 +- .../01-client-cred-team-access.cy.ts | 2 +- e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts | 2 +- e2e/cypress/tests/12-access-permission/01-create-api.cy.ts | 2 +- .../tests/13-delete-application/04-delete-namespace-gwa.ts | 4 ++-- .../tests/14-namespace-preview-mode/01-create-api.cy.ts | 2 +- .../tests/15-org-assignment/01-client-cred-team-access.ts | 2 +- e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts | 2 +- .../tests/15-org-assignment/03-multiple-org-admin-org-unit.ts | 2 +- e2e/cypress/tests/16-aps-api/01-create-api.cy.ts | 2 +- e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts | 2 +- e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts | 4 ++-- e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts | 4 ++-- e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts | 2 +- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts index f79ab4561..5035d2e11 100644 --- a/e2e/cypress/support/auth-commands.ts +++ b/e2e/cypress/support/auth-commands.ts @@ -262,7 +262,7 @@ Cypress.Commands.add('publishApi', (fileName: string, namespace: string, flag?: cy.executeCliCommand('gwa config set --namespace ' + namespace).then((response) => { cy.executeCliCommand('gwa config set --token ' + res.body.access_token).then((response) => { { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") cy.executeCliCommand('gwa pg ./cypress/fixtures/' + fileName).then((response) => { debugger expect(response.stdout).to.contain("Gateway config published") diff --git a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts index 7ac036f63..5913ee86d 100644 --- a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts +++ b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts @@ -37,13 +37,13 @@ describe('Create API Spec', () => { it('Check gwa config command to set environment', () => { var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); cy.executeCliCommand('gwa config set --host '+cleanedUrl+' --scheme http').then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) it('Check gwa config command to set token', () => { cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/01-api-key/08-gwa-get.ts b/e2e/cypress/tests/01-api-key/08-gwa-get.ts index 183e7da09..f39e1f99a 100644 --- a/e2e/cypress/tests/01-api-key/08-gwa-get.ts +++ b/e2e/cypress/tests/01-api-key/08-gwa-get.ts @@ -35,7 +35,7 @@ describe('Verify GWA get commands', () => { it('Check gwa config command to set token', () => { cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts b/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts index 89a234fbe..24e2c4b36 100644 --- a/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts +++ b/e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts @@ -32,7 +32,7 @@ describe('Grant appropriate permissions to team members for client credential fl it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts b/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts index 68d052395..9ffeb309f 100644 --- a/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts +++ b/e2e/cypress/tests/10-clear-resources/01-create-api.cy.ts @@ -35,7 +35,7 @@ describe('Create API Spec for Delete Resources', () => { it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts b/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts index 7c9c82f68..f30f59aa4 100644 --- a/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts +++ b/e2e/cypress/tests/12-access-permission/01-create-api.cy.ts @@ -35,7 +35,7 @@ describe('Create API Spec', () => { it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts b/e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts index b193b10fa..219282ac6 100644 --- a/e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts +++ b/e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts @@ -27,7 +27,7 @@ describe('Verify namespace delete using gwa command', () => { it('Set token using gwa config command', () => { cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) @@ -54,7 +54,7 @@ describe('Verify namespace delete using gwa command', () => { cy.get('@apiowner').then(({ namespace }: any) => { _namespace = namespace cy.executeCliCommand('gwa config set --namespace ' + namespace).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") cy.executeCliCommand('gwa namespace destroy').then((response) => { expect(response.stderr).to.contain('services have been configured in this namespace'); }); diff --git a/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts b/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts index 9f9ac4455..c1c977618 100644 --- a/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts +++ b/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts @@ -35,7 +35,7 @@ describe('Create API Spec', () => { it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts b/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts index 1bcf051b0..3d491297b 100644 --- a/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts +++ b/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts @@ -43,7 +43,7 @@ describe('Add Organization to publish API', () => { it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts b/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts index 0d62f19e5..4a04424c9 100644 --- a/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts +++ b/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts @@ -92,7 +92,7 @@ describe('Multiple Org Adming for the organization', () => { it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts b/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts index 31462b969..2d10435b5 100644 --- a/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts +++ b/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts @@ -108,7 +108,7 @@ describe('Multiple Org Admin for the organization', () => { it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts b/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts index 1da1f8f0a..d47a5fa60 100644 --- a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts +++ b/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts @@ -35,7 +35,7 @@ describe('Create API Spec', () => { it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts b/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts index eb72c6ca4..34f0c0ada 100644 --- a/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts +++ b/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts @@ -33,7 +33,7 @@ describe('Get the user session token', () => { it('Set token with gwa config command', () => { cy.exec('gwa config set --token ' + userSession, { timeout: 3000, failOnNonZeroExit: false }).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) }) diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts index 4bca4791f..08222a4b6 100644 --- a/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts +++ b/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts @@ -83,13 +83,13 @@ describe('Verify CLI commands', () => { it('Check gwa config command to set environment', () => { var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); cy.executeCliCommand('gwa config set --host '+cleanedUrl+' --scheme http').then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) it('Check gwa config command to set token', () => { cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts index 95680db17..9538323c9 100644 --- a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts +++ b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts @@ -48,13 +48,13 @@ describe('Verify CLI commands', () => { it('Check gwa config command to set environment', () => { cy.executeCliCommand('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http').then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) it('Check gwa config command to set token', () => { cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - assert.equal(response.stdout, "Config settings saved") + expect(response.stdout).to.contain("Config settings saved") }); }) diff --git a/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts b/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts index 22a35f443..651edf39b 100644 --- a/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts +++ b/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts @@ -41,7 +41,7 @@ describe('Verify CLI commands', () => { // it('Check gwa config command to set token', () => { // cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - // assert.equal(response.stdout, "Config settings saved") + // expect(response.stdout).to.contain("Config settings saved") // }); // }) From edd16d3e560aca2b7d243ea9bfa5438d79f1f6b4 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Fri, 1 Sep 2023 12:43:37 -0700 Subject: [PATCH 68/81] Increased time out in cy exec command --- e2e/cypress/support/util-commands.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts index 963055675..adc305382 100644 --- a/e2e/cypress/support/util-commands.ts +++ b/e2e/cypress/support/util-commands.ts @@ -136,7 +136,8 @@ Cypress.Commands.add('updateJsonValue', (filePath: string, jsonPath: string, new }) Cypress.Commands.add('executeCliCommand', (command: string) => { - cy.exec(command, { timeout: 6000, failOnNonZeroExit: false }).then((response) => { + cy.exec(command, { timeout: 9000, failOnNonZeroExit: false }).then((response) => { + cy.wait(3000) return response }); }) From f0e78c2ef3e4522dd5f0ae5f4ce6db4ace0a4455 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Fri, 1 Sep 2023 12:59:29 -0700 Subject: [PATCH 69/81] Remove wait statement inside cy exec command --- e2e/cypress/support/util-commands.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts index adc305382..e52fcde09 100644 --- a/e2e/cypress/support/util-commands.ts +++ b/e2e/cypress/support/util-commands.ts @@ -137,7 +137,6 @@ Cypress.Commands.add('updateJsonValue', (filePath: string, jsonPath: string, new Cypress.Commands.add('executeCliCommand', (command: string) => { cy.exec(command, { timeout: 9000, failOnNonZeroExit: false }).then((response) => { - cy.wait(3000) return response }); }) From 0a5c95ba11e8040afb0c5fb3e62b4672ab1d1f28 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 4 Sep 2023 10:05:54 -0700 Subject: [PATCH 70/81] Re order the spec files for execution in CI/CD --- .../03-request-access-inactive-env.cy.ts | 143 ++++++++++++++++++ .../01-create-api.cy.ts | 0 .../02-namespace-preview-mode.cy.ts | 0 .../01-client-cred-team-access.ts | 0 .../02-multiple-org-admin.ts | 0 .../03-multiple-org-admin-org-unit.ts | 0 .../01-create-api.cy.ts | 0 .../02-organization.cy.ts | 0 .../03-documentation.cy.ts | 0 .../04-keycloak-shared-IDP-config.cy.ts | 0 .../05-authorizationProfiles.cy.ts | 0 .../06-products.cy.ts | 0 .../07-api-directory.cy.ts | 0 .../08-namespaces.cy.ts | 0 .../{17-CORS => 16-CORS}/01-create-api.cy.ts | 0 .../01-cli-commands.ts | 40 ++--- .../02-cli-generate-config.ts | 53 ++++--- e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts | 85 ----------- ...01-delete-application-without-access.cy.ts | 0 ...ete-application-with-pending-request.cy.ts | 0 ...te-application-with-approved-request.cy.ts | 0 .../04-delete-namespace-gwa.ts | 0 e2e/cypress/tests/19-gwa-test/01-cli-demo.ts | 37 ----- 23 files changed, 183 insertions(+), 175 deletions(-) create mode 100644 e2e/cypress/tests/01-api-key/03-request-access-inactive-env.cy.ts rename e2e/cypress/tests/{14-namespace-preview-mode => 13-namespace-preview-mode}/01-create-api.cy.ts (100%) rename e2e/cypress/tests/{14-namespace-preview-mode => 13-namespace-preview-mode}/02-namespace-preview-mode.cy.ts (100%) rename e2e/cypress/tests/{15-org-assignment => 14-org-assignment}/01-client-cred-team-access.ts (100%) rename e2e/cypress/tests/{15-org-assignment => 14-org-assignment}/02-multiple-org-admin.ts (100%) rename e2e/cypress/tests/{15-org-assignment => 14-org-assignment}/03-multiple-org-admin-org-unit.ts (100%) rename e2e/cypress/tests/{16-aps-api => 15-aps-api}/01-create-api.cy.ts (100%) rename e2e/cypress/tests/{16-aps-api => 15-aps-api}/02-organization.cy.ts (100%) rename e2e/cypress/tests/{16-aps-api => 15-aps-api}/03-documentation.cy.ts (100%) rename e2e/cypress/tests/{16-aps-api => 15-aps-api}/04-keycloak-shared-IDP-config.cy.ts (100%) rename e2e/cypress/tests/{16-aps-api => 15-aps-api}/05-authorizationProfiles.cy.ts (100%) rename e2e/cypress/tests/{16-aps-api => 15-aps-api}/06-products.cy.ts (100%) rename e2e/cypress/tests/{16-aps-api => 15-aps-api}/07-api-directory.cy.ts (100%) rename e2e/cypress/tests/{16-aps-api => 15-aps-api}/08-namespaces.cy.ts (100%) rename e2e/cypress/tests/{17-CORS => 16-CORS}/01-create-api.cy.ts (100%) rename e2e/cypress/tests/{18 -gwa-cli => 17-gwa-cli}/01-cli-commands.ts (71%) rename e2e/cypress/tests/{18 -gwa-cli => 17-gwa-cli}/02-cli-generate-config.ts (53%) delete mode 100644 e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts rename e2e/cypress/tests/{13-delete-application => 18-delete-application}/01-delete-application-without-access.cy.ts (100%) rename e2e/cypress/tests/{13-delete-application => 18-delete-application}/02-delete-application-with-pending-request.cy.ts (100%) rename e2e/cypress/tests/{13-delete-application => 18-delete-application}/03-delete-application-with-approved-request.cy.ts (100%) rename e2e/cypress/tests/{13-delete-application => 18-delete-application}/04-delete-namespace-gwa.ts (100%) delete mode 100644 e2e/cypress/tests/19-gwa-test/01-cli-demo.ts diff --git a/e2e/cypress/tests/01-api-key/03-request-access-inactive-env.cy.ts b/e2e/cypress/tests/01-api-key/03-request-access-inactive-env.cy.ts new file mode 100644 index 000000000..ddf82c7b4 --- /dev/null +++ b/e2e/cypress/tests/01-api-key/03-request-access-inactive-env.cy.ts @@ -0,0 +1,143 @@ +// import ApiDirectoryPage from '../../pageObjects/apiDirectory' +// import ApplicationPage from '../../pageObjects/applications' +// import HomePage from '../../pageObjects/home' +// import LoginPage from '../../pageObjects/login' +// import NamespaceAccessPage from '../../pageObjects/namespaceAccess' +// import Products from '../../pageObjects/products' +// import MyAccessPage from '../../pageObjects/myAccess' + +// describe('Change an Active environment to Inactive', () => { +// const login = new LoginPage() +// const home = new HomePage() +// const na = new NamespaceAccessPage() +// const pd = new Products() + +// before(() => { +// cy.visit('/') +// cy.deleteAllCookies() +// cy.reload() +// }) + +// beforeEach(() => { +// cy.preserveCookies() +// cy.fixture('apiowner').as('apiowner') +// // cy.visit(login.path) +// }) + +// it('authenticates Janis (api owner)', () => { +// cy.get('@apiowner').then(({ user, namespace }: any) => { +// cy.login(user.credentials.username, user.credentials.password) +// cy.log('Logged in!') +// home.useNamespace(namespace) +// }) +// }) + +// it('Navigate to Products Page', () => { +// cy.visit(pd.path) +// }) + +// it('Change the current active environment to inactive state', () => { +// cy.get('@apiowner').then(({ product }: any) => { +// pd.editProductEnvironment(product.name, product.environment.name) +// pd.editProductEnvironmentConfig(product.environment.config, true) +// }) +// }) + +// after(() => { +// cy.logout() +// cy.clearLocalStorage({ log: true }) +// cy.deleteAllCookies() +// }) +// }) + +// describe('Verify enactive environment in rrequest access pop up', () => { +// const apiDir = new ApiDirectoryPage() +// const app = new ApplicationPage() +// const myAccessPage = new MyAccessPage() + +// before(() => { +// cy.visit('/') +// cy.deleteAllCookies() +// cy.reload() +// }) + +// beforeEach(() => { +// cy.preserveCookies() +// cy.fixture('developer').as('developer') +// // cy.visit(login.path) +// }) + +// it('authenticates Harley (developer)', () => { +// cy.get('@developer').then(({ user }: any) => { +// cy.login(user.credentials.username, user.credentials.password) +// }) +// }) + +// it('creates an application', () => { +// cy.visit(app.path) +// cy.get('@developer').then(({ application }: any) => { +// app.createApplication(application) +// }) +// }) + +// it('Verify that inactive environment is not displayed', () => { +// cy.visit(apiDir.path) +// cy.get('@developer').then(({ product, application }: any) => { +// apiDir.checkInactiveEnvironmentAccessReqOption(product, application) +// }) +// }) + +// it('Close the popup by click on Cancel button', () => { +// myAccessPage.cancelRequestAccessPopUp() +// }) + +// after(() => { +// cy.logout() +// cy.clearLocalStorage({ log: true }) +// cy.deleteAllCookies() +// }) +// }) + +// describe('Change an the environment back to active', () => { +// const login = new LoginPage() +// const home = new HomePage() +// const na = new NamespaceAccessPage() +// const pd = new Products() + +// before(() => { +// cy.visit('/') +// cy.deleteAllCookies() +// cy.reload() +// }) + +// beforeEach(() => { +// cy.preserveCookies() +// cy.fixture('apiowner').as('apiowner') +// // cy.visit(login.path) +// }) + +// it('authenticates Janis (api owner)', () => { +// cy.get('@apiowner').then(({ user, namespace }: any) => { +// cy.login(user.credentials.username, user.credentials.password) +// cy.log('Logged in!') +// home.useNamespace(namespace) +// }) +// }) + +// it('Navigate to Products Page', () => { +// cy.visit(pd.path) +// }) + +// it('Change the environment back to active state', () => { +// cy.get('@apiowner').then(({ product }: any) => { +// pd.editProductEnvironment(product.name, product.environment.name) +// pd.editProductEnvironmentConfig(product.environment.config) +// }) +// }) + +// after(() => { +// cy.logout() +// cy.clearLocalStorage({ log: true }) +// cy.deleteAllCookies() +// }) +// }) \ No newline at end of file diff --git a/e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts b/e2e/cypress/tests/13-namespace-preview-mode/01-create-api.cy.ts similarity index 100% rename from e2e/cypress/tests/14-namespace-preview-mode/01-create-api.cy.ts rename to e2e/cypress/tests/13-namespace-preview-mode/01-create-api.cy.ts diff --git a/e2e/cypress/tests/14-namespace-preview-mode/02-namespace-preview-mode.cy.ts b/e2e/cypress/tests/13-namespace-preview-mode/02-namespace-preview-mode.cy.ts similarity index 100% rename from e2e/cypress/tests/14-namespace-preview-mode/02-namespace-preview-mode.cy.ts rename to e2e/cypress/tests/13-namespace-preview-mode/02-namespace-preview-mode.cy.ts diff --git a/e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts b/e2e/cypress/tests/14-org-assignment/01-client-cred-team-access.ts similarity index 100% rename from e2e/cypress/tests/15-org-assignment/01-client-cred-team-access.ts rename to e2e/cypress/tests/14-org-assignment/01-client-cred-team-access.ts diff --git a/e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts b/e2e/cypress/tests/14-org-assignment/02-multiple-org-admin.ts similarity index 100% rename from e2e/cypress/tests/15-org-assignment/02-multiple-org-admin.ts rename to e2e/cypress/tests/14-org-assignment/02-multiple-org-admin.ts diff --git a/e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts b/e2e/cypress/tests/14-org-assignment/03-multiple-org-admin-org-unit.ts similarity index 100% rename from e2e/cypress/tests/15-org-assignment/03-multiple-org-admin-org-unit.ts rename to e2e/cypress/tests/14-org-assignment/03-multiple-org-admin-org-unit.ts diff --git a/e2e/cypress/tests/16-aps-api/01-create-api.cy.ts b/e2e/cypress/tests/15-aps-api/01-create-api.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/01-create-api.cy.ts rename to e2e/cypress/tests/15-aps-api/01-create-api.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/02-organization.cy.ts b/e2e/cypress/tests/15-aps-api/02-organization.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/02-organization.cy.ts rename to e2e/cypress/tests/15-aps-api/02-organization.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/03-documentation.cy.ts b/e2e/cypress/tests/15-aps-api/03-documentation.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/03-documentation.cy.ts rename to e2e/cypress/tests/15-aps-api/03-documentation.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/04-keycloak-shared-IDP-config.cy.ts b/e2e/cypress/tests/15-aps-api/04-keycloak-shared-IDP-config.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/04-keycloak-shared-IDP-config.cy.ts rename to e2e/cypress/tests/15-aps-api/04-keycloak-shared-IDP-config.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts b/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts rename to e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/06-products.cy.ts b/e2e/cypress/tests/15-aps-api/06-products.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/06-products.cy.ts rename to e2e/cypress/tests/15-aps-api/06-products.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts b/e2e/cypress/tests/15-aps-api/07-api-directory.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts rename to e2e/cypress/tests/15-aps-api/07-api-directory.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/08-namespaces.cy.ts b/e2e/cypress/tests/15-aps-api/08-namespaces.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/08-namespaces.cy.ts rename to e2e/cypress/tests/15-aps-api/08-namespaces.cy.ts diff --git a/e2e/cypress/tests/17-CORS/01-create-api.cy.ts b/e2e/cypress/tests/16-CORS/01-create-api.cy.ts similarity index 100% rename from e2e/cypress/tests/17-CORS/01-create-api.cy.ts rename to e2e/cypress/tests/16-CORS/01-create-api.cy.ts diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts b/e2e/cypress/tests/17-gwa-cli/01-cli-commands.ts similarity index 71% rename from e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts rename to e2e/cypress/tests/17-gwa-cli/01-cli-commands.ts index 08222a4b6..86e8972fa 100644 --- a/e2e/cypress/tests/18 -gwa-cli/01-cli-commands.ts +++ b/e2e/cypress/tests/17-gwa-cli/01-cli-commands.ts @@ -35,32 +35,20 @@ describe('Verify CLI commands', () => { }) }) - it('Check for gwa help', () => { - cy.executeCliCommand('gwa help').then((response) => { - debugger - assert.equal(response.stdout, cli.content.help) - }); - }) - - it('Check gwa command for login help', () => { - cy.executeCliCommand('gwa login -h').then((response) => { - assert.equal(response.stdout, cli.content.login_help) - }); - }) it('Check gwa command to login with client ID and secret', () => { let clientID = cli.credentials.clientID let clientSecret = cli.credentials.clientSecret cy.log('gwa login --host ${url} --scheme http') cy.executeCliCommand('gwa login --client-id ' + clientID + ' --client-secret ' + clientSecret + ' --host ' + cleanedUrl + ' --scheme http').then((response) => { - assert.equal(response.stdout, "Logged in") + expect(response.stdout).to.contain('Successfully logged in'); }); }) it('Check gwa command for login with invalid client id', () => { let clientID = "dummy-client" let clientSecret = cli.credentials.clientSecret - cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+cleanedUrl+' --scheme http').then((response) => { + cy.executeCliCommand('gwa login --client-id ' + clientID + ' --client-secret ' + clientSecret + ' --host ' + cleanedUrl + ' --scheme http').then((response) => { assert.equal(response.stderr, "Error: unauthorized_client\nINVALID_CREDENTIALS: Invalid client credentials") }); }) @@ -68,21 +56,15 @@ describe('Verify CLI commands', () => { it('Check gwa command for login with invalid client secret', () => { let clientID = cli.credentials.clientID let clientSecret = "dummy-client-secret" - cy.executeCliCommand('gwa login --client-id '+clientID+' --client-secret '+clientSecret+' --host '+cleanedUrl+' --scheme http').then((response) => { + cy.executeCliCommand('gwa login --client-id ' + clientID + ' --client-secret ' + clientSecret + ' --host ' + cleanedUrl + ' --scheme http').then((response) => { assert.equal(response.stderr, "Error: unauthorized_client\nINVALID_CREDENTIALS: Invalid client credentials") }); }) - it('Check gwa command for config help', () => { - cy.executeCliCommand('gwa config -h').then((response) => { - debugger - assert.equal(response.stdout, cli.content.config_help) - }); - }) it('Check gwa config command to set environment', () => { var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); - cy.executeCliCommand('gwa config set --host '+cleanedUrl+' --scheme http').then((response) => { + cy.executeCliCommand('gwa config set --host ' + cleanedUrl + ' --scheme http').then((response) => { expect(response.stdout).to.contain("Config settings saved") }); }) @@ -93,13 +75,6 @@ describe('Verify CLI commands', () => { }); }) - it('Check gwa command for namespace help', () => { - cy.executeCliCommand('gwa namespace -h').then((response) => { - debugger - assert.equal(response.stdout, cli.content.namespace_help) - }); - }) - it('Check gwa command to create namespace', () => { cy.executeCliCommand('gwa namespace create --host ' + cleanedUrl + ' --scheme http').then((response) => { assert.isNotNaN(response.stdout) @@ -107,10 +82,17 @@ describe('Verify CLI commands', () => { }); }) + it('Check gwa namespace list command and verify the created namespace in the list', () => { cy.executeCliCommand('gwa namespace list --host ' + cleanedUrl + ' --scheme http').then((response) => { expect(response.stdout).to.contain(namespace); }); }) + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + }) \ No newline at end of file diff --git a/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts b/e2e/cypress/tests/17-gwa-cli/02-cli-generate-config.ts similarity index 53% rename from e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts rename to e2e/cypress/tests/17-gwa-cli/02-cli-generate-config.ts index 651edf39b..30d11a689 100644 --- a/e2e/cypress/tests/18 -gwa-cli/02-cli-generate-config.ts +++ b/e2e/cypress/tests/17-gwa-cli/02-cli-generate-config.ts @@ -10,7 +10,7 @@ let cli = require("../../fixtures/test_data/gwa-cli.json") const jose = require('node-jose') -describe('Verify CLI commands', () => { +describe('Verify CLI commands for generate/apply config', () => { const login = new LoginPage() const apiDir = new ApiDirectoryPage() const app = new ApplicationPage() @@ -39,31 +39,36 @@ describe('Verify CLI commands', () => { }) }) - // it('Check gwa config command to set token', () => { - // cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - // expect(response.stdout).to.contain("Config settings saved") - // }); - // }) + it('Check gwa config command to set token', () => { + cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { + expect(response.stdout).to.contain("Config settings saved") + }); + }) + + it('Check gwa command to generate config for client credential template', () => { + cy.executeCliCommand('gwa generate-config --template client-credentials-shared-idp --service my-service --upstream https://httpbin.org --org ministry-of-health --org-unit planning-and-innovation-division').then((response) => { + assert.equal(response.stdout, "File gw-config.yml created") + }); + }) - // it('Check gwa command to generate config', () => { - // cy.executeCliCommand('gwa generate-config --template client-credentials-shared-idp --service my-service --upstream https://httpbin.org --org ministry-of-health --org-unit planning-and-innovation-division').then((response) => { - // assert.equal(response.stdout, "File gw-config.yml created") - // }); - // }) + it('Check gwa command to apply generated config', () => { + cy.executeCliCommand('gwa apply').then((response) => { + debugger + let wordOccurrences = (response.stdout.match(/\bcreated\b/g) || []).length; + expect(wordOccurrences).to.equal(3) + namespace = response.stdout.split('\n')[0] + namespace = namespace.replace('-', '').trim() + }); + }) - // it('Check gwa command to apply generated config', () => { - // cy.executeCliCommand('gwa apply').then((response) => { - // let wordOccurrences = (response.stdout.match(/\bcreated\b/g) || []).length; - // expect(wordOccurrences).to.equal(3) - // wordOccurrences = (response.stdout.match(/\published\b/g) || []).length; - // expect(wordOccurrences).to.equal(1) - // }); - // }) + it('Check gwa command to generate config for kong httpbin template', () => { + cy.executeCliCommand('gwa generate-config --template kong-httpbin --service my-service --upstream https://httpbin.org --org ministry-of-health --org-unit planning-and-innovation-division').then((response) => { + assert.equal(response.stdout, "File gw-config.yml created") + }); + }) it('activates new namespace', () => { - cy.get('@apiowner').then(({ namespace }: any) => { - home.useNamespace(namespace) - }) + home.useNamespace(namespace) }) it('Verify that the product created through gwa command is displayed in the portal', () => { @@ -76,11 +81,11 @@ describe('Verify CLI commands', () => { }) it('Verify the issuer details for the product', () => { - pd.verifyIssuer('gw-d4ed4 default (test)') + pd.verifyIssuer(namespace + ' default (test)') }) it('Verify that the dataset created through GWA comand is assocuated with the product', () => { cy.visit(pd.path) - pd.verifyDataset('my-service','my-service API') + pd.verifyDataset('my-service', 'my-service API') }) }) \ No newline at end of file diff --git a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts b/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts deleted file mode 100644 index 9538323c9..000000000 --- a/e2e/cypress/tests/18 -gwa-cli/01-cli-demo.ts +++ /dev/null @@ -1,85 +0,0 @@ -import LoginPage from '../../pageObjects/login' -import ApplicationPage from '../../pageObjects/applications' -import ApiDirectoryPage from '../../pageObjects/apiDirectory' -import MyAccessPage from '../../pageObjects/myAccess' -const YAML = require('yamljs'); -let userSession: any -let cli = require("../../fixtures/test_data/gwa-cli.json") - -const jose = require('node-jose') - -describe('Verify CLI commands', () => { - const login = new LoginPage() - const apiDir = new ApiDirectoryPage() - const app = new ApplicationPage() - const ma = new MyAccessPage() - let namespace: string - - before(() => { - // cy.visit('/') - cy.deleteAllCookies() - cy.reload() - }) - - beforeEach(() => { - cy.preserveCookies() - cy.fixture('apiowner').as('apiowner') - // cy.visit(login.path) - }) - - it('authenticates Janis (api owner) to get the user session token', () => { - cy.get('@apiowner').then(({ apiTest }: any) => { - cy.getUserSessionTokenValue(apiTest.namespace, false).then((value) => { - userSession = value - }) - }) - }) - - it('Check gwa command to login with client ID and secret', () => { - let url = "oauth2proxy.localtest.me:4180" - let clientID = cli.credentials.clientID - let clientSecret = cli.credentials.clientSecret - cy.log('gwa login --host ${url} --scheme http') - cy.executeCliCommand('gwa login --client-id ' + clientID + ' --client-secret ' + clientSecret + ' --host ' + url + ' --scheme http').then((response) => { - assert.equal(response.stdout, "Logged in") - }); - }) - - - it('Check gwa config command to set environment', () => { - cy.executeCliCommand('gwa config set --host oauth2proxy.localtest.me:4180 --scheme http').then((response) => { - expect(response.stdout).to.contain("Config settings saved") - }); - }) - - it('Check gwa config command to set token', () => { - cy.executeCliCommand('gwa config set --token ' + userSession).then((response) => { - expect(response.stdout).to.contain("Config settings saved") - }); - }) - - it('Check gwa command to create namespace', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.executeCliCommand('gwa namespace create --host ' + url + ' --scheme http').then((response) => { - assert.isNotNaN(response.stdout) - namespace = response.stdout - cy.replaceWordInJsonObject('newplatform', namespace, 'service-gwa.yml') - cy.updateJsonValue('apiowner.json', 'namespace', namespace) - }); - }) - - it('Check gwa namespace list command and verify the created namespace in the list', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.executeCliCommand('gwa namespace list --host ' + url + ' --scheme http').then((response) => { - expect(response.stdout).to.contain(namespace); - }); - }) - - it('Check that deleted namespace does not display in gwa namespace list command', () => { - let url = "oauth2proxy.localtest.me:4180" - cy.executeCliCommand('gwa namespace list').then((response) => { - expect(response.stdout).not.to.contain(namespace); - }); - }) - -}) \ No newline at end of file diff --git a/e2e/cypress/tests/13-delete-application/01-delete-application-without-access.cy.ts b/e2e/cypress/tests/18-delete-application/01-delete-application-without-access.cy.ts similarity index 100% rename from e2e/cypress/tests/13-delete-application/01-delete-application-without-access.cy.ts rename to e2e/cypress/tests/18-delete-application/01-delete-application-without-access.cy.ts diff --git a/e2e/cypress/tests/13-delete-application/02-delete-application-with-pending-request.cy.ts b/e2e/cypress/tests/18-delete-application/02-delete-application-with-pending-request.cy.ts similarity index 100% rename from e2e/cypress/tests/13-delete-application/02-delete-application-with-pending-request.cy.ts rename to e2e/cypress/tests/18-delete-application/02-delete-application-with-pending-request.cy.ts diff --git a/e2e/cypress/tests/13-delete-application/03-delete-application-with-approved-request.cy.ts b/e2e/cypress/tests/18-delete-application/03-delete-application-with-approved-request.cy.ts similarity index 100% rename from e2e/cypress/tests/13-delete-application/03-delete-application-with-approved-request.cy.ts rename to e2e/cypress/tests/18-delete-application/03-delete-application-with-approved-request.cy.ts diff --git a/e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts b/e2e/cypress/tests/18-delete-application/04-delete-namespace-gwa.ts similarity index 100% rename from e2e/cypress/tests/13-delete-application/04-delete-namespace-gwa.ts rename to e2e/cypress/tests/18-delete-application/04-delete-namespace-gwa.ts diff --git a/e2e/cypress/tests/19-gwa-test/01-cli-demo.ts b/e2e/cypress/tests/19-gwa-test/01-cli-demo.ts deleted file mode 100644 index a51ddd82d..000000000 --- a/e2e/cypress/tests/19-gwa-test/01-cli-demo.ts +++ /dev/null @@ -1,37 +0,0 @@ -import LoginPage from '../../pageObjects/login' -import ApplicationPage from '../../pageObjects/applications' -import ApiDirectoryPage from '../../pageObjects/apiDirectory' -import MyAccessPage from '../../pageObjects/myAccess' -const YAML = require('yamljs'); -let userSession: any -let cli = require("../../fixtures/test_data/gwa-cli.json") - -const jose = require('node-jose') - -describe('Verify CLI commands', () => { - const login = new LoginPage() - const apiDir = new ApiDirectoryPage() - const app = new ApplicationPage() - const ma = new MyAccessPage() - let namespace: string - - before(() => { - // cy.visit('/') - cy.deleteAllCookies() - cy.reload() - }) - - beforeEach(() => { - cy.preserveCookies() - cy.fixture('apiowner').as('apiowner') - // cy.visit(login.path) - }) - - - it('Check gwa command for config help', () => { - cy.executeCliCommand('gwa config -h').then((response) => { - expect(response.stdout).to.contain("Configuration commands"); - }); - }) - -}) \ No newline at end of file From ae9be1685791c9078da064ec9a0f2c151926a49b Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Tue, 5 Sep 2023 14:51:32 -0700 Subject: [PATCH 71/81] Update Test scenarios/specs order and added test for zenhub#887 --- .github/workflows/aps-cypress-e2e.yaml | 2 +- e2e/cypress/pageObjects/apiDirectory.ts | 8 + e2e/cypress/pageObjects/authProfile.ts | 15 + e2e/cypress/pageObjects/myAccess.ts | 6 + .../03-request-access-inactive-env.cy.ts | 286 +++++++++--------- ...ess-with-out-collecting-credentials.cy.ts} | 0 ...uest-without-collecting-credentials.cy.ts} | 0 ...als.cy.ts => 06-collect-credentials.cy.ts} | 0 ...st.cy.ts => 07-approve-pending-rqst.cy.ts} | 0 ...ant-access.cy.ts => 08-grant-access.cy.ts} | 0 .../{08-gwa-get.ts => 09-gwa-get.ts} | 2 + .../15-aps-api/05-authorizationProfiles.cy.ts | 94 ++++++ e2e/cypress/tests/16-CORS/01-create-api.cy.ts | 126 -------- .../01-cli-commands.ts | 0 .../02-cli-generate-config.ts | 7 + ...01-delete-application-without-access.cy.ts | 0 ...ete-application-with-pending-request.cy.ts | 0 ...te-application-with-approved-request.cy.ts | 0 .../04-delete-namespace-gwa.ts | 0 19 files changed, 276 insertions(+), 270 deletions(-) rename e2e/cypress/tests/01-api-key/{03-request-access-with-out-collecting-credentials.cy.ts => 04-request-access-with-out-collecting-credentials.cy.ts} (100%) rename e2e/cypress/tests/01-api-key/{04-review-request-without-collecting-credentials.cy.ts => 05-review-request-without-collecting-credentials.cy.ts} (100%) rename e2e/cypress/tests/01-api-key/{05-collect-credentials.cy.ts => 06-collect-credentials.cy.ts} (100%) rename e2e/cypress/tests/01-api-key/{06-approve-pending-rqst.cy.ts => 07-approve-pending-rqst.cy.ts} (100%) rename e2e/cypress/tests/01-api-key/{07-grant-access.cy.ts => 08-grant-access.cy.ts} (100%) rename e2e/cypress/tests/01-api-key/{08-gwa-get.ts => 09-gwa-get.ts} (98%) delete mode 100644 e2e/cypress/tests/16-CORS/01-create-api.cy.ts rename e2e/cypress/tests/{17-gwa-cli => 16-gwa-cli}/01-cli-commands.ts (100%) rename e2e/cypress/tests/{17-gwa-cli => 16-gwa-cli}/02-cli-generate-config.ts (96%) rename e2e/cypress/tests/{18-delete-application => 17-delete-application}/01-delete-application-without-access.cy.ts (100%) rename e2e/cypress/tests/{18-delete-application => 17-delete-application}/02-delete-application-with-pending-request.cy.ts (100%) rename e2e/cypress/tests/{18-delete-application => 17-delete-application}/03-delete-application-with-approved-request.cy.ts (100%) rename e2e/cypress/tests/{18-delete-application => 17-delete-application}/04-delete-namespace-gwa.ts (100%) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 23b5db5ca..dae997fd9 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -2,7 +2,7 @@ name: Build and Deploy Cypress and Execute Tests on: push: - branches: ['test', 'cypress*'] + branches: ['test', 'cypress/*'] env: DASHBOARD_PROJECT_ID: ${{ secrets.CY_DASHBOARD_PRJ_ID }} diff --git a/e2e/cypress/pageObjects/apiDirectory.ts b/e2e/cypress/pageObjects/apiDirectory.ts index f270ccfba..f0911e67e 100644 --- a/e2e/cypress/pageObjects/apiDirectory.ts +++ b/e2e/cypress/pageObjects/apiDirectory.ts @@ -58,6 +58,14 @@ class ApiDirectoryPage { cy.get(this.submitBtn).click() } + checkInactiveEnvironmentAccessReqOption(product: any, app: any){ + cy.contains('a', product.name, { timeout: 10000 }).should('be.visible'); + cy.contains(product.name).click() + cy.get(this.rqstAccessBtn).click() + cy.get(this.appSelect).select(app.name) + cy.get('[data-testid=access-rqst-app-env-' + product.environment + ']').should('not.exist'); + } + isProductDisplay(productName: string, expResult: boolean) { cy.get("button").then(($btn) => { var flag = true diff --git a/e2e/cypress/pageObjects/authProfile.ts b/e2e/cypress/pageObjects/authProfile.ts index 09ce67d09..cb69ccb7a 100644 --- a/e2e/cypress/pageObjects/authProfile.ts +++ b/e2e/cypress/pageObjects/authProfile.ts @@ -165,6 +165,21 @@ class AuthorizationProfile { cy.contains(issuerURL).should('exist') cy.visit(this.path) } + + deleteAuthProfile(authProfileName: string) { + cy.wait(2000) + let authProfileText + cy.get(this.profileTable).find('tr').each(($e1, index, $list) => { + authProfileText = $e1.find('td:nth-child(1)').text(); + if (authProfileText===authProfileName) { + cy.wrap($e1).find('button').eq(1).click() + cy.wait(2000) + cy.wrap($e1).find('button').last().click({force: true}) + cy.verifyToastMessage(authProfileName +' deleted') + return false + } + }) + } } export default AuthorizationProfile diff --git a/e2e/cypress/pageObjects/myAccess.ts b/e2e/cypress/pageObjects/myAccess.ts index 7a200768a..65b5d8bd6 100644 --- a/e2e/cypress/pageObjects/myAccess.ts +++ b/e2e/cypress/pageObjects/myAccess.ts @@ -14,6 +14,7 @@ class myAccessPage { regenerateCredentialCloseBtn: string = '[data-testid=regenerate-credentials-done-button]' collectCredentialsBtn: string = '[data-testid="generate-credentials-button"]' clientIDValueTxt: string = '[data-testid="sa-new-creds-client-id"]' + cancelRequestAccessRequest: string = '[data-testid="access-request-cancel-button"]' path: string = '/devportal/access' @@ -37,6 +38,11 @@ class myAccessPage { cy.get(this.closeRequestAccesss).click() } + cancelRequestAccessPopUp() + { + cy.get(this.cancelRequestAccessRequest).click() + } + saveReGenAPIKeyValue(): void { cy.get(this.apiKyeValueTxt).invoke('val').then(($apiKey: any) => { cy.saveState('newApiKey', $apiKey) diff --git a/e2e/cypress/tests/01-api-key/03-request-access-inactive-env.cy.ts b/e2e/cypress/tests/01-api-key/03-request-access-inactive-env.cy.ts index ddf82c7b4..cf01b89e4 100644 --- a/e2e/cypress/tests/01-api-key/03-request-access-inactive-env.cy.ts +++ b/e2e/cypress/tests/01-api-key/03-request-access-inactive-env.cy.ts @@ -1,143 +1,143 @@ -// import ApiDirectoryPage from '../../pageObjects/apiDirectory' -// import ApplicationPage from '../../pageObjects/applications' -// import HomePage from '../../pageObjects/home' -// import LoginPage from '../../pageObjects/login' -// import NamespaceAccessPage from '../../pageObjects/namespaceAccess' -// import Products from '../../pageObjects/products' -// import MyAccessPage from '../../pageObjects/myAccess' - -// describe('Change an Active environment to Inactive', () => { -// const login = new LoginPage() -// const home = new HomePage() -// const na = new NamespaceAccessPage() -// const pd = new Products() - -// before(() => { -// cy.visit('/') -// cy.deleteAllCookies() -// cy.reload() -// }) - -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('apiowner').as('apiowner') -// // cy.visit(login.path) -// }) - -// it('authenticates Janis (api owner)', () => { -// cy.get('@apiowner').then(({ user, namespace }: any) => { -// cy.login(user.credentials.username, user.credentials.password) -// cy.log('Logged in!') -// home.useNamespace(namespace) -// }) -// }) - -// it('Navigate to Products Page', () => { -// cy.visit(pd.path) -// }) - -// it('Change the current active environment to inactive state', () => { -// cy.get('@apiowner').then(({ product }: any) => { -// pd.editProductEnvironment(product.name, product.environment.name) -// pd.editProductEnvironmentConfig(product.environment.config, true) -// }) -// }) - -// after(() => { -// cy.logout() -// cy.clearLocalStorage({ log: true }) -// cy.deleteAllCookies() -// }) -// }) - -// describe('Verify enactive environment in rrequest access pop up', () => { -// const apiDir = new ApiDirectoryPage() -// const app = new ApplicationPage() -// const myAccessPage = new MyAccessPage() - -// before(() => { -// cy.visit('/') -// cy.deleteAllCookies() -// cy.reload() -// }) - -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('developer').as('developer') -// // cy.visit(login.path) -// }) - -// it('authenticates Harley (developer)', () => { -// cy.get('@developer').then(({ user }: any) => { -// cy.login(user.credentials.username, user.credentials.password) -// }) -// }) - -// it('creates an application', () => { -// cy.visit(app.path) -// cy.get('@developer').then(({ application }: any) => { -// app.createApplication(application) -// }) -// }) - -// it('Verify that inactive environment is not displayed', () => { -// cy.visit(apiDir.path) -// cy.get('@developer').then(({ product, application }: any) => { -// apiDir.checkInactiveEnvironmentAccessReqOption(product, application) -// }) -// }) - -// it('Close the popup by click on Cancel button', () => { -// myAccessPage.cancelRequestAccessPopUp() -// }) - -// after(() => { -// cy.logout() -// cy.clearLocalStorage({ log: true }) -// cy.deleteAllCookies() -// }) -// }) - -// describe('Change an the environment back to active', () => { -// const login = new LoginPage() -// const home = new HomePage() -// const na = new NamespaceAccessPage() -// const pd = new Products() - -// before(() => { -// cy.visit('/') -// cy.deleteAllCookies() -// cy.reload() -// }) - -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('apiowner').as('apiowner') -// // cy.visit(login.path) -// }) - -// it('authenticates Janis (api owner)', () => { -// cy.get('@apiowner').then(({ user, namespace }: any) => { -// cy.login(user.credentials.username, user.credentials.password) -// cy.log('Logged in!') -// home.useNamespace(namespace) -// }) -// }) - -// it('Navigate to Products Page', () => { -// cy.visit(pd.path) -// }) - -// it('Change the environment back to active state', () => { -// cy.get('@apiowner').then(({ product }: any) => { -// pd.editProductEnvironment(product.name, product.environment.name) -// pd.editProductEnvironmentConfig(product.environment.config) -// }) -// }) - -// after(() => { -// cy.logout() -// cy.clearLocalStorage({ log: true }) -// cy.deleteAllCookies() -// }) -// }) \ No newline at end of file +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import ApplicationPage from '../../pageObjects/applications' +import HomePage from '../../pageObjects/home' +import LoginPage from '../../pageObjects/login' +import NamespaceAccessPage from '../../pageObjects/namespaceAccess' +import Products from '../../pageObjects/products' +import MyAccessPage from '../../pageObjects/myAccess' + +describe('Change an Active environment to Inactive', () => { + const login = new LoginPage() + const home = new HomePage() + const na = new NamespaceAccessPage() + const pd = new Products() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + it('authenticates Janis (api owner)', () => { + cy.get('@apiowner').then(({ user, namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + cy.log('Logged in!') + home.useNamespace(namespace) + }) + }) + + it('Navigate to Products Page', () => { + cy.visit(pd.path) + }) + + it('Change the current active environment to inactive state', () => { + cy.get('@apiowner').then(({ product }: any) => { + pd.editProductEnvironment(product.name, product.environment.name) + pd.editProductEnvironmentConfig(product.environment.config, true) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) + +describe('Verify enactive environment in rrequest access pop up', () => { + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const myAccessPage = new MyAccessPage() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + // cy.visit(login.path) + }) + + it('authenticates Harley (developer)', () => { + cy.get('@developer').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + }) + }) + + it('creates an application', () => { + cy.visit(app.path) + cy.get('@developer').then(({ application }: any) => { + app.createApplication(application) + }) + }) + + it('Verify that inactive environment is not displayed', () => { + cy.visit(apiDir.path) + cy.get('@developer').then(({ product, application }: any) => { + apiDir.checkInactiveEnvironmentAccessReqOption(product, application) + }) + }) + + it('Close the popup by click on Cancel button', () => { + myAccessPage.cancelRequestAccessPopUp() + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) + +describe('Change an the environment back to active', () => { + const login = new LoginPage() + const home = new HomePage() + const na = new NamespaceAccessPage() + const pd = new Products() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + it('authenticates Janis (api owner)', () => { + cy.get('@apiowner').then(({ user, namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + cy.log('Logged in!') + home.useNamespace(namespace) + }) + }) + + it('Navigate to Products Page', () => { + cy.visit(pd.path) + }) + + it('Change the environment back to active state', () => { + cy.get('@apiowner').then(({ product }: any) => { + pd.editProductEnvironment(product.name, product.environment.name) + pd.editProductEnvironmentConfig(product.environment.config) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) \ No newline at end of file diff --git a/e2e/cypress/tests/01-api-key/03-request-access-with-out-collecting-credentials.cy.ts b/e2e/cypress/tests/01-api-key/04-request-access-with-out-collecting-credentials.cy.ts similarity index 100% rename from e2e/cypress/tests/01-api-key/03-request-access-with-out-collecting-credentials.cy.ts rename to e2e/cypress/tests/01-api-key/04-request-access-with-out-collecting-credentials.cy.ts diff --git a/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts b/e2e/cypress/tests/01-api-key/05-review-request-without-collecting-credentials.cy.ts similarity index 100% rename from e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.cy.ts rename to e2e/cypress/tests/01-api-key/05-review-request-without-collecting-credentials.cy.ts diff --git a/e2e/cypress/tests/01-api-key/05-collect-credentials.cy.ts b/e2e/cypress/tests/01-api-key/06-collect-credentials.cy.ts similarity index 100% rename from e2e/cypress/tests/01-api-key/05-collect-credentials.cy.ts rename to e2e/cypress/tests/01-api-key/06-collect-credentials.cy.ts diff --git a/e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts b/e2e/cypress/tests/01-api-key/07-approve-pending-rqst.cy.ts similarity index 100% rename from e2e/cypress/tests/01-api-key/06-approve-pending-rqst.cy.ts rename to e2e/cypress/tests/01-api-key/07-approve-pending-rqst.cy.ts diff --git a/e2e/cypress/tests/01-api-key/07-grant-access.cy.ts b/e2e/cypress/tests/01-api-key/08-grant-access.cy.ts similarity index 100% rename from e2e/cypress/tests/01-api-key/07-grant-access.cy.ts rename to e2e/cypress/tests/01-api-key/08-grant-access.cy.ts diff --git a/e2e/cypress/tests/01-api-key/08-gwa-get.ts b/e2e/cypress/tests/01-api-key/09-gwa-get.ts similarity index 98% rename from e2e/cypress/tests/01-api-key/08-gwa-get.ts rename to e2e/cypress/tests/01-api-key/09-gwa-get.ts index f39e1f99a..24fcab411 100644 --- a/e2e/cypress/tests/01-api-key/08-gwa-get.ts +++ b/e2e/cypress/tests/01-api-key/09-gwa-get.ts @@ -42,6 +42,7 @@ describe('Verify GWA get commands', () => { it('Verify "gwa get" for dataset', () => { cy.get('@apiowner').then(({ product }: any) => { cy.executeCliCommand('gwa get datasets').then((response) => { + debugger expect(response.stdout).not.to.contain(product); }) }) @@ -70,6 +71,7 @@ describe('Verify GWA get commands', () => { it('Verify "gwa get" for products', () => { cy.get('@apiowner').then(({ product }: any) => { cy.executeCliCommand('gwa get products').then((response) => { + debugger expect(response.stdout).not.to.contain(product); }) }) diff --git a/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts b/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts index 34f0c0ada..b473e239c 100644 --- a/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts +++ b/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts @@ -1,4 +1,6 @@ +import AuthorizationProfile from "../../pageObjects/authProfile" import HomePage from "../../pageObjects/home" +import login from "../../pageObjects/login" import LoginPage from "../../pageObjects/login" let userSession: any let testData = require("../../fixtures/test_data/authorizationProfile.json") @@ -201,4 +203,96 @@ describe('Verify GWA command to publish issuer and apply generated config', () = }) }) + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + +}) + +describe('Deleted shared auth profile', () => { + + const login = new LoginPage() + const home = new HomePage() + const authProfile = new AuthorizationProfile() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + cy.fixture('api').as('api') + }) + + it('Authenticates Janis (api owner) to get the user session token', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.getUserSessionTokenValue(apiTest.namespace).then((value) => { + userSession = value + namespace = apiTest.namespace + home.useNamespace(namespace); + }) + }) + }) + + it('Navigate to authorization profile page', () => { + cy.visit(authProfile.path) + }) + + it('Delete the authorizarion profile inherited from shared IDP', () => { + cy.get('@api').then(({ authorizationProfiles }: any) => { + authProfile.deleteAuthProfile(authorizationProfiles.shared_IDP_inheritFrom_expectedResponse.name) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) + +describe('Verify that client ID of deleted shared auth profile in IDP', () => { + + var nameSpace: string + const home = new HomePage() + const authProfile = new AuthorizationProfile() + + before(() => { + cy.visit(Cypress.env('KEYCLOAK_URL')) + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + cy.fixture('apiowner').as('apiowner') + cy.fixture('state/regen').as('regen') + cy.fixture('admin').as('admin') + cy.fixture('api').as('api') + }) + + it('Authenticates Admin owner', () => { + cy.get('@admin').then(({ user }: any) => { + cy.contains('Administration Console').click({ force: true }) + cy.keycloakLogin(user.credentials.username, user.credentials.password) + }) + }) + + it('Navigate to Clients', () => { + cy.contains('Clients').click() + }) + + it('Verify that the client id of deleted shared auth profile does not display', () => { + cy.get('@api').then(({ authorizationProfiles }: any) => { + debugger + cy.contains(authorizationProfiles.shared_IDP_inheritFrom_expectedResponse.name).should('not.exist') + }) + }) + }) \ No newline at end of file diff --git a/e2e/cypress/tests/16-CORS/01-create-api.cy.ts b/e2e/cypress/tests/16-CORS/01-create-api.cy.ts deleted file mode 100644 index e7a84a363..000000000 --- a/e2e/cypress/tests/16-CORS/01-create-api.cy.ts +++ /dev/null @@ -1,126 +0,0 @@ -import WebAppPage from '../../pageObjects/webApp' - -describe('Create API Spec', () => { - const webApp = new WebAppPage() - let updatedBody: any - let pluginID: string - let serviceID: string - before(() => { - cy.visit(Cypress.env('WEBAPP_URL')) - // cy.visit(Cypress.env('WEBAPP_URL')) - cy.deleteAllCookies() - cy.reload() - }) - - beforeEach(() => { - cy.fixture('apiowner').as('apiowner') - cy.fixture('cors/kong-cors-plugin-config.json').as('kong-cors-plugin-config') - cy.preserveCookies() - }) - serviceID = 'ce5d3e76-1d35-47f0-8ddf-fad087b1f969' - pluginID = '73a51e86-23ec-43c2-97fc-b96ed9f5bd90' - - // it('Create a route for the service in Kong', () => { - // cy.readFile('cypress/fixtures/state/store.json').then((store_cred) => { - // serviceID = store_cred.servicesid - // cy.get('@kong-cors-plugin-config').then(({ createRoute }: any) => { - // cy.updateJsonValue(JSON.stringify(createRoute), '$.service.id', serviceID).then((updatedValue) => { - // cy.updateKongPluginForJSONRequest(updatedValue, 'routes').then((response) => { - // expect(response.status).to.be.equal(201) - // expect(response.statusText).to.be.equal('Created') - // }) - // }) - // }) - // }) - // }) - - // it('Publish CORS plugin to kong with a valid origins value', () => { - // cy.get('@kong-cors-plugin-config').then(({ uploadCORSPlugin }: any) => { - // debugger - // cy.updateKongPluginForJSONRequest(uploadCORSPlugin, 'services/'+serviceID+'/plugins').then((response) => { - // debugger - // expect(response.status).to.be.equal(201) - // expect(response.statusText).to.be.equal('Created') - // pluginID=response.body.id - // }) - // }) - // }) - - // it('Verify for successful CORS call for valid origin value', () => { - // webApp.getStatusAfterClickOnCORS().then((statusText)=>{ - // expect(statusText).to.be.equal('Response Code: 200') - // }) - // }) - - it('Set incorrrect origin name in CORS plugin', () => { - cy.get('@kong-cors-plugin-config').then(({ uploadCORSPlugin }: any) => { - debugger - cy.updateJsonValue(JSON.stringify(uploadCORSPlugin), '$.config.origins[0]', 'https://google.com').then((updatedValue) => { - updatedBody = updatedValue - cy.updateKongPluginForJSONRequest(updatedBody, 'services/' + serviceID + '/plugins/' + pluginID, 'PUT').then((response) => { - debugger - expect(response.status).to.be.equal(200) - }) - }) - }) - }) - - it('Verify for successful CORS call for valid origin value', () => { - // cy.origin(Cypress.env('WEBAPP_URL'), () => { - // cy.wait(5000) - // cy.get('[id="corsButton"]').click({ force: true }) - // cy.wait(8000) - // cy.visit('/') - - webApp.getStatusAfterClickOnCORS().then((statusText) => { - expect(statusText).to.be.equal('Error: Failed to fetch') - }) - }) - - - // it('Allow all origin name in CORS plugin', () => { - // cy.get('@kong-cors-plugin-config').then(({ uploadCORSPlugin }: any) => { - // debugger - // cy.updateJsonValue(JSON.stringify(uploadCORSPlugin), '$.config.origins[0]', '*').then((updatedValue) => { - // updatedBody = updatedValue - // cy.updateKongPluginForJSONRequest(updatedBody, 'services/'+serviceID+'/plugins/'+pluginID, 'PUT').then((response) => { - // debugger - // expect(response.status).to.be.equal(200) - // }) - // }) - // }) - // }) - - // it('Verify for successful CORS call for valid origin value', () => { - // webApp.getStatusAfterClickOnCORS().then((statusText)=>{ - // expect(statusText).to.be.equal('Response Code: 200') - // }) - // }) - - // it('Verify for successful CORS call for invalid header', () => { - // webApp.getStatusAfterClickOnCORSForHeaders().then((statusText)=>{ - // expect(statusText).to.be.equal('Error: Failed to fetch') - // }) - // }) - - // it('Set the header name as Access-Control-Allow-Headers in CORS plugin', () => { - // cy.get('@kong-cors-plugin-config').then(({ uploadCORSPlugin }: any) => { - // debugger - // cy.updateJsonValue(JSON.stringify(uploadCORSPlugin), '$.config.headers[4]', 'X-PINGOTHER').then((updatedValue) => { - // updatedBody = updatedValue - // cy.updateKongPluginForJSONRequest(updatedBody, 'services/'+serviceID+'/plugins/'+pluginID, 'PUT').then((response) => { - // debugger - // expect(response.status).to.be.equal(200) - // }) - // }) - // }) - // }) - - // it('Verify for successful CORS call after setting the header in Access-Control-Allow-Headers list', () => { - // webApp.getStatusAfterClickOnCORSForHeaders().then((statusText)=>{ - // expect(statusText).to.be.equal('Response Code: 200') - // }) - // }) - -}) - diff --git a/e2e/cypress/tests/17-gwa-cli/01-cli-commands.ts b/e2e/cypress/tests/16-gwa-cli/01-cli-commands.ts similarity index 100% rename from e2e/cypress/tests/17-gwa-cli/01-cli-commands.ts rename to e2e/cypress/tests/16-gwa-cli/01-cli-commands.ts diff --git a/e2e/cypress/tests/17-gwa-cli/02-cli-generate-config.ts b/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts similarity index 96% rename from e2e/cypress/tests/17-gwa-cli/02-cli-generate-config.ts rename to e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts index 30d11a689..bb346b5cd 100644 --- a/e2e/cypress/tests/17-gwa-cli/02-cli-generate-config.ts +++ b/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts @@ -88,4 +88,11 @@ describe('Verify CLI commands for generate/apply config', () => { cy.visit(pd.path) pd.verifyDataset('my-service', 'my-service API') }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() +}) + }) \ No newline at end of file diff --git a/e2e/cypress/tests/18-delete-application/01-delete-application-without-access.cy.ts b/e2e/cypress/tests/17-delete-application/01-delete-application-without-access.cy.ts similarity index 100% rename from e2e/cypress/tests/18-delete-application/01-delete-application-without-access.cy.ts rename to e2e/cypress/tests/17-delete-application/01-delete-application-without-access.cy.ts diff --git a/e2e/cypress/tests/18-delete-application/02-delete-application-with-pending-request.cy.ts b/e2e/cypress/tests/17-delete-application/02-delete-application-with-pending-request.cy.ts similarity index 100% rename from e2e/cypress/tests/18-delete-application/02-delete-application-with-pending-request.cy.ts rename to e2e/cypress/tests/17-delete-application/02-delete-application-with-pending-request.cy.ts diff --git a/e2e/cypress/tests/18-delete-application/03-delete-application-with-approved-request.cy.ts b/e2e/cypress/tests/17-delete-application/03-delete-application-with-approved-request.cy.ts similarity index 100% rename from e2e/cypress/tests/18-delete-application/03-delete-application-with-approved-request.cy.ts rename to e2e/cypress/tests/17-delete-application/03-delete-application-with-approved-request.cy.ts diff --git a/e2e/cypress/tests/18-delete-application/04-delete-namespace-gwa.ts b/e2e/cypress/tests/17-delete-application/04-delete-namespace-gwa.ts similarity index 100% rename from e2e/cypress/tests/18-delete-application/04-delete-namespace-gwa.ts rename to e2e/cypress/tests/17-delete-application/04-delete-namespace-gwa.ts From 831f1ce492184a605728b7eb26efd0baeb8bd0ea Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 6 Sep 2023 09:15:48 -0700 Subject: [PATCH 72/81] Update steps for API Key request access and gwa generate confin --- ...04-request-access-with-out-collecting-credentials.cy.ts | 7 ------- e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts | 4 ++++ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/e2e/cypress/tests/01-api-key/04-request-access-with-out-collecting-credentials.cy.ts b/e2e/cypress/tests/01-api-key/04-request-access-with-out-collecting-credentials.cy.ts index 63747c8fa..4eb63eb4c 100644 --- a/e2e/cypress/tests/01-api-key/04-request-access-with-out-collecting-credentials.cy.ts +++ b/e2e/cypress/tests/01-api-key/04-request-access-with-out-collecting-credentials.cy.ts @@ -26,13 +26,6 @@ describe('Request Access without colleting credential Spec', () => { }) }) - it('creates an application', () => { - cy.visit(app.path) - cy.get('@developer').then(({ application }: any) => { - app.createApplication(application) - }) - }) - it('Collect the credentials', () => { cy.visit(apiDir.path) cy.get('@developer').then(({ product, application,accessRequest }: any) => { diff --git a/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts b/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts index bb346b5cd..5344b2168 100644 --- a/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts +++ b/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts @@ -89,6 +89,10 @@ describe('Verify CLI commands for generate/apply config', () => { pd.verifyDataset('my-service', 'my-service API') }) + it('Navigate to home path', () => { + cy.visit(login.path) + }) + after(() => { cy.logout() cy.clearLocalStorage({ log: true }) From 22b471f0c852bbfb271ef2f46e4934dc85ff404f Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Thu, 7 Sep 2023 21:07:53 -0700 Subject: [PATCH 73/81] update workflow file to check cypress test on remote VM --- .github/workflows/aps-cypress-e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index dae997fd9..23b5db5ca 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -2,7 +2,7 @@ name: Build and Deploy Cypress and Execute Tests on: push: - branches: ['test', 'cypress/*'] + branches: ['test', 'cypress*'] env: DASHBOARD_PROJECT_ID: ${{ secrets.CY_DASHBOARD_PRJ_ID }} From 5964e8742b4f34b5b8969bffd0a9ffaa73bd7bbe Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Wed, 13 Sep 2023 13:51:21 -0700 Subject: [PATCH 74/81] 1)Added scenarios to verify invalid namespace name 2) Replace 'gwa publish'to 'gwa apply' 3)Made changes as per PR Review comments --- .github/workflows/aps-cypress-e2e.yaml | 2 +- .github/workflows/build-gwa-binary.yaml | 37 -------- e2e/cypress/fixtures/api.json | 55 +++++++++--- e2e/cypress/support/auth-commands.ts | 6 +- e2e/cypress/support/global.d.ts | 4 + e2e/cypress/support/util-commands.ts | 18 +++- .../tests/01-api-key/01-create-api.cy.ts | 26 ++++-- e2e/cypress/tests/01-api-key/09-gwa-get.ts | 2 - .../15-aps-api/05-authorizationProfiles.cy.ts | 28 +++--- .../tests/15-aps-api/07-api-directory.cy.ts | 20 ++--- .../tests/15-aps-api/08-namespaces.cy.ts | 89 ++++++++++++++++++- .../tests/16-gwa-cli/01-cli-commands.ts | 4 + e2e/gw-config.yml | 36 ++++++++ 13 files changed, 239 insertions(+), 88 deletions(-) delete mode 100644 .github/workflows/build-gwa-binary.yaml create mode 100644 e2e/gw-config.yml diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 23b5db5ca..7d7e39ba4 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -35,7 +35,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v2 with: - go-version: '1.19.x' + go-version: '1.20.x' - name: create .env file run: | diff --git a/.github/workflows/build-gwa-binary.yaml b/.github/workflows/build-gwa-binary.yaml deleted file mode 100644 index 718b4f941..000000000 --- a/.github/workflows/build-gwa-binary.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: Build GWA Binary - -on: - push: - branches: ['cypress/*'] - -jobs: - cypress-run: - runs-on: ubuntu-latest - steps: - - name: Checkout Source Repository - run: | - git clone https://github.com/bcgov/gwa-cli.git -b dev - cd gwa-cli - - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: 1.16 # Replace with the desired Go version - - - name: Install just - run: | - wget https://github.com/casey/just/releases/download/v0.10.1/just-v0.10.1-x86_64-unknown-linux-musl -O just - chmod +x just - sudo mv just /usr/local/bin/ - - - name: Build Go Binary - run: just build - - - name: Upload Binary - uses: actions/upload-artifact@v2 - with: - name: gwa - path: /usr/local/bin # Replace with the path to your built binary - - - name: Check GWA help - run: gwa -h \ No newline at end of file diff --git a/e2e/cypress/fixtures/api.json b/e2e/cypress/fixtures/api.json index 38ce371fc..38bcb15c3 100644 --- a/e2e/cypress/fixtures/api.json +++ b/e2e/cypress/fixtures/api.json @@ -16,7 +16,7 @@ "Namespace.Assign" ], "expectedNamespace": { - "name": "gw-65590", + "name": "gw-3a443", "orgUnit": "planning-and-innovation-division", "enabled": true }, @@ -104,16 +104,16 @@ "organizationUnit": "planning-and-innovation-division" }, "directory": { - "name": "api-auto-test-product", - "title": "API Auto Test Product", - "notes": "API Gateway Services provides a way to configure services on the API Gateway, manage access to APIs and get insight into the use of them.", - "license_title": "Access Only", - "view_audience": "Government", - "security_class": "LOW-PUBLIC", + "name": "gwa-auto-test-product", + "title": "GWA Auto Test Product", + "notes": "For Test Purpose", + "license_title": "Open Government Licence - British Columbia", + "view_audience": "Public", + "security_class": "PUBLIC", + "record_publish_date": "2017-09-05", "tags": [ - "gateway", - "kong", - "openapi" + "tag1", + "tag2" ], "organization": { "name": "ministry-of-health", @@ -125,8 +125,14 @@ }, "products": [ { - "name": "API Auto Test Product", + "id": "2", + "name": "GWA Auto Test Product", "environments": [ + { + "name": "test", + "active": true, + "flow": "kong-api-key-acl" + }, { "name": "dev", "active": true, @@ -216,6 +222,25 @@ ], "isShared": true }, + "shared_gwa": { + "name": "Gold Shared IdP", + "description": "A Shared IdP for Teams to use", + "flow": "client-credentials", + "mode": "auto", + "clientAuthenticator": "client-secret", + "environmentDetails": [ + { + "clientId": "gwa-api", + "clientRegistration": "managed", + "clientSecret": "18900468-3db1-43f7-a8af-e75f079eb742", + "environment": "test", + "issuerUrl": "http://keycloak.localtest.me:9080/auth/realms/master", + "exists": true + } + ], + "isShared": true, + "apiKeyName": "X-API-KEY" + }, "shared_gwa_publish": { "name": "Gold Shared IdP", "description": "A Shared IdP for Teams to use", @@ -362,6 +387,14 @@ "permProtectedNs": "deny", "org": "ministry-of-health", "orgUnit": "planning-and-innovation-division" + }, + "userDefinedNamespace": { + "name": "gwanelatform", + "displayName": "Test for GWA test" + }, + "inValidNamespace": { + "name": "gwa", + "displayName": "Test for GWA test" } } } \ No newline at end of file diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts index 5035d2e11..a031aed1c 100644 --- a/e2e/cypress/support/auth-commands.ts +++ b/e2e/cypress/support/auth-commands.ts @@ -264,7 +264,6 @@ Cypress.Commands.add('publishApi', (fileName: string, namespace: string, flag?: { expect(response.stdout).to.contain("Config settings saved") cy.executeCliCommand('gwa pg ./cypress/fixtures/' + fileName).then((response) => { - debugger expect(response.stdout).to.contain("Gateway config published") }) } @@ -574,6 +573,11 @@ Cypress.Commands.add('forceVisit', (url: string) => { }); }); +Cypress.Commands.add('updateJsonBoby', (json: any, key: string, newValue: string):any => { + json[key] = newValue + return json +}); + const formDataRequest = ( options: formDataRequestOptions, accessToken: string, diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts index 51390b46f..71d1f2e93 100644 --- a/e2e/cypress/support/global.d.ts +++ b/e2e/cypress/support/global.d.ts @@ -97,5 +97,9 @@ declare namespace Cypress { gwaPublish(type: string, fileName: string): Chainable> replaceWord(originalString: string, wordToReplace: string, replacementWord: string): Chainable + + updateJsonBoby(json: any, key: string, newValue: string):Chainable + + deleteFileInE2EFolder(fileName: string):Chainable } } diff --git a/e2e/cypress/support/util-commands.ts b/e2e/cypress/support/util-commands.ts index e52fcde09..9d1653869 100644 --- a/e2e/cypress/support/util-commands.ts +++ b/e2e/cypress/support/util-commands.ts @@ -1,7 +1,7 @@ import 'cypress-v10-preserve-cookie' -import jsonpath = require('jsonpath'); -const fs = require('fs'); const YAML = require('yamljs'); +const path = require('path'); + const listOfCookies = [ 'AUTH_SESSION_ID_LEGACY', @@ -160,6 +160,20 @@ Cypress.Commands.add('gwaPublish', (type: string, fileName: string) => { return response }); }) +// cypress/support/commands.js + +Cypress.Commands.add('deleteFileInE2EFolder', (fileName: string) => { + const currentDirectory = Cypress.config('fileServerFolder'); // Get the current working directory + const filePath = path.join(currentDirectory, fileName) + debugger + try { + cy.exec(`rm -f ${filePath}`); + cy.log(`File '${fileName}' has been deleted from the e2e folder.`); + } catch (error) { + cy.log(`Error deleting file '${fileName}' from the e2e folder`); + } +}); + Cypress.Commands.add('replaceWord', (originalString: string, wordToReplace: string, replacementWord: string)=> { // Create a regular expression with the 'g' flag for global search diff --git a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts index 5913ee86d..3fa36e074 100644 --- a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts +++ b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts @@ -36,7 +36,7 @@ describe('Create API Spec', () => { it('Check gwa config command to set environment', () => { var cleanedUrl = Cypress.env('BASE_URL').replace(/^http?:\/\//i, ""); - cy.executeCliCommand('gwa config set --host '+cleanedUrl+' --scheme http').then((response) => { + cy.executeCliCommand('gwa config set --host ' + cleanedUrl + ' --scheme http').then((response) => { expect(response.stdout).to.contain("Config settings saved") }); }) @@ -79,15 +79,23 @@ describe('Create API Spec', () => { }) }) - it('creates as new product in the directory through GWA Cli command', () => { - cy.gwaPublish('product', 'gwa-product.yaml').then((response: any) => { - expect(response.stdout).to.contain('Product successfully published'); - }) - }) + // it('creates as new product in the directory through GWA Cli command', () => { + // cy.gwaPublish('product', 'gwa-product.yaml').then((response: any) => { + // expect(response.stdout).to.contain('Product successfully published'); + // }) + // }) + + // it('Upload dataset using GWA Cli command', () => { + // cy.gwaPublish('dataset', 'gwa-dataset.yaml').then((response: any) => { + // expect(response.stdout).to.contain('Dataset successfully published'); + // }) + // }) - it('Upload dataset using GWA Cli command', () => { - cy.gwaPublish('dataset', 'gwa-dataset.yaml').then((response: any) => { - expect(response.stdout).to.contain('Dataset successfully published'); + it('Upload dataset and Product using GWA Apply command', () => { + cy.executeCliCommand('gwa apply').then((response) => { + debugger + let wordOccurrences = (response.stdout.match(/\bcreated\b/g) || []).length; + expect(wordOccurrences).to.equal(2) }) }) diff --git a/e2e/cypress/tests/01-api-key/09-gwa-get.ts b/e2e/cypress/tests/01-api-key/09-gwa-get.ts index 24fcab411..f39e1f99a 100644 --- a/e2e/cypress/tests/01-api-key/09-gwa-get.ts +++ b/e2e/cypress/tests/01-api-key/09-gwa-get.ts @@ -42,7 +42,6 @@ describe('Verify GWA get commands', () => { it('Verify "gwa get" for dataset', () => { cy.get('@apiowner').then(({ product }: any) => { cy.executeCliCommand('gwa get datasets').then((response) => { - debugger expect(response.stdout).not.to.contain(product); }) }) @@ -71,7 +70,6 @@ describe('Verify GWA get commands', () => { it('Verify "gwa get" for products', () => { cy.get('@apiowner').then(({ product }: any) => { cy.executeCliCommand('gwa get products').then((response) => { - debugger expect(response.stdout).not.to.contain(product); }) }) diff --git a/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts b/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts index b473e239c..5417e4c65 100644 --- a/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts +++ b/e2e/cypress/tests/15-aps-api/05-authorizationProfiles.cy.ts @@ -169,7 +169,7 @@ describe('API Tests for Authorization Profiles created with inheritFrom attribut }) -describe('Verify GWA command to publish issuer and apply generated config', () => { +describe('Published a shared authorization profile', () => { let response: any let actualResponse: any @@ -180,9 +180,20 @@ describe('Verify GWA command to publish issuer and apply generated config', () = cy.fixture('apiowner').as('apiowner') }) - it('Create a credential issuer using gwa publish command', () => { - cy.gwaPublish('issuer', 'gwa-issuer.yaml').then((response: any) => { - expect(response.stdout).to.contain('Issuer successfully published'); + it('Prepare the Request Specification to create a shared IDP profile', () => { + cy.get('@api').then(({ authorizationProfiles }: any) => { + cy.setHeaders(authorizationProfiles.headers) + cy.setAuthorizationToken(userSession) + cy.setRequestBody(authorizationProfiles.shared_gwa) + }) + }) + + it('Create a shared credential issuer', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.makeAPIRequest('ds/api/v2/namespaces/' + apiTest.namespace + '/issuers', 'PUT').then((response) => { + expect(response.status).to.be.equal(200) + expect(response.body.result).to.be.equal("created") + }) }) }) @@ -195,14 +206,6 @@ describe('Verify GWA command to publish issuer and apply generated config', () = }) }) - it('Compare the values in response against the values passed through gwa command', () => { - cy.get('@api').then(({ authorizationProfiles }: any) => { - actualResponse = response - expectedResponse = authorizationProfiles.shared_gwa_publish - cy.compareJSONObjects(actualResponse, expectedResponse, true) - }) - }) - after(() => { cy.logout() cy.clearLocalStorage({ log: true }) @@ -290,7 +293,6 @@ describe('Verify that client ID of deleted shared auth profile in IDP', () => { it('Verify that the client id of deleted shared auth profile does not display', () => { cy.get('@api').then(({ authorizationProfiles }: any) => { - debugger cy.contains(authorizationProfiles.shared_IDP_inheritFrom_expectedResponse.name).should('not.exist') }) }) diff --git a/e2e/cypress/tests/15-aps-api/07-api-directory.cy.ts b/e2e/cypress/tests/15-aps-api/07-api-directory.cy.ts index 7554decb5..19309fcd2 100644 --- a/e2e/cypress/tests/15-aps-api/07-api-directory.cy.ts +++ b/e2e/cypress/tests/15-aps-api/07-api-directory.cy.ts @@ -146,7 +146,7 @@ describe('API Tests for Updating dataset', () => { it('Verify the expected directory details are display in the response', () => { cy.get('@api').then(({ apiDirectory }: any) => { - // cy.compareJSONObjects(response, apiDirectory.directory, true) + cy.compareJSONObjects(response, apiDirectory.directory, true) }) }) @@ -183,11 +183,11 @@ describe('API Tests for Updating dataset', () => { }) }) - // it('Verify the expected namespace directory details are display in the response', () => { - // cy.get('@api').then(({ apiDirectory }: any) => { - // cy.compareJSONObjects(response, apiDirectory.directory, true) - // }) - // }) + it('Verify the expected namespace directory details are display in the response', () => { + cy.get('@api').then(({ apiDirectory }: any) => { + cy.compareJSONObjects(response, apiDirectory.directory, false) + }) + }) it('Get the namespace directory details by its ID (/namespaces/{ns}/directory/{id}) and verify the success code in the response', () => { cy.get('@apiowner').then(({ namespace }: any) => { @@ -211,11 +211,9 @@ describe('API Tests for Updating dataset', () => { }) it('Delete the dataset (/organizations/{org}/datasets/{name}) and verify the success code in the response', () => { - cy.get('@apiowner').then(({ apiTest }: any) => { - cy.get('@api').then(({ apiDirectory, organization }: any) => { - cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'DELETE').then((res) => { - expect(res.status).to.be.equal(200) - }) + cy.get('@api').then(({ apiDirectory, organization }: any) => { + cy.makeAPIRequest(apiDirectory.orgEndPoint + '/' + organization.orgName + '/datasets/' + apiDirectory.body.name, 'DELETE').then((res) => { + expect(res.status).to.be.equal(200) }) }) }) diff --git a/e2e/cypress/tests/15-aps-api/08-namespaces.cy.ts b/e2e/cypress/tests/15-aps-api/08-namespaces.cy.ts index 5e88102bf..8a050f7e4 100644 --- a/e2e/cypress/tests/15-aps-api/08-namespaces.cy.ts +++ b/e2e/cypress/tests/15-aps-api/08-namespaces.cy.ts @@ -1,5 +1,6 @@ import HomePage from "../../pageObjects/home" import LoginPage from "../../pageObjects/login" +let testData = require("../../fixtures/apiowner.json") let userSession: any let nameSpace: string @@ -136,7 +137,7 @@ describe('API Tests for Namespace Summary', () => { cy.get('@api').then(({ namespaces }: any) => { cy.makeAPIRequest(namespaces.endPoint + "/" + namespace, 'GET').then((res) => { expect(res.status).to.be.equal(200) - response = res.body + response = res.body.name }) }) }) @@ -149,6 +150,92 @@ describe('API Tests for Namespace Summary', () => { }) }) +describe('API Tests for Create Namespace', () => { + + const login = new LoginPage() + const home = new HomePage() + var response: any + + beforeEach(() => { + cy.fixture('api').as('api') + cy.fixture('apiowner').as('apiowner') + }) + + it('Prepare the Request Specification for the API', () => { + cy.get('@api').then(({ namespaces }: any) => { + cy.setHeaders(namespaces.headers) + cy.setAuthorizationToken(userSession) + }) + }) + + it('Create system generated namespace when user does not specify namespace name', () => { + cy.get('@api').then(({ namespaces }: any) => { + cy.makeAPIRequest(namespaces.endPoint, 'POST').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body.displayName).to.be.equal(null) + nameSpace = res.body.name + }) + }) + }) + + it('Verify that the generated namespace is displayed in the namespace list', () => { + cy.get('@api').then(({ namespaces }: any) => { + cy.makeAPIRequest(namespaces.endPoint, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body).to.be.contain(nameSpace) + }) + }) + }) + + it('Create users own namespace with its description', () => { + cy.get('@api').then(({ namespaces }: any) => { + cy.setRequestBody(namespaces.userDefinedNamespace) + cy.makeAPIRequest(namespaces.endPoint, 'POST').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body.displayName).to.be.equal(namespaces.userDefinedNamespace.displayName) + nameSpace = res.body.name + }) + }) + }) + + it('Verify that the generated namespace is displayed in the namespace list', () => { + cy.get('@api').then(({ namespaces }: any) => { + cy.makeAPIRequest(namespaces.endPoint, 'GET').then((res) => { + expect(res.status).to.be.equal(200) + expect(res.body).to.be.contain(nameSpace) + }) + }) + }) +}) + +describe('API Tests for invalid namespace name', () => { + + beforeEach(() => { + cy.fixture('api').as('api') + cy.fixture('apiowner').as('apiowner') + }) + + it('Verify validation message in response when user creat namespace using invalid name', () => { + cy.get('@api').then(({ namespaces }: any) => { + cy.fixture('apiowner').then((testdata: any) => { + let namespaceName: Array = testdata.invalid_namespace + testdata + namespaceName.forEach((name: any) => { + cy.setHeaders(namespaces.headers) + // cy.setRequestBody('{"name": "' + name + '","displayName": "Test for GWA test"}') + cy.updateJsonBoby(namespaces.inValidNamespace, 'name', name).then((updatedBody) => { + cy.setRequestBody(updatedBody) + cy.makeAPIRequest(namespaces.endPoint, 'POST').then((res) => { + expect(res.status).to.be.equal(422) + expect(res.body.message).to.be.equal('Validation Failed') + }) + }) + }) + }) + }) + }) +}) + // describe('API Tests for Deleting Namespace', () => { // const login = new LoginPage() diff --git a/e2e/cypress/tests/16-gwa-cli/01-cli-commands.ts b/e2e/cypress/tests/16-gwa-cli/01-cli-commands.ts index 86e8972fa..fb4bd7390 100644 --- a/e2e/cypress/tests/16-gwa-cli/01-cli-commands.ts +++ b/e2e/cypress/tests/16-gwa-cli/01-cli-commands.ts @@ -89,6 +89,10 @@ describe('Verify CLI commands', () => { }); }) + it('Delete Exsting config file', () => { + cy.deleteFileInE2EFolder('gw-config.yml') + }) + after(() => { cy.logout() cy.clearLocalStorage({ log: true }) diff --git a/e2e/gw-config.yml b/e2e/gw-config.yml new file mode 100644 index 000000000..3b0034ccf --- /dev/null +++ b/e2e/gw-config.yml @@ -0,0 +1,36 @@ +kind: DraftDataset +name: gwa-auto-test-product +license_title: Open Government Licence - British Columbia +security_class: PUBLIC +view_audience: Public +download_audience: Public +record_publish_date: '2017-09-05' +notes: For Test Purpose +title: GWA Auto Test Product +tags: + - tag1 + - tag2 +organization: ministry-of-health +organizationUnit: planning-and-innovation-division +isInCatalog: true +isDraft: false +--- +kind: Product +name: GWA Auto Test Product +appId: 'KFH78YU956RE' +environments: + - name: dev + active: false + approval: false + flow: public + appId: '406CB7CF' +# --- +# kind: ProductEnvironment +# name: dev +# product: my-service API +# appId: '5F194B28' +# active: false +# approval: true +# flow: client-credentials +# credentialIssuer: gw-1977c default +# services: [my-service-dev] From 7c95abfd98d5083345e92a9ed38947e35b774d44 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Fri, 15 Sep 2023 09:07:42 -0700 Subject: [PATCH 75/81] Update API directory test data in the file --- e2e/cypress.config.ts | 4 ++-- e2e/cypress/fixtures/api.json | 20 +++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index 97d36458a..526b4dd58 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -23,11 +23,11 @@ export default defineConfig({ './cypress/tests/10-*/*.ts', './cypress/tests/11-*/*.ts', './cypress/tests/12-*/*.ts', + './cypress/tests/13-*/*.ts', './cypress/tests/14-*/*.ts', './cypress/tests/15-*/*.ts', './cypress/tests/16-*/*.ts', - './cypress/tests/13-*/*.ts', - './cypress/tests/19-*/*.ts' + './cypress/tests/17-*/*.ts' ] return config }, diff --git a/e2e/cypress/fixtures/api.json b/e2e/cypress/fixtures/api.json index 38bcb15c3..41435f225 100644 --- a/e2e/cypress/fixtures/api.json +++ b/e2e/cypress/fixtures/api.json @@ -129,14 +129,14 @@ "name": "GWA Auto Test Product", "environments": [ { - "name": "test", + "name": "dev", "active": true, - "flow": "kong-api-key-acl" + "flow": "kong-api-key-only" }, { - "name": "dev", + "name": "test", "active": true, - "flow": "kong-api-key-acl" + "flow": "client-credentials" } ] } @@ -226,20 +226,18 @@ "name": "Gold Shared IdP", "description": "A Shared IdP for Teams to use", "flow": "client-credentials", - "mode": "auto", "clientAuthenticator": "client-secret", + "mode": "auto", "environmentDetails": [ { - "clientId": "gwa-api", - "clientRegistration": "managed", - "clientSecret": "18900468-3db1-43f7-a8af-e75f079eb742", "environment": "test", "issuerUrl": "http://keycloak.localtest.me:9080/auth/realms/master", - "exists": true + "clientRegistration": "managed", + "clientId": "gwa-api", + "clientSecret": "18900468-3db1-43f7-a8af-e75f079eb742" } ], - "isShared": true, - "apiKeyName": "X-API-KEY" + "isShared": true }, "shared_gwa_publish": { "name": "Gold Shared IdP", From c264a589f99483d884ef94d5aa74e7d2ec9168fd Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Fri, 15 Sep 2023 09:31:16 -0700 Subject: [PATCH 76/81] Remove commented code and debugger statements --- e2e/cypress/tests/01-api-key/01-create-api.cy.ts | 13 ------------- .../tests/16-gwa-cli/02-cli-generate-config.ts | 1 - 2 files changed, 14 deletions(-) diff --git a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts index 3fa36e074..20f5bd96f 100644 --- a/e2e/cypress/tests/01-api-key/01-create-api.cy.ts +++ b/e2e/cypress/tests/01-api-key/01-create-api.cy.ts @@ -79,21 +79,8 @@ describe('Create API Spec', () => { }) }) - // it('creates as new product in the directory through GWA Cli command', () => { - // cy.gwaPublish('product', 'gwa-product.yaml').then((response: any) => { - // expect(response.stdout).to.contain('Product successfully published'); - // }) - // }) - - // it('Upload dataset using GWA Cli command', () => { - // cy.gwaPublish('dataset', 'gwa-dataset.yaml').then((response: any) => { - // expect(response.stdout).to.contain('Dataset successfully published'); - // }) - // }) - it('Upload dataset and Product using GWA Apply command', () => { cy.executeCliCommand('gwa apply').then((response) => { - debugger let wordOccurrences = (response.stdout.match(/\bcreated\b/g) || []).length; expect(wordOccurrences).to.equal(2) }) diff --git a/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts b/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts index 5344b2168..7ced10b71 100644 --- a/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts +++ b/e2e/cypress/tests/16-gwa-cli/02-cli-generate-config.ts @@ -53,7 +53,6 @@ describe('Verify CLI commands for generate/apply config', () => { it('Check gwa command to apply generated config', () => { cy.executeCliCommand('gwa apply').then((response) => { - debugger let wordOccurrences = (response.stdout.match(/\bcreated\b/g) || []).length; expect(wordOccurrences).to.equal(3) namespace = response.stdout.split('\n')[0] From 88190bacc47f1074078057b75844b6ed2cd26b1f Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Fri, 15 Sep 2023 09:41:37 -0700 Subject: [PATCH 77/81] remove branch name --- .github/workflows/aps-cypress-e2e.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 7d7e39ba4..918a69a7d 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -20,7 +20,7 @@ jobs: steps: - name: Build GWA API Image run: | - git clone https://github.com/bcgov/gwa-api.git -b dev + git clone https://github.com/bcgov/gwa-api.git cd gwa-api/microservices/gatewayApi docker build -t gwa-api:e2e . @@ -29,7 +29,7 @@ jobs: - name: Checkout Source Repository run: | - git clone https://github.com/bcgov/gwa-cli.git -b dev + git clone https://github.com/bcgov/gwa-cli.git cd gwa-cli - name: Setup Go From f0e0b5b9aefa65543bd80eb7399ef283e8721483 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Fri, 15 Sep 2023 14:16:33 -0700 Subject: [PATCH 78/81] Added step to set GWA_VERSION variable in env file in github workflow --- .github/workflows/aps-cypress-e2e.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 918a69a7d..f7eae80ee 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -42,6 +42,7 @@ jobs: cd gwa-cli echo "GWA_API_HOST=api-services-portal-feature-gwa-cli-v2.apps.silver.devops.gov.bc.ca" >> .env echo "GWA_CLIENT_ID=gwa-cli" >> .env + echo "GWA_VERSION=2.2" >> .env - name: Debug run: echo ${{ github.workspace }} From 8825c2490aa6ae7f57d0586e7f48c4f092547d5b Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Sun, 17 Sep 2023 13:23:15 -0700 Subject: [PATCH 79/81] Update workflow file to download build from release --- .github/workflows/aps-cypress-e2e.yaml | 62 ++++++++++++++++---------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index f7eae80ee..1276b20a1 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -26,37 +26,51 @@ jobs: - name: Checkout Portal uses: actions/checkout@v2 - - - name: Checkout Source Repository - run: | - git clone https://github.com/bcgov/gwa-cli.git - cd gwa-cli - - name: Setup Go - uses: actions/setup-go@v2 + + - name: Download Binar + uses: robinraju/release-downloader@v1.8 with: - go-version: '1.20.x' + repository: "bcgov/gwa-cli" + latest: true + fileName: "gwa_Linux_x86_64.tgz" + out-file-path: "${{ github.workspace }}/e2e" - - name: create .env file + - name: Unzip file run: | - cd gwa-cli - echo "GWA_API_HOST=api-services-portal-feature-gwa-cli-v2.apps.silver.devops.gov.bc.ca" >> .env - echo "GWA_CLIENT_ID=gwa-cli" >> .env - echo "GWA_VERSION=2.2" >> .env + cd ${{ github.workspace }}/e2e + tar xvzf gwa_Linux_x86_64.tgz + + # - name: Checkout Source Repository + # run: | + # git clone https://github.com/bcgov/gwa-cli.git + # cd gwa-cli - - name: Debug - run: echo ${{ github.workspace }} + # - name: Setup Go + # uses: actions/setup-go@v2 + # with: + # go-version: '1.20.x' - - name: Build - run: | - cd gwa-cli - go clean - go build -o ${{ github.workspace }}/e2e/gwa + # - name: create .env file + # run: | + # cd gwa-cli + # echo "GWA_API_HOST=api-services-portal-feature-gwa-cli-v2.apps.silver.devops.gov.bc.ca" >> .env + # echo "GWA_CLIENT_ID=gwa-cli" >> .env + # echo "GWA_VERSION=2.2" >> .env - - uses: actions/upload-artifact@v2 - with: - name: binary-artifact - path: ${{ github.workspace }}/e2e + # - name: Debug + # run: echo ${{ github.workspace }} + + # - name: Build + # run: | + # cd gwa-cli + # go clean + # go build -o ${{ github.workspace }}/e2e/gwa + + # - uses: actions/upload-artifact@v2 + # with: + # name: binary-artifact + # path: ${{ github.workspace }}/e2e - name: Build Docker Images run: | From 80a9d11ea420607488ed1511048de89d7b29cc88 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Sun, 17 Sep 2023 21:18:33 -0700 Subject: [PATCH 80/81] Update workflow file to download binary from release page and update docker file --- .github/workflows/aps-cypress-e2e.yaml | 47 ++++++++------------------ e2e/Dockerfile | 1 + 2 files changed, 15 insertions(+), 33 deletions(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index 1276b20a1..f8ae02cb5 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -28,49 +28,30 @@ jobs: uses: actions/checkout@v2 + - name: Determine Download file name + id: set_variable + run: | + echo ${{ runner.arch }} + if [ "${{ runner.arch }}" == "X64" ]; then + echo "::set-output name=my_variable::gwa_Linux_x86_64.tgz" + else if [ "${{ runner.arch }}" == "ARM64" ]; then + echo "::set-output name=my_variable::gwa_Linux_arm64.tgz" + else + echo "unsupported architecture" + fi + - name: Download Binar uses: robinraju/release-downloader@v1.8 with: repository: "bcgov/gwa-cli" latest: true - fileName: "gwa_Linux_x86_64.tgz" + fileName: ${{ steps.set_variable.outputs.my_variable }} out-file-path: "${{ github.workspace }}/e2e" - name: Unzip file run: | cd ${{ github.workspace }}/e2e - tar xvzf gwa_Linux_x86_64.tgz - - # - name: Checkout Source Repository - # run: | - # git clone https://github.com/bcgov/gwa-cli.git - # cd gwa-cli - - # - name: Setup Go - # uses: actions/setup-go@v2 - # with: - # go-version: '1.20.x' - - # - name: create .env file - # run: | - # cd gwa-cli - # echo "GWA_API_HOST=api-services-portal-feature-gwa-cli-v2.apps.silver.devops.gov.bc.ca" >> .env - # echo "GWA_CLIENT_ID=gwa-cli" >> .env - # echo "GWA_VERSION=2.2" >> .env - - # - name: Debug - # run: echo ${{ github.workspace }} - - # - name: Build - # run: | - # cd gwa-cli - # go clean - # go build -o ${{ github.workspace }}/e2e/gwa - - # - uses: actions/upload-artifact@v2 - # with: - # name: binary-artifact - # path: ${{ github.workspace }}/e2e + tar xvzf ${{ steps.set_variable.outputs.my_variable }} - name: Build Docker Images run: | diff --git a/e2e/Dockerfile b/e2e/Dockerfile index a77289f4a..b253160d1 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -7,6 +7,7 @@ COPY cypress.config.ts /e2e COPY tsconfig.json /e2e COPY package.json /e2e COPY package-lock.json /e2e +COPY *.yml /e2e COPY entrypoint.sh /tmp COPY gwa /usr/local/bin ADD cypress /e2e/cypress From 6f8678f47d1f570cb55d4529c63530492f8d712c Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Sun, 17 Sep 2023 22:04:59 -0700 Subject: [PATCH 81/81] Corrected the else if statement in workflow file --- .github/workflows/aps-cypress-e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aps-cypress-e2e.yaml b/.github/workflows/aps-cypress-e2e.yaml index f8ae02cb5..5b5eea26e 100644 --- a/.github/workflows/aps-cypress-e2e.yaml +++ b/.github/workflows/aps-cypress-e2e.yaml @@ -34,7 +34,7 @@ jobs: echo ${{ runner.arch }} if [ "${{ runner.arch }}" == "X64" ]; then echo "::set-output name=my_variable::gwa_Linux_x86_64.tgz" - else if [ "${{ runner.arch }}" == "ARM64" ]; then + elif [ "${{ runner.arch }}" == "ARM64" ]; then echo "::set-output name=my_variable::gwa_Linux_arm64.tgz" else echo "unsupported architecture"