Skip to content

Commit

Permalink
Merge branch 'feature/ns-to-gw' into feature/ns-to-gw-portal-labels
Browse files Browse the repository at this point in the history
  • Loading branch information
rustyjux committed Jul 5, 2024
1 parent 5e159c7 commit 99aedb1
Show file tree
Hide file tree
Showing 22 changed files with 213 additions and 127 deletions.
4 changes: 2 additions & 2 deletions e2e/cypress/tests/19-api-v3/07-endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ describe('Endpoints', () => {
names: ['testme', 'testme-dev', 'testme-test'],
hosts: [
'testme.api.gov.bc.ca',
'testme.api.dev.gov.bc.ca',
'testme.api.test.gov.bc.ca',
'testme.dev.api.gov.bc.ca',
'testme.test.api.gov.bc.ca',
'testme-api-gov-bc-ca.dev.api.gov.bc.ca',
'testme-api-gov-bc-ca.test.api.gov.bc.ca',
],
Expand Down
1 change: 0 additions & 1 deletion src/batch/feed-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ const transformations = {
export const putFeedWorker = async (context: any, req: any, res: any) => {
const entity = req.params['entity'];
assert.strictEqual(entity in metadata, true);
logger.info('putFeedWorker %s', entity);

const md = metadata[entity];
const refKey = md.refKey;
Expand Down
16 changes: 10 additions & 6 deletions src/controllers/v3/EndpointsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import {
} from 'tsoa';
import { KeystoneService } from '../ioc/keystoneInjector';
import { inject, injectable } from 'tsyringe';
import { getRecords, removeEmpty } from '../../batch/feed-worker';
import {
getRecords,
parseJsonString,
removeEmpty,
} from '../../batch/feed-worker';
import { GatewayRoute, GatewayService } from './types';

interface MatchList {
Expand All @@ -38,9 +42,9 @@ export class EndpointsController extends Controller {
@Request() request: any
): Promise<any> {
const ctx = this.keystone.sudo();
const records = await getRecords(ctx, 'GatewayRoute', 'allGatewayRoutes', [
'service',
]);
const records = (
await getRecords(ctx, 'GatewayRoute', 'allGatewayRoutes', ['service'])
).map((o) => parseJsonString(o, ['hosts']));

let counter = 0;
let matchHostList: MatchList;
Expand All @@ -67,8 +71,8 @@ export class EndpointsController extends Controller {
names: [`${serviceName}`, `${serviceName}-dev`, `${serviceName}-test`],
hosts: [
`${serviceName}.api.gov.bc.ca`,
`${serviceName}.api.dev.gov.bc.ca`,
`${serviceName}.api.test.gov.bc.ca`,
`${serviceName}.dev.api.gov.bc.ca`,
`${serviceName}.test.api.gov.bc.ca`,
`${serviceName}-api-gov-bc-ca.dev.api.gov.bc.ca`,
`${serviceName}-api-gov-bc-ca.test.api.gov.bc.ca`,
],
Expand Down
1 change: 1 addition & 0 deletions src/lists/extensions/Namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ module.exports = {
'Namespace.Manage',
'CredentialIssuer.Admin',
'GatewayConfig.Publish',
'Access.Manage',
]) {
await permissionApi.createPermission(
rset.id,
Expand Down
2 changes: 0 additions & 2 deletions src/nextapp/.env.local
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
NEXT_PUBLIC_APP_VERSION=0.0.0
NEXT_PUBLIC_APP_REVISION=000000000000000000000000
NEXT_PUBLIC_GRAFANA_URL=https://grafana-apps-gov-bc-ca.dev.api.gov.bc.ca
NEXT_PUBLIC_KUBE_CLUSTER=local
NEXT_PUBLIC_HELP_DESK_URL=https://dpdd.atlassian.net/servicedesk/customer/portal/1/group/2
NEXT_PUBLIC_HELP_CHAT_URL=https://chat.developer.gov.bc.ca/channel/aps-ops
Expand All @@ -9,4 +8,3 @@ NEXT_PUBLIC_HELP_API_DOCS_URL=/ds/api/v3/console/
NEXT_PUBLIC_HELP_SUPPORT_URL=https://dev.developer.gov.bc.ca/docs/default/component/aps-infra-platform-docs/
NEXT_PUBLIC_HELP_RELEASE_URL=https://dev.developer.gov.bc.ca/docs/default/component/aps-infra-platform-docs/reference/releases/
NEXT_PUBLIC_HELP_STATUS_URL=https://uptime.com/s/bcgov-dss

71 changes: 42 additions & 29 deletions src/nextapp/components/gateway-get-started/gateway-get-started.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ const GatewayGetStarted: React.FC = () => {
const QuickStartUrl = global?.helpLinks.helpSupportUrl + 'tutorials/quick-start'
const GwaInstallUrl = global?.helpLinks.helpSupportUrl + 'how-to/gwa-install'
const GwaCommandsUrl = global?.helpLinks.helpSupportUrl + 'resources/gwa-commands'
const apiRootUrl = global?.apiRootUrl
const configHost = apiRootUrl ? apiRootUrl.replace('https://', '').replace('http://', '') : ''

return (
<>
Expand All @@ -65,7 +67,7 @@ const GatewayGetStarted: React.FC = () => {
<Heading size="md">No gateways created yet</Heading>
</VStack>
<Heading size="lg">What is a gateway?</Heading>
<Text pt={6} pb={8}>
<Text pt={6} pb={6}>
A gateway acts as a central entry point for multiple APIs. Its main purpose is to facilitate communication and control the data flow between your APIs and those who consume them.
</Text>
<Text pt={0} pb={8}>
Expand Down Expand Up @@ -111,7 +113,7 @@ const GatewayGetStarted: React.FC = () => {
<Box>
<Heading size="lg">Steps to create and configure your first gateway</Heading>
<Text pt={6} pb={10}>
Follow these steps to create and configure your first gateway. For more details on how to set up an API, consult our API provider{' '}
Follow these steps to create and configure your first gateway. For a more detailed introduction to setting up an API, consult our{' '}
<Link
href={QuickStartUrl}
target="_blank"
Expand Down Expand Up @@ -215,7 +217,7 @@ const GatewayGetStarted: React.FC = () => {
<SmoothScrollLink
href={"#generate-config"}
>template</SmoothScrollLink>
{' '}to set up its configuration: services, routes and plugins.
{' '}to set up service and route configuration.
</Text>
</VStack>
</Box>
Expand Down Expand Up @@ -304,11 +306,13 @@ const GatewayGetStarted: React.FC = () => {
</Box>
<Box>
<Heading size="md" fontSize="18px" pt={10} pb={6}>Prepare your configuration</Heading>
<CliCommand
title='Use the test environment'
description='Configure the CLI to run against a test environment while you are getting familiarized with the API Services Portal.'
command='gwa config set host api-gov-bc-ca.test.api.gov.bc.ca'
/>
{global?.apiRootUrl && (
<CliCommand
title='Use the test environment'
description='Configure the CLI to run against a test environment while you are getting familiarized with the API Services Portal.'
command={`gwa config set host ${configHost}`}
/>
)}
<CliCommand
title='Log in'
description='Log in via device with your IDIR.'
Expand All @@ -325,7 +329,7 @@ const GatewayGetStarted: React.FC = () => {
id='generate-config'
title='Generate gateway configuration file'
description='Run this command to generate a basic gateway configuration YAML file.'
command='gwa generate-config --template quick-start'
command='gwa generate-config --template basic-service'
/>

<Heading size="md" fontSize="18px" pt={10} pb={6}>Apply configuration to your gateway</Heading>
Expand All @@ -340,31 +344,40 @@ const GatewayGetStarted: React.FC = () => {
title='Test your gateway'
description={
<>
Visit the{' '}
<Link
Get the URL for your newly published gateway service <Code>...api.gov.bc.ca</Code> using this command.
Visit the URL in a browser to see your API gateway in action.
</>
}
command='gwa status --hosts'
/>
<Box pt={10}>
<Heading size="md">Next steps</Heading>
<Text pt={6}>
Congratulations! You have set up your first gateway service, creating a custom route to your service through your API gateway.
</Text>
<Text pt={6}>
For a deeper introduction to the API Services Portal, follow the {' '}
<Link
href={QuickStartUrl}
target="_blank"
color="bc-link"
textDecor="underline"
>Your Products page</Link> to request credentials.
Then, get the URL for your newly published gateway service <Code>...api.gov.bc.ca</Code> using this command.
Pass the client ID and secret in a POST request to this URL to get a JWT token to access your API.
</>
}
command='gwa status -hosts'
/>
>Quick Start tutorial</Link>
{' '}to create a protected API.
</Text>
</Box>

<Heading size="md" fontSize="18px" pt={10} pb={6}>Help</Heading>
<CliCommand
title='Help'
description={
<>
If you are not sure about how to use a specific command, you can type <Code>--help</Code> after the
command's name to learn more about its usage and syntax.
</>
}
command='gwa <command> --help'
/>
<Heading size="md" fontSize="18px" pt={10} pb={6}>Help</Heading>
<CliCommand
title='Help'
description={
<>
If you are not sure about how to use a specific command, you can type <Code>--help</Code> after the
command's name to learn more about its usage and syntax.
</>
}
command='gwa <command> --help'
/>
</Box>
</Card>
</>
Expand Down
1 change: 1 addition & 0 deletions src/nextapp/components/no-gateway-redirect/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './no-gateway-redirect';
17 changes: 17 additions & 0 deletions src/nextapp/components/no-gateway-redirect/no-gateway-redirect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as React from 'react';
import { useRouter } from 'next/router';
import { useAuth } from '@/shared/services/auth';

const NoGatewayRedirect = () => {
const router = useRouter();
const { user } = useAuth();
const hasNamespace = !!user?.namespace;

React.useEffect(() => {
if (!hasNamespace) {
router.push('/manager/gateways/list');
}
}, [hasNamespace]);
};

export default NoGatewayRedirect;
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@ import {
} from '@chakra-ui/react';
import { FaClock, FaMinusCircle, FaCheckCircle } from 'react-icons/fa';

import { useGlobal } from '@/shared/services/global';

interface PublishingPopoverProps {
status: string;
}

const PublishingPopover: React.FC<PublishingPopoverProps> = ({ status }) => {
const global = useGlobal();
const DiscoveryUrl =
global?.helpLinks.helpSupportUrl +
'how-to/api-discovery/#enabling-for-discovery';

return (
<>
{status === 'disabled' && (
Expand All @@ -44,7 +51,7 @@ const PublishingPopover: React.FC<PublishingPopoverProps> = ({ status }) => {
directory any API contained in this gateway. Request publishing
permission by{' '}
<Link
href="https://developer.gov.bc.ca/docs/default/component/aps-infra-platform-docs/how-to/api-discovery/#enabling-for-discovery"
href={DiscoveryUrl}
target="_blank"
color="bc-link"
textDecor="underline"
Expand Down
6 changes: 5 additions & 1 deletion src/nextapp/pages/manager/activity/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import ActivityFilters from '@/components/activity-filters';
import { FaTimesCircle } from 'react-icons/fa';
import EmptyPane from '@/components/empty-pane';
import ActivityItem from '@/components/activity-item';
import NoGatewayRedirect from '@/components/no-gateway-redirect';

const timeZone = 'America/Vancouver';

Expand All @@ -50,6 +51,9 @@ interface FilterState {
}

const ActivityPage: React.FC = () => {
// Redirect to My Gateways page if no gateway selected
NoGatewayRedirect();

const breadcrumbs = useNamespaceBreadcrumbs([
{
text: 'Activity',
Expand Down Expand Up @@ -248,4 +252,4 @@ const query = gql`
blob
}
}
`;
`;
4 changes: 4 additions & 0 deletions src/nextapp/pages/manager/admin-access/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ import {
} from '@/components/namespace-access';
import { useAuth } from '@/shared/services/auth';
import { useNamespaceBreadcrumbs } from '@/shared/hooks';
import NoGatewayRedirect from '@/components/no-gateway-redirect';

const AccessRedirectPage: React.FC = () => {
// Redirect to My Gateways page if no gateway selected
NoGatewayRedirect();

const { user } = useAuth();
const breadcrumbs = useNamespaceBreadcrumbs([
{ href: '/manager/admin-access', text: 'Administration Access' },
Expand Down
4 changes: 4 additions & 0 deletions src/nextapp/pages/manager/authorization-profiles/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import type {
Mutation,
Query,
} from '@/shared/types/query.types';
import NoGatewayRedirect from '@/components/no-gateway-redirect';

export const getServerSideProps: GetServerSideProps = async (context) => {
const queryKey = 'authorizationProfiles';
Expand Down Expand Up @@ -69,6 +70,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
const AuthorizationProfiles: React.FC<
InferGetServerSidePropsType<typeof getServerSideProps>
> = ({ queryKey }) => {
// Redirect to My Gateways page if no gateway selected
NoGatewayRedirect();

const breadcrumbs = useNamespaceBreadcrumbs([
{
href: '/manager/authorization-profiles',
Expand Down
4 changes: 4 additions & 0 deletions src/nextapp/pages/manager/consumers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import GrantAccessDialog from '@/components/access-request/grant-access-dialog';
import ConsumerFilters from '@/components/consumer-filters';
import AccessRequestsList from '@/components/access-request/access-requests-list';
import { useNamespaceBreadcrumbs } from '@/shared/hooks';
import NoGatewayRedirect from '@/components/no-gateway-redirect';

const sortDate = new Intl.DateTimeFormat('en-ca', { dateStyle: 'short' });

Expand Down Expand Up @@ -76,6 +77,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
const ConsumersPage: React.FC<
InferGetServerSidePropsType<typeof getServerSideProps>
> = ({ queryKey }) => {
// Redirect to My Gateways page if no gateway selected
NoGatewayRedirect();

const toast = useToast();
const breadcrumbs = useNamespaceBreadcrumbs([{ text: 'Consumers' }]);
const client = useQueryClient();
Expand Down
12 changes: 4 additions & 8 deletions src/nextapp/pages/manager/gateways/detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import useCurrentNamespace from '@/shared/hooks/use-current-namespace';
import { useGlobal } from '@/shared/services/global';
import EditNamespaceDisplayName from '@/components/edit-display-name';
import { useNamespaceBreadcrumbs } from '@/shared/hooks';
import NoGatewayRedirect from '@/components/no-gateway-redirect';

const actions = [
{
Expand Down Expand Up @@ -120,6 +121,9 @@ const secondaryActions = [
];

const NamespacesPage: React.FC = () => {
// Redirect to My Gateways page if no gateway selected
NoGatewayRedirect();

const { user } = useAuth();
const breadcrumbs = useNamespaceBreadcrumbs();
const hasNamespace = !!user?.namespace;
Expand Down Expand Up @@ -155,14 +159,6 @@ const NamespacesPage: React.FC = () => {
text: 'Your Organization and Business Unit will appear here',
};
}, [namespace]);

// Redirect to My Gateways page if no gateway selected
React.useEffect(() => {
if (!hasNamespace) {
router.push('/manager/gateways/list');
}
}, [hasNamespace]);

const handleDelete = React.useCallback(async () => {
if (user?.namespace) {
try {
Expand Down
3 changes: 1 addition & 2 deletions src/nextapp/pages/manager/gateways/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Container } from '@chakra-ui/react';
import { useApi } from '@/shared/services/api';
import { useAuth } from '@/shared/services/auth';
import PageHeader from '@/components/page-header';
import { has } from 'lodash';

const GatewaysHome: React.FC = () => {
const { data, isSuccess, isError } = useApi(
Expand All @@ -21,7 +20,7 @@ const GatewaysHome: React.FC = () => {

React.useEffect(() => {
if (hasNamespace) {
router.push('/manager/gateways/detail');
router.push('/manager/gateways/list');
} else {
if (isSuccess && data.allNamespaces.length === 0) {
router.push('/manager/gateways/get-started');
Expand Down
Loading

0 comments on commit 99aedb1

Please sign in to comment.