Skip to content

Commit

Permalink
Merge pull request #914 from bcgov/feature/innkeeperSettings
Browse files Browse the repository at this point in the history
Expose server settings to Innkeeper UI and Tenant UI via plugin routes
  • Loading branch information
loneil authored Nov 16, 2023
2 parents 56f43b1 + dcb4c2c commit 85ae68a
Show file tree
Hide file tree
Showing 36 changed files with 967 additions and 229 deletions.
1 change: 0 additions & 1 deletion charts/traction/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ kubectl delete secret,pvc --selector "app.kubernetes.io/instance"=my-release
| `ui.ux.copyright` | | `""` |
| `ui.ux.owner` | | `""` |
| `ui.ux.coverImageCopyright` | | `Photo by Kristoffer Fredriksson on StockSnap` |
| `ui.ariesDetails.ledgerDescription` | Ledger description | `bcovrin-test` |
| `ui.oidc.showInnkeeperAdminLogin` | Show Innkeeper Admin Login | `true` |
| `ui.oidc.showWritableComponents` | Show ledger-write UI components | `true` |
| `ui.oidc.active` | Enable OIDC authentication | `true` |
Expand Down
1 change: 0 additions & 1 deletion charts/traction/templates/ui/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ metadata:
labels:
{{- include "tenant-ui.labels" . | nindent 4 }}
data:
FRONTEND_ARIES_LEDGER_DESCRIPTION: {{ .Values.ui.ariesDetails.ledgerDescription | quote }}
FRONTEND_INNKEEPER_OIDC_ACTIVE: {{ .Values.ui.oidc.active | quote }}
FRONTEND_INNKEEPER_OIDC_AUTHORITY: {{ .Values.ui.oidc.authority | quote }}
FRONTEND_INNKEEPER_OIDC_CLIENT: {{ .Values.ui.oidc.client | quote }}
Expand Down
4 changes: 0 additions & 4 deletions charts/traction/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -622,10 +622,6 @@ ui:
## @param ui.ux.infoBanner.showMessage Show the info banner <boolean>
showMessage: false

ariesDetails:
## @param ui.ariesDetails.ledgerDescription Ledger description
ledgerDescription: "bcovrin-test"

## Backend Configuration
##
oidc:
Expand Down
2 changes: 0 additions & 2 deletions deploy/traction/values-development.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ ui:
]
}
}
ariesDetails:
ledgerDescription: "bcovrin-test"
smtp:
server: apps.smtp.gov.bc.ca
port: 25
Expand Down
2 changes: 0 additions & 2 deletions deploy/traction/values-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ ui:
]
}
}
ariesDetails:
ledgerDescription: "bcovrin-test"
smtp:
server: apps.smtp.gov.bc.ca
port: 25
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use_kwargs,
)
from aries_cloudagent.admin.request_context import AdminRequestContext
from aries_cloudagent.admin.server import AdminConfigSchema
from aries_cloudagent.messaging.models.base import BaseModelError
from aries_cloudagent.messaging.models.openapi import OpenAPISchema
from aries_cloudagent.messaging.valid import JSONWebToken, UUIDFour
Expand All @@ -21,6 +22,7 @@
from aries_cloudagent.multitenant.base import BaseMultitenantManager
from aries_cloudagent.multitenant.error import WalletKeyMissingError
from aries_cloudagent.storage.error import StorageError, StorageNotFoundError
from aries_cloudagent.version import __version__
from aries_cloudagent.wallet.error import WalletSettingsError
from aries_cloudagent.wallet.models.wallet_record import WalletRecord
from marshmallow import fields, validate
Expand Down Expand Up @@ -917,6 +919,41 @@ async def innkeeper_authentications_api_delete(request: web.BaseRequest):
return web.json_response({"success": result})


@docs(tags=[SWAGGER_CATEGORY], summary="Fetch the server configuration")
@response_schema(AdminConfigSchema(), 200, description="")
@innkeeper_only
@error_handler
async def innkeeper_config_handler(request: web.BaseRequest):
context: AdminRequestContext = request["context"]
# use base/root profile for server config, use Tenant Manager profile
# this is to not get the Innkeeper tenant's config, but the server cfg
mgr = context.inject(TenantManager)
profile = mgr.profile

config = {
key: (
profile.context.settings[key]
)
for key in profile.context.settings
if key
not in [
"admin.admin_api_key",
"multitenant.jwt_secret",
"wallet.key",
"wallet.rekey",
"wallet.seed",
"wallet.storage_creds",
]
}
try:
del config["plugin_config"]["traction_innkeeper"]["innkeeper_wallet"]["wallet_key"]
except KeyError as e:
LOGGER.warn(f"The key to be removed: '{e.args[0]}' is missing from the dictionary.")
config["version"] = __version__

