Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: analysis-bucket implementation #433

Merged
merged 11 commits into from
Jun 11, 2024
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 33 additions & 33 deletions packages/client-ui/middleware/auth.global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,61 +6,53 @@
*/

import { useStore } from '@authup/client-web-kit';
import { hasOwnProperty } from '@privateaim/kit';
import { storeToRefs } from 'pinia';
import type { RouteLocationNormalized } from 'vue-router';
import {
navigateTo,
} from '#app';
import { LayoutKey } from '../config/layout';

function checkAbilityOrPermission(route: RouteLocationNormalized, has: (name: string) => boolean) {
const layoutKeys : string[] = [
LayoutKey.REQUIRED_PERMISSIONS,
];

function checkPermission(route: RouteLocationNormalized, has: (name: string) => boolean) {
let isAllowed : undefined | boolean;

for (let i = 0; i < layoutKeys.length; i++) {
const layoutKey = layoutKeys[i];
const layoutKey = LayoutKey.REQUIRED_PERMISSIONS;

for (let j = 0; j < route.matched.length; j++) {
const matchedRecord = route.matched[j];
for (let j = 0; j < route.matched.length; j++) {
const matchedRecord = route.matched[j];

if (!Object.prototype.hasOwnProperty.call(matchedRecord.meta, layoutKey)) {
continue;
}
if (!hasOwnProperty(matchedRecord.meta, layoutKey)) {
continue;
}

const value = matchedRecord.meta[layoutKey];
if (Array.isArray(value)) {
isAllowed = value.some((val) => has(val));
}
const value = matchedRecord.meta[layoutKey];
if (Array.isArray(value)) {
isAllowed = value.some((val) => has(val));
}

if (isAllowed) {
return true;
}
if (isAllowed) {
return true;
}
}

if (typeof isAllowed === 'undefined') {
return true;
}

if (!isAllowed) {
const parts = route.path.split('/');
parts.pop();
throw new Error(parts.join('/'));
}

return true;
return isAllowed;
}

export default defineNuxtRouteMiddleware(async (to, from) => {
const store = useStore();
const { loggedIn } = storeToRefs(store);

let redirectPath = '/';
let redirectPath = '/login';

if (typeof from !== 'undefined') {
if (
typeof from !== 'undefined' &&
from.fullPath !== to.fullPath
) {
redirectPath = from.fullPath;
}

Expand All @@ -69,7 +61,10 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
} catch (e) {
store.logout();

if (!to.fullPath.startsWith('/logout') && !to.fullPath.startsWith('/login')) {
if (
!to.fullPath.startsWith('/logout') &&
!to.fullPath.startsWith('/login')
) {
return navigateTo({
path: '/logout',
query: {
Expand Down Expand Up @@ -99,15 +94,20 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
query,
});
}
}

try {
checkAbilityOrPermission(to, (name) => store.abilities.has(name));
} catch (e) {
if (
to.matched.some((matched) => !!matched.meta[LayoutKey.REQUIRED_PERMISSIONS])
) {
const permitted = checkPermission(to, (name) => store.abilities.has(name));
if (!permitted) {
return navigateTo({
path: redirectPath,
});
}
} else if (
}

if (
!to.fullPath.startsWith('/logout') &&
to.matched.some((matched) => matched.meta[LayoutKey.REQUIRED_LOGGED_OUT])
) {
Expand Down
41 changes: 25 additions & 16 deletions packages/client-ui/pages/analyses/[id]/results.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
- view the LICENSE file that was distributed with this source code.
-->
<script lang="ts">
import { FAnalysisBucket, FAnalysisBucketFileDownload, FAnalysisBucketFiles } from '@privateaim/client-vue';
import { computed } from 'vue';
import type { BuildInput } from 'rapiq';
import type { PropType } from 'vue';
import { type Analysis, type AnalysisFile, AnalysisFileType } from '@privateaim/core';
import { FAnalysisFileDownload, FAnalysisFiles } from '@privateaim/client-vue';
import { type Analysis, type AnalysisBucket, AnalysisBucketType } from '@privateaim/core';
import { defineNuxtComponent } from '#app';

export default defineNuxtComponent({
components: { FAnalysisFiles, FAnalysisFileDownload },
components: { FAnalysisBucket, FAnalysisBucketFiles, FAnalysisFileDownload: FAnalysisBucketFileDownload },
props: {
entity: {
type: Object as PropType<Analysis>,
Expand All @@ -22,12 +22,12 @@ export default defineNuxtComponent({
},
emits: ['updated', 'failed'],
setup(props) {
const query = computed<BuildInput<AnalysisFile>>(() => ({
const query = computed<BuildInput<AnalysisBucket>>(() => ({
filter: {
type: AnalysisFileType.RESULT,
type: AnalysisBucketType.RESULT,
analysis_id: props.entity.id,
},
} satisfies BuildInput<AnalysisFile>));
} satisfies BuildInput<AnalysisBucket>));

return {
query,
Expand All @@ -37,16 +37,25 @@ export default defineNuxtComponent({
</script>
<template>
<div class="panel-box">
<FAnalysisFiles
v-if="entity"
:query="query"
>
<template #itemActions="{ data }">
<FAnalysisFileDownload
:entity="data"
:with-icon="true"
/>
<FAnalysisBucket :query="query">
<template #default="{ data: bucket }">
<FAnalysisBucketFiles
v-if="entity"
:query="{ filters: { bucket_id: bucket.id } }"
>
<template #itemActions="{ data }">
<FAnalysisFileDownload
:entity="data"
:with-icon="true"
/>
</template>
</FAnalysisBucketFiles>
</template>
</FAnalysisFiles>
<template #error>
<div class="alert alert-sm alert-warning">
The result bucket does not exist. Therefore, no files can be downloaded.
</div>
</template>
</FAnalysisBucket>
</div>
</template>
2 changes: 2 additions & 0 deletions packages/client-ui/plugins/01.auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { install } from '@authup/client-web-kit';
import type { Pinia } from 'pinia';
import { useCookie } from '#imports';

export default defineNuxtPlugin({
Expand All @@ -14,6 +15,7 @@ export default defineNuxtPlugin({
const { authupUrl: baseURL } = runtimeConfig.public;

ctx.vueApp.use(install, {
pinia: ctx.$pinia as Pinia,
baseURL,
cookieSet: (key, value) => {
const cookie = useCookie(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
DomainType,
} from '@privateaim/core';
import type {
AnalysisFile,
AnalysisBucketFile,
} from '@privateaim/core';
import type { PropType } from 'vue';
import {
Expand All @@ -20,7 +20,7 @@ import { createEntityManager, defineEntityManagerEvents } from '../../core';
export default defineComponent({
props: {
entity: {
type: Object as PropType<AnalysisFile>,
type: Object as PropType<AnalysisBucketFile>,
required: true,
},
filesSelected: {
Expand All @@ -32,11 +32,11 @@ export default defineComponent({
},
},
emits: {
...defineEntityManagerEvents<AnalysisFile>(),
...defineEntityManagerEvents<AnalysisBucketFile>(),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
toggle: (_entity?: AnalysisFile) => true,
toggle: (_entity?: AnalysisBucketFile) => true,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
check: (_entity?: AnalysisFile) => true,
check: (_entity?: AnalysisBucketFile) => true,
},
setup(props, setup) {
const manager = createEntityManager({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
* view the LICENSE file that was distributed with this source code.
*/

import type { AnalysisFile } from '@privateaim/core';
import type { AnalysisBucketFile } from '@privateaim/core';
import type { PropType } from 'vue';
import { defineComponent } from 'vue';
import { ActionCommandElementType, injectStorageHTTPClient, renderActionCommand } from '../../core';

const FAnalysisFileDownload = defineComponent({
const FAnalysisBucketFileDownload = defineComponent({
props: {
entity: {
type: Object as PropType<AnalysisFile>,
type: Object as PropType<AnalysisBucketFile>,
required: true,
},
elementType: {
Expand All @@ -33,7 +33,7 @@ const FAnalysisFileDownload = defineComponent({
const storageClient = injectStorageHTTPClient();

const execute = async () => {
const url = storageClient.bucketFile.getStreamURL(props.entity.bucket_file_id);
const url = storageClient.bucketFile.getStreamURL(props.entity.external_id);

window.open(
url,
Expand All @@ -57,5 +57,5 @@ const FAnalysisFileDownload = defineComponent({
});

export {
FAnalysisFileDownload,
FAnalysisBucketFileDownload,
};
Loading
Loading