diff --git a/package.json b/package.json index 149cf00..43ddf59 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,10 @@ }, "dependencies": { "@mdi/font": "6.2.95", + "axios": "^1.6.8", "core-js": "^3.34.0", + "keycloak-js": "^24.0.2", + "pinia-plugin-persistedstate": "^3.2.1", "roboto-fontface": "*", "vue": "^3.4.21", "vuetify": "^3.5.8" diff --git a/src/components/AppFooter.vue b/src/components/AppFooter.vue deleted file mode 100644 index c2b6d45..0000000 --- a/src/components/AppFooter.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - - - diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue index 98ce2c4..ae58577 100644 --- a/src/components/HelloWorld.vue +++ b/src/components/HelloWorld.vue @@ -1,5 +1,19 @@ + + diff --git a/src/config/app.ts b/src/config/app.ts new file mode 100644 index 0000000..c534c0d --- /dev/null +++ b/src/config/app.ts @@ -0,0 +1,5 @@ +let app = { + name: "MC Search" +} + +export default app diff --git a/src/config/config.ts b/src/config/config.ts new file mode 100644 index 0000000..7634e08 --- /dev/null +++ b/src/config/config.ts @@ -0,0 +1,13 @@ +let config = { + auth: { + server: "https://kc.ivampiresp.com", + clientId: "dev", + realm: "test", + scopes: "openid email profile", + }, + api: { + baseUrl: "http://127.0.0.1:8081", + } +} + +export default config diff --git a/src/config/keycloak.ts b/src/config/keycloak.ts new file mode 100644 index 0000000..093fb6c --- /dev/null +++ b/src/config/keycloak.ts @@ -0,0 +1,10 @@ +import Keycloak from "keycloak-js"; +import config from "@/config/config"; + +let keycloak = new Keycloak({ + url: config.auth.server, + realm: config.auth.realm, + clientId: config.auth.clientId, +}) + +export default keycloak diff --git a/src/layouts/default/AppBar.vue b/src/layouts/default/AppBar.vue index 2b30ddf..9333fa8 100644 --- a/src/layouts/default/AppBar.vue +++ b/src/layouts/default/AppBar.vue @@ -33,23 +33,24 @@ - {{ configStore.appName }} + {{ app.name }} diff --git a/src/pages/README.md b/src/pages/README.md deleted file mode 100644 index 341536c..0000000 --- a/src/pages/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Pages - -Vue components created in this folder will automatically be converted to navigatable routes. - -Full documentation for this feature can be found in the Official [unplugin-vue-router](https://github.com/posva/unplugin-vue-router) repository. diff --git a/src/pages/index.vue b/src/pages/index.vue deleted file mode 100644 index dac59c7..0000000 --- a/src/pages/index.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/plugins/api.ts b/src/plugins/api.ts index 8f3e9c0..dddf9f8 100644 --- a/src/plugins/api.ts +++ b/src/plugins/api.ts @@ -1,22 +1,17 @@ -import { Configuration } from "../api"; +import {Configuration, SpiderApi} from "@/api"; +import {useUserStore} from "@/stores/user"; +import config from "@/config/config"; -// import axios from "axios"; -// import router from "@/router"; -// import {useUserStore} from "@/store/user"; -// import { useConfigStore } from "@/store/config"; -// -// -// const userStore = useUserStore() -// const configStore = useConfigStore() -// -// const conf = new Configuration -// conf.basePath = configStore.apiServer -// -// conf.apiKey = "Bearer " + userStore.jwt_token -// const document = new DocumentsApi(conf); -// const library = new LibrariesApi(conf); -// -// -// export { -// document, library, conf -// } +const userStore = useUserStore() + +const conf = new Configuration + +conf.basePath = config.api.baseUrl +conf.apiKey = "Bearer " + userStore.id_token + + +const theSpiderApi = new SpiderApi(conf); + +export { + theSpiderApi, conf +} diff --git a/src/plugins/vuetify.ts b/src/plugins/vuetify.ts index 7652788..ec96fdf 100644 --- a/src/plugins/vuetify.ts +++ b/src/plugins/vuetify.ts @@ -11,9 +11,16 @@ import 'vuetify/styles' // Composables import { createVuetify } from 'vuetify' +// lang +import { pl, zhHans } from 'vuetify/locale' +import { md3 } from 'vuetify/blueprints' + // https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides export default createVuetify({ - theme: { - defaultTheme: 'dark', + locale: { + locale: 'zhHans', + fallback: 'sv', + messages: { zhHans, pl }, }, + blueprint: md3, }) diff --git a/src/router/index.ts b/src/router/index.ts index 2122680..0e08a3e 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,8 +1,6 @@ -// Composables import { createRouter, createWebHistory } from "vue-router"; -// import { useUserStore } from "@/stores/user"; -// import { useConfigStore } from "@/stores/config"; +import {useUserStore} from "@/stores/user"; const routes = [ { path: "/", @@ -15,6 +13,17 @@ const routes = [ // which is lazy-loaded when the route is visited. component: () => import("@/views/Home.vue"), }, + { + path: "/auth/login", + name: "login", + meta: { + auth: false, + }, + // route level code-splitting + // this generates a separate chunk (Home-[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import("@/views/auth/Login.vue"), + }, ]; @@ -23,35 +32,29 @@ const router = createRouter({ routes, }); -// router.beforeEach((to, from) => { -// -// // get route name -// console.log(from.name, from.fullPath) -// -// const userStore = useUserStore(); -// const configStore = useConfigStore(); -// -// // if (to.matched.length === 0) { -// // return router.push({ name: "errors.404" }); -// // } -// -// if (to.meta.title) { -// document.title = to.meta.title + " - " + configStore.getAppName(); -// } else { -// document.title = configStore.getAppName(); -// } -// -// if (to.meta.auth == true) { -// // validate login state -// if (userStore.jwt_token == null) { -// router.push({ name: "login" }); -// } -// } else { -// document.title = configStore.getAppName(); -// } -// -// return true; -// -// }); +router.beforeEach((to: any, from: any) => { + console.log(from.name, from.fullPath) + + const userStore = useUserStore(); + + // if (to.matched.length === 0) { + // return router.push({ name: "errors.404" }); + // } + + + if (to.meta.auth == true) { + // validate login state + if (userStore.access_token == null) { + router.push({name: "login"}).then(r => { + console.log(r) + }); + } + } + + return true; + +}); + + export default router; diff --git a/src/stores/index.ts b/src/stores/index.ts index 1536252..609faa8 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -1,4 +1,5 @@ // Utilities import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' -export default createPinia() +export default createPinia().use(piniaPluginPersistedstate) diff --git a/src/stores/user.ts b/src/stores/user.ts new file mode 100644 index 0000000..ea43601 --- /dev/null +++ b/src/stores/user.ts @@ -0,0 +1,33 @@ +import {defineStore} from 'pinia' + +export const useUserStore = defineStore('user', { + persist: true, + state: () => ({ + refresh_token: null as null | string, + access_token: null as null | string, + id_token: null as null | string, + expired_at: null as null | Date, + user: null as null | any, + }), + actions: { + setRefreshToken(refresh_token: string) { + this.refresh_token = refresh_token + }, + setAccessToken(access_token: string) { + this.access_token = access_token + }, + setIdToken(id_token: string) { + this.id_token = id_token + }, + setProfile(user: any) { + this.user = user + }, + logout() { + this.user = null; + this.expired_at = null; + this.id_token = null; + this.access_token = null; + this.refresh_token = null + } + } +}) diff --git a/src/typed-router.d.ts b/src/typed-router.d.ts index 6d6767c..8ff91b7 100644 --- a/src/typed-router.d.ts +++ b/src/typed-router.d.ts @@ -18,6 +18,5 @@ declare module 'vue-router/auto-routes' { * Route name map generated by unplugin-vue-router */ export interface RouteNamedMap { - '/': RouteRecordInfo<'/', '/', Record, Record>, } } diff --git a/src/views/Home.vue b/src/views/Home.vue index 8941a75..954f5b4 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -1,7 +1,6 @@ diff --git a/src/views/auth/Login.vue b/src/views/auth/Login.vue new file mode 100644 index 0000000..27587d4 --- /dev/null +++ b/src/views/auth/Login.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/yarn.lock b/yarn.lock index 84e1153..42e8374 100644 --- a/yarn.lock +++ b/yarn.lock @@ -723,6 +723,11 @@ ast-walker-scope@^0.6.0: "@babel/parser" "^7.24.0" ast-kit "^0.12.1" +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -730,6 +735,15 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +axios@^1.6.8: + version "1.6.8" + resolved "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" + integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -830,6 +844,13 @@ color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + computeds@^0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz#215b08a4ba3e08a11ff6eee5d6d8d7166a97ce2e" @@ -933,6 +954,11 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1393,6 +1419,11 @@ flatted@^3.2.9: resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -1400,6 +1431,15 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1762,6 +1802,11 @@ isexe@^2.0.0: resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +js-sha256@^0.11.0: + version "0.11.0" + resolved "https://registry.npmjs.org/js-sha256/-/js-sha256-0.11.0.tgz#256a921d9292f7fe98905face82e367abaca9576" + integrity sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q== + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -1801,6 +1846,19 @@ jsonc-parser@^3.2.0: resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== +jwt-decode@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b" + integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== + +keycloak-js@^24.0.2: + version "24.0.2" + resolved "https://registry.npmjs.org/keycloak-js/-/keycloak-js-24.0.2.tgz#9e7320ed1859b0f493acbc57c64728da2b5eb49b" + integrity sha512-V2N8cSz3NfON98XHp+DCzvrb1WW35JalL5Zphe/uoVWOxcof7v522Yz9Q2O3BqXqXP3V/H9ml6o24BwwtXUTGA== + dependencies: + js-sha256 "^0.11.0" + jwt-decode "^4.0.0" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -1880,6 +1938,18 @@ micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + minimatch@9.0.3, minimatch@^9.0.3: version "9.0.3" resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -2079,6 +2149,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pinia-plugin-persistedstate@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz#66780602aecd6c7b152dd7e3ddc249a1f7a13fe5" + integrity sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ== + pinia@^2.1.7: version "2.1.7" resolved "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz#4cf5420d9324ca00b7b4984d3fbf693222115bbc" @@ -2123,6 +2198,11 @@ prelude-ls@^1.2.1: resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + punycode@^2.1.0: version "2.3.1" resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"