diff --git a/.eslintignore b/.eslintignore index 9f81cf8..9d5fd02 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,4 +4,5 @@ /.quasar /node_modules .eslintrc.cjs +/src /quasar.config.*.temporary.compiled* diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 68b682e..e6e2e50 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -46,11 +46,11 @@ module.exports = { // https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files // required to lint *.vue files 'vue' - + // https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674 // Prettier has not been included as plugin to avoid performance impact // add it as an extension for your IDE - + ], globals: { @@ -68,10 +68,8 @@ module.exports = { // add your custom rules here rules: { - - 'prefer-promise-reject-errors': 'off', - quotes: ['warn', 'single', { avoidEscape: true }], + 'prefer-promise-reject-errors': 'off', // this rule, if on, would require explicit return type on the `render` function '@typescript-eslint/explicit-function-return-type': 'off', diff --git a/index.html b/index.html index 3c8c78f..015e4d3 100644 --- a/index.html +++ b/index.html @@ -9,13 +9,14 @@ - + + diff --git a/package-lock.json b/package-lock.json index 61b9953..a04e0b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@quasar/extras": "^1.16.4", "axios": "^1.2.1", + "keycloak-js": "^24.0.3", "pinia": "^2.0.11", "quasar": "^2.8.0", "vue": "^3.4.18", @@ -4677,6 +4678,11 @@ "node": ">=0.10.0" } }, + "node_modules/js-sha256": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.11.0.tgz", + "integrity": "sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4785,6 +4791,23 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/keycloak-js": { + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-24.0.3.tgz", + "integrity": "sha512-4L0zTiQATKZiGQ6WM5qjjUIrN7pntzHDy4JebvgWA+im3oUDQ8UmQhIU0wnhONKrUK8pM4chyE/vDNStBNcR8w==", + "dependencies": { + "js-sha256": "^0.11.0", + "jwt-decode": "^4.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -10797,6 +10820,11 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true }, + "js-sha256": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.11.0.tgz", + "integrity": "sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -10884,6 +10912,20 @@ "universalify": "^2.0.0" } }, + "jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==" + }, + "keycloak-js": { + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-24.0.3.tgz", + "integrity": "sha512-4L0zTiQATKZiGQ6WM5qjjUIrN7pntzHDy4JebvgWA+im3oUDQ8UmQhIU0wnhONKrUK8pM4chyE/vDNStBNcR8w==", + "requires": { + "js-sha256": "^0.11.0", + "jwt-decode": "^4.0.0" + } + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/package.json b/package.json index 6ab6d3e..0a3ca0b 100644 --- a/package.json +++ b/package.json @@ -13,29 +13,30 @@ "build": "quasar build" }, "dependencies": { - "axios": "^1.2.1", - "vue-i18n": "^9.2.2", - "pinia": "^2.0.11", "@quasar/extras": "^1.16.4", + "axios": "^1.2.1", + "keycloak-js": "^24.0.3", + "pinia": "^2.0.11", "quasar": "^2.8.0", "vue": "^3.4.18", + "vue-i18n": "^9.2.2", "vue-router": "^4.0.12" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.10.0", - "@typescript-eslint/parser": "^5.10.0", - "vite-plugin-checker": "^0.6.4", - "vue-tsc": "^1.8.22", - "eslint": "^8.11.0", - "eslint-plugin-vue": "^9.0.0", - "eslint-config-prettier": "^8.1.0", - "prettier": "^2.5.1", - "@types/node": "^12.20.21", "@intlify/vite-plugin-vue-i18n": "^3.3.1", "@quasar/app-vite": "^1.8.0", "@quasar/cli": "^2.4.0", + "@types/node": "^12.20.21", + "@typescript-eslint/eslint-plugin": "^5.10.0", + "@typescript-eslint/parser": "^5.10.0", "autoprefixer": "^10.4.2", - "typescript": "^4.5.4" + "eslint": "^8.11.0", + "eslint-config-prettier": "^8.1.0", + "eslint-plugin-vue": "^9.0.0", + "prettier": "^2.5.1", + "typescript": "^4.5.4", + "vite-plugin-checker": "^0.6.4", + "vue-tsc": "^1.8.22" }, "engines": { "node": "^20 || ^18 || ^16", diff --git a/quasar.config.js b/quasar.config.js index 2dac4fa..5806b3f 100644 --- a/quasar.config.js +++ b/quasar.config.js @@ -60,7 +60,16 @@ module.exports = configure(function (/* ctx */) { // publicPath: '/', // analyze: true, - // env: {}, + env: { + //Defined in realm_export.json + KEYCLOAK_REALM:'PraxistransferKeycloak', + KEYCLOAK_CLIENT_ID:'praxistransfer', + + //Defined in realm_export.json, initialize_keycloak.sh and quasar.config.js + PORT_KEYCLOAK:8083, + PORT_FRONTEND:8080, + PORT_BACKEND:8081, + }, // rawDefine: {} // ignorePublicFolder: true, // minify: false, @@ -93,11 +102,19 @@ module.exports = configure(function (/* ctx */) { ] }, + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer devServer: { // https: true - port: 8081, // default: 3000; changed to 8081 to match keycloak settings - open: true // opens browser window automatically + port: 8080, // default: 3000; changed to 8080 to match keycloak settings + open: true, // opens browser window automatically + proxy: { + '/api': { + target: 'http://localhost:8080', + changeOrigin: true + } + }, + }, // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework diff --git a/src/App.vue b/src/App.vue index 1325c29..c1b93fe 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,9 +1,27 @@ - - + + + + diff --git a/src/boot/axios.ts b/src/boot/axios.ts index 05a9944..5303aa9 100644 --- a/src/boot/axios.ts +++ b/src/boot/axios.ts @@ -14,7 +14,7 @@ declare module '@vue/runtime-core' { // good idea to move this instance creation inside of the // "export default () => {}" function below (which runs individually // for each client) -const api = axios.create({ baseURL: 'https://api.example.com' }); +const api = axios.create({ baseURL: 'http://localhost:'+ process.env.PORT_BACKEND }); export default boot(({ app }) => { // for use inside Vue files (Options API) through this.$axios and this.$api diff --git a/src/components/ProtectedData.vue b/src/components/ProtectedData.vue new file mode 100644 index 0000000..de4c72d --- /dev/null +++ b/src/components/ProtectedData.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index 049f1c3..08eb52d 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -21,7 +21,6 @@ diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..51157cd --- /dev/null +++ b/src/main.ts @@ -0,0 +1,62 @@ +import {createApp} from 'vue'; +import {createPinia} from 'pinia'; + +import App from './App.vue'; + +import Keycloak, {type KeycloakConfig, type KeycloakInitOptions} from 'keycloak-js'; +import { useKeycloakStore } from 'stores/keycloakStore'; +import {useUserStore} from 'stores/user-store'; + +const app = createApp(App); +app.use(createPinia()); + +/** + * Initialisierungsoptionen für Keycloak. + * @param url URL zu Keycloak, Port definiert in keycloak_init.sh und quasar.config.js-Datei. Müssen identisch sein! + * @param realm Name des Realms, hinterlegt in realm-export.json von Keycloak und quasar.config.js-Datei. Müssen identisch sein! + * @param clientId Name des Clients, hinterlegt in realm-export.json von Keycloak und quasar.config.js-Datei. Müssen identisch sein! + * @param onLoad = 'login-required': Hierdurch wird zum Aufrufen der ganzen Applikation ein login benötigt. + * @param redirectUri: URL, zu der nach dem Login weitergeleitet wird. Hierbei wird die Port des Frontends aus der .env-Datei verwendet. + */ + +const keycloak = new Keycloak({ + url: 'http://localhost:8083/', + realm: 'PraxistransferKeycloak', + clientId: 'praxistransfer' +}); + +console.log("ICH WAR HIER"); + +try { + const authenticated = await keycloak.init({ + onLoad: 'login-required', + redirectUri: 'http://localhost:8080/test/' + }).then( (auth) => { + console.log("Authenticated :" + authenticated); + }); + +} catch (error) { + console.error(error); +} + +console.log(keycloak); +console.log(keycloak.subject); + +// Anfrage ans Backend +const userStore = useUserStore(); + +if (keycloak.subject != null) { + //userStore.loadPtpUsersByKeycloakID(keycloak.subject); + userStore.getPtpUserByKeycloakID(keycloak.subject); + /*console.log(userStore.userLoaded); + if(userStore.userLoaded) { + console.log("Hier ist der Bruder: " + JSON.stringify(userStore.user)); + }*/ + userStore.loadPtpUsersByKeycloakID(keycloak.subject).then(user => { + console.log(JSON.stringify(user)); + }) +} else { + console.log("hier ist was schlimmes passiert menno"); +} + + diff --git a/src/models.ts b/src/models.ts new file mode 100644 index 0000000..3da2788 --- /dev/null +++ b/src/models.ts @@ -0,0 +1,12 @@ +export interface ptpUser { + keycloakID: string; + firstName: string; + lastName: string; + username: string; +} + +export interface responseModel { + success: boolean; + message: string; + response: any; +} diff --git a/src/pages/IndexPage.vue b/src/pages/IndexPage.vue index eeee211..efe2b03 100644 --- a/src/pages/IndexPage.vue +++ b/src/pages/IndexPage.vue @@ -11,7 +11,7 @@ + + + + diff --git a/src/router/routes.ts b/src/router/routes.ts index 2d34fc1..e174e01 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -6,6 +6,10 @@ const routes: RouteRecordRaw[] = [ component: () => import('layouts/MainLayout.vue'), children: [{ path: '', component: () => import('pages/IndexPage.vue') }], }, + { + path: '/test', + component: () => import('pages/TestPage.vue') + }, // Always leave this as last one, // but you can also remove it diff --git a/src/stores/keycloakStore.ts b/src/stores/keycloakStore.ts new file mode 100644 index 0000000..c4fdb8a --- /dev/null +++ b/src/stores/keycloakStore.ts @@ -0,0 +1,18 @@ +import type Keycloak from 'keycloak-js'; +import { defineStore } from 'pinia'; +//import api from 'axios'; + +export const useKeycloakStore = defineStore('keycloakStore', { + state: ()=>({ + keycloak: null as Keycloak| null, + }), + getters: { + getKeycloak: (state) => state.keycloak, + }, + actions:{ + setKeycloak(keycloak: Keycloak): void { + this.keycloak = keycloak; + }, + + }, +}); diff --git a/src/stores/user-store.ts b/src/stores/user-store.ts new file mode 100644 index 0000000..0b226a7 --- /dev/null +++ b/src/stores/user-store.ts @@ -0,0 +1,26 @@ +import { defineStore } from 'pinia'; +import {api} from 'boot/axios'; +import {ptpUser, responseModel} from 'src/models'; +import Keycloak from 'keycloak-js'; + +export const useUserStore = defineStore('userStore', { + state: () => ({ + user: {"keycloakID":null,"firstName":null,"lastName":null,"username":null}, + userLoaded: false, + }), + getters: { + + }, + actions: { + getPtpUserByKeycloakID(keycloakID : string) { + this.loadPtpUsersByKeycloakID(keycloakID).then((response : responseModel) => { + this.user = response.response; + this.userLoaded = true; + console.log("ich habe das gesetzt: " + JSON.stringify(this.user) + " / " + this.userLoaded); + }); + }, + async loadPtpUsersByKeycloakID(keycloakID : string) : Promise { + return (await api.get("/users/login/"+keycloakID)).data; + }, + }, +});