From b10c892d1b4dbf693db14edec08fca27dc5b512c Mon Sep 17 00:00:00 2001 From: ike thecoder Date: Fri, 10 Mar 2023 14:54:35 -0800 Subject: [PATCH 1/6] Feature Email Editing and Null User (#750) * First pass at email editing layout. * Add missing icon * Get a working email form with content editable. * add mutation backend logic * only update email if provided * upd profile * add mutation to whitelist * fix null user error * Update ci-build-deploy.yaml * Fix persistent dialog to complete profile * Update ci-build-deploy.yaml * Disable editing email for IDIR users * Turn on bcsc only complete profile prompt * Fix dialog persistence issue, save and refresh email after mutation * Remove hardcoded provider field in profile * upd the session identity email on change --------- Co-authored-by: Joshua Jones --- src/auth/auth-oauth2-proxy.js | 28 ++-- .../httplocalhost4180profile-f201b4.gql | 6 + src/authz/matrix.csv | 3 +- src/lists/User.js | 21 +++ src/mocks/handlers.js | 13 +- src/mocks/resolvers/personas.js | 4 +- .../complete-profile/complete-profile.tsx | 91 +++++++++++ .../components/complete-profile/index.ts | 1 + src/nextapp/pages/_app.tsx | 2 + src/nextapp/pages/profile.tsx | 153 +++++++++++++++--- src/nextapp/shared/services/utils.ts | 2 +- src/nextapp/shared/types/query.types.ts | 6 + src/services/keystone/index.ts | 1 + src/services/keystone/temporary-identity.ts | 40 +++++ src/services/keystone/types.ts | 6 + src/services/keystone/user.ts | 24 +++ 16 files changed, 366 insertions(+), 35 deletions(-) create mode 100644 src/authz/graphql-whitelist/httplocalhost4180profile-f201b4.gql create mode 100644 src/nextapp/components/complete-profile/complete-profile.tsx create mode 100644 src/nextapp/components/complete-profile/index.ts diff --git a/src/auth/auth-oauth2-proxy.js b/src/auth/auth-oauth2-proxy.js index f51517a26..0945e154f 100644 --- a/src/auth/auth-oauth2-proxy.js +++ b/src/auth/auth-oauth2-proxy.js @@ -246,7 +246,7 @@ class Oauth2ProxyAuthStrategy { async register_user(req, res, next) { const _users = this.keystone.getListByKey('User'); - const users = this.keystone.getListByKey(this.listKey); + const identityList = this.keystone.getListByKey(this.listKey); // If no user in session but we are authenticated, then redirect to /admin/signin const allRoles = [ @@ -263,7 +263,9 @@ class Oauth2ProxyAuthStrategy { const jti = oauthUser['jti']; // JWT ID - Unique Identifier for the token const sub = oauthUser['sub']; // Subject ID - Whom the token refers to - const name = oauthUser['name']; + const name = Boolean(oauthUser['name']) + ? oauthUser['name'] + : oauthUser['provider_username']; const identityProvider = oauthUser['identity_provider']; const providerUserGuid = oauthUser['provider_user_guid']; const providerUsername = oauthUser['provider_username']; @@ -355,6 +357,12 @@ class Oauth2ProxyAuthStrategy { let userId = _results.length == 0 ? null : _results[0].id; + // if the email is passed, then treat that as the source of truth + let userEmail = email; + if (!Boolean(email) && _results.length != 0) { + userEmail = _results[0].email; + } + if (_results.length == 0) { // auto-create a user record const { data, errors } = await this.keystone.executeGraphQL({ @@ -365,7 +373,7 @@ class Oauth2ProxyAuthStrategy { } }`, variables: { name, - email, + userEmail, username, identityProvider, providerUserGuid, @@ -385,14 +393,14 @@ class Oauth2ProxyAuthStrategy { const saved = _results[0]; if ( saved.name != name || - saved.email != email || + (Boolean(email) && saved.email != email) || saved.identityProvider === null || saved.providerUsername != providerUsername ) { logger.info( 'register_user - updating name (%s), email (%s), provider (%s), providerUserGuid (%s), providerUsername (%s) for %s', name, - email, + userEmail, identityProvider, providerUserGuid, providerUsername, @@ -406,7 +414,7 @@ class Oauth2ProxyAuthStrategy { } }`, variables: { name, - email, + email: userEmail, identityProvider, providerUserGuid, providerUsername, @@ -422,7 +430,7 @@ class Oauth2ProxyAuthStrategy { } } - let results = await users.adapter.find({ jti: jti }); + let results = await identityList.adapter.find({ jti }); var operation = 'update'; @@ -438,7 +446,7 @@ class Oauth2ProxyAuthStrategy { jti, sub, name, - email, + email: userEmail, username, identityProvider, providerUserGuid, @@ -453,7 +461,7 @@ class Oauth2ProxyAuthStrategy { if (errors) { logger.error('register_user - NO! Something went wrong %j', errors); } - results = await users.adapter.find({ ['jti']: jti }); + results = await identityList.adapter.find({ ['jti']: jti }); operation = 'create'; } @@ -560,4 +568,4 @@ Oauth2ProxyAuthStrategy.authType = 'password'; module.exports = { Oauth2ProxyAuthStrategy, -}; \ No newline at end of file +}; diff --git a/src/authz/graphql-whitelist/httplocalhost4180profile-f201b4.gql b/src/authz/graphql-whitelist/httplocalhost4180profile-f201b4.gql new file mode 100644 index 000000000..47ffd1523 --- /dev/null +++ b/src/authz/graphql-whitelist/httplocalhost4180profile-f201b4.gql @@ -0,0 +1,6 @@ + + mutation UpdateUserEmail($email: String!) { + updateEmail(email: $email) { + email + } + } diff --git a/src/authz/matrix.csv b/src/authz/matrix.csv index 619dd3e2d..5a0c1ac28 100644 --- a/src/authz/matrix.csv +++ b/src/authz/matrix.csv @@ -224,5 +224,6 @@ Portal User or Guest,,allContents,,,,,,,,,"portal-user,guest",allow, Portal User or Guest,,DiscoverableProduct,,,,,,,,,"portal-user,guest",allow, Portal User or Guest,,services,,,,,,,,,"portal-user,guest",allow, ALL USERS,,mySelf,,,,,,,,,,allow,filterBySelf +ALL USERS,,updateEmail,,,,,,,,,,allow,filterBySelf ALL USERS,,acceptLegal,,,,,,,,,,allow, -ALL USERS,,,User,update,,,,,,,,allow, \ No newline at end of file +ALL USERS,,,User,update,,,,,,,,allow,filterBySelf \ No newline at end of file diff --git a/src/lists/User.js b/src/lists/User.js index 8d320228c..08d123dc4 100644 --- a/src/lists/User.js +++ b/src/lists/User.js @@ -11,7 +11,11 @@ const { EnforcementPoint } = require('../authz/enforcement'); const { lookupEnvironmentAndIssuerById, updateUserLegalAccept, + updateUserEmail, } = require('../services/keystone'); +const { + updateUserProfileDetails, +} = require('../services/keystone/temporary-identity'); // Access control functions const userIsAdmin = ({ authentication: { item: user } }) => { @@ -106,6 +110,23 @@ module.exports = { }, access: EnforcementPoint, }, + { + schema: 'updateEmail(email: String!): User', + resolver: async (item, args, context, info, { query, access }) => { + const user = await updateUserEmail( + context, + context.authedItem.userId, + args.email + ); + await updateUserProfileDetails( + context, + context.authedItem.jti, + args.email + ); + return user; + }, + access: EnforcementPoint, + }, ], }); }, diff --git a/src/mocks/handlers.js b/src/mocks/handlers.js index e15196bd5..09fa395e4 100644 --- a/src/mocks/handlers.js +++ b/src/mocks/handlers.js @@ -104,6 +104,7 @@ const allNamespaces = [ ]; let namespace = personas.mark.namespace; let user = { ...personas.harley, namespace }; +let email = null; export function resetAll() { consumersStore.reset(); @@ -216,7 +217,7 @@ export const handlers = [ allNamespaces.push(namespace); - req( + res( ctx.data({ createNamespace: namespace, }) @@ -304,6 +305,16 @@ export const handlers = [ keystone.mutation('SaveConsumerLabels', saveConsumerLabels), keystone.mutation('GrantAccessToConsumer', grantAccessToConsumerHandler), keystone.mutation('RevokeAccessFromConsumer', revokeAccessFromConsumer), + keystone.mutation('UpdateUserEmail', (req, res, ctx) => { + email = req.variables.email; + return res( + ctx.data({ + updateEmail: { + email, + }, + }) + ); + }), keystone.query('GetBusinessProfile', (req, res, ctx) => { const { serviceAccessId } = req.variables; const institution = diff --git a/src/mocks/resolvers/personas.js b/src/mocks/resolvers/personas.js index 92a39109f..099245ff8 100644 --- a/src/mocks/resolvers/personas.js +++ b/src/mocks/resolvers/personas.js @@ -13,10 +13,11 @@ export const harley = { id: 'harley1', userId: 'uid-harley1', name: 'Harley Jones', - username: 'harley@idir', + username: 'harley_j', email: 'harley@gov.ca', roles: ['portal-user', 'provider-user'], isAdmin: false, + provider: 'bcsc', namespace: 'aps-portal', groups: null, legalsAgreed: '[]', @@ -31,6 +32,7 @@ export const mark = { email: 'mark.smith@gov.ca', roles: ['api-owner'], isAdmin: true, + provider: 'idir', namespace: 'aps-portal', groups: null, legalsAgreed: '[]', diff --git a/src/nextapp/components/complete-profile/complete-profile.tsx b/src/nextapp/components/complete-profile/complete-profile.tsx new file mode 100644 index 000000000..1d309a408 --- /dev/null +++ b/src/nextapp/components/complete-profile/complete-profile.tsx @@ -0,0 +1,91 @@ +import * as React from 'react'; +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalFooter, + ModalBody, + ModalCloseButton, + useDisclosure, + Button, + FormControl, + FormLabel, + Input, + FormHelperText, +} from '@chakra-ui/react'; +import { useAuth } from '@/shared/services/auth'; +import { useApiMutation } from '@/shared/services/api'; +import { gql } from 'graphql-request'; +import { useQueryClient } from 'react-query'; + +const CompleteProfile: React.FC = () => { + const form = React.useRef(null); + const mutate = useApiMutation(mutation); + const client = useQueryClient(); + const { user } = useAuth(); + const { isOpen, onClose } = useDisclosure({ + defaultIsOpen: !user?.email, + }); + + async function handleSubmit(event: React.FormEvent) { + event.preventDefault(); + if (form.current?.checkValidity()) { + const data = new FormData(form.current); + const email = data.get('email'); + await mutate.mutateAsync({ email }); + client.invalidateQueries('user'); + onClose(); + } + } + function handleSave() { + if (form.current?.checkValidity()) { + form.current.requestSubmit(); + } else { + form.current?.elements.email.reportValidity(); + } + } + + if (user?.provider !== 'bcsc' || !user) { + return <>; + } + + return ( + + + + Complete Your Profile + + +
+ + Name + + + + Email address + + This is to notify you when your API access request has been + approved + + + +
+
+ + + +
+
+ ); +}; + +export default CompleteProfile; + +const mutation = gql` + mutation UpdateUserEmail($email: String!) { + updateEmail(email: $email) { + email + } + } +`; diff --git a/src/nextapp/components/complete-profile/index.ts b/src/nextapp/components/complete-profile/index.ts new file mode 100644 index 000000000..2d2fda317 --- /dev/null +++ b/src/nextapp/components/complete-profile/index.ts @@ -0,0 +1 @@ +export { default } from './complete-profile'; diff --git a/src/nextapp/pages/_app.tsx b/src/nextapp/pages/_app.tsx index 4b20e9c00..3e0a4e26b 100644 --- a/src/nextapp/pages/_app.tsx +++ b/src/nextapp/pages/_app.tsx @@ -30,6 +30,7 @@ import '@/shared/styles/global.css'; // const SiteContext = createContext({site: 'devportal'}); import { AppWrapper } from './context'; import '../../mocks'; +import CompleteProfile from '@/components/complete-profile'; const footerItems = [ { href: 'http://www2.gov.bc.ca/gov/content/home', text: 'Home' }, @@ -98,6 +99,7 @@ const App: React.FC = ({ Component, pageProps }) => { type="image/x-icon" /> +
diff --git a/src/nextapp/pages/profile.tsx b/src/nextapp/pages/profile.tsx index c050f1d10..9ea8f7483 100644 --- a/src/nextapp/pages/profile.tsx +++ b/src/nextapp/pages/profile.tsx @@ -4,25 +4,106 @@ import { Avatar, Box, Container, + Editable, + EditableInput, + EditablePreview, Flex, Grid, GridItem, Heading, Text, + ButtonGroup, + Button, + useEditableControls, + Icon, + Input, + useToast, } from '@chakra-ui/react'; -import { getProviderText } from '@/shared/services/utils'; import Head from 'next/head'; -import { uid } from 'react-uid'; - -const fields = [ - { name: 'Name', key: 'name' }, - { name: 'Email', key: 'email' }, - { name: 'Username', key: 'providerUsername' }, - { name: 'Provider', key: 'provider' }, -]; +import { FaExclamationTriangle, FaPen } from 'react-icons/fa'; +import { useApiMutation } from '@/shared/services/api'; +import { gql } from 'graphql-request'; +import { useQueryClient } from 'react-query'; +import { getProviderText } from '@/shared/services/utils'; const ProfilePage: React.FC = () => { const { user } = useAuth(); + const mutate = useApiMutation(mutation); + const toast = useToast(); + const client = useQueryClient(); + const inputRef = React.useRef(null); + const [isInvalid, setIsInvalid] = React.useState(false); + const isEditEmailDisabled = user?.provider === 'idir'; + + function Figure({ + children, + label, + }: { + children: React.ReactNode; + label: string; + }) { + return ( + + + {label} + + {children} + + ); + } + function EditableControls() { + const { + isEditing, + getSubmitButtonProps, + getCancelButtonProps, + getEditButtonProps, + } = useEditableControls(); + + return isEditing ? ( + + + + + ) : ( + + + + ); + } + + async function handleSubmit(value: string) { + const email = value.trim(); + if (email && inputRef.current?.checkValidity()) { + try { + setIsInvalid(false); + await mutate.mutateAsync({ email }); + client.invalidateQueries('user'); + toast({ + status: 'success', + title: 'Email updated', + isClosable: true, + }); + return false; + } catch (err) { + toast({ + status: 'error', + title: 'Unable to update email', + description: err, + isClosable: true, + }); + } + } + setIsInvalid(true); + } return ( <> @@ -41,18 +122,40 @@ const ProfilePage: React.FC = () => { gridRowGap={8} gap={8} > - {fields.map((f) => ( - - - {f.name} - - - {f.key === 'provider' - ? getProviderText(user[f.key]) - : user[f.key] ?? '-'} - - - ))} +
{user.name}
+
+ {isEditEmailDisabled && (user.email ?? '-')} + {!isEditEmailDisabled && ( + + + + + + )} + {!user?.email && ( + + + Email is Required + + )} + {isInvalid && Invalid Email} +
+
{user.username}
+
+ {getProviderText(user.provider)} +
@@ -60,4 +163,12 @@ const ProfilePage: React.FC = () => { ); }; +const mutation = gql` + mutation UpdateUserEmail($email: String!) { + updateEmail(email: $email) { + email + } + } +`; + export default ProfilePage; diff --git a/src/nextapp/shared/services/utils.ts b/src/nextapp/shared/services/utils.ts index 2b4bf7aef..3af440537 100644 --- a/src/nextapp/shared/services/utils.ts +++ b/src/nextapp/shared/services/utils.ts @@ -57,7 +57,7 @@ export const getProviderText = (provider: string): string => { case 'bceid-business': return 'Business BCeID'; case 'github': - return 'Github'; + return 'GitHub'; default: return ''; } diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index 50830dd08..5e71493e2 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -4493,6 +4493,7 @@ export type Mutation = { deleteUsers?: Maybe>>; forceDeleteEnvironment?: Maybe; acceptLegal?: Maybe; + updateEmail?: Maybe; updateConsumerGroupMembership?: Maybe; grantAccessToConsumer?: Maybe; revokeAccessFromConsumer?: Maybe; @@ -5247,6 +5248,11 @@ export type MutationAcceptLegalArgs = { }; +export type MutationUpdateEmailArgs = { + email: Scalars['String']; +}; + + export type MutationUpdateConsumerGroupMembershipArgs = { prodEnvId: Scalars['ID']; consumerId: Scalars['ID']; diff --git a/src/services/keystone/index.ts b/src/services/keystone/index.ts index 8e25b9ff9..84558efab 100644 --- a/src/services/keystone/index.ts +++ b/src/services/keystone/index.ts @@ -63,6 +63,7 @@ export { export { lookupUserLegals, updateUserLegalAccept, + updateUserEmail, LegalAgreed, lookupUserByUsername, lookupUsersByUsernames, diff --git a/src/services/keystone/temporary-identity.ts b/src/services/keystone/temporary-identity.ts index 76183f1da..4cff1e4d9 100644 --- a/src/services/keystone/temporary-identity.ts +++ b/src/services/keystone/temporary-identity.ts @@ -2,6 +2,7 @@ import { Logger } from '../../logger'; import { scopesToRoles } from '../../auth/scope-role-utils'; import { getUma2FromIssuer } from '../keycloak'; import { UMA2TokenService } from '../uma2'; +import { strict as assert } from 'assert'; import jwtDecoder from 'jwt-decode'; import { TemporaryIdentity } from './types'; @@ -100,6 +101,35 @@ export async function assignNamespace( return Boolean(errors) == false; } +export async function updateUserProfileDetails( + context: any, + jti: string, + email: string +): Promise { + const noauthContext = context.createContext({ + skipAccessControl: true, + }); + + const ident = await getIdentityByJti(noauthContext, jti); + let tempId = ident.id; + + const { errors } = await context.executeGraphQL({ + context: noauthContext, + query: `mutation ($tempId: ID!, $email: String) { + updateTemporaryIdentity(id: $tempId, data: {email: $email }) { + id + } }`, + variables: { + tempId, + email, + }, + }); + if (errors) { + logger.error('[updateUserProfileDetails] %s %j', jti, errors); + } + return Boolean(errors) == false; +} + async function getIdentityByJti( context: any, jti: string @@ -114,5 +144,15 @@ async function getIdentityByJti( }, }); logger.debug('[getIdentityByJti] %j', result); + + if (result.errors) { + logger.error('[getIdentityByJti] %s %j', jti, result); + } + assert.strictEqual( + result.data?.allTemporaryIdentities?.length, + 1, + 'Unable to get identity information' + ); + return result.data.allTemporaryIdentities[0]; } diff --git a/src/services/keystone/types.ts b/src/services/keystone/types.ts index 50830dd08..5e71493e2 100644 --- a/src/services/keystone/types.ts +++ b/src/services/keystone/types.ts @@ -4493,6 +4493,7 @@ export type Mutation = { deleteUsers?: Maybe>>; forceDeleteEnvironment?: Maybe; acceptLegal?: Maybe; + updateEmail?: Maybe; updateConsumerGroupMembership?: Maybe; grantAccessToConsumer?: Maybe; revokeAccessFromConsumer?: Maybe; @@ -5247,6 +5248,11 @@ export type MutationAcceptLegalArgs = { }; +export type MutationUpdateEmailArgs = { + email: Scalars['String']; +}; + + export type MutationUpdateConsumerGroupMembershipArgs = { prodEnvId: Scalars['ID']; consumerId: Scalars['ID']; diff --git a/src/services/keystone/user.ts b/src/services/keystone/user.ts index a3e6a0a18..3739532d4 100644 --- a/src/services/keystone/user.ts +++ b/src/services/keystone/user.ts @@ -29,6 +29,30 @@ export async function lookupUserLegals( return JSON.parse(result.data.User.legalsAgreed); } +export async function updateUserEmail( + context: any, + userId: string, + email: string +): Promise { + const result = await context.executeGraphQL({ + query: `mutation UpdateUserEmail($userId: ID!, $email: String!) { + updateUser(id: $userId, data: { email: $email } ) { + id + email + } + }`, + variables: { userId, email }, + }); + + logger.debug('[updateUserEmail] RESULT %j', result); + assert.strictEqual( + result.data.updateUser != null, + true, + 'Failed to update user email' + ); + return result.data.updateUser; +} + export async function updateUserLegalAccept( context: any, userId: string, From 7790644a15fa32d6375cff440abc8b802d877409 Mon Sep 17 00:00:00 2001 From: Joshua Jones Date: Fri, 10 Mar 2023 14:55:05 -0800 Subject: [PATCH 2/6] Add dash to new namespace dialog (#767) --- src/nextapp/components/new-namespace/new-namespace.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nextapp/components/new-namespace/new-namespace.tsx b/src/nextapp/components/new-namespace/new-namespace.tsx index 6416fdf27..9ed28b46b 100644 --- a/src/nextapp/components/new-namespace/new-namespace.tsx +++ b/src/nextapp/components/new-namespace/new-namespace.tsx @@ -96,7 +96,7 @@ const NewNamespace: React.FC = ({ isOpen, onClose }) => { Names must be: - Alphanumeric (letters and numbers only, no special + Alphanumeric (letters, numbers and dashes only, no special characters) Unique to all other namespaces From fc230da295423c0e99dcf43b18a6684a4b4ac0c9 Mon Sep 17 00:00:00 2001 From: ike thecoder Date: Sat, 11 Mar 2023 14:25:20 -0800 Subject: [PATCH 3/6] Feature Ops Metrics fix (#777) * upd feeder logging * get more reliable data comparison for batch * add a json stringifier * inc activity result in ops metrics * remove unused imports for feeder * upd authz profile email * user profile username fix --- .../feeder-init/platform-authz-profile.yaml | 2 +- feeds/ckan/index.js | 2 +- feeds/kong/index.js | 63 +- feeds/logger.js | 7 +- feeds/prometheus/index.js | 18 +- feeds/utils/portal.js | 7 +- feeds/utils/results.js | 35 + feeds/utils/transfers.js | 8 +- src/batch/feed-worker.ts | 2 +- src/batch/transformations/toString.ts | 15 +- .../transformations/toStringDefaultArray.ts | 14 +- src/nextapp/pages/profile.tsx | 2 +- src/package-lock.json | 733 ++---------------- src/package.json | 1 + src/services/report/ops-metrics.ts | 6 +- src/yarn.lock | 294 +++---- 16 files changed, 303 insertions(+), 906 deletions(-) create mode 100644 feeds/utils/results.js diff --git a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml index abec9d467..dbf523ad5 100644 --- a/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml +++ b/.github/workflows/scripts/feeder-init/platform-authz-profile.yaml @@ -18,7 +18,7 @@ record: - GatewayConfig.Publish - Content.Publish - CredentialIssuer.Admin - owner: janis@gov.bc.ca + owner: api-owner@local environmentDetails: - environment: prod issuerUrl: '{OIDC_ISSUER}' diff --git a/feeds/ckan/index.js b/feeds/ckan/index.js index c16e875c1..1176f6417 100644 --- a/feeds/ckan/index.js +++ b/feeds/ckan/index.js @@ -47,7 +47,7 @@ async function scopedSync( loadDatasetProducer(xfer, scopedDir, destinationUrl) ); - fs.rmdirSync(scopedDir, { recursive: true }); + fs.rmSync(scopedDir, { recursive: true }); } async function syncOrgs({ url, workingPath, destinationUrl }) { diff --git a/feeds/kong/index.js b/feeds/kong/index.js index 60827013d..020341f92 100644 --- a/feeds/kong/index.js +++ b/feeds/kong/index.js @@ -70,6 +70,8 @@ async function scopedSyncByNamespace( loadGroupsProducer(xfer, destinationUrl, '/feed/GatewayGroup') ); + xfer.resultCollector().output(); + // remove any GatewayService or GatewayRoutes that no longer exist in Kong const destination = portal(destinationUrl); @@ -94,7 +96,7 @@ async function scopedSyncByNamespace( } } - fs.rmdirSync(scopedDir, { recursive: true }); + fs.rmSync(scopedDir, { recursive: true }); } async function scopedSyncByConsumer( @@ -122,7 +124,9 @@ async function scopedSyncByConsumer( ) ); - fs.rmdirSync(scopedDir, { recursive: true }); + xfer.resultCollector().output(); + + fs.rmSync(scopedDir, { recursive: true }); } async function sync({ url, workingPath, destinationUrl }) { @@ -166,9 +170,13 @@ async function sync({ url, workingPath, destinationUrl }) { '/feed/GatewayConsumer' ) ); + await xfer.concurrentWork( loadGroupsProducer(xfer, destinationUrl, '/feed/GatewayGroup') ); + + xfer.resultCollector().output(); + //await xfer.concurrentWork(loadProducer(xfer, destinationUrl, 'gw-products', 'name', 'product', '/feed/Product')) //await xfer.concurrentWork(loadServiceAccessProducer(xfer, destinationUrl, 'gw-consumers', '/feed/ServiceAccess')) } @@ -181,26 +189,11 @@ function loadProducer(xfer, destinationUrl, file, name, type, feedPath) { type == 'consumer' ? xfer.get_json_content('gw-acls')['data'] : null; let index = 0; - log.info('[producer] %s : %d records', file, items.length); - - const results = { - 'no-change': 0, - created: 0, - 'created-failed': 0, - updated: 0, - deleted: 0, - 'updated-failed': 0, - 'deleted-failed': 0, - }; + log.debug('[producer] %s : %d records', file, items.length); return () => { if (index == items.length) { - Object.keys(results) - .filter((r) => results[r] != 0) - .forEach((r) => { - log.info('[%s] %d', String(r).padStart(15, ' '), results[r]); - }); - log.info('Finished producing ' + index + ' records.'); + log.info('[producer] %s : Finished %d records', file, items.length); return null; } const item = items[index]; @@ -244,12 +237,14 @@ function loadProducer(xfer, destinationUrl, file, name, type, feedPath) { return destination .fireAndForget(feedPath, item) .then((result) => { - results[result['result']]++; + xfer.resultCollector().inc(result['result']); log.debug('%s -> %s OK', file, result); }) .catch((err) => { - log.error(`[${nm}] ERR ${err}`); + xfer.resultCollector().inc('exception'); + log.error('%s', err); + log.error('%j', item); }); }; } @@ -279,28 +274,17 @@ function loadGroupsProducer(xfer, destinationUrl, feedPath) { }); }); - log.info('[loadGroupsProducer] (%s) %d records', feedPath, items.length); + log.debug('[loadGroupsProducer] (%s) %d records', feedPath, items.length); let index = 0; - const results = { - 'no-change': 0, - created: 0, - 'created-failed': 0, - updated: 0, - deleted: 0, - 'updated-failed': 0, - 'deleted-failed': 0, - }; - return () => { if (index == items.length) { - Object.keys(results) - .filter((r) => results[r] != 0) - .forEach((r) => { - log.info('[%s] %d', String(r).padStart(15, ' '), results[r]); - }); - log.info('Finished producing ' + index + ' records.'); + log.info( + '[loadGroupsProducer] %s : Finished %d records', + feedPath, + items.length + ); return null; } const item = items[index]; @@ -316,10 +300,11 @@ function loadGroupsProducer(xfer, destinationUrl, feedPath) { return destination .fireAndForget(feedPath, item) .then((result) => { - results[result['result']]++; + xfer.resultCollector().inc(result['result']); log.debug('%s -> %s OK', feedPath, result); }) .catch((err) => { + xfer.resultCollector().inc('exception'); log.error(`[${nm}] ERR ${err}`); }); }; diff --git a/feeds/logger.js b/feeds/logger.js index 0adaa447f..a9ca597eb 100644 --- a/feeds/logger.js +++ b/feeds/logger.js @@ -1,4 +1,5 @@ const winston = require('winston'); +const { createLogger, format, transports } = require('winston'); const enumerateErrorFormat = winston.format((info) => { if (info instanceof Error) { @@ -14,12 +15,16 @@ function Logger(category) { level: process.env.LOG_LEVEL || 'debug', format: winston.format.combine( enumerateErrorFormat(), + format.timestamp({ + format: 'YYYY-MM-DD HH:mm:ss', + }), process.env.NODE_ENV === 'production' ? winston.format.uncolorize() : winston.format.colorize(), winston.format.splat(), winston.format.printf( - ({ level, message, stack }) => `${level}: [${category}] ${message}` + ({ timestamp, level, message, stack }) => + `${timestamp} ${level}: [${category}] ${message}` ) ), transports: [ diff --git a/feeds/prometheus/index.js b/feeds/prometheus/index.js index 741a94268..d885020e4 100644 --- a/feeds/prometheus/index.js +++ b/feeds/prometheus/index.js @@ -91,6 +91,8 @@ async function syncQueryRanges( await xfer.concurrentWork( producer(xfer, 'query_range', params.numDays, destinationUrl) ); + + xfer.resultCollector().output(); } async function syncQueries( @@ -126,6 +128,8 @@ async function syncQueries( await xfer.concurrentWork( producer(xfer, 'query', params.numDays, destinationUrl) ); + + xfer.resultCollector().output(); } function producer(xfer, queryType, numDays, destinationUrl) { @@ -139,7 +143,7 @@ function producer(xfer, queryType, numDays, destinationUrl) { const results = Array.isArray(json['data']) ? json['data'][0]['result'] : json['data']['result']; - log.info( + log.debug( '[producer] %s %s : %d records', target, _query.id, @@ -180,8 +184,16 @@ function producer(xfer, queryType, numDays, destinationUrl) { return destination .fireAndForget('/feed/Metric', item.metric) - .then((result) => log.debug(`[${name}] OK`, result)) - .catch((err) => log.error(`[${name}] ERR ${err}`)); + .then((result) => { + xfer.resultCollector().inc(result['result']); + + log.debug('%s -> %s OK', name, result); + }) + .catch((err) => { + xfer.resultCollector().inc('exception'); + log.error('%s', err); + log.error('%j', item); + }); }; } diff --git a/feeds/utils/portal.js b/feeds/utils/portal.js index 31659700c..6b4f2a651 100644 --- a/feeds/utils/portal.js +++ b/feeds/utils/portal.js @@ -1,5 +1,8 @@ const fs = require('fs'); const fetch = require('node-fetch'); +const { Logger } = require('../logger'); + +const log = Logger('utils.portal'); const checkStatus = require('./checkStatus').checkStatus; @@ -25,7 +28,7 @@ function portal(baseUrl, logFeeds = _logFeeds) { let retry = attempts; while (retry <= attempts) { retry != attempts && - console.log('Retrying [' + (attempts - retry) + '] ' + url); + log.error('Retrying [' + (attempts - retry) + '] ' + url); try { return await fetch(baseUrl + url, { method: 'put', @@ -47,7 +50,7 @@ function portal(baseUrl, logFeeds = _logFeeds) { let retry = attempts; while (retry <= attempts) { retry != attempts && - console.log('Retrying [' + (attempts - retry) + '] ' + url); + log.error('Retrying [' + (attempts - retry) + '] ' + url); try { return await fetch(baseUrl + url, { method: 'delete', diff --git a/feeds/utils/results.js b/feeds/utils/results.js new file mode 100644 index 000000000..4a5fef342 --- /dev/null +++ b/feeds/utils/results.js @@ -0,0 +1,35 @@ +const { Logger } = require('../logger'); + +const log = Logger('results'); + +class ResultsService { + init() { + this.results = { + 'no-change': 0, + exception: 0, + created: 0, + 'created-failed': 0, + updated: 0, + deleted: 0, + 'updated-failed': 0, + 'deleted-failed': 0, + }; + } + + inc(result) { + this.results[result]++; + } + + output() { + const { results } = this; + Object.keys(results) + .filter((r) => results[r] != 0) + .forEach((r) => { + log.info('[%s] %d', String(r).padStart(15, ' '), results[r]); + }); + } +} + +module.exports = { + ResultsService, +}; diff --git a/feeds/utils/transfers.js b/feeds/utils/transfers.js index fdd466ab4..3f14f5305 100644 --- a/feeds/utils/transfers.js +++ b/feeds/utils/transfers.js @@ -5,13 +5,19 @@ const PromisePool = require('es6-promise-pool'); const { checkStatus } = require('./checkStatus'); const { Logger } = require('../logger'); const stringify = require('json-stable-stringify'); +const { ResultsService } = require('./results'); const log = Logger('utils.xfer'); function transfers(workingPath, baseUrl, exceptions) { fs.mkdirSync(workingPath, { recursive: true }); + const resultCollector = new ResultsService(); + resultCollector.init(); + return { + resultCollector: () => resultCollector, + copy: async function (_url, filename, index = 0) { log.debug('[copy] %s%s', baseUrl, _url); const out = workingPath + '/' + filename + '-' + index + '.json'; @@ -79,7 +85,7 @@ function transfers(workingPath, baseUrl, exceptions) { // Wait for the pool to settle. return poolPromise.then( function () { - log.info('All promises fulfilled'); + log.debug('All promises fulfilled'); }, function (error) { log.error('Some promise rejected: ' + error.message); diff --git a/src/batch/feed-worker.ts b/src/batch/feed-worker.ts index c805c7660..76122ea68 100644 --- a/src/batch/feed-worker.ts +++ b/src/batch/feed-worker.ts @@ -203,7 +203,7 @@ function buildQueryResponse(md: any, children: string[] = undefined): string[] { const relationshipFields = Object.keys( md.transformations ).filter((tranField: any) => - ['connectOne', 'connectExclusiveList', 'connectMany'].includes( + ['byKey', 'connectOne', 'connectExclusiveList', 'connectMany'].includes( md.transformations[tranField].name ) ); diff --git a/src/batch/transformations/toString.ts b/src/batch/transformations/toString.ts index 3f17918c7..55903fb63 100644 --- a/src/batch/transformations/toString.ts +++ b/src/batch/transformations/toString.ts @@ -1,4 +1,15 @@ +import stringify from 'json-stable-stringify'; -export function toString (keystone: any, transformInfo: any, currentData: any, inputData: any, key: string) { - return inputData[key] == null || (currentData != null && currentData[key] === JSON.stringify(inputData[key])) ? null:JSON.stringify(inputData[key]) +export function toString( + keystone: any, + transformInfo: any, + currentData: any, + inputData: any, + key: string +) { + const value = stringify(inputData[key]); + return inputData[key] == null || + (currentData != null && currentData[key] === value) + ? null + : value; } diff --git a/src/batch/transformations/toStringDefaultArray.ts b/src/batch/transformations/toStringDefaultArray.ts index a4dbf949b..41973c2ae 100644 --- a/src/batch/transformations/toStringDefaultArray.ts +++ b/src/batch/transformations/toStringDefaultArray.ts @@ -1,4 +1,14 @@ +import stringify from 'json-stable-stringify'; -export function toStringDefaultArray (keystone: any, transformInfo: any, currentData: any, inputData: any, key: string) { - return inputData[key] == null || (currentData != null && currentData[key] === JSON.stringify(inputData[key])) ? null:JSON.stringify(inputData[key]) +export function toStringDefaultArray( + keystone: any, + transformInfo: any, + currentData: any, + inputData: any, + key: string +) { + return inputData[key] == null || + (currentData != null && currentData[key] === stringify(inputData[key])) + ? null + : stringify(inputData[key]); } diff --git a/src/nextapp/pages/profile.tsx b/src/nextapp/pages/profile.tsx index 9ea8f7483..5b2aa8d46 100644 --- a/src/nextapp/pages/profile.tsx +++ b/src/nextapp/pages/profile.tsx @@ -152,7 +152,7 @@ const ProfilePage: React.FC = () => { )} {isInvalid && Invalid Email} -
{user.username}
+
{user.providerUsername}
{getProviderText(user.provider)}
diff --git a/src/package-lock.json b/src/package-lock.json index fce36aba6..bd8cafbc2 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -53,12 +53,12 @@ "http-proxy-middleware": "^1.1.2", "isomorphic-unfetch": "^3.1.0", "js-yaml": "^4.1.0", + "json-stable-stringify": "^1.0.2", "jwks-rsa": "^2.0.5", "jwt-decode": "^3.1.2", "keycloak-connect": "^17.0.1", "lodash": "^4.17.21", "multer": "^1.4.2", - "next": "9.5.5", "nodemailer": "^6.6.0", "npmlog": "^6.0.1", "numeral": "^2.0.6", @@ -7732,31 +7732,6 @@ "node": ">=0.10.0" } }, - "node_modules/@keystone-next/fields/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/@keystone-next/fields/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/@keystone-next/keystone": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@keystone-next/keystone/-/keystone-9.0.0.tgz", @@ -8084,31 +8059,6 @@ "node": ">=0.10.0" } }, - "node_modules/@keystone-ui/button/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/@keystone-ui/button/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/@keystone-ui/fields": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@keystone-ui/fields/-/fields-1.0.3.tgz", @@ -8193,31 +8143,6 @@ "node": ">=0.10.0" } }, - "node_modules/@keystone-ui/fields/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/@keystone-ui/fields/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/@keystone-ui/loading": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@keystone-ui/loading/-/loading-1.0.0.tgz", @@ -8284,31 +8209,6 @@ "node": ">=0.10.0" } }, - "node_modules/@keystone-ui/loading/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/@keystone-ui/loading/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/@keystone-ui/modals": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@keystone-ui/modals/-/modals-1.0.2.tgz", @@ -8379,31 +8279,6 @@ "node": ">=0.10.0" } }, - "node_modules/@keystone-ui/modals/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/@keystone-ui/modals/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/@keystone-ui/notice": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@keystone-ui/notice/-/notice-1.0.1.tgz", @@ -8487,31 +8362,6 @@ "node": ">=0.10.0" } }, - "node_modules/@keystone-ui/notice/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/@keystone-ui/notice/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/@keystonejs/access-control": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/@keystonejs/access-control/-/access-control-7.1.2.tgz", @@ -11140,31 +10990,6 @@ "node": ">=0.10.0" } }, - "node_modules/@keystonejs/fields-wysiwyg-tinymce/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/@keystonejs/fields-wysiwyg-tinymce/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/@keystonejs/fields/node_modules/@arch-ui/alert": { "version": "0.0.18", "resolved": "https://registry.npmjs.org/@arch-ui/alert/-/alert-0.0.18.tgz", @@ -16208,58 +16033,11 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/@types/keystonejs__adapter-knex/node_modules/pg": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.18.2.tgz", - "integrity": "sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA==", - "optional": true, - "peer": true, - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "0.1.3", - "pg-packet-stream": "^1.1.0", - "pg-pool": "^2.0.10", - "pg-types": "^2.1.0", - "pgpass": "1.x", - "semver": "4.3.2" - }, - "engines": { - "node": ">= 4.5.0" - } - }, "node_modules/@types/keystonejs__adapter-knex/node_modules/pg-connection-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.1.0.tgz", "integrity": "sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg==" }, - "node_modules/@types/keystonejs__adapter-knex/node_modules/pg-pool": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.10.tgz", - "integrity": "sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg==", - "optional": true, - "peer": true, - "peerDependencies": { - "pg": ">5.0" - } - }, - "node_modules/@types/keystonejs__adapter-knex/node_modules/pg/node_modules/pg-connection-string": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", - "integrity": "sha512-i0NV/CrSkFTaiOQs9AGy3tq0dkSjtTd4d7DfsjeDVZAA4aIHInwfFEmriNYGGJUfZ5x6IAC/QddoUpUJjQAi0w==", - "optional": true, - "peer": true - }, - "node_modules/@types/keystonejs__adapter-knex/node_modules/semver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha512-VyFUffiBx8hABJ9HYSTXLRwyZtdDHMzMtFmID1aiNAD2BZppBmJm0Hqw3p2jkgxP9BNt1pQ9RnC49P0EcXf6cA==", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/@types/keystonejs__adapter-knex/node_modules/tarn": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tarn/-/tarn-2.0.0.tgz", @@ -17161,46 +16939,6 @@ "@vue/shared": "3.0.5" } }, - "node_modules/@vue/reactivity": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.0.5.tgz", - "integrity": "sha512-3xodUE3sEIJgS7ntwUbopIpzzvi7vDAOjVamfb2l+v1FUg0jpd3gf62N2wggJw3fxBMr+QvyxpD+dBoxLsmAjw==", - "optional": true, - "peer": true, - "dependencies": { - "@vue/shared": "3.0.5" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.0.5.tgz", - "integrity": "sha512-Cnyi2NqREwOLcTEsIi1DQX1hHtkVj4eGm4hBG7HhokS05DqpK4/80jG6PCCnCH9rIJDB2FqtaODX397210plXg==", - "optional": true, - "peer": true, - "dependencies": { - "@vue/reactivity": "3.0.5", - "@vue/shared": "3.0.5" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.5.tgz", - "integrity": "sha512-iilX1KySeIzHHtErT6Y44db1rhWK5tAI0CiJIPr+SJoZ2jbjoOSE6ff/jfIQakchbm1d6jq6VtRVnp5xYdOXKA==", - "optional": true, - "peer": true, - "dependencies": { - "@vue/runtime-core": "3.0.5", - "@vue/shared": "3.0.5", - "csstype": "^2.6.8" - } - }, - "node_modules/@vue/runtime-dom/node_modules/csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==", - "optional": true, - "peer": true - }, "node_modules/@vue/shared": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.5.tgz", @@ -33525,11 +33263,14 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= sha512-i/J297TW6xyj7sDFa7AmBPkQvLIxWr2kKPWI26tXydnZrzVAocNqn5DMNT1Mzk0vit1V5UkRM7C1KdVNp7Lmcg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", + "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", "dependencies": { - "jsonify": "~0.0.0" + "jsonify": "^0.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/json-stable-stringify-without-jsonify": { @@ -33574,11 +33315,11 @@ } }, "node_modules/jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA==", - "engines": { - "node": "*" + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/jsonwebtoken": { @@ -39800,13 +39541,6 @@ "node": ">=4.0.0" } }, - "node_modules/pg-packet-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pg-packet-stream/-/pg-packet-stream-1.1.0.tgz", - "integrity": "sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg==", - "optional": true, - "peer": true - }, "node_modules/pg-pool": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", @@ -47837,18 +47571,6 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" }, - "node_modules/vue": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.0.5.tgz", - "integrity": "sha512-TfaprOmtsAfhQau7WsomXZ8d9op/dkQLNIq8qPV3A0Vxs6GR5E+c1rfJS1SDkXRQj+dFyfnec7+U0Be1huiScg==", - "optional": true, - "peer": true, - "dependencies": { - "@vue/compiler-dom": "3.0.5", - "@vue/runtime-dom": "3.0.5", - "@vue/shared": "3.0.5" - } - }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -49533,8 +49255,7 @@ "@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==", - "requires": {} + "integrity": "sha512-VcsXHfTFoCodDAgJZxN04GdFK1kqOhZQnQY/9Fa147P+I8xfvOSz5d+lKAPB+hwSgBNyd7ncAKGIs4+utbL+yA==" }, "@apollographql/graphql-playground-html": { "version": "1.6.29", @@ -51955,8 +51676,7 @@ "@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==", - "requires": {} + "integrity": "sha512-UaPsImGHvCgFO3ayp6Ugafu2/3/EG8wlW/8Y9Ihfk1UFv8cpV+3BfWKmuZ7IcmxcBL9dkP6E8p3/M1T0FB92hg==" }, "@chakra-ui/descendant": { "version": "2.0.0", @@ -53690,8 +53410,7 @@ "@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==", - "requires": {} + "integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==" }, "@hapi/accept": { "version": "5.0.1", @@ -55242,28 +54961,6 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2" } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } } } }, @@ -55519,28 +55216,6 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2" } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } } } }, @@ -55601,28 +55276,6 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2" } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } } } }, @@ -55671,28 +55324,6 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2" } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } } } }, @@ -55745,28 +55376,6 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2" } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } } } }, @@ -55826,28 +55435,6 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2" } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } } } }, @@ -57988,8 +57575,7 @@ "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==", - "requires": {} + "integrity": "sha512-YSJ9Gb4tGpbzPje3eNKtu26hWM8ApxTk9RzjK+6zfD5V/RMTkuWONk24y6c9lZk0OAYNZNUmrnb/QZfU3j9nag==" } } }, @@ -58069,8 +57655,7 @@ "react-codemirror2": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-7.2.1.tgz", - "integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==", - "requires": {} + "integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==" } } }, @@ -58507,28 +58092,6 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2" } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } } } }, @@ -58739,8 +58302,7 @@ "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "dev": true, - "requires": {} + "dev": true }, "@mdx-js/util": { "version": "1.6.22", @@ -58796,8 +58358,7 @@ "@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==", - "requires": {} + "integrity": "sha512-BTpWy1e+FxN82RnLz4x1+JcEewVdfmUhV1C6/XYD5AjS7PQp9QFF7K8bCD6gzPTr2l+prvqOyVueQhFJxB1vfg==" }, "@next/env": { "version": "9.5.5", @@ -58985,8 +58546,7 @@ "@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==", - "requires": {} + "integrity": "sha512-4sVhkrBKuj3h+PFw69yOyO/l3nQB/mm95V+Kz7LRSlIrbZr6hZarZD5Ft4ewdONPROkIHQM/6KSK90+OAimxsQ==" }, "@prisma/bar": { "version": "0.0.1", @@ -60291,8 +59851,7 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -60643,8 +60202,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -61735,52 +61293,11 @@ "minimist": "^1.2.6" } }, - "pg": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.18.2.tgz", - "integrity": "sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA==", - "optional": true, - "peer": true, - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "0.1.3", - "pg-packet-stream": "^1.1.0", - "pg-pool": "^2.0.10", - "pg-types": "^2.1.0", - "pgpass": "1.x", - "semver": "4.3.2" - }, - "dependencies": { - "pg-connection-string": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", - "integrity": "sha512-i0NV/CrSkFTaiOQs9AGy3tq0dkSjtTd4d7DfsjeDVZAA4aIHInwfFEmriNYGGJUfZ5x6IAC/QddoUpUJjQAi0w==", - "optional": true, - "peer": true - } - } - }, "pg-connection-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.1.0.tgz", "integrity": "sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg==" }, - "pg-pool": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.10.tgz", - "integrity": "sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg==", - "optional": true, - "peer": true, - "requires": {} - }, - "semver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha512-VyFUffiBx8hABJ9HYSTXLRwyZtdDHMzMtFmID1aiNAD2BZppBmJm0Hqw3p2jkgxP9BNt1pQ9RnC49P0EcXf6cA==", - "optional": true, - "peer": true - }, "tarn": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tarn/-/tarn-2.0.0.tgz", @@ -62570,48 +62087,6 @@ "@vue/shared": "3.0.5" } }, - "@vue/reactivity": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.0.5.tgz", - "integrity": "sha512-3xodUE3sEIJgS7ntwUbopIpzzvi7vDAOjVamfb2l+v1FUg0jpd3gf62N2wggJw3fxBMr+QvyxpD+dBoxLsmAjw==", - "optional": true, - "peer": true, - "requires": { - "@vue/shared": "3.0.5" - } - }, - "@vue/runtime-core": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.0.5.tgz", - "integrity": "sha512-Cnyi2NqREwOLcTEsIi1DQX1hHtkVj4eGm4hBG7HhokS05DqpK4/80jG6PCCnCH9rIJDB2FqtaODX397210plXg==", - "optional": true, - "peer": true, - "requires": { - "@vue/reactivity": "3.0.5", - "@vue/shared": "3.0.5" - } - }, - "@vue/runtime-dom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.5.tgz", - "integrity": "sha512-iilX1KySeIzHHtErT6Y44db1rhWK5tAI0CiJIPr+SJoZ2jbjoOSE6ff/jfIQakchbm1d6jq6VtRVnp5xYdOXKA==", - "optional": true, - "peer": true, - "requires": { - "@vue/runtime-core": "3.0.5", - "@vue/shared": "3.0.5", - "csstype": "^2.6.8" - }, - "dependencies": { - "csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==", - "optional": true, - "peer": true - } - } - }, "@vue/shared": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.5.tgz", @@ -62883,8 +62358,7 @@ "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, - "requires": {} + "dev": true }, "acorn-node": { "version": "1.8.2", @@ -63005,14 +62479,12 @@ "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==", - "requires": {} + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" }, "ally.js": { "version": "1.4.1", @@ -63310,8 +62782,7 @@ "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==", - "requires": {} + "integrity": "sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA==" }, "apollo-server-express": { "version": "2.25.3", @@ -64189,8 +63660,7 @@ "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, - "requires": {} + "dev": true }, "babel-plugin-polyfill-corejs2": { "version": "0.3.1", @@ -66602,8 +66072,7 @@ "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==", - "requires": {} + "integrity": "sha512-eCnYYEUEc5i32LHwpE/W7NlddOB9oHwsPaWtWzYtflNkkwa3IfindIcoXdVWs12zCbwaMCavKNu84EXogVIWHw==" }, "create-require": { "version": "1.1.1", @@ -66766,8 +66235,7 @@ "icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "requires": {} + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" }, "lru-cache": { "version": "7.8.0", @@ -66787,8 +66255,7 @@ "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==", - "requires": {} + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -68410,8 +67877,7 @@ "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, - "requires": {} + "dev": true }, "eslint-plugin-jest": { "version": "24.1.3", @@ -68476,8 +67942,7 @@ "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, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -70596,8 +70061,7 @@ "graphql-executor": { "version": "0.0.22", "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.22.tgz", - "integrity": "sha512-WbKSnSHFn6REKKH4T6UAwDM3mLUnYMQlQLNG0Fw+Lkb3ilCnL3m5lkJ7411LAI9sF7BvPbthovVZhsEUh9Xfag==", - "requires": {} + "integrity": "sha512-WbKSnSHFn6REKKH4T6UAwDM3mLUnYMQlQLNG0Fw+Lkb3ilCnL3m5lkJ7411LAI9sF7BvPbthovVZhsEUh9Xfag==" }, "graphql-extensions": { "version": "0.15.0", @@ -70728,8 +70192,7 @@ "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "requires": {} + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" } } }, @@ -70809,8 +70272,7 @@ "graphql-ws": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.7.0.tgz", - "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==", - "requires": {} + "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==" }, "minimatch": { "version": "4.2.1", @@ -70982,8 +70444,7 @@ "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "requires": {} + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" } } }, @@ -71063,8 +70524,7 @@ "graphql-ws": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.7.0.tgz", - "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==", - "requires": {} + "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==" }, "minimatch": { "version": "4.2.1", @@ -71147,8 +70607,7 @@ "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==", - "requires": {} + "integrity": "sha512-xE8AGPJa5X+g7iFmRQw/8H+7lXIDJvSkW6lou/XSSq17opPQl+dbKOMiqraHMx52VrDgS061ZVx90OSuqS6ykA==" }, "graphql-subscriptions": { "version": "1.1.0", @@ -71209,8 +70668,7 @@ "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==", - "requires": {} + "integrity": "sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==" }, "graphql-upload": { "version": "11.0.0", @@ -71234,8 +70692,7 @@ "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==", - "requires": {} + "integrity": "sha512-sHkK9+lUm20/BGawNEWNtVAeJzhZeBg21VmvmLoT5NdGVeZWv5PdIhkcayQIAgjSyyQ17WMKmbDijIPG2On+Ag==" }, "gray-percentage": { "version": "2.0.0", @@ -72745,8 +72202,7 @@ "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==", - "requires": {} + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==" }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -74160,8 +73616,7 @@ "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, - "requires": {} + "dev": true }, "jest-regex-util": { "version": "26.0.0", @@ -75345,8 +74800,7 @@ "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -75376,11 +74830,11 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= sha512-i/J297TW6xyj7sDFa7AmBPkQvLIxWr2kKPWI26tXydnZrzVAocNqn5DMNT1Mzk0vit1V5UkRM7C1KdVNp7Lmcg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", + "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", "requires": { - "jsonify": "~0.0.0" + "jsonify": "^0.0.1" } }, "json-stable-stringify-without-jsonify": { @@ -75414,9 +74868,9 @@ } }, "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA==" + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==" }, "jsonwebtoken": { "version": "8.5.1", @@ -76571,8 +76025,7 @@ "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, - "requires": {} + "dev": true }, "match-sorter": { "version": "6.1.0", @@ -76881,8 +76334,7 @@ "meros": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/meros/-/meros-1.1.4.tgz", - "integrity": "sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ==", - "requires": {} + "integrity": "sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ==" }, "mersenne-twister": { "version": "1.1.0", @@ -77310,8 +76762,7 @@ "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==", - "requires": {} + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" }, "move-concurrently": { "version": "1.0.1", @@ -77887,8 +77338,7 @@ "@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==", - "requires": {} + "integrity": "sha512-Gz5z0+ID+KAGto6Tkgv1a340damEw3HG6ANLKwNi5/QSHqQ3JUAVxMuhz3qnL54505I777evpzL89ofWEMIWKw==" }, "acorn": { "version": "6.4.2", @@ -80240,18 +79690,10 @@ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" }, - "pg-packet-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pg-packet-stream/-/pg-packet-stream-1.1.0.tgz", - "integrity": "sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg==", - "optional": true, - "peer": true - }, "pg-pool": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", - "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", - "requires": {} + "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==" }, "pg-protocol": { "version": "1.5.0", @@ -81141,8 +80583,7 @@ "version": "5.5.1", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz", "integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==", - "dev": true, - "requires": {} + "dev": true }, "react-copy-to-clipboard": { "version": "5.0.4", @@ -81156,8 +80597,7 @@ "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==", - "requires": {} + "integrity": "sha512-qvasG5iH6M+Ix3HAtCiSum6xbngG5re5F2bZN3VRof7FAl3LJbNcq+5geEITSLRt5uo3IsXF5eFvG6Ggpzw8og==" }, "react-display-name": { "version": "0.2.5", @@ -81289,14 +80729,12 @@ "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==", - "requires": {} + "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==" }, "react-image": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/react-image/-/react-image-4.0.3.tgz", - "integrity": "sha512-19MUK9u1qaw9xys8XEsVkSpVhHctEBUeYFvrLTe1PN+4w5Co13AN2WA7xtBshPM6SthsOj77SlDrEAeOaJpf7g==", - "requires": {} + "integrity": "sha512-19MUK9u1qaw9xys8XEsVkSpVhHctEBUeYFvrLTe1PN+4w5Co13AN2WA7xtBshPM6SthsOj77SlDrEAeOaJpf7g==" }, "react-immutable-proptypes": { "version": "2.2.0", @@ -81328,8 +80766,7 @@ "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==", - "requires": {} + "integrity": "sha512-XraIC/tkrD9JtrmVA7ypEN1QIpKc52mXBH1u/bz/aicRLo8QQEJQAMUTb8mz4B6dqpPwyzgjrr7Ljv/2ACDtqw==" }, "react-is": { "version": "17.0.2", @@ -81415,14 +80852,12 @@ "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==", - "requires": {} + "integrity": "sha512-JmerjAXs7qJ959+d0Ygt7Cb2+4fG+n3I2VXO6JO0AcAY1vkRN/JpZKAN67CMXY889xEJcfylmMPhzvf6nWO68Q==" }, "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==", - "requires": {} + "integrity": "sha512-czJNP0MpcqJISnFwxYz8IlJklsUbWyuSqWJWLbXi/MUQWIEu2t6PbOGHIVvtpw9i0N3hHZ50nSNCDMLp4fpenQ==" }, "react-query": { "version": "3.5.11", @@ -81988,8 +81423,7 @@ "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==", - "requires": {} + "integrity": "sha1-Ohoy32Y2ZGK2NpHw4dw15HK7yfM= sha512-SchSn/DWfGb3oAejd+1hhHx01xUoxY+V7TeK0BKqpkLKiQPVFf7DYzEaKmrEVxsWxielKfSK9/Xq66YyxgR1cg==" }, "redux-localstorage": { "version": "1.0.0-rc5", @@ -83643,14 +83077,12 @@ "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==", - "requires": {} + "integrity": "sha512-TtrlaslxQBEMV0LYdf3s7VAbTxRPe1xaW10WNNGAzGA855/0RhkaHjKkQiRjHv5rvbRleVf7Nxr9fH+4uErfxQ==" }, "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==", - "requires": {} + "integrity": "sha512-JS0iW7uaciE/W3ADuzeN1HOnSjncQhHPXJ65nZNQzB0DF7mXVmbwQKI6cmCo/xKni7XRJT0JbWSpXFhEdPiBUA==" }, "slice-ansi": { "version": "3.0.0", @@ -84508,8 +83940,7 @@ "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==", - "requires": {} + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" } } }, @@ -84574,8 +84005,7 @@ "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==", - "requires": {} + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" } } }, @@ -86294,22 +85724,19 @@ "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==", - "requires": {} + "integrity": "sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ==" }, "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, - "requires": {} + "dev": true }, "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, - "requires": {} + "dev": true }, "use-latest": { "version": "1.2.0", @@ -86510,18 +85937,6 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" }, - "vue": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.0.5.tgz", - "integrity": "sha512-TfaprOmtsAfhQau7WsomXZ8d9op/dkQLNIq8qPV3A0Vxs6GR5E+c1rfJS1SDkXRQj+dFyfnec7+U0Be1huiScg==", - "optional": true, - "peer": true, - "requires": { - "@vue/compiler-dom": "3.0.5", - "@vue/runtime-dom": "3.0.5", - "@vue/shared": "3.0.5" - } - }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -87300,8 +86715,7 @@ "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, - "requires": {} + "dev": true }, "webpack-hot-middleware": { "version": "2.25.1", @@ -87560,8 +86974,7 @@ "ws": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", - "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", - "requires": {} + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==" }, "xdg-basedir": { "version": "4.0.0", diff --git a/src/package.json b/src/package.json index 17eca2c84..a27c830bb 100644 --- a/src/package.json +++ b/src/package.json @@ -98,6 +98,7 @@ "graphql-tools": "^7.0.2", "http-proxy-middleware": "^1.1.2", "isomorphic-unfetch": "^3.1.0", + "json-stable-stringify": "^1.0.2", "js-yaml": "^4.1.0", "jwks-rsa": "^2.0.5", "jwt-decode": "^3.1.2", diff --git a/src/services/report/ops-metrics.ts b/src/services/report/ops-metrics.ts index db13af229..30b2bec02 100644 --- a/src/services/report/ops-metrics.ts +++ b/src/services/report/ops-metrics.ts @@ -92,7 +92,7 @@ export class OpsMetrics { this.gActivity = new Gauge({ name: 'ops_metrics_activity_summary', help: 'Activity Summary', - labelNames: ['namespace', 'actor', 'activity', 'date'], + labelNames: ['namespace', 'actor', 'activity', 'result', 'date'], }); this.gProducts = new Gauge({ @@ -228,7 +228,7 @@ export class OpsMetrics { async function recurse(skip = 0) { const data = await batch.listAll( 'allActivities', - ['namespace', 'action', 'type', 'context', 'createdAt'], + ['namespace', 'action', 'result', 'type', 'context', 'createdAt'], undefined, skip, 50 @@ -249,11 +249,13 @@ export class OpsMetrics { if (Boolean(activity) == false) { logger.warn("Context didn't produce anything meaningful %j", data); } + const result = data.result; gActivity.inc( { actor, namespace: data.namespace, activity, + result, date: new Date(data.createdAt).toISOString(), }, 1 diff --git a/src/yarn.lock b/src/yarn.lock index 64983d6de..6090d0781 100644 --- a/src/yarn.lock +++ b/src/yarn.lock @@ -690,7 +690,7 @@ "resolved" "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz" "version" "7.17.7" -"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.1.0", "@babel/core@^7.11.5", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.14.3", "@babel/core@^7.15.0", "@babel/core@^7.4.0-0", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.8.0", "@babel/core@^7.9.6": +"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.14.3", "@babel/core@^7.15.0", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.8.0": "integrity" "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==" "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz" "version" "7.17.9" @@ -2128,7 +2128,7 @@ "core-js-pure" "^3.0.0" "regenerator-runtime" "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2", "@babel/runtime@>=7": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": "integrity" "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==" "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz" "version" "7.17.9" @@ -2654,7 +2654,7 @@ "@chakra-ui/checkbox" "1.5.1" "@chakra-ui/utils" "1.7.0" -"@chakra-ui/system@>=1.0.0", "@chakra-ui/system@1.6.4": +"@chakra-ui/system@1.6.4": "integrity" "sha512-sj93AHFIC8XaQnv3CgQt3Zyr7P3fYUbGMxHKxGDMcSplg+lwOoWVX3UhY3HKCezblsib1+HFhB37oFp7jHlJ4A==" "resolved" "https://registry.npmjs.org/@chakra-ui/system/-/system-1.6.4.tgz" "version" "1.6.4" @@ -2708,7 +2708,7 @@ "@types/tinycolor2" "1.4.2" "tinycolor2" "1.4.2" -"@chakra-ui/theme@>=1.0.0", "@chakra-ui/theme@1.8.4": +"@chakra-ui/theme@1.8.4": "integrity" "sha512-fmzl4gHpETwv7QvvWs1cLouXOTjkzsVWURZNzkDFWm/wOV8IQ2GsDFjP+dA5J2pvHIB6KovyXoN3BdTz9qdPqw==" "resolved" "https://registry.npmjs.org/@chakra-ui/theme/-/theme-1.8.4.tgz" "version" "1.8.4" @@ -2837,7 +2837,7 @@ "@emotion/weak-memoize" "^0.2.5" "stylis" "4.0.13" -"@emotion/core@^10.0.14", "@emotion/core@^10.0.27", "@emotion/core@^10.0.28", "@emotion/core@^10.0.35", "@emotion/core@^10.0.9", "@emotion/core@^10.1.1": +"@emotion/core@^10.0.14", "@emotion/core@^10.0.35", "@emotion/core@^10.0.9", "@emotion/core@^10.1.1": "integrity" "sha512-ZMLG6qpXR8x031NXD8HJqugy/AZSkAuMxxqB46pmAR7ze47MhNJ56cdoX243QPZdGctrdfo+s08yZTiwaUcRKA==" "resolved" "https://registry.npmjs.org/@emotion/core/-/core-10.1.1.tgz" "version" "10.1.1" @@ -2908,7 +2908,7 @@ "resolved" "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz" "version" "0.7.4" -"@emotion/react@^11.0.0", "@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.4.1", "@emotion/react@>=10.0.35": +"@emotion/react@^11.4.1": "integrity" "sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ==" "resolved" "https://registry.npmjs.org/@emotion/react/-/react-11.9.0.tgz" "version" "11.9.0" @@ -2995,7 +2995,7 @@ "@emotion/styled-base" "^10.3.0" "babel-plugin-emotion" "^10.0.27" -"@emotion/styled@^11.0.0", "@emotion/styled@^11.3.0": +"@emotion/styled@^11.3.0": "integrity" "sha512-OghEVAYBZMpEquHZwuelXcRjRJQOVayvbmNR0zr174NHdmMgrNkLC6TljKC5h9lZLkN5WGrdUcrKlOJ4phhoTQ==" "resolved" "https://registry.npmjs.org/@emotion/styled/-/styled-11.8.1.tgz" "version" "11.8.1" @@ -4994,11 +4994,6 @@ "schema-utils" "^3.0.0" "source-map" "^0.7.3" -"@popperjs/core@^2.0.0", "@popperjs/core@2.4.4": - "integrity" "sha512-1oO6+dN5kdIA3sKPZhRGJTfGVP4SWV6KqlMOwry4J3HfyD68sl/3KmG7DeYUzvN+RbhXDnv/D8vNNB8168tAMg==" - "resolved" "https://registry.npmjs.org/@popperjs/core/-/core-2.4.4.tgz" - "version" "2.4.4" - "@popperjs/core@^2.5.4": "integrity" "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==" "resolved" "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz" @@ -5014,6 +5009,11 @@ "resolved" "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz" "version" "2.11.5" +"@popperjs/core@2.4.4": + "integrity" "sha512-1oO6+dN5kdIA3sKPZhRGJTfGVP4SWV6KqlMOwry4J3HfyD68sl/3KmG7DeYUzvN+RbhXDnv/D8vNNB8168tAMg==" + "resolved" "https://registry.npmjs.org/@popperjs/core/-/core-2.4.4.tgz" + "version" "2.4.4" + "@preconstruct/next@^2.0.0": "integrity" "sha512-jpNffjgVKSilBCi3tNs2MEqqGdQBOo5n97B9OCfMDqO9SoiH7MyCmQ+tHCYQvY5gmD6Bf3Fas79N7Rzj6vJBsQ==" "resolved" "https://registry.npmjs.org/@preconstruct/next/-/next-2.0.0.tgz" @@ -5031,7 +5031,7 @@ "resolved" "https://registry.npmjs.org/@prisma/bar/-/bar-0.0.1.tgz" "version" "0.0.1" -"@prisma/cli@*", "@prisma/cli@2.12.1": +"@prisma/cli@2.12.1": "integrity" "sha512-obkwK95dEeifCdVehG0rS0BlPQGLsOtc9U1MgbrjNX3MnhXQdwROnvymfPB3DBlNyoLoHGklPgi9UlwBokNXcQ==" "resolved" "https://registry.npmjs.org/@prisma/cli/-/cli-2.12.1.tgz" "version" "2.12.1" @@ -6106,7 +6106,7 @@ "react-docgen-typescript" "^2.0.0" "tslib" "^2.0.0" -"@storybook/react@^6.4.21", "@storybook/react@6.4.21": +"@storybook/react@^6.4.21": "integrity" "sha512-7SJJnEbZ5THQBjor37shxnhXiFTB7g46U68I/PY56A5ZLb4TkorKStrniKgTcxG9xNqQjyxm0S6CICUp9gn8PQ==" "resolved" "https://registry.npmjs.org/@storybook/react/-/react-6.4.21.tgz" "version" "6.4.21" @@ -6297,7 +6297,7 @@ "resolved" "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.0.7.tgz" "version" "1.0.7" -"@testing-library/dom@^7.28.1", "@testing-library/dom@>=7.21.4": +"@testing-library/dom@^7.28.1": "integrity" "sha512-CtrJRiSYEfbtNGtEsd78mk1n1v2TUbeABlNIcOCJdDfkN5/JTOwQEbbQpoSRxGqzcWPgStMvJ4mNolSuBRv1NA==" "resolved" "https://registry.npmjs.org/@testing-library/dom/-/dom-7.29.4.tgz" "version" "7.29.4" @@ -6866,7 +6866,7 @@ "@types/node" "*" "form-data" "^3.0.0" -"@types/node@*", "@types/node@^14.0.1", "@types/node@^14.0.10", "@types/node@^14.14.41", "@types/node@>=12": +"@types/node@*", "@types/node@^14.0.1", "@types/node@^14.0.10", "@types/node@^14.14.41": "integrity" "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==" "resolved" "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz" "version" "14.18.12" @@ -6973,7 +6973,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.8.0", "@types/react@^16.8.0 || ^17.0.0", "@types/react@^17.0.0", "@types/react@^17.0.6", "@types/react@>=16": +"@types/react@*", "@types/react@^17.0.0", "@types/react@^17.0.6": "integrity" "sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g==" "resolved" "https://registry.npmjs.org/@types/react/-/react-17.0.44.tgz" "version" "17.0.44" @@ -7150,7 +7150,7 @@ "@types/source-list-map" "*" "source-map" "^0.7.3" -"@types/webpack@^4.41.26", "@types/webpack@^4.41.8", "@types/webpack@4.x || 5.x": +"@types/webpack@^4.41.26", "@types/webpack@^4.41.8": "integrity" "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==" "resolved" "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz" "version" "4.41.32" @@ -7247,7 +7247,7 @@ "eslint-scope" "^5.0.0" "eslint-utils" "^2.0.0" -"@typescript-eslint/parser@^4.0.0", "@typescript-eslint/parser@^4.13.0": +"@typescript-eslint/parser@^4.13.0": "integrity" "sha512-KO0J5SRF08pMXzq9+abyHnaGQgUJZ3Z3ax+pmqz9vl81JxmTTOUfQmq7/4awVfq09b6C4owNlOgOwp61pYRBSg==" "resolved" "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.13.0.tgz" "version" "4.13.0" @@ -7353,30 +7353,6 @@ "@vue/compiler-dom" "3.0.5" "@vue/shared" "3.0.5" -"@vue/reactivity@3.0.5": - "integrity" "sha512-3xodUE3sEIJgS7ntwUbopIpzzvi7vDAOjVamfb2l+v1FUg0jpd3gf62N2wggJw3fxBMr+QvyxpD+dBoxLsmAjw==" - "resolved" "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.0.5.tgz" - "version" "3.0.5" - dependencies: - "@vue/shared" "3.0.5" - -"@vue/runtime-core@3.0.5": - "integrity" "sha512-Cnyi2NqREwOLcTEsIi1DQX1hHtkVj4eGm4hBG7HhokS05DqpK4/80jG6PCCnCH9rIJDB2FqtaODX397210plXg==" - "resolved" "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.0.5.tgz" - "version" "3.0.5" - dependencies: - "@vue/reactivity" "3.0.5" - "@vue/shared" "3.0.5" - -"@vue/runtime-dom@3.0.5": - "integrity" "sha512-iilX1KySeIzHHtErT6Y44db1rhWK5tAI0CiJIPr+SJoZ2jbjoOSE6ff/jfIQakchbm1d6jq6VtRVnp5xYdOXKA==" - "resolved" "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.5.tgz" - "version" "3.0.5" - dependencies: - "@vue/runtime-core" "3.0.5" - "@vue/shared" "3.0.5" - "csstype" "^2.6.8" - "@vue/shared@3.0.5": "integrity" "sha512-gYsNoGkWejBxNO6SNRjOh/xKeZ0H0V+TFzaPzODfBjkAIb0aQgBuixC1brandC/CDJy1wYPwSoYrXpvul7m6yw==" "resolved" "https://registry.npmjs.org/@vue/shared/-/shared-3.0.5.tgz" @@ -7622,16 +7598,16 @@ "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz" "version" "7.2.0" -"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^7.0.0", "acorn@^7.1.1", "acorn@^7.4.0", "acorn@^7.4.1": - "integrity" "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - "resolved" "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" - "version" "7.4.1" - "acorn@^6.4.1": "integrity" "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" "resolved" "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" "version" "6.4.2" +"acorn@^7.0.0", "acorn@^7.1.1", "acorn@^7.4.0", "acorn@^7.4.1": + "integrity" "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" + "version" "7.4.1" + "acorn@^8.2.4": "integrity" "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz" @@ -7706,7 +7682,7 @@ "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" "version" "3.5.2" -"ajv@^6.1.0", "ajv@^6.10.0", "ajv@^6.10.2", "ajv@^6.12.2", "ajv@^6.12.4", "ajv@^6.12.5", "ajv@^6.12.6", "ajv@^6.9.1", "ajv@>=5.0.0": +"ajv@^6.1.0", "ajv@^6.10.0", "ajv@^6.10.2", "ajv@^6.12.2", "ajv@^6.12.4", "ajv@^6.12.5", "ajv@^6.12.6": "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" "version" "6.12.6" @@ -9860,7 +9836,7 @@ "graphql-language-service-interface" "^2.4.3" "graphql-language-service-parser" "^1.6.5" -"codemirror@^5.18.2", "codemirror@^5.26.0", "codemirror@^5.47.0", "codemirror@^5.54.0", "codemirror@^5.58.1", "codemirror@^5.58.3", "codemirror@5.x": +"codemirror@^5.18.2", "codemirror@^5.47.0", "codemirror@^5.58.1", "codemirror@^5.58.3": "integrity" "sha512-d0SSW/PCCD4LoSCBPdnP0BzmZB1v3emomCUtVlIWgZHJ06yVeBOvBtOH7vYz707pfAvEeWbO9aP6akh8vl1V3w==" "resolved" "https://registry.npmjs.org/codemirror/-/codemirror-5.59.1.tgz" "version" "5.59.1" @@ -10349,7 +10325,7 @@ "path-type" "^4.0.0" "yaml" "^1.7.2" -"cosmiconfig@^7.0.0", "cosmiconfig@>=6", "cosmiconfig@7.0.1": +"cosmiconfig@^7.0.0", "cosmiconfig@7.0.1": "integrity" "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==" "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz" "version" "7.0.1" @@ -10771,11 +10747,6 @@ "resolved" "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz" "version" "2.6.20" -"csstype@^2.6.8": - "integrity" "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" - "resolved" "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz" - "version" "2.6.21" - "csstype@^3.0.2", "csstype@^3.0.6": "integrity" "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==" "resolved" "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz" @@ -10913,7 +10884,7 @@ "resolved" "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz" "version" "1.30.1" -"date-fns@^2.12.0", "date-fns@^2.16.1", "date-fns@^2.19.0", "date-fns@^2.21.3": +"date-fns@^2.16.1", "date-fns@^2.19.0", "date-fns@^2.21.3": "integrity" "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==" "resolved" "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz" "version" "2.28.0" @@ -11671,7 +11642,7 @@ "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" "version" "1.0.2" -"encoding@^0.1.0", "encoding@^0.1.11": +"encoding@^0.1.11": "integrity" "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==" "resolved" "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" "version" "0.1.13" @@ -12010,7 +11981,7 @@ "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" "version" "2.1.0" -"eslint@*", "eslint@^3 || ^4 || ^5 || ^6 || ^7", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", "eslint@^5.0.0 || ^6.0.0 || ^7.0.0", "eslint@^7.18.0", "eslint@>= 6", "eslint@>=5", "eslint@>=7.0.0": +"eslint@^7.18.0": "integrity" "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==" "resolved" "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz" "version" "7.18.0" @@ -12322,7 +12293,7 @@ "resolved" "https://registry.npmjs.org/express-unless/-/express-unless-0.3.1.tgz" "version" "0.3.1" -"express@^4.16.3", "express@^4.17.1", "express@>=4.0.0": +"express@^4.16.3", "express@^4.17.1": "integrity" "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==" "resolved" "https://registry.npmjs.org/express/-/express-4.17.1.tgz" "version" "4.17.1" @@ -12602,7 +12573,7 @@ dependencies: "flat-cache" "^3.0.4" -"file-loader@*", "file-loader@^6.2.0": +"file-loader@^6.2.0": "integrity" "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==" "resolved" "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" "version" "6.2.0" @@ -12946,7 +12917,7 @@ dependencies: "map-cache" "^0.2.2" -"framer-motion@^4.1.17", "framer-motion@3.x || 4.x": +"framer-motion@^4.1.17": "integrity" "sha512-thx1wvKzblzbs0XaK2X0G1JuwIdARcoNOW7VVwjO8BUltzXPyONGAElLu6CiCScsOQRI7FIk/45YTFtJw5Yozw==" "resolved" "https://registry.npmjs.org/framer-motion/-/framer-motion-4.1.17.tgz" "version" "4.1.17" @@ -13309,7 +13280,7 @@ "resolved" "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" "version" "0.4.1" -"glob@*", "glob@^7.0.0", "glob@^7.0.5", "glob@^7.1.1", "glob@^7.1.2", "glob@^7.1.3", "glob@^7.1.4", "glob@^7.1.6": +"glob@^7.0.0", "glob@^7.0.5", "glob@^7.1.1", "glob@^7.1.2", "glob@^7.1.3", "glob@^7.1.4", "glob@^7.1.6": "integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==" "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" "version" "7.2.0" @@ -13664,11 +13635,6 @@ "resolved" "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.7.0.tgz" "version" "5.7.0" -"graphql@^0.10.5 || ^0.11.3 || ^0.12.0 || ^0.13.0 || ^14.0.0", "graphql@^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0", "graphql@^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", "graphql@^0.11.3 || ^0.12.3 || ^0.13.0 || ^14.0.0 || ^15.0.0", "graphql@^0.12.0 || ^0.13.0 || ^14.0.0", "graphql@^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0", "graphql@^0.13.0 || ^14.0.0 || ^15.0.0", "graphql@^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0", "graphql@^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", "graphql@^14.0.0 || ^15.0.0", "graphql@^14.0.0 || ^15.0.0 || ^16.0.0", "graphql@^14.2.1 || ^15.0.0", "graphql@^14.2.1 || ^15.0.0 || ^16.0.0", "graphql@^15.0.0", "graphql@^15.0.0 || ^16.0.0", "graphql@^15.3.0", "graphql@^15.4.0", "graphql@^15.4.0 || ^16.0.0", "graphql@^15.5.0", "graphql@^15.5.0 || ^16.0.0", "graphql@^15.7.2 || ^16.0.0", "graphql@>=0.10.0", "graphql@>=0.11 <=15", "graphql@>=0.11 <=16", "graphql@>=0.8.0", "graphql@0.13.1 - 15", "graphql@14 - 15", "graphql@14.x || 15.x": - "integrity" "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==" - "resolved" "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz" - "version" "15.8.0" - "graphql@^14.5.8": "integrity" "sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==" "resolved" "https://registry.npmjs.org/graphql/-/graphql-14.7.0.tgz" @@ -13676,6 +13642,11 @@ dependencies: "iterall" "^1.2.2" +"graphql@^15.3.0", "graphql@^15.4.0", "graphql@^15.5.0": + "integrity" "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==" + "resolved" "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz" + "version" "15.8.0" + "gray-percentage@^2.0.0": "integrity" "sha1-tyonTRsTeRBKAFC2OyB9xT/lb5k= sha512-T0i4bwJoXbweuBM7bJwil9iHVAwXxmS9IFsEy27cXvRYxHwR2YVSBSXBjJw4EDKUvLpfjANeT5PrvTuAH1XnTw==" "resolved" "https://registry.npmjs.org/gray-percentage/-/gray-percentage-2.0.0.tgz" @@ -14289,7 +14260,7 @@ "resolved" "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz" "version" "3.0.6" -"immutable@^3.8.1 || ^4.0.0-rc.1", "immutable@^4.0.0-rc.12", "immutable@^4.0.0-rc.9", "immutable@>=3.6.2", "immutable@>=3.8.1", "immutable@>=3.8.1 || >4.0.0-rc": +"immutable@^4.0.0-rc.12", "immutable@^4.0.0-rc.9": "integrity" "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==" "resolved" "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz" "version" "4.0.0" @@ -15481,7 +15452,7 @@ "jest-regex-util" "^27.5.1" "jest-snapshot" "^27.5.1" -"jest-resolve@*", "jest-resolve@^27.5.1": +"jest-resolve@^27.5.1": "integrity" "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==" "resolved" "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz" "version" "27.5.1" @@ -15825,12 +15796,12 @@ "resolved" "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" "version" "1.0.1" -"json-stable-stringify@^1.0.1": - "integrity" "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= sha512-i/J297TW6xyj7sDFa7AmBPkQvLIxWr2kKPWI26tXydnZrzVAocNqn5DMNT1Mzk0vit1V5UkRM7C1KdVNp7Lmcg==" - "resolved" "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" - "version" "1.0.1" +"json-stable-stringify@^1.0.1", "json-stable-stringify@^1.0.2": + "integrity" "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==" + "resolved" "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz" + "version" "1.0.2" dependencies: - "jsonify" "~0.0.0" + "jsonify" "^0.0.1" "json-to-pretty-yaml@^1.2.2": "integrity" "sha1-9M0L0KXo/h3yWq9boRiwmf2ZLVs= sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==" @@ -15875,10 +15846,10 @@ optionalDependencies: "graceful-fs" "^4.1.6" -"jsonify@~0.0.0": - "integrity" "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA==" - "resolved" "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" - "version" "0.0.0" +"jsonify@^0.0.1": + "integrity" "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==" + "resolved" "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz" + "version" "0.0.1" "jsonwebtoken@^8.1.0", "jsonwebtoken@^8.5.1": "integrity" "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==" @@ -16263,7 +16234,7 @@ "date-fns" "^1.27.2" "figures" "^2.0.0" -"listr@^0.14.2", "listr@^0.14.3": +"listr@^0.14.3": "integrity" "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==" "resolved" "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz" "version" "0.14.3" @@ -17452,7 +17423,7 @@ "resolved" "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz" "version" "1.0.2" -"mongoose@*", "mongoose@^5.11.11", "mongoose@^5.11.13", "mongoose@^5.12.11": +"mongoose@^5.11.11", "mongoose@^5.11.13", "mongoose@^5.12.11": "integrity" "sha512-j+BlQjjxgZg0iWn42kLeZTB91OejcxWpY2Z50bsZTiKJ7HHcEtcY21Godw496GMkBqJMTzmW7G/kZ04mW+Cb7Q==" "resolved" "https://registry.npmjs.org/mongoose/-/mongoose-5.13.14.tgz" "version" "5.13.14" @@ -17637,7 +17608,7 @@ "resolved" "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz" "version" "1.0.0" -"next@^9.5.3", "next@^9.5.5", "next@9.5.5": +"next@^9.5.3", "next@^9.5.5": "integrity" "sha512-KF4MIdTYeI6YIGODNw27w9HGzCll4CXbUpkP6MNvyoHlpsunx8ybkQHm/hYa7lWMozmsn58LwaXJOhe4bSrI0g==" "resolved" "https://registry.npmjs.org/next/-/next-9.5.5.tgz" "version" "9.5.5" @@ -18011,7 +17982,7 @@ "resolved" "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz" "version" "2.2.0" -"nyc@^15.1.0", "nyc@>=15": +"nyc@^15.1.0": "integrity" "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==" "resolved" "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz" "version" "15.1.0" @@ -18790,11 +18761,6 @@ "resolved" "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz" "version" "2.5.0" -"pg-connection-string@0.1.3": - "integrity" "sha512-i0NV/CrSkFTaiOQs9AGy3tq0dkSjtTd4d7DfsjeDVZAA4aIHInwfFEmriNYGGJUfZ5x6IAC/QddoUpUJjQAi0w==" - "resolved" "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz" - "version" "0.1.3" - "pg-connection-string@2.1.0": "integrity" "sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg==" "resolved" "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.1.0.tgz" @@ -18815,16 +18781,6 @@ "resolved" "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz" "version" "1.0.1" -"pg-packet-stream@^1.1.0": - "integrity" "sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg==" - "resolved" "https://registry.npmjs.org/pg-packet-stream/-/pg-packet-stream-1.1.0.tgz" - "version" "1.1.0" - -"pg-pool@^2.0.10": - "integrity" "sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg==" - "resolved" "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.10.tgz" - "version" "2.0.10" - "pg-pool@^3.5.1": "integrity" "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==" "resolved" "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz" @@ -18846,21 +18802,7 @@ "postgres-date" "~1.0.4" "postgres-interval" "^1.1.0" -"pg@^7.18.2", "pg@>5.0": - "integrity" "sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA==" - "resolved" "https://registry.npmjs.org/pg/-/pg-7.18.2.tgz" - "version" "7.18.2" - dependencies: - "buffer-writer" "2.0.0" - "packet-reader" "1.0.0" - "pg-connection-string" "0.1.3" - "pg-packet-stream" "^1.1.0" - "pg-pool" "^2.0.10" - "pg-types" "^2.1.0" - "pgpass" "1.x" - "semver" "4.3.2" - -"pg@^8.3.0", "pg@^8.5.1", "pg@^8.6.0", "pg@>=8.0": +"pg@^8.5.1", "pg@^8.6.0": "integrity" "sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw==" "resolved" "https://registry.npmjs.org/pg/-/pg-8.7.3.tgz" "version" "8.7.3" @@ -19192,7 +19134,7 @@ "source-map" "^0.6.1" "supports-color" "^5.4.0" -"postcss@^7", "postcss@^7.0.0 || ^8.0.1", "postcss@^7.0.14", "postcss@^7.0.18", "postcss@^7.0.26", "postcss@^7.0.32", "postcss@^7.0.35", "postcss@^7.0.36", "postcss@^7.0.5", "postcss@^7.0.6", "postcss@^8.2.14": +"postcss@^7", "postcss@^7.0.14", "postcss@^7.0.18", "postcss@^7.0.26", "postcss@^7.0.32", "postcss@^7.0.35", "postcss@^7.0.36", "postcss@^7.0.5", "postcss@^7.0.6": "integrity" "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==" "resolved" "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz" "version" "7.0.39" @@ -19200,7 +19142,7 @@ "picocolors" "^0.2.1" "source-map" "^0.6.1" -"postcss@^8.1.0", "postcss@^8.2.15": +"postcss@^8.2.1": "integrity" "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==" "resolved" "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz" "version" "8.4.12" @@ -19209,7 +19151,7 @@ "picocolors" "^1.0.0" "source-map-js" "^1.0.2" -"postcss@^8.2.1": +"postcss@^8.2.15": "integrity" "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==" "resolved" "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz" "version" "8.4.12" @@ -19320,7 +19262,7 @@ "resolved" "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz" "version" "1.1.2" -"prisma@>=2.15.0", "prisma@2.16.1": +"prisma@2.16.1": "integrity" "sha512-TniTihl4xwWY7Hy+1UUpZ6jxHyriRDUW4i7TChZNBZM88IG8kvR5cSX+/JY/lzWGMUR4ZDBzoIuNcdPx/7eWag==" "resolved" "https://registry.npmjs.org/prisma/-/prisma-2.16.1.tgz" "version" "2.16.1" @@ -19420,7 +19362,7 @@ "kleur" "^3.0.3" "sisteransi" "^1.0.5" -"prop-types@^15.0.0", "prop-types@^15.5.10", "prop-types@^15.5.4", "prop-types@^15.5.7", "prop-types@^15.5.8", "prop-types@^15.6.0", "prop-types@^15.6.1", "prop-types@^15.6.2", "prop-types@^15.7.2", "prop-types@^15.8.1", "prop-types@>=15.5.0": +"prop-types@^15.0.0", "prop-types@^15.5.10", "prop-types@^15.5.4", "prop-types@^15.5.7", "prop-types@^15.5.8", "prop-types@^15.6.0", "prop-types@^15.6.1", "prop-types@^15.6.2", "prop-types@^15.7.2": "integrity" "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==" "resolved" "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" "version" "15.8.1" @@ -19777,16 +19719,7 @@ "node-dir" "^0.1.10" "strip-indent" "^3.0.0" -"react-dom@*", "react-dom@^0.14.0 || ^15.0.0 || ^16 || ^17", "react-dom@^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1", "react-dom@^15.0.0 || ^16.0.0 || ^17.0.0", "react-dom@^16.3.0", "react-dom@^16.6.0", "react-dom@^16.6.0 || ^17.0.0", "react-dom@^16.6.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0", "react-dom@^16.8.0 || 17.x", "react-dom@^16.9.0", "react-dom@^17.0.1", "react-dom@^17.0.2", "react-dom@>= 16.3.0", "react-dom@>=16.0.0", "react-dom@>=16.6.0", "react-dom@>=16.8", "react-dom@>=16.8 || ^17.0.0", "react-dom@>=16.8.0", "react-dom@>=16.8.6": - "integrity" "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==" - "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz" - "version" "17.0.2" - dependencies: - "loose-envify" "^1.1.0" - "object-assign" "^4.1.1" - "scheduler" "^0.20.2" - -"react-dom@^0.14.0 || ^15.0.0 || ^16.0.0", "react-dom@^15.3.0 || ^16.0.0-alpha", "react-dom@^15.6.0 || ^16.0.0", "react-dom@^16.13.1", "react-dom@>=15.0.0", "react-dom@>=15.5 <16": +"react-dom@^16.13.1": "integrity" "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==" "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz" "version" "16.14.0" @@ -19806,15 +19739,14 @@ "prop-types" "^15.6.2" "scheduler" "^0.19.1" -"react-dom@^16.7.0": - "integrity" "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==" - "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz" - "version" "16.14.0" +"react-dom@^17.0.1", "react-dom@^17.0.2": + "integrity" "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==" + "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz" + "version" "17.0.2" dependencies: "loose-envify" "^1.1.0" "object-assign" "^4.1.1" - "prop-types" "^15.6.2" - "scheduler" "^0.19.1" + "scheduler" "^0.20.2" "react-draggable@^4.4.3": "integrity" "sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==" @@ -20044,7 +19976,7 @@ "react-is" "^16.6.0" "react-lifecycles-compat" "^3.0.0" -"react-refresh@^0.11.0", "react-refresh@>=0.10.0 <1.0.0": +"react-refresh@^0.11.0": "integrity" "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" "resolved" "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz" "version" "0.11.0" @@ -20294,7 +20226,16 @@ "@babel/runtime" "^7.0.0" "memoize-one" ">=3.1.1 <6" -"react@*", "react@^0.13.0 || ^0.14.0 || ^15.0.0 || ^16.0.0", "react@^0.14.0 || ^15.0.0 || ^16 || ^17", "react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "react@^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1", "react@^14.0.0 || ^15.0.0 || ^16.0.0", "react@^15.0.0 || ^16.0.0", "react@^15.0.0 || ^16.0.0 || ^17.0.0", "react@^15.0.0 || ^16.0.0 || ^17.0.0|| ^18.0.0", "react@^15.3.0 || ^16.0.0 || ^17.0.0", "react@^16.0 || ^17.0", "react@^16.11.0 || ^17.0.0", "react@^16.13.1 || ^17.0.0", "react@^16.3.0", "react@^16.3.0 || ^17.0.0", "react@^16.6.0", "react@^16.6.0 || ^17.0.0", "react@^16.6.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0", "react@^16.8.0 || ^17", "react@^16.8.0 || ^17.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || 17.x", "react@^16.8.4 || ^17.0.0", "react@^16.9.0", "react@^17.0.1", "react@^17.0.2", "react@>= 0.14.0", "react@>= 16.3.0", "react@>=15", "react@>=15.0.0", "react@>=16", "react@>=16.0.0", "react@>=16.12.0", "react@>=16.13.1", "react@>=16.3.0", "react@>=16.6.0", "react@>=16.8", "react@>=16.8 || ^17.0.0", "react@>=16.8.0", "react@>=16.8.6", "react@15.x.x || 16.x.x", "react@17.0.2": +"react@^16.14.0": + "integrity" "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==" + "resolved" "https://registry.npmjs.org/react/-/react-16.14.0.tgz" + "version" "16.14.0" + dependencies: + "loose-envify" "^1.1.0" + "object-assign" "^4.1.1" + "prop-types" "^15.6.2" + +"react@^17.0.1", "react@^17.0.2": "integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==" "resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz" "version" "17.0.2" @@ -20302,7 +20243,7 @@ "loose-envify" "^1.1.0" "object-assign" "^4.1.1" -"react@^0.14.0 || ^15.0.0 || ^16.0.0", "react@^0.14.0 || ^15.0.0-0 || ^16.0.0-0", "react@^0.14.9 || ^15.3.0 || ^16.0.0-rc || ^16.0", "react@^15.3.0 || ^16.0.0-alpha", "react@^15.6.0 || ^16.0.0", "react@^16.14.0", "react@>=15.5 <16", "react@16.13.1": +"react@16.13.1": "integrity" "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==" "resolved" "https://registry.npmjs.org/react/-/react-16.13.1.tgz" "version" "16.13.1" @@ -20311,24 +20252,6 @@ "object-assign" "^4.1.1" "prop-types" "^15.6.2" -"react@^16.13.1", "react@>=15.5 <=16.x": - "integrity" "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==" - "resolved" "https://registry.npmjs.org/react/-/react-16.14.0.tgz" - "version" "16.14.0" - dependencies: - "loose-envify" "^1.1.0" - "object-assign" "^4.1.1" - "prop-types" "^15.6.2" - -"react@^16.7.0": - "integrity" "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==" - "resolved" "https://registry.npmjs.org/react/-/react-16.14.0.tgz" - "version" "16.14.0" - dependencies: - "loose-envify" "^1.1.0" - "object-assign" "^4.1.1" - "prop-types" "^15.6.2" - "read-pkg-up@^1.0.1": "integrity" "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==" "resolved" "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz" @@ -20667,7 +20590,7 @@ "resolved" "https://registry.npmjs.org/redux-saga/-/redux-saga-0.16.2.tgz" "version" "0.16.2" -"redux@^2.0.0 || ^3.0.0 || ^4.0.0-0", "redux@^3.7.2": +"redux@^3.7.2": "integrity" "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==" "resolved" "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz" "version" "3.7.2" @@ -21441,11 +21364,6 @@ "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" "version" "5.7.1" -"semver@4.3.2": - "integrity" "sha512-VyFUffiBx8hABJ9HYSTXLRwyZtdDHMzMtFmID1aiNAD2BZppBmJm0Hqw3p2jkgxP9BNt1pQ9RnC49P0EcXf6cA==" - "resolved" "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz" - "version" "4.3.2" - "semver@7.0.0": "integrity" "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" "resolved" "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" @@ -21710,7 +21628,7 @@ "resolved" "https://registry.npmjs.org/slate-react-placeholder/-/slate-react-placeholder-0.2.9.tgz" "version" "0.2.9" -"slate-react@^0.22.10", "slate-react@>=0.19.3", "slate-react@>=0.22.0": +"slate-react@^0.22.10": "integrity" "sha512-B2Ms1u/REbdd8yKkOItKgrw/tX8klgz5l5x6PP86+oh/yqmB6EHe0QyrYlQ9fc3WBlJUVTOL+nyAP1KmlKj2/w==" "resolved" "https://registry.npmjs.org/slate-react/-/slate-react-0.22.10.tgz" "version" "0.22.10" @@ -21732,7 +21650,7 @@ "tiny-invariant" "^1.0.1" "tiny-warning" "^0.0.3" -"slate@^0.47.9", "slate@>=0.32.0 <0.50.0", "slate@>=0.42.2", "slate@>=0.46.0 <0.50.0", "slate@>=0.47.0": +"slate@^0.47.9": "integrity" "sha512-EK4O6b7lGt+g5H9PGw9O5KCM4RrOvOgE9mPi3rzQ0zDRlgAb2ga4TdpS6XNQbrsJWsc8I1fjaSsUeCqCUhhi9A==" "resolved" "https://registry.npmjs.org/slate/-/slate-0.47.9.tgz" "version" "0.47.9" @@ -22394,7 +22312,7 @@ "hey-listen" "^1.0.8" "tslib" "^2.1.0" -"styled-components@^4.0.0", "styled-components@>= 2": +"styled-components@^4.0.0": "integrity" "sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g==" "resolved" "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz" "version" "4.4.1" @@ -22437,7 +22355,12 @@ "resolved" "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz" "version" "0.0.10" -"stylis@^3.5.0", "stylis@3.5.4": +"stylis@^3.5.0": + "integrity" "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" + "resolved" "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz" + "version" "3.5.4" + +"stylis@3.5.4": "integrity" "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" "resolved" "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz" "version" "3.5.4" @@ -22458,7 +22381,7 @@ "symbol-observable" "^1.0.4" "ws" "^5.2.0 || ^6.0.0 || ^7.0.0" -"subscriptions-transport-ws@^0.9.0", "subscriptions-transport-ws@^0.9.18", "subscriptions-transport-ws@^0.9.19", "subscriptions-transport-ws@^0.9.5": +"subscriptions-transport-ws@^0.9.18", "subscriptions-transport-ws@^0.9.19", "subscriptions-transport-ws@^0.9.5": "integrity" "sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw==" "resolved" "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz" "version" "0.9.19" @@ -23124,7 +23047,7 @@ "ts-node" "^9.0.0" "tsconfig" "^7.0.0" -"ts-node@^9", "ts-node@^9.0.0", "ts-node@>=9.0.0", "ts-node@9.1.1": +"ts-node@^9", "ts-node@^9.0.0", "ts-node@9.1.1": "integrity" "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==" "resolved" "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz" "version" "9.1.1" @@ -23289,7 +23212,7 @@ "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" "version" "0.20.2" -"type-fest@^0.21.3", "type-fest@>=0.17.0 <3.0.0": +"type-fest@^0.21.3": "integrity" "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" "version" "0.21.3" @@ -23349,7 +23272,7 @@ "resolved" "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" "version" "0.0.6" -"typescript@*", "typescript@^4.1.2", "typescript@^4.1.3", "typescript@>= 2.7", "typescript@>= 3.x", "typescript@>= 4.3.x", "typescript@>=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev", "typescript@>=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev", "typescript@>=2.7", "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", "typescript@4.2.4": +"typescript@^4.1.2", "typescript@^4.1.3", "typescript@4.2.4": "integrity" "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==" "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz" "version" "4.2.4" @@ -23940,15 +23863,6 @@ "resolved" "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz" "version" "3.16.0" -"vue@^2.6.10 || ^3.0.0", "vue@3.0.5": - "integrity" "sha512-TfaprOmtsAfhQau7WsomXZ8d9op/dkQLNIq8qPV3A0Vxs6GR5E+c1rfJS1SDkXRQj+dFyfnec7+U0Be1huiScg==" - "resolved" "https://registry.npmjs.org/vue/-/vue-3.0.5.tgz" - "version" "3.0.5" - dependencies: - "@vue/compiler-dom" "3.0.5" - "@vue/runtime-dom" "3.0.5" - "@vue/shared" "3.0.5" - "w3c-hr-time@^1.0.2": "integrity" "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==" "resolved" "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz" @@ -24093,7 +24007,7 @@ "resolved" "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz" "version" "1.2.1" -"webpack-hot-middleware@^2.25.0", "webpack-hot-middleware@^2.25.1", "webpack-hot-middleware@2.x": +"webpack-hot-middleware@^2.25.0", "webpack-hot-middleware@^2.25.1": "integrity" "sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw==" "resolved" "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz" "version" "2.25.1" @@ -24126,10 +24040,10 @@ dependencies: "debug" "^3.0.0" -"webpack@*", "webpack@^2.0.0 || ^3.0.0 || ^4.0.0", "webpack@^4 || ^5", "webpack@^4.0.0", "webpack@^4.0.0 || ^5.0.0", "webpack@^4.27.0 || ^5.0.0", "webpack@^4.36.0 || ^5.0.0", "webpack@>= 4", "webpack@>=2", "webpack@>=4.43.0 <6.0.0", "webpack@4", "webpack@4.46.0": - "integrity" "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==" - "resolved" "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz" - "version" "4.46.0" +"webpack@4.44.1": + "integrity" "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==" + "resolved" "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz" + "version" "4.44.1" dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -24139,7 +24053,7 @@ "ajv" "^6.10.2" "ajv-keywords" "^3.4.1" "chrome-trace-event" "^1.0.2" - "enhanced-resolve" "^4.5.0" + "enhanced-resolve" "^4.3.0" "eslint-scope" "^4.0.3" "json-parse-better-errors" "^1.0.2" "loader-runner" "^2.4.0" @@ -24155,10 +24069,10 @@ "watchpack" "^1.7.4" "webpack-sources" "^1.4.1" -"webpack@4.44.1": - "integrity" "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==" - "resolved" "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz" - "version" "4.44.1" +"webpack@4", "webpack@4.46.0": + "integrity" "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==" + "resolved" "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz" + "version" "4.46.0" dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -24168,7 +24082,7 @@ "ajv" "^6.10.2" "ajv-keywords" "^3.4.1" "chrome-trace-event" "^1.0.2" - "enhanced-resolve" "^4.3.0" + "enhanced-resolve" "^4.5.0" "eslint-scope" "^4.0.3" "json-parse-better-errors" "^1.0.2" "loader-runner" "^2.4.0" @@ -24375,7 +24289,7 @@ "signal-exit" "^3.0.2" "typedarray-to-buffer" "^3.1.5" -"ws@*", "ws@^5.2.0 || ^6.0.0 || ^7.0.0", "ws@7.4.5": +"ws@^5.2.0 || ^6.0.0 || ^7.0.0", "ws@7.4.5": "integrity" "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==" "resolved" "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz" "version" "7.4.5" From 7ca3b86882df06c2cb27dce6ecd9c9766fd09431 Mon Sep 17 00:00:00 2001 From: ike thecoder Date: Mon, 13 Mar 2023 23:01:00 -0700 Subject: [PATCH 4/6] increase max records for query resources (#781) --- src/logger.ts | 6 ++- .../uma2/resource-registration-service.ts | 9 +++- src/test/integrated/keycloak/client.ts | 47 +++++++++++++++---- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/logger.ts b/src/logger.ts index bd37089bc..676795fac 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -14,12 +14,16 @@ export function Logger(category: string) { level: process.env.LOG_LEVEL || 'debug', format: winston.format.combine( enumerateErrorFormat(), + winston.format.timestamp({ + format: 'YYYY-MM-DD HH:mm:ss', + }), process.env.NODE_ENV === 'production' ? winston.format.uncolorize() : winston.format.colorize(), winston.format.splat(), winston.format.printf( - ({ level, message, stack }) => `${level}: [${category}] ${message}` + ({ timestamp, level, message, stack }) => + `${timestamp} ${level}: [${category}] ${message}` ) ), transports: [ diff --git a/src/services/uma2/resource-registration-service.ts b/src/services/uma2/resource-registration-service.ts index 115e04ebb..4fdb76b6a 100644 --- a/src/services/uma2/resource-registration-service.ts +++ b/src/services/uma2/resource-registration-service.ts @@ -12,6 +12,8 @@ export interface ResourceSetQuery { owner?: string; type?: string; scope?: string; + first?: number; + max?: number; } export interface ResourceScope { @@ -100,7 +102,12 @@ export class UMAResourceRegistrationService { } public async listResources(query: ResourceSetQuery): Promise { - const requestQuery = querystring.stringify(query as any); + // TODO: Really should do graceful paging, but will be awhile before + // there are 1000+ namespaces! + const requestQuery = querystring.stringify({ + ...{ first: 0, max: 1000 }, + ...query, + } as any); const url = `${this.resourceRegistrationEndpoint}?${requestQuery}`; logger.debug('[listResources] %s', url); const result = await fetch(url, { diff --git a/src/test/integrated/keycloak/client.ts b/src/test/integrated/keycloak/client.ts index dc456f653..22852ed26 100644 --- a/src/test/integrated/keycloak/client.ts +++ b/src/test/integrated/keycloak/client.ts @@ -9,6 +9,7 @@ npm run ts-build export CID="" export CSC="" export ISSUER="" +export TOK="" npm run ts-watch node dist/test/integrated/keycloak/client.js @@ -17,14 +18,44 @@ node dist/test/integrated/keycloak/client.js import { o } from '../util'; import { KeycloakClientService } from '../../../services/keycloak'; +import { UMAResourceRegistrationService } from '../../../services/uma2'; (async () => { - const kc = new KeycloakClientService(process.env.ISSUER); - - await kc.login(process.env.CID, process.env.CSC); - - // await kc.regenerateSecret('6af832cb-6178-438f-a4fc-8c5e1d14d5d2'); - // console.log(await kc.listMembers('660cadef-9233-4532-ba45-5393beaddea4')); - const res = await kc.list('42da4f15'); - o(res); + if (false) { + const kc = new KeycloakClientService(process.env.ISSUER); + + await kc.login(process.env.CID, process.env.CSC); + + await kc.regenerateSecret('6af832cb-6178-438f-a4fc-8c5e1d14d5d2'); + const res = await kc.list('42da4f15'); + o(res); + } + + const resourceRegistrationEndpoint = + process.env.ISSUER + '/authz/protection/resource_set'; + const accessToken = process.env.TOK; + const clientUuid = '250398da-a174-404d-ae18-6a6ebc9de06d'; + + const kcprotectApi = new UMAResourceRegistrationService( + resourceRegistrationEndpoint, + accessToken + ); + const resOwnerResourceIds = await kcprotectApi.listResources({ + owner: clientUuid, + type: 'namespace', + }); + + const namespaces = await kcprotectApi.listResourcesByIdList( + resOwnerResourceIds + ); + + const matched = namespaces + .filter((ns) => ns.name == 'testelson') + .map((ns) => ({ + id: ns.id, + name: ns.name, + scopes: ns.resource_scopes, + })); + + o(matched); })(); From 581da5460efcd09f7bd007bd8632202e5525eb4e Mon Sep 17 00:00:00 2001 From: nirajCITZ <94716060+nirajCITZ@users.noreply.github.com> Date: Fri, 31 Mar 2023 13:27:42 -0700 Subject: [PATCH 5/6] Added following scenarios: (#791) 1)Cypress test to verify free (Public) access 2)Cypress Test - Delete Service account 3)Cypress Test - Verify rate_limiting_902 and rate_limiting plugins by applying them to different level 4)Cypress Test for Org Admin Co-authored-by: Niraj Patel --- e2e/cypress/fixtures/apiowner.json | 32 +++++ e2e/cypress/fixtures/developer.json | 10 ++ .../manage-control-config-setting.json | 3 +- .../manage-control/kong-plugin-config.json | 7 +- e2e/cypress/fixtures/rate-limiting-902.yml | 8 ++ e2e/cypress/pageObjects/apiDirectory.ts | 5 +- e2e/cypress/pageObjects/consumers.ts | 2 - e2e/cypress/pageObjects/products.ts | 10 +- e2e/cypress/pageObjects/serviceAccounts.ts | 15 +++ e2e/cypress/support/auth-commands.ts | 25 ++-- e2e/cypress/support/global.d.ts | 4 +- .../07-kong-public-auth.ts | 110 ++++++++++++++++++ .../03-delete-service-acc.ts | 58 +++++++++ .../01-client-cred-team-access.ts | 2 - 14 files changed, 265 insertions(+), 26 deletions(-) create mode 100644 e2e/cypress/fixtures/rate-limiting-902.yml create mode 100644 e2e/cypress/tests/09-update-product-env/07-kong-public-auth.ts create mode 100644 e2e/cypress/tests/10-clear-resources/03-delete-service-acc.ts diff --git a/e2e/cypress/fixtures/apiowner.json b/e2e/cypress/fixtures/apiowner.json index 1d4d97b95..c16eb318e 100644 --- a/e2e/cypress/fixtures/apiowner.json +++ b/e2e/cypress/fixtures/apiowner.json @@ -188,6 +188,38 @@ } } }, + "clientIdSecret_publicProfile": { + "product": { + "name": "Client Credentials Test Product", + "orgName": "Ministry of Health", + "orgUnitName": "Planning and Innovation Division", + "environment": { + "name": "test", + "config": { + "terms": "Terms of Use for API Gateway", + "authorization": "Public", + "optionalInstructions": "This is a automation test", + "serviceName": "cc-service-for-platform" + } + } + } + }, + "KongApiOnly": { + "product": { + "name": "Auto Test Product", + "orgName": "Ministry of Health", + "orgUnitName": "Planning and Innovation Division", + "environment": { + "name": "dev", + "config": { + "terms": "Terms of Use for API Gateway", + "authorization": "Kong API Key Only", + "optionalInstructions": "This is a automation test", + "serviceName": "a-service-for-newplatform" + } + } + } + }, "clientIdSecret_KongKeyToCC": { "product": { "name": "Auto Test Product", diff --git a/e2e/cypress/fixtures/developer.json b/e2e/cypress/fixtures/developer.json index 97f33802c..1be081bea 100644 --- a/e2e/cypress/fixtures/developer.json +++ b/e2e/cypress/fixtures/developer.json @@ -134,6 +134,16 @@ "environment": "dev" } }, + "elevatedAccess":{ + "application": { + "name": "Request for Elevated Acess", + "description": "Test application for auto test" + }, + "product": { + "name": "Auto Test Product", + "environment": "dev" + } + }, "deleteApplication":{ "application": { "name": "delete-application-without-access", diff --git a/e2e/cypress/fixtures/manage-control-config-setting.json b/e2e/cypress/fixtures/manage-control-config-setting.json index 0133242b5..cecd9ef62 100644 --- a/e2e/cypress/fixtures/manage-control-config-setting.json +++ b/e2e/cypress/fixtures/manage-control-config-setting.json @@ -1,7 +1,8 @@ { "rateLimiting": { "requestPerHour_Consumer" : "1", - "requestPerHour_Global" : "2" + "requestPerHour_Global" : "2", + "rateLimiting_hour": "25" }, "ipRestriction" :{ "ipRange_valid" : "192.168.0.1/0", diff --git a/e2e/cypress/fixtures/manage-control/kong-plugin-config.json b/e2e/cypress/fixtures/manage-control/kong-plugin-config.json index 9eaf278cd..758974149 100644 --- a/e2e/cypress/fixtures/manage-control/kong-plugin-config.json +++ b/e2e/cypress/fixtures/manage-control/kong-plugin-config.json @@ -4,6 +4,11 @@ "config.hour": "20", "config.policy": "local" }, + "rateLimiting902": { + "name": "rate-limiting_902", + "config.hour": "20", + "limit_by": "service" + }, "rateLimitingConsumer": { "name": "rate-limiting", "config.hour": "100", @@ -17,6 +22,6 @@ "username": "consumer1" }, "keyAuth": { - "config.anonymous": "09f98d53-4797-4ba9-a9e8-6417a1cee3b0" + "config.anonymous": "e60a4444-eeab-4d5b-8285-6e6a648d85ec" } } \ No newline at end of file diff --git a/e2e/cypress/fixtures/rate-limiting-902.yml b/e2e/cypress/fixtures/rate-limiting-902.yml new file mode 100644 index 000000000..69b4e9f11 --- /dev/null +++ b/e2e/cypress/fixtures/rate-limiting-902.yml @@ -0,0 +1,8 @@ + plugins: + - name: rate-limiting_902 + tags: [ns.newplatform] + config: + fault_tolerant: true + hide_client_headers: false + limit_by: service + minute: 30 \ No newline at end of file diff --git a/e2e/cypress/pageObjects/apiDirectory.ts b/e2e/cypress/pageObjects/apiDirectory.ts index e9eb39934..88a47ca23 100644 --- a/e2e/cypress/pageObjects/apiDirectory.ts +++ b/e2e/cypress/pageObjects/apiDirectory.ts @@ -19,9 +19,12 @@ class ApiDirectoryPage { addOrganizationBtn: string = '[data-testid="addOrganizationBtn"]' - createAccessRequest(product: any, app: any, accessRqst: any) { + createAccessRequest(product: any, app: any, accessRqst: any, elevatedAccess?: boolean) { cy.contains('a', product.name, { timeout: 10000 }).should('be.visible'); cy.contains(product.name).click() + if(elevatedAccess){ + cy.contains('For elevated access, please Request Access').should('be.visible'); + } cy.get(this.rqstAccessBtn).click() cy.get(this.appSelect).select(app.name) cy.get('[data-testid=access-rqst-app-env-' + product.environment + ']').click() diff --git a/e2e/cypress/pageObjects/consumers.ts b/e2e/cypress/pageObjects/consumers.ts index a5afb9d2b..11e383e0e 100644 --- a/e2e/cypress/pageObjects/consumers.ts +++ b/e2e/cypress/pageObjects/consumers.ts @@ -98,8 +98,6 @@ export default class ConsumersPage { cy.contains('span', 'Route').click({ force: true }) } cy.get(this.applyBtn).click() - // cy.contains('h2', 'ip-restriction').should('be.visible') - // cy.wait(500) cy.get(this.consumerDialogSaveBtn).click() cy.wait(1000) } diff --git a/e2e/cypress/pageObjects/products.ts b/e2e/cypress/pageObjects/products.ts index 4df354210..1883c9511 100644 --- a/e2e/cypress/pageObjects/products.ts +++ b/e2e/cypress/pageObjects/products.ts @@ -48,7 +48,7 @@ class Products { } createNewProduct(productName: string, env: string) { - cy.get(this.newProductBtn).click() + cy.get(this.newProductBtn).first().click() cy.get(this.productNameInput).type(productName) cy.get(`[data-testid=prd-env-${env}-radio]`).click() cy.get(this.createBtn).click() @@ -224,14 +224,6 @@ class Products { force: true, delay: 500 }) - // cy.get(this.catelogueDropDownMenu) - // .find('div') - // .find('p') - // .each(($e1, index, $list) => { - // if ($e1.text() === productName) { - // cy.wrap($e1).click() - // } - // }) this.updateProduct() } diff --git a/e2e/cypress/pageObjects/serviceAccounts.ts b/e2e/cypress/pageObjects/serviceAccounts.ts index 5999035d7..0bc7fbdf4 100644 --- a/e2e/cypress/pageObjects/serviceAccounts.ts +++ b/e2e/cypress/pageObjects/serviceAccounts.ts @@ -62,6 +62,21 @@ class ServiceAccountsPage { } }) } + + deleteServiceAccount(clientId : string) { + cy.wait(2000) + let namespaceText + cy.get(this.serviceAccountTbl).find('tr').each(($e1, index, $list) => { + namespaceText = $e1.find('td:nth-child(1)').text(); + cy.log('namespaceText --> '+namespaceText) + if (namespaceText===clientId) { + cy.wrap($e1).find('button').first().click() + cy.wrap($e1).find(this.serviceAcctDeleteBtn).first().click() + cy.get(this.deleteServiceAcctConfirmationBtn).click() + return false + } + }) + } } export default ServiceAccountsPage diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts index 2af2260b2..81ba77095 100644 --- a/e2e/cypress/support/auth-commands.ts +++ b/e2e/cypress/support/auth-commands.ts @@ -472,18 +472,25 @@ Cypress.Commands.add('updatePluginFile', (filename: string, serviceName: string, }) }) -Cypress.Commands.add('updatePropertiesOfPluginFile', (filename: string, propertyName: string, propertyValue: any) => { + + +Cypress.Commands.add('updatePropertiesOfPluginFile', (filename: string, propertyName: any, propertyValue: any) => { cy.readFile('cypress/fixtures/' + filename).then((content: any) => { let obj = YAML.parse(content) const keys = Object.keys(obj); - 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 - } - }); + if (propertyName === "config.anonymous") { + 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 + } + }); + } 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 a1cadb0c9..19da26672 100644 --- a/e2e/cypress/support/global.d.ts +++ b/e2e/cypress/support/global.d.ts @@ -71,7 +71,9 @@ declare namespace Cypress { updatePluginFile (filename: string, serviceName: string, pluginFileName: string):Chainable> - updatePropertiesOfPluginFile(filename: string, propertyName: string, propertyValue: any):Chainable> + updateElementsInPluginFile(filename: string, elementName: string, elementValue: string):Chainable> + + updatePropertiesOfPluginFile(filename: string, propertyName: any, propertyValue: any):Chainable> keycloakLogin(username: string, password: string): Chainable 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 new file mode 100644 index 000000000..12a48b816 --- /dev/null +++ b/e2e/cypress/tests/09-update-product-env/07-kong-public-auth.ts @@ -0,0 +1,110 @@ +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import ApplicationPage from '../../pageObjects/applications' +import ConsumersPage from '../../pageObjects/consumers' +import HomePage from '../../pageObjects/home' +import LoginPage from '../../pageObjects/login' +import MyAccessPage from '../../pageObjects/myAccess' +import Products from '../../pageObjects/products' + +describe('Verify for Kong Public Auth', () => { + const login = new LoginPage() + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const myAccessPage = new MyAccessPage() + let consumerid: string + let consumerNumber: string + let existingAPIKey: string + var nameSpace: string + let userSession: string + const home = new HomePage() + const pd = new Products() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + cy.fixture('apiowner').as('apiowner') + cy.fixture('state/regen').as('regen') + cy.visit(login.path) + }) + + it('Authenticates api owner', () => { + cy.get('@apiowner').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + }) + }) + it('Activates the namespace', () => { + cy.getUserSession().then(() => { + cy.get('@apiowner').then(({ clientCredentials }: any) => { + nameSpace = clientCredentials.namespace + home.useNamespace(clientCredentials.namespace) + cy.get('@login').then(function (xhr: any) { + userSession = xhr.response.headers['x-auth-request-access-token'] + }) + }) + }) + }) + + it('Deactivate the service for Test environment', () => { + cy.visit(pd.path) + cy.get('@apiowner').then(({ clientCredentials }: any) => { + let product = clientCredentials.clientIdSecret_publicProfile.product + pd.deactivateService(product.name, product.environment.name, product.environment.config) + cy.wait(3000) + }) + }) + + it('Update the authorization scope from Kong ACL-API to Client Credential', () => { + cy.visit(pd.path) + cy.get('@apiowner').then(({ clientCredentials }: any) => { + let product = clientCredentials.clientIdSecret_publicProfile.product + pd.editProductEnvironment(product.name, product.environment.name) + pd.editProductEnvironmentConfig(product.environment.config) + }) + }) + + 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") + }) + }) + }) + }) + + it('activate the service for Test environment', () => { + cy.visit(pd.path) + cy.get('@apiowner').then(({ clientCredentials }: any) => { + cy.wait(2000) + let product = clientCredentials.clientIdSecret_publicProfile.product + pd.activateService(product.name, product.environment.name, product.environment.config) + cy.wait(3000) + }) + }) + + it('Verify that API is accessible with out any credential', () => { + 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','').then((response) => { + cy.log(response) + expect(response.status).to.be.equal(200) + }) + }) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + +}) \ No newline at end of file diff --git a/e2e/cypress/tests/10-clear-resources/03-delete-service-acc.ts b/e2e/cypress/tests/10-clear-resources/03-delete-service-acc.ts new file mode 100644 index 000000000..205cbc26e --- /dev/null +++ b/e2e/cypress/tests/10-clear-resources/03-delete-service-acc.ts @@ -0,0 +1,58 @@ +import HomePage from '../../pageObjects/home' +import LoginPage from '../../pageObjects/login' +import NameSpacePage from '../../pageObjects/namespace' +import Products from '../../pageObjects/products' +import ServiceAccountsPage from '../../pageObjects/serviceAccounts' + + +describe('Create API Spec', () => { + const login = new LoginPage() + const home = new HomePage() + const sa = new ServiceAccountsPage() + const pd = new Products() + const ns = new NameSpacePage() + var nameSpace: string + let userSession: string + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + cy.fixture('api').as('api') + // 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('Delete existing service account', () => { + cy.fixture('state/store').then((creds: any) => { + let cc = JSON.parse(creds.credentials) + const id = cc.clientId + cy.visit(sa.path) + sa.deleteServiceAccount(id) + }) + }) + + it('Verify that the service account is disabled', () => { + cy.fixture('state/store').then((creds: any) => { + let cc = JSON.parse(creds.credentials) + cy.getAccessToken(cc.clientId, cc.clientSecret).then(() => { + cy.get('@accessTokenResponse').then((token_res: any) => { + expect(token_res.status).to.be.equal(400) + expect(token_res.body.error).to.contains("unauthorized_client") + }) + }) + }) + }) +}) \ No newline at end of file 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 8253994c9..6ac09b0c5 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 @@ -9,7 +9,6 @@ import ServiceAccountsPage from '../../pageObjects/serviceAccounts' import MyAccessPage from '../../pageObjects/myAccess' import ConsumersPage from '../../pageObjects/consumers' - describe('Add Organization to publish API', () => { const login = new LoginPage() const home = new HomePage() @@ -48,7 +47,6 @@ describe('Add Organization to publish API', () => { cy.visit(sa.path) cy.get('@apiowner').then(({ serviceAccount }: any) => { sa.createServiceAccount(serviceAccount.scopes) - cy.wait(6000) }) sa.saveServiceAcctCreds() }) From 970a73e1655c95d09052d34f77f0aac641144c58 Mon Sep 17 00:00:00 2001 From: nirajCITZ <94716060+nirajCITZ@users.noreply.github.com> Date: Thu, 11 May 2023 14:18:14 -0700 Subject: [PATCH 6/6] Cypress delete service acc (#805) * Added following scenarios: 1)Cypress test to verify free (Public) access 2)Cypress Test - Delete Service account 3)Cypress Test - Verify rate_limiting_902 and rate_limiting plugins by applying them to different level 4)Cypress Test for Org Admin * Added scenario for free elevated access rate limiting and update test execution sequence * Update authorization profile -inheritFrom scenario and update the execution order * Update free-elivated scenarios, added Link consumer to namespace scenarios and added test-dataid * Update free-elevated scenario --------- Co-authored-by: Niraj Patel --- e2e/cypress.config.ts | 2 +- e2e/cypress/fixtures/api.json | 2 +- .../manage-control-config-setting.json | 3 +- .../fixtures/service-plugin-key-auth-only.yml | 22 +- e2e/cypress/pageObjects/consumers.ts | 58 +++- e2e/cypress/pageObjects/myAccess.ts | 8 + e2e/cypress/pageObjects/namespaceAccess.ts | 1 - e2e/cypress/pageObjects/products.ts | 21 +- e2e/cypress/support/auth-commands.ts | 25 +- e2e/cypress/support/global.d.ts | 2 + .../tests/01-api-key/01-create-api.cy.ts | 7 + .../01-api-key/05-collect-credentials.cy.ts | 1 + .../08-apply-kong-api-only-consumer.cy.ts | 85 ------ ...09-kong-api-only-apply-rate-limiting.cy.ts | 58 ---- .../01-client-cred-team-access.cy.ts | 0 .../02-create_authorizarion_profile.cy.ts | 0 ...client-cred-create-api-prod-auth-pro.cy.ts | 0 .../04-cids-access-rqst.cy.ts | 0 .../05-cids-access-approve-api-rqst.cy.ts | 0 .../06-jwt-genkp-access-rqst.cy.ts | 0 ...07-jwt-genkp-access-approve-api-rqst.cy.ts | 0 .../08-jwks-url-gen-keys-access-rqst.cy.ts | 0 ...09-jwks-url-access-approval-api-rqst.cy.ts | 0 .../03-manage-labels/03-link-consumers.ts | 75 ++++++ .../01-gateway-service-details.cy.ts | 0 .../02-filter-gateway-service.cy.ts | 0 .../01-migrate-user-access.cy.ts | 0 .../01-api-key.cy.ts | 20 +- .../02-client-credentials.cy.ts | 0 .../01-ip-restriction.cy.ts | 0 .../02-rate-limiting.cy.ts | 0 ...03-kong-api-only-apply-rate-limiting.cy.ts | 248 ++++++++++++++++++ ...nt-role copy.ts => 03-read-client-role.ts} | 0 .../04-keycloak-shared-IDP-config.cy.ts | 66 +++++ ...s.cy.ts => 05-authorizationProfiles.cy.ts} | 0 .../{05-products.cy.ts => 06-products.cy.ts} | 0 ...directory.cy.ts => 07-api-directory.cy.ts} | 0 ...7-namespaces.cy.ts => 08-namespaces.cy.ts} | 0 local/feeder-init/organization-unit.yaml | 8 + .../link-consumer/link-consumer.tsx | 4 +- .../products-list/dataset-input.tsx | 2 +- 41 files changed, 517 insertions(+), 201 deletions(-) delete mode 100644 e2e/cypress/tests/01-api-key/08-apply-kong-api-only-consumer.cy.ts delete mode 100644 e2e/cypress/tests/01-api-key/09-kong-api-only-apply-rate-limiting.cy.ts rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/01-client-cred-team-access.cy.ts (100%) rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/02-create_authorizarion_profile.cy.ts (100%) rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/03-client-cred-create-api-prod-auth-pro.cy.ts (100%) rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/04-cids-access-rqst.cy.ts (100%) rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/05-cids-access-approve-api-rqst.cy.ts (100%) rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/06-jwt-genkp-access-rqst.cy.ts (100%) rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/07-jwt-genkp-access-approve-api-rqst.cy.ts (100%) rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/08-jwks-url-gen-keys-access-rqst.cy.ts (100%) rename e2e/cypress/tests/{04-client-credential-flow => 02-client-credential-flow}/09-jwks-url-access-approval-api-rqst.cy.ts (100%) create mode 100644 e2e/cypress/tests/03-manage-labels/03-link-consumers.ts rename e2e/cypress/tests/{05-gateway-services => 04-gateway-services}/01-gateway-service-details.cy.ts (100%) rename e2e/cypress/tests/{05-gateway-services => 04-gateway-services}/02-filter-gateway-service.cy.ts (100%) rename e2e/cypress/tests/{06-migrate-user => 05-migrate-user}/01-migrate-user-access.cy.ts (100%) rename e2e/cypress/tests/{07-refresh-credential => 06-refresh-credential}/01-api-key.cy.ts (83%) rename e2e/cypress/tests/{07-refresh-credential => 06-refresh-credential}/02-client-credentials.cy.ts (100%) rename e2e/cypress/tests/{02-manage-control => 07-manage-control}/01-ip-restriction.cy.ts (100%) rename e2e/cypress/tests/{02-manage-control => 07-manage-control}/02-rate-limiting.cy.ts (100%) create mode 100644 e2e/cypress/tests/07-manage-control/03-kong-api-only-apply-rate-limiting.cy.ts rename e2e/cypress/tests/08-client-role/{03-read-client-role copy.ts => 03-read-client-role.ts} (100%) create mode 100644 e2e/cypress/tests/16-aps-api/04-keycloak-shared-IDP-config.cy.ts rename e2e/cypress/tests/16-aps-api/{04-authorizationProfiles.cy.ts => 05-authorizationProfiles.cy.ts} (100%) rename e2e/cypress/tests/16-aps-api/{05-products.cy.ts => 06-products.cy.ts} (100%) rename e2e/cypress/tests/16-aps-api/{06-api-directory.cy.ts => 07-api-directory.cy.ts} (100%) rename e2e/cypress/tests/16-aps-api/{07-namespaces.cy.ts => 08-namespaces.cy.ts} (100%) diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index 9b30b00eb..023a06a0f 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -13,10 +13,10 @@ export default defineConfig({ config.specPattern=[ './cypress/tests/01-*/*.ts', './cypress/tests/02-*/*.ts', + './cypress/tests/06-*/*.ts', './cypress/tests/03-*/*.ts', './cypress/tests/04-*/*.ts', './cypress/tests/05-*/*.ts', - './cypress/tests/06-*/*.ts', './cypress/tests/07-*/*.ts', './cypress/tests/08-*/*.ts', './cypress/tests/09-*/*.ts', diff --git a/e2e/cypress/fixtures/api.json b/e2e/cypress/fixtures/api.json index 6f87b30c9..e7ae3668f 100644 --- a/e2e/cypress/fixtures/api.json +++ b/e2e/cypress/fixtures/api.json @@ -182,7 +182,7 @@ "mode": "auto", "environmentDetails": [ { - "environment": "dev", + "environment": "test", "issuerUrl": "http://keycloak.localtest.me:9080/auth/realms/master", "clientRegistration": "managed", "clientId": "gwa-api", diff --git a/e2e/cypress/fixtures/manage-control-config-setting.json b/e2e/cypress/fixtures/manage-control-config-setting.json index cecd9ef62..58be9e76d 100644 --- a/e2e/cypress/fixtures/manage-control-config-setting.json +++ b/e2e/cypress/fixtures/manage-control-config-setting.json @@ -2,7 +2,8 @@ "rateLimiting": { "requestPerHour_Consumer" : "1", "requestPerHour_Global" : "2", - "rateLimiting_hour": "25" + "rateLimiting_hour": "25", + "requestPerHour_Elevated" : "250" }, "ipRestriction" :{ "ipRange_valid" : "192.168.0.1/0", diff --git a/e2e/cypress/fixtures/service-plugin-key-auth-only.yml b/e2e/cypress/fixtures/service-plugin-key-auth-only.yml index 823116108..897d275a7 100644 --- a/e2e/cypress/fixtures/service-plugin-key-auth-only.yml +++ b/e2e/cypress/fixtures/service-plugin-key-auth-only.yml @@ -1,10 +1,12 @@ - plugins: - - name: key-auth - tags: [ ns.newplatform ] - protocols: [ http, https ] - config: - key_names: ["X-API-KEY"] - run_on_preflight: true - hide_credentials: true - key_in_body: false - +plugins: + - + name: key-auth + tags: + - ns.newplatform + protocols: + - http + - https + config: + key_names: + - x-api-key + anonymous: 1aaf2351-0622-4cc4-8d14-32e78771e620 diff --git a/e2e/cypress/pageObjects/consumers.ts b/e2e/cypress/pageObjects/consumers.ts index 11e383e0e..95e50f454 100644 --- a/e2e/cypress/pageObjects/consumers.ts +++ b/e2e/cypress/pageObjects/consumers.ts @@ -2,8 +2,12 @@ import { Assertion } from "chai" import { wrap } from "module" import dateformat from 'dateformat' import { checkElementExists } from "../support/e2e" +import { String } from "cypress/types/lodash" +import { StringLiteral } from "typescript" +import { truncate } from "fs/promises" export default class ConsumersPage { + path: string = '/manager/consumers' rateLimitHourInput: string = '[data-testid="ratelimit-hour-input"]' ipRestrictionAllowInput: string = '[data-testid="allow-ip-restriction-input-input"]' @@ -38,6 +42,9 @@ export default class ConsumersPage { removeRateLimitControlButton: string = '[data-testid="ratelimit-item-delete-btn-0"]' rateLimitRouteRadioBtn: string = '[data-testid="ratelimit-route-radio"]' consumerDialogCancelBtn: string = '[data-testid="edit-consumer-dialog-edit-cancel-btn"]' + linkConsumerToNamespaceBtn: string = '[data-testid="link-consumer-namespace"]' + userNameTxt: string = '[data-testid="link-consumer-username"]' + linkBtn: string = '[data-testid="link-consumer-link-btn"]' clickOnRateLimitingOption() { cy.get(this.rateLimitingOption, { timeout: 2000 }).click() @@ -65,14 +72,24 @@ export default class ConsumersPage { setRateLimiting(requestCount: string, scope = 'Service', policy = 'Local') { this.editConsumerDialog() cy.wait(2000) - if (!checkElementExists(this.rateLimitingOption)){ + if (!checkElementExists(this.rateLimitingOption)) { cy.get(this.consumerDialogCancelBtn).click() this.editConsumerDialog() } - // cy.wait(1000) + cy.wait(1000) + this.setRateLimitingWithOutConsumerID(requestCount, scope, policy) + // cy.wait(500) + cy.get(this.consumerDialogSaveBtn).click() + cy.get(this.consumerDialogSaveBtn, { timeout: 2000 }).should('not.exist') + cy.wait(3000) + } + + setRateLimitingWithOutConsumerID(requestCount: string, scope?: string, policy?: string) { + scope = scope || 'Service' + policy = policy || 'Local' this.clickOnRateLimitingOption() cy.wait(3000) - + cy.get(this.rateLimitHourInput, { timeout: 5000 }).click() cy.get(this.rateLimitHourInput, { timeout: 2000 }).type(requestCount) @@ -83,10 +100,6 @@ export default class ConsumersPage { cy.get(this.policyDropDown).select(policy, { force: true }).invoke('val') } cy.get(this.rateLimitingApplyBtn).click() - // cy.wait(500) - cy.get(this.consumerDialogSaveBtn).click() - cy.get(this.consumerDialogSaveBtn, { timeout: 2000 }).should('not.exist') - cy.wait(3000) } setAllowedIPAddress(allowIP: string, scope = 'Service') { @@ -149,7 +162,7 @@ export default class ConsumersPage { cy.verifyToastMessage("Access request approved") } - reviewThePendingRequest() : Boolean{ + reviewThePendingRequest(): Boolean { cy.wait(3000) var flag = false; cy.get("body").then($body => { @@ -308,7 +321,7 @@ export default class ConsumersPage { selectAuthorizationScope(scopes: any) { cy.contains("Authorization").click() scopes.forEach(function (scope: string) { - cy.get('[data-testid="client-scope-'+scope+'"]').click() + cy.get('[data-testid="client-scope-' + scope + '"]').click() cy.wait(1000) }) } @@ -316,8 +329,31 @@ export default class ConsumersPage { selectClientRole(roles: any) { cy.contains("Authorization").click() roles.forEach(function (role: string) { - cy.get('[data-testid="client-role-'+role.toLocaleLowerCase()+'"]').click() + cy.get('[data-testid="client-role-' + role.toLocaleLowerCase() + '"]').click() cy.wait(1000) }) } -} + + deleteConsumer(consumerID: any) { + cy.get(this.allConsumerTable).find('tr').each(($row, index) => { + 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}) + } + }) + } + + clickOnLinkConsumerToNamespaceBtn() { + cy.get(this.linkConsumerToNamespaceBtn).click({force:true}) + } + + linkTheConsumerToNamespace(consumerID: any) { + cy.get(this.userNameTxt).type(consumerID) + cy.get(this.linkBtn).click({force:true}) + } + + 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/pageObjects/myAccess.ts b/e2e/cypress/pageObjects/myAccess.ts index e8fb9516e..9865f08b4 100644 --- a/e2e/cypress/pageObjects/myAccess.ts +++ b/e2e/cypress/pageObjects/myAccess.ts @@ -1,4 +1,5 @@ class myAccessPage { + generateSecretsBtn: string = '[data-testid=generate-secrets-button]' apiKyeValueTxt: string = '[data-testid=sa-new-creds-api-key]' clientId: string = '[data-testid=sa-new-creds-client-id]' @@ -12,6 +13,7 @@ class myAccessPage { regenerateCredentialBtn: string = '[data-testid=regenerate-credentials-btn]' regenerateCredentialCloseBtn: string = '[data-testid=regenerate-credentials-done-button]' collectCredentialsBtn: string = '[data-testid="generate-credentials-button"]' + clientIDValueTxt: string = '[data-testid="sa-new-creds-client-id"]' path: string = '/devportal/access' @@ -158,6 +160,12 @@ class myAccessPage { } }) } + + saveClientIDValue() { + cy.get(this.clientIDValueTxt).invoke('val').then(($clientID: any) => { + cy.saveState('clientID', $clientID) + }) + } } export default myAccessPage diff --git a/e2e/cypress/pageObjects/namespaceAccess.ts b/e2e/cypress/pageObjects/namespaceAccess.ts index e01b72ba3..bcc4d471e 100644 --- a/e2e/cypress/pageObjects/namespaceAccess.ts +++ b/e2e/cypress/pageObjects/namespaceAccess.ts @@ -29,7 +29,6 @@ class NamespaceAccessPage { // cy.get(this.userNameInput).type(editPermission.email); let accessRole: Array = editPermission.accessRole accessRole.forEach(function (accessName) { - debugger cy.contains("Permissions").next().find('li').find('label').each(($el, index, $list) => { // cy.wrap($el).find('input').uncheck({ force: true }); const textAccessRoleName = $el.text() diff --git a/e2e/cypress/pageObjects/products.ts b/e2e/cypress/pageObjects/products.ts index 1883c9511..31f030291 100644 --- a/e2e/cypress/pageObjects/products.ts +++ b/e2e/cypress/pageObjects/products.ts @@ -35,6 +35,7 @@ class Products { credentialIssuer: string = '[name="credentialIssuer"]' config: string | undefined publishAPI: string = '[id="orgEnabled"]' + messageForNotDataset: string = '[data-testid="no-result-for-dataset"]' getTestIdEnvName(env: string): string { switch (env) { @@ -110,16 +111,14 @@ class Products { authType === 'Oauth2 Authorization Code Flow' || authType === 'Oauth2 Client Credentials Flow' ) { - debugger let env = this.getTestIdEnvName(config.authIssuerEnv) cy.get('[name="credentialIssuer"]').select( `${config.authIssuer} (${env})` ) } - cy.get(this.envCfgOptText).type(config.optionalInstructions) + cy.get(this.envCfgOptText).clear().type(config.optionalInstructions) cy.get('[name="active"]').then($button => { - debugger if ($button.is(':disabled')) { flag = false } @@ -129,7 +128,6 @@ class Products { .as('checkbox') .invoke('is', ':checked') .then(checked => { - debugger if (invalid) { cy .get('@checkbox') @@ -148,7 +146,6 @@ class Products { .as('checkbox') .invoke('is', ':checked') .then(checked => { - debugger if (!isApproved) { cy .get('@checkbox') @@ -164,7 +161,6 @@ class Products { // cy.get(this.envCfgApprovalCheckbox).click() // cy.get(this.editPrdEnvConfigBtn).click() cy.wait(3000) - debugger if (flag) { cy.get(this.envCfgApplyChangesContinueBtn).click() } @@ -300,8 +296,7 @@ class Products { .get(this.publishAPI) .as('checkbox') .invoke('is', ':checked') - .then(checked => { - debugger + .then(checked => { if (status) { cy .get('@checkbox') @@ -314,6 +309,16 @@ class Products { } }); } + + checkMessageForNoDataset(productName: string,search_input: string ) { + this.editProduct(productName) + cy.get(this.catelogueDropDown).type(search_input + '{downArrow}' + '{enter}', { + force: true, + delay: 500 + }) + cy.get(this.messageForNotDataset).should('be.visible'); + + } } export default Products diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts index 81ba77095..b259044d5 100644 --- a/e2e/cypress/support/auth-commands.ts +++ b/e2e/cypress/support/auth-commands.ts @@ -59,15 +59,6 @@ Cypress.Commands.add('login', (username: string, password: string, skipFlag = fa cy.get(login.loginSubmitButton).click() } - // log.end() - // cy.getLoginCallback().then(() => { - // cy.get('@login1').should((response :any) => { - // debugger - // if (response.status == 403) - // cy.wait(60000); - // cy.log("Trigger the block") - // }) - // }) if (!skipFlag) { cy.get(home.nsDropdown, { timeout: 6000 }).then(($el) => { expect($el).to.exist @@ -87,6 +78,14 @@ 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)=>{ + id = $text.text() + return id + }) +}) + Cypress.Commands.add('resetCredential', (accessRole: string) => { const login = new LoginPage() const home = new HomePage() @@ -291,7 +290,11 @@ Cypress.Commands.add('makeKongRequest', (serviceName: string, methodType: string let authorization cy.fixture('state/regen').then((creds: any) => { cy.wait(2000) - let token = key || creds.apikey + let token = key + if (key==undefined) + { + token = creds.apikey + } const service = serviceName cy.log("Token->" + token) return cy.request({ @@ -354,7 +357,7 @@ Cypress.Commands.add('updateKongPlugin', (pluginName: string, name: string, endP let endpoint if (pluginName == '') endpoint = 'plugins' - else + else if(id !== undefined) endpoint = pluginName.toLowerCase() + '/' + id.toString() + '/' + 'plugins' endpoint = (typeof endPoint !== 'undefined') ? endPoint : endpoint body = config[name] diff --git a/e2e/cypress/support/global.d.ts b/e2e/cypress/support/global.d.ts index 19da26672..734da1e79 100644 --- a/e2e/cypress/support/global.d.ts +++ b/e2e/cypress/support/global.d.ts @@ -79,6 +79,8 @@ declare namespace Cypress { selectLoginOptions(username: string): Chainable + getLastConsumerID(): Chainable + // isProductDisplay(productName: string, expResult : boolean) :Chainable> } } 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 0149e41d4..5e1abba9c 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 @@ -86,6 +86,13 @@ 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") + }) + }) + it('update the Dataset in BC Data Catelogue to appear the API in the Directory', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ product }: any) => { diff --git a/e2e/cypress/tests/01-api-key/05-collect-credentials.cy.ts b/e2e/cypress/tests/01-api-key/05-collect-credentials.cy.ts index 2d381b69b..d70aaafe0 100644 --- a/e2e/cypress/tests/01-api-key/05-collect-credentials.cy.ts +++ b/e2e/cypress/tests/01-api-key/05-collect-credentials.cy.ts @@ -40,6 +40,7 @@ describe('Collect credential Spec', () => { myAccessPage.clickOnCollectCredentialButton() myAccessPage.clickOnGenerateSecretButton() cy.contains("API Key").should('be.visible') + myAccessPage.saveClientIDValue() myAccessPage.saveAPIKeyValue() }) diff --git a/e2e/cypress/tests/01-api-key/08-apply-kong-api-only-consumer.cy.ts b/e2e/cypress/tests/01-api-key/08-apply-kong-api-only-consumer.cy.ts deleted file mode 100644 index da8205eef..000000000 --- a/e2e/cypress/tests/01-api-key/08-apply-kong-api-only-consumer.cy.ts +++ /dev/null @@ -1,85 +0,0 @@ -describe('Apply Kong API key only plugin', () => { - var consumerID: string - var consumerKey: string - var pluginID: string - - beforeEach(() => { - cy.preserveCookies() - cy.fixture('access-manager').as('access-manager') - cy.fixture('developer').as('developer') - cy.fixture('apiowner').as('apiowner') - cy.fixture('state/store').as('store') - }) - - it('Apply Key-auth only authorization plugin to Kong Gateway', () => { - 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)) - }) - }) - }) - }) - - it('Get the plugin ID of Key-auth plugin', () => { - cy.makeKongGatewayRequest('plugins', '', 'GET').then((response) => { - expect(response.status).to.be.equal(200) - pluginID = _.get((_.filter(response.body.data,["name","key-auth"]))[0],'id') - }) - }) - - it('Create a new consumer and save the consumer Id', () => { - cy.makeKongGatewayRequest('consumers', 'createConsumer', 'POST').then((response) => { - expect(response.status).to.be.equal(201) - consumerID = response.body.id - cy.saveState("consumersid", consumerID) - }) - }) - - it('Create a key for the newly created consumer', () => { - const endpoint = 'consumers/' + consumerID + '/key-auth' - cy.makeKongGatewayRequest(endpoint, '', 'POST').then((response) => { - expect(response.status).to.be.equal(201) - consumerKey = response.body.key - cy.saveState("consumerkey", consumerKey) - }) - }) - - it('Update the Kong key-auth plugin the new consumer', () => { - cy.saveState("config.anonymous", consumerID) - cy.updateKongPlugin('', 'keyAuth', 'plugins/' + pluginID, 'PATCH').then((response) => { - expect(response.status).to.be.equal(200) - }) - }) -}) - -describe('Check the API key for free and elevated access', () => { - - beforeEach(() => { - cy.preserveCookies() - cy.fixture('apiowner').as('apiowner') - cy.fixture('state/store').as('store') - }) - - it('Verify the service is accessibale with 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', key).then((response) => { - expect(response.status).to.be.equal(200) - }) - }) - }) - }) - - it('Verify the service is accessible with API key for elevated access', () => { - cy.get('@apiowner').then(async ({ product }: any) => { - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - }) - }) - }) -}) - - diff --git a/e2e/cypress/tests/01-api-key/09-kong-api-only-apply-rate-limiting.cy.ts b/e2e/cypress/tests/01-api-key/09-kong-api-only-apply-rate-limiting.cy.ts deleted file mode 100644 index 6ecf3fbbd..000000000 --- a/e2e/cypress/tests/01-api-key/09-kong-api-only-apply-rate-limiting.cy.ts +++ /dev/null @@ -1,58 +0,0 @@ - -describe('Check the API key for free and elevated access', () => { - - beforeEach(() => { - cy.preserveCookies() - cy.fixture('apiowner').as('apiowner') - cy.fixture('state/store').as('store') - }) - - it('Verify the service is accessibale with 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', key).then((response) => { - expect(response.status).to.be.equal(200) - }) - }) - }) - }) - - it('Verify the service is accessible with API key for elevated access', () => { - cy.get('@apiowner').then(async ({ product }: any) => { - cy.fixture('state/store').then((creds: any) => { - cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { - expect(response.status).to.be.equal(200) - }) - }) - }) - }) -}) - -describe('Apply Rate limiting for Free Access', () => { - - beforeEach(() => { - cy.preserveCookies() - cy.fixture('apiowner').as('apiowner') - cy.fixture('state/store').as('store') - }) - - it('set api rate limit to free access', () => { - cy.updateKongPlugin('consumers', 'rateLimitingConsumer').then((response) => { - expect(response.status).to.be.equal(201) - }) - }) - - it('Verify the rate limiting is applied 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', key).then((response) => { - expect(response.status).to.be.equal(200) - expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.equal(99) - }) - }) - }) - }) - -}) diff --git a/e2e/cypress/tests/04-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 similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/01-client-cred-team-access.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/01-client-cred-team-access.cy.ts diff --git a/e2e/cypress/tests/04-client-credential-flow/02-create_authorizarion_profile.cy.ts b/e2e/cypress/tests/02-client-credential-flow/02-create_authorizarion_profile.cy.ts similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/02-create_authorizarion_profile.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/02-create_authorizarion_profile.cy.ts diff --git a/e2e/cypress/tests/04-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 similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/03-client-cred-create-api-prod-auth-pro.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/03-client-cred-create-api-prod-auth-pro.cy.ts diff --git a/e2e/cypress/tests/04-client-credential-flow/04-cids-access-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/04-cids-access-rqst.cy.ts similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/04-cids-access-rqst.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/04-cids-access-rqst.cy.ts diff --git a/e2e/cypress/tests/04-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 similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/05-cids-access-approve-api-rqst.cy.ts diff --git a/e2e/cypress/tests/04-client-credential-flow/06-jwt-genkp-access-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/06-jwt-genkp-access-rqst.cy.ts similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/06-jwt-genkp-access-rqst.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/06-jwt-genkp-access-rqst.cy.ts diff --git a/e2e/cypress/tests/04-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 similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/07-jwt-genkp-access-approve-api-rqst.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/07-jwt-genkp-access-approve-api-rqst.cy.ts diff --git a/e2e/cypress/tests/04-client-credential-flow/08-jwks-url-gen-keys-access-rqst.cy.ts b/e2e/cypress/tests/02-client-credential-flow/08-jwks-url-gen-keys-access-rqst.cy.ts similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/08-jwks-url-gen-keys-access-rqst.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/08-jwks-url-gen-keys-access-rqst.cy.ts diff --git a/e2e/cypress/tests/04-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 similarity index 100% rename from e2e/cypress/tests/04-client-credential-flow/09-jwks-url-access-approval-api-rqst.cy.ts rename to e2e/cypress/tests/02-client-credential-flow/09-jwks-url-access-approval-api-rqst.cy.ts diff --git a/e2e/cypress/tests/03-manage-labels/03-link-consumers.ts b/e2e/cypress/tests/03-manage-labels/03-link-consumers.ts new file mode 100644 index 000000000..446dd1bd8 --- /dev/null +++ b/e2e/cypress/tests/03-manage-labels/03-link-consumers.ts @@ -0,0 +1,75 @@ +import ConsumersPage from '../../pageObjects/consumers' +import LoginPage from '../../pageObjects/login' +import HomePage from '../../pageObjects/home' +import ProductPage from '../../pageObjects/products' + +describe('Link Consumers to Namespace', () => { + const login = new LoginPage() + const consumers = new ConsumersPage() + const home = new HomePage() + let consumerID: any + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + cy.getServiceOrRouteID('services') + cy.getServiceOrRouteID('routes') + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + cy.fixture('developer').as('developer') + cy.fixture('state/store').as('store') + // cy.visit(login.path) + }) + + it('authenticates Mark (Access-Manager)', () => { + cy.get('@access-manager').then(({ user, namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) + }) + + it('Navigate to Consumer Page', () => { + cy.visit(consumers.path); + cy.wait(5000) + }) + + it('Get the consumer ID from the list', () => { + // cy.getLastConsumerID().then((title)=>{ + // consumerID = title + // }) + cy.wrap(consumers).its('inputValue').then(inputValue => { + consumerID = inputValue.text() + }) + }) + + it('Delete the consumer ID from the list', () => { + consumers.deleteConsumer(consumerID) + }) + + // it('Click on "Link Consumers to Namespace" button', () => { + // consumers.clickOnLinkConsumerToNamespaceBtn() + // }) + + // it('Link the delete consumer to the Namespace', () => { + // consumers.linkTheConsumerToNamespace(consumerID) + + // }) + + // it('Verify that the consumer is linked to the namespace', () => { + // cy.getLastConsumerID().then((title)=>{ + // expect(title).to.equal(consumerID) + // }) + // }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + +}) \ No newline at end of file diff --git a/e2e/cypress/tests/05-gateway-services/01-gateway-service-details.cy.ts b/e2e/cypress/tests/04-gateway-services/01-gateway-service-details.cy.ts similarity index 100% rename from e2e/cypress/tests/05-gateway-services/01-gateway-service-details.cy.ts rename to e2e/cypress/tests/04-gateway-services/01-gateway-service-details.cy.ts diff --git a/e2e/cypress/tests/05-gateway-services/02-filter-gateway-service.cy.ts b/e2e/cypress/tests/04-gateway-services/02-filter-gateway-service.cy.ts similarity index 100% rename from e2e/cypress/tests/05-gateway-services/02-filter-gateway-service.cy.ts rename to e2e/cypress/tests/04-gateway-services/02-filter-gateway-service.cy.ts diff --git a/e2e/cypress/tests/06-migrate-user/01-migrate-user-access.cy.ts b/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts similarity index 100% rename from e2e/cypress/tests/06-migrate-user/01-migrate-user-access.cy.ts rename to e2e/cypress/tests/05-migrate-user/01-migrate-user-access.cy.ts diff --git a/e2e/cypress/tests/07-refresh-credential/01-api-key.cy.ts b/e2e/cypress/tests/06-refresh-credential/01-api-key.cy.ts similarity index 83% rename from e2e/cypress/tests/07-refresh-credential/01-api-key.cy.ts rename to e2e/cypress/tests/06-refresh-credential/01-api-key.cy.ts index 753e6960b..bb494f1b4 100644 --- a/e2e/cypress/tests/07-refresh-credential/01-api-key.cy.ts +++ b/e2e/cypress/tests/06-refresh-credential/01-api-key.cy.ts @@ -22,7 +22,7 @@ describe('Regenerate Credential for API Key', () => { cy.preserveCookies() cy.fixture('developer').as('developer') cy.fixture('apiowner').as('apiowner') - cy.fixture('state/regen').as('regen') + cy.fixture('state/store').as('store') cy.visit(login.path) }) @@ -33,22 +33,20 @@ describe('Regenerate Credential for API Key', () => { }) it('Get the consumer id based on consumer number', () => { - cy.get('@regen').then((creds: any) => { - const consumerNumber = creds.consumernumber + cy.get('@store').then(({clientid}: any) => { + debugger cy.makeKongGatewayRequest('consumers', '', 'GET').then((response) => { expect(response.status).to.be.equal(200) - consumerid = Cypress._.get((Cypress._.filter(response.body.data, ["custom_id", consumerNumber]))[0], 'id') + consumerid = Cypress._.get((Cypress._.filter(response.body.data, ["custom_id", clientid]))[0], 'id') }) }) }) it('Get current API Key', () => { - cy.get('@regen').then((creds: any) => { - cy.get('@developer').then(({ user }: any) => { - cy.makeKongGatewayRequest('consumers/' + consumerid + '/key-auth', '', 'GET').then((response: any) => { - expect(response.status).to.be.equal(200) - existingAPIKey = response.body.data[0].key - }) + cy.get('@developer').then(({ user }: any) => { + cy.makeKongGatewayRequest('consumers/' + consumerid + '/key-auth', '', 'GET').then((response: any) => { + expect(response.status).to.be.equal(200) + existingAPIKey = response.body.data[0].key }) }) }) @@ -74,11 +72,9 @@ describe('Regenerate Credential for API Key', () => { }) it('Verify that only one API key(new key) is set to the consumer in Kong gateway', () => { - cy.get('@regen').then((creds: any) => { cy.makeKongGatewayRequest('consumers/' + consumerid + '/key-auth', '', 'GET').then((response: any) => { expect(response.status).to.be.equal(200) expect(response.body.data.length).to.be.equal(1) - }) }) }) diff --git a/e2e/cypress/tests/07-refresh-credential/02-client-credentials.cy.ts b/e2e/cypress/tests/06-refresh-credential/02-client-credentials.cy.ts similarity index 100% rename from e2e/cypress/tests/07-refresh-credential/02-client-credentials.cy.ts rename to e2e/cypress/tests/06-refresh-credential/02-client-credentials.cy.ts diff --git a/e2e/cypress/tests/02-manage-control/01-ip-restriction.cy.ts b/e2e/cypress/tests/07-manage-control/01-ip-restriction.cy.ts similarity index 100% rename from e2e/cypress/tests/02-manage-control/01-ip-restriction.cy.ts rename to e2e/cypress/tests/07-manage-control/01-ip-restriction.cy.ts diff --git a/e2e/cypress/tests/02-manage-control/02-rate-limiting.cy.ts b/e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts similarity index 100% rename from e2e/cypress/tests/02-manage-control/02-rate-limiting.cy.ts rename to e2e/cypress/tests/07-manage-control/02-rate-limiting.cy.ts 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 new file mode 100644 index 000000000..f3d0f283b --- /dev/null +++ b/e2e/cypress/tests/07-manage-control/03-kong-api-only-apply-rate-limiting.cy.ts @@ -0,0 +1,248 @@ +import _ = require("cypress/types/lodash") +import ApiDirectoryPage from "../../pageObjects/apiDirectory" +import ApplicationPage from "../../pageObjects/applications" +import HomePage from "../../pageObjects/home" +import LoginPage from "../../pageObjects/login" +import Products from "../../pageObjects/products" +import MyAccessPage from '../../pageObjects/myAccess' +import ConsumersPage from "../../pageObjects/consumers" +let apiKey: any + +describe('Apply Kong API key only plugin', () => { + var consumerID: string + var consumerKey: string + var pluginID: string + var serviceID: string + var nameSpace: string + let userSession: string + const home = new HomePage() + const pd = new Products() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + cy.fixture('developer').as('developer') + cy.fixture('state/store').as('store') + }) + + it('Authenticates api owner', () => { + cy.get('@apiowner').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + }) + }) + + it('Activates the namespace', () => { + cy.getUserSession().then(() => { + cy.get('@apiowner').then(({ namespace }: any) => { + nameSpace = namespace + home.useNamespace(namespace) + }) + }) + }) + + it('Deactivate the service for Test environment', () => { + cy.visit(pd.path) + cy.get('@apiowner').then(({ product }: any) => { + pd.deactivateService(product.name, product.environment.name, product.environment.config) + cy.wait(3000) + }) + }) + + it('Create a new consumer and save the consumer Id', () => { + cy.makeKongGatewayRequest('consumers', 'createConsumer', 'POST').then((response) => { + expect(response.status).to.be.equal(201) + consumerID = response.body.id + cy.saveState("consumersid", consumerID) + }) + }) + + it('Set Consumer ID to key auth anonymous config', () => { + cy.updatePropertiesOfPluginFile('service-plugin-key-auth-only.yml', 'config.anonymous', consumerID) + }) + + it('Update the authorization scope from Kong ACL-API to Kong API Only', () => { + cy.visit(pd.path) + cy.get('@apiowner').then(({ clientCredentials }: any) => { + let product = clientCredentials.KongApiOnly.product + pd.editProductEnvironment(product.name, product.environment.name) + pd.editProductEnvironmentConfig(product.environment.config) + }) + }) + + it('Apply Key-auth only authorization plugin to Kong Gateway', () => { + 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)) + }) + }) + }) + }) + + it('activate the service for Dev environment', () => { + 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) + cy.wait(3000) + }) + }) + + it('Apply Rate limiting on free access', () => { + cy.updateKongPlugin('consumers', 'rateLimitingConsumer', 'consumers/'+consumerID+'/plugins').then((response) => { + expect(response.status).to.be.equal(201) + }) + }) +}) + +describe('Check the API key for free access', () => { + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + cy.fixture('state/store').as('store') + }) + + it('Verify the service is accessibale with 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) => { + expect(response.status).to.be.equal(200) + expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.equal(99) + }) + }) + }) + }) +}) + +describe('Check the API key for Elevated access', () => { + + const login = new LoginPage() + const apiDir = new ApiDirectoryPage() + const app = new ApplicationPage() + const ma = new MyAccessPage() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + // cy.visit(login.path) + }) + + it('Developer logs in', () => { + 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(({ elevatedAccess }: any) => { + app.createApplication(elevatedAccess.application) + }) + }) + + it('Collect the credentials', () => { + cy.visit(apiDir.path) + cy.get('@developer').then(async ({ elevatedAccess, accessRequest }: any) => { + apiDir.createAccessRequest(elevatedAccess.product, elevatedAccess.application, accessRequest, true) + ma.clickOnGenerateSecretButton() + cy.contains("API Key").should('be.visible') + cy.get(ma.apiKyeValueTxt).invoke('val').then(($apiKey: any) => { + apiKey = $apiKey + }) + ma.saveAPIKeyValue() + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) + +describe('Approve Pending Request Spec', () => { + const login = new LoginPage() + const consumers = new ConsumersPage() + const home = new HomePage() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + cy.getServiceOrRouteID('services') + cy.getServiceOrRouteID('routes') + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('manage-control-config-setting').as('manage-control-config-setting') + cy.fixture('apiowner').as('apiowner') + cy.fixture('developer').as('developer') + cy.fixture('state/store').as('store') + // cy.visit(login.path) + }) + + it('authenticates Mark (Access-Manager)', () => { + cy.get('@access-manager').then(({ user, namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) + }) + + it('verify the request details', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.get('@developer').then(({ accessRequest, elevatedAccess }: any) => { + cy.visit(consumers.path); + consumers.reviewThePendingRequest() + consumers.verifyRequestDetails(product, accessRequest, elevatedAccess.application) + }) + }) + }) + + it('Navigate to Control Tab', () => { + cy.contains('Controls').click() + }) + + it('Set Rate Limiting', () => { + cy.get('@manage-control-config-setting').then(({ rateLimiting }: any) => { + consumers.setRateLimitingWithOutConsumerID(rateLimiting.requestPerHour_Elevated, 'Route') + }) + }) + + it('approves an access request', () => { + consumers.approvePendingRequest() + }) + + it('Verify that API is accessible with the generated API Key', () => { + cy.get('@apiowner').then(async ({ product }: any) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET', apiKey).then((response) => { + expect(response.status).to.be.equal(200) + expect(parseInt(response.headers["x-ratelimit-remaining-hour"])).to.be.equal(249) + }) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + +}) diff --git a/e2e/cypress/tests/08-client-role/03-read-client-role copy.ts b/e2e/cypress/tests/08-client-role/03-read-client-role.ts similarity index 100% rename from e2e/cypress/tests/08-client-role/03-read-client-role copy.ts rename to e2e/cypress/tests/08-client-role/03-read-client-role.ts diff --git a/e2e/cypress/tests/16-aps-api/04-keycloak-shared-IDP-config.cy.ts b/e2e/cypress/tests/16-aps-api/04-keycloak-shared-IDP-config.cy.ts new file mode 100644 index 000000000..ed2fd5f48 --- /dev/null +++ b/e2e/cypress/tests/16-aps-api/04-keycloak-shared-IDP-config.cy.ts @@ -0,0 +1,66 @@ +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import ApplicationPage from '../../pageObjects/applications' +import AuthorizationProfile from '../../pageObjects/authProfile' +import ConsumersPage from '../../pageObjects/consumers' +import HomePage from '../../pageObjects/home' +import keycloakGroupPage from '../../pageObjects/keycloakGroup' +import KeycloakUserGroupPage from '../../pageObjects/keycloakUserGroup' +import LoginPage from '../../pageObjects/login' +import MyAccessPage from '../../pageObjects/myAccess' +import Products from '../../pageObjects/products' + +describe('Apply Shared IDP config at Keycloak user group', () => { + const userGroups = new KeycloakUserGroupPage() + 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 User Groups', () => { + cy.contains('Groups').click() + }) + + it('Edit the namespace from the tree view', () => { + cy.get('@apiowner').then(({ apiTest }: any) => { + cy.contains(apiTest.namespace).click() + userGroups.clickOnEditButton() + }) + }) + + it('Navigate to attribute tab', () => { + userGroups.selectTab('Attributes') + }) + + it('Set the Attributes', () => { + groups.setAttribute('perm-protected-ns','allow') + }) + + after(() => { + cy.keycloakLogout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) + +}) + diff --git a/e2e/cypress/tests/16-aps-api/04-authorizationProfiles.cy.ts b/e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/04-authorizationProfiles.cy.ts rename to e2e/cypress/tests/16-aps-api/05-authorizationProfiles.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/05-products.cy.ts b/e2e/cypress/tests/16-aps-api/06-products.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/05-products.cy.ts rename to e2e/cypress/tests/16-aps-api/06-products.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/06-api-directory.cy.ts b/e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/06-api-directory.cy.ts rename to e2e/cypress/tests/16-aps-api/07-api-directory.cy.ts diff --git a/e2e/cypress/tests/16-aps-api/07-namespaces.cy.ts b/e2e/cypress/tests/16-aps-api/08-namespaces.cy.ts similarity index 100% rename from e2e/cypress/tests/16-aps-api/07-namespaces.cy.ts rename to e2e/cypress/tests/16-aps-api/08-namespaces.cy.ts diff --git a/local/feeder-init/organization-unit.yaml b/local/feeder-init/organization-unit.yaml index 7ce1cf097..d427ca2fb 100644 --- a/local/feeder-init/organization-unit.yaml +++ b/local/feeder-init/organization-unit.yaml @@ -19,3 +19,11 @@ record: description: '' extSource: '' extRecordHash: '' + - id: 319b3297-846d-4b97-8095-ceb3ec505fdf + name: public-health + sector: 'Public Health and Safety' + title: 'Public Health' + tags: [] + description: '' + extSource: '' + extRecordHash: '' diff --git a/src/nextapp/components/link-consumer/link-consumer.tsx b/src/nextapp/components/link-consumer/link-consumer.tsx index 4a7b0a436..5e5a764d4 100644 --- a/src/nextapp/components/link-consumer/link-consumer.tsx +++ b/src/nextapp/components/link-consumer/link-consumer.tsx @@ -71,6 +71,7 @@ const LinkConsumerDialog: React.FC = ({ leftIcon={} onClick={onOpen} variant="primary" + data-testid="link-consumer-namespace" > {title} @@ -97,6 +98,7 @@ const LinkConsumerDialog: React.FC = ({ name="username" type="text" placeholder="Enter username of the Consumer you would like to link" + data-testid="link-consumer-username" /> @@ -107,7 +109,7 @@ const LinkConsumerDialog: React.FC = ({ - + diff --git a/src/nextapp/components/products-list/dataset-input.tsx b/src/nextapp/components/products-list/dataset-input.tsx index aabfbce21..7a8cbfa9c 100644 --- a/src/nextapp/components/products-list/dataset-input.tsx +++ b/src/nextapp/components/products-list/dataset-input.tsx @@ -163,7 +163,7 @@ const DatasetInput: React.FC = ({ dataset }) => { ))} {isOpen && isSuccess && !results.length && ( - + No results found