Skip to content

Commit

Permalink
Identity Provider from hardcode to config
Browse files Browse the repository at this point in the history
Signed-off-by: Jason Sherman <[email protected]>
  • Loading branch information
usingtechnology committed Jan 25, 2024
1 parent 9515042 commit c0c81a0
Show file tree
Hide file tree
Showing 36 changed files with 534 additions and 207 deletions.
33 changes: 33 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ The `.devcontainer` folder contains the `devcontainer.json` file which defines t

In order to run CHEFS you require Keycloak (configured), Postgresql (seeded) and the CHEFS backend/API and frontend/UX. Previously, this was a series of downloads and configuration updates and numerous commands to run. See `.devcontainer/chefs_local` files.

**NODE_CONFIG_DIR** to simplify loading a default configuration to the CHEFS infrastructure (Keycloak, Postgresql, etc), we set an environment variable [`NODE_CONFIG_DIR`](https://github.com/node-config/node-config/wiki/Environment-Variables#node_config_dir). This supercedes the files found under `app/config`. Running node apps and commands (ex. knex, launch configurations) will use this environment variable and load configuration from `.devcontainer/chefs_local`.

Also included are convenient launch tasks to run and debug CHEFS.

## Open CHEFS in the devcontainer
Expand Down Expand Up @@ -65,6 +67,37 @@ When the devcontainer is built, it copies `.devcontainer/chefs_local/local.json.
## Formio Components
If you are developing the formio components, you should build and redeploy them before running your local debug instances of CHEFS. Use tasks `Components build` and `Components Deploy`.

## KNEX - Database tools
[knex](https://knexjs.org) is installed globally and should be run from the `/app` directory where the knex configuration is located. Use knex to stub out migrations or to rollback migrations as you are developing.

### create a migration file
This will create a stub file with a timestamp. You will populate the up and down methods to add/update/delete database objects.

```
cd app
knex migrate:make my_new_migration_script
> Created Migration: /workspaces/common-hosted-form-service/app/src/db/migrations/20240119172630_my_new_migration_script.js
```

### rollback previous migration
When developing your migrations, you may find it useful to run the migration and roll it back if it isn't exactly what you expect to happen.

#### run the migration(s)
```
cd app
knex migrate:latest
> Batch 2 run: 1 migrations
```

#### rollback the migration(s)
```
cd app
knex migrate:rollback
> Batch 2 rolled back: 1 migrations
```

Please review the [knex](https://knexjs.org) for more detail and how to leverage the tool.

## Troubleshooting
All development machines are unique and here we will document problems that have been encountered and how to fix them.

Expand Down
25 changes: 25 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,35 @@
}
},

"customizations": {
"vscode": {
"extensions": [
"cweijan.vscode-postgresql-client2",
"Vue.volar",
"esbenp.prettier-vscode"
],
"settings": {
"database-client.telemetry.usesOnlineServices": false,
"editor.defaultFormatter": null,
"editor.formatOnSave": false,
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"prettier.configPath": "${containerWorkspaceFolder}/app/frontend/.prettierrc",
"prettier.documentSelectors": ["${containerWorkspaceFolder}/app/frontend/**/*.{js,vue}"]
}
}
},

"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},

"containerEnv": {
"NODE_CONFIG_DIR": "${containerWorkspaceFolder}/.devcontainer/chefs_local"
},

// Use this environment variable if you need to bind mount your local source code into a new container.
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
Expand Down
2 changes: 2 additions & 0 deletions .devcontainer/post-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set -ex
WORKSPACE_DIR=$(pwd)
CHEFS_LOCAL_DIR=${WORKSPACE_DIR}/.devcontainer/chefs_local

npm install knex -g

# install app libraries, prepare for app development and debugging...
cd app
npm install
Expand Down
4 changes: 1 addition & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
"runtimeArgs": ["run", "serve"],
"runtimeExecutable": "npm",
"type": "node",
"env": {
"NODE_CONFIG_DIR": "${workspaceFolder}/.devcontainer/chefs_local",
}
"env": {}
},
{
"cwd": "${workspaceFolder}/app/frontend",
Expand Down
6 changes: 4 additions & 2 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,16 @@
{
"label": "chefs_local up",
"type": "shell",
"command": "docker-compose -f ${workspaceFolder}/.devcontainer/chefs_local/docker-compose.yml up -d",
"command": "docker-compose",
"args": ["-f", "${workspaceFolder}/.devcontainer/chefs_local/docker-compose.yml", "up", "-d"],
"isBackground": true,
"problemMatcher": [],
},
{
"label": "chefs_local down",
"type": "shell",
"command": "docker-compose -f ${workspaceFolder}/.devcontainer/chefs_local/docker-compose.yml down",
"command": "docker-compose",
"args": ["-f", "${workspaceFolder}/.devcontainer/chefs_local/docker-compose.yml", "down"],
"isBackground": true,
"problemMatcher": [],
},
Expand Down
14 changes: 11 additions & 3 deletions app/frontend/src/components/base/BaseSecure.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { mapActions, mapState } from 'pinia';
import { useAuthStore } from '~/store/auth';
import { useFormStore } from '~/store/form';
import { useIdpStore } from '~/store/identityProviders';
export default {
props: {
Expand All @@ -13,6 +14,10 @@ export default {
type: Array,
default: undefined,
},
permission: {
type: String,
default: undefined,
},
},
computed: {
...mapState(useAuthStore, [
Expand All @@ -23,6 +28,7 @@ export default {
'ready',
]),
...mapState(useFormStore, ['lang']),
...mapState(useIdpStore, ['hasPermission']),
mailToLink() {
return `mailto:${
import.meta.env.VITE_CONTACT
Expand All @@ -34,7 +40,9 @@ export default {
return import.meta.env.VITE_CONTACT;
},
},
methods: mapActions(useAuthStore, ['login']),
methods: {
...mapActions(useAuthStore, ['login']),
},
};
</script>

