feat: use keycloak
This commit is contained in:
parent
867ba7746d
commit
89d8fbc843
|
|
@ -1,4 +1,4 @@
|
||||||
# Client Portal
|
# Portal
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
|
|
@ -8,5 +8,5 @@
|
||||||
|
|
||||||
- Node.js
|
- Node.js
|
||||||
- Nuxt
|
- Nuxt
|
||||||
- Directus
|
- Keycloak
|
||||||
- Vuetify
|
- Vuetify
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
export const usePortalTags = () => {
|
|
||||||
const { fetchUser, setUser } = useDirectusAuth();
|
|
||||||
const user = useDirectusUser();
|
|
||||||
|
|
||||||
const tags = computed(() => (toValue(user)?.tags as Array<string>) || []);
|
|
||||||
|
|
||||||
const details = computed(() => {
|
|
||||||
const value = toValue(tags);
|
|
||||||
|
|
||||||
return {
|
|
||||||
interest: value.includes("portal-interest"),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
if (!user.value) {
|
|
||||||
const user = await fetchUser();
|
|
||||||
setUser(user.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return details;
|
|
||||||
};
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
export default defineNuxtRouteMiddleware(async () => {
|
|
||||||
const { fetchUser, setUser } = useDirectusAuth();
|
|
||||||
|
|
||||||
const user = useDirectusUser();
|
|
||||||
|
|
||||||
if (!user.value) {
|
|
||||||
const user = await fetchUser();
|
|
||||||
setUser(user.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.value) {
|
|
||||||
return navigateTo("/login");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: "2024-11-01",
|
compatibilityDate: "2024-11-01",
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
modules: ["nuxt-directus", "vuetify-nuxt-module", "@vite-pwa/nuxt"],
|
modules: ["vuetify-nuxt-module", "@vite-pwa/nuxt"],
|
||||||
app: {
|
app: {
|
||||||
head: {
|
head: {
|
||||||
titleTemplate: "%s • Port Nimara Client Portal",
|
titleTemplate: "%s • Portal",
|
||||||
title: "Port Nimara Client Portal",
|
|
||||||
meta: [
|
meta: [
|
||||||
{ property: "og:title", content: "Port Nimara Client Portal" },
|
{ property: "og:title", content: "Portal" },
|
||||||
{ property: "og:image", content: "/og-image.png" },
|
{ property: "og:image", content: "/og-image.png" },
|
||||||
{ name: "twitter:card", content: "summary_large_image" },
|
{ name: "twitter:card", content: "summary_large_image" },
|
||||||
],
|
],
|
||||||
|
|
@ -18,17 +17,19 @@ export default defineNuxtConfig({
|
||||||
},
|
},
|
||||||
runtimeConfig: {
|
runtimeConfig: {
|
||||||
public: {
|
public: {
|
||||||
directus: {
|
keycloak: {
|
||||||
url: "https://cms.portnimara.dev",
|
url: "",
|
||||||
|
realm: "",
|
||||||
|
clientId: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
vuetify: {
|
vuetify: {
|
||||||
vuetifyOptions: {
|
vuetifyOptions: {
|
||||||
theme: {
|
theme: {
|
||||||
defaultTheme: "portnimara",
|
defaultTheme: "portal",
|
||||||
themes: {
|
themes: {
|
||||||
portnimara: {
|
portal: {
|
||||||
colors: {
|
colors: {
|
||||||
primary: "#387bca",
|
primary: "#387bca",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vite-pwa/nuxt": "^0.10.6",
|
"@vite-pwa/nuxt": "^0.10.6",
|
||||||
|
"keycloak-js": "^26.2.0",
|
||||||
"nuxt": "^3.15.4",
|
"nuxt": "^3.15.4",
|
||||||
"nuxt-directus": "^5.7.0",
|
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
"vue-router": "latest",
|
"vue-router": "latest",
|
||||||
"vuetify-nuxt-module": "^0.18.3"
|
"vuetify-nuxt-module": "^0.18.3"
|
||||||
|
|
@ -8268,6 +8268,12 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/keycloak-js": {
|
||||||
|
"version": "26.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-26.2.0.tgz",
|
||||||
|
"integrity": "sha512-CrFcXTN+d6J0V/1v3Zpioys6qHNWE6yUzVVIsCUAmFn9H14GZ0vuYod+lt+SSpMgWGPuneDZBSGBAeLBFuqjsw==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||||
|
|
@ -9159,15 +9165,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nuxt-directus": {
|
|
||||||
"version": "5.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/nuxt-directus/-/nuxt-directus-5.7.0.tgz",
|
|
||||||
"integrity": "sha512-hoNXbhQ8UgDrCXqzqxC0wngi64AVqYYGGU/bwylgZWbKyU0m6kyNQVLGuQuXmFbogr2WMaw+FtXSgLz+DS32hA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@nuxt/kit": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/nypm": {
|
"node_modules/nypm": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.5.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vite-pwa/nuxt": "^0.10.6",
|
"@vite-pwa/nuxt": "^0.10.6",
|
||||||
|
"keycloak-js": "^26.2.0",
|
||||||
"nuxt": "^3.15.4",
|
"nuxt": "^3.15.4",
|
||||||
"nuxt-directus": "^5.7.0",
|
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
"vue-router": "latest",
|
"vue-router": "latest",
|
||||||
"vuetify-nuxt-module": "^0.18.3"
|
"vuetify-nuxt-module": "^0.18.3"
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<v-app full-height>
|
<v-app full-height>
|
||||||
<v-navigation-drawer
|
<v-navigation-drawer v-model="drawer" :location="mdAndDown ? 'bottom' : undefined">
|
||||||
v-model="drawer"
|
|
||||||
:location="mdAndDown ? 'bottom' : undefined"
|
|
||||||
>
|
|
||||||
<v-img v-if="!mdAndDown" src="/logo.jpg" height="75" class="my-6" />
|
<v-img v-if="!mdAndDown" src="/logo.jpg" height="75" class="my-6" />
|
||||||
|
|
||||||
<v-list color="primary" lines="two">
|
<v-list color="primary" lines="two">
|
||||||
<v-list-item
|
<v-list-item v-for="(item, index) in menu" :key="index" :to="item.to" :title="item.title"
|
||||||
v-for="(item, index) in menu"
|
:prepend-icon="item.icon" />
|
||||||
:key="index"
|
|
||||||
:to="item.to"
|
|
||||||
:title="item.title"
|
|
||||||
:prepend-icon="item.icon"
|
|
||||||
/>
|
|
||||||
</v-list>
|
</v-list>
|
||||||
|
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-list lines="two">
|
<v-list lines="two">
|
||||||
<v-list-item
|
<v-list-item title="Logged in" prepend-icon="mdi-account" />
|
||||||
v-if="user"
|
<v-list-item @click="logOut" title="Log out" prepend-icon="mdi-logout" base-color="error" />
|
||||||
:title="`${user.first_name} ${user.last_name}`"
|
|
||||||
:subtitle="user.email"
|
|
||||||
prepend-icon="mdi-account"
|
|
||||||
/>
|
|
||||||
<v-list-item
|
|
||||||
@click="logOut"
|
|
||||||
title="Log out"
|
|
||||||
prepend-icon="mdi-logout"
|
|
||||||
base-color="error"
|
|
||||||
/>
|
|
||||||
</v-list>
|
</v-list>
|
||||||
</template>
|
</template>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
|
|
@ -42,13 +24,7 @@
|
||||||
<v-img src="/logo.jpg" height="50" />
|
<v-img src="/logo.jpg" height="50" />
|
||||||
|
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-btn
|
<v-btn @click="logOut" class="mr-3" variant="text" color="error" icon="mdi-logout" />
|
||||||
@click="logOut"
|
|
||||||
class="mr-3"
|
|
||||||
variant="text"
|
|
||||||
color="error"
|
|
||||||
icon="mdi-logout"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
|
|
||||||
|
|
@ -60,18 +36,14 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: ["authentication"],
|
|
||||||
layout: false,
|
layout: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { mdAndDown } = useDisplay();
|
const { mdAndDown } = useDisplay();
|
||||||
const { logout } = useDirectusAuth();
|
|
||||||
const user = useDirectusUser();
|
|
||||||
const tags = usePortalTags();
|
|
||||||
|
|
||||||
const drawer = ref(false);
|
const drawer = ref(false);
|
||||||
|
|
||||||
const interestMenu = [
|
const menu = ref([
|
||||||
{
|
{
|
||||||
to: "/dashboard/interest-eoi-queue",
|
to: "/dashboard/interest-eoi-queue",
|
||||||
icon: "mdi-tray-full",
|
icon: "mdi-tray-full",
|
||||||
|
|
@ -102,11 +74,6 @@ const interestMenu = [
|
||||||
icon: "mdi-account-check",
|
icon: "mdi-account-check",
|
||||||
title: "Interest Status",
|
title: "Interest Status",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
const defaultMenu = [
|
|
||||||
{
|
{
|
||||||
to: "/dashboard/site",
|
to: "/dashboard/site",
|
||||||
icon: "mdi-view-dashboard",
|
icon: "mdi-view-dashboard",
|
||||||
|
|
@ -117,14 +84,9 @@ const defaultMenu = [
|
||||||
icon: "mdi-finance",
|
icon: "mdi-finance",
|
||||||
title: "Data Analytics",
|
title: "Data Analytics",
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
const menu = computed(() =>
|
|
||||||
toValue(tags).interest ? interestMenu : defaultMenu
|
|
||||||
);
|
|
||||||
|
|
||||||
const logOut = async () => {
|
const logOut = async () => {
|
||||||
await logout();
|
|
||||||
return navigateTo("/login");
|
return navigateTo("/login");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,3 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
const tags = usePortalTags();
|
onBeforeMount(() => navigateTo("/dashboard/interest-analytics"));
|
||||||
|
|
||||||
onBeforeMount(() =>
|
|
||||||
navigateTo(
|
|
||||||
toValue(tags).interest ? "/dashboard/interest-analytics" : "/dashboard/site"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import Keycloak from "keycloak-js";
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((application) => {
|
||||||
|
const runtimeConfig = useRuntimeConfig();
|
||||||
|
|
||||||
|
const keycloak = new Keycloak({
|
||||||
|
url: runtimeConfig.public.keycloak.url,
|
||||||
|
realm: runtimeConfig.public.keycloak.realm,
|
||||||
|
clientId: runtimeConfig.public.keycloak.clientId,
|
||||||
|
});
|
||||||
|
|
||||||
|
keycloak.init({
|
||||||
|
onLoad: "login-required",
|
||||||
|
});
|
||||||
|
|
||||||
|
keycloak.updateToken(2000);
|
||||||
|
|
||||||
|
application.$keycloak = keycloak;
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue