Skip to content

Commit

Permalink
UX code to support Event Stream Service configuration
Browse files Browse the repository at this point in the history
Signed-off-by: Jason Sherman <[email protected]>
  • Loading branch information
usingtechnology committed Aug 15, 2024
1 parent df51bba commit c66b5cd
Show file tree
Hide file tree
Showing 23 changed files with 640 additions and 621 deletions.
11 changes: 11 additions & 0 deletions .devcontainer/chefs_local/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@
"proxy": "5fb2054478353fd8d514056d1745b3a9eef066deadda4b90967af7ca65ce6505"
}
},
"features": {
"eventStreamService": false
},
"eventStreamService": {
"servers": "localhost:4222,localhost:4223,localhost:4224",
"streamName": "CHEFS",
"source": "chefs",
"domain": "forms",
"username": "chefs",
"password": "password"
},
"serviceClient": {
"commonServices": {
"ches": {
Expand Down
8 changes: 8 additions & 0 deletions app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ apiRouter.use('/config', (_req, res, next) => {
const uploads = config.get('files.uploads');
const features = config.get('features');
const feConfig = { ...frontend, uploads: uploads, features: features };
if (featureFlags.eventStreamService) {
let ess = config.util.cloneDeep(config.get('eventStreamService'));
delete ess['username'];
delete ess['password'];
feConfig['eventStreamService'] = {
...ess,
};
}
res.status(200).json(feConfig);
} catch (err) {
next(err);
Expand Down
1 change: 1 addition & 0 deletions app/config/custom-environment-variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"eventStreamService": {
"servers": "EVENTSTREAMSERVICE_SERVERS",
"streamName": "EVENTSTREAMSERVICE_STREAMNAME",
"source": "EVENTSTREAMSERVICE_SOURCE",
"domain": "EVENTSTREAMSERVICE_DOMAIN",
"username": "EVENTSTREAMSERVICE_USERNAME",
"password": "EVENTSTREAMSERVICE_PASSWORD"
Expand Down
1 change: 1 addition & 0 deletions app/config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"eventStreamService": {
"servers": "localhost:4222,localhost:4223,localhost:4224",
"streamName": "CHEFS",
"source": "chefs",
"domain": "forms",
"username": "chefs",
"password": "password"
Expand Down
1 change: 1 addition & 0 deletions app/frontend/src/components/designer/FormDesigner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ export default {
apiIntegration: this.form.apiIntegration,
useCase: this.form.useCase,
labels: this.form.labels,
eventStreamConfig: this.form.eventStreamConfig,
});
// update user labels with any new added labels
if (
Expand Down
11 changes: 11 additions & 0 deletions app/frontend/src/components/designer/FormSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import FormGeneralSettings from '~/components/designer/settings/FormGeneralSetti
import FormFunctionalitySettings from '~/components/designer/settings/FormFunctionalitySettings.vue';
import FormScheduleSettings from '~/components/designer/settings/FormScheduleSettings.vue';
import FormSubmissionSettings from '~/components/designer/settings/FormSubmissionSettings.vue';
import FormEventStreamSettings from '~/components/designer/settings/FormEventStreamSettings.vue';
import { useAppStore } from '~/store/app';
import { useFormStore } from '~/store/form';
export default {
Expand All @@ -14,6 +17,7 @@ export default {
FormFunctionalitySettings,
FormScheduleSettings,
FormSubmissionSettings,
FormEventStreamSettings,
},
props: {
disabled: {
Expand All @@ -24,6 +28,10 @@ export default {
computed: {
...mapWritableState(useFormStore, ['form']),
...mapState(useFormStore, ['isFormPublished', 'isRTL']),
eventStreamEnabled() {
const appStore = useAppStore();
return appStore.config?.features?.eventStreamService;
},
},
};
</script>
Expand All @@ -46,6 +54,9 @@ export default {
<v-col v-if="form.schedule.enabled && isFormPublished" cols="12" md="6">
<FormScheduleSettings />
</v-col>
<v-col v-if="eventStreamEnabled">
<FormEventStreamSettings :disabled="disabled" />
</v-col>
</v-row>
</v-container>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
<script setup>
import moment from 'moment';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { onMounted, ref } from 'vue';
import { useAppStore } from '~/store/app';
import { useFormStore } from '~/store/form';
import { useNotificationStore } from '~/store/notification';
import { encryptionKeyService } from '~/services';
const { t, locale } = useI18n({ useScope: 'global' });
const appStore = useAppStore();
const formStore = useFormStore();
const notificationStore = useNotificationStore();
const { form, isRTL } = storeToRefs(formStore);
const loading = ref(true);
const algorithms = ref([]);
const techdocsLink =
'https://developer.gov.bc.ca/docs/default/component/chefs-techdocs/Capabilities/Functionalities';
onMounted(async () => {
await fetchAlgorithms();
});
async function fetchAlgorithms() {
loading.value = true;
try {
algorithms.value = [];
const result = await encryptionKeyService.listEncryptionAlgorithms();
algorithms.value = result.data;
} catch (e) {
notificationStore.addNotification({
text: t('trans.formSettings.fetchEncryptionAlgorithmListError'),
consoleError: t('trans.formSettings.fetchEncryptionAlgorithmListError', {
error: e.message,
}),
});
}
}
async function generateKey() {
let generatedKey;
// when we have more algorithms, move this into some kind of service...
if (form.value.eventStreamConfig.encryptionKey.algorithm === 'aes-256-gcm') {
const data = crypto.getRandomValues(new Uint8Array(16));
const hashBuffer = await window.crypto.subtle.digest('SHA-256', data);
generatedKey = Array.from(new Uint8Array(hashBuffer))
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
}
form.value.eventStreamConfig.encryptionKey.key = generatedKey;
}
/* c8 ignore start */
// eslint-disable-next-line no-unused-vars
const encryptionKeyRules = ref([
(v) => {
if (form.value.eventStreamConfig.enablePrivateStream) {
return !!v || t('trans.formSettings.encryptionKeyReq');
}
},
]);
/* c8 ignore stop */
defineExpose({
fetchAlgorithms,
generateKey,
});
</script>

<template>
<BasePanel class="fill-height">
<template #title
><span :lang="locale">{{
$t('trans.formSettings.eventStreamTitle')
}}</span></template
>

<div class="mb-6 ml-1 font-weight-bold" :lang="locale">
{{ $t('trans.formSettings.eventStreamMessage') }}
<v-tooltip location="bottom">
<template #activator="{ props }">
<v-icon
color="primary"
class="mx-1"
:class="{ 'mx-1': isRTL }"
v-bind="props"
icon="mdi:mdi-help-circle-outline"
></v-icon>
</template>
<span>
<a
:href="techdocsLink"
class="preview_info_link_field_white"
target="_blank"
:hreflang="locale"
>
{{ $t('trans.formSettings.learnMore') }}
<v-icon icon="mdi:mdi-arrow-top-right-bold-box-outline"></v-icon>
</a>
</span>
</v-tooltip>
</div>
<div class="mb-6 ml-1" :lang="locale">
<h3>{{ $t('trans.formSettings.natsConfiguration') }}</h3>
<div class="ml-4">
<span>
<span :lang="locale" class="font-weight-bold"
>{{ $t('trans.formSettings.serversLabel') }}:
</span>
<span class="ml-2">{{
appStore.config?.eventStreamService?.servers
}}</span>
</span>
<br />
<span>
<span :lang="locale" class="font-weight-bold"
>{{ $t('trans.formSettings.streamNameLabel') }}:
</span>
<span class="ml-2">{{
appStore.config?.eventStreamService?.streamName
}}</span>
</span>
<br />
<span>
<span :lang="locale" class="font-weight-bold"
>{{ $t('trans.formSettings.sourceLabel') }}:
</span>
<span class="ml-2">{{
appStore.config?.eventStreamService?.source
}}</span>
</span>
<br />
<span>
<span :lang="locale" class="font-weight-bold"
>{{ $t('trans.formSettings.domainLabel') }}:
</span>
<span class="ml-2">{{
appStore.config?.eventStreamService?.domain
}}</span>
</span>
</div>
</div>
<div class="mt-6 ml-1" :lang="locale">
<h3>{{ $t('trans.formSettings.publishConfiguration') }}</h3>
</div>
<v-row class="pl-6 m-0">
<v-col cols="12" md="6" class="pl-0 pr-0 pb-0">
<v-checkbox
v-model="form.eventStreamConfig.enablePublicStream"
hide-details="auto"
class="my-0"
>
<template #label>
<span
:class="{ 'mr-2': isRTL }"
:lang="locale"
v-html="$t('trans.formSettings.enablePublicStream')"
></span>
</template>
</v-checkbox>
</v-col>
</v-row>
<v-row class="pl-6 m-0">
<v-col cols="12" md="6" class="pl-0 pr-0 pb-0">
<v-checkbox
v-model="form.eventStreamConfig.enablePrivateStream"
hide-details="auto"
class="my-0"
>
<template #label>
<span
:class="{ 'mr-2': isRTL }"
:lang="locale"
v-html="$t('trans.formSettings.enablePrivateStream')"
></span>
</template>
</v-checkbox>
</v-col>
<v-col cols="12" md="6" class="pl-0 pr-0 pb-0"> </v-col>
</v-row>
<v-expand-transition>
<v-row v-if="form.eventStreamConfig.enablePrivateStream" class="pl-6 m-0">
<v-col cols="12" md="8" class="pl-0 pr-0 pb-0">
<v-select
v-model="form.eventStreamConfig.encryptionKey.algorithm"
:items="algorithms"
item-title="display"
item-value="code"
:label="$t('trans.formSettings.encryptionKeyAlgorithm')"
density="compact"
solid
variant="outlined"
:lang="locale"
:rules="encryptionKeyRules"
></v-select
></v-col>
<v-col cols="12" md="8" class="pl-0 pr-0 pb-0">
<v-text-field
v-model="form.eventStreamConfig.encryptionKey.key"
density="compact"
solid
variant="outlined"
:label="$t('trans.formSettings.encryptionKey')"
:lang="locale"
:rules="encryptionKeyRules"
/>
</v-col>
<v-col cols="12" md="4" class="pl-4 pr-0 pb-0 pt-4">
<v-tooltip location="bottom">
<template #activator="{ props }">
<v-btn
color="primary"
:disabled="!form.eventStreamConfig.enablePrivateStream"
v-bind="props"
size="x-small"
density="default"
:icon="'mdi:mdi-auto-fix'"
:title="$t('trans.formSettings.encryptionKeyGenerate')"
@click="generateKey"
/>
</template>
<span :lang="locale">{{
$t('trans.formSettings.encryptionKeyGenerate')
}}</span>
</v-tooltip>
<BaseCopyToClipboard
:disabled="!form.eventStreamConfig.encryptionKey.key"
class="mx-2"
:text-to-copy="form.eventStreamConfig.encryptionKey.key"
:snack-bar-text="$t('trans.formSettings.encryptionKeyCopySnackbar')"
:tooltip-text="$t('trans.formSettings.encryptionKeyCopyTooltip')"
:lang="locale"
/>
</v-col>
</v-row>
</v-expand-transition>
<v-row class="pl-6 m-0">
<v-col cols="12" class="pl-0 pr-0 pb-0">
<span>
<span :lang="locale" class="font-weight-bold"
>{{ $t('trans.formSettings.eventStreamUpdatedBy') }}:
</span>
<span
>{{ form.eventStreamConfig.updatedBy }} @
{{
moment(
new Date(form.eventStreamConfig.updatedAt),
'YYYY-MM-DD HH:MM:SS'
)
}}</span
>
</span>
</v-col>
<v-col cols="12" class="pl-0 pr-0 pb-0">
<span v-if="form.eventStreamConfig.encryptionKey.updatedBy">
<span :lang="locale" class="font-weight-bold"
>{{ $t('trans.formSettings.encryptionKeyUpdatedBy') }}:
</span>
<span
>{{ form.eventStreamConfig.encryptionKey.updatedBy }} @
{{
moment(
new Date(form.eventStreamConfig.encryptionKey.updatedAt),
'YYYY-MM-DD HH:MM:SS'
)
}}</span
>
</span>
</v-col>
</v-row>
</BasePanel>
</template>
Loading

0 comments on commit c66b5cd

Please sign in to comment.