return web.json_response({"config": config})


async def register(app: web.Application):
"""Register routes."""
LOGGER.info("> registering routes")
Expand Down Expand Up @@ -987,6 +1024,11 @@ async def register(app: web.Application):
"/innkeeper/authentications/api/{tenant_authentication_api_id}",
innkeeper_authentications_api_delete,
),
web.get(
"/innkeeper/server/status/config",
innkeeper_config_handler,
allow_head=False,
),
]
)
LOGGER.info("< registering routes")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
request_schema,
)
from aries_cloudagent.admin.request_context import AdminRequestContext
from aries_cloudagent.admin.server import AdminConfigSchema
from aries_cloudagent.messaging.models.openapi import OpenAPISchema
from aries_cloudagent.multitenant.admin.routes import (
format_wallet_record,
Expand All @@ -16,6 +17,7 @@
)
from aries_cloudagent.multitenant.base import BaseMultitenantManager
from aries_cloudagent.storage.error import StorageNotFoundError
from aries_cloudagent.version import __version__
from aries_cloudagent.wallet.models.wallet_record import (
WalletRecordSchema,
WalletRecord,
Expand Down Expand Up @@ -352,6 +354,55 @@ async def tenant_api_key_delete(request: web.BaseRequest):
return web.json_response({"success": result})


@docs(tags=[SWAGGER_CATEGORY], summary="Fetch the server configuration")
@response_schema(AdminConfigSchema(), 200, description="")
@error_handler
async def tenant_server_config_handler(request: web.BaseRequest):
context: AdminRequestContext = request["context"]
# use base/root profile for server config, use Tenant Manager profile
# this is to not get the Innkeeper tenant's config, but the server cfg
mgr = context.inject(TenantManager)
profile = mgr.profile

config = {
k: (
profile.context.settings[k]
)
for k in profile.context.settings
if k
not in [
"default_label",
"admin.admin_api_key",
"admin.admin_insecure_mode",
"admin.enabled",
"admin.host",
"admin.port",
"admin.webhook_urls",
"admin.admin_client_max_request_size",
"multitenant.jwt_secret",
"wallet.key",
"wallet.name",
"multitenant.wallet_name",
"wallet.storage_type",
"wallet.storage_config",
"wallet.rekey",
"wallet.seed",
"wallet.storage_creds",
]
}
try:
del config["plugin_config"]["traction_innkeeper"]["innkeeper_wallet"]
config["config"]["ledger.ledger_config_list"] = [
{k: v for k, v in d.items() if k != "genesis_transactions"}
for d in config["config"]["ledger.ledger_config_list"]
]
except KeyError as e:
LOGGER.warn(f"The key to be removed: '{e.args[0]}' is missing from the dictionary.")
config["version"] = __version__

return web.json_response({"config": config})


async def register(app: web.Application):
"""Register routes."""
LOGGER.info("> registering routes")
Expand All @@ -376,6 +427,11 @@ async def register(app: web.Application):
"/tenant/authentications/api/{tenant_authentication_api_id}",
tenant_api_key_delete,
),
web.get(
"/tenant/server/status/config",
tenant_server_config_handler,
allow_head=False
),
]
)
LOGGER.info("< registering routes")
Expand Down
6 changes: 0 additions & 6 deletions services/tenant-ui/config/custom-environment-variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@
"messageLevel": "UX_INFO_BANNER_MESSAGE_LEVEL",
"showMessage": "UX_INFO_BANNER_SHOW_MESSAGE"
}
},
"ariesDetails": {
"acapyVersion": "FRONTEND_ACAPY_VERSION_DISPLAY",
"ledgerName": "FRONTEND_ARIES_LEDGER_DESCRIPTION",
"ledgerBrowser": "ACAPY_LEDGER_BROWSER_URL",
"tailsServer": "ACAPY_TAILS_BASE_URL"
}
},
"image": {
Expand Down
6 changes: 0 additions & 6 deletions services/tenant-ui/config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@
"messageLevel": "info",
"showMessage": false
}
},
"ariesDetails": {
"acapyVersion": "0.10.3",
"ledgerName": "bcovrin-test",
"ledgerBrowser": "http://test.bcovrin.vonx.io",
"tailsServer": "https://tails-test.vonx.io"
}
},
"image": {
Expand Down
72 changes: 30 additions & 42 deletions services/tenant-ui/frontend/src/components/about/Acapy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<p class="mt-0">
{{
$t('about.acaPy.acapyVersion', {
version: config.frontend.ariesDetails.acapyVersion,
version: acapyVersion,
})
}}
</p>
Expand All @@ -16,55 +16,43 @@
</div>

<div class="grid">
<div class="col-2">
{{ $t('about.acaPy.ledger') }}
</div>
<div class="col-10">
{{ config.frontend.ariesDetails.ledgerName }}
</div>

<div class="col-2">
{{ $t('about.acaPy.ledgerBrowser') }}
</div>
<div class="col-10">
{{ config.frontend.ariesDetails.ledgerBrowser }}
</div>

<div class="col-2">
{{ $t('about.acaPy.tailsServer') }}
</div>
<div class="col-10">
{{ config.frontend.ariesDetails.tailsServer }}
</div>
</div>

<div class="grid mt-4">
<div class="col-12 md:col-6 lg:col-4">
<Accordion>
<AccordionTab :header="$t('about.acaPy.plugins')">
<div v-if="loading" class="flex justify-content-center">
<ProgressSpinner />
</div>
<vue-json-pretty v-else :data="acapyPlugins" />
</AccordionTab>
</Accordion>
<PluginList />
</div>
</div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import { storeToRefs } from 'pinia';
import { useConfigStore } from '@/store/configStore';
import { useInnkeeperTenantsStore, useTenantStore } from '@/store';
// PrimeVue
import Accordion from 'primevue/accordion';
import AccordionTab from 'primevue/accordiontab';
import ProgressSpinner from 'primevue/progressspinner';
import VueJsonPretty from 'vue-json-pretty';
const { acapyPlugins, config, loading } = storeToRefs(useConfigStore());
const configStore = useConfigStore();
configStore.getPluginList();
import PluginList from './PluginList.vue';
const route = useRoute();
const innTenantsStore = useInnkeeperTenantsStore();
const tenantsStore = useTenantStore();
const { serverConfig: innServerConfig } = storeToRefs(
useInnkeeperTenantsStore()
);
const { serverConfig } = storeToRefs(useTenantStore());
const acapyVersion = ref('');
const currentRouteName = computed(() => {
return route.name;
});
onMounted(async () => {
// Depending on if you're the innkeeper these setttings are different
if (currentRouteName.value === 'InnkeeperAbout') {
await innTenantsStore.getServerConfig();
acapyVersion.value = innServerConfig.value?.config?.version;
} else {
await tenantsStore.getServerConfig();
acapyVersion.value = serverConfig.value?.config?.version;
}
});
</script>

<style scoped>
Expand Down
31 changes: 31 additions & 0 deletions services/tenant-ui/frontend/src/components/about/PluginList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<template>
<Accordion>
<AccordionTab :header="$t('about.acaPy.plugins')">
<div v-if="loading" class="flex justify-content-center">
<ProgressSpinner />
</div>
<vue-json-pretty v-else :data="acapyPlugins" />
</AccordionTab>
</Accordion>
</template>

<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useConfigStore } from '@/store/configStore';
// PrimeVue
import Accordion from 'primevue/accordion';
import AccordionTab from 'primevue/accordiontab';
import ProgressSpinner from 'primevue/progressspinner';
import VueJsonPretty from 'vue-json-pretty';
const { acapyPlugins, loading } = storeToRefs(useConfigStore());
const configStore = useConfigStore();
configStore.getPluginList();
</script>

<style scoped>
.logo-acapy {
width: 14em;
}
</style>
32 changes: 32 additions & 0 deletions services/tenant-ui/frontend/src/components/common/ConfigItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<template>
<p>
<strong v-if="props.title">
{{ title }}{{ $t('common.configDelim') }}
</strong>
<strong v-else>
<slot name="title"></slot>{{ $t('common.configDelim') }}
</strong>

<span v-if="contentToString">{{ props.content }}</span>
<slot v-else name="content"></slot>
</p>
</template>

<script setup lang="ts">
import { computed } from 'vue';
// Can pass in the fields as props, or use slots if more customization needed
const props = withDefaults(
defineProps<{
title?: string;
content?: string | number | boolean;
}>(),
{
title: '',
content: '',
}
);
const contentToString = computed(() =>
typeof props.content === 'boolean' ? props.content.toString() : props.content
);
</script>
Loading

0 comments on commit 85ae68a

Please sign in to comment.