Expand All @@ -50,7 +58,7 @@ export default {
</p>
</div>
<div
v-else-if="idp && idp.length > 0 && !idp.includes(identityProvider)"
v-else-if="permission && !hasPermission(identityProvider, permission)"
class="text-center"
>
<h1 class="my-8" :lang="lang">
Expand All @@ -59,7 +67,7 @@ export default {
<p :lang="lang">
{{
$t('trans.baseSecure.403ErrorMsg', {
idp: idp,
idp: permission,
})
}}
</p>
Expand Down
9 changes: 6 additions & 3 deletions app/frontend/src/components/base/BaseStepper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { mapState } from 'pinia';
import BaseSecure from '~/components/base/BaseSecure.vue';
import { useFormStore } from '~/store/form';
import { IdentityProviders } from '~/utils/constants';
import { AppPermissions } from '~/utils/constants';
export default {
name: 'BaseStepper',
Expand All @@ -17,7 +17,7 @@ export default {
},
computed: {
...mapState(useFormStore, ['lang', 'isRTL']),
IDP: () => IdentityProviders,
APP_PERMS: () => AppPermissions,
creatorStep() {
return this.step;
},
Expand All @@ -26,7 +26,10 @@ export default {
</script>

<template>
<BaseSecure :idp="[IDP.IDIR]" :class="{ 'dir-rtl': isRTL }">
<BaseSecure
:permission="APP_PERMS.VIEWS_FORM_STEPPER"
:class="{ 'dir-rtl': isRTL }"
>
<v-stepper
v-model="creatorStep"
alt-labels
Expand Down
5 changes: 3 additions & 2 deletions app/frontend/src/components/bcgov/BCGovNavBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { mapState } from 'pinia';
import { useAuthStore } from '~/store/auth';
import { useFormStore } from '~/store/form';
import { IdentityProviders } from '~/utils/constants';
import { useIdpStore } from '~/store/identityProviders';
export default {
data() {
Expand All @@ -13,12 +13,13 @@ export default {
computed: {
...mapState(useAuthStore, ['authenticated', 'isAdmin', 'identityProvider']),
...mapState(useFormStore, ['lang']),
...mapState(useIdpStore, ['isPrimary']),
hideNavBar() {
// hide nav bar if user is on form submitter page
return this.$route && this.$route.meta && this.$route.meta.formSubmitMode;
},
hasPrivileges() {
return this.identityProvider === IdentityProviders.IDIR;
return this.isPrimary(this.identityProvider);
},
},
};
Expand Down
5 changes: 3 additions & 2 deletions app/frontend/src/components/designer/FormsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { mapActions, mapState } from 'pinia';
import { i18n } from '~/internationalization';
import { useAuthStore } from '~/store/auth';
import { useFormStore } from '~/store/form';
import { useIdpStore } from '~/store/identityProviders';
import BaseDialog from '~/components/base/BaseDialog.vue';
import { IdentityProviders } from '~/utils/constants';
import { checkFormManage, checkSubmissionView } from '~/utils/permissionUtils';
export default {
Expand All @@ -25,6 +25,7 @@ export default {
computed: {
...mapState(useFormStore, ['formList', 'isRTL', 'lang']),
...mapState(useAuthStore, ['user']),
...mapState(useIdpStore, ['isPrimary']),
headers() {
return [
{
Expand All @@ -44,7 +45,7 @@ export default {
];
},
canCreateForm() {
return this.user.idp === IdentityProviders.IDIR;
return this.isPrimary(this.user.idp);
},
filteredFormList() {
return this.formList.filter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { nextTick } from 'vue';
import BasePanel from '~/components/base/BasePanel.vue';
import BaseInfoCard from '~/components/base/BaseInfoCard.vue';
import { IdentityMode, IdentityProviders } from '~/utils/constants';
import { IdentityMode } from '~/utils/constants';
import { useFormStore } from '~/store/form';
import { useIdpStore } from '~/store/identityProviders';
export default {
components: {
Expand All @@ -28,13 +29,11 @@ export default {
},
computed: {
...mapState(useFormStore, ['isRTL', 'lang']),
...mapState(useIdpStore, ['loginButtons', 'hasFormAccessSettings']),
...mapWritableState(useFormStore, ['form']),
ID_MODE() {
return IdentityMode;
},
ID_PROVIDERS() {
return IdentityProviders;
},
},
methods: {
userTypeChanged() {
Expand Down Expand Up @@ -128,31 +127,20 @@ export default {
class="my-0"
@update:model-value="updateLoginType"
>
<v-radio class="mx-2" :value="ID_PROVIDERS.IDIR">
<template #label>
<span :class="{ 'mr-2': isRTL }"> IDIR </span>
</template>
</v-radio>
<v-radio class="mx-2" :value="ID_PROVIDERS.BCEIDBASIC">
<template #label>
<span :class="{ 'mr-2': isRTL }"> Basic BCeID </span>
</template>
</v-radio>
<v-radio class="mx-2" :value="ID_PROVIDERS.BCEIDBUSINESS">
<v-radio
v-for="button in loginButtons"
:key="button.type"
:value="button.type"
class="mx-2"
>
<template #label>
<span :class="{ 'mr-2': isRTL }"> Business BCeID </span>
<span :class="{ 'mr-2': isRTL }"> {{ button.label }} </span>
</template>
</v-radio>
<!-- Mandatory BCeID process notification -->
<v-expand-transition>
<BaseInfoCard
v-if="
idpType &&
[
ID_PROVIDERS.BCEIDBASIC,
ID_PROVIDERS.BCEIDBUSINESS,
].includes(idpType)
"
v-if="hasFormAccessSettings(idpType, 'idim')"
class="mr-4"
:class="{ 'dir-rtl': isRTL }"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { mapState, mapWritableState } from 'pinia';
import BasePanel from '~/components/base/BasePanel.vue';
import { useAuthStore } from '~/store/auth';
import { useFormStore } from '~/store/form';
import { IdentityMode, IdentityProviders } from '~/utils/constants';
import { useIdpStore } from '~/store/identityProviders';
import { IdentityMode } from '~/utils/constants';
export default {
components: {
Expand All @@ -24,12 +25,13 @@ export default {
computed: {
...mapState(useAuthStore, ['identityProvider']),
...mapState(useFormStore, ['isFormPublished', 'isRTL', 'lang']),
...mapState(useIdpStore, ['isPrimary']),
...mapWritableState(useFormStore, ['form']),
ID_MODE() {
return IdentityMode;
},
idirUser() {
return this.identityProvider === IdentityProviders.IDIR;
primaryIdpUser() {
return this.isPrimary(this.identityProvider);
},
},
methods: {
Expand Down Expand Up @@ -225,7 +227,7 @@ export default {
v-model="form.subscribe.enabled"
hide-details="auto"
class="my-0"
:disabled="idirUser === false || !isFormPublished"
:disabled="primaryIdpUser === false || !isFormPublished"
>
<template #label>
<div :class="{ 'mr-2': isRTL }">
Expand Down
Loading

0 comments on commit c0c81a0

Please sign in to comment.