From 7db52bed3f7765e94788a67f7bbc81d36c577f4a Mon Sep 17 00:00:00 2001
From: Christoph Reiter <reiter.christoph@gmail.com>
Date: Thu, 7 Oct 2021 13:17:03 +0200
Subject: [PATCH] auth-keycloak: load roles from the new frontend user entity
 instead of the person

auth.person-id is now deprecated, auth.user-id should be used instead

auth.person is now deprecated and only contains a list of roles. There is good replacement
for this at this point.
---
 packages/auth/README.md            |  3 +-
 packages/auth/src/auth-keycloak.js | 94 +++++++++++++++---------------
 2 files changed, 48 insertions(+), 49 deletions(-)

diff --git a/packages/auth/README.md b/packages/auth/README.md
index 7b082516..8da3f09c 100644
--- a/packages/auth/README.md
+++ b/packages/auth/README.md
@@ -55,8 +55,7 @@ The component emits a `dbp-set-property` event for the attribute `auth`:
 - `auth.login-status`: Login status (`unknown`, `logging-in`, `logging-out`, `logged-in`, `logged-out`)
 - `auth.token`: Keycloak token to send with your requests
 - `auth.user-full-name`: Full name of the user
-- `auth.person-id`: Person identifier of the user
-- `auth.person`: Person json object of the user
+- `auth.user-id`: Identifier of the user
 
 
 ## Login Button
diff --git a/packages/auth/src/auth-keycloak.js b/packages/auth/src/auth-keycloak.js
index 49ffc1ad..a8884b34 100644
--- a/packages/auth/src/auth-keycloak.js
+++ b/packages/auth/src/auth-keycloak.js
@@ -14,8 +14,7 @@ import {AdapterLitElement} from "@dbp-toolkit/provider/src/adapter-lit-element";
  *   auth.login-status: Login status (see object LoginStatus)
  *   auth.token: Keycloak token to send with your requests
  *   auth.user-full-name: Full name of the user
- *   auth.person-id: Person identifier of the user
- *   auth.person: Person json object of the user
+ *   auth.user-id: Identifier of the user
  */
 export class AuthKeycloak extends AdapterLitElement {
     constructor() {
@@ -24,10 +23,10 @@ export class AuthKeycloak extends AdapterLitElement {
         this.token = "";
         this.subject = "";
         this.name = "";
-        this.personId = "";
         this.tryLogin = false;
-        this.person = null;
         this.entryPointUrl = '';
+        this._user = null;
+        this._userId = "";
         this._loginStatus = LoginStatus.UNKNOWN;
         this.requestedLoginStatus = LoginStatus.UNKNOWN;
         this._i18n = createInstance();
@@ -82,9 +81,34 @@ export class AuthKeycloak extends AdapterLitElement {
         super.update(changedProperties);
     }
 
-    _onKCChanged(event) {
+    async _fetchUser(userId) {
+        let jsonld = await JSONLD.getInstance(this.entryPointUrl, this.lang);
+        let baseUrl = '';
+        try {
+            baseUrl = jsonld.getApiUrlForEntityName("FrontendUser");
+        } catch(error) {
+            // backwards compat
+            baseUrl = jsonld.getApiUrlForEntityName("Person");
+        }
+        const apiUrl = baseUrl + '/' + encodeURIComponent(userId);
+
+        let response = await fetch(apiUrl, {
+            headers: {
+                'Authorization': 'Bearer ' + this.token,
+            },
+        });
+        if (!response.ok) {
+            throw response;
+        }
+        let user = await response.json();
+        let dummyUser = {
+            roles: user['roles'] ?? [],
+        };
+        return dummyUser;
+    }
+
+    async _onKCChanged(event) {
         const kc = event.detail;
-        let newPerson = false;
 
         if (kc.authenticated) {
             let tokenChanged = (this.token !== kc.token);
@@ -92,14 +116,16 @@ export class AuthKeycloak extends AdapterLitElement {
             this.token = kc.token;
 
             this.subject = kc.subject;
-            const personId = kc.idTokenParsed.preferred_username;
-            if (personId !== this.personId) {
-                this.person = null;
-                newPerson = true;
+            const userId = kc.idTokenParsed.preferred_username;
+            let userChanged = (userId !== this._userId);
+            if (userChanged) {
+                this._userId = userId;
+                let user = await this._fetchUser(userId);
+                if (userId === this._userId) {
+                    this._user = user;
+                }
             }
-            this.personId = personId;
-
-            this._setLoginStatus(LoginStatus.LOGGED_IN, tokenChanged || newPerson);
+            this._setLoginStatus(LoginStatus.LOGGED_IN, tokenChanged || userChanged);
         } else {
             if (this._loginStatus === LoginStatus.LOGGED_IN) {
                 this._setLoginStatus(LoginStatus.LOGGING_OUT);
@@ -107,39 +133,11 @@ export class AuthKeycloak extends AdapterLitElement {
             this.name = "";
             this.token = "";
             this.subject = "";
-            this.personId = "";
-            this.person = null;
+            this._userId = "";
+            this._user = null;
 
             this._setLoginStatus(LoginStatus.LOGGED_OUT);
         }
-
-        const that = this;
-        if (newPerson) {
-            JSONLD.getInstance(this.entryPointUrl).then((jsonld) => {
-                try {
-                    // find the correct api url for the current person
-                    // we are fetching the logged-in person directly to respect the REST philosophy
-                    // see: https://github.com/api-platform/api-platform/issues/337
-                    const apiUrl = jsonld.getApiUrlForEntityName("Person") + '/' + that.personId;
-
-                    fetch(apiUrl, {
-                        headers: {
-                            'Content-Type': 'application/ld+json',
-                            'Authorization': 'Bearer ' + that.token,
-                        },
-                    })
-                        .then(response => response.json())
-                        .then((person) => {
-                            that.person = person;
-                            this._setLoginStatus(this._loginStatus, true);
-                        });
-                } catch (error) {
-                    console.warn(error);
-                    that.person = null;
-                    this._setLoginStatus(this._loginStatus, true);
-                }
-            }, {}, that.lang);
-        }
     }
 
     sendSetPropertyEvents() {
@@ -148,8 +146,10 @@ export class AuthKeycloak extends AdapterLitElement {
             'subject': this.subject,
             'token': this.token,
             'user-full-name': this.name,
-            'person-id': this.personId,
-            'person': this.person,
+            'user-id': this._userId,
+            // Deprecated
+            'person-id': this._userId,
+            'person': this._user,
         };
 
         // inject a window.DBPAuth variable for cypress
@@ -178,8 +178,8 @@ export class AuthKeycloak extends AdapterLitElement {
             name: { type: String, attribute: false },
             token: { type: String, attribute: false },
             subject: { type: String, attribute: false },
-            personId: { type: String, attribute: false },
-            person: { type: Object, attribute: false },
+            _userId: { type: String, attribute: false },
+            _user: { type: Object, attribute: false },
             _loginStatus: { type: String, attribute: false },
             keycloakUrl: { type: String, attribute: 'url' },
             realm: { type: String },
-- 
GitLab