diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..c9779090758158d5142d7c7731cd6e27808e6d90 --- /dev/null +++ b/LICENSE @@ -0,0 +1,101 @@ +OPEN-SOURCE-LIZENZ FÜR DIE EUROPÄISCHE UNION v. 1.2 +EUPL © Europäische Union 2007, 2016 +Diese Open-Source-Lizenz für die Europäische Union („EUPL“) gilt für Werke (im Sinne der nachfolgenden Begriffsbestimmung), die unter EUPL-Bedingungen zur Verfügung gestellt werden. Das Werk darf nur in der durch diese Lizenz gestatteten Form genutzt werden (insoweit eine solche Nutzung dem Urheber vorbehalten ist). +Das Werk wird unter den Bedingungen dieser Lizenz zur Verfügung gestellt, wenn der Lizenzgeber (im Sinne der nachfolgenden Begriffsbestimmung) den folgenden Hinweis unmittelbar hinter dem Urheberrechtshinweis dieses Werks anbringt: + Lizenziert unter der EUPL +oder in einer anderen Form zum Ausdruck bringt, dass er es unter der EUPL lizenzieren möchte. + +1.Begriffsbestimmungen +Für diese Lizenz gelten folgende Begriffsbestimmungen: +— „Lizenz“:diese Lizenz. +— „Originalwerk“:das Werk oder die Software, die vom Lizenzgeber unter dieser Lizenz verbreitet oder zugänglich gemacht wird, und zwar als Quellcode und gegebenenfalls auch als ausführbarer Code. +— „Bearbeitungen“:die Werke oder Software, die der Lizenznehmer auf der Grundlage des Originalwerks oder seiner Bearbeitungen schaffen kann. In dieser Lizenz wird nicht festgelegt, wie umfangreich die Änderung oder wie stark die Abhängigkeit vom Originalwerk für eine Einstufung als Bearbeitung sein muss; dies bestimmt sich nach dem Urheberrecht, das in dem unter Artikel 15 aufgeführten Land anwendbar ist. +— „Werk“:das Originalwerk oder seine Bearbeitungen. +— „Quellcode“:diejenige Form des Werkes, die zur Auffassung durch den Menschen bestimmt ist und die am besten geeignet ist, um vom Menschen verstanden und verändert zu werden. +— „Ausführbarer Code“:die — üblicherweise — kompilierte Form des Werks, die von einem Computer als Programm ausgeführt werden soll. +— „Lizenzgeber“:die natürliche oder juristische Person, die das Werk unter der Lizenz verbreitet oder zugänglich macht. +— „Bearbeiter“:jede natürliche oder juristische Person, die das Werk unter der Lizenz verändert oder auf andere Weise zur Schaffung einer Bearbeitung beiträgt. +— „Lizenznehmer“ („Sie“):jede natürliche oder juristische Person, die das Werk unter den Lizenzbedingungen nutzt. +— „Verbreitung“ oder „Zugänglichmachung“:alle Formen von Verkauf, Überlassung, Verleih, Vermietung, Verbreitung, Weitergabe, Übermittlung oder anderweitiger Online- oder Offline-Bereitstellung von Vervielfältigungen des Werks oder Zugänglichmachung seiner wesentlichen Funktionen für dritte natürliche oder juristische Personen. + +2.Umfang der Lizenzrechte +Der Lizenzgeber erteilt Ihnen hiermit für die Gültigkeitsdauer der am Originalwerk bestehenden Urheberrechte eine weltweite, unentgeltliche, nicht ausschließliche, unterlizenzierbare Lizenz, die Sie berechtigt: +— das Werk uneingeschränkt zu nutzen, +— das Werk zu vervielfältigen, +— das Werk zu verändern und Bearbeitungen auf der Grundlage des Werks zu schaffen, +— das Werk öffentlich zugänglich zu machen, was das Recht einschließt, das Werk oder Vervielfältigungsstücke davon öffentlich bereitzustellen oder wahrnehmbar zu machen oder das Werk, soweit möglich, öffentlich aufzuführen, +— das Werk oder Vervielfältigungen davon zu verbreiten, +— das Werk oder Vervielfältigungen davon zu vermieten oder zu verleihen, +— das Werk oder Vervielfältigungen davon weiter zu lizenzieren. +Für die Wahrnehmung dieser Rechte können beliebige, derzeit bekannte oder künftige Medien, Träger und Formate verwendet werden, soweit das geltende Recht dem nicht entgegensteht. Für die Länder, in denen Urheberpersönlichkeitsrechte an dem Werk bestehen, verzichtet der Lizenzgeber im gesetzlich zulässigen Umfang auf seine Urheberpersönlichkeitsrechte, um die Lizenzierung der oben aufgeführten Verwertungsrechte wirksam durchführen zu können. Der Lizenzgeber erteilt dem Lizenznehmer ein nicht ausschließliches, unentgeltliches Nutzungsrecht an seinen Patenten, sofern dies zur Ausübung der durch die Lizenz erteilten Nutzungsrechte am Werk notwendig ist. + +3.Zugänglichmachung des Quellcodes +Der Lizenzgeber kann das Werk entweder als Quellcode oder als ausführbaren Code zur Verfügung stellen. Stellt er es als ausführbaren Code zur Verfügung, so stellt er darüber hinaus eine maschinenlesbare Kopie des Quellcodes für jedes von ihm verbreitete Vervielfältigungsstück des Werks zur Verfügung, oder er verweist in einem Vermerk im Anschluss an den dem Werk beigefügten Urheberrechtshinweis auf einen Speicherort, an dem problemlos und unentgeltlich auf den Quellcode zugegriffen werden kann, solange der Lizenzgeber das Werk verbreitet oder zugänglich macht. + +4.Einschränkungen des Urheberrechts +Es ist nicht Zweck dieser Lizenz, Ausnahmen oder Schranken der ausschließlichen Rechte des Urhebers am Werk, die dem Lizenznehmer zugutekommen, einzuschränken. Auch die Erschöpfung dieser Rechte bleibt von dieser Lizenz unberührt. + +5.Pflichten des Lizenznehmers +Die Einräumung der oben genannten Rechte ist an mehrere Beschränkungen und Pflichten für den Lizenznehmer gebunden: + +Urheberrechtshinweis, Lizenztext, Nennung des Bearbeiters: Der Lizenznehmer muss alle Urheberrechts-, Patent- oder Markenrechtshinweise und alle Hinweise auf die Lizenz und den Haftungsausschluss unverändert lassen. Jedem von ihm verbreiteten oder zugänglich gemachten Vervielfältigungsstück des Werks muss der Lizenznehmer diese Hinweise sowie diese Lizenz beifügen. Der Lizenznehmer muss auf jedem abgeleiteten Werk deutlich darauf hinweisen, dass das Werk geändert wurde, und das Datum der Bearbeitung angeben. + +„Copyleft“-Klausel: Der Lizenznehmer darf Vervielfältigungen des Originalwerks oder Bearbeitungen nur unter den Bedingungen dieser EUPL oder einer neueren Version dieser Lizenz verbreiten oder zugänglich machen, außer wenn das Originalwerk ausdrücklich nur unter dieser Lizenzversion — z. B. mit der Angabe „Nur EUPL V. 1.2“ — verbreitet werden darf. Der Lizenznehmer (der zum Lizenzgeber wird) darf für das Werk oder die Bearbeitung keine zusätzlichen Bedingungen anbieten oder vorschreiben, die die Bedingungen dieser Lizenz verändern oder einschränken. + +Kompatibilitäts-Klausel: Wenn der Lizenznehmer Bearbeitungen, die auf dem Werk und einem anderen Werk, das unter einer kompatiblen Lizenz lizenziert wurde, basieren, oder die Kopien dieser Bearbeitungen verbreitet oder zugänglich macht, kann dies unter den Bedingungen dieser kompatiblen Lizenz erfolgen. Unter „kompatibler Lizenz“ ist eine im Anhang dieser Lizenz angeführte Lizenz zu verstehen. Sollten die Verpflichtungen des Lizenznehmers aus der kompatiblen Lizenz mit denjenigen aus der vorliegenden Lizenz (EUPL) in Konflikt stehen, werden die Verpflichtungen aus der kompatiblen Lizenz Vorrang haben. + +Bereitstellung des Quellcodes: Wenn der Lizenznehmer Vervielfältigungsstücke des Werks verbreitet oder zugänglich macht, muss er eine maschinenlesbare Fassung des Quellcodes mitliefern oder einen Speicherort angeben, über den problemlos und unentgeltlich so lange auf diesen Quellcode zugegriffen werden kann, wie der Lizenznehmer das Werk verbreitet oder zugänglich macht. + +Rechtsschutz: Diese Lizenz erlaubt nicht die Benutzung von Kennzeichen, Marken oder geschützten Namensrechten des Lizenzgebers, soweit dies nicht für die angemessene und übliche Beschreibung der Herkunft des Werks und der inhaltlichen Wiedergabe des Urheberrechtshinweises erforderlich ist. + +6.Urheber und Bearbeiter +Der ursprüngliche Lizenzgeber gewährleistet, dass er das Urheberrecht am Originalwerk innehat oder dieses an ihn lizenziert wurde und dass er befugt ist, diese Lizenz zu erteilen. +Jeder Bearbeiter gewährleistet, dass er das Urheberrecht an den von ihm vorgenommenen Änderungen des Werks besitzt und befugt ist, diese Lizenz zu erteilen. +Jedes Mal, wenn Sie die Lizenz annehmen, erteilen Ihnen der ursprüngliche Lizenzgeber und alle folgenden Bearbeiter eine Befugnis zur Nutzung ihrer Beiträge zum Werk unter den Bedingungen dieser Lizenz. + +7.Gewährleistungsausschluss +Die Arbeit an diesem Werk wird laufend fortgeführt; es wird durch unzählige Bearbeiter ständig verbessert. Das Werk ist nicht vollendet und kann daher Fehler („bugs“) enthalten, die dieser Art der Entwicklung inhärent sind. +Aus den genannten Gründen wird das Werk unter dieser Lizenz „so, wie es ist“ ohne jegliche Gewährleistung zur Verfügung gestellt. Dies gilt unter anderem — aber nicht ausschließlich — für Marktreife, Verwendbarkeit für einen bestimmten Zweck, Mängelfreiheit, Richtigkeit sowie Nichtverletzung von anderen Immaterialgüterrechten als dem Urheberrecht (vgl. dazu Artikel 6 dieser Lizenz). +Dieser Gewährleistungsausschluss ist wesentlicher Bestandteil der Lizenz und Bedingung für die Einräumung von Rechten an dem Werk. + +8.Haftungsausschluss/Haftungsbeschränkung +Außer in Fällen von Vorsatz oder der Verursachung von Personenschäden haftet der Lizenzgeber nicht für direkte oder indirekte, materielle oder immaterielle Schäden irgendwelcher Art, die aus der Lizenz oder der Benutzung des Werks folgen; dies gilt unter anderem, aber nicht ausschließlich, für Firmenwertverluste, Produktionsausfall, Computerausfall oder Computerfehler, Datenverlust oder wirtschaftliche Schäden, und zwar auch dann, wenn der Lizenzgeber auf die Möglichkeit solcher Schäden hingewiesen wurde. Unabhängig davon haftet der Lizenzgeber im Rahmen der gesetzlichen Produkthaftung, soweit die entsprechenden Regelungen auf das Werk anwendbar sind. + +9.Zusatzvereinbarungen +Wenn Sie das Werk verbreiten, können Sie Zusatzvereinbarungen schließen, in denen Verpflichtungen oder Dienstleistungen festgelegt werden, die mit dieser Lizenz vereinbar sind. Sie dürfen Verpflichtungen indessen nur in Ihrem eigenen Namen und auf Ihre eigene Verantwortung eingehen, nicht jedoch im Namen des ursprünglichen Lizenzgebers oder eines anderen Bearbeiters, und nur, wenn Sie sich gegenüber allen Bearbeitern verpflichten, sie zu entschädigen, zu verteidigen und von der Haftung freizustellen, falls aufgrund der von Ihnen eingegangenen Gewährleistungsverpflichtung oder Haftungsübernahme Forderungen gegen sie geltend gemacht werden oder eine Haftungsverpflichtung entsteht. + +10.Annahme der Lizenz +Sie können den Bestimmungen dieser Lizenz zustimmen, indem Sie das Symbol „Lizenz annehmen“ unter dem Fenster mit dem Lizenztext anklicken oder indem Sie Ihre Zustimmung auf vergleichbare Weise in einer nach anwendbarem Recht zulässigen Form geben. Das Anklicken des Symbols gilt als Anzeichen Ihrer eindeutigen und unwiderruflichen Annahme der Lizenz und der darin enthaltenen Klauseln und Bedingungen. In gleicher Weise gilt als Zeichen der eindeutigen und unwiderruflichen Zustimmung die Ausübung eines Rechtes, das in Artikel 2 dieser Lizenz angeführt ist, wie das Erstellen einer Bearbeitung oder die Verbreitung oder Zugänglichmachung des Werks oder dessen Vervielfältigungen. + +11.Informationspflichten +Wenn Sie das Werk verbreiten oder zugänglich machen (beispielsweise, indem Sie es zum Herunterladen von einer Website anbieten), müssen Sie über den Vertriebskanal oder das benutzte Verbreitungsmedium der Öffentlichkeit zumindest jene Informationen bereitstellen, die nach dem anwendbaren Recht bezüglich der Lizenzgeber, der Lizenz und ihrer Zugänglichkeit, des Abschlusses des Lizenzvertrags sowie darüber, wie die Lizenz durch den Lizenznehmer gespeichert und vervielfältigt werden kann, erforderlich sind. + +12.Beendigung der Lizenz +Die Lizenz und die damit eingeräumten Rechte erlöschen automatisch, wenn der Lizenznehmer gegen die Lizenzbedingungen verstößt. Ein solches Erlöschen der Lizenz führt nicht zum Erlöschen der Lizenzen von Personen, denen das Werk vom Lizenznehmer unter dieser Lizenz zur Verfügung gestellt worden ist, solange diese Personen die Lizenzbedingungen erfüllen. +13.Sonstiges +Unbeschadet des Artikels 9 stellt die Lizenz die vollständige Vereinbarung der Parteien über das Werk dar. Sind einzelne Bestimmungen der Lizenz nach geltendem Recht nichtig oder unwirksam, so berührt dies nicht die Wirksamkeit oder Durchsetzbarkeit der Lizenz an sich. Solche Bestimmungen werden vielmehr so ausgelegt oder modifiziert, dass sie wirksam und durchsetzbar sind. Die Europäische Kommission kann weitere Sprachfassungen oder neue Versionen dieser Lizenz oder aktualisierte Fassungen des Anhangs veröffentlichen, soweit dies notwendig und angemessen ist, ohne den Umfang der Lizenzrechte zu verringern. Neue Versionen werden mit einer eindeutigen Versionsnummer veröffentlicht. Alle von der Europäischen Kommission anerkannten Sprachfassungen dieser Lizenz sind gleichwertig. Die Parteien können sich auf die Sprachfassung ihrer Wahl berufen. + +14.Gerichtsstand +Unbeschadet besonderer Vereinbarungen zwischen den Parteien gilt Folgendes: +— Für alle Streitigkeiten über die Auslegung dieser Lizenz zwischen den Organen, Einrichtungen und sonstigen Stellen der Europäischen Union als Lizenzgeber und einem Lizenznehmer ist der Gerichtshof der Europäischen Union gemäß Artikel 272 des Vertrags über die Arbeitsweise der Europäischen Union zuständig; +— Gerichtsstand für Streitigkeiten zwischen anderen Parteien über die Auslegung dieser Lizenz ist allein der Ort, an dem der Lizenzgeber seinen Wohnsitz oder den wirtschaftlichen Mittelpunkt seiner Tätigkeit hat. + +15.Anwendbares Recht +Unbeschadet besonderer Vereinbarungen zwischen den Parteien gilt Folgendes: +— Diese Lizenz unterliegt dem Recht des Mitgliedstaats der Europäischen Union, in dem der Lizenzgeber seinen Sitz, Wohnsitz oder eingetragenen Sitz hat; +— diese Lizenz unterliegt dem belgischen Recht, wenn der Lizenzgeber keinen Sitz, Wohnsitz oder eingetragenen Sitz in einem Mitgliedstaat der Europäischen Union hat. + +Anlage +„Kompatible Lizenzen“ nach Artikel 5 der EUPL sind: +— GNU General Public License (GPL) v. 2, v. 3 +— GNU Affero General Public License (AGPL) v. 3 +— Open Software License (OSL) v. 2.1, v. 3.0 +— Eclipse Public License (EPL) v. 1.0 +— CeCILL v. 2.0, v. 2.1 +— Mozilla Public Licence (MPL) v. 2 +— GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +— Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) für andere Werke als Software +— European Union Public Licence (EUPL) v. 1.1, v. 1.2 +— Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) oder Strong Reciprocity (LiLiQ-R+) +Die Europäische Kommission kann diesen Anhang aktualisieren, um neuere Fassungen der obigen Lizenzen aufzunehmen, ohne hierfür eine neue Fassung der EUPL auszuarbeiten, solange diese Lizenzen die in Artikel 2 gewährten Rechte gewährleisten und den erfassten Quellcode vor ausschließlicher Aneignung schützen. +Alle sonstigen Änderungen oder Ergänzungen dieses Anhangs bedürfen der Ausarbeitung einer neuen Version der EUPL. diff --git a/README.md b/README.md index 27d0110791315c6e801ddde881588825d5430e8f..f2ef57cfd6dbad35ef5ba71f80a5db147d598393 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,25 @@ -# user-manager Project +# user-manager This project uses Quarkus, the Supersonic Subatomic Java Framework. If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ . ## Configuring the application -This properties mist be configured to run the application - -quarkus.mongodb.connection-string=<The connection string for the mongo db database> -quarkus.mongodb.database=<name of the mongo db database> -usermanager.keycloak.sync.cron=<default is "0 15 2 * * ?" > -usermanager.keycloak.api.user=< the name of the keycloak admin api user, default: goofyApiUser> -usermanager.keycloak.api.password=< the password of the keycloak admin api user> -usermanager.keycloak.api.realm=<The name of the realm> -usermanager.keycloak.api.organisations-einheit-id-key=< The key where the organisationsEinheitId of the group is saved, default is 'organisationseinheitId'> - +This properties must be configured to run the application + +| Key | Value | Default | Mandatory | Description | +|----------------------------------------------------|----------------------------------------------------|------------------------| --------- |----------------------------------------------------------------| +| quarkus.oidc.auth-server-url | https://sso.dev.by.ozg-cloud.de/realms/sh-kiel-dev | none | yes | Url of the keycloak server with the realm | +| quarkus.mongodb.connection-string | mongodb://ozg-mongodb:27017 | none | yes | The connection string for the mongo db database | +| quarkus.mongodb.database | usermanager | usermanager | no | Name of the mongo db database | +| ozgcloud.keycloak.sync.period | 5m | 6h | no | Period between synchronizations | +| ozgcloud.keycloak.api.user | apiUser | none | yes | The name of the keycloak admin api user | +| ozgcloud.keycloak.api.password | **** | none | yes | The password of the keycloak admin api user | +| ozgcloud.keycloak.api.realm | realm-name | none | yes | The name of the realm | +| ozgcloud.keycloak.api.organisations-einheit-id-key | organisationseinheitId | organisationseinheitId | no | The key where the organisationsEinheitId of the group is saved | +| ozgcloud.keycloak.api.ldap-id-key | LDAP_ID | LDAP_ID | no | The key to get the keycloak user id from | +| ozgcloud.user-manager.url | http://localhost:8080 | none | yes | The external root url of the usermanager | +| keycloak.url | https://sso.service | none | yes | The root url of the keycloak service | ## Running the application in dev mode @@ -25,6 +30,27 @@ You can run your application in dev mode that enables live coding using: > **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/. +> If you want to use remote Keycloak for local development, then use the profile remotekc. Be aware, +> that it deactivates synchronization - if you need it, then you have to create your own realm and +> set it in properties, like this: +> ```yaml +> keycloak: +> realm: your-realm +> ozgcloud: +> usersync: +> period: "6h" +> ``` + +## Running the server with custom realm +In order to start user-manager-server connecting againts dev keycloak locally with custom realm +use below configuration in your IDE or CLI. +``` +-Dquarkus.profile=local,remotekc +-Dquarkus.oidc.auth-server-url=https://sso.dev.by.ozg-cloud.de/realms/sebo-test +-Dozgcloud.keycloak.api.realm=sebo-test +-Dozgcloud.usersync.period="5s" +``` + ## Packaging and running the application The application can be packaged using: @@ -85,3 +111,115 @@ Monitor your application's health using SmallRye Health This involves injection fields, constructors and initializers, observer methods, producer methods and fields, disposers and interceptor methods. [See section 2 of quarkus guide ](https://quarkus.io/guides/cdi-reference#native-executables-and-private-members) + + +## Quarkus Speichernutzung + +### Usermanager Einstellungen + +Usermanager als über-jar erstellen und lokal starten: + +```bash +./mvnw clean package -Dquarkus.package.type=uber-jar + +java -Dquarkus.oidc.auth-server-url=https://sso.dev.by.ozg-cloud.de/realms/by-kiel-dev \ + -Dozgcloud.user-manager.url=http://localhost:8080 \ + -Dkeycloak.url=https://sso.dev.by.ozg-cloud.de \ + -jar ./target/user-manager-server-1.3.0-SNAPSHOT-runner.jar +``` + +Usermanager als native Anwendung erstellen und lokal starten: + +```bash +./mvnw clean package -Pnative + +./target/user-manager-server-1.3.0-SNAPSHOT-runner \ + -Dquarkus.oidc.auth-server-url=https://sso.dev.by.ozg-cloud.de/realms/by-kiel-dev \ + -Dquarkus.mongodb.connection-string=mongodb://localhost:27018 \ + -Dozgcloud.user-manager.url=http://localhost:8080 \ + -Dkeycloak.url=https://sso.dev.by.ozg-cloud.de \ + -Dozgcloud.keycloak.api.user=usermanagerapiuser \ + -Dozgcloud.keycloak.api.password=hlc_j1I1Ji0trC0 \ + -Dozgcloud.keycloak.api.realm=by-kiel-dev \ + -Dozgcloud.keycloak.api.client=alfa \ + -Dozgcloud.usersync.period="5m" \ + -Xmx32m +``` + +### Commands + +Anzeigen des Verwendeten Speichers: + +```bash +ps -e -o pid,rss,args | grep application +``` + +Anzeigen der Details der Speichernutzung: + +```bash +pmap -x [pid] +``` + +Loggen der Speichernutzung in Datei: + +```bash +top -b -d1 -o +%MEM | grep user-manager >> usermanager_Xmx32m_long.tsv +``` + +### Quarkus Speicherverwendung + +Minimale quarkus features: cdi, resteasy-reactive, smallrye-context-propagation, vertx + +#### Verbrauchter Speicher ohne festgelegtem Heapspace + +| Application | Selected additional features | Memory Usage in MB | +| ----------- | ------------------- | ------------ | +| quarkus-test-min-1.0.0-SNAPSHOT-runner | - | 39,232 | +| quarkus-test-1.0.0-SNAPSHOT-runner | resteasy-reactive-jackson | 44,172 | +| quarkus-test-db-1.0.0-SNAPSHOT-runner | mongodb-client, mongodb-panache, narayana-jta, resteasy-reactive-jackson | 46,936 | +| quarkus-test-um-1.0.0-SNAPSHOT-runner | config-yaml, grpc-server, micrometer, mongodb-client, mongodb-panache, narayana-jta, smallrye-health, scheduler | 52,068 | +| quarkus-test-oidc-1.0.0-SNAPSHOT-runner | config-yaml, grpc-server, micrometer, mongodb-client, mongodb-panache, narayana-jta, smallrye-health, scheduler, oidc, keycloak-admin | 71,580 | +| user-manager-server-1.3.0-SNAPSHOT-runner | Usermanager Projekt | 124,164 | + +#### Speicher bei Last + +Lastest wurde über SoapUI (Projekt Usermanager user-manager-server/src/test/resources/Usermanager-REST-Last.xml) gemacht + +| Heapspace | max Memory Usage in MB | max Transactions/s | +| --------- | ---------------------- | ------------------ | +| default | 160 | 300 | +| 32m | 99 | 115 | + +#### Empfohlene Speichereinstellungen + +Prod: + +```yaml + limits: + cpu: "500m" + memory: "192Mi" + requests: + cpu: "50m" + memory: "192Mi" +``` + +Dev: + +```yaml + limits: + cpu: "500m" + memory: "100Mi" + requests: + cpu: "50m" + memory: "100Mi" +``` + +### Weitere Urls + +<https://e.printstacktrace.blog/graalvm-heap-size-of-native-image-how-to-set-it/> + +<https://quarkus.io/guides/performance-measure> + +<https://www.graalvm.org/22.0/reference-manual/native-image/MemoryManagement/> + +<https://github.com/quarkusio/quarkus/issues/22757> diff --git a/build-native-local-docker-image.sh b/build-native-local-docker-image.sh new file mode 100755 index 0000000000000000000000000000000000000000..ab1c459a98a531eea6efa08d8bd1556a83baf9b4 --- /dev/null +++ b/build-native-local-docker-image.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + + +export QUARKUS_CONTAINER_IMAGE_NAME=user-manager +export QUARKUS_CONTAINER_IMAGE_TAG=build-latest +export QUARKUS_NATIVE_CONTAINER_RUNTIME=docker +cd user-manager-server +./mvnw clean install -D skipTests \ + -Pnative \ + -Dquarkus.container-image.registry=docker.ozg-sh.de \ + -Dquarkus.container-image.push=false \ + -Dquarkus.container-image.build=true \ + -Dquarkus.native.remote-container-build=false \ No newline at end of file diff --git a/dependency-check-supressions.xml b/dependency-check-supressions.xml new file mode 100644 index 0000000000000000000000000000000000000000..db1350f8a83ff8c231b055286a017cd62152964f --- /dev/null +++ b/dependency-check-supressions.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + Ministerpräsidenten des Landes Schleswig-Holstein + Staatskanzlei + Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + + Lizenziert unter der EUPL, Version 1.2 oder - sobald + diese von der Europäischen Kommission genehmigt wurden - + Folgeversionen der EUPL ("Lizenz"); + Sie dürfen dieses Werk ausschließlich gemäß + dieser Lizenz nutzen. + Eine Kopie der Lizenz finden Sie hier: + + https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + + Sofern nicht durch anwendbare Rechtsvorschriften + gefordert oder in schriftlicher Form vereinbart, wird + die unter der Lizenz verbreitete Software "so wie sie + ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + ausdrücklich oder stillschweigend - verbreitet. + Die sprachspezifischen Genehmigungen und Beschränkungen + unter der Lizenz sind dem Lizenztext zu entnehmen. + +--> +<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd"> + <suppress> + <vulnerabilityName>CVE-DUMMY</vulnerabilityName> + </suppress> +</suppressions> \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2b069ba0d883cda4e84d37e98c7a78dec369f805..dd4499663669152bb1f7800a993b15e2b0fddd4d 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,7 @@ +<?xml version="1.0"?> <!-- - Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den Ministerpräsidenten des Landes Schleswig-Holstein Staatskanzlei Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -23,33 +24,107 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <parent> + <groupId>de.ozgcloud.common</groupId> + <artifactId>ozgcloud-common-dependencies</artifactId> + <version>3.0.1</version> + </parent> <modelVersion>4.0.0</modelVersion> - <groupId>de.itvsh.kop</groupId> + <groupId>de.ozgcloud.user</groupId> <artifactId>user-manager</artifactId> - <version>1.2.0</version> - - <name>User Manager Parent</name> + <version>2.1.0</version> + <name>OZG-Cloud User Manager</name> <packaging>pom</packaging> - + <properties> - <kop.license.version>1.3.0</kop.license.version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + + <quarkus.platform.version>3.5.0</quarkus.platform.version> + <ozgcloud.license.version>1.6.0</ozgcloud.license.version> + <jakarta.interceptor.version>2.1.0</jakarta.interceptor.version> + <jakarta.annotatioin.version>2.1.1</jakarta.annotatioin.version> + <lombok.version>1.18.24</lombok.version> + <keycloak-adapter.version>22.0.5</keycloak-adapter.version> + + <!-- plugins --> + <maven.compiler.release>17</maven.compiler.release> + <jandex-maven-plugin-version>1.2.3</jandex-maven-plugin-version> + <compiler-plugin.version>3.8.1</compiler-plugin.version> + <jacoco.plugin.version>0.8.8</jacoco.plugin.version> + <surefire-plugin.version>3.2.2</surefire-plugin.version> + <maven-failsafe-plugin.version>3.2.2</maven-failsafe-plugin.version> + <git-commit-id-plugin.version>4.9.10</git-commit-id-plugin.version> + <maven-source.plugin.version>3.3.0</maven-source.plugin.version> </properties> <modules> - <module>user-manager-server</module> <module>user-manager-interface</module> + <module>user-manager-server</module> </modules> - + + <dependencyManagement> + <dependencies> + <!-- Modules --> + <dependency> + <groupId>de.ozgcloud.user</groupId> + <artifactId>user-manager-interface</artifactId> + <version>${project.version}</version> + </dependency> + + <!-- Quarkus --> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom</artifactId> + <version>${quarkus.platform.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + + <!-- Jakarta --> + <dependency> + <groupId>jakarta.interceptor</groupId> + <artifactId>jakarta.interceptor-api</artifactId> + <version>${jakarta.interceptor.version}</version> + </dependency> + <dependency> + <groupId>jakarta.annotation</groupId> + <artifactId>jakarta.annotation-api</artifactId> + <version>${jakarta.annotatioin.version}</version> + </dependency> + + <!-- Mapstruct --> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct</artifactId> + <version>${mapstruct.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct-processor</artifactId> + <version>${mapstruct.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> + </dependencyManagement> + <build> <pluginManagement> - <plugins> + <plugins> <plugin> <groupId>com.mycila</groupId> <artifactId>license-maven-plugin</artifactId> <version>4.1</version> <configuration> + <mapping> + <config>SCRIPT_STYLE</config> + </mapping> <licenseSets> <licenseSet> <header>license/eupl_v1_2_de/header.txt</header> @@ -63,27 +138,108 @@ </configuration> <dependencies> <dependency> - <groupId>de.itvsh.kop.common</groupId> - <artifactId>kop-common-license</artifactId> - <version>${kop.license.version}</version> + <groupId>de.ozgcloud.common</groupId> + <artifactId>ozgcloud-common-license</artifactId> + <version>${ozgcloud.license.version}</version> </dependency> </dependencies> </plugin> + <plugin> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.jboss.jandex</groupId> + <artifactId>jandex-maven-plugin</artifactId> + <version>${jandex-maven-plugin-version}</version> + <executions> + <execution> + <id>make-index</id> + <goals> + <goal>jandex</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire-plugin.version}</version> + </plugin> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${maven-failsafe-plugin.version}</version> + </plugin> + <plugin> + <groupId>pl.project13.maven</groupId> + <artifactId>git-commit-id-plugin</artifactId> + <version>${git-commit-id-plugin.version}</version> + <executions> + <execution> + <id>get-the-git-infos</id> + <phase>initialize</phase> + <goals> + <goal>revision</goal> + </goals> + </execution> + </executions> + <configuration> + <offline>true</offline> + </configuration> + </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>${jacoco.plugin.version}</version> + <executions> + <execution> + <id>start-agent</id> + <goals> + <goal>prepare-agent</goal> + </goals> + <configuration> + <propertyName>surefire.jacoco.args</propertyName> + <exclClassLoaders>*QuarkusClassLoader</exclClassLoaders> + <destFile>${project.build.directory}/jacoco-quarkus.exec</destFile> + <append>true</append> + </configuration> + </execution> + <execution> + <id>generate-report</id> + <phase>package</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>${maven-source.plugin.version}</version> + <executions> + <execution> + <id>attach-sources</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </pluginManagement> </build> - - <distributionManagement> - <repository> - <id>ozg-nexus</id> - <name>ozg-releases</name> - <url>https://nexus.ozg-sh.de/repository/ozg-releases/</url> - </repository> - <snapshotRepository> - <id>ozg-snapshots-nexus</id> - <name>ozg-snapshots</name> - <url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url> - </snapshotRepository> - </distributionManagement> </project> - diff --git a/release-erstellen.sh b/release-erstellen.sh new file mode 100755 index 0000000000000000000000000000000000000000..a5f3ac8504c3079b9c257fda15dd63422290d8d3 --- /dev/null +++ b/release-erstellen.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + + +if [ "$#" -ne 1 ]; then + echo "Aufruf: ozg-release-erstellen.sh JA" + echo "Als Parameter bitte 'JA' eintragen zur Sicherheit" + exit 1 +fi + + +## alle -SNAPSHOT in pom.xmls entfernen +SED_PARAMS="-i" +if [[ "$OSTYPE" =~ ^darwin ]]; then + SED_PARAMS="$SED_PARAMS '' -e" +fi +find . -name pom.xml -exec sed $SED_PARAMS 's/-SNAPSHOT//g' {} + + +## release version auslesen +NEWVERSION=$(xmlstarlet sel -N w="http://maven.apache.org/POM/4.0.0" -t -v '//w:project/w:version' -n pom.xml) + +echo +echo "NEXT STEPS:" +echo "***********" +echo "Änderungen prüfen" +echo "git commit -a -m 'release version "$NEWVERSION"'" +echo "git push" +echo "git tag "$NEWVERSION +echo "git push --tags" diff --git a/release-startdev.sh b/release-startdev.sh new file mode 100755 index 0000000000000000000000000000000000000000..ec754656b6b78dac7104413f712e84ec4e88601f --- /dev/null +++ b/release-startdev.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + + +#set -x + +if [ "$#" -ne 1 ]; then + echo "Aufruf: ozg-release-startdev.sh NEWVERSION" + exit 1 +fi + +NEWVERSION=$1 + +echo + +# pom.xml:main -> project.version setzen +# projectname/pom.xml:parent -> project.parent.version setzen +# projectname/pom.xml:parent,main -> project.parent.version und project.version setzen +# +PROJECTS="pom.xml:main + user-manager-interface/pom.xml:main + user-manager-server/pom.xml:main + " + +for PROJECT in $PROJECTS; +do + POMFILE=$(echo $PROJECT | cut -d':' -f1) + ACTIONS=$(echo $PROJECT | cut -d':' -f2) + + ## Auf SNAPSHOT Versionen testen + if fgrep -q "SNAPSHOT" $POMFILE; then + RED='\033[0;31m' + NC='\033[0m' + echo "${RED}ERROR: Datei "$POMFILE" enthält noch SNAPSHOT Versionen, das sollte hier nicht passieren.${NC}" + exit 1 + fi +echo $ACTIONS + ## Versionen setzen + if [[ $ACTIONS == "main" ]] ; then + xmlstarlet ed --pf -L -N w="http://maven.apache.org/POM/4.0.0" -u '//w:project/w:version' -v $NEWVERSION $POMFILE + fi + + if [[ $ACTIONS == "parent" ]]; then + xmlstarlet ed --pf -L -N w="http://maven.apache.org/POM/4.0.0" -u '//w:project/w:parent/w:version' -v $NEWVERSION $POMFILE + fi +done + + + +echo +echo "NEXT STEPS:" +echo "***********" +echo "Änderungen prüfen" +echo "git commit -a -m 'start development "$NEWVERSION"'" +echo "git push" + diff --git a/run_helm_test.sh b/run_helm_test.sh new file mode 100755 index 0000000000000000000000000000000000000000..f4ed8c6209d0193bfac0ee4a13720e6b55e5641f --- /dev/null +++ b/run_helm_test.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + + +set -e +set -x + +helm template ./src/main/helm/ -f src/test/linter-values.yaml +helm lint -f src/test/linter-values.yaml ./src/main/helm/ +cd src/main/helm && helm unittest --helm3 -f '../../test/helm/*.yaml' -v '../../test/unit-values.yaml' . \ No newline at end of file diff --git a/run_local.sh b/run_local.sh new file mode 100755 index 0000000000000000000000000000000000000000..14d64ebbc85f9c584ae3c106134e5e05c61b7109 --- /dev/null +++ b/run_local.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +./mvnw -pl user-manager-server quarkus:dev -Dquarkus.profile=local,remotekc \ No newline at end of file diff --git a/src/main/helm/Chart.yaml b/src/main/helm/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..24c5819fe141db1b085d078c67cf7a56a48b3203 --- /dev/null +++ b/src/main/helm/Chart.yaml @@ -0,0 +1,30 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart for UserManager +name: user-manager +version: 0.0.0-MANAGED-BY-JENKINS +icon: https://simpleicons.org/icons/helm.svg \ No newline at end of file diff --git a/src/main/helm/README.md b/src/main/helm/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c7e009cd83e68c95334a46619915723634859987 --- /dev/null +++ b/src/main/helm/README.md @@ -0,0 +1,35 @@ +# Helm + +## Linter + +`helm lint -f test-values.yaml` + +## Unit-Tests + +Für Unit-Tests wird das helm [helm-unittest](https://github.com/quintush/helm-unittest) plugin benötigt. Die Unit-Tests liegen im Verzeichnis src/test/helm + +`helm unittest -f '../../test/helm/*.yaml' -v '../../test/unit-values.yaml' .` + +## SyntaxCheck + +`helm template --debug -f test-values.yaml .` + +## Package + +`helm package --version=[version] .` + +## Versionierung + +Jenkins verwendet die Version aus der pom.xml + +### Master Branch + +Im master Branch werden die ersten 7 Zeichen vom git commit hash an die Version gehangen. + +### Release Branch + +Ist nur die Version aus der pom.xml + +### Feature Branch + +In einem feature Branch wird der Branchname an die Version gehangen. diff --git a/src/main/helm/templates/_helpers.tpl b/src/main/helm/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..c75701fd803c0c182d21d01a5d956092df489911 --- /dev/null +++ b/src/main/helm/templates/_helpers.tpl @@ -0,0 +1,139 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* Truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec) */}} +{{/* Name */}} +{{- define "app.name" -}} +{{- default .Release.Name | toString | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* Namespace */}} +{{- define "app.namespace" -}} +{{- default .Release.Namespace | toString | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* Version */}} +{{- define "app.version" -}} +{{- default .Chart.Version | toString | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* Chart: Name + Version */}} +{{- define "app.chart" -}} +{{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* Managed-by -> On Helm, this value is always Helm */}} +{{- define "app.managedBy" -}} +{{- default .Release.Service | toString | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* Default Labels: Helm recommended best-practice labels https://helm.sh/docs/chart_best_practices/labels/ */}} +{{- define "app.defaultLabels" }} +app.kubernetes.io/instance: user-manager +app.kubernetes.io/managed-by: {{ include "app.managedBy" . }} +app.kubernetes.io/name: {{ include "app.name" . }} +app.kubernetes.io/namespace: {{ include "app.namespace" . }} +app.kubernetes.io/part-of: ozgcloud +app.kubernetes.io/version: {{ include "app.version" . }} +helm.sh/chart: {{ include "app.chart" . }} +{{- end -}} + +{{- define "app.matchLabels" }} +app.kubernetes.io/name: {{ include "app.name" . }} +app.kubernetes.io/namespace: {{ include "app.namespace" . }} +{{- end -}} + +{{- define "app.imagePullSecret" }} +{{- with .Values.imageCredentials }} +{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }} +{{- end }} +{{- end }} + +{{- define "app.cronjobScheduler" }} +{{- printf "%d %d * * *" (div (randNumeric 2) 2) (div (randNumeric 1) 2) -}} +{{- end -}} + +{{- define "app.ozgcloudEnvironment" -}} +{{- required "Environment muss angegeben sein" (.Values.ozgcloud).environment -}} +{{- end -}} + +{{- define "app.ssoServerUrl" -}} +{{- if contains "https://" .Values.sso.serverUrl -}} +{{- .Values.sso.serverUrl -}} +{{- else -}} +{{- printf "https://%s" .Values.sso.serverUrl -}} +{{- end -}} +{{- end -}} + +{{- define "app.ozgcloudBundesland" -}} +{{- required "ozgcloud.bundesland must be set " (.Values.ozgcloud).bundesland }} +{{- end -}} + +{{- define "app.ozgcloudBezeichner" -}} +{{- if (.Values.ozgcloud).bezeichner -}} + +{{ $length := len (.Values.ozgcloud).bezeichner }} +{{- if lt 27 $length -}} +{{ required (printf "Bezeichner %s ist zu lang (max. 27 Zeichen)" (.Values.ozgcloud).bezeichner) nil }} +{{- else -}} +{{- required "Bezeichner muss angegeben sein" (.Values.ozgcloud).bezeichner -}} +{{- end -}} +{{- else -}} +{{- required "Bezeichner muss angegeben sein" (.Values.ozgcloud).bezeichner -}} +{{- end -}} +{{- end -}} + +{{- define "app.ssoRealm" -}} +{{ printf "%s-%s-%s" (include "app.ozgcloudBundesland" .) ( include "app.ozgcloudBezeichner" . ) ( include "app.ozgcloudEnvironment" . ) | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{- define "app.ssoClientName" -}} +{{- if (.Values.sso).client_name -}} +{{ printf "%s" (.Values.sso).client_name }} +{{- else -}} +{{ printf "alfa" }} +{{- end -}} +{{- end -}} + +{{- define "app.baseUrl" -}} +{{ printf "https://%s-%s.%s" (include "app.ozgcloudBezeichner" .) (include "app.name" .) .Values.baseUrl }} +{{- end -}} + +{{- define "app.alfaAddress" -}} +{{ printf "https://%s.%s" (include "app.ozgcloudBezeichner" .) .Values.baseUrl }} +{{- end -}} + +{{- define "app.replaceAllNonAlphanumeric" -}} +{{- regexReplaceAll "[^a-zA-Z0-9]" . "" }} +{{- end -}} + +{{- define "app.generateKeycloakUserRessourceName" -}} +{{- $lowerUserName := .Values.sso.api_user.name | lower }} +{{- $alphanumericUserName := (include "app.replaceAllNonAlphanumeric" $lowerUserName ) }} +{{- printf "%s-keycloak-user" ( $alphanumericUserName | trunc 20) }} +{{- end -}} + +{{- define "app.generateKeycloakUserSecretName" -}} +{{- $lowerUserName := .Values.sso.api_user.name | lower }} +{{- $alphanumericUserName := (include "app.replaceAllNonAlphanumeric" $lowerUserName ) }} +{{- printf "%s-credentials" ( $alphanumericUserName | trunc 20) }} +{{- end -}} + +{{- define "app.databaseSecretName" -}} +{{- if (.Values.database).secretName -}} +{{ .Values.database.secretName }} +{{- else -}} +{{ printf "ozg-mongodb-admin-user-manager-user" }} +{{- end -}} +{{- end -}} + +{{- define "app.databaseName" -}} +{{- if (.Values.database).databaseName -}} +{{ .Values.database.databaseName }} +{{- else -}} +{{ printf "user-manager-database" }} +{{- end -}} +{{- end -}} + +{{- define "app.serviceAccountName" -}} +{{ printf "%s" ( (.Values.serviceAccount).name | default "user-manager-service-account" ) }} +{{- end -}} \ No newline at end of file diff --git a/src/main/helm/templates/api-password-secret.yaml b/src/main/helm/templates/api-password-secret.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dd655e103de6ebf4a068e02a17bc5d5cc3b7813a --- /dev/null +++ b/src/main/helm/templates/api-password-secret.yaml @@ -0,0 +1,35 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if and (not (.Values.sso).api_user) (((.Values.ozgcloud).keycloak).api).password -}} +apiVersion: v1 +kind: Secret +metadata: + name: user-manager-api-password + labels: + {{- include "app.defaultLabels" . | indent 4 }} +type: Opaque +stringData: + password: {{ required "ozgcloud.keycloak.api.password must be set" .Values.ozgcloud.keycloak.api.password }} +{{- end -}} \ No newline at end of file diff --git a/src/main/helm/templates/cert_issuer.yaml b/src/main/helm/templates/cert_issuer.yaml new file mode 100644 index 0000000000000000000000000000000000000000..90ca7b6d569dff0a7c2e3e964e0bf75faf36a4d2 --- /dev/null +++ b/src/main/helm/templates/cert_issuer.yaml @@ -0,0 +1,31 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: user-manager-issuer + namespace: {{ include "app.namespace" . }} +spec: + selfSigned: {} \ No newline at end of file diff --git a/src/main/helm/templates/certificate.yaml b/src/main/helm/templates/certificate.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4186f058e1b4e46a5362dfdffa98f614d2e2d2ea --- /dev/null +++ b/src/main/helm/templates/certificate.yaml @@ -0,0 +1,44 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: user-manager-tls-certificate + namespace: {{ include "app.namespace" . }} +spec: + secretName: user-manager-tls-cert + issuerRef: + name: user-manager-issuer + kind: Issuer + duration: 8760h0m0s + renewBefore: 720h0m0s + commonName: {{ include "app.name" . }} + dnsNames: + - "*.{{ include "app.name" . }}.{{ include "app.namespace" . }}.svc.cluster.local" + - "{{ include "app.name" . }}.{{ include "app.namespace" . }}.svc.cluster.local" + - "{{ include "app.name" . }}.{{ include "app.namespace" . }}.svc.cluster" + - "{{ include "app.name" . }}.{{ include "app.namespace" . }}.svc" + - "{{ include "app.name" . }}.{{ include "app.namespace" . }}" + - "{{ include "app.name" . }}" \ No newline at end of file diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d8dcee246d7bf038cae687362fcae04001b51927 --- /dev/null +++ b/src/main/helm/templates/deployment.yaml @@ -0,0 +1,211 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "app.name" . }} + namespace: {{ include "app.namespace" . }} + labels: + {{- include "app.defaultLabels" . | indent 4 }} + annotations: +spec: + progressDeadlineSeconds: 600 + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: 10 + selector: + matchLabels: + {{- include "app.matchLabels" . | indent 6 }} + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + type: RollingUpdate + template: + metadata: + labels: + {{- include "app.defaultLabels" . | indent 8 }} + component: user-manager + spec: + {{- if (.Values.serviceAccount).create }} + serviceAccountName: {{ include "app.serviceAccountName" . }} + {{- end }} + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/name: {{ include "app.name" . }} + containers: + - env: + - name: QUARKUS_MONGODB_CONNECTION_STRING + valueFrom: + secretKeyRef: + name: {{ include "app.databaseSecretName" . }} + key: connectionString.standard + optional: false + {{- if not (.Values.sso).api_user }} + - name: OZGCLOUD_KEYCLOAK_API_PASSWORD + valueFrom: + secretKeyRef: + name: user-manager-api-password + key: password + optional: false + - name: OZGCLOUD_KEYCLOAK_API_USER + value: {{ .Values.ozgcloud.keycloak.api.user }} + {{- else }} + - name: OZGCLOUD_KEYCLOAK_API_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "app.generateKeycloakUserSecretName" . }} + key: password + optional: false + - name: OZGCLOUD_KEYCLOAK_API_USER + valueFrom: + secretKeyRef: + name: {{ include "app.generateKeycloakUserSecretName" . }} + key: name + optional: false + {{- end }} + - name: QUARKUS_MONGODB_DATABASE + value: {{ include "app.databaseName" . }} + - name: OZGCLOUD_KEYCLOAK_API_REALM + value: {{ include "app.ssoRealm" . }} + - name: OZGCLOUD_KEYCLOAK_API_CLIENT + value: {{ include "app.ssoClientName" . }} + - name: QUARKUS_OIDC_AUTH_SERVER_URL + value: {{ include "app.ssoServerUrl" . }}/realms/{{ include "app.ssoRealm" . }} + - name: KEYCLOAK_URL + value: {{ include "app.ssoServerUrl" . }} + - name: OZGCLOUD_USER_MANAGER_URL + value: {{ include "app.baseUrl" . }} + {{- if ((.Values.ozgcloud).usersync).period }} + - name: OZGCLOUD_USERSYNC_PERIOD + value: {{ .Values.ozgcloud.usersync.period }} + {{- end }} + - name: QUARKUS_HTTP_CORS_ORIGINS + value: {{ (include "app.alfaAddress" .) }} + {{- with (.Values.env).customList }} +{{ toYaml . | indent 8 }} + {{- end }} + {{- if .Values.optionalTrustStoreSecretName }} + - name: TRUST_STORE_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.optionalTrustStoreSecretName }} + key: password + optional: false + args: + - '-Djavax.net.ssl.trustStore=/optional-trust-store/truststore.jks' + - '-Djavax.net.ssl.trustStorePassword=$(TRUST_STORE_PASSWORD)' + {{- end }} + image: "{{ .Values.image.repo }}/{{ .Values.image.name }}:{{ coalesce (.Values.image).tag "latest" }}" + imagePullPolicy: Always + name: user-manager + ports: + - containerPort: 9000 + name: grpc-9000 + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /q/health/ready + port: 8080 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 3 + startupProbe: + failureThreshold: 10 + httpGet: + path: /q/health/started + port: 8080 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + resources: + {{- with .Values.resources }} +{{ toYaml . | indent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + privileged: false + readOnlyRootFilesystem: false + runAsNonRoot: true + {{- with (.Values.securityContext).runAsUser }} + runAsUser: {{ . }} + {{- end }} + {{- with (.Values.securityContext).runAsGroup }} + runAsGroup: {{ . }} + {{- end }} + stdin: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + tty: true + volumeMounts: + - name: user-manager-tls-certificate + mountPath: "/user-manager-tls-certificate/tls.crt" + subPath: tls.crt + readOnly: true + - name: user-manager-tls-certificate + mountPath: "/user-manager-tls-certificate/tls.key" + subPath: tls.key + readOnly: true + {{- if .Values.optionalTrustStoreSecretName }} + - name: optional-trust-store + mountPath: "/optional-trust-store/truststore.jks" + subPath: truststore.jks + readOnly: true + {{- end }} + volumes: + - name: user-manager-tls-certificate + secret: + secretName: user-manager-tls-cert + {{- if .Values.optionalTrustStoreSecretName }} + - name: optional-trust-store + secret: + secretName: {{ .Values.optionalTrustStoreSecretName }} + {{- end }} + dnsConfig: {} + dnsPolicy: ClusterFirst + imagePullSecrets: + {{- if .Values.imagePullSecret }} + - name: {{ .Values.imagePullSecret }} + {{ else }} + - name: user-manager-image-pull-secret + {{- end }} + restartPolicy: Always + {{- with .Values.hostAliases }} + hostAliases: +{{ toYaml . | indent 8 }} + {{- end }} + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 \ No newline at end of file diff --git a/src/main/helm/templates/image-pull-secret.yaml b/src/main/helm/templates/image-pull-secret.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d381e4a7e2af9f3c188040da7ac1d9243c518b22 --- /dev/null +++ b/src/main/helm/templates/image-pull-secret.yaml @@ -0,0 +1,34 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if not (.Values.imagePullSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: user-manager-image-pull-secret + namespace: {{ include "app.namespace" . }} +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: {{ include "app.imagePullSecret" . }} +{{- end }} \ No newline at end of file diff --git a/src/main/helm/templates/ingress.yaml b/src/main/helm/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..544c062b6769cd78cdfa3ca52143f51b01a3bb55 --- /dev/null +++ b/src/main/helm/templates/ingress.yaml @@ -0,0 +1,65 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + {{- with .Values.ingress.configuration_snippet}} + annotations: {{- toYaml . | nindent 4 }} + {{- end }} + more_set_headers "Access-Control-Allow-Origin: {{ (include "app.alfaAddress" .) }}"; + {{- if (.Values.ingress).certManagerAnnotations -}} + {{- range (.Values.ingress).certManagerAnnotations }} +{{ . | indent 4 }} + {{- end }} + {{- else if (.Values.ingress).use_staging_cert }} + cert-manager.io/cluster-issuer: letsencrypt-staging + {{- else }} + cert-manager.io/cluster-issuer: letsencrypt-prod + {{- end }} + name: {{ include "app.name" . }} + namespace: {{ include "app.namespace" . }} +spec: + {{- if and (.Values.ingress).className (ne (.Values).cluster_env "dataport") }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + rules: + - http: + paths: + - backend: + service: + port: + number: 8080 + name: {{ include "app.name" . }} + path: '' + pathType: ImplementationSpecific + host: {{ trimPrefix "https://" ( include "app.baseUrl" . ) }} + tls: + - hosts: + - {{ trimPrefix "https://" ( include "app.baseUrl" . ) }} + {{- if (.Values.ingress).tlsSecretName }} + secretName: {{ (.Values.ingress).tlsSecretName }} + {{- else if ne (.Values).cluster_env "dataport" }} + secretName: {{ .Values.ozgcloud.bezeichner }}-{{ include "app.name" . }}-tls + {{- end }} \ No newline at end of file diff --git a/src/main/helm/templates/keycloak-user-crd.yaml b/src/main/helm/templates/keycloak-user-crd.yaml new file mode 100644 index 0000000000000000000000000000000000000000..127ba798a08ea0ec3a3448e8935822f124b2b829 --- /dev/null +++ b/src/main/helm/templates/keycloak-user-crd.yaml @@ -0,0 +1,60 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if not (.Values.sso).disableOzgOperator }} +{{ if (.Values.sso).api_user }} +apiVersion: operator.ozgcloud.de/v1 +kind: OzgCloudKeycloakUser +metadata: + name: {{ include "app.generateKeycloakUserRessourceName" . }} + namespace: {{ include "app.namespace" . }} +spec: + keep_after_delete: {{ .Values.sso.api_user.keep_after_delete | default false }} + keycloak_user: + username: {{ .Values.sso.api_user.name | lower }} + first_name: {{ .Values.sso.api_user.first_name | default "" }} + last_name: {{ .Values.sso.api_user.last_name | default "" }} + email: {{ .Values.sso.api_user.email | default "" }} + {{- if .Values.sso.api_user.groups }} + groups: {{ .Values.sso.api_user.groups | toJson }} + {{- else }} + groups: [] + {{- end }} + {{- if .Values.sso.api_user.password }} + password: {{ .Values.sso.api_user.password }} + {{- end }} + {{- if .Values.sso.api_user.realm_roles }} + realm_roles: + {{- with .Values.sso.api_user.realm_roles }} +{{ toYaml . | indent 6 }} + {{- end }} + {{- end }} + {{- if .Values.sso.api_user.client_roles }} + client_roles: + {{- with .Values.sso.api_user.client_roles }} +{{ toYaml . | indent 6 }} + {{- end }} + {{- end }} +{{ end }} +{{- end }} \ No newline at end of file diff --git a/src/main/helm/templates/network_policy.yaml b/src/main/helm/templates/network_policy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8e8479b7133a090f20ac3147656e7a7bfed12929 --- /dev/null +++ b/src/main/helm/templates/network_policy.yaml @@ -0,0 +1,67 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if not (.Values.networkPolicy).disabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: network-policy-user-manager + namespace: {{ .Release.Namespace }} +spec: + podSelector: + matchLabels: + component: user-manager + policyTypes: + - Ingress + - Egress + ingress: + - ports: + - port: 8080 + {{- with (.Values.networkPolicy).additionalIngressConfig }} + - from: +{{ toYaml . | indent 8 }} + {{- end }} + egress: + - to: + - podSelector: + matchLabels: + component: ozgcloud-mongodb + ports: + - port: 27017 + protocol: TCP + # public keycloak ip + - to: + - ipBlock: + cidr: {{ required "Keycloak public IP must be set" (.Values.networkPolicy).ssoPublicIp }} + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ required "networkPolicy.dnsServerNamespace must be set" (.Values.networkPolicy).dnsServerNamespace }} + ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP +{{- end }} + diff --git a/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_read_role.yaml b/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_read_role.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1c7dcc612a75b34ada081e7294c56dea6b9b77ae --- /dev/null +++ b/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_read_role.yaml @@ -0,0 +1,43 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if not (.Values.sso).disableOzgOperator }} +{{- if (.Values.sso).api_user }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ozgcloud-keycloak-operator-secrets-read-role-user-manager + namespace: {{ include "app.namespace" $ }} +rules: + - apiGroups: + - "*" + resourceNames: + - {{ include "app.replaceAllNonAlphanumeric" .Values.sso.api_user.name }}-credentials + resources: + - secrets + verbs: + - get + - list +{{- end }} +{{- end }} \ No newline at end of file diff --git a/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_read_role_binding.yaml b/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_read_role_binding.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dbb6d1bab08151b66679e3f2d1b7bacdfdbc6652 --- /dev/null +++ b/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_read_role_binding.yaml @@ -0,0 +1,41 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if not (.Values.sso).disableOzgOperator }} +{{- if (.Values.sso).api_user }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ozgcloud-keycloak-operator-secrets-read-role-binding-user-manager + namespace: {{ include "app.namespace" . }} +subjects: + - kind: ServiceAccount + name: ozgcloud-keycloak-operator-serviceaccount + namespace: {{ required "sso.operatorNamespace muss angegeben sein" .Values.sso.operatorNamespace }} +roleRef: + kind: Role + name: ozgcloud-keycloak-operator-secrets-read-role-user-manager + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end }} \ No newline at end of file diff --git a/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_write_role.yaml b/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_write_role.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f56fe612cf4d11359a4062fd8f72b6c738d27aa9 --- /dev/null +++ b/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_write_role.yaml @@ -0,0 +1,40 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if not (.Values.sso).disableOzgOperator }} +{{- if (.Values.sso).api_user }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ozgcloud-keycloak-operator-secrets-write-role-user-manager + namespace: {{ include "app.namespace" $ }} +rules: + - apiGroups: + - "*" + resources: + - secrets + verbs: + - create +{{- end }} +{{- end }} \ No newline at end of file diff --git a/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_write_role_binding.yaml b/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_write_role_binding.yaml new file mode 100644 index 0000000000000000000000000000000000000000..86aa366ec5cbd42fd03bddc3d0f7caea61a1989f --- /dev/null +++ b/src/main/helm/templates/ozgcloud_keycloak_operator_secrets_write_role_binding.yaml @@ -0,0 +1,41 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if not (.Values.sso).disableOzgOperator }} +{{- if (.Values.sso).api_user }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ozgcloud-keycloak-operator-secrets-write-role-binding-user-manager + namespace: {{ include "app.namespace" . }} +subjects: + - kind: ServiceAccount + name: ozgcloud-keycloak-operator-serviceaccount + namespace: {{ required "sso.operatorNamespace muss angegeben sein" .Values.sso.operatorNamespace }} +roleRef: + kind: Role + name: ozgcloud-keycloak-operator-secrets-write-role-user-manager + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end }} \ No newline at end of file diff --git a/src/main/helm/templates/service.yaml b/src/main/helm/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..49556820e41b0b220648fb5753c96353a84b3b70 --- /dev/null +++ b/src/main/helm/templates/service.yaml @@ -0,0 +1,44 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "app.name" . }} + namespace: {{ include "app.namespace" . }} + labels: + {{- include "app.defaultLabels" . | indent 4 }} + component: user-manager-service +spec: + type: ClusterIP + ports: + - name: grpc-9000 + port: 9000 + protocol: TCP + - name: http + port: 8080 + protocol: TCP + selector: + {{- include "app.matchLabels" . | indent 4 }} + component: user-manager diff --git a/src/main/helm/templates/service_account.yaml b/src/main/helm/templates/service_account.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3bac8e223d1fd108b386d1f06ed4e9fb2284a67c --- /dev/null +++ b/src/main/helm/templates/service_account.yaml @@ -0,0 +1,31 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +{{- if (.Values.serviceAccount).create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "app.serviceAccountName" . }} + namespace: {{ include "app.namespace" . }} +{{- end }} \ No newline at end of file diff --git a/src/main/helm/templates/service_monitor.yaml b/src/main/helm/templates/service_monitor.yaml new file mode 100644 index 0000000000000000000000000000000000000000..41e25272fa6007b3093fa406e0f70eb1556a2030 --- /dev/null +++ b/src/main/helm/templates/service_monitor.yaml @@ -0,0 +1,48 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "app.name" . }} + namespace: {{ include "app.namespace" . }} + labels: + {{- include "app.defaultLabels" . | indent 4 }} + component: user-manager-service-monitor + k8s-app: prometheus-app-monitor + +spec: + endpoints: + - interval: 30s + targetPort: 8080 + path: /q/metrics + scheme: http + namespaceSelector: + matchNames: + - {{ include "app.namespace" . }} + selector: + matchLabels: + {{- include "app.matchLabels" . | indent 6 }} + component: user-manager-service \ No newline at end of file diff --git a/src/main/helm/values.yaml b/src/main/helm/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9a0d2e1da7b076bc8b0592c600e0c0b1c479227c --- /dev/null +++ b/src/main/helm/values.yaml @@ -0,0 +1,47 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +cluster_env: "" + +replicaCount: 2 + +image: + repo: docker.ozg-sh.de + name: user-manager + tag: latest # [default: latest] + +database: # username is always <release-name>-database-user + databaseName: user-manager-database + +ozgcloud: + keycloak: + api: + user: userManagerApiUser + +ingress: + configuration_snippet: + nginx.ingress.kubernetes.io/configuration-snippet: | + more_set_headers "Access-Control-Allow-Methods: GET,PATCH,OPTIONS"; + more_set_headers "Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-XSRF-TOKEN"; + more_set_headers "Access-Control-Expose-Headers: Content-Length,Content-Range"; diff --git a/src/test/helm/api-password-secret_test.yaml b/src/test/helm/api-password-secret_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3b0ee8dc6b9aef0367282c9444bdb77fc7ad8a66 --- /dev/null +++ b/src/test/helm/api-password-secret_test.yaml @@ -0,0 +1,48 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test api password secret +release: + name: user-manager + namespace: sh-test-test +templates: + - templates/api-password-secret.yaml +tests: + - it: test api secret kind + asserts: + - isKind: + of: Secret + - it: test api password + asserts: + - equal: + path: stringData.password + value: geheim + - it: should use Keycloak User Operator + set: + sso: + api_user: + name: userManagerApiUser + asserts: + - hasDocuments: + count: 0 \ No newline at end of file diff --git a/src/test/helm/cert_issuer_test.yaml b/src/test/helm/cert_issuer_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..728aab704074781efc9c344eb9235f6b130354cb --- /dev/null +++ b/src/test/helm/cert_issuer_test.yaml @@ -0,0 +1,50 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: cert-issuer +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/cert_issuer.yaml +tests: + - it: should contains header data + asserts: + - isAPIVersion: + of: cert-manager.io/v1 + - isKind: + of: Issuer + - it: should have metadata + asserts: + - equal: + path: metadata.name + value: user-manager-issuer + - equal: + path: metadata.namespace + value: sh-helm-test + - it: should be selfSigned + asserts: + - equal: + path: spec.selfSigned + value: {} \ No newline at end of file diff --git a/src/test/helm/certificate_test.yaml b/src/test/helm/certificate_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b6ce4ec239f2f0e4999787d46c81bbede549e9be --- /dev/null +++ b/src/test/helm/certificate_test.yaml @@ -0,0 +1,93 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: certificate +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/certificate.yaml +tests: + - it: should contains header data + asserts: + - isAPIVersion: + of: cert-manager.io/v1 + - isKind: + of: Certificate + - it: should have metadata + asserts: + - equal: + path: metadata.name + value: user-manager-tls-certificate + - equal: + path: metadata.namespace + value: sh-helm-test + - it: should have secretName + asserts: + - equal: + path: spec.secretName + value: user-manager-tls-cert + - it: should have issuerRef + asserts: + - equal: + path: spec.issuerRef.name + value: user-manager-issuer + - equal: + path: spec.issuerRef.kind + value: Issuer + - it: should have duration + asserts: + - equal: + path: spec.duration + value: 8760h0m0s + - it: should have renewBefore + asserts: + - equal: + path: spec.renewBefore + value: 720h0m0s + - it: should have commonName + asserts: + - equal: + path: spec.commonName + value: "user-manager" + - it: should have dnsNames + asserts: + - equal: + path: spec.dnsNames[0] + value: "*.user-manager.sh-helm-test.svc.cluster.local" + - equal: + path: spec.dnsNames[1] + value: "user-manager.sh-helm-test.svc.cluster.local" + - equal: + path: spec.dnsNames[2] + value: "user-manager.sh-helm-test.svc.cluster" + - equal: + path: spec.dnsNames[3] + value: "user-manager.sh-helm-test.svc" + - equal: + path: spec.dnsNames[4] + value: "user-manager.sh-helm-test" + - equal: + path: spec.dnsNames[5] + value: "user-manager" \ No newline at end of file diff --git a/src/test/helm/deployment-keycloak-values-test.yaml b/src/test/helm/deployment-keycloak-values-test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1ca2053c0356ab0acac836e20572cbdfac27ad98 --- /dev/null +++ b/src/test/helm/deployment-keycloak-values-test.yaml @@ -0,0 +1,145 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager +templates: + - templates/deployment.yaml +tests: + - it: validate keycloak configuration values + template: deployment.yaml + release: + namespace: sh-helm-test + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_KEYCLOAK_API_USER + value: userManagerApiUser + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_KEYCLOAK_API_PASSWORD + valueFrom: + secretKeyRef: + name: user-manager-api-password + key: password + optional: false + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_KEYCLOAK_API_REALM + value: sh-helm-test + - contains: + path: spec.template.spec.containers[0].env + content: + name: QUARKUS_OIDC_AUTH_SERVER_URL + value: https://sso.test.sh.ozg-cloud.de/realms/sh-helm-test + - contains: + path: spec.template.spec.containers[0].env + content: + name: KEYCLOAK_URL + value: https://sso.test.sh.ozg-cloud.de + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_KEYCLOAK_API_CLIENT + value: alfa + + - it: should set keycloak client name + template: deployment.yaml + release: + namespace: sh-helm-test + set: + sso: + client_name: alfa + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_KEYCLOAK_API_CLIENT + value: alfa + + - it: sso.serverurl with https + template: deployment.yaml + release: + namespace: sh-helm-test + set: + sso.serverUrl: https://sso.test.by.ozg-cloud.de + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: QUARKUS_OIDC_AUTH_SERVER_URL + value: https://sso.test.by.ozg-cloud.de/realms/sh-helm-test + - contains: + path: spec.template.spec.containers[0].env + content: + name: KEYCLOAK_URL + value: https://sso.test.by.ozg-cloud.de + - it: sso.serverurl without https + template: deployment.yaml + release: + namespace: sh-helm-test + set: + sso.serverUrl: sso.test.by.ozg-cloud.de + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: QUARKUS_OIDC_AUTH_SERVER_URL + value: https://sso.test.by.ozg-cloud.de/realms/sh-helm-test + - contains: + path: spec.template.spec.containers[0].env + content: + name: KEYCLOAK_URL + value: https://sso.test.by.ozg-cloud.de + - it: should use Keycloak User Operator + template: deployment.yaml + release: + namespace: sh-helm-test + set: + sso: + api_user: + name: -userManager-ApiUser + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_KEYCLOAK_API_USER + valueFrom: + secretKeyRef: + name: usermanagerapiuser-credentials + key: name + optional: false + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_KEYCLOAK_API_PASSWORD + valueFrom: + secretKeyRef: + name: usermanagerapiuser-credentials + key: password + optional: false diff --git a/src/test/helm/deployment-mongodb-passwort-secretref-test.yaml b/src/test/helm/deployment-mongodb-passwort-secretref-test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7bfc134a1c5cfce471bfb3405fc34f9dad15fafb --- /dev/null +++ b/src/test/helm/deployment-mongodb-passwort-secretref-test.yaml @@ -0,0 +1,60 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager +templates: + - templates/deployment.yaml +tests: + - it: should reference mongodb connectionString for user-manager + set: + database.secretName: pluto-database-admin-user-manager-database-user + template: deployment.yaml + release: + namespace: sh-helm-test + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: QUARKUS_MONGODB_CONNECTION_STRING + valueFrom: + secretKeyRef: + key: connectionString.standard + name: pluto-database-admin-user-manager-database-user + optional: false + - it: check default mongodb connectionString for user-manager + template: deployment.yaml + release: + namespace: sh-helm-test + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: QUARKUS_MONGODB_CONNECTION_STRING + valueFrom: + secretKeyRef: + key: connectionString.standard + name: ozg-mongodb-admin-user-manager-user + optional: false \ No newline at end of file diff --git a/src/test/helm/deployment-test.yaml b/src/test/helm/deployment-test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..932191baf3177d7ab9aa1c380075ed82f42da391 --- /dev/null +++ b/src/test/helm/deployment-test.yaml @@ -0,0 +1,43 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: deployment +release: + name: user-manager +templates: + - templates/deployment.yaml +tests: + - it: test resources for prod environment + release: + namespace: sh-helm-test + template: deployment.yaml + asserts: + - isKind: + of: Deployment + - equal: + path: spec.template.spec.containers[0].image + value: docker.ozg-sh.de/user-manager:latest + - equal: + path: spec.replicas + value: 2 diff --git a/src/test/helm/deployment-url-value-test.yaml b/src/test/helm/deployment-url-value-test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..88791953b6980f47b9bebecf00e1ef4a44abdc8f --- /dev/null +++ b/src/test/helm/deployment-url-value-test.yaml @@ -0,0 +1,40 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager +templates: + - templates/deployment.yaml +tests: + - it: validate keycloak configuration values + template: deployment.yaml + release: + namespace: sh-name-dev + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_USER_MANAGER_URL + value: https://helm-user-manager.test.sh.ozg-cloud.de \ No newline at end of file diff --git a/src/test/helm/deployment_container_security_context_test.yaml b/src/test/helm/deployment_container_security_context_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..98afd1eb3954cdaed8e37debca26c562c4ce4c71 --- /dev/null +++ b/src/test/helm/deployment_container_security_context_test.yaml @@ -0,0 +1,65 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/deployment.yaml +tests: + - it: check default values + asserts: + - isKind: + of: Deployment + - equal: + path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation + value: false + - equal: + path: spec.template.spec.containers[0].securityContext.privileged + value: false + - equal: + path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem + value: false + - equal: + path: spec.template.spec.containers[0].securityContext.runAsNonRoot + value: true + - isNull: + path: spec.template.spec.containers[0].securityContext.runAsUser + - isNull: + path: spec.template.spec.containers[0].securityContext.runAsGroup + - it: check runAsUser + set: + securityContext.runAsUser: 1000 + asserts: + - equal: + path: spec.template.spec.containers[0].securityContext.runAsUser + value: 1000 + - it: check runAsGroup + set: + securityContext.runAsGroup: 1000 + asserts: + - equal: + path: spec.template.spec.containers[0].securityContext.runAsGroup + value: 1000 \ No newline at end of file diff --git a/src/test/helm/deployment_defaults_labels_test.yaml b/src/test/helm/deployment_defaults_labels_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5a814d2fc605019e66ffb2c68f8631b7d3a16fbf --- /dev/null +++ b/src/test/helm/deployment_defaults_labels_test.yaml @@ -0,0 +1,68 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/deployment.yaml + - templates/service.yaml + - templates/service_monitor.yaml +tests: + - it: check default labels + asserts: + - equal: + path: metadata.labels.[app.kubernetes.io/instance] + value: user-manager + - equal: + path: metadata.labels.[app.kubernetes.io/name] + value: user-manager + - equal: + path: metadata.labels.[app.kubernetes.io/part-of] + value: ozgcloud + - equal: + path: metadata.labels.[app.kubernetes.io/namespace] + value: sh-helm-test + - it: check component label for deployment + templates: + - templates/deployment.yaml + asserts: + - equal: + path: spec.template.metadata.labels.[component] + value: user-manager + - it: check component label for service + templates: + - templates/service.yaml + asserts: + - equal: + path: metadata.labels.[component] + value: user-manager-service + - it: check component label for service monitor + templates: + - templates/service_monitor.yaml + asserts: + - equal: + path: metadata.labels.[component] + value: user-manager-service-monitor diff --git a/src/test/helm/deployment_env_test.yaml b/src/test/helm/deployment_env_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..227cd7f8c6dd6d80f73c20b304cde6f81644eeae --- /dev/null +++ b/src/test/helm/deployment_env_test.yaml @@ -0,0 +1,87 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test environments +templates: + - templates/deployment.yaml +tests: + - it: check customList + template: deployment.yaml + set: + env.customList: + - name: my_test_environment_name + value: "A test value" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: my_test_environment_name + value: "A test value" + - it: check customList test value is not set by default + template: deployment.yaml + asserts: + - notContains: + path: spec.template.spec.containers[0].env + content: + name: my_test_environment_name + value: "A test value" + - it: check quarkus origin is set + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: QUARKUS_HTTP_CORS_ORIGINS + value: "https://helm.test.sh.ozg-cloud.de" + - it: check quarkus mongodb database default value + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: QUARKUS_MONGODB_DATABASE + value: user-manager-database + - it: check quarkus mongodb database set databaseName + set: + database.databaseName: test-database + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: QUARKUS_MONGODB_DATABASE + value: test-database + - it: check user sync period set + set: + ozgcloud.usersync.period: "6h" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_USERSYNC_PERIOD + value: "6h" + - it: check user sync period NOT set + asserts: + - notContains: + path: spec.template.spec.containers[0].env + content: + name: OZGCLOUD_USERSYNC_PERIOD + value: "6h" \ No newline at end of file diff --git a/src/test/helm/deployment_host_aliases_test.yaml b/src/test/helm/deployment_host_aliases_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4cf4a472c005e7e980faa28c1aa3a972d51cb152 --- /dev/null +++ b/src/test/helm/deployment_host_aliases_test.yaml @@ -0,0 +1,50 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: deployment host aliases +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/deployment.yaml +tests: + - it: should not set hostAliases + asserts: + - isNull: + path: spec.template.spec.hostAliases + - it: should set hostAliases + set: + hostAliases: + - ip: "127.0.0.1" + hostname: + - "eins" + - "zwei" + asserts: + - contains: + path: spec.template.spec.hostAliases + content: + ip: "127.0.0.1" + hostname: + - "eins" + - "zwei" diff --git a/src/test/helm/deployment_imagepull_secret_test.yaml b/src/test/helm/deployment_imagepull_secret_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2f45b321a7c1da6d0b054f0a42600b3e7319839f --- /dev/null +++ b/src/test/helm/deployment_imagepull_secret_test.yaml @@ -0,0 +1,47 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/deployment.yaml +tests: + - it: should use default imagePull secret + asserts: + - isKind: + of: Deployment + - equal: + path: spec.template.spec.imagePullSecrets[0].name + value: user-manager-image-pull-secret + - it: should set the imagePull secret + set: + imagePullSecret: image-pull-secret + asserts: + - isKind: + of: Deployment + - equal: + path: spec.template.spec.imagePullSecrets[0].name + value: image-pull-secret \ No newline at end of file diff --git a/src/test/helm/deployment_optional_trust_store_test.yaml b/src/test/helm/deployment_optional_trust_store_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..72c3138240f1ef6fb5c6bf23d61f26907b271432 --- /dev/null +++ b/src/test/helm/deployment_optional_trust_store_test.yaml @@ -0,0 +1,79 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test environments +templates: + - templates/deployment.yaml +tests: + - it: check without truststore + asserts: + - isEmpty: + path: spec.template.spec.containers[0].args + - notContains: + path: spec.template.spec.containers[0].env + content: + name: TRUST_STORE_PASSWORD + - notContains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: optional-trust-store + mountPath: "/optional-trust-store/truststore.jks" + subPath: truststore.jks + readOnly: true + - notContains: + path: spec.template.spec.volumes + content: + name: optional-trust-store + + - it: check with truststore + set: + optionalTrustStoreSecretName: optional-trust-store-secret + asserts: + - equal: + path: spec.template.spec.containers[0].args + value: + - '-Djavax.net.ssl.trustStore=/optional-trust-store/truststore.jks' + - '-Djavax.net.ssl.trustStorePassword=$(TRUST_STORE_PASSWORD)' + - contains: + path: spec.template.spec.containers[0].env + content: + name: TRUST_STORE_PASSWORD + valueFrom: + secretKeyRef: + name: optional-trust-store-secret + key: password + optional: false + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: optional-trust-store + mountPath: "/optional-trust-store/truststore.jks" + subPath: truststore.jks + readOnly: true + - contains: + path: spec.template.spec.volumes + content: + name: optional-trust-store + secret: + secretName: optional-trust-store-secret \ No newline at end of file diff --git a/src/test/helm/deployment_resources_test.yaml b/src/test/helm/deployment_resources_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f5101300c97ff02e37a5790e4422d62815b52fb5 --- /dev/null +++ b/src/test/helm/deployment_resources_test.yaml @@ -0,0 +1,57 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager +templates: + - templates/deployment.yaml +tests: + - it: test resources + template: deployment.yaml + set: + resources: + limits: + cpu: "11m" + memory: "22Mi" + requests: + cpu: "33m" + memory: "44Mi" + asserts: + - equal: + path: spec.template.spec.containers[0].resources.limits.cpu + value: 11m + - equal: + path: spec.template.spec.containers[0].resources.limits.memory + value: 22Mi + - equal: + path: spec.template.spec.containers[0].resources.requests.cpu + value: 33m + - equal: + path: spec.template.spec.containers[0].resources.requests.memory + value: 44Mi + - it: test empty resources + asserts: + - isEmpty: + path: spec.template.spec.containers[0].resources \ No newline at end of file diff --git a/src/test/helm/deployment_scrapeMetrics_test.yaml b/src/test/helm/deployment_scrapeMetrics_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a3bfb8be872d705d2e5db36c2e97e8d3674a776c --- /dev/null +++ b/src/test/helm/deployment_scrapeMetrics_test.yaml @@ -0,0 +1,41 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/deployment.yaml + - templates/secret_database_quarkus.yaml +tests: + - it: should set the metrics port by default + template: deployment.yaml + asserts: + - contains: + path: spec.template.spec.containers[0].ports + content: + name: http + containerPort: 8080 + protocol: TCP \ No newline at end of file diff --git a/src/test/helm/deployment_service_account_test.yaml b/src/test/helm/deployment_service_account_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e5025e38d770a9c886613456bd1aef501fbc3103 --- /dev/null +++ b/src/test/helm/deployment_service_account_test.yaml @@ -0,0 +1,52 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: deployment service account +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/deployment.yaml +tests: + - it: should use service account with default name + set: + serviceAccount: + create: true + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: user-manager-service-account + - it: should use service account with name + set: + serviceAccount: + create: true + name: helm-service-account + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: helm-service-account + - it: should use default service account + asserts: + - isNull: + path: spec.template.spec.serviceAccountName \ No newline at end of file diff --git a/src/test/helm/deplyoment_cert_bindings_test.yaml b/src/test/helm/deplyoment_cert_bindings_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e36a01820b4fd0b3cbefe9f7a2cbad6650a7cefd --- /dev/null +++ b/src/test/helm/deplyoment_cert_bindings_test.yaml @@ -0,0 +1,60 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: deployment cert bindings +release: + name: user-manager + namespace: user-manager +templates: + - templates/deployment.yaml +tests: + - it: should mount volumes for user-manager root ca + set: + ozgcloud.environment: dev + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: user-manager-tls-certificate + mountPath: "/user-manager-tls-certificate/tls.crt" + subPath: tls.crt + readOnly: true + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: user-manager-tls-certificate + mountPath: "/user-manager-tls-certificate/tls.key" + subPath: tls.key + readOnly: true + + - it: should have volumes for user-manager root certificate + set: + namespace: sh-helm-test + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: user-manager-tls-certificate + secret: + secretName: user-manager-tls-cert \ No newline at end of file diff --git a/src/test/helm/imagepull_secret_test.yaml b/src/test/helm/imagepull_secret_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..089e97801a98670143dc4ba6cb49c02fee163cc0 --- /dev/null +++ b/src/test/helm/imagepull_secret_test.yaml @@ -0,0 +1,59 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test image pull secret +templates: + - templates/image-pull-secret.yaml +release: + name: user-manager + namespace: helm-test +tests: + - it: should match basic data + set: + imageCredentials: + registry: docker.ozg-sh.de + username: test + password: test1234 + email: webmaster@ozg-sh.de + asserts: + - hasDocuments: + count: 1 + - containsDocument: + kind: Secret + apiVersion: v1 + - equal: + path: metadata.name + value: user-manager-image-pull-secret + - equal: + path: metadata.namespace + value: helm-test + - isNotEmpty: + path: data.[.dockerconfigjson] + + - it: should not create image pull secret + set: + imagePullSecret: "image-pull-secret" + asserts: + - hasDocuments: + count: 0 \ No newline at end of file diff --git a/src/test/helm/ingress-nginx-tests.yaml b/src/test/helm/ingress-nginx-tests.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4d01a181dc951599798f3de68b17a9ca3ba043cc --- /dev/null +++ b/src/test/helm/ingress-nginx-tests.yaml @@ -0,0 +1,74 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test ingress options +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/ingress.yaml +tests: + - it: should create ingress tls + asserts: + - equal: + path: spec.tls[0].secretName + value: helm-user-manager-tls + - it: should not set ingressClassName + asserts: + - isNull: + path: spec.ingressClassName + - it: should set ingressClassName + set: + ingress.className: nginx + asserts: + - equal: + path: spec.ingressClassName + value: nginx + - it: should not create ingress tls/ingressClassName + set: + cluster_env: dataport + asserts: + - isNull: + path: spec.ingressClassName + - isNull: + path: spec.tls[0].secretName + - it: should use default letsencrypt-prod cluster-issuer + asserts: + - equal: + path: metadata.annotations.[cert-manager.io/cluster-issuer] + value: letsencrypt-prod + - it: should use letsencrypt-staging cluster-issuer + set: + ingress.use_staging_cert: true + asserts: + - equal: + path: metadata.annotations.[cert-manager.io/cluster-issuer] + value: letsencrypt-staging + - it: should use letsencrypt-prod cluster-issuer + set: + ingress.use_staging_cert: false + asserts: + - equal: + path: metadata.annotations.[cert-manager.io/cluster-issuer] + value: letsencrypt-prod \ No newline at end of file diff --git a/src/test/helm/ingress_nginx_cors_test.yaml b/src/test/helm/ingress_nginx_cors_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..88e35a589ca5c46d074be7054010d2142d138e47 --- /dev/null +++ b/src/test/helm/ingress_nginx_cors_test.yaml @@ -0,0 +1,42 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test ingress +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/ingress.yaml +tests: + - it: check ingress annotations if nginx test environment + asserts: + - isKind: + of: Ingress + - equal: + path: metadata.annotations.[nginx.ingress.kubernetes.io/configuration-snippet] + value: | + more_set_headers "Access-Control-Allow-Methods: GET,PATCH,OPTIONS"; + more_set_headers "Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-XSRF-TOKEN"; + more_set_headers "Access-Control-Expose-Headers: Content-Length,Content-Range"; + more_set_headers "Access-Control-Allow-Origin: https://helm.test.sh.ozg-cloud.de"; diff --git a/src/test/helm/keycloak-user-crd-test.yaml b/src/test/helm/keycloak-user-crd-test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3bc02df43817a58239294c6b53ecd67ad04d43aa --- /dev/null +++ b/src/test/helm/keycloak-user-crd-test.yaml @@ -0,0 +1,281 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: Keycloak User CRD +release: + name: user-manager + namespace: by-helm-test +templates: + - templates/keycloak-user-crd.yaml +tests: + - it: should contain header data + set: + sso: + api_user: + name: testapiuser + asserts: + - isAPIVersion: + of: operator.ozgcloud.de/v1 + - isKind: + of: OzgCloudKeycloakUser + - it: should have metadata + set: + sso: + api_user: + name: test-apiuser + asserts: + - equal: + path: metadata.name + value: testapiuser-keycloak-user + - equal: + path: metadata.namespace + value: by-helm-test + - it: should have default Values + set: + ozgcloud: + bundesland: by + bezeichner: helm + environment: test + sso: + serverUrl: https://sso.test.by.ozg-cloud.de + api_user: + name: testapiuser + asserts: + - equal: + path: spec.keep_after_delete + value: false + - equal: + path: spec.keycloak_user.first_name + values: "" + - equal: + path: spec.keycloak_user.last_name + values: "" + - equal: + path: spec.keycloak_user.email + values: "" + - isEmpty: + path: spec.keycloak_user.groups + - isNull: + path: spec.keycloak_user.password + - isNull: + path: spec.keycloak_user.realm_roles + - isNull: + path: spec.keycloak_user.client_roles + + - it: should have Keycloak User without roles + set: + ozgcloud: + bundesland: by + bezeichner: helm + environment: test + baseUrl: "test.by.ozg-cloud.de" + sso: + api_user: + name: testapiuser + first_name: UserManager + last_name: ApiUser + email: testapiuser@ozg-sh.de + serverUrl: https://sso.test.by.ozg-cloud.de + asserts: + - equal: + path: spec.keep_after_delete + value: false + - equal: + path: spec.keycloak_user.username + value: testapiuser + - equal: + path: spec.keycloak_user.first_name + value: UserManager + - equal: + path: spec.keycloak_user.last_name + value: ApiUser + - equal: + path: spec.keycloak_user.email + value: testapiuser@ozg-sh.de + - isEmpty: + path: spec.keycloak_user.groups + - isNull: + path: spec.keycloak_user.realm_roles + - isNull: + path: spec.keycloak_user.client_roles + + - it: should have Keycloak User with client role + set: + ozgcloud: + bundesland: by + bezeichner: helm + environment: test + baseUrl: "test.by.ozg-cloud.de" + sso: + api_user: + name: testapiuser + first_name: UserManager + last_name: ApiUser + email: testapiuser@ozg-sh.de + client_roles: + - name: alfa + role: VERWALTUNG_USER + serverUrl: https://sso.test.by.ozg-cloud.de + asserts: + - equal: + path: spec.keep_after_delete + value: false + - equal: + path: spec.keycloak_user.username + value: testapiuser + - equal: + path: spec.keycloak_user.first_name + value: UserManager + - equal: + path: spec.keycloak_user.last_name + value: ApiUser + - equal: + path: spec.keycloak_user.email + value: testapiuser@ozg-sh.de + - isEmpty: + path: spec.keycloak_user.groups + - isNull: + path: spec.keycloak_user.realm_roles + - contains: + path: spec.keycloak_user.client_roles + content: + name: alfa + role: VERWALTUNG_USER + + - it: should have Keycloak User with realm role + set: + ozgcloud: + bundesland: by + bezeichner: helm + environment: test + baseUrl: "test.by.ozg-cloud.de" + sso: + api_user: + name: testapiuser + first_name: UserManager + last_name: ApiUser + email: testapiuser@ozg-sh.de + realm_roles: + - "offline_access" + serverUrl: https://sso.test.by.ozg-cloud.de + asserts: + - equal: + path: spec.keep_after_delete + value: false + - equal: + path: spec.keycloak_user.username + value: testapiuser + - equal: + path: spec.keycloak_user.first_name + value: UserManager + - equal: + path: spec.keycloak_user.last_name + value: ApiUser + - equal: + path: spec.keycloak_user.email + value: testapiuser@ozg-sh.de + - isEmpty: + path: spec.keycloak_user.groups + - isNull: + path: spec.keycloak_user.client_roles + - contains: + path: spec.keycloak_user.realm_roles + content: + offline_access + + - it: should have Keycloak User with group + set: + ozgcloud: + bundesland: by + bezeichner: helm + environment: test + baseUrl: "test.by.ozg-cloud.de" + sso: + api_user: + name: testapiuser + first_name: UserManager + last_name: ApiUser + email: testapiuser@ozg-sh.de + groups: + - Bauamt + serverUrl: https://sso.test.by.ozg-cloud.de + asserts: + - equal: + path: spec.keep_after_delete + value: false + - equal: + path: spec.keycloak_user.username + value: testapiuser + - equal: + path: spec.keycloak_user.first_name + value: UserManager + - equal: + path: spec.keycloak_user.last_name + value: ApiUser + - equal: + path: spec.keycloak_user.email + value: testapiuser@ozg-sh.de + - isNull: + path: spec.keycloak_user.realm_roles + - isNull: + path: spec.keycloak_user.client_roles + - contains: + path: spec.keycloak_user.groups + content: + Bauamt + + - it: should have lowercase username + set: + ozgcloud: + bundesland: by + bezeichner: helm + environment: test + sso: + api_user: + name: testApiUser + serverUrl: https://sso.test.by.ozg-cloud.de + asserts: + - equal: + path: spec.keycloak_user.username + value: testapiuser + - equal: + path: spec.keep_after_delete + value: false + - equal: + path: spec.keycloak_user.first_name + values: "" + - equal: + path: spec.keycloak_user.last_name + values: "" + - equal: + path: spec.keycloak_user.email + values: "" + - isEmpty: + path: spec.keycloak_user.groups + - isNull: + path: spec.keycloak_user.password + - isNull: + path: spec.keycloak_user.realm_roles + - isNull: + path: spec.keycloak_user.client_roles \ No newline at end of file diff --git a/src/test/helm/network_policy_test.yaml b/src/test/helm/network_policy_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..42aaa61d80b9966800c57c6ab28fb7efdf60d9f6 --- /dev/null +++ b/src/test/helm/network_policy_test.yaml @@ -0,0 +1,128 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: network policy test +release: + namespace: by-helm-test +templates: + - templates/network_policy.yaml +tests: + - it: should match apiVersion + set: + networkPolicy: + dnsServerNamespace: test-namespace-dns + asserts: + - isAPIVersion: + of: networking.k8s.io/v1 + - it: should match kind + set: + networkPolicy: + dnsServerNamespace: test-namespace-dns + asserts: + - isKind: + of: NetworkPolicy + - it: validate metadata + set: + networkPolicy: + dnsServerNamespace: test-namespace-dns + asserts: + - equal: + path: metadata + value: + name: network-policy-user-manager + namespace: by-helm-test + - it: validate spec + set: + networkPolicy: + dnsServerNamespace: test-namespace-dns + asserts: + - equal: + path: spec + value: + podSelector: + matchLabels: + component: user-manager + policyTypes: + - Ingress + - Egress + ingress: + - ports: + - port: 8080 + egress: + - to: + - podSelector: + matchLabels: + component: ozgcloud-mongodb + ports: + - port: 27017 + protocol: TCP + # public keycloak ip + - to: + - ipBlock: + cidr: 51.89.117.53/32 + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: test-namespace-dns + ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - it: add ingress rule by values + set: + networkPolicy: + dnsServerNamespace: test-namespace-dns + additionalIngressConfig: + - podSelector: + matchLabels: + component: client2 + asserts: + - equal: + path: spec.ingress + value: + - ports: + - port: 8080 + - from: + - podSelector: + matchLabels: + component: client2 + + - it: test network policy disabled + set: + networkPolicy: + dnsServerNamespace: test-namespace-dns + disabled: true + asserts: + - hasDocuments: + count: 0 + + - it: test network policy unset should be disabled + set: + networkPolicy: + dnsServerNamespace: test-namespace-dns + disabled: false + asserts: + - hasDocuments: + count: 1 \ No newline at end of file diff --git a/src/test/helm/ozgcloud_keycloak_operator_secrets_read_role_binding_test.yaml b/src/test/helm/ozgcloud_keycloak_operator_secrets_read_role_binding_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a25cdf9448f9937c505867d639deb21cc8d7b1d7 --- /dev/null +++ b/src/test/helm/ozgcloud_keycloak_operator_secrets_read_role_binding_test.yaml @@ -0,0 +1,97 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test ozgcloud_keycloak_operator_secrets_read_role_binding +release: + name: alfa + namespace: by-helm-test +templates: + - templates/ozgcloud_keycloak_operator_secrets_read_role_binding.yaml +tests: + - it: should contain header data + set: + sso: + api_user: + - name: apiuser + operatorNamespace: test-operator-namespace + asserts: + - isAPIVersion: + of: rbac.authorization.k8s.io/v1 + - isKind: + of: RoleBinding + - it: should have metadata + set: + sso: + api_user: + - name: apiuser + operatorNamespace: test-operator-namespace + asserts: + - equal: + path: metadata.name + value: ozgcloud-keycloak-operator-secrets-read-role-binding-user-manager + - equal: + path: metadata.namespace + value: by-helm-test + - it: should have subjects values + set: + sso: + api_user: + - name: apiuser + operatorNamespace: test-operator-namespace + asserts: + - contains: + path: subjects + content: + kind: ServiceAccount + name: ozgcloud-keycloak-operator-serviceaccount + namespace: test-operator-namespace + - it: should have roleRef values + set: + sso: + api_user: + - name: apiuser + operatorNamespace: test-operator-namespace + asserts: + - equal: + path: roleRef.kind + value: Role + - equal: + path: roleRef.name + value: ozgcloud-keycloak-operator-secrets-read-role-user-manager + - equal: + path: roleRef.apiGroup + value: rbac.authorization.k8s.io + - it: should not create RoleBinding if no keycloak users available + asserts: + - hasDocuments: + count: 0 + - it: should not create RoleBinding if ozg operator is disabled + set: + sso: + disableOzgOperator: true + api_user: + - name: apiuser + asserts: + - hasDocuments: + count: 0 \ No newline at end of file diff --git a/src/test/helm/ozgcloud_keycloak_operator_secrets_read_role_test.yaml b/src/test/helm/ozgcloud_keycloak_operator_secrets_read_role_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..456d13b5e70d1e7e1c0ab1b8e3ba6c30d199ea4a --- /dev/null +++ b/src/test/helm/ozgcloud_keycloak_operator_secrets_read_role_test.yaml @@ -0,0 +1,84 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test ozgcloud_keycloak_operator_secrets_read_role +release: + name: alfa + namespace: by-helm-test +templates: + - templates/ozgcloud_keycloak_operator_secrets_read_role.yaml +tests: + - it: should contain header data + set: + sso: + api_user: + name: apiuser + asserts: + - isAPIVersion: + of: rbac.authorization.k8s.io/v1 + - isKind: + of: Role + - it: should have metadata + set: + sso: + api_user: + name: apiuser + asserts: + - equal: + path: metadata.name + value: ozgcloud-keycloak-operator-secrets-read-role-user-manager + - equal: + path: metadata.namespace + value: by-helm-test + - it: should have subjects values + set: + sso: + api_user: + name: _with_underscore_and.with.dot. + asserts: + - contains: + path: rules + content: + apiGroups: + - "*" + resourceNames: + - withunderscoreandwithdot-credentials + resources: + - secrets + verbs: + - get + - list + - it: should not create RoleBinding if no keycloak users available + asserts: + - hasDocuments: + count: 0 + - it: should not create Role if ozg operator is disabled + set: + sso: + disableOzgOperator: true + api_user: + - name: apiuser + asserts: + - hasDocuments: + count: 0 \ No newline at end of file diff --git a/src/test/helm/ozgcloud_keycloak_operator_secrets_write_role_binding_test.yaml b/src/test/helm/ozgcloud_keycloak_operator_secrets_write_role_binding_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9db214d6126a293924009ef7baa1ae94616368c3 --- /dev/null +++ b/src/test/helm/ozgcloud_keycloak_operator_secrets_write_role_binding_test.yaml @@ -0,0 +1,97 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test ozgcloud_keycloak_operator_secrets_role_binding +release: + name: alfa + namespace: by-helm-test +templates: + - templates/ozgcloud_keycloak_operator_secrets_write_role_binding.yaml +tests: + - it: should contain header data + set: + sso: + api_user: + - name: apiuser + operatorNamespace: test-operator-namespace + asserts: + - isAPIVersion: + of: rbac.authorization.k8s.io/v1 + - isKind: + of: RoleBinding + - it: should have metadata + set: + sso: + api_user: + - name: apiuser + operatorNamespace: test-operator-namespace + asserts: + - equal: + path: metadata.name + value: ozgcloud-keycloak-operator-secrets-write-role-binding-user-manager + - equal: + path: metadata.namespace + value: by-helm-test + - it: should have subjects values + set: + sso: + api_user: + - name: apiuser + operatorNamespace: test-operator-namespace + asserts: + - contains: + path: subjects + content: + kind: ServiceAccount + name: ozgcloud-keycloak-operator-serviceaccount + namespace: test-operator-namespace + - it: should have roleRef values + set: + sso: + api_user: + - name: apiuser + operatorNamespace: test-operator-namespace + asserts: + - equal: + path: roleRef.kind + value: Role + - equal: + path: roleRef.name + value: ozgcloud-keycloak-operator-secrets-write-role-user-manager + - equal: + path: roleRef.apiGroup + value: rbac.authorization.k8s.io + - it: should not create RoleBinding if no keycloak users available + asserts: + - hasDocuments: + count: 0 + - it: should not create RoleBinding if ozg operator is disabled + set: + sso: + disableOzgOperator: true + api_user: + - name: apiuser + asserts: + - hasDocuments: + count: 0 \ No newline at end of file diff --git a/src/test/helm/ozgcloud_keycloak_operator_secrets_write_role_test.yaml b/src/test/helm/ozgcloud_keycloak_operator_secrets_write_role_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1d69236ce54a6f770025bf0dc8011b107f0f0d1e --- /dev/null +++ b/src/test/helm/ozgcloud_keycloak_operator_secrets_write_role_test.yaml @@ -0,0 +1,81 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test ozgcloud_keycloak_operator_secrets_write_role +release: + name: alfa + namespace: by-helm-test +templates: + - templates/ozgcloud_keycloak_operator_secrets_write_role.yaml +tests: + - it: should contain header data + set: + sso: + api_user: + - name: apiuser + asserts: + - isAPIVersion: + of: rbac.authorization.k8s.io/v1 + - isKind: + of: Role + - it: should have metadata + set: + sso: + api_user: + - name: apiuser + asserts: + - equal: + path: metadata.name + value: ozgcloud-keycloak-operator-secrets-write-role-user-manager + - equal: + path: metadata.namespace + value: by-helm-test + - it: should have subjects values + set: + sso: + api_user: + - name: apiuser + asserts: + - contains: + path: rules + content: + apiGroups: + - "*" + resources: + - secrets + verbs: + - create + - it: should not create RoleBinding if no keycloak users available + asserts: + - hasDocuments: + count: 0 + - it: should not create Role if ozg operator is disabled + set: + sso: + disableOzgOperator: true + api_user: + - name: apiuser + asserts: + - hasDocuments: + count: 0 \ No newline at end of file diff --git a/src/test/helm/service_account_test.yaml b/src/test/helm/service_account_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..212853c804aa6fa549b347c1b785d6eb27af008c --- /dev/null +++ b/src/test/helm/service_account_test.yaml @@ -0,0 +1,62 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test service account +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/service_account.yaml +tests: + - it: should create service account with default name + set: + serviceAccount: + create: true + asserts: + - isKind: + of: ServiceAccount + - equal: + path: metadata.name + value: user-manager-service-account + - equal: + path: metadata.namespace + value: sh-helm-test + - it: should create service account with name + set: + serviceAccount: + create: true + name: helm-service-account + asserts: + - isKind: + of: ServiceAccount + - equal: + path: metadata.name + value: helm-service-account + - equal: + path: metadata.namespace + value: sh-helm-test + - it: should not create service account + asserts: + - hasDocuments: + count: 0 \ No newline at end of file diff --git a/src/test/helm/service_monitor_test.yaml b/src/test/helm/service_monitor_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fde000bcb4c46f168482f55b048cdf189d5743a3 --- /dev/null +++ b/src/test/helm/service_monitor_test.yaml @@ -0,0 +1,67 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager + namespace: sh-helm-test +templates: + - templates/service_monitor.yaml +tests: + - it: should have the label component with value user-manager-service-monitor attached + asserts: + - isKind: + of: ServiceMonitor + - equal: + path: metadata.labels.[component] + value: user-manager-service-monitor + - it: should be able to enable the endpoint + asserts: + - isKind: + of: ServiceMonitor + - contains: + path: spec.endpoints + content: + interval: 30s + path: /q/metrics + scheme: http + targetPort: 8080 + - it: namespace selector should contain the namespace + asserts: + - contains: + path: spec.namespaceSelector.matchNames + content: sh-helm-test + - it: selector should contain the component label with the value user-manager-service + asserts: + - equal: + path: spec.selector.matchLabels.[component] + value: user-manager-service + - it: selector should contain helm recommended labels name and namespace + asserts: + - equal: + path: spec.selector.matchLabels.[app.kubernetes.io/name] + value: user-manager + - equal: + path: spec.selector.matchLabels.[app.kubernetes.io/namespace] + value: sh-helm-test diff --git a/src/test/helm/service_test.yaml b/src/test/helm/service_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3fda82ef5fd5e1ba17bb08dff12a13dd2903931b --- /dev/null +++ b/src/test/helm/service_test.yaml @@ -0,0 +1,77 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test deployment +release: + name: user-manager + namespace: helm-test +templates: + - templates/service.yaml +tests: + - it: should have the label component with value user-manager-service attached + asserts: + - isKind: + of: Service + - equal: + path: metadata.labels.[component] + value: user-manager-service + - it: should be of type ClusterIP + asserts: + - equal: + path: spec.type + value: ClusterIP + - it: ports should contain the http port + asserts: + - contains: + path: spec.ports + content: + name: http + port: 8080 + protocol: TCP + count: 1 + any: true + - it: ports should contain the grpc port + asserts: + - contains: + path: spec.ports + content: + name: grpc-9000 + port: 9000 + protocol: TCP + count: 1 + any: true + - it: selector should contain the component label with the value user-manager + asserts: + - equal: + path: spec.selector.[component] + value: user-manager + - it: selector should contain helm recommended labels name and namespace + asserts: + - equal: + path: spec.selector.[app.kubernetes.io/name] + value: user-manager + - equal: + path: spec.selector.[app.kubernetes.io/namespace] + value: helm-test + \ No newline at end of file diff --git a/src/test/linter-values.yaml b/src/test/linter-values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d88aa6746bb6f298a625bc5e2a211f490957b6ce --- /dev/null +++ b/src/test/linter-values.yaml @@ -0,0 +1,41 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +baseUrl: test.sh.ozg-cloud.de + +ozgcloud: + bundesland: sh + bezeichner: helm + environment: test + keycloak: + api: + password: geheim + +sso: + serverUrl: sso.test.sh.ozg-cloud.de + +networkPolicy: + ssoPublicIp: 51.89.117.53/32 + dnsServerNamespace: test-dns-namespace + \ No newline at end of file diff --git a/src/test/unit-values.yaml b/src/test/unit-values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..22c227d91ba54bb0525deeed7f397e5a6e94b5a4 --- /dev/null +++ b/src/test/unit-values.yaml @@ -0,0 +1,39 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +baseUrl: test.sh.ozg-cloud.de + +ozgcloud: + bundesland: sh + bezeichner: helm + environment: test + keycloak: + api: + password: geheim + +sso: + serverUrl: sso.test.sh.ozg-cloud.de + +networkPolicy: + ssoPublicIp: 51.89.117.53/32 diff --git a/user-manager-interface/pom.xml b/user-manager-interface/pom.xml index b1a9cadf53655e65da396c50ff70b0ee9b7eacaf..e9578aa5bb7a2c07b9cc42357c664b4665317321 100644 --- a/user-manager-interface/pom.xml +++ b/user-manager-interface/pom.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den Ministerpräsidenten des Landes Schleswig-Holstein Staatskanzlei Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -24,56 +24,30 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> - <groupId>de.itvsh.kop.common</groupId> - <artifactId>kop-common-dependencies</artifactId> - <version>1.2.1</version> - <relativePath /> + <groupId>de.ozgcloud.user</groupId> + <artifactId>user-manager</artifactId> + <version>2.1.0</version> </parent> - <groupId>de.itvsh.kop.user</groupId> <artifactId>user-manager-interface</artifactId> - <version>1.1.0</version> - - <name>UserManager Interface</name> + <name>OZG-Cloud User Manager Interface</name> <description>gRPC Interface for User Manager</description> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - - <kop.license.version>1.3.0</kop.license.version> - - <java.version>17</java.version> - <maven.compiler.source>${java.version}</maven.compiler.source> - <maven.compiler.target>${java.version}</maven.compiler.target> - - <quarkus.platform.version>2.13.0.Final</quarkus.platform.version> - <jandex-maven-plugin-version>1.2.3</jandex-maven-plugin-version> - </properties> - - <dependencyManagement> - <dependencies> - <!-- Quarkus --> - <dependency> - <groupId>io.quarkus.platform</groupId> - <artifactId>quarkus-bom</artifactId> - <version>${quarkus.platform.version}</version> - <type>pom</type> - <scope>import</scope> - </dependency> - </dependencies> - </dependencyManagement> - <dependencies> <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-grpc</artifactId> + <groupId>io.grpc</groupId> + <artifactId>grpc-stub</artifactId> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-protobuf</artifactId> </dependency> - <!-- Java 9+ compatibility --> <dependency> <groupId>javax.annotation</groupId> @@ -82,76 +56,57 @@ </dependencies> <build> + <sourceDirectory>src/main/proto</sourceDirectory> + <plugins> <plugin> - <groupId>io.quarkus</groupId> + <groupId>io.quarkus.platform</groupId> <artifactId>quarkus-maven-plugin</artifactId> - <version>${quarkus.platform.version}</version> - <executions> - <execution> - <goals> - <goal>build</goal> - <goal>generate-code</goal> - <goal>generate-code-tests</goal> - </goals> - </execution> - </executions> </plugin> <plugin> <groupId>org.jboss.jandex</groupId> <artifactId>jandex-maven-plugin</artifactId> - <version>${jandex-maven-plugin-version}</version> - <executions> - <execution> - <id>make-index</id> - <goals> - <goal>jandex</goal> - </goals> - </execution> - </executions> </plugin> - + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + </plugin> + <plugin> <groupId>com.mycila</groupId> <artifactId>license-maven-plugin</artifactId> - <version>4.1</version> <configuration> <mapping> <proto>SLASHSTAR_STYLE</proto> <config>SCRIPT_STYLE</config> </mapping> - <licenseSets> - <licenseSet> - <header>license/eupl_v1_2_de/header.txt</header> - <excludes> - <exclude>**/*.yaml</exclude> - <exclude>**/*.yml</exclude> - <exclude>README.md</exclude> - </excludes> - </licenseSet> - </licenseSets> </configuration> - <dependencies> - <dependency> - <groupId>de.itvsh.kop.common</groupId> - <artifactId>kop-common-license</artifactId> - <version>${kop.license.version}</version> - </dependency> - </dependencies> + </plugin> + + <plugin> + <groupId>com.github.os72</groupId> + <artifactId>protoc-jar-maven-plugin</artifactId> + <version>${protoc-jar-plugin.version}</version> + <executions> + <execution> + <phase>generate-sources</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <outputTargets> + <outputTarget> + <type>java</type> + </outputTarget> + <outputTarget> + <type>grpc-java</type> + <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.60.0</pluginArtifact> + </outputTarget> + </outputTargets> + </configuration> + </execution> + </executions> </plugin> </plugins> </build> - - <distributionManagement> - <repository> - <id>ozg-nexus</id> - <name>ozg-releases</name> - <url>https://nexus.ozg-sh.de/repository/ozg-releases/</url> - </repository> - <snapshotRepository> - <id>ozg-snapshots-nexus</id> - <name>ozg-snapshots</name> - <url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url> - </snapshotRepository> - </distributionManagement> -</project> \ No newline at end of file +</project> diff --git a/user-manager-interface/src/main/proto/userprofile.model.proto b/user-manager-interface/src/main/protobuf/organisationseinheit.model.proto similarity index 73% rename from user-manager-interface/src/main/proto/userprofile.model.proto rename to user-manager-interface/src/main/protobuf/organisationseinheit.model.proto index babb6a383b5361a0be5977624e114f6f2c71b798..40219dc8164b9cb9a3f8db4eb5d11bf120dd8f11 100644 --- a/user-manager-interface/src/main/proto/userprofile.model.proto +++ b/user-manager-interface/src/main/protobuf/organisationseinheit.model.proto @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -23,13 +23,15 @@ */ syntax = "proto3"; -package de.itvsh.kop.user.grpc; +package de.ozgcloud.user.grpc; option java_multiple_files = true; -option java_package = "de.itvsh.kop.user.userprofile"; -option java_outer_classname = "UserProfileModelProto"; +option java_package = "de.ozgcloud.user.organisationseinheit"; +option java_outer_classname = "OrganisationsEinheitModelProto"; -message GrpcUserProfile { - string firstName = 1; - string lastName = 2; +message GrpcOrganisationsEinheit { + string organisationsEinheitId = 1; +} + +message GrpcGetSupportedOrganisationsEinheitenRequest { } \ No newline at end of file diff --git a/user-manager-interface/src/main/protobuf/organisationseinheit.proto b/user-manager-interface/src/main/protobuf/organisationseinheit.proto new file mode 100644 index 0000000000000000000000000000000000000000..15880b9ae2717df0b016b289f9444ecbaa8e409c --- /dev/null +++ b/user-manager-interface/src/main/protobuf/organisationseinheit.proto @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +syntax = "proto3"; +import "organisationseinheit.model.proto"; + +package de.ozgcloud.user.grpc; + +option java_multiple_files = true; +option java_package = "de.ozgcloud.user.grpc.organisationseinheit"; +option java_outer_classname = "OrganisationsEinheitProto"; + +service OrganisationsEinheitService { + rpc GetSupportedOrganisationsEinheiten(GrpcGetSupportedOrganisationsEinheitenRequest) returns (GrpcGetSupportedOrganisationsEinheitenResponse); +} + +message GrpcGetSupportedOrganisationsEinheitenResponse { + repeated GrpcOrganisationsEinheit organisationseinheiten = 1; +} \ No newline at end of file diff --git a/user-manager-interface/src/main/proto/recipient.model.proto b/user-manager-interface/src/main/protobuf/recipient.model.proto similarity index 88% rename from user-manager-interface/src/main/proto/recipient.model.proto rename to user-manager-interface/src/main/protobuf/recipient.model.proto index c2bce6ae000dc7dab106b60131f34f1b2a00fae9..a50c7b61a3171cbb8ee42bc2afdb97fa40effed1 100644 --- a/user-manager-interface/src/main/proto/recipient.model.proto +++ b/user-manager-interface/src/main/protobuf/recipient.model.proto @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -23,10 +23,10 @@ */ syntax = "proto3"; -package de.itvsh.kop.user.grpc; +package de.ozgcloud.user.grpc; option java_multiple_files = true; -option java_package = "de.itvsh.kop.user.recipient"; +option java_package = "de.ozgcloud.user.recipient"; option java_outer_classname = "RecipientModelProto"; message GrpcRecipient { diff --git a/user-manager-interface/src/main/proto/recipient.proto b/user-manager-interface/src/main/protobuf/recipient.proto similarity index 89% rename from user-manager-interface/src/main/proto/recipient.proto rename to user-manager-interface/src/main/protobuf/recipient.proto index b27457089d35fda245eaf8bfdd0873a1fdee710e..ebabb572df9891987b27c6de74f1493bd22827c7 100644 --- a/user-manager-interface/src/main/proto/recipient.proto +++ b/user-manager-interface/src/main/protobuf/recipient.proto @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -23,12 +23,12 @@ */ syntax = "proto3"; -package de.itvsh.kop.user.grpc; +package de.ozgcloud.user.grpc; import "recipient.model.proto"; option java_multiple_files = true; -option java_package = "de.itvsh.kop.user.grpc.recipient"; +option java_package = "de.ozgcloud.user.grpc.recipient"; option java_outer_classname = "RecipientProto"; service RecipientService { diff --git a/user-manager-interface/src/main/protobuf/userprofile.model.proto b/user-manager-interface/src/main/protobuf/userprofile.model.proto new file mode 100644 index 0000000000000000000000000000000000000000..6301624169e1158a27073981cedbc0ada45b4983 --- /dev/null +++ b/user-manager-interface/src/main/protobuf/userprofile.model.proto @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +syntax = "proto3"; + +package de.ozgcloud.user.grpc; + +option java_multiple_files = true; +option java_package = "de.ozgcloud.user.userprofile"; +option java_outer_classname = "UserProfileModelProto"; + +message GrpcUserProfile { + string id = 1; + string firstName = 2; + string lastName = 3; + string email = 4; +} + + +message GrpcGetUserProfileRequest { + string userId = 1; +} + +message GrpcGetUserProfileResponse { + GrpcUserProfile userProfile = 1; +} + +message GrpcFindInactiveUserIdsResponse { + repeated GrpcUserProfileId userProfileIds = 1; +} + +message GrpcUserProfileId { + string id = 1; +} + +message GrpcDeleteInactiveUserRequest { + string userId = 1; +} + +message GrpcFindInactiveUserIdsRequest { +} + +message GrpcDeleteInactiveUserResponse { +} \ No newline at end of file diff --git a/user-manager-interface/src/main/proto/userprofile.proto b/user-manager-interface/src/main/protobuf/userprofile.proto similarity index 72% rename from user-manager-interface/src/main/proto/userprofile.proto rename to user-manager-interface/src/main/protobuf/userprofile.proto index df56506fa9df167443346d46f7058bb950c26518..50defdb88704f12170c89fb43cb841f556e08191 100644 --- a/user-manager-interface/src/main/proto/userprofile.proto +++ b/user-manager-interface/src/main/protobuf/userprofile.proto @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -23,22 +23,22 @@ */ syntax = "proto3"; -package de.itvsh.kop.user.grpc; +package de.ozgcloud.user.grpc; import "userprofile.model.proto"; option java_multiple_files = true; -option java_package = "de.itvsh.kop.user.grpc.userprofile"; +option java_package = "de.ozgcloud.user.grpc.userprofile"; option java_outer_classname = "UserProfileProto"; service UserProfileService { + rpc GetById(GrpcGetUserProfileRequest) returns (GrpcGetUserProfileResponse); -} -message GrpcGetUserProfileRequest { - string userId = 1; -} + rpc GetByExternalId(GrpcGetUserProfileRequest) returns (GrpcGetUserProfileResponse); + + rpc FindInactiveUserIds(GrpcFindInactiveUserIdsRequest) returns (GrpcFindInactiveUserIdsResponse); + + rpc DeleteInactiveUser(GrpcDeleteInactiveUserRequest) returns (GrpcDeleteInactiveUserResponse); -message GrpcGetUserProfileResponse { - GrpcUserProfile userProfile = 1; } \ No newline at end of file diff --git a/user-manager-server/.mvn/wrapper/maven-wrapper.properties b/user-manager-server/.mvn/wrapper/maven-wrapper.properties index 70e554c8e229ddc0f489d20addd346846acb4dde..4f15c4db157211576495c75d7c700cd2ea4b4bea 100644 --- a/user-manager-server/.mvn/wrapper/maven-wrapper.properties +++ b/user-manager-server/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/user-manager-server/lombok.config b/user-manager-server/lombok.config index d07dd9b0e2b0281fbf514a968b9451cb6af62f93..81661f0fd9c5f6e2f40f39aa9ee13f7017fc2726 100644 --- a/user-manager-server/lombok.config +++ b/user-manager-server/lombok.config @@ -1,5 +1,5 @@ # -# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den # Ministerpräsidenten des Landes Schleswig-Holstein # Staatskanzlei # Abteilung Digitalisierung und zentrales IT-Management der Landesregierung diff --git a/user-manager-server/pom.xml b/user-manager-server/pom.xml index 2a4f0ac8113d4c178cd028546823909f338428da..a4aae30ce85c6bc3f9631c8fd2394c341c582e85 100644 --- a/user-manager-server/pom.xml +++ b/user-manager-server/pom.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den Ministerpräsidenten des Landes Schleswig-Holstein Staatskanzlei Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -24,81 +24,41 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> - <groupId>de.itvsh.kop.user</groupId> + <parent> + <groupId>de.ozgcloud.user</groupId> + <artifactId>user-manager</artifactId> + <version>2.1.0</version> + </parent> + <artifactId>user-manager-server</artifactId> - <version>1.1.0</version> - <name>User Manager</name> + <name>OZG-Cloud User Manager Server</name> <properties> <skipITs>false</skipITs> - - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <compiler-plugin.version>3.8.1</compiler-plugin.version> - <maven.compiler.release>17</maven.compiler.release> - - <kop-common.version>1.3.0</kop-common.version> - <kop.license.version>1.3.0</kop.license.version> - - <jacoco.plugin.version>0.8.8</jacoco.plugin.version> - <quarkus.platform.version>2.13.0.Final</quarkus.platform.version> - <surefire-plugin.version>3.0.0-M7</surefire-plugin.version> - <maven-failsafe-plugin.version>3.0.0-M7</maven-failsafe-plugin.version> - <git-commit-id-plugin.version>4.9.10</git-commit-id-plugin.version> - - <!-- Versions already declared in kop-common-dependencies bom -> use bom as parent!? --> - <mapstruct.version>1.5.1.Final</mapstruct.version> - <lombok.version>1.18.24</lombok.version> - <commons-lang3.version>3.12.0</commons-lang3.version> </properties> - <dependencyManagement> - <dependencies> - <dependency> - <groupId>de.itvsh.kop.user</groupId> - <artifactId>user-manager-interface</artifactId> - <version>${project.version}</version> - </dependency> - <!-- Quarkus --> - <dependency> - <groupId>io.quarkus.platform</groupId> - <artifactId>quarkus-bom</artifactId> - <version>${quarkus.platform.version}</version> - <type>pom</type> - <scope>import</scope> - </dependency> - <dependency> - <groupId>de.itvsh.kop.common</groupId> - <artifactId>kop-common-dependencies</artifactId> - <version>${kop-common.version}</version> - <type>pom</type> - <scope>import</scope> - </dependency> - <dependency> - <groupId>de.itvsh.kop.common</groupId> - <artifactId>kop-common-lib</artifactId> - <version>${kop-common.version}</version> - <exclusions> - <exclusion> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-slf4j-impl</artifactId> - </exclusion> - </exclusions> - </dependency> - </dependencies> - </dependencyManagement> - <dependencies> <dependency> - <groupId>de.itvsh.kop.user</groupId> + <groupId>de.ozgcloud.user</groupId> <artifactId>user-manager-interface</artifactId> </dependency> <dependency> - <groupId>de.itvsh.kop.common</groupId> - <artifactId>kop-common-lib</artifactId> + <groupId>de.ozgcloud.common</groupId> + <artifactId>ozgcloud-common-lib</artifactId> + <exclusions> + <exclusion> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </exclusion> + </exclusions> </dependency> <!-- Quarkus --> @@ -154,6 +114,10 @@ <groupId>io.quarkus</groupId> <artifactId>quarkus-scheduler</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-grpc</artifactId> + </dependency> <!-- Logging --> <dependency> @@ -186,7 +150,6 @@ <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> - <scope>provided</scope> </dependency> <dependency> <groupId>io.quarkus</groupId> @@ -198,8 +161,6 @@ <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> - <version>${mapstruct.version}</version> - <scope>provided</scope> </dependency> <dependency> <groupId>com.thedeanda</groupId> @@ -207,6 +168,32 @@ <scope>test</scope> </dependency> + <!-- Jakarta --> + <dependency> + <groupId>jakarta.interceptor</groupId> + <artifactId>jakarta.interceptor-api</artifactId> + </dependency> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + </dependency> + <dependency> + <groupId>jakarta.validation</groupId> + <artifactId>jakarta.validation-api</artifactId> + </dependency> + <dependency> + <groupId>jakarta.ws.rs</groupId> + <artifactId>jakarta.ws.rs-api</artifactId> + </dependency> + <dependency> + <groupId>jakarta.annotation</groupId> + <artifactId>jakarta.annotation-api</artifactId> + </dependency> + <dependency> + <groupId>jakarta.inject</groupId> + <artifactId>jakarta.inject-api</artifactId> + </dependency> + <!-- Test --> <dependency> <groupId>io.quarkus</groupId> @@ -250,51 +237,61 @@ <plugin> <groupId>io.quarkus.platform</groupId> <artifactId>quarkus-maven-plugin</artifactId> - <version>${quarkus.platform.version}</version> <extensions>true</extensions> + </plugin> + <plugin> + <groupId>pl.project13.maven</groupId> + <artifactId>git-commit-id-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>com.mycila</groupId> + <artifactId>license-maven-plugin</artifactId> + </plugin> + <!-- Core plugins --> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> <executions> <execution> + <id>default-compile1</id> + <phase>compile</phase> <goals> - <goal>build</goal> - <goal>generate-code</goal> - <goal>generate-code-tests</goal> + <goal>compile</goal> </goals> + <configuration> + <fork>true</fork> + <annotationProcessorPaths> + <path> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + </path> + <path> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct-processor</artifactId> + <version>${mapstruct.version}</version> + </path> + <!-- other annotation processors --> + </annotationProcessorPaths> + <showWarnings>true</showWarnings> + <compilerArgs> + <arg>-parameters</arg> + <compilerArg> + -Amapstruct.defaultComponentModel=jakarta + </compilerArg> + <compilerArg> + -Amapstruct.unmappedTargetPolicy=WARN + </compilerArg> + </compilerArgs> + </configuration> </execution> </executions> </plugin> - <plugin> - <artifactId>maven-compiler-plugin</artifactId> - <version>${compiler-plugin.version}</version> - <configuration> - <fork>true</fork> - <annotationProcessorPaths> - <path> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> - </path> - <path> - <groupId>org.mapstruct</groupId> - <artifactId>mapstruct-processor</artifactId> - <version>${mapstruct.version}</version> - </path> - <!-- other annotation processors --> - </annotationProcessorPaths> - <showWarnings>true</showWarnings> - <compilerArgs> - <arg>-parameters</arg> - <compilerArg> - -Amapstruct.defaultComponentModel=cdi - </compilerArg> - <compilerArg> - -Amapstruct.unmappedTargetPolicy=WARN - </compilerArg> - </compilerArgs> - </configuration> - </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>${surefire-plugin.version}</version> <configuration> <systemPropertyVariables> <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> @@ -306,7 +303,6 @@ </plugin> <plugin> <artifactId>maven-failsafe-plugin</artifactId> - <version>${maven-failsafe-plugin.version}</version> <executions> <execution> <goals> @@ -327,77 +323,6 @@ <classesDirectory>${project.build.outputDirectory}</classesDirectory> </configuration> </plugin> - <plugin> - <groupId>pl.project13.maven</groupId> - <artifactId>git-commit-id-plugin</artifactId> - <version>${git-commit-id-plugin.version}</version> - <executions> - <execution> - <id>get-the-git-infos</id> - <phase>initialize</phase> - <goals> - <goal>revision</goal> - </goals> - </execution> - </executions> - <configuration> - <offline>true</offline> - </configuration> - </plugin> - <plugin> - <groupId>org.jacoco</groupId> - <artifactId>jacoco-maven-plugin</artifactId> - <version>${jacoco.plugin.version}</version> - <executions> - <execution> - <id>start-agent</id> - <goals> - <goal>prepare-agent</goal> - </goals> - <configuration> - <propertyName>surefire.jacoco.args</propertyName> - <exclClassLoaders>*QuarkusClassLoader</exclClassLoaders> - <destFile>${project.build.directory}/jacoco-quarkus.exec</destFile> - <append>true</append> - </configuration> - </execution> - <execution> - <id>generate-report</id> - <phase>package</phase> - <goals> - <goal>report</goal> - </goals> - </execution> - </executions> - </plugin> - - <plugin> - <groupId>com.mycila</groupId> - <artifactId>license-maven-plugin</artifactId> - <version>4.1</version> - <configuration> - <mapping> - <config>SCRIPT_STYLE</config> - </mapping> - <licenseSets> - <licenseSet> - <header>license/eupl_v1_2_de/header.txt</header> - <excludes> - <exclude>**/README</exclude> - <exclude>src/test/resources/**</exclude> - <exclude>src/main/resources/**</exclude> - </excludes> - </licenseSet> - </licenseSets> - </configuration> - <dependencies> - <dependency> - <groupId>de.itvsh.kop.common</groupId> - <artifactId>kop-common-license</artifactId> - <version>${kop.license.version}</version> - </dependency> - </dependencies> - </plugin> </plugins> </build> @@ -416,17 +341,4 @@ </properties> </profile> </profiles> - - <distributionManagement> - <repository> - <id>ozg-nexus</id> - <name>ozg-releases</name> - <url>https://nexus.ozg-sh.de/repository/ozg-releases/</url> - </repository> - <snapshotRepository> - <id>ozg-snapshots-nexus</id> - <name>ozg-snapshots</name> - <url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url> - </snapshotRepository> - </distributionManagement> -</project> \ No newline at end of file +</project> diff --git a/user-manager-server/sonar-project.properties b/user-manager-server/sonar-project.properties index 692212d7c8ce919bfd8b6a361e8d7fb8af6d77d9..bdfd85e559fac136858a044a5a592ea6cff0cea7 100644 --- a/user-manager-server/sonar-project.properties +++ b/user-manager-server/sonar-project.properties @@ -1,5 +1,5 @@ # -# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den # Ministerpräsidenten des Landes Schleswig-Holstein # Staatskanzlei # Abteilung Digitalisierung und zentrales IT-Management der Landesregierung diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/UserRepository.java b/user-manager-server/src/main/java/de/itvsh/kop/user/UserRepository.java deleted file mode 100644 index 79533852c5d7b1ed85fbe753dac372140b2bf9d7..0000000000000000000000000000000000000000 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/UserRepository.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.itvsh.kop.user; - -import static de.itvsh.kop.user.User.*; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -import javax.enterprise.context.ApplicationScoped; - -import org.bson.types.ObjectId; - -import de.itvsh.kop.common.logging.KopLogging; -import de.itvsh.kop.user.common.errorhandling.ResourceNotFoundException; -import de.itvsh.kop.user.settings.NotificationsSendFor; -import io.quarkus.mongodb.panache.PanacheMongoRepository; - -@ApplicationScoped -@KopLogging -class UserRepository implements PanacheMongoRepository<User> { - private static final String LIKE_OR = " like ?1 or "; - private static final String SEARCH_QUERY = LASTNAME_FIELD + LIKE_OR + - FIRSTNAME_FIELD + LIKE_OR + - USERNAME_FIELD + LIKE_OR + - EMAIL_FIELD + " like ?1"; - - private static final String AND_DELETED = " and deleted = ?2"; - - private static final String SEARCH_RECIPIENT_QUERY = ORGANISATIONS_EINHEIT_IDS_FIELD + " = ?1 and " + NOTIFICATION_SEND_FOR_FIELD + " = ?2"; - private static final String UPDATE_UNSYNCED_USER_QUERY = LAST_SYNC_TIMESTAMP_FIELD + " < ?1"; - - public User updateUser(User userToUpdate) { - var user = findById(userToUpdate.getId()); - userToUpdate.setUserSettings(user.getUserSettings()); - update(userToUpdate); - - return findById(user.getId()); - } - - public Optional<User> findByExternalId(String externalId) { - return find(EXTERNAL_ID_FIELD, externalId).firstResultOptional(); - } - - public Optional<User> findById(String id) { - return findByIdOptional(new ObjectId(id)); - } - - public Optional<User> findByEmail(String email) { - return find(EMAIL_FIELD, email).firstResultOptional(); - } - - public Stream<User> findUsers(String query, int limit) { - return find(SEARCH_QUERY, "/.*" + query + "*/i").range(0, limit - 1).stream(); - } - - public Stream<User> findUsers(String query, boolean deleted, int limit) { - return find(SEARCH_QUERY + AND_DELETED, "/.*" + query + "*/i", deleted).range(0, limit - 1).stream(); - } - - public List<User> findRecipientByOrganisationsEinheitId(String organisationseinheitId) { - return find(SEARCH_RECIPIENT_QUERY, organisationseinheitId, NotificationsSendFor.ALL.name()).list(); - } - - public long updateUnsyncedUsers(long lastSyncTimestamp) { - return update(DELETED_FIELD, true).where(UPDATE_UNSYNCED_USER_QUERY, lastSyncTimestamp); - } - - public User refresh(User user) { - return findByIdOptional(user.getId()) - .orElse(findByExternalId(user.getExternalId()).orElseThrow(() -> new ResourceNotFoundException(User.class, user.getExternalId()))); - } -} diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/UserService.java b/user-manager-server/src/main/java/de/itvsh/kop/user/UserService.java deleted file mode 100644 index 5306416e269989e160ee6df9204209e59bf17fbd..0000000000000000000000000000000000000000 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/UserService.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.itvsh.kop.user; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; - -import org.apache.commons.lang3.StringUtils; - -import de.itvsh.kop.common.logging.KopLogging; -import de.itvsh.kop.user.common.errorhandling.ResourceNotFoundException; - -@ApplicationScoped -@KopLogging -public class UserService { - static final String UUID_PATTERN = "-"; - - @Inject - UserRepository repository; - - public User save(User user) { - findUser(user).ifPresentOrElse(persistedUser -> repository.updateUser(addIdUser(user, persistedUser)), - () -> repository.persist(user)); - return repository.refresh(user); - } - - public Stream<User> findUsers(String query, int limit) { - return repository.findUsers(query, limit); - } - - public Stream<User> findActiveUsers(String query, int limit) { - return repository.findUsers(query, false, limit); - } - - public Stream<User> findInactiveUsers(String query, int limit) { - return repository.findUsers(query, true, limit); - } - - private Optional<User> findUser(User user) { - return repository.findByExternalId(user.getExternalId()) - .or(() -> findByEmail(user.getEmail())); - } - - private Optional<User> findByEmail(String email) { - if (StringUtils.isNotBlank(email)) { - return repository.findByEmail(email); - } - return Optional.empty(); - } - - private User addIdUser(User user, User persistedUser) { - return user.toBuilder().id(persistedUser.getId()).build(); - } - - public void markUnsyncedUsersAsDeleted(long lastSyncTimestamp) { - repository.updateUnsyncedUsers(lastSyncTimestamp); - } - - public List<User> findRecipientByOrganisationsEinheitId(String organisationsEinheitId) { - return repository.findRecipientByOrganisationsEinheitId(organisationsEinheitId); - } - - public User getById(String id) { - if (id.contains(UUID_PATTERN)) { - // TODO wenn user migriert wurden wieder entfernen. - return repository.findByExternalId(id).orElseThrow(() -> new ResourceNotFoundException(User.class, id)); - } - - return repository.findById(id).orElseThrow(() -> new ResourceNotFoundException(User.class, id)); - } - - public User findByExternalId(String id) { - return repository.findByExternalId(id).orElseThrow(() -> new ResourceNotFoundException(User.class, id)); - } -} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/userprofile/UserProfileGrpcService.java b/user-manager-server/src/main/java/de/itvsh/kop/user/userprofile/UserProfileGrpcService.java deleted file mode 100644 index 2561d97f954e711e72316d8b16efc8a929f1fdd4..0000000000000000000000000000000000000000 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/userprofile/UserProfileGrpcService.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.itvsh.kop.user.userprofile; - -import javax.inject.Inject; - -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.grpc.userprofile.GrpcGetUserProfileRequest; -import de.itvsh.kop.user.grpc.userprofile.GrpcGetUserProfileResponse; -import de.itvsh.kop.user.grpc.userprofile.UserProfileServiceGrpc.UserProfileServiceImplBase; -import io.grpc.stub.StreamObserver; -import io.quarkus.grpc.GrpcService; - -@GrpcService -public class UserProfileGrpcService extends UserProfileServiceImplBase { - - @Inject - UserService service; - @Inject - UserProfileMapper mapper; - - @Override - public void getById(GrpcGetUserProfileRequest request, StreamObserver<GrpcGetUserProfileResponse> responseObserver) { - var userProfile = service.getById(request.getUserId()); - - responseObserver.onNext(GrpcGetUserProfileResponse.newBuilder().setUserProfile(mapper.mapTo(userProfile)).build()); - responseObserver.onCompleted(); - } -} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/UserRole.java b/user-manager-server/src/main/java/de/ozgcloud/user/FindUserProfilesQuery.java similarity index 68% rename from user-manager-server/src/main/java/de/itvsh/kop/user/UserRole.java rename to user-manager-server/src/main/java/de/ozgcloud/user/FindUserProfilesQuery.java index 3dc6a4871c970c0237c59ab830a13403d627f2ce..8be433612a753c564927b632bfdc5e1e57fcfdde 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/UserRole.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/FindUserProfilesQuery.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,15 +21,23 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; -import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class UserRole { - - public static final String EINHEITLICHER_ANSPRECHPARTNER = "EINHEITLICHER_ANSPRECHPARTNER"; - public static final String VERWALTUNG_POSTSTELLE = "VERWALTUNG_POSTSTELLE"; - public static final String VERWALTUNG_USER = "VERWALTUNG_USER"; -} \ No newline at end of file +@Builder(toBuilder = true) +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@ToString +class FindUserProfilesQuery { + private String searchBy; + private String organisationsEinheitId; + private int limit; +} diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/RemoteUserIterator.java b/user-manager-server/src/main/java/de/ozgcloud/user/RemoteUserIterator.java similarity index 95% rename from user-manager-server/src/main/java/de/itvsh/kop/user/RemoteUserIterator.java rename to user-manager-server/src/main/java/de/ozgcloud/user/RemoteUserIterator.java index a336f04d164776a9ba85044b3fde36dfd4e36708..0d8b2090c7f001f509b4a52999ef19769741dde2 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/RemoteUserIterator.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/RemoteUserIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.Iterator; diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/RoleHierarchy.java b/user-manager-server/src/main/java/de/ozgcloud/user/RoleHierarchy.java new file mode 100644 index 0000000000000000000000000000000000000000..f86bc5586c62e61ec977aa0ea0e6593f50a7f06c --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/RoleHierarchy.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; +import java.util.Objects; + +import lombok.Builder; +import lombok.Getter; +import lombok.Singular; + +@Builder +@Getter +class RoleHierarchy { + + private final String roleName; + + @Singular + private List<RoleHierarchy> subRoles; + + public List<String> getFlattenedHierarchy(String roleName) { + var subRoles = new ArrayDeque<String>(); + collectSubRoles(this, roleName, subRoles); + return subRoles.stream().toList(); + } + + boolean collectSubRoles(RoleHierarchy role, String roleName, Deque<String> subRoles) { + subRoles.addLast(role.getRoleName()); + if (Objects.equals(role.getRoleName(), roleName)) { + return true; + } + for (var subRole : role.getSubRoles()) { + if (collectSubRoles(subRole, roleName, subRoles)) { + return true; + } + } + subRoles.removeLast(); + return false; + } + +} diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/User.java b/user-manager-server/src/main/java/de/ozgcloud/user/User.java similarity index 78% rename from user-manager-server/src/main/java/de/itvsh/kop/user/User.java rename to user-manager-server/src/main/java/de/ozgcloud/user/User.java index 99c8a9722443fb8bed03ef8caf47b372e895ff05..757609d8f273bf427cfd81d397a83f888a12cdd9 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/User.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/User.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.Collection; import java.util.Date; @@ -31,7 +31,7 @@ import org.bson.types.ObjectId; import com.fasterxml.jackson.annotation.JsonIgnore; -import de.itvsh.kop.user.settings.UserSettings; +import de.ozgcloud.user.settings.UserSettings; import io.quarkus.runtime.annotations.RegisterForReflection; import lombok.AllArgsConstructor; import lombok.Builder; @@ -51,22 +51,31 @@ import lombok.ToString; public class User { public static final String EXTERNAL_ID_FIELD = "externalId"; + public static final String KEYCLOAK_USER_ID = "keycloakUserId"; public static final String EMAIL_FIELD = "email"; public static final String DELETED_FIELD = "deleted"; public static final String LAST_SYNC_TIMESTAMP_FIELD = "lastSyncTimestamp"; public static final String LASTNAME_FIELD = "lastName"; public static final String FIRSTNAME_FIELD = "firstName"; + public static final String FULL_NAME_FIELD = "fullName"; + public static final String FULL_NAME_REVERSED_FIELD = "fullNameReversed"; public static final String USERNAME_FIELD = "username"; - static final String ORGANISATIONS_EINHEIT_IDS_FIELD = "organisationsEinheitIds"; - static final String NOTIFICATION_SEND_FOR_FIELD = "userSettings.notificationsSendFor"; + public static final String ORGANISATIONS_EINHEIT_IDS_FIELD = "organisationsEinheitIds"; + public static final String NOTIFICATION_SEND_FOR_FIELD = "userSettings.notificationsSendFor"; @JsonIgnore @BsonId private ObjectId id; @JsonIgnore private String externalId; + @JsonIgnore + private String keycloakUserId; private String firstName; private String lastName; + @JsonIgnore + private String fullName; + @JsonIgnore + private String fullNameReversed; private String username; private String email; @JsonIgnore diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/userprofile/UserProfileMapper.java b/user-manager-server/src/main/java/de/ozgcloud/user/UserIdProjection.java similarity index 65% rename from user-manager-server/src/main/java/de/itvsh/kop/user/userprofile/UserProfileMapper.java rename to user-manager-server/src/main/java/de/ozgcloud/user/UserIdProjection.java index dc0c33cf8f73338c49b9e08c6a7d4b5d83943bcd..9817fa38a38ca4d015482085352f9994f13d59a5 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/userprofile/UserProfileMapper.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/UserIdProjection.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,18 +21,24 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.userprofile; +package de.ozgcloud.user; -import org.mapstruct.Mapper; -import org.mapstruct.NullValueCheckStrategy; -import org.mapstruct.ReportingPolicy; +import org.bson.codecs.pojo.annotations.BsonIgnore; +import org.bson.types.ObjectId; -import de.itvsh.kop.user.User; +import io.quarkus.mongodb.panache.common.ProjectionFor; +import lombok.Getter; +import lombok.Setter; -@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, // - unmappedSourcePolicy = ReportingPolicy.WARN, // - nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) -interface UserProfileMapper { +@ProjectionFor(User.class) +@Setter +@Getter +public class UserIdProjection { - GrpcUserProfile mapTo(User userProfile); -} \ No newline at end of file + private ObjectId id; + + @BsonIgnore + public String getAsString() { + return id.toHexString(); + } +} diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/UserProfileResource.java b/user-manager-server/src/main/java/de/ozgcloud/user/UserProfileResource.java similarity index 65% rename from user-manager-server/src/main/java/de/itvsh/kop/user/UserProfileResource.java rename to user-manager-server/src/main/java/de/ozgcloud/user/UserProfileResource.java index 3d2ff11d2fd526739b1ba5490d059ed6e7ba9af5..e19c2a62ff33ffcb3a9b0a6da1ba6a1532ebeb89 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/UserProfileResource.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/UserProfileResource.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,30 +21,31 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; +import java.util.Optional; import java.util.stream.Stream; -import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; - import org.eclipse.microprofile.config.inject.ConfigProperty; import org.jboss.resteasy.reactive.common.util.RestMediaType; -import de.itvsh.kop.common.logging.KopLogging; +import de.ozgcloud.common.logging.OzgCloudLogging; import io.quarkus.hal.HalCollectionWrapper; import io.quarkus.hal.HalEntityWrapper; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; -@KopLogging +@OzgCloudLogging @Path(UserProfileResource.USERS_PATH) public class UserProfileResource { static final String PARAM_SEARCH_BY = "searchBy"; static final String PARAM_DELETED = "deleted"; + static final String PARAM_ORGANISATIONS_EINHEIT_ID = "organisationsEinheitId"; static final int LIMIT = 10; @@ -59,19 +60,29 @@ public class UserProfileResource { // TODO parameter in den resourceAssembler verschieben // TODO wozu ist der eigentlich gut? - bitte aus Request übernehmen - @ConfigProperty(name = "kop.user-manager.url") + @ConfigProperty(name = "ozgcloud.user-manager.url") String userManagerUrl; @GET @Produces({ MediaType.APPLICATION_JSON, RestMediaType.APPLICATION_HAL_JSON }) - public HalCollectionWrapper findUsers(@QueryParam(value = PARAM_SEARCH_BY) String query, @QueryParam(value = PARAM_DELETED) Boolean deleted) { + public HalCollectionWrapper findUsers( + @QueryParam(value = PARAM_SEARCH_BY) String searchBy, + @QueryParam(value = PARAM_DELETED) Optional<Boolean> deleted, + @QueryParam(value = PARAM_ORGANISATIONS_EINHEIT_ID) Optional<String> organisationsEinheitId) { + + var query = FindUserProfilesQuery.builder() + .searchBy(searchBy) + .organisationsEinheitId(organisationsEinheitId.orElse(null)) + .limit(LIMIT) + .build(); + Stream<User> users; - if (deleted == null) { - users = userService.findUsers(query, LIMIT); - } else if (deleted) { - users = userService.findInactiveUsers(query, LIMIT); + if (deleted.isEmpty()) { + users = userService.findUsers(query); + } else if (deleted.orElse(false)) { + users = userService.findInactiveUsers(query); } else { - users = userService.findActiveUsers(query, LIMIT); + users = userService.findActiveUsers(query); } return resourceAssembler.toUserProfileResourceList(users.toList(), userManagerUrl); } diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/UserProfileResourceAssembler.java b/user-manager-server/src/main/java/de/ozgcloud/user/UserProfileResourceAssembler.java similarity index 90% rename from user-manager-server/src/main/java/de/itvsh/kop/user/UserProfileResourceAssembler.java rename to user-manager-server/src/main/java/de/ozgcloud/user/UserProfileResourceAssembler.java index e4329c10bb0ff984a6afc492434c5c60ed24373e..e0a872a7554cd9ebe58b6bdb4252373b9cd9dbe2 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/UserProfileResourceAssembler.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/UserProfileResourceAssembler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,14 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.List; -import javax.enterprise.context.ApplicationScoped; -import javax.ws.rs.core.Link; +import de.ozgcloud.user.settings.UserSettingsResource; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.ws.rs.core.Link; -import de.itvsh.kop.user.settings.UserSettingsResource; import io.quarkus.hal.HalCollectionWrapper; import io.quarkus.hal.HalEntityWrapper; diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/UserRepository.java b/user-manager-server/src/main/java/de/ozgcloud/user/UserRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..c5d18817a72e19efce448d1d245ecfb369915eb1 --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/UserRepository.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user; + +import static de.ozgcloud.user.User.*; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.bson.types.ObjectId; + +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.common.errorhandling.ResourceNotFoundException; +import io.quarkus.mongodb.panache.PanacheMongoRepository; +import io.quarkus.panache.common.Parameters; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +@OzgCloudLogging +class UserRepository implements PanacheMongoRepository<User> { + + static final String PARAM_NAME_SEARCH_BY = "searchBy"; + static final String PARAM_NAME_DELETED = "deleted"; + static final String PARAM_NAME_ORGANISATIONS_EINHEIT_ID = "organisationsEinheitId"; + static final String PARAM_NAME_TIMESTAMP = "timestamp"; + + private static final String LIKE_OR = " like " + param(PARAM_NAME_SEARCH_BY) + " or "; + private static final String SEARCH_QUERY = LASTNAME_FIELD + LIKE_OR + + FIRSTNAME_FIELD + LIKE_OR + + USERNAME_FIELD + LIKE_OR + + FULL_NAME_FIELD + LIKE_OR + + FULL_NAME_REVERSED_FIELD + LIKE_OR + + EMAIL_FIELD + " like " + param(PARAM_NAME_SEARCH_BY); + + private static final String AND_DELETED = " and deleted = " + param(PARAM_NAME_DELETED); + private static final String AND_ORGANISATIONS_EINHEIT_ID_IN = " and " + ORGANISATIONS_EINHEIT_IDS_FIELD + " in " + param( + PARAM_NAME_ORGANISATIONS_EINHEIT_ID); + static final String UPDATE_UNSYNCED_USER_QUERY = LAST_SYNC_TIMESTAMP_FIELD + " < " + param(PARAM_NAME_TIMESTAMP); + + private static String param(String paramName) { + return String.format(":%s", paramName); + } + + public User updateUser(User userToUpdate) { + var user = findById(userToUpdate.getId()); + userToUpdate.setUserSettings(user.getUserSettings()); + update(userToUpdate); + + return findById(user.getId()); + } + + public Optional<User> findByExternalId(String externalId) { + return find(EXTERNAL_ID_FIELD, externalId).firstResultOptional(); + } + + public Optional<User> findById(String id) { + return Optional.ofNullable(id) + .filter(ObjectId::isValid) + .map(ObjectId::new) + .flatMap(this::findByIdOptional); + } + + public Optional<User> findByEmail(String email) { + return find(EMAIL_FIELD, email).firstResultOptional(); + } + + public Stream<User> findUsers(String query, int limit) { + var params = Parameters.with(PARAM_NAME_SEARCH_BY, toRegex(query)); + + return find(SEARCH_QUERY, params).range(0, limit - 1).stream(); + } + + public Stream<User> findUsersByDeleted(String query, boolean deleted, int limit) { + var params = Parameters.with(PARAM_NAME_SEARCH_BY, toRegex(query)).and(PARAM_NAME_DELETED, deleted); + + return find(SEARCH_QUERY + AND_DELETED, params).range(0, limit - 1).stream(); + } + + public Stream<User> findUsersByDeletedAndOrganisationsEinheitId(String query, boolean deleted, String organisationsEinheitId, int limit) { + var params = Parameters.with(PARAM_NAME_SEARCH_BY, toRegex(query)) + .and(PARAM_NAME_DELETED, deleted) + .and(PARAM_NAME_ORGANISATIONS_EINHEIT_ID, organisationsEinheitId); + + return find(SEARCH_QUERY + AND_DELETED + AND_ORGANISATIONS_EINHEIT_ID_IN, params).range(0, limit - 1).stream(); + } + + String toRegex(String query) { + return "/.*" + query + ".*/i"; + } + + public long updateUnsyncedUsers(long lastSyncTimestamp) { + var params = Parameters.with(PARAM_NAME_TIMESTAMP, lastSyncTimestamp); + return update(DELETED_FIELD, true).where(UPDATE_UNSYNCED_USER_QUERY, params); + } + + public User refresh(User user) { + return findByIdOptional(user.getId()) + .orElse(findByExternalId(user.getExternalId()).orElseThrow(() -> new ResourceNotFoundException(User.class, user.getExternalId()))); + } + + public Optional<User> findByKeycloakId(String id) { + return find(KEYCLOAK_USER_ID, id).firstResultOptional(); + } + + public Stream<String> findAllDeletedUserIds() { + return find(DELETED_FIELD, true).project(UserIdProjection.class).stream().map(UserIdProjection::getAsString); + } + + public void deleteById(String id) { + deleteById(new ObjectId(id)); + } + +} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/UserResourceMapper.java b/user-manager-server/src/main/java/de/ozgcloud/user/UserResourceMapper.java similarity index 75% rename from user-manager-server/src/main/java/de/itvsh/kop/user/UserResourceMapper.java rename to user-manager-server/src/main/java/de/ozgcloud/user/UserResourceMapper.java index 930db5ccedf04d288dcfcf0f95523abae28e7c7d..0ebec5903e5fe0b2373133b1a9fb6cb197c577ba 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/UserResourceMapper.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/UserResourceMapper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,17 +21,19 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.stream.Stream; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.UserResource; @@ -42,7 +44,7 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; -import de.itvsh.kop.user.keycloak.KeycloakApiProperties; +import de.ozgcloud.user.keycloak.KeycloakApiProperties; @Mapper(unmappedTargetPolicy = ReportingPolicy.WARN) public abstract class UserResourceMapper { @@ -57,8 +59,11 @@ public abstract class UserResourceMapper { @Mapping(target = "email", expression = "java(mapEmail(userRes))") @Mapping(target = "firstName", expression = "java(mapFirstName(userRes))") @Mapping(target = "lastName", expression = "java(mapLastName(userRes))") + @Mapping(target = "fullName", expression = "java(mapFullName(userRes))") + @Mapping(target = "fullNameReversed", expression = "java(mapFullNameReversed(userRes))") @Mapping(target = "username", expression = "java(mapUsername(userRes))") @Mapping(target = "externalId", expression = "java(mapId(userRes))") + @Mapping(target = "keycloakUserId", expression = "java(mapKeycloakUserId(userRes))") @Mapping(target = "organisationsEinheitIds", expression = "java(mapOrganisationsEinheitIds(userRes))") @Mapping(target = "roles", expression = "java(mapRoles(userRes))") @Mapping(target = "lastSyncTimestamp", ignore = true) @@ -68,7 +73,7 @@ public abstract class UserResourceMapper { Date mapCreatedAt(UserResource userRes) { var createdAt = userRes.toRepresentation().getCreatedTimestamp(); - return createdAt != null ? new Date(createdAt) : new Date(); + return Optional.ofNullable(createdAt).map(Date::new).orElse(new Date()); } Set<String> mapOrganisationsEinheitIds(UserResource userRes) { @@ -79,10 +84,7 @@ public abstract class UserResourceMapper { private List<String> getOrganisationsEinheitIdsFromGroups(List<GroupRepresentation> groups) { return groups.stream() - .map(group -> { - var groupFromRealm = realm.getGroupByPath(group.getPath()); - return groupFromRealm != null ? groupFromRealm.getAttributes() : null; - }) + .map(this::mapGroup) .filter(Objects::nonNull) .map(attributeMap -> attributeMap.get(properties.organisationsEinheitIdKey())) .filter(Objects::nonNull) @@ -90,9 +92,14 @@ public abstract class UserResourceMapper { .toList(); } + private Map<String, List<String>> mapGroup(GroupRepresentation group) { + var groupFromRealm = realm.getGroupByPath(group.getPath()); + + return Optional.ofNullable(groupFromRealm).map(GroupRepresentation::getAttributes).orElse(null); + } + List<String> mapRoles(UserResource userRes) { var roleRepresentation = Optional.ofNullable(userRes.roles().getAll().getClientMappings()) - .filter(Objects::nonNull) .filter(map -> map.containsKey(properties.client())) .map(map -> map.get(properties.client())) .map(ClientMappingsRepresentation::getMappings) @@ -106,12 +113,15 @@ public abstract class UserResourceMapper { return Optional.ofNullable(userRepresentation.getAttributes()) .map(attributes -> attributes.get(properties.ldapIdKey())) - .filter(Objects::nonNull) .map(id -> id.get(0)) .orElseGet(userRepresentation::getId); } + String mapKeycloakUserId(UserResource userRes) { + return userRes.toRepresentation().getId(); + } + String mapEmail(UserResource userRes) { return userRes.toRepresentation().getEmail(); } @@ -127,4 +137,14 @@ public abstract class UserResourceMapper { String mapUsername(UserResource userRes) { return userRes.toRepresentation().getUsername(); } + + String mapFullName(UserResource userRes) { + return String.join(" ", Stream.of(userRes.toRepresentation().getFirstName(), userRes.toRepresentation().getLastName()) + .filter(Objects::nonNull).toArray(String[]::new)); + } + + String mapFullNameReversed(UserResource userRes) { + return String.join(" ", Stream.of(userRes.toRepresentation().getLastName(), userRes.toRepresentation().getFirstName()) + .filter(Objects::nonNull).toArray(String[]::new)); + } } diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/UserRole.java b/user-manager-server/src/main/java/de/ozgcloud/user/UserRole.java new file mode 100644 index 0000000000000000000000000000000000000000..6877095cc6fcf3102ac076ae6e4d97796d89688e --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/UserRole.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user; + +import java.util.Collection; +import java.util.Collections; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class UserRole { + + public static final String EINHEITLICHER_ANSPRECHPARTNER = "EINHEITLICHER_ANSPRECHPARTNER"; + public static final String VERWALTUNG_POSTSTELLE = "VERWALTUNG_POSTSTELLE"; + public static final String VERWALTUNG_USER = "VERWALTUNG_USER"; + public static final String VERWALTUNG_LOESCHEN = "VERWALTUNG_LOESCHEN"; + + private static final RoleHierarchy HIERARCHY = RoleHierarchy.builder() + .roleName(VERWALTUNG_LOESCHEN) + .subRole(RoleHierarchy.builder() + .roleName(VERWALTUNG_USER) + .build()) + .build(); + + public static boolean containsWithinRoleHierarchy(Collection<String> userRoles, String roleName) { + return !Collections.disjoint(userRoles, HIERARCHY.getFlattenedHierarchy(roleName)); + } + +} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/UserService.java b/user-manager-server/src/main/java/de/ozgcloud/user/UserService.java new file mode 100644 index 0000000000000000000000000000000000000000..223a1eebc51906e39ecd059bc4614c7d19a70255 --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/UserService.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.apache.commons.lang3.StringUtils; + +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.common.errorhandling.ResourceNotFoundException; +import de.ozgcloud.user.common.errorhandling.TechnicalException; +import de.ozgcloud.user.keycloak.KeycloakUserRemoteService; +import io.smallrye.mutiny.Uni; +import io.smallrye.mutiny.infrastructure.Infrastructure; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +@OzgCloudLogging +public class UserService { + + @Inject + UserRepository repository; + @Inject + KeycloakUserRemoteService keycloakUserRemoteService; + + public User save(User user) { + findUser(user).ifPresentOrElse(persistedUser -> repository.updateUser(addIdUser(user, persistedUser)), + () -> repository.persist(user)); + return repository.refresh(user); + } + + public Stream<User> findUsers(FindUserProfilesQuery query) { + return repository.findUsers(query.getSearchBy(), query.getLimit()); + } + + public Stream<User> findActiveUsers(FindUserProfilesQuery query) { + if (StringUtils.isNotBlank(query.getOrganisationsEinheitId())) { + return repository.findUsersByDeletedAndOrganisationsEinheitId( + query.getSearchBy(), + false, + query.getOrganisationsEinheitId(), + query.getLimit()); + } + return repository.findUsersByDeleted(query.getSearchBy(), false, query.getLimit()); + } + + public Stream<User> findInactiveUsers(FindUserProfilesQuery query) { + if (StringUtils.isNotBlank(query.getOrganisationsEinheitId())) { + return repository.findUsersByDeletedAndOrganisationsEinheitId( + query.getSearchBy(), + true, + query.getOrganisationsEinheitId(), + query.getLimit()); + } + return repository.findUsersByDeleted(query.getSearchBy(), true, query.getLimit()); + } + + private Optional<User> findUser(User user) { + return repository.findByExternalId(user.getExternalId()) + .or(() -> findByEmail(user.getEmail())); + } + + private Optional<User> findByEmail(String email) { + if (StringUtils.isNotBlank(email)) { + return repository.findByEmail(email); + } + return Optional.empty(); + } + + private User addIdUser(User user, User persistedUser) { + return user.toBuilder().id(persistedUser.getId()).build(); + } + + public void markUnsyncedUsersAsDeleted(long lastSyncTimestamp) { + repository.updateUnsyncedUsers(lastSyncTimestamp); + } + + public User getById(String id) { + return repository.findById(id).orElseThrow(() -> new ResourceNotFoundException(User.class, id)); + } + + public User findByExternalId(String externalId) { + return repository.findByKeycloakId(externalId) + .or(() -> findInKeycloakAndSave(externalId)) + .orElseThrow(() -> new ResourceNotFoundException(User.class, externalId)); + } + + private Optional<User> findInKeycloakAndSave(String externalId) { + return keycloakUserRemoteService.findUserById(externalId).map(this::saveAndSync); + } + + public User saveAndSync(User user) { + var saved = save(user); + Uni.createFrom() + .item(user) + .runSubscriptionOn(Infrastructure.getDefaultWorkerPool()) + .subscribe() + .with(u -> keycloakUserRemoteService.updateOzgCloudUserId(saved)); + return saved; + } + + public Stream<String> findAllInactiveUserIds() { + return repository.findAllDeletedUserIds(); + } + + public void deleteInactive(String userId) { + var user = getById(userId); + assertInactiveUser(user); + repository.deleteById(userId); + } + + void assertInactiveUser(User user) { + if (!user.isDeleted()) { + throw new TechnicalException(String.format("Deleting active users is not allowed [user id: %s].", user.getId().toHexString())); + } + } +} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/JwtUtil.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/JwtUtil.java similarity index 90% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/JwtUtil.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/JwtUtil.java index be7bae09ba093a0616d1eec4dc89d37a7c6ca6c9..3ce6b05358500e6df84fa8db1b71f1f186aa0063 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/JwtUtil.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/JwtUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,23 +21,22 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common; +package de.ozgcloud.user.common; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.json.JsonArray; -import javax.json.JsonString; +import de.ozgcloud.user.keycloak.KeycloakApiProperties; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.json.JsonArray; +import jakarta.json.JsonString; import org.apache.commons.lang3.StringUtils; import org.eclipse.microprofile.jwt.JsonWebToken; -import de.itvsh.kop.user.keycloak.KeycloakApiProperties; - @ApplicationScoped public class JwtUtil { diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/LivenessCheck.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/LivenessCheck.java similarity index 92% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/LivenessCheck.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/LivenessCheck.java index fba90fa41fe3faa4e4747d4de498e3bbeecc6594..ce76ea7285d573e54352fe8f155a6adb22cd131e 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/LivenessCheck.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/LivenessCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common; +package de.ozgcloud.user.common; import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/NativeConfig.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/NativeConfig.java similarity index 92% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/NativeConfig.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/NativeConfig.java index 12c4482bdecd3db70c6b6885f9f1cab0b86a5084..1708a22ec9251bd742a4d83e20440ec444f2663d 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/NativeConfig.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/NativeConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,8 +21,9 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common; +package de.ozgcloud.user.common; +import de.ozgcloud.user.UserIdProjection; import io.quarkus.runtime.annotations.RegisterForReflection; @RegisterForReflection(targets = { @@ -42,7 +43,8 @@ import io.quarkus.runtime.annotations.RegisterForReflection; org.jboss.resteasy.plugins.providers.multipart.MultipartFormAnnotationWriter.class, org.jboss.resteasy.plugins.providers.multipart.MimeMultipartProvider.class, org.jboss.resteasy.plugins.providers.multipart.XopWithMultipartRelatedReader.class, - org.jboss.resteasy.plugins.providers.multipart.XopWithMultipartRelatedWriter.class + org.jboss.resteasy.plugins.providers.multipart.XopWithMultipartRelatedWriter.class, + UserIdProjection.class }) public class NativeConfig { } diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/TargetTypeProvider.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/TargetTypeProvider.java similarity index 88% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/TargetTypeProvider.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/TargetTypeProvider.java index 93a2f92e0bcc35a6c121c4c2aa5390208bbe27ba..6404962ec7b4981ef9ddca2406f3149c0a558384 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/TargetTypeProvider.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/TargetTypeProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,11 +21,11 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common; +package de.ozgcloud.user.common; import java.lang.reflect.Type; -import javax.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.ApplicationScoped; import org.jboss.resteasy.reactive.server.core.CurrentRequestManager; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/CallContextUser.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/CallContextUser.java similarity index 90% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/CallContextUser.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/CallContextUser.java index f6426845a1a04b6fb64571f443b8d0cd348472d7..0509bfb404f358bd893ca9f26da9112ff13fc8a0 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/CallContextUser.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/CallContextUser.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,12 +21,11 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; import java.io.Serializable; import java.security.Principal; import java.util.Collection; -import java.util.List; import java.util.Optional; import lombok.Builder; @@ -54,7 +53,7 @@ public class CallContextUser implements Serializable, Principal { @Builder.Default private final transient boolean authenticated = false; - private final transient List<String> roles; + private final transient Collection<String> roles; @Override public String getName() { diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/CurrentCallContextUserService.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/CurrentCallContextUserService.java similarity index 75% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/CurrentCallContextUserService.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/CurrentCallContextUserService.java index d326597eb5a0d60e852c71ee8fa6e02e49c38d4e..493def198efedbf0bdc87c80a28c3326f9df31e2 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/CurrentCallContextUserService.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/CurrentCallContextUserService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,17 +21,19 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; import java.util.Optional; -import javax.enterprise.context.RequestScoped; +import de.ozgcloud.user.UserRole; +import jakarta.enterprise.context.RequestScoped; @RequestScoped public class CurrentCallContextUserService { + private CallContextUser user; - void setCallContextUser(CallContextUser callContextUser) { + public void setCallContextUser(CallContextUser callContextUser) { this.user = callContextUser; } @@ -40,6 +42,10 @@ public class CurrentCallContextUserService { } public boolean hasRole(String userRole) { - return user.getRoles().contains(userRole); + return UserRole.containsWithinRoleHierarchy(user.getRoles(), userRole); + } + + public void clearCallContextUser() { + this.user = null; } } diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/GrpcCallContextInterceptor.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/GrpcCallContextInterceptor.java similarity index 60% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/GrpcCallContextInterceptor.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/GrpcCallContextInterceptor.java index 097afa48dc13827f50b4628e77eda344dc91c762..626832677cedf86c7a715135c06781fec51dee57 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/GrpcCallContextInterceptor.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/GrpcCallContextInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,33 +21,30 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; -import java.nio.charset.StandardCharsets; -import java.util.Collection; import java.util.Optional; import java.util.UUID; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import org.apache.logging.log4j.CloseableThreadContext; +import de.ozgcloud.user.common.errorhandling.ResourceNotFoundException; import io.grpc.ForwardingServerCallListener; import io.grpc.Metadata; -import io.grpc.Metadata.Key; import io.grpc.ServerCall; import io.grpc.ServerCall.Listener; import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; +import io.grpc.Status; import io.quarkus.grpc.GlobalInterceptor; import lombok.extern.log4j.Log4j2; +@Log4j2 @ApplicationScoped @GlobalInterceptor -@Log4j2 public class GrpcCallContextInterceptor implements ServerInterceptor { private static final String REQUEST_ID_KEY = "requestId"; @@ -61,22 +58,36 @@ public class GrpcCallContextInterceptor implements ServerInterceptor { static final String REQUEST_ID_PLACEHOLDER = "no-requestId-given"; + static final String MISSING_CLIENT_NAME_MESSAGE_TEMPLATE = "Missing client name in grpc header for request %s."; + @Inject CurrentCallContextUserService userService; @Override public <Q, S> Listener<Q> interceptCall(ServerCall<Q, S> call, Metadata headers, ServerCallHandler<Q, S> next) { - return new LogContextSettingListener<>(next.startCall(call, headers), headers); + return new LogContextSettingListener<>(next.startCall(call, headers), call, headers); } - class LogContextSettingListener<A> extends ForwardingServerCallListener.SimpleForwardingServerCallListener<A> { + class LogContextSettingListener<A, Q, S> extends ForwardingServerCallListener.SimpleForwardingServerCallListener<A> { private final String requestId; private final Metadata headers; + private final ServerCall<Q, S> originCall; + private final Optional<String> clientName; - public LogContextSettingListener(ServerCall.Listener<A> delegate, Metadata headers) { + public LogContextSettingListener(ServerCall.Listener<A> delegate, ServerCall<Q, S> originCall, Metadata headers) { super(delegate); this.headers = headers; this.requestId = getRequestId(); + this.originCall = originCall; + this.clientName = getClientName(); + } + + String getRequestId() { + return GrpcUtil.getFromHeaders(KEY_REQUEST_ID, headers).orElseGet(() -> UUID.randomUUID().toString()); + } + + private Optional<String> getClientName() { + return GrpcUtil.getFromHeaders(KEY_CLIENT_NAME, headers); } @Override @@ -101,67 +112,61 @@ public class GrpcCallContextInterceptor implements ServerInterceptor { @Override public void onReady() { + if (clientName.isEmpty()) { + handleMissingClientName(); + return; + } doSurroundOn(super::onReady); } + void handleMissingClientName() { + var message = String.format(MISSING_CLIENT_NAME_MESSAGE_TEMPLATE, requestId); + LOG.error(message); + originCall.close(Status.PERMISSION_DENIED.withDescription(message), headers); + } + void doSurroundOn(Runnable runnable) { - try (CloseableThreadContext.Instance ctc = CloseableThreadContext.put(REQUEST_ID_KEY, requestId)) { + try (var ctc = CloseableThreadContext.put(REQUEST_ID_KEY, requestId)) { startSecurityContext(); runnable.run(); + } catch (Exception e) { + handleException(e); + } finally { clearSecurityContext(); } } - String getRequestId() { - return getFromHeaders(KEY_REQUEST_ID, headers).orElseGet(() -> UUID.randomUUID().toString()); + void handleException(Exception e) { + if (e instanceof ResourceNotFoundException) { + LOG.warn("Grpc Interceptor: " + e.getMessage(), e); + originCall.close(Status.NOT_FOUND, headers); + } else { + LOG.error("Grpc Interceptor: Unknown exception", e); + originCall.close(Status.UNKNOWN, headers); + } } void startSecurityContext() { userService.setCallContextUser(createCallContextUser()); - } void clearSecurityContext() { - userService.setCallContextUser(createCallContextUser()); - + userService.clearCallContextUser(); } CallContextUser createCallContextUser() { var builder = CallContextUser.builder() - .userId(getFromHeaders(GrpcCallContextInterceptor.KEY_USER_ID, headers)) - .userName(getFromHeaders(KEY_USER_NAME, headers)) + .clientName(clientName.orElseGet(() -> null)) + .userId(GrpcUtil.getFromHeaders(GrpcCallContextInterceptor.KEY_USER_ID, headers)) + .userName(GrpcUtil.getFromHeaders(KEY_USER_NAME, headers)) .authenticated(true) - .organisatorischeEinheitenIds(getCollection(KEY_ACCESS_LIMITED_ORGAID, headers)); + .organisatorischeEinheitenIds(GrpcUtil.getCollection(KEY_ACCESS_LIMITED_ORGAID, headers)); - getFromHeaders(KEY_ACCESS_LIMITED, headers).map(Boolean::parseBoolean).ifPresentOrElse( + GrpcUtil.getFromHeaders(KEY_ACCESS_LIMITED, headers).map(Boolean::parseBoolean).ifPresentOrElse( builder::organisationEinheitenIdCheckNecessary, () -> builder.organisationEinheitenIdCheckNecessary(false)); - // FIXME throw exception if missing required data - // Lernen: niemals code von woanders kopieren ohne mal darüber nachzudenken - getFromHeaders(KEY_CLIENT_NAME, headers).ifPresentOrElse(builder::clientName, () -> LOG.warn("Missing client name in grpc header.")); - return builder.build(); } } - - // TODO move to a grpcUtil class in common - static Optional<String> getFromHeaders(String key, Metadata headers) { - return Optional.ofNullable(headers.get(createKeyOf(key))).map(val -> new String(val, StandardCharsets.UTF_8)); - } - - // TODO move to a grpcUtil class in common - static Collection<String> getCollection(String key, Metadata headers) { - return Optional.ofNullable(headers.getAll(createKeyOf(key))) - .map(vals -> StreamSupport.stream(vals.spliterator(), false)) - .orElseGet(Stream::empty) - .map(bytes -> new String(bytes, StandardCharsets.UTF_8)) - .toList(); - } - - // TODO move to a grpcUtil class in common - static Key<byte[]> createKeyOf(String key) { - return Key.of(key, Metadata.BINARY_BYTE_MARSHALLER); - } - } diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/GrpcUtil.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/GrpcUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..d48cbed28056db54912997603d4a48ddae8b2a29 --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/GrpcUtil.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.common.callcontext; + +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Optional; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import io.grpc.Metadata; +import io.grpc.Metadata.Key; + +// TODO move to a grpcUtil class in common +class GrpcUtil { + + public static Optional<String> getFromHeaders(String key, Metadata headers) { + return Optional.ofNullable(headers.get(createKeyOf(key))) + .map(GrpcUtil::toUtf8String); + } + + public static Collection<String> getCollection(String key, Metadata headers) { + return Optional.ofNullable(headers.getAll(createKeyOf(key))) + .map(GrpcUtil::split) + .orElseGet(Stream::empty) + .map(GrpcUtil::toUtf8String) + .toList(); + } + + public static Key<byte[]> createKeyOf(String key) { + return Key.of(key, Metadata.BINARY_BYTE_MARSHALLER); + } + + private static Stream<byte[]> split(Iterable<byte[]> vals) { + return StreamSupport.stream(vals.spliterator(), false); + } + + private static String toUtf8String(byte[] bytes) { + return new String(bytes, StandardCharsets.UTF_8); + } +} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/HttpRequestInterceptor.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/HttpRequestInterceptor.java similarity index 86% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/HttpRequestInterceptor.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/HttpRequestInterceptor.java index 11366a4dc7c922b943317d4121d570b27870d5dc..591c7d32a3fe29ef32754e571e6257fa384a161b 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/HttpRequestInterceptor.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/HttpRequestInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,14 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; import java.io.IOException; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.ext.Provider; -import javax.ws.rs.ext.ReaderInterceptor; -import javax.ws.rs.ext.ReaderInterceptorContext; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.ext.Provider; +import jakarta.ws.rs.ext.ReaderInterceptor; +import jakarta.ws.rs.ext.ReaderInterceptorContext; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.CloseableThreadContext; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/HttpSecurityFilter.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/HttpSecurityFilter.java similarity index 81% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/HttpSecurityFilter.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/HttpSecurityFilter.java index a84743ecc0584e161c40e755b1b80e27357599f6..0b0ba71051ac825bbe74a49274e84ac909c016cf 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/callcontext/HttpSecurityFilter.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/callcontext/HttpSecurityFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,17 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; import java.io.IOException; -import javax.inject.Inject; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.PreMatching; -import javax.ws.rs.ext.Provider; +import jakarta.inject.Inject; +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.container.ContainerRequestFilter; +import jakarta.ws.rs.container.PreMatching; +import jakarta.ws.rs.ext.Provider; -import de.itvsh.kop.user.common.JwtUtil; +import de.ozgcloud.user.common.JwtUtil; @Provider @PreMatching diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/AccessForbiddenException.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/AccessForbiddenException.java similarity index 88% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/AccessForbiddenException.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/AccessForbiddenException.java index 31100db1c7bbb9bed171efa08a22517070ff3d5a..b7c1e5245c901b0e9bf76e6abab039eb5972e841 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/AccessForbiddenException.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/AccessForbiddenException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,9 +21,9 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; -import de.itvsh.kop.common.errorhandling.FunctionalErrorCode; +import de.ozgcloud.common.errorhandling.FunctionalErrorCode; public class AccessForbiddenException extends FunctionalException { private static final long serialVersionUID = 1L; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ApiError.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ApiError.java similarity index 91% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ApiError.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ApiError.java index ed83cb428be3525a4838c7b5176b0bdbe434880c..ba1a680f8e64d03bc39d54142b4bc1ed4306edcd 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ApiError.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ApiError.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; import java.util.List; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ApiErrorUtil.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ApiErrorUtil.java similarity index 82% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ApiErrorUtil.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ApiErrorUtil.java index e81936ce1366a974a7e0efaf743b106fb8709746..ce2e075f304d01298d5d9496a93fa1cd2e206d2b 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ApiErrorUtil.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ApiErrorUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,20 +21,20 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; import java.util.UUID; -import javax.enterprise.context.ApplicationScoped; - -import de.itvsh.kop.common.errorhandling.ExceptionUtil; +import de.ozgcloud.common.errorhandling.ExceptionUtil; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.ws.rs.NotFoundException; import lombok.extern.log4j.Log4j2; @Log4j2 @ApplicationScoped public class ApiErrorUtil { - public static final String RESOURCE_NOT_FOUNT_MESSAGE_CODE = "resource.not_found"; + public static final String RESOURCE_NOT_FOUND_MESSAGE_CODE = "resource.not_found"; public static final String RUNTIME_MESSAGE_CODE = "generale.server_error"; public static final String ACCESS_DENIED_MESSAGE_CODE = "generale.access_denied"; public static final String SERVICE_UNAVAILABLE_MESSAGE_CODE = "generale.service_unavailable"; @@ -59,12 +59,20 @@ public class ApiErrorUtil { return Issue.builder().messageCode(RUNTIME_MESSAGE_CODE).message(message).exceptionId(exceptionId).build(); } + public ApiError buildFromNotFoundException(NotFoundException e) { + return ApiError.builder().issue(buildIssueForNotFoundException(e)).build(); + } + + private Issue buildIssueForNotFoundException(NotFoundException e) { + return Issue.builder().message(e.getMessage()).messageCode(RESOURCE_NOT_FOUND_MESSAGE_CODE).exceptionId(createExceptionId()).build(); + } + public ApiError buildFromResourceNotFoundException(ResourceNotFoundException e) { return ApiError.builder().issue(buildIssueForResourceNotFoundException(e)).build(); } private Issue buildIssueForResourceNotFoundException(ResourceNotFoundException e) { - return Issue.builder().message(e.getMessage()).messageCode(RESOURCE_NOT_FOUNT_MESSAGE_CODE).exceptionId(e.getExceptionId()).build(); + return Issue.builder().message(e.getMessage()).messageCode(RESOURCE_NOT_FOUND_MESSAGE_CODE).exceptionId(e.getExceptionId()).build(); } public ApiError buildFromAccessForbiddenException(AccessForbiddenException e) { diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ExceptionHandler.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ExceptionHandler.java similarity index 78% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ExceptionHandler.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ExceptionHandler.java index d751f9aa0a8332b1d2a09865c0d8c7d48b6a91e1..b3284cc19be5c00d16e74d011c39784aa450f279 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ExceptionHandler.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ExceptionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,11 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; -import javax.inject.Inject; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.UriInfo; import org.jboss.resteasy.reactive.server.ServerExceptionMapper; @@ -37,6 +39,9 @@ public class ExceptionHandler { @Inject ApiErrorUtil apiErrorUtil; + @Inject + UriInfo uriInfo; + @ServerExceptionMapper public Response mapRuntimeException(RuntimeException e) { LOG.error(e.getMessage(), e); @@ -45,6 +50,14 @@ public class ExceptionHandler { .build(); } + @ServerExceptionMapper + public Response mapNotFoundException(NotFoundException e) { + LOG.warn(e.getMessage() + ". Path: " + uriInfo.getPath(), e); + return Response.status(Status.NOT_FOUND) + .entity(apiErrorUtil.buildFromNotFoundException(e)) + .build(); + } + @ServerExceptionMapper public Response mapResourceNotFoundException(ResourceNotFoundException e) { LOG.info(e.getMessage(), e); diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/FunctionalException.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/FunctionalException.java similarity index 84% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/FunctionalException.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/FunctionalException.java index a304ccf2f92e71ad90e16fc6224bbb24efd16051..dc3162be229b18a78f9e6c8121da260c62fe03ae 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/FunctionalException.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/FunctionalException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,14 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; - -import de.itvsh.kop.common.errorhandling.ExceptionUtil; -import de.itvsh.kop.common.errorhandling.FunctionalErrorCode; -import de.itvsh.kop.common.errorhandling.IdentifiableException; +package de.ozgcloud.user.common.errorhandling; import java.util.UUID; +import de.ozgcloud.common.errorhandling.ExceptionUtil; +import de.ozgcloud.common.errorhandling.FunctionalErrorCode; +import de.ozgcloud.common.errorhandling.IdentifiableException; + public class FunctionalException extends RuntimeException implements IdentifiableException { private static final long serialVersionUID = 1L; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/Issue.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/Issue.java similarity index 93% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/Issue.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/Issue.java index 7ef4deb71a0835790a4ad5c65c5d5a3274fffcf0..0d9261f2451604ff3684cf6cc2ee00652350e9ea 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/Issue.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/Issue.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; import java.util.List; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/KeycloakUnavailableException.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/KeycloakUnavailableException.java similarity index 92% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/KeycloakUnavailableException.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/KeycloakUnavailableException.java index 5eadd9f3600e9760aa7fb92b60212a57502df865..c0fec05e4a8a3f3defbe7d435a472a58b9fbb849 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/KeycloakUnavailableException.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/KeycloakUnavailableException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; public class KeycloakUnavailableException extends TechnicalException { diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/LockCreationException.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/LockCreationException.java similarity index 91% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/LockCreationException.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/LockCreationException.java index 926021272524586421d9ee79276ce8d2544969c6..beefa50748b5447ebeb284707bc0d8540bdb8e51 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/LockCreationException.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/LockCreationException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; public class LockCreationException extends TechnicalException { diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ResourceNotFoundException.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ResourceNotFoundException.java similarity index 89% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ResourceNotFoundException.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ResourceNotFoundException.java index d6346d099bb28c53782988dc7a5ea82ba8d371ce..4bca21a45db5bdc4c2b5ad2a0f99d0982262b807 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/ResourceNotFoundException.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/ResourceNotFoundException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,9 +21,9 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; -import de.itvsh.kop.common.errorhandling.FunctionalErrorCode; +import de.ozgcloud.common.errorhandling.FunctionalErrorCode; import lombok.Getter; @Getter diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/TechnicalException.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/TechnicalException.java similarity index 92% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/TechnicalException.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/TechnicalException.java index 67dd8ec85f392e467096b79e93c2cbca19150f80..07a8b03e06bf7239d1e58034fa2729d4e9f056c9 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/TechnicalException.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/errorhandling/TechnicalException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; import java.util.UUID; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/Lock.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/lock/Lock.java similarity index 92% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/Lock.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/lock/Lock.java index f6399a5d0b43f634553256d6597bc9b5d6633367..578c84a7c783a374030a5ad22d0ffb2931a35649 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/Lock.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/lock/Lock.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.lock; +package de.ozgcloud.user.common.lock; import io.quarkus.mongodb.panache.PanacheMongoEntity; import io.quarkus.mongodb.panache.common.MongoEntity; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/LockRepository.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/lock/LockRepository.java similarity index 86% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/LockRepository.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/lock/LockRepository.java index ea4f6fceedfb0b336356790934d4bb4d9ba3e03e..0d34a268aeb60a632f65a7f155b181df99f6ef47 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/LockRepository.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/lock/LockRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,18 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.lock; +package de.ozgcloud.user.common.lock; import java.time.Instant; import java.util.Optional; -import javax.enterprise.context.ApplicationScoped; - -import de.itvsh.kop.common.logging.KopLogging; +import de.ozgcloud.common.logging.OzgCloudLogging; import io.quarkus.mongodb.panache.PanacheMongoRepository; +import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped -@KopLogging +@OzgCloudLogging class LockRepository implements PanacheMongoRepository<Lock> { Optional<Lock> findLockBefore(Instant timestamp) { diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/LockService.java b/user-manager-server/src/main/java/de/ozgcloud/user/common/lock/LockService.java similarity index 74% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/LockService.java rename to user-manager-server/src/main/java/de/ozgcloud/user/common/lock/LockService.java index 6c1d662e61051ab36b3a40038430a415f5093d2d..8734d65a5f87fa723409c0c9ff90a6a9a33dd78e 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/lock/LockService.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/common/lock/LockService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,21 +21,21 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.lock; +package de.ozgcloud.user.common.lock; import java.time.Instant; import java.time.temporal.ChronoUnit; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; -import de.itvsh.kop.common.logging.KopLogging; -import de.itvsh.kop.user.common.errorhandling.LockCreationException; +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.common.errorhandling.LockCreationException; import lombok.extern.log4j.Log4j2; @Log4j2 @ApplicationScoped -@KopLogging +@OzgCloudLogging public class LockService { @Inject @@ -56,17 +56,24 @@ public class LockService { return lastSyncTimeStamp.plus(1, ChronoUnit.DAYS).isBefore(Instant.now()); } - public void unlock(Lock lock) { - repository.delete(lock); - LOG.info("Lock deleted"); + public void unlock() { + var count = repository.deleteAll(); + LOG.debug("%s Locks deleted".formatted(count)); } public void lock(Instant timestamp) { repository.persist(Lock.builder().timestamp(timestamp.toEpochMilli()).build()); - LOG.info("Lock created"); + LOG.debug("Lock created"); } - public Lock getByTimestamp(Instant timestamp) { + Lock getByTimestamp(Instant timestamp) { return repository.findLock(timestamp).orElseThrow(LockCreationException::new); } + + public Lock lockCollection() { + var now = Instant.now(); + lock(now); + + return getByTimestamp(now); + } } diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakApiProperties.java b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakApiProperties.java similarity index 85% rename from user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakApiProperties.java rename to user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakApiProperties.java index 5bb7e88df733c7878d78ea93aedcb3a83c62bbf4..a1f52112a04d1e3f69cbeaadaaae46b3a1f15a3d 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakApiProperties.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakApiProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,13 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.keycloak; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; import io.smallrye.config.ConfigMapping; -@ConfigMapping(prefix = "kop.keycloak.api") +@ConfigMapping(prefix = "ozgcloud.keycloak.api") public interface KeycloakApiProperties { @NotBlank diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakApiService.java b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakApiService.java similarity index 54% rename from user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakApiService.java rename to user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakApiService.java index 403fc8bd1e2076239aa5bedbd7a89bad908643b2..59474563171fa9a25cede393f2322b684bff6f65 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakApiService.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakApiService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,30 +21,36 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.keycloak; +import java.util.Optional; import java.util.Spliterators; import java.util.function.Supplier; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.ws.rs.ClientErrorException; -import javax.ws.rs.ProcessingException; - -import de.itvsh.kop.common.logging.KopLogging; +import org.apache.commons.lang3.ObjectUtils; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.admin.client.resource.UserResource; import org.keycloak.representations.idm.UserRepresentation; -import de.itvsh.kop.user.RemoteUserIterator; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserResourceMapper; -import de.itvsh.kop.user.common.errorhandling.KeycloakUnavailableException; +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.RemoteUserIterator; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserResourceMapper; +import de.ozgcloud.user.common.errorhandling.KeycloakUnavailableException; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.ClientErrorException; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.ProcessingException; +import lombok.extern.log4j.Log4j2; @ApplicationScoped -@KopLogging +@OzgCloudLogging +@Log4j2 class KeycloakApiService { @Inject @@ -66,6 +72,14 @@ class KeycloakApiService { return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); } + Optional<User> findUserById(String id) { + try { + return Optional.of(realmResource.users().get(id)).map(mapper::toKopUser); + } catch (NotFoundException e) { + return Optional.empty(); + } + } + private RemoteUserIterator createRealmUserIterator() { return new RemoteUserIterator(realmResource); } @@ -74,11 +88,29 @@ class KeycloakApiService { return mapper.toKopUser(realmResource.users().get(userRepresentation.getId())); } - private <T> T handlingKeycloakException(Supplier<T> runnable) { + <T> T handlingKeycloakException(Supplier<T> runnable) { try { return runnable.get(); } catch (ClientErrorException | ProcessingException | IllegalStateException e) { throw new KeycloakUnavailableException(properties.user(), properties.realm(), keycloakUrl, e); } } + + public void updateAttribute(String keycloakUserId, String attributeName, String attributeValue) { + var userResource = realmResource.users().get(keycloakUserId); + var userRepresentation = userResource.toRepresentation(); + var ozgCloudUserIdInKeycloak = userRepresentation.firstAttribute(attributeName); + if (ObjectUtils.notEqual(ozgCloudUserIdInKeycloak, attributeValue)) { + userRepresentation.singleAttribute(attributeName, attributeValue); + tryUpdateUserResource(userResource, userRepresentation, attributeName); + } + } + + void tryUpdateUserResource(UserResource userResource, UserRepresentation userRepresentation, String attributeName) { + try { + userResource.update(new OlderUserRepresentation(userRepresentation)); + } catch (BadRequestException e) { + LOG.warn("Could not update user attribute {} in Keycloak.", attributeName, e); + } + } } \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakProvider.java b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakProvider.java similarity index 90% rename from user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakProvider.java rename to user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakProvider.java index 4f5a8d84d2cbb61cfbaba1df8bc2e26aca1a634b..d5351d37fe3b9023550d9c6c9785afd943d9413c 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakProvider.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,10 +21,10 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.keycloak; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.keycloak.admin.client.Keycloak; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/UserIdResource.java b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteService.java similarity index 52% rename from user-manager-server/src/main/java/de/itvsh/kop/user/UserIdResource.java rename to user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteService.java index 7b63864025ccfe0fc3153ca5c8ca2756e060937d..d95681f901bed9e4d5635f63f9a9605b811c3125 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/UserIdResource.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,28 +21,34 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user.keycloak; -import javax.annotation.security.PermitAll; -import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; +import java.util.Optional; +import java.util.stream.Stream; -import de.itvsh.kop.common.logging.KopLogging; +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.User; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +@OzgCloudLogging +public class KeycloakUserRemoteService { + + static final String ATTRIBUTE_NAME_OZG_CLOUD_USER_ID = "ozgCloudUserId"; -@KopLogging -@Path(UserIdResource.PATH_MIGRATION) -public class UserIdResource { - static final String PATH_MIGRATION = "/migration/user"; // NOSONAR @Inject - UserService userService; + KeycloakApiService apiService; - @GET - @Path("/{id}") - @PermitAll - public String findByExternalId(@PathParam(value = "id") String id) { - return userService.findByExternalId(id).getId().toHexString(); + public Stream<User> getAllUsers() { + return apiService.findAllUser(); } -} + public void updateOzgCloudUserId(User user) { + apiService.updateAttribute(user.getKeycloakUserId(), ATTRIBUTE_NAME_OZG_CLOUD_USER_ID, user.getId().toString()); + } + + public Optional<User> findUserById(String id) { + return apiService.findUserById(id); + } +} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/OlderUserRepresentation.java b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/OlderUserRepresentation.java new file mode 100644 index 0000000000000000000000000000000000000000..15d9ff1ae33e05cf5fe83c66bf6bd5b4bba99660 --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/keycloak/OlderUserRepresentation.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.keycloak; + +import org.keycloak.representations.idm.UserProfileMetadata; +import org.keycloak.representations.idm.UserRepresentation; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * This is a user representation which works with currently used Keycloak version 20.0.3 Because of Quarkus upgrade to 3.5.0 the keycloak admin client + * was updated to 22.0.5. The reason for that is the new resteasy client based on Jakarata EE 10 (jakarta.ws.rs-api). Keycloak admin client 20 .0.3 is + * based on Jersey (javax.ws.rs-api). What we do here is simple ignoring one field added in the newer version of Keycloak in order for entity to be + * processable by the older version. Once Keycloak will be upgraded we can remove this class. + * + * The workaround was discussed with Quarkus team https://github.com/quarkusio/quarkus/discussions/36766 + */ +class OlderUserRepresentation extends UserRepresentation { + + @JsonIgnore + private UserProfileMetadata userProfileMetadata; + + public OlderUserRepresentation(UserRepresentation origin) { + setAttributes(origin.getAttributes()); + setClientRoles(origin.getClientRoles()); + setEmail(origin.getEmail()); + setId(origin.getId()); + setCreatedTimestamp(origin.getCreatedTimestamp()); + setFirstName(origin.getFirstName()); + setLastName(origin.getLastName()); + setUsername(origin.getUsername()); + setAccess(origin.getAccess()); + setClientConsents(origin.getClientConsents()); + setCredentials(origin.getCredentials()); + setDisableableCredentialTypes(origin.getDisableableCredentialTypes()); + setEmailVerified(origin.isEmailVerified()); + setEnabled(origin.isEnabled()); + setFederatedIdentities(origin.getFederatedIdentities()); + setFederationLink(origin.getFederationLink()); + setGroups(origin.getGroups()); + setNotBefore(origin.getNotBefore()); + setOrigin(origin.getOrigin()); + setRealmRoles(origin.getRealmRoles()); + setRequiredActions(origin.getRequiredActions()); + setSelf(origin.getSelf()); + setServiceAccountClientId(origin.getServiceAccountClientId()); + setSocialLinks(origin.getSocialLinks()); + setTotp(origin.isEmailVerified()); + } +} diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitGrpcService.java b/user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitGrpcService.java new file mode 100644 index 0000000000000000000000000000000000000000..3e91082af03d41199ee9618960a770ee5fd7d64d --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitGrpcService.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.organisationseinheit; + +import java.util.Collection; + +import jakarta.inject.Inject; + +import de.ozgcloud.user.grpc.organisationseinheit.GrpcGetSupportedOrganisationsEinheitenResponse; +import de.ozgcloud.user.grpc.organisationseinheit.OrganisationsEinheitServiceGrpc.OrganisationsEinheitServiceImplBase; +import io.grpc.stub.StreamObserver; +import io.quarkus.grpc.GrpcService; + +@GrpcService +public class OrganisationsEinheitGrpcService extends OrganisationsEinheitServiceImplBase { + + @Inject + OrganisationsEinheitService organisationsEinheitService; + + @Override + public void getSupportedOrganisationsEinheiten(GrpcGetSupportedOrganisationsEinheitenRequest request, + StreamObserver<GrpcGetSupportedOrganisationsEinheitenResponse> responseObserver) { + var organisationsEinheitIds = organisationsEinheitService.findAllOrganisationsEinheitIds(); + var response = GrpcGetSupportedOrganisationsEinheitenResponse.newBuilder() + .addAllOrganisationseinheiten(mapToGrpc(organisationsEinheitIds)) + .build(); + + responseObserver.onNext(response); + responseObserver.onCompleted(); + } + + private Collection<GrpcOrganisationsEinheit> mapToGrpc(Collection<String> organisationsEinheitIds) { + return organisationsEinheitIds.stream().map(id -> GrpcOrganisationsEinheit.newBuilder().setOrganisationsEinheitId(id).build()).toList(); + } +} diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/UserNotFoundException.java b/user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepository.java similarity index 52% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/UserNotFoundException.java rename to user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepository.java index d869f78bebfad4fdd2475985416f239f5b3dc757..982f68c74b1660ca818e9851bacff59fb073225d 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/UserNotFoundException.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,20 +21,27 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.organisationseinheit; -public class UserNotFoundException extends TechnicalException { +import static de.ozgcloud.user.User.*; +import static org.apache.commons.collections4.IterableUtils.*; - private static final long serialVersionUID = 1L; +import java.util.Collection; - private static final String MESSAGE_WITH_EXTERNALID_TEMPLATE = "User not found for keycloak id %s"; - private static final String MESSAGE_WITH_ID_TEMPLATE = "User not found for id %s"; +import com.mongodb.client.model.Filters; - public UserNotFoundException(String id) { - super(String.format(MESSAGE_WITH_ID_TEMPLATE, id)); - } +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.User; +import io.quarkus.mongodb.panache.PanacheMongoRepository; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +@OzgCloudLogging +class OrganisationsEinheitRepository implements PanacheMongoRepository<User> { - public UserNotFoundException(String externalId, Throwable cause) { - super(String.format(MESSAGE_WITH_EXTERNALID_TEMPLATE, externalId), cause); + public Collection<String> findAllOrganisationsEinheitIds() { + return toList( + unmodifiableIterable( + mongoCollection().distinct(User.ORGANISATIONS_EINHEIT_IDS_FIELD, Filters.eq(DELETED_FIELD, false), String.class))); } } \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteService.java b/user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitService.java similarity index 67% rename from user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteService.java rename to user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitService.java index ccf0ea5b48467fdafd547ca7fe6d37bf175320be..bf6859e9791b59cbb8949926d44c392a541f105b 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteService.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,24 +21,20 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.organisationseinheit; -import java.util.stream.Stream; +import java.util.Collection; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; - -import de.itvsh.kop.common.logging.KopLogging; -import de.itvsh.kop.user.User; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; @ApplicationScoped -@KopLogging -public class KeycloakUserRemoteService { +class OrganisationsEinheitService { @Inject - KeycloakApiService apiService; + OrganisationsEinheitRepository repository; - public Stream<User> getAllUsers() { - return apiService.findAllUser(); + public Collection<String> findAllOrganisationsEinheitIds() { + return repository.findAllOrganisationsEinheitIds(); } -} \ No newline at end of file +} diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientGrpcService.java b/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientGrpcService.java similarity index 68% rename from user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientGrpcService.java rename to user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientGrpcService.java index b66c0bdac1aebc48cf10e7a4c25838bab79ec45b..11900da15c53eb7a2bc6c68022482687f7e32e7b 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientGrpcService.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientGrpcService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,17 +21,16 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.recipient; +package de.ozgcloud.user.recipient; import java.util.Collection; -import java.util.List; -import javax.inject.Inject; +import jakarta.inject.Inject; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.grpc.recipient.GrpcFindRecipientRequest; -import de.itvsh.kop.user.grpc.recipient.GrpcFindRecipientResponse; -import de.itvsh.kop.user.grpc.recipient.RecipientServiceGrpc.RecipientServiceImplBase; +import de.ozgcloud.user.User; +import de.ozgcloud.user.grpc.recipient.GrpcFindRecipientRequest; +import de.ozgcloud.user.grpc.recipient.GrpcFindRecipientResponse; +import de.ozgcloud.user.grpc.recipient.RecipientServiceGrpc.RecipientServiceImplBase; import io.grpc.stub.StreamObserver; import io.quarkus.grpc.GrpcService; @@ -45,14 +44,13 @@ public class RecipientGrpcService extends RecipientServiceImplBase { @Override public void findRecipientByOrganisationsEinheitId(GrpcFindRecipientRequest request, StreamObserver<GrpcFindRecipientResponse> responseObserver) { - List<User> recipients = recipientService.findRecipientByOrganisationsEinheitId(request.getOrganisationsEinheitId()); + var recipients = recipientService.findByOrganisationsEinheitId(request.getOrganisationsEinheitId()); - responseObserver.onNext(buildSearchReponse(recipients.stream().map(recipientMapper::toRecipient).toList())); + responseObserver.onNext(buildSearchReponse(recipients)); responseObserver.onCompleted(); } - private GrpcFindRecipientResponse buildSearchReponse(Collection<GrpcRecipient> recipients) { - return GrpcFindRecipientResponse.newBuilder().addAllRecipient(recipients).build(); - + private GrpcFindRecipientResponse buildSearchReponse(Collection<User> recipients) { + return GrpcFindRecipientResponse.newBuilder().addAllRecipient(recipients.stream().map(recipientMapper::toRecipient).toList()).build(); } -} +} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientMapper.java b/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientMapper.java similarity index 91% rename from user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientMapper.java rename to user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientMapper.java index 2274a16aa9373f133e14e65101e72dc9710da4da..5deaaec15d33a40a3e3604d3021542f71a8405fe 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientMapper.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientMapper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,14 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.recipient; +package de.ozgcloud.user.recipient; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.ReportingPolicy; -import de.itvsh.kop.user.User; +import de.ozgcloud.user.User; @Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, // unmappedSourcePolicy = ReportingPolicy.WARN, // diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientRepository.java b/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..7e9f21411be620963cf33a3f028ee7d8c3d006c5 --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientRepository.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.recipient; + +import static de.ozgcloud.user.User.*; + +import java.util.List; + +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.User; +import de.ozgcloud.user.settings.NotificationsSendFor; +import io.quarkus.mongodb.panache.PanacheMongoRepository; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +@OzgCloudLogging +class RecipientRepository implements PanacheMongoRepository<User> { + + private static final String SEARCH_RECIPIENT_QUERY = ORGANISATIONS_EINHEIT_IDS_FIELD + " = ?1 and " + NOTIFICATION_SEND_FOR_FIELD + " = ?2"; + + public List<User> findByOrganisationsEinheitId(String organisationseinheitId) { + return find(SEARCH_RECIPIENT_QUERY, organisationseinheitId, NotificationsSendFor.ALL.name()).list(); + } +} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientService.java b/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientService.java similarity index 72% rename from user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientService.java rename to user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientService.java index 922ee3eff17ec3302808852d6a0ac9c4d2d93e30..8f8f6c4cec79ac34697e74e1a271fda8f0599e01 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/recipient/RecipientService.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/recipient/RecipientService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,18 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.recipient; +package de.ozgcloud.user.recipient; import java.util.List; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; +import de.ozgcloud.user.common.errorhandling.FunctionalException; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import com.cronutils.utils.StringUtils; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.common.errorhandling.FunctionalException; +import de.ozgcloud.user.User; @ApplicationScoped class RecipientService { @@ -40,12 +39,12 @@ class RecipientService { static final String MISSING_ORGANISATIONS_EINHEIT_ID_MESSAGE_TEMPLATE = "OrganisationsEinheitId ('%s') can not be null or empty"; @Inject - UserService userService; + RecipientRepository repository; - public List<User> findRecipientByOrganisationsEinheitId(String organisationsEinheitId) { + public List<User> findByOrganisationsEinheitId(String organisationsEinheitId) { if (StringUtils.isEmpty(organisationsEinheitId)) { throw new FunctionalException(() -> String.format(MISSING_ORGANISATIONS_EINHEIT_ID_MESSAGE_TEMPLATE, organisationsEinheitId)); } - return userService.findRecipientByOrganisationsEinheitId(organisationsEinheitId); + return repository.findByOrganisationsEinheitId(organisationsEinheitId); } } \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/NotificationsSendFor.java b/user-manager-server/src/main/java/de/ozgcloud/user/settings/NotificationsSendFor.java similarity index 90% rename from user-manager-server/src/main/java/de/itvsh/kop/user/settings/NotificationsSendFor.java rename to user-manager-server/src/main/java/de/ozgcloud/user/settings/NotificationsSendFor.java index 81d73b17215a01e2faaeb6a975b1c8cbbefbe0e8..3b44ebe9863c128c3e5190c1ad7aa8a912e70bee 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/NotificationsSendFor.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/settings/NotificationsSendFor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; public enum NotificationsSendFor { ALL, NONE; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/SendNewVorgangNotification.java b/user-manager-server/src/main/java/de/ozgcloud/user/settings/SendNewVorgangNotification.java similarity index 90% rename from user-manager-server/src/main/java/de/itvsh/kop/user/settings/SendNewVorgangNotification.java rename to user-manager-server/src/main/java/de/ozgcloud/user/settings/SendNewVorgangNotification.java index 2f5d0b84aeb3c017956e4542fbd9200256d2ba5f..9b827c81e41f311ab1802f8f5f25c244eb3b71e3 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/SendNewVorgangNotification.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/settings/SendNewVorgangNotification.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; public enum SendNewVorgangNotification { NONE, ALL; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/Settings.java b/user-manager-server/src/main/java/de/ozgcloud/user/settings/Settings.java similarity index 92% rename from user-manager-server/src/main/java/de/itvsh/kop/user/settings/Settings.java rename to user-manager-server/src/main/java/de/ozgcloud/user/settings/Settings.java index 2ae73eb2f89c44f2115c3ba0b9a460c2962ca154..33924367b9345988ea65e6fb2d64bd60468e41f9 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/Settings.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/settings/Settings.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettings.java b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettings.java similarity index 92% rename from user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettings.java rename to user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettings.java index b9c12a6a7f043db47ab6305640c978fb75be3b4f..10a6afb5d5cb578072b22605528138bfb558a772 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettings.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettings.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsRepository.java b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsRepository.java similarity index 63% rename from user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsRepository.java rename to user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsRepository.java index 9491fc4dbff13d2d7192130c462c36d7b93e1eee..32b1eef265757298652a5830607562ed0e2babdb 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsRepository.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,24 +21,29 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; -import javax.enterprise.context.ApplicationScoped; +import java.util.Optional; -import de.itvsh.kop.common.logging.KopLogging; import org.bson.types.ObjectId; -import de.itvsh.kop.user.User; +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.User; import io.quarkus.mongodb.panache.PanacheMongoRepository; +import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped -@KopLogging +@OzgCloudLogging class UserSettingsRepository implements PanacheMongoRepository<User> { - public UserSettings updateByUserId(String userId, UserSettings userSettings) { - var savedUser = findById(new ObjectId(userId)); - savedUser.setUserSettings(userSettings); - update(savedUser); - return findById(savedUser.getId()).getUserSettings(); + public Optional<UserSettings> updateByUserId(String userId, UserSettings userSettings) { + return Optional.ofNullable(userId) + .filter(ObjectId::isValid) + .map(ObjectId::new) + .flatMap(id -> findByIdOptional(id).map(user -> { + user.setUserSettings(userSettings); + update(user); + return findById(user.getId()).getUserSettings(); + })); } } \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsResource.java b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsResource.java similarity index 77% rename from user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsResource.java rename to user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsResource.java index ec5d1ddd723cb0e8bf73b19f5fdf6af72c8c80fa..86d15c4dcc4cd74c51e3a7e57375bcfd6119217b 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsResource.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsResource.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,17 +21,19 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import java.util.Objects; -import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.PATCH; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; +import de.ozgcloud.user.common.errorhandling.AccessForbiddenException; +import de.ozgcloud.user.common.errorhandling.FunctionalException; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.PATCH; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.lang3.StringUtils; import org.eclipse.microprofile.config.inject.ConfigProperty; @@ -39,10 +41,8 @@ import org.eclipse.microprofile.jwt.JsonWebToken; import org.jboss.resteasy.reactive.ResponseStatus; import org.jboss.resteasy.reactive.common.util.RestMediaType; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.common.errorhandling.AccessForbiddenException; -import de.itvsh.kop.user.common.errorhandling.FunctionalException; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserService; import io.quarkus.hal.HalEntityWrapper; @Path(UserSettingsResource.USER_PATH) @@ -63,7 +63,7 @@ public class UserSettingsResource { @Inject UserSettingsResourceAssembler resourceAssembler; - @ConfigProperty(name = "kop.user-manager.url") + @ConfigProperty(name = "ozgcloud.user-manager.url") String userManagerUrl; @GET @@ -85,9 +85,10 @@ public class UserSettingsResource { if (Objects.isNull(userSettings)) { throw new FunctionalException(() -> "Request Body missing."); } - var updatedSettings = userSettingsService.updateByUserId(userSettings, userId); - return resourceAssembler.toResource(updatedSettings, userId, userManagerUrl); + return userSettingsService.updateByUserId(userSettings, userId) + .map(updatedSettings -> resourceAssembler.toResource(updatedSettings, userId, userManagerUrl)) + .orElseThrow(() -> new FunctionalException(() -> "Invalid user id")); } void checkUserAccess(String userId) { diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsResourceAssembler.java b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsResourceAssembler.java similarity index 84% rename from user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsResourceAssembler.java rename to user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsResourceAssembler.java index e2ec0d3c666c57997780409312b90ac323d8a321..5fcfab1c6a7f99a01b721bd8989b53f97d1b2704 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsResourceAssembler.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsResourceAssembler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,17 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.ws.rs.core.Link; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.Link; import org.apache.commons.lang3.StringUtils; -import de.itvsh.kop.user.UserRole; -import de.itvsh.kop.user.common.callcontext.CallContextUser; -import de.itvsh.kop.user.common.callcontext.CurrentCallContextUserService; +import de.ozgcloud.user.UserRole; +import de.ozgcloud.user.common.callcontext.CallContextUser; +import de.ozgcloud.user.common.callcontext.CurrentCallContextUserService; import io.quarkus.hal.HalEntityWrapper; @ApplicationScoped diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsService.java b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsService.java similarity index 76% rename from user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsService.java rename to user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsService.java index db61a750a743c31fb4605c0146ab1e5a8eb237a2..7a952ea67486fb35427337648bff2b0d86c46411 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/settings/UserSettingsService.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/settings/UserSettingsService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,17 +21,18 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import java.util.Objects; +import java.util.Optional; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; -import de.itvsh.kop.user.UserService; +import de.ozgcloud.user.UserService; @ApplicationScoped -public class UserSettingsService { +class UserSettingsService { @Inject UserService userService; @@ -39,14 +40,10 @@ public class UserSettingsService { @Inject UserSettingsRepository repository; - public UserSettings updateByUserId(UserSettings userSettings, String userId) { + public Optional<UserSettings> updateByUserId(UserSettings userSettings, String userId) { return repository.updateByUserId(userId, userSettings); } - public UserSettings findByUserId(String userId) { - return userService.getById(userId).getUserSettings(); - } - public UserSettings getByUserId(String userId) { var user = userService.getById(userId); diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/sync/SyncScheduler.java b/user-manager-server/src/main/java/de/ozgcloud/user/sync/SyncScheduler.java similarity index 66% rename from user-manager-server/src/main/java/de/itvsh/kop/user/sync/SyncScheduler.java rename to user-manager-server/src/main/java/de/ozgcloud/user/sync/SyncScheduler.java index b586b6dd21147a8913f6aa22cb1852b3984aa897..8bcea86f8fc0641432a78b46c45dfa208445aa36 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/sync/SyncScheduler.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/sync/SyncScheduler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,14 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.sync; +package de.ozgcloud.user.sync; import static io.quarkus.scheduler.Scheduled.ConcurrentExecution.*; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; +import de.ozgcloud.user.common.lock.LockService; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; -import de.itvsh.kop.user.common.lock.LockService; import io.quarkus.scheduler.Scheduled; import lombok.extern.log4j.Log4j2; @@ -41,15 +41,28 @@ public class SyncScheduler { @Inject LockService syncLockService; - @Scheduled(cron = "{kop.keycloak.sync.cron}", concurrentExecution = SKIP) + @Scheduled(every = "{ozgcloud.usersync.period}", concurrentExecution = SKIP) public void start() { if (syncLockService.isNotLocked()) { - syncService.sync(); + var lock = syncLockService.lockCollection(); + + sync(lock.getTimestamp()); } else { LOG.warn("UserManager: Database is locked, no sync happend."); if (syncLockService.isLockOlderThanADay()) { - LOG.warn("Database lock is older than a day"); + LOG.warn("Database lock is older than a day, removing it now"); + syncLockService.unlock(); } } } + + private void sync(long syncTimestamp) { + try { + syncService.sync(syncTimestamp); + } catch (Exception e) { + LOG.error("Error syncing UserManager database.", e); + } finally { + syncLockService.unlock(); + } + } } \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/sync/SyncService.java b/user-manager-server/src/main/java/de/ozgcloud/user/sync/SyncService.java similarity index 54% rename from user-manager-server/src/main/java/de/itvsh/kop/user/sync/SyncService.java rename to user-manager-server/src/main/java/de/ozgcloud/user/sync/SyncService.java index dba4dacc0e129af29e9c30953690094156ac045c..f0a0658f9e024830291be7f2b64d208334a7d544 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/sync/SyncService.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/sync/SyncService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,25 +21,21 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.sync; +package de.ozgcloud.user.sync; -import java.time.Instant; import java.util.function.Predicate; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; - -import de.itvsh.kop.common.logging.KopLogging; import org.apache.commons.collections4.CollectionUtils; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.common.lock.Lock; -import de.itvsh.kop.user.common.lock.LockService; -import de.itvsh.kop.user.keycloak.KeycloakUserRemoteService; +import de.ozgcloud.common.logging.OzgCloudLogging; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.keycloak.KeycloakUserRemoteService; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; @ApplicationScoped -@KopLogging +@OzgCloudLogging class SyncService { private final Predicate<User> HAS_ANY_ROLE = user -> CollectionUtils.isNotEmpty(user.getRoles());// NOSONAR @@ -48,29 +44,17 @@ class SyncService { UserService userService; @Inject KeycloakUserRemoteService keycloakService; - @Inject - LockService lockService; - public void sync() { - var now = Instant.now(); - lockService.lock(now); + void sync(long syncTimestamp) { + keycloakService.getAllUsers() + .filter(HAS_ANY_ROLE) + .forEach(user -> userService.saveAndSync(addLastSyncTimestamp(user, syncTimestamp))); - doSync(lockService.getByTimestamp(now)); + userService.markUnsyncedUsersAsDeleted(syncTimestamp); } - void doSync(Lock lock) { - try { - keycloakService.getAllUsers() - .filter(HAS_ANY_ROLE) - .forEach(user -> userService.save(addLastSyncTimestamp(user, lock))); - - userService.markUnsyncedUsersAsDeleted(lock.getTimestamp()); - } finally { - lockService.unlock(lock); - } + User addLastSyncTimestamp(User user, long syncTimestamp) { + return user.toBuilder().lastSyncTimestamp(syncTimestamp).build(); } - private User addLastSyncTimestamp(User user, Lock lock) { - return user.toBuilder().lastSyncTimestamp(lock.getTimestamp()).build(); - } } \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/userprofile/UserProfileGrpcService.java b/user-manager-server/src/main/java/de/ozgcloud/user/userprofile/UserProfileGrpcService.java new file mode 100644 index 0000000000000000000000000000000000000000..f23bb08a4fb669bb9c1d9be98f00eb839fa0600e --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/userprofile/UserProfileGrpcService.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.userprofile; + +import java.util.stream.Stream; + +import jakarta.inject.Inject; + +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.grpc.userprofile.UserProfileServiceGrpc.UserProfileServiceImplBase; +import io.grpc.stub.StreamObserver; +import io.quarkus.grpc.GrpcService; + +@GrpcService +public class UserProfileGrpcService extends UserProfileServiceImplBase { + + @Inject + UserService service; + + @Inject + UserProfileMapper mapper; + + @Override + public void getById(GrpcGetUserProfileRequest request, StreamObserver<GrpcGetUserProfileResponse> responseObserver) { + var userProfile = service.getById(request.getUserId()); + + responseObserver.onNext(buildResponse(userProfile)); + responseObserver.onCompleted(); + } + + private GrpcGetUserProfileResponse buildResponse(User userProfile) { + return GrpcGetUserProfileResponse.newBuilder().setUserProfile(mapper.mapTo(userProfile)).build(); + } + + @Override + public void getByExternalId(GrpcGetUserProfileRequest request, StreamObserver<GrpcGetUserProfileResponse> responseObserver) { + var userProfile = service.findByExternalId(request.getUserId()); + + responseObserver.onNext(buildResponse(userProfile)); + responseObserver.onCompleted(); + } + + @Override + public void findInactiveUserIds(GrpcFindInactiveUserIdsRequest request, StreamObserver<GrpcFindInactiveUserIdsResponse> responseObserver) { + var userIds = service.findAllInactiveUserIds(); + + responseObserver.onNext(buildGrpcGetInactiveUserIdsResponse(userIds)); + responseObserver.onCompleted(); + } + + GrpcFindInactiveUserIdsResponse buildGrpcGetInactiveUserIdsResponse(Stream<String> userIds) { + return GrpcFindInactiveUserIdsResponse.newBuilder() + .addAllUserProfileIds(userIds.map(id -> GrpcUserProfileId.newBuilder().setId(id).build())::iterator) + .build(); + } + + @Override + public void deleteInactiveUser(GrpcDeleteInactiveUserRequest request, StreamObserver<GrpcDeleteInactiveUserResponse> responseObserver) { + service.deleteInactive(request.getUserId()); + + responseObserver.onNext(GrpcDeleteInactiveUserResponse.newBuilder().build()); + responseObserver.onCompleted(); + } +} \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/userprofile/UserProfileMapper.java b/user-manager-server/src/main/java/de/ozgcloud/user/userprofile/UserProfileMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..1d66c684b5b71e491d9988362190fbee003ef9d9 --- /dev/null +++ b/user-manager-server/src/main/java/de/ozgcloud/user/userprofile/UserProfileMapper.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.userprofile; + +import org.bson.types.ObjectId; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.ReportingPolicy; + +import de.ozgcloud.user.User; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, // + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +interface UserProfileMapper { + + @Mapping(target = "emailBytes", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "firstNameBytes", ignore = true) + @Mapping(target = "idBytes", ignore = true) + @Mapping(target = "lastNameBytes", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + GrpcUserProfile mapTo(User userProfile); + + default String toString(ObjectId objectId) { + return objectId.toString(); + } +} \ No newline at end of file diff --git a/user-manager-server/src/main/resources/application-dev.yaml b/user-manager-server/src/main/resources/application-dev.yaml deleted file mode 100644 index 49dba13aa368d6d5e73808b82ac41a030fc2dac5..0000000000000000000000000000000000000000 --- a/user-manager-server/src/main/resources/application-dev.yaml +++ /dev/null @@ -1,29 +0,0 @@ -quarkus: - mongodb: - database: usermanager - oidc: - auth-server-url: https://sso.dev.ozg-sh.de/realms/sh-kiel-dev - http: - auth: - permission: - bearer: - paths: /api/userProfiles/*,/api/user/* - policy: permit - deny-api: - paths: /api/* - policy: deny - permit-migration: - enabled: false - paths: /api/migration/user/* - policy: permit - methods: GET -kop: - keycloak: - sync: - cron: "0 */10 * * * ?" - api: - realm: dev - organisations-einheit-id-key: organisationsEinheitId - ldap-id-key: LDAP_ID -keycloak: - url: https://sso.dev.ozg-sh.de \ No newline at end of file diff --git a/user-manager-server/src/main/resources/application-e2e.yaml b/user-manager-server/src/main/resources/application-e2e.yaml index cf5b3d2cf1235951c0a62a3b19cd3f3f8d3a1aea..8271e98165715c5c001c00c88febd06af92a8198 100644 --- a/user-manager-server/src/main/resources/application-e2e.yaml +++ b/user-manager-server/src/main/resources/application-e2e.yaml @@ -1,24 +1,28 @@ quarkus: oidc: - auth-server-url: https://sso.dev.ozg-sh.de/realms/sh-e2e-dev - client-id: sh-e2e-dev-goofy + auth-server-url: https://sso.dev.by.ozg-cloud.de/realms/by-e2e-local-dev + client-id: alfa http: cors: - origins: https://e2e.dev.ozg-sh.de,http://localhost:4300,http://127.0.0.1:4300 + origins: https://e2e.dev.by.ozg-cloud.de,http://localhost:4300,http://127.0.0.1:4300 mongodb: - connection-string: mongodb://ozg-mongodb:27017 + connection-string: mongodb://localhost:27017 database: test log: category: "io.quarkus.oidc.runtime.OidcProvider": level: TRACE min-level: TRACE - -kop: - keycloak: - api: - realm: sh-e2e-dev - client: sh-e2e-dev-goofy keycloak: - url: https://sso.dev.ozg-sh.de \ No newline at end of file + url: https://sso.dev.by.ozg-cloud.de + +ozgcloud: + keycloak: + api: + user: userManagerApiUser + password: S9UEMuLG9y9ev99 + realm: by-e2e-local-dev + client: alfa + usersync: + period: disabled \ No newline at end of file diff --git a/user-manager-server/src/main/resources/application-local.yaml b/user-manager-server/src/main/resources/application-local.yaml index e1640d828eb3f6bfcb7cb4be0a177c5d386cdbd2..ed73dcd875b0b22577007c10eea629a8a0dd9b86 100644 --- a/user-manager-server/src/main/resources/application-local.yaml +++ b/user-manager-server/src/main/resources/application-local.yaml @@ -1,10 +1,14 @@ quarkus: - port: 8082 mongodb: connection-string: mongodb://localhost:27017 database: usermanager -kop: + log: + console: + json: false + +ozgcloud: user-manager: url: http://localhost:9092 + keycloak: - url: http://localhost:8088 \ No newline at end of file + url: http://localhost:8088 \ No newline at end of file diff --git a/user-manager-server/src/main/resources/application-remotekc.yaml b/user-manager-server/src/main/resources/application-remotekc.yaml index 990d18d0af5c44794a9db8eb2b6aa7272ba8e342..7522b73325d3ae81f5ac7dce0d490d69392930e5 100644 --- a/user-manager-server/src/main/resources/application-remotekc.yaml +++ b/user-manager-server/src/main/resources/application-remotekc.yaml @@ -1,23 +1,28 @@ +keycloak: + url: https://sso.dev.by.ozg-cloud.de + realm: by-kiel-dev + quarkus: mongodb: database: usermanager oidc: - auth-server-url: https://sso.dev.ozg-sh.de/realms/sh-kiel-dev + auth-server-url: ${keycloak.url}/realms/${keycloak.realm} http: - port: 9091 + port: 9092 cors: ~: true origins: http://localhost:4300 -kop: + +ozgcloud: user-manager: - url: http://localhost:9091 + url: http://localhost:9092 keycloak: - sync: - cron: "* */10 * * * ?" api: - realm: sh-kiel-dev + user: userManagerApiUser + password: hlc_j1I1Ji0trC0 + realm: ${keycloak.realm} organisations-einheit-id-key: organisationseinheitId - client: sh-kiel-dev-goofy + client: alfa ldap-id-key: LDAP_ID -keycloak: - url: https://sso.dev.ozg-sh.de \ No newline at end of file + usersync: + period: disabled \ No newline at end of file diff --git a/user-manager-server/src/main/resources/application.yaml b/user-manager-server/src/main/resources/application.yaml index 495489831930fe0e4e71e43610591ad0655b1f24..2b4d4d46bbb8454c3a07367095923d2b59921254 100644 --- a/user-manager-server/src/main/resources/application.yaml +++ b/user-manager-server/src/main/resources/application.yaml @@ -1,42 +1,49 @@ +"%prod": + quarkus: + grpc: + server: + ssl: + certificate: /user-manager-tls-certificate/tls.crt + key: /user-manager-tls-certificate/tls.key + quarkus: - application: - name: kopusermanager - http: - cors: - ~: true - auth: - permission: - bearer: - paths: /api/userProfiles/*,/api/user/* - policy: authenticated - permit-migration: - paths: /api/migration/user/* - policy: permit - methods: GET - deny-api: - paths: /api/* - policy: deny - scheduler: - metrics: - enabled: true - log: - level: INFO - console: - json: - fields: - level: - field-name: log.level - mongodb: - database: usermanager + application: + name: ozgcloud_usermanager + http: + cors: + ~: true + auth: + permission: + bearer: + paths: /api/userProfiles/*,/api/user/* + policy: authenticated + permit-migration: + paths: /api/migration/user/* + policy: permit + methods: GET + deny-api: + paths: /api/* + policy: deny + scheduler: + metrics: + enabled: true + log: + level: INFO + mongodb: + database: usermanager + grpc: - server: - enable-reflection-service: true -kop: - keycloak: - api: - ldap-id-key: LDAP_ID - organisations-einheit-id-key: organisationseinheitId - realm: sh-kiel-dev - client: sh-kiel-dev-goofy - sync: - cron: "0 5 2 * * ?" \ No newline at end of file + server: + enable-reflection-service: true + +ozgcloud: + keycloak: + api: + ldap-id-key: LDAP_ID + organisations-einheit-id-key: organisationseinheitId + user: "-" + password: "-" + realm: by-kiel-dev + client: alfa + usersync: + period: "6h" \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserIdResourceITCase.java b/user-manager-server/src/test/java/de/itvsh/kop/user/UserIdResourceITCase.java deleted file mode 100644 index d25f94c4b937b1c597320dcd715700cca2b640d5..0000000000000000000000000000000000000000 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserIdResourceITCase.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.itvsh.kop.user; - -import static io.restassured.RestAssured.*; -import static org.hamcrest.CoreMatchers.*; -import static org.mockito.Mockito.when; - -import org.junit.jupiter.api.Test; - -import io.quarkus.test.junit.QuarkusTest; -import io.quarkus.test.junit.TestProfile; -import io.quarkus.test.junit.mockito.InjectMock; - -@QuarkusTest -@TestProfile(UserProfileResourceTestProfile.class) -class UserIdResourceITCase { - private static final String EXTERNAL_ID_PATH = UserIdResource.PATH_MIGRATION + "/{id}"; - - @InjectMock - UserService userService; - - @Test - void shouldGetInternalIdByExternalId() { - when(userService.findByExternalId(UserTestFactory.EXTERNAL_ID)).thenReturn(UserTestFactory.createWithId()); - - given() - .when().get(EXTERNAL_ID_PATH, UserTestFactory.EXTERNAL_ID) - .then() - .statusCode(200).body(is(UserTestFactory.ID.toHexString())); - } -} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserRepositoryITCase.java b/user-manager-server/src/test/java/de/itvsh/kop/user/UserRepositoryITCase.java deleted file mode 100644 index 0794cfe67288fd1d5f8281237a687b4b58320b1f..0000000000000000000000000000000000000000 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserRepositoryITCase.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.itvsh.kop.user; - -import static de.itvsh.kop.user.settings.NotificationsSendFor.*; -import static java.util.function.Predicate.not; -import static org.assertj.core.api.Assertions.*; - -import java.time.Instant; -import java.util.List; - -import javax.inject.Inject; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import com.thedeanda.lorem.LoremIpsum; - -import de.itvsh.kop.user.settings.UserSettings; -import io.quarkus.test.junit.QuarkusTest; - -@QuarkusTest -class UserRepositoryITCase { - - @Inject - UserRepository repository; - - private User user1; - private User user2; - - @BeforeEach - void init() { - repository.deleteAll(); - user1 = UserTestFactory.create(); - repository.persist(user1); - - user2 = UserTestFactory.createBuilder().externalId("unknown").build(); - repository.persist(user2); - user2 = user2.toBuilder().externalId(null).build(); - } - - @DisplayName("Update unsynced users") - @Nested - class TestUpdateUnsyncedUser { - - private long lastSyncTimestamp = Instant.now().toEpochMilli(); - - @BeforeEach - void init() { - repository.deleteAll(); - } - - @Test - void shouldMarkUnsyncedUserAsDeleted() { - repository.persist(createUserWithLastSyncTimestamp(lastSyncTimestamp - 1000)); - - repository.updateUnsyncedUsers(lastSyncTimestamp); - - assertThat(getFirstUser().isDeleted()).isTrue(); - } - - @Test - void shouldNotMarkUserIfSynced() { - repository.persist(createUserWithLastSyncTimestamp(lastSyncTimestamp)); - - repository.updateUnsyncedUsers(lastSyncTimestamp); - - assertThat(getFirstUser().isDeleted()).isFalse(); - } - - private User createUserWithLastSyncTimestamp(long lastSyncTimestamp) { - return UserTestFactory.createBuilder().lastSyncTimestamp(lastSyncTimestamp).build(); - } - - private User getFirstUser() { - var allUser = repository.findAll(); - return allUser.list().get(0); - } - } - - @DisplayName("Find Users") - @Nested - class TestFindUsers { - - private static final int LIMIT_5 = 5; - - @BeforeEach - void init() { - repository.deleteAll(); - repository.persist(UserTestFactory.createBuilder().email(LoremIpsum.getInstance().getEmail()).externalId("additional-id").build()); - user1 = UserTestFactory.create(); - repository.persist(user1); - } - - @Test - void shouldFindByLastName() { - var res = repository.findUsers(UserTestFactory.LAST_NAME, false, LIMIT_5); - - assertThat(res).isNotEmpty().hasSize(2); - } - - @Test - void shouldFindByFirstName() { - var res = repository.findUsers(UserTestFactory.FIRST_NAME, false, LIMIT_5); - - assertThat(res).isNotEmpty().hasSize(2); - } - - @Test - void shouldFindByUsername() { - var res = repository.findUsers(UserTestFactory.USER_NAME, false, LIMIT_5); - - assertThat(res).isNotEmpty().hasSize(2); - } - - @Test - void shouldFindByUsernamePart() { - var res = repository.findUsers(UserTestFactory.USER_NAME.substring(0, 4), false, LIMIT_5); - - assertThat(res).isNotEmpty().hasSize(2); - } - - @Test - void shouldFindByEmail() { - var res = repository.findUsers(UserTestFactory.EMAIL, false, LIMIT_5); - - assertThat(res).isNotEmpty().hasSize(1); - } - - @Test - void shouldNotFind() { - var res = repository.findUsers("xxx", false, 5); - assertThat(res).isEmpty(); - } - - @Test - void shouldFindCaseInsensitive() { - var res = repository.findUsers(UserTestFactory.LAST_NAME.toLowerCase(), false, LIMIT_5); - assertThat(res).isNotEmpty().hasSize(2); - } - - @Test - void shouldFindByExternalId() { - var res = repository.findByExternalId(user1.getExternalId()); - - assertThat(res).isPresent(); - assertThat(res.get().getExternalId()).isEqualTo(user1.getExternalId()); - } - - @Test - void shouldFindById() { - var res = repository.findById(user1.getId()); - - assertThat(res).isNotNull(); - assertThat(res.getId()).isEqualTo(user1.getId()); - } - - @Test - void shouldFindByEmailOnly() { - var res = repository.findByEmail(user1.getEmail()); - - assertThat(res).isPresent(); - assertThat(res.get().getExternalId()).isEqualTo(user1.getExternalId()); - } - - @Test - void shouldNotFindByEmptyEmail() { - var res = repository.findByEmail(null); - - assertThat(res).isEmpty(); - } - - @Test - void shouldFindDeletedUsers() { - User user1 = UserTestFactory.createBuilder().firstName("Max").deleted(true).build(); - User user2 = UserTestFactory.createBuilder().firstName("Maximilian").deleted(true).build(); - User user3 = UserTestFactory.createBuilder().firstName("Maximus").deleted(false).build(); - - repository.persist(user1); - repository.persist(user2); - repository.persist(user3); - - var foundUsers = repository.findUsers("Max", true, 10).toList(); - - assertThat(foundUsers).hasSize(2); - foundUsers.forEach(u -> assertThat(u.isDeleted()).isTrue()); - } - - @Test - void shouldFindNotDeletedUsers() { - User user1 = UserTestFactory.createBuilder().firstName("Max").deleted(true).build(); - User user2 = UserTestFactory.createBuilder().firstName("Maximilian").deleted(true).build(); - User user3 = UserTestFactory.createBuilder().firstName("Maximus").deleted(false).build(); - - repository.persist(user1); - repository.persist(user2); - repository.persist(user3); - - var foundUsers = repository.findUsers("Max", false, 10).toList(); - - foundUsers.forEach(u -> assertThat(u.isDeleted()).isFalse()); - } - - @Test - void shouldFindDeletedAndNotDeletedUsers() { - User user1 = UserTestFactory.createBuilder().firstName("Max").deleted(true).build(); - User user2 = UserTestFactory.createBuilder().firstName("Maximilian").deleted(true).build(); - User user3 = UserTestFactory.createBuilder().firstName("Maximus").deleted(false).build(); - - repository.persist(user1); - repository.persist(user2); - repository.persist(user3); - - var foundUsers = repository.findUsers("Max", 10).toList(); - - assertThat(foundUsers).hasSizeGreaterThan(2); - List<User> startWithMax = foundUsers.stream().filter(u -> u.getFirstName().startsWith("Max")).toList(); - assertThat(startWithMax.size()).isEqualTo(3); - assertThat(startWithMax.stream().filter(User::isDeleted).count()).isEqualTo(2); - assertThat(startWithMax.stream().filter(not(User::isDeleted)).count()).isEqualTo(1); - } - - @Test - void shouldFindByOrganisationeinheitIdAndNotificatinoActivated() { - var recipientUser = UserTestFactory.createBuilder().userSettings(new UserSettings(ALL)).build(); - var notRecipientUser = UserTestFactory.createBuilder().organisationsEinheitIds(List.of("a")).build(); - repository.persist(List.of(notRecipientUser, recipientUser)); - - var users = repository.findRecipientByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); - - assertThat(users).hasSize(1); - assertThat(users.get(0).getOrganisationsEinheitIds()).contains(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); - } - - @Test - void shouldUseLimit() { - repository.persist(UserTestFactory.create()); - - var res = repository.findUsers(UserTestFactory.LAST_NAME.toLowerCase(), false, 2); - assertThat(res).isNotEmpty().hasSize(2); - } - } - - @DisplayName("Test refreshing user") - @Nested - class TestRefresh { - @Test - void shouldRefreshByExternalId() { - var user = repository.refresh(user1.toBuilder().id(null).build()); - - assertThat(user).isNotNull().hasFieldOrPropertyWithValue("id", user1.getId()); - } - - @Test - void shouldRefreshById() { - var user = repository.refresh(user1); - - assertThat(user).isNotNull().hasFieldOrPropertyWithValue("id", user1.getId()); - } - } - - @DisplayName("Test for empty result list ") - @Nested - class TestReturnEmptyList { - @Test - void whenIdNotFound() { - var recipientUser = UserTestFactory.createBuilder().userSettings(new UserSettings(ALL)).build(); - repository.persist(recipientUser); - var users = repository.findRecipientByOrganisationsEinheitId("some_id"); - assertThat(users).isEmpty(); - } - - @Test - void whenNotificationDeactivated() { - - var users = repository.findRecipientByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); - assertThat(users).isEmpty(); - } - - @Test - void shouldReturnEmptyListNotificationDeactivated() { - var users = repository.findRecipientByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); - - assertThat(users).isEmpty(); - } - } -} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserServiceTest.java b/user-manager-server/src/test/java/de/itvsh/kop/user/UserServiceTest.java deleted file mode 100644 index 7bf81cd55b2ab07e26b19473a2fd192a87c41a8e..0000000000000000000000000000000000000000 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserServiceTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.itvsh.kop.user; - -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import java.time.Instant; -import java.util.Optional; -import java.util.UUID; - -import org.apache.commons.lang3.StringUtils; -import org.bson.types.ObjectId; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import de.itvsh.kop.user.keycloak.KeycloakUserRemoteService; - -class UserServiceTest { - - @InjectMocks - UserService service; - @Mock - UserRepository repository; - @Mock - KeycloakUserRemoteService keycloakRemoteService; - - @DisplayName("Find by id") - @Nested - class TestFindById { - - @Test - void shouldFindByIdOnInternalId() { - when(repository.findById(anyString())).thenReturn(Optional.of(UserTestFactory.create())); - - service.getById("xxx"); - - verify(repository).findById(anyString()); - } - - @Test - void shouldFindByExternalIdOnUUID() { - when(repository.findByExternalId(any())).thenReturn(Optional.of(UserTestFactory.create())); - - service.getById(UUID.randomUUID().toString()); - - verify(repository).findByExternalId(anyString()); - } - } - - @DisplayName("Save") - @Nested - class TestSave { - - private final User user = UserTestFactory.create(); - - @BeforeEach - void init() { - when(repository.refresh(any())).thenReturn(UserTestFactory.createWithId()); - } - - @Test - void shouldCallUpdate() { - when(repository.findByExternalId(any())).thenReturn(Optional.of(user)); - - service.save(user.toBuilder().firstName("Other").build()); - - verify(repository).updateUser(any(User.class)); - } - - @Test - void shouldCallPersist() { - service.save(user); - - verify(repository).persist(any(User.class)); - } - - @Test - void shouldCallFindByExternalId() { - service.save(user); - - verify(repository, atLeastOnce()).findByExternalId(any()); - } - - @Test - void shouldCallFindByEmail() { - service.save(UserTestFactory.createBuilder().externalId(null).build()); - - verify(repository, atLeastOnce()).findByEmail(anyString()); - } - - @Test - void shouldNotCallFindByEmailOnEmptyEMail() { - service.save(UserTestFactory.createBuilder().id(new ObjectId()).externalId(null).email(StringUtils.EMPTY).build()); - - verify(repository, never()).findByEmail(anyString()); - } - } - - @DisplayName("Mark unsynced users as deleted") - @Nested - class TestMarkUnsyncedUserAsDeleted { - - @Test - void shouldCallRepository() { - var lastSyncTimestamp = Instant.now().toEpochMilli(); - - service.markUnsyncedUsersAsDeleted(lastSyncTimestamp); - - verify(repository).updateUnsyncedUsers(lastSyncTimestamp); - } - } - - @DisplayName("Find recipient by organisationsEinheitId") - @Nested - class TestFindRecipientByOrganisationsEinheitId { - - @Test - void shouldCallRepository() { - service.findRecipientByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); - - verify(repository).findRecipientByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); - } - } - - @DisplayName("Search users") - @Nested - class TestUserSearch { - - private static final String SEARCH_QUERY = "aaa"; - private static final int LIMIT = 50; - - @Test - void shouldFindUsers() { - service.findUsers(SEARCH_QUERY, LIMIT); - - verify(repository).findUsers(SEARCH_QUERY, LIMIT); - } - - @Test - void shouldFindActiveUsers() { - service.findActiveUsers(SEARCH_QUERY, LIMIT); - - verify(repository).findUsers(SEARCH_QUERY, false, LIMIT); - } - - @Test - void shouldFindInactiveUsers() { - service.findInactiveUsers(SEARCH_QUERY, LIMIT); - - verify(repository).findUsers(SEARCH_QUERY, true, LIMIT); - } - } -} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/reflection/SaferReflection.java b/user-manager-server/src/test/java/de/itvsh/kop/user/common/reflection/SaferReflection.java deleted file mode 100644 index f9fb8aeb06c459e191e8c3409a25fcf11d856190..0000000000000000000000000000000000000000 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/reflection/SaferReflection.java +++ /dev/null @@ -1,28 +0,0 @@ -package de.itvsh.kop.user.common.reflection; - -import static java.lang.String.*; -import static org.junit.jupiter.api.Assertions.*; - -import org.springframework.util.ReflectionUtils; - -/** - * Safer in this case means "with error handling". - */ -public class SaferReflection { - - private SaferReflection() { - // noop - } - - public static <T, V> void setField(String fieldName, T target, V value) { - var field = ReflectionUtils.findField(target.getClass(), fieldName); - if (field == null) { - fail(format( - "Can't mock because of reflection error. Unknown field: %s. Check in code if the field name in class fits to the string passed" - + " to reflection call.", - fieldName)); - } - field.setAccessible(true); - ReflectionUtils.setField(field, target, value); - } -} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakApiServiceTest.java b/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakApiServiceTest.java deleted file mode 100644 index 4003592a8dd8560feb97c96ae1455fff115ea184..0000000000000000000000000000000000000000 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakApiServiceTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.itvsh.kop.user.keycloak; - -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import java.util.stream.Stream; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.keycloak.admin.client.resource.RealmResource; -import org.keycloak.admin.client.resource.UserResource; -import org.keycloak.admin.client.resource.UsersResource; -import org.keycloak.representations.idm.UserRepresentation; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; - -import de.itvsh.kop.user.RemoteUserIterator; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserRepresentationTestFactory; -import de.itvsh.kop.user.UserResourceMapper; -import de.itvsh.kop.user.UserTestFactory; - -class KeycloakApiServiceTest { - - @Spy - @InjectMocks - private KeycloakApiService service; - @Mock - private RealmResource realmResource; - @Mock - private UserResourceMapper userResourceMapper; - @Mock - private KeycloakApiProperties properties; - - @Mock - private UserResource userResource; - - @DisplayName("Find all user") - @Nested - class TestFindAllUser { - - @Mock - private UsersResource usersResource; - - @Mock - private RemoteUserIterator iterator; - - private User user = UserTestFactory.create(); - private UserRepresentation userRepresentation = UserRepresentationTestFactory.create(); - private Stream<UserRepresentation> userStream = Stream.of(userRepresentation); - - @BeforeEach - void init() { - doReturn(userStream).when(service).getAllUserRepresentation(); - } - - @Test - void shouldCreateIteratorWithRealmResource() { - service.findAllUser(); - - verify(service).getAllUserRepresentation(); - } - - @Test - void shouldCallMapper() { - when(userResourceMapper.toKopUser(any(UserResource.class))).thenReturn(user); - when(realmResource.users()).thenReturn(usersResource); - when(usersResource.get(anyString())).thenReturn(userResource); - - service.findAllUser().toList(); - - verify(userResourceMapper).toKopUser(any(UserResource.class)); - } - } -} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/UserProfileGrpcServiceTest.java b/user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/UserProfileGrpcServiceTest.java deleted file mode 100644 index 3cc9644e2f164bef1d39738ee38742ca81458d63..0000000000000000000000000000000000000000 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/UserProfileGrpcServiceTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.itvsh.kop.user.userprofile; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import java.util.UUID; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.UserTestFactory; -import de.itvsh.kop.user.grpc.userprofile.GrpcGetUserProfileRequest; -import de.itvsh.kop.user.grpc.userprofile.GrpcGetUserProfileResponse; -import io.grpc.stub.StreamObserver; -import lombok.SneakyThrows; - -class UserProfileGrpcServiceTest { - - @InjectMocks - UserProfileGrpcService grpcService; - @Mock - UserService userService; - @Mock - UserProfileMapper mapper; - - @DisplayName("Get userprofile by id") - @Nested - class TestGetUserProfileById { - - @Mock - private StreamObserver<GrpcGetUserProfileResponse> streamObserver; - @Captor - private ArgumentCaptor<GrpcGetUserProfileResponse> responseCaptor; - - private final User userProfile = UserTestFactory.create(); - private final String userId = UUID.randomUUID().toString(); - private final GrpcGetUserProfileRequest request = GrpcGetUserProfileRequest.newBuilder().setUserId(userId).build(); - private final GrpcUserProfile grpcUserProfile = GrpcUserProfileTestFactory.create(); - - @BeforeEach - void init() { - when(userService.getById(anyString())).thenReturn(userProfile); - when(mapper.mapTo(any())).thenReturn(grpcUserProfile); - } - - @Test - void shouldCallService() { - callGetById(); - - verify(userService).getById(userId); - } - - @Test - void shouldMapUserProfile() { - callGetById(); - - verify(mapper).mapTo(userProfile); - } - - @Test - void shouldCallOnNext() { - callGetById(); - - verify(streamObserver).onNext(any(GrpcGetUserProfileResponse.class)); - } - - @Test - void shouldCallOnCompleted() { - callGetById(); - - verify(streamObserver).onCompleted(); - } - - @Test - void shouldReturnUserProfile() { - callGetById(); - - verify(streamObserver).onNext(responseCaptor.capture()); - assertThat(responseCaptor.getValue().getUserProfile().getFirstName()).isEqualTo(UserTestFactory.FIRST_NAME); - assertThat(responseCaptor.getValue().getUserProfile().getLastName()).isEqualTo(UserTestFactory.LAST_NAME); - } - - @SneakyThrows - private void callGetById() { - grpcService.getById(request, streamObserver); - } - } -} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/GroupRepresentationTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/GroupRepresentationTestFactory.java similarity index 94% rename from user-manager-server/src/test/java/de/itvsh/kop/user/GroupRepresentationTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/GroupRepresentationTestFactory.java index b6555495e52c1615c886ef7efc1b5297aea435c5..ced7e7384a433ae4fa84d15a84d37b940fc62c2b 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/GroupRepresentationTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/GroupRepresentationTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.List; import java.util.Map; diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/RoleHierarchyTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/RoleHierarchyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..16f3680f45b2814012ec4fad05c9e73243f867a8 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/RoleHierarchyTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.ArrayDeque; +import java.util.Deque; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Spy; + +class RoleHierarchyTest { + + private final RoleHierarchy subRole = RoleHierarchy.builder().roleName(UserRole.VERWALTUNG_USER).build(); + @Spy + private final RoleHierarchy root = RoleHierarchy.builder() + .roleName(UserRole.VERWALTUNG_LOESCHEN) + .subRole(subRole) + .build(); + + @Nested + class TestGetFlattenedHierarchy { + + @Test + void shouldCollectSubRoles() { + root.getFlattenedHierarchy(UserRole.VERWALTUNG_LOESCHEN); + + verify(root).collectSubRoles(eq(root), eq(UserRole.VERWALTUNG_LOESCHEN), any(Deque.class)); + } + } + + @Nested + class TestCollectSubRoles { + + private static final String UNKNOWN_ROLE = "unknown"; + + private final Deque<String> collectedSubRoles = new ArrayDeque<>(); + + @Test + void shouldAddLast() { + root.collectSubRoles(root, UserRole.VERWALTUNG_LOESCHEN, collectedSubRoles); + + assertThat(collectedSubRoles).containsExactly(UserRole.VERWALTUNG_LOESCHEN); + } + + @Test + void shouldReturnTrue() { + var result = root.collectSubRoles(root, UserRole.VERWALTUNG_LOESCHEN, collectedSubRoles); + + assertThat(result).isTrue(); + } + + @Test + void shouldReturnFalse() { + var result = root.collectSubRoles(root, UNKNOWN_ROLE, collectedSubRoles); + + assertThat(result).isFalse(); + } + + @Test + void shouldCollectSubRoles() { + root.collectSubRoles(root, UserRole.VERWALTUNG_USER, collectedSubRoles); + + verify(root).collectSubRoles(subRole, UserRole.VERWALTUNG_USER, collectedSubRoles); + } + + @Test + void shouldReturnTrueOnExistingRole() { + var result = root.collectSubRoles(root, UserRole.VERWALTUNG_USER, collectedSubRoles); + + assertThat(result).isTrue(); + } + + @Test + void shouldAddLastSubRole() { + root.collectSubRoles(root, UserRole.VERWALTUNG_USER, collectedSubRoles); + + assertThat(collectedSubRoles).containsExactly(UserRole.VERWALTUNG_LOESCHEN, UserRole.VERWALTUNG_USER); + } + + @Test + void shouldRemoveLast() { + root.collectSubRoles(root, UserRole.VERWALTUNG_LOESCHEN, collectedSubRoles); + + assertThat(collectedSubRoles).containsExactly(UserRole.VERWALTUNG_LOESCHEN); + } + + } + +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/TestDatabaseUtils.java b/user-manager-server/src/test/java/de/ozgcloud/user/TestDatabaseUtils.java similarity index 92% rename from user-manager-server/src/test/java/de/itvsh/kop/user/TestDatabaseUtils.java rename to user-manager-server/src/test/java/de/ozgcloud/user/TestDatabaseUtils.java index 81646a3905a273de123db7b37a647181c65d1c4a..69e3ec927bb1d3e29e23e336c64c15961083bb31 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/TestDatabaseUtils.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/TestDatabaseUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceAssemblerTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceAssemblerTest.java similarity index 80% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceAssemblerTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceAssemblerTest.java index d5d0be062c845c95ece65669dc1d1603e1b46d9f..87cec726cd89cfc1a3847e7a7497675ba2ea8e39 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceAssemblerTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceAssemblerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,9 +21,8 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; -import static de.itvsh.kop.user.UserTestFactory.*; import static org.assertj.core.api.Assertions.*; import java.util.List; @@ -35,7 +34,7 @@ import org.mockito.Spy; import com.thedeanda.lorem.LoremIpsum; -import de.itvsh.kop.user.settings.UserSettingsResource; +import de.ozgcloud.user.settings.UserSettingsResource; class UserProfileResourceAssemblerTest { @@ -48,33 +47,31 @@ class UserProfileResourceAssemblerTest { @Nested class TestToUserProfileResource { - private static final User USER = createWithId(); - @Test void shouldAddSelfLink() { - var res = assembler.toUserProfileResource(USER, USER_MANAGER_URL); + var res = assembler.toUserProfileResource(UserTestFactory.create(), USER_MANAGER_URL); assertThat(res.getLinks().get(UserProfileResourceAssembler.REL_SELF)) .isNotNull() .hasFieldOrPropertyWithValue("href", - USER_MANAGER_URL + UserProfileResource.USER_PROFILE_RESOURCE_PATH_TEMPLATE.replace("{id}", ID.toHexString())); + USER_MANAGER_URL + UserProfileResource.USER_PROFILE_RESOURCE_PATH_TEMPLATE.replace("{id}", UserTestFactory.ID_STR)); } @Test void shouldAddSettingsLink() { - var res = assembler.toUserProfileResource(USER, USER_MANAGER_URL); + var res = assembler.toUserProfileResource(UserTestFactory.create(), USER_MANAGER_URL); assertThat(res.getLinks().get(UserProfileResourceAssembler.REL_SETTINGS)) .isNotNull() .hasFieldOrPropertyWithValue("href", - USER_MANAGER_URL + UserSettingsResource.SETTINGS_LINK_PATTERN.replace("{id}", ID.toHexString())); + USER_MANAGER_URL + UserSettingsResource.SETTINGS_LINK_PATTERN.replace("{id}", UserTestFactory.ID_STR)); } } @DisplayName("To Userprofile Resource List") @Nested class TestToUserProfileResourceList { - private static final List<User> USERS = List.of(createWithId(), createWithId()); + private static final List<User> USERS = List.of(UserTestFactory.create(), UserTestFactory.create()); @Test void shouldAddSelfLink() { diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceITCase.java similarity index 77% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceITCase.java index e4b9d4d4d6199522de801f017acd08f41e332b9d..560b211f8de3b5aaa3811146f3dadec78e0fc633 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,13 +21,12 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; -import static de.itvsh.kop.user.UserTestFactory.*; +import static de.ozgcloud.user.UserTestFactory.*; import static io.restassured.RestAssured.*; import static org.hamcrest.CoreMatchers.*; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; import java.util.stream.Stream; @@ -38,32 +37,35 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import de.itvsh.kop.user.common.errorhandling.ApiErrorUtil; -import de.itvsh.kop.user.common.errorhandling.ResourceNotFoundException; -import de.itvsh.kop.user.settings.UserSettingsResource; +import de.ozgcloud.user.common.errorhandling.ApiErrorUtil; +import de.ozgcloud.user.common.errorhandling.ResourceNotFoundException; +import de.ozgcloud.user.settings.UserSettingsResource; +import io.quarkus.test.InjectMock; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; -import io.quarkus.test.junit.mockito.InjectMock; @QuarkusTest @TestProfile(UserProfileResourceTestProfile.class) class UserProfileResourceITCase { - private static final String HTTP_LOCALHOST = "http://localhost:9092"; + private static final String HTTP_LOCALHOST = "http://localhost:9092"; private static final String SEARCH_PATH = UserProfileResource.USERS_PATH + "/?" + UserProfileResource.PARAM_SEARCH_BY + "="; @InjectMock UserService userService; - private String settingsUrlWithUserId = HTTP_LOCALHOST + UserSettingsResource.SETTINGS_LINK_PATTERN.replace("{id}", ID.toHexString()); - private String urlWithUserId = HTTP_LOCALHOST + UserProfileResource.USER_PROFILE_RESOURCE_PATH_TEMPLATE.replace("{id}", ID.toHexString()); + private String settingsUrlWithUserId = HTTP_LOCALHOST + + UserSettingsResource.SETTINGS_LINK_PATTERN.replace("{id}", UserTestFactory.ID_STR); + private String urlWithUserId = HTTP_LOCALHOST + + UserProfileResource.USER_PROFILE_RESOURCE_PATH_TEMPLATE.replace("{id}", UserTestFactory.ID_STR); @DisplayName("Test get user by id") @Nested class TestGetUser { + @BeforeEach void init() { - when(userService.getById(any())).thenReturn(createWithId()); + when(userService.getById(any())).thenReturn(UserTestFactory.create()); } @Test @@ -71,7 +73,7 @@ class UserProfileResourceITCase { given() .when() .accept(RestMediaType.APPLICATION_HAL_JSON) - .get(UserProfileResource.USERS_PATH + "/{id}", ID.toHexString()) + .get(UserProfileResource.USERS_PATH + "/{id}", UserTestFactory.ID_STR) .then().statusCode(200) .body("_links.self.href", equalTo(urlWithUserId)); } @@ -81,7 +83,7 @@ class UserProfileResourceITCase { given() .when() .accept(RestMediaType.APPLICATION_HAL_JSON) - .get(UserProfileResource.USERS_PATH + "/{id}", ID.toHexString()) + .get(UserProfileResource.USERS_PATH + "/{id}", UserTestFactory.ID_STR) .then().statusCode(200) .body("_links.settings.href", equalTo(settingsUrlWithUserId)); } @@ -97,7 +99,7 @@ class UserProfileResourceITCase { response.then() .statusCode(404) - .body("issues[0].messageCode", equalTo(ApiErrorUtil.RESOURCE_NOT_FOUNT_MESSAGE_CODE)) + .body("issues[0].messageCode", equalTo(ApiErrorUtil.RESOURCE_NOT_FOUND_MESSAGE_CODE)) .body("issues[0].message", equalTo("Functional error: Resource 'User' with id 'not_found' not found. (ExceptionId: " + exception.getExceptionId() + ")")) @@ -105,23 +107,24 @@ class UserProfileResourceITCase { } } - @DisplayName("Test search user") @Nested - class TestSearch { + class TestFindUsers { + + private static final String SEARCH_BY = "no_one"; @BeforeEach void init() { - when(userService.findUsers(any(), anyInt())).thenReturn(Stream.of(createWithId())); + when(userService.findUsers(any())).thenReturn(Stream.of(UserTestFactory.create())); } @Test void shouldGetEmptyList() { - when(userService.findUsers(eq("no_one"), anyInt())).thenReturn(Stream.empty()); + when(userService.findUsers(any())).thenReturn(Stream.empty()); given() .when() .accept(RestMediaType.APPLICATION_HAL_JSON) - .get(SEARCH_PATH + "no_one") + .get(SEARCH_PATH + SEARCH_BY) .then() .statusCode(200) .body(is("{\"_embedded\":{\"userProfileList\":[]},\"_links\":{\"self\":{\"href\":\"http://localhost:9092/api/userProfiles\"}}}")); @@ -151,7 +154,7 @@ class UserProfileResourceITCase { @Test void shouldGetOneDeletedUser() { var user = UserTestFactory.createBuilder().deleted(true).build(); - when(userService.findInactiveUsers(anyString(), anyInt())).thenReturn(Stream.of(user)); + when(userService.findInactiveUsers(any())).thenReturn(Stream.of(user)); given() .when() @@ -166,7 +169,7 @@ class UserProfileResourceITCase { @Test void shouldGetOneNotDeletedUser() { var user = UserTestFactory.createBuilder().deleted(false).build(); - when(userService.findActiveUsers(anyString(), anyInt())).thenReturn(Stream.of(user)); + when(userService.findActiveUsers(any())).thenReturn(Stream.of(user)); given() .when() @@ -180,9 +183,9 @@ class UserProfileResourceITCase { @Test void shouldGetDeletedAndNotDeletedUsers() { - User user1 = UserTestFactory.createBuilder().deleted(false).build(); - User user2 = UserTestFactory.createBuilder().deleted(true).build(); - when(userService.findUsers(anyString(), anyInt())).thenReturn(Stream.of(user1, user2)); + var user1 = UserTestFactory.createBuilder().deleted(false).build(); + var user2 = UserTestFactory.createBuilder().deleted(true).build(); + when(userService.findUsers(any())).thenReturn(Stream.of(user1, user2)); given() .when() @@ -202,7 +205,7 @@ class UserProfileResourceITCase { @BeforeEach void init() { - when(userService.findUsers(any(), anyInt())).thenReturn(Stream.of(createWithId())); + when(userService.findUsers(any())).thenReturn(Stream.of(UserTestFactory.create())); } @Test diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceTest.java similarity index 51% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceTest.java index a725a41d453ccaccbb9ed7e2ff0bdb2b9aa30991..3ce08254ddd541c9439881fd0860947af324fe6f 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,46 +21,44 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; +import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.util.List; +import java.util.Optional; import java.util.UUID; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import com.thedeanda.lorem.LoremIpsum; -import de.itvsh.kop.user.common.reflection.SaferReflection; - class UserProfileResourceTest { private static final String USER_MANAGER_URL = LoremIpsum.getInstance().getUrl(); @InjectMocks private UserProfileResource resource; + @Mock private UserService userService; + @Mock private UserProfileResourceAssembler resourceAssembler; @BeforeEach void init() { - mockUserManagerUrl(); - } - - private void mockUserManagerUrl() { - SaferReflection.setField("userManagerUrl", resource, USER_MANAGER_URL); + resource.userManagerUrl = USER_MANAGER_URL; } - @DisplayName("Find by id") @Nested class TestFindById { @@ -87,42 +85,65 @@ class UserProfileResourceTest { } } - @DisplayName("Find by query") @Nested - class TestFindByQuery { + class TestFindUsers { private static final String SEARCH_QUERY = "abc"; - private final List<User> users = List.of(UserTestFactory.create()); - - @Test - void shouldSearchNotDeletedUserProfiles() { - when(userService.findActiveUsers(anyString(), anyInt())).thenReturn(users.stream()); + private static final List<User> users = List.of(UserTestFactory.create()); + private static Optional<Boolean> EMPTY_PARAM_DELETED = Optional.empty(); + private static Optional<Boolean> DELETED_USER_PROFILES = Optional.of(true); + private static Optional<Boolean> NOT_DELETED_USER_PROFILES = Optional.of(false); + private static Optional<String> EMPTY_PARAM_ORGANISATIONSEINHEIT_ID = Optional.empty(); - resource.findUsers(SEARCH_QUERY, false); + @Captor + private ArgumentCaptor<FindUserProfilesQuery> query; - verify(userService).findActiveUsers(SEARCH_QUERY, UserProfileResource.LIMIT); - verify(resourceAssembler).toUserProfileResourceList(users, USER_MANAGER_URL); + @Test + void shouldFindNotDeletedUserProfiles() { + resource.findUsers(SEARCH_QUERY, NOT_DELETED_USER_PROFILES, EMPTY_PARAM_ORGANISATIONSEINHEIT_ID); + + verify(userService).findActiveUsers(query.capture()); + assertThat(query.getValue()).usingRecursiveComparison().isEqualTo( + FindUserProfilesQuery + .builder() + .searchBy(SEARCH_QUERY) + .limit(UserProfileResource.LIMIT) + .build()); } @Test - void shouldSearchDeletedUserProfiles() { - when(userService.findInactiveUsers(anyString(), anyInt())).thenReturn(users.stream()); - - resource.findUsers(SEARCH_QUERY, true); + void shouldFindDeletedUserProfiles() { + resource.findUsers(SEARCH_QUERY, DELETED_USER_PROFILES, EMPTY_PARAM_ORGANISATIONSEINHEIT_ID); + + verify(userService).findInactiveUsers(query.capture()); + assertThat(query.getValue()).usingRecursiveComparison().isEqualTo( + FindUserProfilesQuery + .builder() + .searchBy(SEARCH_QUERY) + .limit(UserProfileResource.LIMIT) + .build()); + } - verify(userService).findInactiveUsers(SEARCH_QUERY, UserProfileResource.LIMIT); - verify(resourceAssembler).toUserProfileResourceList(users, USER_MANAGER_URL); + @Test + void shouldFindAllUserProfiles() { + resource.findUsers(SEARCH_QUERY, EMPTY_PARAM_DELETED, EMPTY_PARAM_ORGANISATIONSEINHEIT_ID); + + verify(userService).findUsers(query.capture()); + assertThat(query.getValue()).usingRecursiveComparison().isEqualTo( + FindUserProfilesQuery + .builder() + .searchBy(SEARCH_QUERY) + .limit(UserProfileResource.LIMIT) + .build()); } @Test - void shouldSearchDeletedAndNotDeletedUserProfiles() { - when(userService.findUsers(anyString(), anyInt())).thenReturn(users.stream()); + void shouldCallResourceAssembler() { + when(userService.findUsers(any())).thenReturn(users.stream()); - resource.findUsers(SEARCH_QUERY, null); + resource.findUsers(SEARCH_QUERY, EMPTY_PARAM_DELETED, EMPTY_PARAM_ORGANISATIONSEINHEIT_ID); - verify(userService).findUsers(SEARCH_QUERY, UserProfileResource.LIMIT); verify(resourceAssembler).toUserProfileResourceList(users, USER_MANAGER_URL); } } - } \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceTestProfile.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceTestProfile.java similarity index 94% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceTestProfile.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceTestProfile.java index 16cb762e60a35de89baf37c3450f8ee2c2b5249f..745194172243233b16a7c308620c2e7d28bacbd5 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserProfileResourceTestProfile.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserProfileResourceTestProfile.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.Map; diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/UserRepositoryITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserRepositoryITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..84f91d69573d0ad426eed3e635ce95b631c5ab0a --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserRepositoryITCase.java @@ -0,0 +1,593 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user; + +import static java.util.function.Predicate.not; +import static org.assertj.core.api.Assertions.*; + +import java.time.Instant; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import jakarta.inject.Inject; + +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import de.ozgcloud.user.common.MongoDbTestProfile; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +@QuarkusTest +@TestProfile(MongoDbTestProfile.class) +class UserRepositoryITCase { + + @Inject + UserRepository repository; + + @DisplayName("Update unsynced users") + @Nested + class TestUpdateUnsyncedUser { + + private static final long NOW = Instant.now().toEpochMilli(); + + @BeforeEach + void init() { + repository.deleteAll(); + } + + @Test + void shouldMarkUnsyncedUserAsDeleted() { + repository.persist(createUserWithLastSyncTimestamp(NOW - 1000)); + + repository.updateUnsyncedUsers(NOW); + + assertThat(getFirstUser().isDeleted()).isTrue(); + } + + @Test + void shouldNotMarkUserIfSynced() { + repository.persist(createUserWithLastSyncTimestamp(NOW)); + + repository.updateUnsyncedUsers(NOW); + + assertThat(getFirstUser().isDeleted()).isFalse(); + } + + private User createUserWithLastSyncTimestamp(long lastSyncTimestamp) { + return UserTestFactory.createBuilder().lastSyncTimestamp(lastSyncTimestamp).build(); + } + + private User getFirstUser() { + return repository.findAll().list().get(0); + } + } + + @DisplayName("Find all active user") + @Nested + class TestFindAllActiveUser { + + @BeforeEach + void init() { + repository.deleteAll(); + repository.persist(UserTestFactory.create()); + } + + @Test + void shouldFindByLastName() { + var user = findAllActiveUser(UserTestFactory.LAST_NAME); + + assertThat(user).isNotEmpty().hasSize(1); + } + + @Test + void shouldFindCaseInsensitive() { + var user = findAllActiveUser(UserTestFactory.LAST_NAME.toLowerCase()); + + assertThat(user).isNotEmpty().hasSize(1); + } + + @Test + void shouldFindByFirstName() { + var user = findAllActiveUser(UserTestFactory.FIRST_NAME); + + assertThat(user).isNotEmpty().hasSize(1); + } + + @Test + void shouldFindByUsername() { + var user = findAllActiveUser(UserTestFactory.USER_NAME); + + assertThat(user).isNotEmpty().hasSize(1); + } + + @Test + void shouldFindByUsernamePart() { + var user = findAllActiveUser(UserTestFactory.USER_NAME.substring(0, 4)); + + assertThat(user).isNotEmpty().hasSize(1); + } + + @Test + void shouldFindByEmail() { + var user = findAllActiveUser(UserTestFactory.EMAIL); + + assertThat(user).isNotEmpty().hasSize(1); + } + + @Test + void shouldReturnEmptyListIfNotMatch() { + var user = findAllActiveUser("xxx"); + + assertThat(user).isEmpty(); + } + + private Stream<User> findAllActiveUser(String query) { + return repository.findUsersByDeleted(query, false, 5); + } + + @Test + void shouldFindNotDeletedUsers() { + User user1 = UserTestFactory.createBuilder().id(new ObjectId()).firstName("Max").deleted(true).build(); + User user2 = UserTestFactory.createBuilder().id(new ObjectId()).firstName("Maximilian").deleted(true).build(); + User user3 = UserTestFactory.createBuilder().id(new ObjectId()).firstName("Maximus").deleted(false).build(); + + repository.persist(user1); + repository.persist(user2); + repository.persist(user3); + + var foundUsers = findAllActiveUser("Max").toList(); + + foundUsers.forEach(u -> assertThat(u.isDeleted()).isFalse()); + } + + @Test + void shouldUseLimit() { + repository.persist(UserTestFactory.createBuilder().id(new ObjectId()).build()); + + var res = repository.findUsersByDeleted(UserTestFactory.LAST_NAME.toLowerCase(), false, 2); + assertThat(res).isNotEmpty().hasSize(2); + } + } + + @DisplayName("Find all") + @Nested + class TestFindAll { + + @BeforeEach + void init() { + repository.deleteAll(); + repository.persist(UserTestFactory.createBuilder().id(new ObjectId()).email("test@test.de").externalId("additional-id").build()); + repository.persist(UserTestFactory.create()); + } + + @Test + void shouldFindDeletedAndNotDeletedUsers() { + User user1 = UserTestFactory.createBuilder().id(new ObjectId()).firstName("Max").deleted(true).build(); + User user2 = UserTestFactory.createBuilder().id(new ObjectId()).firstName("Maximilian").deleted(true).build(); + User user3 = UserTestFactory.createBuilder().id(new ObjectId()).firstName("Maximus").deleted(false).build(); + + repository.persist(user1); + repository.persist(user2); + repository.persist(user3); + + var foundUsers = repository.findUsers("Max", 10).toList(); + + assertThat(foundUsers).hasSizeGreaterThan(2); + List<User> startWithMax = foundUsers.stream().filter(u -> u.getFirstName().startsWith("Max")).toList(); + assertThat(startWithMax).hasSize(3); + assertThat(startWithMax.stream().filter(User::isDeleted).count()).isEqualTo(2); + assertThat(startWithMax.stream().filter(not(User::isDeleted)).count()).isEqualTo(1); + } + + @Test + void shouldNotFindAnyUser() { + repository.persist(UserTestFactory.createBuilder().id(null).firstName("Marvel").build()); + + var foundUsers = repository.findUsers("Max", 10).toList(); + + assertThat(foundUsers).isEmpty(); + } + + @Test + void shouldFindOneUser() { + User user1 = UserTestFactory.createBuilder().id(null).firstName("Maximilian").build(); + User user2 = UserTestFactory.createBuilder().id(null).firstName("Madleen").build(); + + repository.persist(user1); + repository.persist(user2); + + var foundUsers = repository.findUsers("Max", 10).toList(); + + assertThat(foundUsers) + .hasSize(1) + .first() + .extracting(User::getFirstName) + .isEqualTo("Maximilian"); + } + } + + @Nested + class TestFindByFullName { + + @BeforeEach + void init() { + repository.deleteAll(); + } + + @ParameterizedTest + @MethodSource("provideDataForFindUsersByFullName") + void shouldFindUsersByFullName(String query, String[] expectedUsernames) { + Arrays.asList( + UserTestFactory.createBuilder().id(null).username("user1").fullName("Franz Vogel").build(), + UserTestFactory.createBuilder().id(null).username("user2").fullName("Franz von Holzhausen").build(), + UserTestFactory.createBuilder().id(null).username("user3").fullName("Peter Lustig").build() + ).forEach(repository::persist); + + var foundUsernames = repository.findUsers(query, 10).map(User::getUsername); + + assertThat(foundUsernames).containsExactlyInAnyOrder(expectedUsernames); + } + + private static Stream<Arguments> provideDataForFindUsersByFullName() { + return Stream.of( + Arguments.of("Fra", new String[] { "user1", "user2" }), + Arguments.of("Franz", new String[] { "user1", "user2" }), + Arguments.of("Franz v", new String[] { "user1", "user2" }), + Arguments.of("Franz Vo ", new String[0]), + Arguments.of("Franz von", new String[] { "user2" }), + Arguments.of("Franz von Holzhausen", new String[] { "user2" }), + Arguments.of("Franz L", new String[0]), + Arguments.of("Peter V", new String[0]) + ); + } + } + + @Nested + class TestFindByFullNameReversed { + + @BeforeEach + void init() { + repository.deleteAll(); + } + + @ParameterizedTest + @MethodSource("provideDataForFindUsersByFullNameReversed") + void shouldFindUsersByFullNameReversed(String query, String[] expectedUsernames) { + Arrays.asList( + UserTestFactory.createBuilder().id(null).username("user1").fullNameReversed("Langbein Franz").build(), + UserTestFactory.createBuilder().id(null).username("user2").fullNameReversed("Lustig Peter").build(), + UserTestFactory.createBuilder().id(null).username("user3").fullNameReversed("Ilona Nowak").build() + ).forEach(repository::persist); + + var foundUsernames = repository.findUsers(query, 10).map(User::getUsername); + + assertThat(foundUsernames).containsExactlyInAnyOrder(expectedUsernames); + } + + private static Stream<Arguments> provideDataForFindUsersByFullNameReversed() { + return Stream.of( + Arguments.of("L", new String[] { "user1", "user2", "user3" }), + Arguments.of("Lustig", new String[] { "user2" }), + Arguments.of("Lustig Peter", new String[] { "user2" }) + ); + } + } + + @Nested + class TestFindUsersByDeletedAndOrganisationsEinheitId { + + private static final String ORGANISATIONSEINHEIT_ID_1 = "ORGA_1"; + private static final String ORGANISATIONSEINHEIT_ID_2 = "ORGA_2"; + private static final int LIMIT = 10; + private User user1; + private User user2; + private User user3; + + @BeforeEach + void init() { + user1 = UserTestFactory.createBuilder().id(null).build(); + user2 = UserTestFactory.createBuilder() + .id(null) + .clearOrganisationsEinheitIds() + .organisationsEinheitId(ORGANISATIONSEINHEIT_ID_1) + .build(); + user3 = UserTestFactory.createBuilder() + .id(null) + .clearOrganisationsEinheitIds() + .organisationsEinheitId(ORGANISATIONSEINHEIT_ID_1) + .build(); + repository.deleteAll(); + } + + @Test + void shouldFindUserWithOrganisationsEinheitId() { + persistTestUsers(); + + var foundUsers = repository.findUsersByDeletedAndOrganisationsEinheitId( + UserTestFactory.USER_NAME, + false, + UserTestFactory.ORGANISTATIONSEINHEITEN_ID, + LIMIT).toList(); + + assertThat(foundUsers) + .hasSize(1) + .first() + .usingRecursiveComparison() + .isEqualTo(user1); + + } + + @Test + void shouldFindUsersWithOrganisationsEinheitId() { + persistTestUsers(); + + var foundUsers = repository.findUsersByDeletedAndOrganisationsEinheitId( + UserTestFactory.USER_NAME, + false, + ORGANISATIONSEINHEIT_ID_1, + LIMIT).toList(); + + assertThat(foundUsers) + .hasSize(2) + .usingRecursiveFieldByFieldElementComparator() + .contains(user2, user3); + + } + + @Test + void shouldNotFindUserWithOrganisationsEinheitId() { + persistTestUsers(); + + var foundUsers = repository.findUsersByDeletedAndOrganisationsEinheitId( + UserTestFactory.USER_NAME, + false, + ORGANISATIONSEINHEIT_ID_2, + LIMIT).toList(); + assertThat(foundUsers).isEmpty(); + } + + private void persistTestUsers() { + repository.persist(user1); + repository.persist(user2); + repository.persist(user3); + } + } + + @DisplayName("Find all inactive user") + @Nested + class TestFindAllInactiveUser { + + @BeforeEach + void init() { + repository.deleteAll(); + User user1 = UserTestFactory.createBuilder().id(null).firstName("Max").deleted(true).build(); + User user2 = UserTestFactory.createBuilder().id(null).firstName("Maximilian").deleted(true).build(); + User user3 = UserTestFactory.createBuilder().id(null).firstName("Maximus").deleted(false).build(); + repository.persist(user1); + repository.persist(user2); + repository.persist(user3); + } + + @Test + void shouldFindDeletedUsers() { + var foundUsers = repository.findUsersByDeleted("Max", true, 10).toList(); + + assertThat(foundUsers).hasSize(2); + foundUsers.forEach(u -> assertThat(u.isDeleted()).isTrue()); + } + + } + + @DisplayName("Find by externalId") + @Nested + class TestFindByExternalId { + + @BeforeEach + void init() { + repository.deleteAll(); + repository.persist(UserTestFactory.create()); + } + + @Test + void shouldFindByExternalId() { + var user = repository.findByExternalId(UserTestFactory.EXTERNAL_ID); + + assertThat(user).isPresent(); + assertThat(user.get()).usingRecursiveComparison().isEqualTo(UserTestFactory.create()); + } + } + + @Nested + class TestFindByKeycloadId { + + @BeforeEach + void init() { + repository.deleteAll(); + } + + @Test + void shouldFindUser() { + repository.persist(UserTestFactory.create()); + + var user = repository.findByKeycloakId(UserTestFactory.KEYCLOAK_USER_ID); + + assertThat(user) + .isPresent() + .map(User::getKeycloakUserId) + .hasValue(UserTestFactory.KEYCLOAK_USER_ID); + } + + @Test + void shouldNotFindUser() { + var user = repository.findByKeycloakId(UserTestFactory.KEYCLOAK_USER_ID); + + assertThat(user).isEmpty(); + } + } + + @DisplayName("Find by id") + @Nested + class TestFindById { + + @BeforeEach + void init() { + repository.deleteAll(); + repository.persist(UserTestFactory.create()); + } + + @Test + void shouldFindById() { + var user = repository.findById(UserTestFactory.ID_STR); + + assertThat(user).isNotNull(); + assertThat(user.get()).usingRecursiveComparison().isEqualTo(UserTestFactory.create()); + } + + @Test + void shouldNotFindIfIdNull() { + assertThat(repository.findById((String) null)).isEmpty(); + } + + @Test + void shouldNotFindIfEmptyId() { + assertThat(repository.findById("")).isEmpty(); + } + + @Test + void shouldNotFindIfBlankId() { + assertThat(repository.findById(" ")).isEmpty(); + } + + @Test + void shouldNotFindIfInvalidId() { + assertThat(repository.findById("wrong_id")).isEmpty(); + } + } + + @DisplayName("Find by email") + @Nested + class TestFindByEmail { + + @BeforeEach + void init() { + repository.deleteAll(); + repository.persist(UserTestFactory.create()); + } + + @Test + void shouldFindByEmailOnly() { + var user = repository.findByEmail(UserTestFactory.EMAIL); + + assertThat(user).isPresent(); + assertThat(user.get()).usingRecursiveComparison().isEqualTo(UserTestFactory.create()); + } + + @Test + void shouldNotFindByEmptyEmail() { + var user = repository.findByEmail(null); + + assertThat(user).isEmpty(); + } + + } + + @DisplayName("Test refreshing user") + @Nested + class TestRefresh { + + @BeforeEach + void init() { + repository.deleteAll(); + repository.persist(UserTestFactory.create()); + } + + @Test + void shouldRefreshByExternalId() { + var user = repository.refresh(UserTestFactory.createBuilder().id(null).build()); + + assertThat(user).usingRecursiveComparison().ignoringFields("id").isEqualTo(UserTestFactory.create()); + } + + @Test + void shouldRefreshById() { + var user = repository.refresh(UserTestFactory.create()); + + assertThat(user).usingRecursiveComparison().ignoringFields("id").isEqualTo(UserTestFactory.create()); + } + } + + @Nested + class TestFindAllDeletedUserIds { + + @BeforeEach + void init() { + repository.deleteAll(); + } + + @Test + void shouldFindOneElement() { + var deletedUser = UserTestFactory.createBuilder().id(null).deleted(true).build(); + repository.persist(deletedUser); + + var userIds = repository.findAllDeletedUserIds(); + + assertThat(userIds).hasSize(1).first().isEqualTo(deletedUser.getId().toHexString()); + } + + @Test + void shouldFindNoneElements() { + repository.persist(UserTestFactory.create()); + + var userIds = repository.findAllDeletedUserIds(); + + assertThat(userIds).isEmpty(); + } + } + + @Nested + class TestDeleteById { + + @BeforeEach + void init() { + repository.deleteAll(); + repository.persist(UserTestFactory.create()); + } + + @Test + void shouldDelete() { + repository.deleteById(UserTestFactory.ID_STR); + + assertThat(repository.findAll().stream()).isEmpty(); + } + } + +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/UserRepositoryTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6fa7b81bb4f5f7f7fa8675f3dacc7f0d5c33d909 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserRepositoryTest.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import org.assertj.core.api.Condition; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.user.common.errorhandling.ResourceNotFoundException; +import io.quarkus.mongodb.panache.PanacheQuery; +import io.quarkus.mongodb.panache.common.PanacheUpdate; +import io.quarkus.panache.common.Parameters; + +class UserRepositoryTest { + @Spy + UserRepository userRepository; + + @Mock + PanacheQuery<User> panacheQuery; + + User user = UserTestFactory.create(); + + @DisplayName("Test updating users") + @Nested + class TestUpdate { + + @Captor + private ArgumentCaptor<Parameters> parametersCaptor; + @Captor + private ArgumentCaptor<String> updateStatementCaptor; + + @Test + void shouldCallUpdate() { + doReturn(UserTestFactory.create()).when(userRepository).findById(any(ObjectId.class)); + doNothing().when(userRepository).update(any(User.class)); + + userRepository.updateUser(UserTestFactory.create()); + + verify(userRepository, times(2)).findById(any(ObjectId.class)); + verify(userRepository).update(any(User.class)); + } + + @Test + void shouldMarkUserAsDeleted() { + PanacheUpdate update = mock(PanacheUpdate.class); + doReturn(update).when(userRepository).update(anyString(), anyBoolean()); + long timestamp = new Date().getTime(); + + userRepository.updateUnsyncedUsers(timestamp); + + verify(userRepository).update(User.DELETED_FIELD, true); + verify(update).where(updateStatementCaptor.capture(), parametersCaptor.capture()); + assertThat(updateStatementCaptor.getValue()).isEqualTo(UserRepository.UPDATE_UNSYNCED_USER_QUERY); + assertThat(parametersCaptor.getValue().map()).containsEntry(UserRepository.PARAM_NAME_TIMESTAMP, timestamp); + } + } + + @DisplayName("Test loading users") + @Nested + class TestFind { + + @Test + void shouldFindByExternalId() { + doReturn(Optional.of(user)).when(panacheQuery).firstResultOptional(); + doReturn(panacheQuery).when(userRepository).find(anyString(), anyString()); + + var userOpt = userRepository.findByExternalId(UserTestFactory.EXTERNAL_ID); + + assertThat(userOpt).isPresent().get().isEqualTo(user); + } + + @Test + void shouldFindByEmail() { + doReturn(Optional.of(user)).when(panacheQuery).firstResultOptional(); + doReturn(panacheQuery).when(userRepository).find(anyString(), anyString()); + + var userOpt = userRepository.findByEmail(UserTestFactory.EMAIL); + + assertThat(userOpt).isPresent().get().isEqualTo(user); + } + + @Test + void shouldFindById() { + doReturn(Optional.of(user)).when(userRepository).findByIdOptional(UserTestFactory.ID); + + var userOpt = userRepository.findById(UserTestFactory.ID.toHexString()); + + assertThat(userOpt).isPresent().get().isEqualTo(user); + } + + @DisplayName("handle loading list of users") + @Nested + class TestFindUsers { + Condition<User> cond = new Condition<>(value -> value.equals(user), "User expected"); + + @Mock + PanacheQuery<?> rangeQuery; + + @BeforeEach + void init() { + doReturn(List.of(UserTestFactory.create()).stream()).when(rangeQuery).stream(); + doReturn(rangeQuery).when(panacheQuery).range(anyInt(), anyInt()); + } + + @Test + void shouldFindUsers() { + doReturn(panacheQuery).when(userRepository).find(anyString(), any(Parameters.class)); + + var userStream = userRepository.findUsers(UserTestFactory.USER_NAME, 1); + + assertThat(userStream).areExactly(0, cond); + } + + @Test + void shouldFindDeletedUsers() { + doReturn(panacheQuery).when(userRepository).find(anyString(), any(Parameters.class)); + + var userStream = userRepository.findUsersByDeleted(UserTestFactory.USER_NAME, true, 1); + + assertThat(userStream).areExactly(0, cond); + } + } + } + + @DisplayName("Test refreshing a user") + @Nested + class TestRefresh { + @Test + void shouldRefreshUserById() { + doReturn(Optional.of(user)).when(userRepository).findByIdOptional(UserTestFactory.ID); + doReturn(Optional.of(user)).when(panacheQuery).firstResultOptional(); + doReturn(panacheQuery).when(userRepository).find(anyString(), anyString()); + + var refreshedUser = userRepository.refresh(user); + + assertThat(refreshedUser).isEqualTo(user); + } + + @Test + void shouldRefreshUserByExternalId() { + doReturn(Optional.empty()).when(userRepository).findByIdOptional(any(ObjectId.class)); + doReturn(Optional.of(user)).when(userRepository).findByExternalId(anyString()); + + var refreshedUser = userRepository.refresh(UserTestFactory.create()); + + assertThat(refreshedUser).isEqualTo(user); + } + + @Test + void shouldThrowResourceNotFound() { + doReturn(Optional.empty()).when(userRepository).findByIdOptional(any(ObjectId.class)); + doReturn(Optional.empty()).when(userRepository).findByExternalId(anyString()); + + assertThatExceptionOfType(ResourceNotFoundException.class).isThrownBy(() -> userRepository.refresh(UserTestFactory.create())); // NOSONAR + } + } + + @Nested + class TestToRegex { + + @Test + void shouldReturnRegex(){ + var regex = userRepository.toRegex("abc"); + + assertThat(regex).isEqualTo("/.*abc.*/i"); + } + } +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserRepresentationTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserRepresentationTestFactory.java similarity index 94% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserRepresentationTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserRepresentationTestFactory.java index 0b3b794dfceb34aeeac8fadc64d00ae065ad6468..6995cba9bb4659032cbece0e285beb70cafbb376 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserRepresentationTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserRepresentationTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.time.Instant; import java.util.List; @@ -49,7 +49,7 @@ public class UserRepresentationTestFactory { private static final String LDAP_ID_KEY = "LDAP_ID"; static final Map<String, List<String>> ATTRIBUTES = Map.of(LDAP_ID_KEY, List.of(EXTERNAL_ID)); - static final String CLIENT_KEY = "sh-kiel-dev-goofy"; + static final String CLIENT_KEY = "alfa"; private static final Map<String, List<String>> CLIENT_ROLED = Map.of(CLIENT_KEY, List.of(ROLE_NAME)); static UserRepresentation createWithAttributes(Map<String, List<String>> attributes) { diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceMapperTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceMapperTest.java similarity index 70% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceMapperTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserResourceMapperTest.java index b863d0bf77774efe7e1c6cb8d82ea85543d7b921..af60b025e0fc8c78f0e590760765d4fdfb6531e9 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceMapperTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceMapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; @@ -39,16 +39,16 @@ import org.keycloak.admin.client.resource.RoleMappingResource; import org.keycloak.admin.client.resource.RoleScopeResource; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.representations.idm.ClientMappingsRepresentation; -import org.keycloak.representations.idm.GroupRepresentation; import org.keycloak.representations.idm.MappingsRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.mapstruct.factory.Mappers; import org.mockito.InjectMocks; import org.mockito.Mock; -import de.itvsh.kop.user.keycloak.KeycloakApiProperties; +import de.ozgcloud.user.keycloak.KeycloakApiProperties; class UserResourceMapperTest { + static final String ORGANISATIONS_EINHEIT_ID_KEY = "organisationseinheitId"; static final String ORGANISATIONS_EINHEIT_ID_1 = "0815"; static final String ORGANISATIONS_EINHEIT_ID_2 = "4711"; @@ -59,105 +59,143 @@ class UserResourceMapperTest { static final Map<String, List<String>> ATTRIBUTES_2 = Map.of(ORGANISATIONS_EINHEIT_ID_KEY, List.of(ORGANISATIONS_EINHEIT_ID_2)); @InjectMocks - private UserResourceMapper mapper = Mappers.getMapper(UserResourceMapper.class); + UserResourceMapper mapper = Mappers.getMapper(UserResourceMapper.class); @Mock - private KeycloakApiProperties properties; + KeycloakApiProperties properties; @Mock - private RealmResource realm; + RealmResource realm; + @DisplayName("To kop user") @Nested - class TestMapping { + class TestToKopUser { @BeforeEach void init() { when(properties.ldapIdKey()).thenReturn("LDAP_ID"); when(properties.organisationsEinheitIdKey()).thenReturn("organisationseinheitId"); - when(properties.client()).thenReturn("sh-kiel-dev-goofy"); + when(properties.client()).thenReturn("alfa"); when(realm.getGroupByPath(GROUP_1_PATH)) .thenReturn(GroupRepresentationTestFactory.createByPathAndOrganisationEinheitId(GROUP_1_PATH, ORGANISATIONS_EINHEIT_ID_1)); when(properties.ldapIdKey()).thenReturn("LDAP_ID"); when(properties.organisationsEinheitIdKey()).thenReturn("organisationseinheitId"); - when(properties.client()).thenReturn("sh-kiel-dev-goofy"); + when(properties.client()).thenReturn("alfa"); } @Test void shouldMapToUser() { - User user = mapper.toKopUser(UserResourceTestFactory.create()); + var user = toKopUser(); assertThat(user).isNotNull(); } @Test void shouldMapEmail() { - User user = mapper.toKopUser(UserResourceTestFactory.create()); + var user = toKopUser(); assertThat(user.getEmail()).isEqualTo(UserRepresentationTestFactory.EMAIL); } - @Test - void shouldMapExternalId() { - User user = mapper.toKopUser(UserResourceTestFactory.create()); + @DisplayName("externalId") + @Nested + class TestMapExternalId { - assertThat(user.getExternalId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID); - } + @Test + void shouldMap() { + var user = toKopUser(); - @Test - void shouldMapExternalIdFallback() { - User user = mapper.toKopUser(UserResourceTestFactory.createWithAttributes(Map.of())); + assertThat(user.getExternalId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID); + } - assertThat(user.getExternalId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID_FALLBACK); + @Test + void shouldMapFallbackOnEmptyAttributes() { + var user = toKopUser(UserResourceTestFactory.createWithAttributes(Collections.emptyMap())); + + assertThat(user.getExternalId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID_FALLBACK); + } } @Test void shouldMapFirstName() { - User user = mapper.toKopUser(UserResourceTestFactory.create()); + var user = toKopUser(); assertThat(user.getFirstName()).isEqualTo(UserRepresentationTestFactory.FIRST_NAME); } @Test void shouldMapLastName() { - User user = mapper.toKopUser(UserResourceTestFactory.create()); + var user = toKopUser(); assertThat(user.getLastName()).isEqualTo(UserRepresentationTestFactory.LAST_NAME); } @Test void shouldMapUserName() { - User user = mapper.toKopUser(UserResourceTestFactory.create()); + var user = toKopUser(); assertThat(user.getUsername()).isEqualTo(UserRepresentationTestFactory.USER_NAME); } @Test void shouldMapOrganisationsEinheitIds() { - User user = mapper.toKopUser(UserResourceTestFactory.create()); + var user = toKopUser(); assertThat(user.getOrganisationsEinheitIds()).isNotEmpty().contains(ORGANISATIONS_EINHEIT_ID_1); } @Test void shouldMapMultipleOrganisationsEinheitIds() { - GroupRepresentation groupRepresentation = GroupRepresentationTestFactory.createByPathAndOrganisationEinheitId(GROUP_2_PATH, + var groupRepresentation = GroupRepresentationTestFactory.createByPathAndOrganisationEinheitId(GROUP_2_PATH, ORGANISATIONS_EINHEIT_ID_2); - when(realm.getGroupByPath(GROUP_2_PATH)).thenReturn(groupRepresentation); - User user = mapper.toKopUser( - UserResourceTestFactory.createWithGroups(List.of(GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_1_PATH), - GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_2_PATH)))); + var user = toKopUser(buildUserResourceWithGroups()); assertThat(user.getOrganisationsEinheitIds()).isNotEmpty().hasSize(2).contains(ORGANISATIONS_EINHEIT_ID_2); } + private UserResource buildUserResourceWithGroups() { + return UserResourceTestFactory.createWithGroups(List.of( + GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_1_PATH), + GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_2_PATH))); + } + @Test void shouldMapRoles() { - User user = mapper.toKopUser(UserResourceTestFactory.create()); + var user = toKopUser(); assertThat(user.getRoles()).isNotEmpty().contains(UserRepresentationTestFactory.ROLE_NAME); } + + @Test + void shouldMapKeycloakUserId() { + var user = toKopUser(); + + assertThat(user.getKeycloakUserId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID_FALLBACK); + } + + @Test + void shouldMapFullName() { + var user = toKopUser(); + + assertThat(user.getFullName()).isEqualTo(UserRepresentationTestFactory.FIRST_NAME + " " + UserRepresentationTestFactory.LAST_NAME); + } + + @Test + void shouldMapFullNameReversed() { + var user = toKopUser(); + + assertThat(user.getFullNameReversed()).isEqualTo(UserRepresentationTestFactory.LAST_NAME + " " + UserRepresentationTestFactory.FIRST_NAME); + } + + private User toKopUser() { + return toKopUser(UserResourceTestFactory.create()); + } + + private User toKopUser(UserResource userResource) { + return mapper.toKopUser(userResource); + } } @DisplayName("Get client roles") @@ -165,18 +203,18 @@ class UserResourceMapperTest { class TestGetClientRoles { @Mock - private UserResource userResource; + UserResource userResource; @Mock - private RoleMappingResource roleMappingResource; + RoleMappingResource roleMappingResource; @Mock - private RoleScopeResource roleScopeResource; + RoleScopeResource roleScopeResource; @Mock - private MappingsRepresentation mappingsRepresentation; + MappingsRepresentation mappingsRepresentation; @Mock - private Map<String, ClientMappingsRepresentation> clientMappingsRepresentation; + Map<String, ClientMappingsRepresentation> clientMappingsRepresentation; @Mock - private ClientMappingsRepresentation clientMappingRepresentation; + ClientMappingsRepresentation clientMappingRepresentation; @BeforeEach void init() { @@ -247,4 +285,4 @@ class UserResourceMapperTest { } } } -} \ No newline at end of file +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceStub.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceStub.java similarity index 93% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceStub.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserResourceStub.java index 79c3ebdcc2f54ad71465b709ee7d5bf52a90fa62..0841ea35d7cee616a8dcc01a7eb6ffa13f48c487 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceStub.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceStub.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,12 +21,12 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.List; import java.util.Map; -import javax.ws.rs.core.Response; +import jakarta.ws.rs.core.Response; import org.keycloak.admin.client.resource.RoleMappingResource; import org.keycloak.admin.client.resource.RoleScopeResource; @@ -44,6 +44,7 @@ import lombok.NoArgsConstructor; @NoArgsConstructor class UserResourceStub implements UserResource { + private UserRepresentation userRepresentation = UserRepresentationTestFactory.create(); private List<GroupRepresentation> groups = List.of(GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_1_PATH)); @@ -60,6 +61,11 @@ class UserResourceStub implements UserResource { return userRepresentation; } + @Override + public UserRepresentation toRepresentation(boolean userProfileMetadata) { + return userRepresentation; + } + @Override public void update(UserRepresentation userRepresentation) { // not implemented @@ -95,6 +101,11 @@ class UserResourceStub implements UserResource { return groups(); } + @Override + public List<GroupRepresentation> groups(String search, boolean briefRepresentation) { + return groups(); + } + @Override public List<GroupRepresentation> groups(String search, Integer firstResult, Integer maxResults, boolean briefRepresentation) { return groups(); @@ -236,7 +247,7 @@ class UserResourceStub implements UserResource { var clientMapRep = new ClientMappingsRepresentation(); var roleRep = new RoleRepresentation(UserRepresentationTestFactory.ROLE_NAME, "Test role", false); clientMapRep.setMappings(List.of(roleRep)); - rep.setClientMappings(Map.of("sh-kiel-dev-goofy", clientMapRep)); + rep.setClientMappings(Map.of("alfa", clientMapRep)); return rep; } diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceTestFactory.java similarity index 94% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserResourceTestFactory.java index f94763b5b95812eb6c74068c514877adaab022fb..0d53a3dc410c32b1462d495373361272bf52d3a7 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserResourceTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.List; import java.util.Map; diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CurrentCallContextUserServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserRoleTest.java similarity index 57% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CurrentCallContextUserServiceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserRoleTest.java index a7852c433cabc95df8e1087a0cb74d2ac1887817..4cd8a7d722227d2711eeb515314be8608d442114 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CurrentCallContextUserServiceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserRoleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,31 +21,41 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user; import static org.assertj.core.api.Assertions.*; -import org.junit.jupiter.api.BeforeEach; +import java.util.List; + import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.mockito.Spy; -class CurrentCallContextUserServiceTest { - @Spy - private CurrentCallContextUserService userService; +class UserRoleTest { @Nested - class TestService { - CallContextUser user = CallContextUserTestFactory.create(); + class TestContainsWithinRoleHierarchy { + + @Test + void shouldReturnTrue() { + var containsRole = UserRole.containsWithinRoleHierarchy(List.of(UserRole.VERWALTUNG_LOESCHEN), UserRole.VERWALTUNG_USER); + + assertThat(containsRole).isTrue(); + } - @BeforeEach - void init() { - userService.setCallContextUser(user); + @Test + void shouldReturnFalse() { + var containsRole = UserRole.containsWithinRoleHierarchy(List.of(UserRole.VERWALTUNG_USER), UserRole.VERWALTUNG_LOESCHEN); + + assertThat(containsRole).isFalse(); } @Test - void shouldGetUser() { - assertThat(userService.getCurrentCallContextUser()).isPresent().get().isEqualTo(user); + void shouldReturnTrueOnSame() { + var containsRole = UserRole.containsWithinRoleHierarchy(List.of(UserRole.VERWALTUNG_USER), UserRole.VERWALTUNG_USER); + + assertThat(containsRole).isTrue(); } + } -} + +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserServiceITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserServiceITCase.java similarity index 84% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserServiceITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserServiceITCase.java index d227e9d85f22f5c2635ce21a22466b269b20c9de..2b2da534e7b645d8715337483dd21a571f875e7e 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserServiceITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserServiceITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,22 +21,25 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import static org.assertj.core.api.Assertions.*; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import de.itvsh.kop.user.settings.NotificationsSendFor; -import de.itvsh.kop.user.settings.UserSettingsTestFactory; +import de.ozgcloud.user.common.MongoDbTestProfile; +import de.ozgcloud.user.settings.NotificationsSendFor; +import de.ozgcloud.user.settings.UserSettingsTestFactory; import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; @QuarkusTest +@TestProfile(MongoDbTestProfile.class) class UserServiceITCase { @Inject diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/UserServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c7aa45360e2b4bc7f1b1e63fc3ea483c4b6109c3 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserServiceTest.java @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user; + +import static de.ozgcloud.user.UserTestFactory.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.time.Instant; +import java.util.Optional; +import java.util.stream.Stream; + +import org.apache.commons.lang3.StringUtils; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.user.common.errorhandling.ResourceNotFoundException; +import de.ozgcloud.user.common.errorhandling.TechnicalException; +import de.ozgcloud.user.keycloak.KeycloakUserRemoteService; + +class UserServiceTest { + + @InjectMocks + @Spy + private UserService service; + + @Mock + private KeycloakUserRemoteService keycloakRemoteService; + + @Mock + private UserRepository repository; + + @Nested + class TestGetById { + + private final static String ID = "xxx"; + + @BeforeEach + void mockRepository() { + when(repository.findById(anyString())).thenReturn(Optional.of(UserTestFactory.create())); + } + + @Test + void shouldCallRepository() { + service.getById(ID); + + verify(repository).findById(anyString()); + } + + @Test + void shouldThrowExceptionIfNotExists() { + when(repository.findById(anyString())).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> service.getById(ID)) + .isInstanceOf(ResourceNotFoundException.class) + .extracting(e -> ((ResourceNotFoundException) e).getId()).isEqualTo(ID); + } + } + + @Nested + class TestSave { + + private final User user = UserTestFactory.create(); + + @BeforeEach + void init() { + when(repository.refresh(any())).thenReturn(UserTestFactory.create()); + } + + @Test + void shouldCallUpdate() { + when(repository.findByExternalId(any())).thenReturn(Optional.of(user)); + + service.save(user.toBuilder().firstName("Other").build()); + + verify(repository).updateUser(any(User.class)); + } + + @Test + void shouldCallPersist() { + service.save(user); + + verify(repository).persist(any(User.class)); + } + + @Test + void shouldCallFindByExternalId() { + service.save(user); + + verify(repository, atLeastOnce()).findByExternalId(any()); + } + + @Test + void shouldCallFindByEmail() { + service.save(UserTestFactory.createBuilder().externalId(null).build()); + + verify(repository, atLeastOnce()).findByEmail(anyString()); + } + + @Test + void shouldNotCallFindByEmailOnEmptyEMail() { + service.save(UserTestFactory.createBuilder().id(new ObjectId()).externalId(null).email(StringUtils.EMPTY).build()); + + verify(repository, never()).findByEmail(anyString()); + } + } + + @Nested + class TestMarkUnsyncedUserAsDeleted { + + @Test + void shouldCallRepository() { + var lastSyncTimestamp = Instant.now().toEpochMilli(); + + service.markUnsyncedUsersAsDeleted(lastSyncTimestamp); + + verify(repository).updateUnsyncedUsers(lastSyncTimestamp); + } + } + + @Nested + class TestFindUsers { + + private static final String SEARCH_QUERY = "aaa"; + private static final int LIMIT = 50; + + @Test + void shouldFindUsers() { + service.findUsers(FindUserProfilesQuery.builder().searchBy(SEARCH_QUERY).limit(LIMIT).build()); + + verify(repository).findUsers(SEARCH_QUERY, LIMIT); + } + } + + @Nested + class TestFindByExternalId { + + @Test + void shouldSearchInUserRepository() { + when(repository.findByKeycloakId(anyString())).thenReturn(Optional.of(UserTestFactory.create())); + + service.findByExternalId(EXTERNAL_ID); + + verify(repository).findByKeycloakId(EXTERNAL_ID); + verify(keycloakRemoteService, never()).findUserById(anyString()); + } + + @Test + void shouldCallKeycloakRemoteService() { + var user = UserTestFactory.create(); + when(keycloakRemoteService.findUserById(anyString())).thenReturn(Optional.of(user)); + when(service.saveAndSync(user)).thenReturn(user); + + service.findByExternalId(EXTERNAL_ID); + + verify(keycloakRemoteService).findUserById(EXTERNAL_ID); + } + + @Test + void shouldCallSaveAndSync() { + var user = UserTestFactory.create(); + when(keycloakRemoteService.findUserById(anyString())).thenReturn(Optional.of(user)); + doReturn(user).when(service).saveAndSync(user); + + service.findByExternalId(EXTERNAL_ID); + + verify(service).saveAndSync(user); + } + + @Test + void shouldThrowException() { + assertThrows(ResourceNotFoundException.class, () -> service.findByExternalId(EXTERNAL_ID)); + } + } + + @Nested + class TestSaveAndSync { + + @Test + void shouldSaveUser() { + var user = UserTestFactory.create(); + + service.saveAndSync(user); + + verify(service).save(user); + } + + @Test + void shouldSyncUser() { + var user = UserTestFactory.create(); + + var saved = service.saveAndSync(user); + + verify(keycloakRemoteService, timeout(1000)).updateOzgCloudUserId(saved); + } + } + + @Nested + class TestFindActiveUsers { + + private static final String SEARCH_BY = "search by"; + private static final int LIMIT = 50; + + @Test + void shouldFindActiveUsers() { + var query = FindUserProfilesQuery.builder() + .searchBy(SEARCH_BY) + .limit(LIMIT) + .build(); + service.findActiveUsers(query); + + verify(repository).findUsersByDeleted(SEARCH_BY, false, LIMIT); + } + + @Test + void shouldFindActiveUsersWithOrganisationsEinheitId() { + var query = FindUserProfilesQuery.builder() + .searchBy(SEARCH_BY) + .organisationsEinheitId(ORGANISTATIONSEINHEITEN_ID) + .limit(LIMIT) + .build(); + service.findActiveUsers(query); + + verify(repository).findUsersByDeletedAndOrganisationsEinheitId(SEARCH_BY, false, ORGANISTATIONSEINHEITEN_ID, LIMIT); + + } + } + + @Nested + class TestFindInactiveUsers { + + private static final String SEARCH_BY = "search by"; + private static final int LIMIT = 50; + + @Test + void shouldInactiveFindUsers() { + var query = FindUserProfilesQuery.builder() + .searchBy(SEARCH_BY) + .limit(LIMIT) + .build(); + service.findInactiveUsers(query); + + verify(repository).findUsersByDeleted(SEARCH_BY, true, LIMIT); + } + + @Test + void shouldFindInactiveUsersWithOrganisationsEinheitId() { + var query = FindUserProfilesQuery.builder() + .searchBy(SEARCH_BY) + .organisationsEinheitId(ORGANISTATIONSEINHEITEN_ID) + .limit(LIMIT) + .build(); + service.findInactiveUsers(query); + + verify(repository).findUsersByDeletedAndOrganisationsEinheitId(SEARCH_BY, true, ORGANISTATIONSEINHEITEN_ID, LIMIT); + + } + } + + @Nested + class TestFindAllInactiveUserIds { + + private final Stream<String> deletedUserIds = Stream.of(ID.toHexString()); + + @BeforeEach + void init() { + when(repository.findAllDeletedUserIds()).thenReturn(deletedUserIds); + } + + @Test + void shouldCallRepository() { + service.findAllInactiveUserIds(); + + verify(repository).findAllDeletedUserIds(); + } + + @Test + void shouldReturnStream() { + var result = service.findAllInactiveUserIds(); + + assertThat(result).hasSize(1).first().isEqualTo(ID.toHexString()); + } + } + + @Nested + class TestDeleteInactive { + + private final User user = UserTestFactory.create(); + + @BeforeEach + void init() { + doReturn(user).when(service).getById(ID_STR); + doNothing().when(service).assertInactiveUser(user); + } + + @Test + void shouldGetUser() { + callService(); + + verify(service).getById(ID_STR); + } + + @Test + void shouldAssertInactiveUser() { + callService(); + + verify(service).assertInactiveUser(user); + } + + @Test + void shouldDeleteUser() { + callService(); + + verify(repository).deleteById(ID_STR); + } + + private void callService() { + service.deleteInactive(ID_STR); + } + } + + @Nested + class TestAssertInactiveUser { + + @Test + void shouldThrowException() { + var user = createBuilder().deleted(false).build(); + + assertThatThrownBy(() -> service.assertInactiveUser(user)).isInstanceOf( + TechnicalException.class); + } + + @Test + void shouldNotThrowException() { + var user = createBuilder().deleted(true); + + assertThatNoException().isThrownBy(() -> service.assertInactiveUser(user.build())); + } + } +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/UserTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserTestFactory.java similarity index 64% rename from user-manager-server/src/test/java/de/itvsh/kop/user/UserTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/UserTestFactory.java index d225445ae74234a30f3d37f86ca2e65b4078f3c0..20f5a6a14d40b3fe0fbf66b06a42673e8896c404 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/UserTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,50 +21,49 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user; +package de.ozgcloud.user; import java.util.List; -import java.util.UUID; import org.bson.types.ObjectId; -import com.thedeanda.lorem.LoremIpsum; - -import de.itvsh.kop.user.settings.UserSettings; -import de.itvsh.kop.user.settings.UserSettingsTestFactory; +import de.ozgcloud.user.settings.UserSettingsTestFactory; public class UserTestFactory { - public static final String FIRST_NAME = LoremIpsum.getInstance().getFirstName(); - public static final String LAST_NAME = LoremIpsum.getInstance().getLastName(); - public static final String USER_NAME = LoremIpsum.getInstance().getName(); + public static final ObjectId ID = new ObjectId(); + public static final String KEYCLOAK_USER_ID = "aec115b5-67be-42c9-a693-36d4d711a87a"; + public static final String ID_STR = ID.toHexString(); + + public static final String FIRST_NAME = "Sabine"; + public static final String LAST_NAME = "Sach"; + public static final String FULL_NAME = FIRST_NAME + " " + LAST_NAME; + public static final String FULL_NAME_REVERSED = LAST_NAME + " " + FIRST_NAME; + public static final String USER_NAME = "sabine"; public static final long LAST_SYNC_TIMESTAMP = 1001L; - public static final String EMAIL = LoremIpsum.getInstance().getEmail(); - public static final String EXTERNAL_ID = UUID.randomUUID().toString(); + public static final String EMAIL = "sabine.sach@ozgcloud.de"; + public static final String EXTERNAL_ID = "aec115b5-67be-42c9-a693-36d4d711a87a"; public static final String ORGANISTATIONSEINHEITEN_ID = "0815"; public static final List<String> ROLES = List.of("ROLE_1", "POSTSTELLE"); - public static final ObjectId ID = new ObjectId(); - public static final UserSettings USER_SETTINGS = UserSettingsTestFactory.create(); public static User create() { return createBuilder().build(); } - public static User createWithId() { - return createBuilder().id(ID).build(); - } - public static User.UserBuilder createBuilder() { return User.builder() - .id(new ObjectId()) + .id(ID) + .keycloakUserId(KEYCLOAK_USER_ID) .firstName(FIRST_NAME) .lastName(LAST_NAME) + .fullName(FULL_NAME) + .fullNameReversed(FULL_NAME_REVERSED) .username(USER_NAME) .lastSyncTimestamp(LAST_SYNC_TIMESTAMP) .email(EMAIL) .externalId(EXTERNAL_ID) .organisationsEinheitId(ORGANISTATIONSEINHEITEN_ID) .roles(ROLES) - .userSettings(USER_SETTINGS); + .userSettings(UserSettingsTestFactory.create()); } } diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/JwtUtilTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/JwtUtilTest.java similarity index 93% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/JwtUtilTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/JwtUtilTest.java index 11675400942724533a39ecbaff68de0a78bc6df7..8ac11c3aab388bf96acb3ca16e971992446d296b 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/JwtUtilTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/JwtUtilTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common; +package de.ozgcloud.user.common; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -30,8 +30,9 @@ import static org.mockito.Mockito.*; import java.util.List; import java.util.Map; -import javax.json.Json; -import javax.json.JsonArray; +import de.ozgcloud.user.common.callcontext.CallContextMetadataTestFactory; +import jakarta.json.Json; +import jakarta.json.JsonArray; import org.eclipse.microprofile.jwt.JsonWebToken; import org.junit.jupiter.api.BeforeEach; @@ -45,10 +46,9 @@ import org.mockito.Spy; import com.cronutils.utils.StringUtils; import com.thedeanda.lorem.LoremIpsum; -import de.itvsh.kop.user.UserRole; -import de.itvsh.kop.user.common.callcontext.CallContextMetadataTestFactory; -import de.itvsh.kop.user.common.callcontext.CurrentCallContextUserService; -import de.itvsh.kop.user.keycloak.KeycloakApiProperties; +import de.ozgcloud.user.UserRole; +import de.ozgcloud.user.common.callcontext.CurrentCallContextUserService; +import de.ozgcloud.user.keycloak.KeycloakApiProperties; class JwtUtilTest { diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/common/MongoDbTestProfile.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/MongoDbTestProfile.java new file mode 100644 index 0000000000000000000000000000000000000000..e4de3a63b7dbaa696f45b5aa1ca53f4fbc1f6ac9 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/MongoDbTestProfile.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.common; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class MongoDbTestProfile implements QuarkusTestProfile { + + @Override + public Map<String, String> getConfigOverrides() { + return Map.of("quarkus.mongodb.devservices.enabled", "true"); + } +} diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextInterceptorTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextInterceptorTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..f6e8208b85db2ae7c806c0b515e1bd9f12bef240 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextInterceptorTestFactory.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.common.callcontext; + +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall.SimpleForwardingClientCall; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; + +public class CallContextInterceptorTestFactory { + + private static final String CLIENT_NAME = "Client - Alfa"; + private static final String ORGANISATIONS_EINHEIT_ID = "organisationsEinheitId"; + private static final Boolean ORGANISATIONS_EINEHIT_ID_CHECK_NECESSARY = Boolean.TRUE; + + public static ClientInterceptor createClientInterceptor() { + return new TestClientInterceptor(); + } + + private static class TestClientInterceptor implements ClientInterceptor { + + @Override + public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) { + return new TestCallContextAttachingClientCall<>(next.newCall(method, callOptions)); + } + + final class TestCallContextAttachingClientCall<ReqT, RespT> extends SimpleForwardingClientCall<ReqT, RespT> { + + protected TestCallContextAttachingClientCall(ClientCall<ReqT, RespT> delegate) { + super(delegate); + } + + @Override + public void start(Listener<RespT> responseListener, Metadata headers) { + headers.merge(new Metadata()); + + super.start(responseListener, headers); + } + } + } + + public static ClientInterceptor createClientInterceptorWithMetadata() { + return new TestClientInterceptorWithMetadata(); + } + + private static class TestClientInterceptorWithMetadata implements ClientInterceptor { + + @Override + public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) { + return new TestCallContextAttachingClientCall<>(next.newCall(method, callOptions)); + } + + final class TestCallContextAttachingClientCall<ReqT, RespT> extends SimpleForwardingClientCall<ReqT, RespT> { + protected TestCallContextAttachingClientCall(ClientCall<ReqT, RespT> delegate) { + super(delegate); + } + + @Override + public void start(Listener<RespT> responseListener, Metadata headers) { + headers.merge(createMetadata()); + + super.start(responseListener, headers); + } + + private Metadata createMetadata() { + var metadata = new Metadata(); + metadata.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_CLIENT_NAME), + CLIENT_NAME.getBytes()); + metadata.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_ACCESS_LIMITED_ORGAID), + ORGANISATIONS_EINHEIT_ID.getBytes()); + metadata.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_ACCESS_LIMITED), + ORGANISATIONS_EINEHIT_ID_CHECK_NECESSARY.toString().getBytes()); + return metadata; + } + } + } +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CallContextMetadataTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextMetadataTestFactory.java similarity index 68% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CallContextMetadataTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextMetadataTestFactory.java index 595919d1ae461e3c3cb93841f006fb280b35725a..4a8114aa2b2f0a4f55895acfbe74dd6c8f6de8fd 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CallContextMetadataTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextMetadataTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; import java.util.UUID; @@ -43,13 +43,13 @@ public class CallContextMetadataTestFactory { public static Metadata createMetadata() { var result = new Metadata(); - result.put(GrpcCallContextInterceptor.createKeyOf(GrpcCallContextInterceptor.KEY_USER_ID), ID.getBytes()); - result.put(GrpcCallContextInterceptor.createKeyOf(GrpcCallContextInterceptor.KEY_USER_NAME), NAME.getBytes()); - result.put(GrpcCallContextInterceptor.createKeyOf(GrpcCallContextInterceptor.KEY_CLIENT_NAME), CLIENT.getBytes()); - result.put(GrpcCallContextInterceptor.createKeyOf(GrpcCallContextInterceptor.KEY_ACCESS_LIMITED_ORGAID), + result.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_USER_ID), ID.getBytes()); + result.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_USER_NAME), NAME.getBytes()); + result.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_CLIENT_NAME), CLIENT.getBytes()); + result.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_ACCESS_LIMITED_ORGAID), ORGANISATORISCHE_EINHEITEN_ID.getBytes()); - result.put(GrpcCallContextInterceptor.createKeyOf(GrpcCallContextInterceptor.KEY_REQUEST_ID), REQUEST_ID.getBytes()); - result.put(GrpcCallContextInterceptor.createKeyOf(GrpcCallContextInterceptor.KEY_ACCESS_LIMITED), + result.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_REQUEST_ID), REQUEST_ID.getBytes()); + result.put(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_ACCESS_LIMITED), DO_ORGA_ID_ACCESS_CHECK.toString().getBytes()); return result; diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CallContextUserTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextUserTestFactory.java similarity index 87% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CallContextUserTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextUserTestFactory.java index f3e93702e91c56153f2c0de7501757a5b775d014..450cc6788d4d59e81e0a8d5ff014071a18867fb1 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/CallContextUserTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CallContextUserTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; import java.util.Optional; @@ -29,9 +29,6 @@ import com.thedeanda.lorem.LoremIpsum; public class CallContextUserTestFactory { - static final String NAME = CallContextMetadataTestFactory.NAME; - static final String ID = CallContextMetadataTestFactory.ID; - private static final String EMAIL = LoremIpsum.getInstance().getEmail(); public static CallContextUser create() { diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CurrentCallContextUserServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CurrentCallContextUserServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..39eece468f9946f694378e557b4f55bb143e0ec3 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/CurrentCallContextUserServiceTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.common.callcontext; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Spy; + +import de.ozgcloud.user.UserRole; + +class CurrentCallContextUserServiceTest { + + @Spy + private CurrentCallContextUserService userService; + + private final CallContextUser callContextUser = CallContextUserTestFactory.create(); + + @DisplayName("Clear call context user") + @Nested + class TestClearCallContextUser { + + @Test + void shouldSetUserToNull() { + userService.clearCallContextUser(); + + assertThat(userService.getCurrentCallContextUser()).isEmpty(); + } + } + + @Nested + class TestGetCurrentCallContextUser { + + @BeforeEach + void init() { + userService.setCallContextUser(callContextUser); + } + + @Test + void shouldGetUser() { + assertThat(userService.getCurrentCallContextUser()).isPresent().get().isEqualTo(callContextUser); + } + } + + @Nested + class TestHasRole { + + private final CallContextUser callContextUser = CallContextUserTestFactory.createBuilder() + .roles(List.of(UserRole.VERWALTUNG_LOESCHEN)) + .build(); + + @BeforeEach + void init() { + userService.setCallContextUser(callContextUser); + } + + @Test + void shouldCheckRoleWithinHierarchy() { + try (var mock = mockStatic(UserRole.class)) { + mock.when(() -> UserRole.containsWithinRoleHierarchy(callContextUser.getRoles(), UserRole.VERWALTUNG_USER)).thenReturn(true); + + userService.hasRole(UserRole.VERWALTUNG_USER); + + mock.verify(() -> UserRole.containsWithinRoleHierarchy(callContextUser.getRoles(), UserRole.VERWALTUNG_USER)); + } + } + + @Test + void shouldReturnTrue() { + var hasRole = userService.hasRole(UserRole.VERWALTUNG_USER); + + assertThat(hasRole).isTrue(); + } + + @Test + void shouldReturnFalse() { + var hasRole = userService.hasRole("unknown"); + + assertThat(hasRole).isFalse(); + } + + } +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/GrpcCallContextInterceptorTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/GrpcCallContextInterceptorTest.java similarity index 55% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/GrpcCallContextInterceptorTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/GrpcCallContextInterceptorTest.java index e5f7866d2441aa915541a613050aecf33739f83a..1e584674f80d62faa96ad06c2916fb5feba3a9db 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/GrpcCallContextInterceptorTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/GrpcCallContextInterceptorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,9 +21,9 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; -import static de.itvsh.kop.user.common.callcontext.GrpcCallContextInterceptor.*; +import static de.ozgcloud.user.common.callcontext.GrpcCallContextInterceptor.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -36,33 +36,41 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import de.itvsh.kop.user.common.callcontext.GrpcCallContextInterceptor.LogContextSettingListener; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.callcontext.GrpcCallContextInterceptor.*; +import de.ozgcloud.user.common.errorhandling.ResourceNotFoundException; import io.grpc.Metadata; import io.grpc.ServerCall; +import io.grpc.Status; class GrpcCallContextInterceptorTest { @InjectMocks private GrpcCallContextInterceptor interceptor; - @Mock private ServerCall.Listener<Object> delegate; - + @Mock + private ServerCall<Object, Object> originCall; @Spy private CurrentCallContextUserService userService; + @DisplayName("Log context setting listener") @Nested - class TestCallListener { - private LogContextSettingListener<?> listener; + class TestLogContextSettingListenerTest { + + private LogContextSettingListener<?, ?, ?> listener; private Metadata headers = CallContextMetadataTestFactory.createMetadata(); @BeforeEach void createListener() { - listener = spy(interceptor.new LogContextSettingListener<>(delegate, headers)); + listener = spy(interceptor.new LogContextSettingListener<>(delegate, originCall, headers)); } + @DisplayName("get request id") @Nested class TestGetRequestId { + @Test void shouldReturnIdFromHeader() { var reqId = listener.getRequestId(); @@ -72,7 +80,7 @@ class GrpcCallContextInterceptorTest { @Test void shouldReturnNewRequestIdIfNoGiven() { - headers.removeAll(createKeyOf(KEY_REQUEST_ID)); + headers.removeAll(GrpcUtil.createKeyOf(KEY_REQUEST_ID)); var reqId = listener.getRequestId(); @@ -81,9 +89,9 @@ class GrpcCallContextInterceptorTest { } - @DisplayName("Map headers to user") + @DisplayName("create call context user") @Nested - class TestHeadersToUser { + class TestCreateCallContextUser { @Test void shouldFilledUser() { var user = buildListener().createCallContextUser(); @@ -94,7 +102,7 @@ class GrpcCallContextInterceptorTest { @Test void shouldFillOrgaIdCollection() { Metadata metadata = CallContextMetadataTestFactory.createMetadata(); - metadata.put(createKeyOf(KEY_ACCESS_LIMITED_ORGAID), "orgaid_2".getBytes()); + metadata.put(GrpcUtil.createKeyOf(KEY_ACCESS_LIMITED_ORGAID), "orgaid_2".getBytes()); var user = buildListener(metadata).createCallContextUser(); @@ -106,7 +114,7 @@ class GrpcCallContextInterceptorTest { @Test void shouldFillEmptyListIfNoOrgaIds() { Metadata metadata = CallContextMetadataTestFactory.createMetadata(); - metadata.removeAll(createKeyOf(KEY_ACCESS_LIMITED_ORGAID)); + metadata.removeAll(GrpcUtil.createKeyOf(KEY_ACCESS_LIMITED_ORGAID)); var user = buildListener(metadata).createCallContextUser(); @@ -129,7 +137,7 @@ class GrpcCallContextInterceptorTest { @Test void shouldMapFalseIfKeyIsNotPresent() { var metadata = CallContextMetadataTestFactory.createMetadata(); - metadata.removeAll(createKeyOf(KEY_ACCESS_LIMITED)); + metadata.removeAll(GrpcUtil.createKeyOf(KEY_ACCESS_LIMITED)); var user = buildListener(metadata).createCallContextUser(); @@ -139,23 +147,40 @@ class GrpcCallContextInterceptorTest { } + @DisplayName("start security context") @Nested class TestStartSecurityContext { - @Test - void shouldHaveAuthenticatedAuthorization() { + @Test + void shouldCreateCallContextUser() { listener.startSecurityContext(); - var userOptional = userService.getCurrentCallContextUser(); + verify(listener).createCallContextUser(); + } + + @Test + void shouldCallUserService() { + listener.startSecurityContext(); - assertThat(userOptional).isPresent(); - assertThat(userOptional.get().isAuthenticated()).isTrue(); + verify(userService).setCallContextUser(any()); } + } + @DisplayName("clear security context") + @Nested + class TestClearSecurityContext { + + @Test + void shouldCallUserService() { + listener.clearSecurityContext(); + + verify(userService).clearCallContextUser(); + } } + @DisplayName("do surround on") @Nested - class TestDoSurround { + class TestDoSurroundOn { private Runnable mockRunnable = mock(Runnable.class); @@ -180,20 +205,45 @@ class GrpcCallContextInterceptorTest { verify(listener).clearSecurityContext(); } - @Test - void shouldClearSecurityContextOnException() { - var testException = new RuntimeException(); + @DisplayName("catch exception") + @Nested + class TestException { + + @Test + void shouldClearSecurityContextOnException() { + listener.doSurroundOn(() -> { + throw new RuntimeException(); + }); - assertThatThrownBy(() -> listener.doSurroundOn(() -> { - throw testException; - })).isSameAs(testException); + verify(listener).clearSecurityContext(); + } + + @Test + void shouldCloseCallWithStatusNotFound() { + listener.doSurroundOn(() -> { + throw new ResourceNotFoundException(User.class, UserTestFactory.ID); + }); + + verify(originCall, never()).close(eq(Status.UNKNOWN), any()); + verify(originCall).close(Status.NOT_FOUND, headers); + } + + @Test + void shouldCloseCallWithStatusUnknown() { + listener.doSurroundOn(() -> { + throw new RuntimeException(); + }); + + verify(originCall, never()).close(eq(Status.NOT_FOUND), any()); + verify(originCall).close(Status.UNKNOWN, headers); + } } } @Nested class TestOnFunctions { - private LogContextSettingListener<Object> listener; + private LogContextSettingListener<Object, ?, ?> listener; @BeforeEach void initListener() { @@ -202,9 +252,7 @@ class GrpcCallContextInterceptorTest { @Test void onMessageShouldCallSurround() { - Object message = mock(Object.class); - - listener.onMessage(message); + listener.onMessage(new Object()); verify(listener).doSurroundOn(any()); } @@ -230,22 +278,59 @@ class GrpcCallContextInterceptorTest { verify(listener).doSurroundOn(any()); } - @Test - void onReadyShouldCallSurround() { - listener.onReady(); + @DisplayName("onReady") + @Nested + class TestOnReady { - verify(listener).doSurroundOn(any()); + @DisplayName("with existing clientName") + @Nested + class TestWithExistingClientName { + + @Test + void shouldCallDoSurroundOn() { + listener.onReady(); + + verify(listener).doSurroundOn(any()); + } + } + + @DisplayName("with missing clientName") + @Nested + class TestWithMissingClientName { + + private LogContextSettingListener<?, ?, ?> listener; + private Metadata headers = CallContextMetadataTestFactory.createMetadata(); + + @BeforeEach + void initListener() { + headers.discardAll(GrpcUtil.createKeyOf(GrpcCallContextInterceptor.KEY_CLIENT_NAME)); + listener = spy(interceptor.new LogContextSettingListener<>(delegate, originCall, headers)); + } + + @Test + void shouldHandleMissingClientName() { + listener.onReady(); + + verify(listener).handleMissingClientName(); + verify(originCall).close(any(), eq(headers)); + } + + @Test + void shouldNotCallDoSurroundOn() { + listener.onReady(); + + verify(listener, never()).doSurroundOn(any()); + } + } } } - private LogContextSettingListener<Object> buildListener() { + private LogContextSettingListener<Object, ?, ?> buildListener() { return buildListener(headers); } - private LogContextSettingListener<Object> buildListener(Metadata headers) { - return spy(interceptor.new LogContextSettingListener<Object>(delegate, headers)); + private LogContextSettingListener<Object, ?, ?> buildListener(Metadata headers) { + return spy(interceptor.new LogContextSettingListener<>(delegate, originCall, headers)); } - } - -} +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/GrpcUtilTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/GrpcUtilTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8765091f21040084203e8d0ed5baecdf8fb54cf9 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/GrpcUtilTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.common.callcontext; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import io.grpc.Metadata; + +class GrpcUtilTest { + + private static final String KEY_STR = "dummy-bin"; + private static final String VALUE_STR = "dummyKeyValueWithöäü#!,.-?"; + + @DisplayName("Create key of") + @Nested + class TestCreateKeyOf { + + @Test + void shouldReturnKey() { + var key = GrpcUtil.createKeyOf(KEY_STR); + + assertThat(key.originalName()).isEqualTo(KEY_STR); + assertThat(key.name()).isEqualTo(KEY_STR); + } + } + + @DisplayName("Get from headers") + @Nested + class TestGetFromHeaders { + + @Test + void shouldReturnValueIfExists() { + var value = GrpcUtil.getFromHeaders(KEY_STR, createMetadata()); + + assertThat(value).isPresent(); + assertThat(value.get()).contains(VALUE_STR); + } + + @Test + void shouldReturnEmptyIfNotExists() { + var value = GrpcUtil.getFromHeaders(KEY_STR, new Metadata()); + + assertThat(value).isEmpty(); + } + } + + @DisplayName("Get collection") + @Nested + class TestGetCollection { + + @Test + void shouldReturnSingleValueAsList() { + var valueList = GrpcUtil.getCollection(KEY_STR, createMetadata()); + + assertThat(valueList).containsExactly(VALUE_STR); + } + + @Test + void shouldReturnMultipleValuesAsList() { + var metadata = createMetadata(); + metadata.put(GrpcUtil.createKeyOf(KEY_STR), "otherValue-bin".getBytes()); + + var valueList = GrpcUtil.getCollection(KEY_STR, metadata); + + assertThat(valueList).containsExactly(VALUE_STR, "otherValue-bin"); + } + + @Test + void shouldReturnEmptyListIfNotExists() { + var valueList = GrpcUtil.getCollection(KEY_STR, new Metadata()); + + assertThat(valueList).isEmpty(); + } + } + + private Metadata createMetadata() { + var metadata = new Metadata(); + metadata.put(GrpcUtil.createKeyOf(KEY_STR), VALUE_STR.getBytes()); + return metadata; + } +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/HttpRequestInterceptorTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/HttpRequestInterceptorTest.java similarity index 89% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/HttpRequestInterceptorTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/HttpRequestInterceptorTest.java index c81a265dfcdd4cd7a0d4f2a723b31bb3127a41b6..2b110005624ed6551c5222fbb89ff1faeed973ae 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/HttpRequestInterceptorTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/HttpRequestInterceptorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; @@ -29,8 +29,8 @@ import static org.mockito.Mockito.*; import java.util.List; import java.util.UUID; -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.ext.ReaderInterceptorContext; +import jakarta.ws.rs.core.MultivaluedHashMap; +import jakarta.ws.rs.ext.ReaderInterceptorContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -38,7 +38,6 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.Spy; -import de.itvsh.kop.user.common.callcontext.HttpRequestInterceptor; class HttpRequestInterceptorTest { @Spy diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/HttpSecurityFilterTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/HttpSecurityFilterTest.java similarity index 93% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/HttpSecurityFilterTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/HttpSecurityFilterTest.java index afb1df56af11dccca2924c09cc839f1cbb5c2ae1..7f7fdbe72d3788f185bc45570dbe87024d115c0e 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/callcontext/HttpSecurityFilterTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/callcontext/HttpSecurityFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.callcontext; +package de.ozgcloud.user.common.callcontext; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -29,7 +29,7 @@ import static org.mockito.Mockito.*; import java.io.IOException; -import javax.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.container.ContainerRequestContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -39,7 +39,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import de.itvsh.kop.user.common.JwtUtil; +import de.ozgcloud.user.common.JwtUtil; class HttpSecurityFilterTest { diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/errorhandling/ApiErrorUtilTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/errorhandling/ApiErrorUtilTest.java similarity index 80% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/errorhandling/ApiErrorUtilTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/errorhandling/ApiErrorUtilTest.java index 0f3583495f45be250f719bab29375e174d020cd7..3b11f4cf1f1607cd62fcedd204645ecb92e8b535 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/errorhandling/ApiErrorUtilTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/errorhandling/ApiErrorUtilTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,13 +21,15 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import java.util.UUID; +import jakarta.ws.rs.NotFoundException; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -37,7 +39,7 @@ import org.mockito.Spy; import com.cronutils.utils.StringUtils; import com.thedeanda.lorem.LoremIpsum; -import de.itvsh.kop.user.User; +import de.ozgcloud.user.User; class ApiErrorUtilTest { @@ -88,6 +90,46 @@ class ApiErrorUtilTest { } } + @DisplayName("Build from NotFound exception") + @Nested + class TestBuildFromNotFoundException { + + private final NotFoundException exception = new NotFoundException(message); + + @BeforeEach + void mockExceptionId() { + doReturn(exceptionId).when(util).createExceptionId(); + } + + @Test + void shouldHaveMessageCode() { + var error = handleException(); + + assertThat(error.getIssues()).hasSize(1); + assertThat(error.getIssues().get(0).getMessageCode()).isEqualTo(ApiErrorUtil.RESOURCE_NOT_FOUND_MESSAGE_CODE); + } + + @Test + void shouldHaveMessage() { + var error = handleException(); + + assertThat(error.getIssues()).hasSize(1); + assertThat(error.getIssues().get(0).getMessage()).contains(exception.getMessage()); + } + + @Test + void shouldHaveExceptionId() { + var error = handleException(); + + assertThat(error.getIssues()).hasSize(1); + assertThat(error.getIssues().get(0).getExceptionId()).isEqualTo(exceptionId); + } + + private ApiError handleException() { + return util.buildFromNotFoundException(exception); + } + } + @DisplayName("Build from resource not found exception") @Nested class TestBuildFromResourceNotFoundException { @@ -99,7 +141,7 @@ class ApiErrorUtilTest { var error = handleException(); assertThat(error.getIssues()).hasSize(1); - assertThat(error.getIssues().get(0).getMessageCode()).isEqualTo(ApiErrorUtil.RESOURCE_NOT_FOUNT_MESSAGE_CODE); + assertThat(error.getIssues().get(0).getMessageCode()).isEqualTo(ApiErrorUtil.RESOURCE_NOT_FOUND_MESSAGE_CODE); } @Test @@ -201,4 +243,11 @@ class ApiErrorUtilTest { return util.buildFromKeycloakUnavailableException(exception); } } + + @Test + void shouldCreateExceptionId() { + var exceptionId = util.createExceptionId(); + + assertThat(exceptionId).isNotNull(); + } } \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/errorhandling/ExceptionHandlerTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/errorhandling/ExceptionHandlerTest.java similarity index 79% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/errorhandling/ExceptionHandlerTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/errorhandling/ExceptionHandlerTest.java index fd1b6e2b1afbc5f8a247ee6ed54012c3d65f0566..1c3fbd6d0b870e28ba8598a63ac4c0b763de0eed 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/errorhandling/ExceptionHandlerTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/errorhandling/ExceptionHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,12 +21,15 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.common.errorhandling; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.core.UriInfo; + import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -37,8 +40,8 @@ import org.mockito.Mock; import com.thedeanda.lorem.LoremIpsum; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserTestFactory; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserTestFactory; class ExceptionHandlerTest { @@ -46,6 +49,8 @@ class ExceptionHandlerTest { private ExceptionHandler handler = new ExceptionHandler(); @Mock private ApiErrorUtil apiErrorUtil; + @Mock + private UriInfo uriInfo; @DisplayName("Handle runtime exception") @Nested @@ -73,6 +78,38 @@ class ExceptionHandlerTest { } } + @DisplayName("Handle notfound exception") + @Nested + class TestHandleNotFoundException { + private final String PATH = "/this_path_does_not_exist"; + + private final NotFoundException exception = new NotFoundException(LoremIpsum.getInstance().getWords(5)); + + @BeforeEach + void mockUtil() { + when(apiErrorUtil.buildFromNotFoundException(any())).thenReturn(ApiError.builder().build()); + } + + @BeforeEach + void mockUriInfo() { + when(uriInfo.getPath()).thenReturn(PATH); + } + + @Test + void shouldCallApiErrorUtilToBuildApiError() { + handler.mapNotFoundException(exception); + + verify(apiErrorUtil).buildFromNotFoundException(exception); + } + + @Test + void shouldHaveStatus() { + var response = handler.mapNotFoundException(exception); + + assertThat(response.getStatus()).isEqualTo(404); + } + } + @DisplayName("Handle resource not found exception") @Nested class TestHandleResourceNotFoundException { diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockRepositoryITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockRepositoryITCase.java similarity index 88% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockRepositoryITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockRepositoryITCase.java index e2f279381a1b86bf37e1f80fd3a2c82017c11efe..31a48a08afe44f54819d55d2fd53d978aeb99c34 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockRepositoryITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockRepositoryITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,21 +21,24 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.lock; +package de.ozgcloud.user.common.lock; import static org.assertj.core.api.Assertions.*; import java.time.Instant; import java.time.temporal.ChronoUnit; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import de.ozgcloud.user.common.MongoDbTestProfile; import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; @QuarkusTest +@TestProfile(MongoDbTestProfile.class) class LockRepositoryITCase { @Inject diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockRepositoryTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0190f762384051a8b290257f7b9b93d94cf55b0c --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockRepositoryTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.common.lock; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.time.Instant; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Spy; + +import io.quarkus.mongodb.panache.PanacheQuery; + +class LockRepositoryTest { + @Spy + LockRepository lockRepository; + + @Mock + PanacheQuery<Lock> panacheFindQuery; + + @DisplayName("Test loading sync lock") + @Nested + class TestGetLock { + private static final Lock LOCK = LockTestFactory.create(); + + @BeforeEach + void init() { + doReturn(panacheFindQuery).when(lockRepository).find(anyString(), anyLong()); + doReturn(Optional.of(LOCK)).when(panacheFindQuery).firstResultOptional(); + } + + @Test + void shouldGetOldLock() { + var lockOptional = lockRepository.findLockBefore(Instant.ofEpochMilli(LOCK.getTimestamp())); + + assertThat(lockOptional).isPresent().get().hasFieldOrPropertyWithValue(Lock.TIMESTAMP_FIELD, LOCK.getTimestamp()); + } + + @Test + void shouldGetLock() { + var lockOptional = lockRepository.findLock(Instant.ofEpochMilli(LOCK.getTimestamp())); + + assertThat(lockOptional).isPresent().get().hasFieldOrPropertyWithValue(Lock.TIMESTAMP_FIELD, LOCK.getTimestamp()); + } + } +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockServiceTest.java similarity index 88% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockServiceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockServiceTest.java index e6db9f2f0a9a0483ed60ff12f79c1b864a77205e..89887349a1b08e4d2fafd3ac1b859321d66acca1 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockServiceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,8 +21,9 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.lock; +package de.ozgcloud.user.common.lock; +import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -36,12 +37,7 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; -import static org.assertj.core.api.Assertions.*; - -import de.itvsh.kop.user.common.errorhandling.LockCreationException; -import de.itvsh.kop.user.common.lock.Lock; -import de.itvsh.kop.user.common.lock.LockRepository; -import de.itvsh.kop.user.common.lock.LockService; +import de.ozgcloud.user.common.errorhandling.LockCreationException; class LockServiceTest { @@ -115,14 +111,11 @@ class LockServiceTest { @DisplayName("Unlock") @Nested class TestUnlock { - - private final Lock lock = LockTestFactory.create(); - @Test - void shouldCallRepositoryDelete() { - service.unlock(lock); + void shouldCallRepositoryDeleteAll() { + service.unlock(); - verify(repository).delete(lock); + verify(repository).deleteAll(); } } diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockTestFactory.java similarity index 89% rename from user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockTestFactory.java index 0d9ed3f70e877844a79be6f139686ef46ec2b72f..6af3f86d755fea2b6cc52417d0864a2f1b18f157 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/common/lock/LockTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/common/lock/LockTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,12 +21,10 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.lock; +package de.ozgcloud.user.common.lock; import java.time.Instant; -import de.itvsh.kop.user.common.lock.Lock; - public class LockTestFactory { private static final long TIMESTAMP = Instant.now().toEpochMilli(); diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakApiServiceITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakApiServiceITCase.java similarity index 91% rename from user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakApiServiceITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakApiServiceITCase.java index e6d76f21ab88e617f83fc0c9f655fa5f45922e14..77d4a07798c36adc876d155095128da5a17c471e 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakApiServiceITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakApiServiceITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,11 +21,11 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.keycloak; import static org.assertj.core.api.Assertions.*; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.junit.jupiter.api.Test; diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakApiServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakApiServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a8d0a743809c2785a3dcf104290c93adefc0a4dd --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakApiServiceTest.java @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.keycloak; + +import static de.ozgcloud.user.UserTestFactory.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.function.Supplier; +import java.util.stream.Stream; + +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.ClientErrorException; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.ProcessingException; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.admin.client.resource.UsersResource; +import org.keycloak.representations.idm.UserRepresentation; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.user.RemoteUserIterator; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserRepresentationTestFactory; +import de.ozgcloud.user.UserResourceMapper; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.errorhandling.KeycloakUnavailableException; + +class KeycloakApiServiceTest { + + @Spy + @InjectMocks + private KeycloakApiService service; + @Mock + private RealmResource realmResource; + @Mock + private UserResourceMapper userResourceMapper; + @Mock + private KeycloakApiProperties properties; + + @Mock + private UserResource userResource; + + @DisplayName("Find all user") + @Nested + class TestFindAllUser { + + @Mock + private UsersResource usersResource; + + @Mock + private RemoteUserIterator iterator; + + private final User user = UserTestFactory.create(); + private final UserRepresentation userRepresentation = UserRepresentationTestFactory.create(); + private final Stream<UserRepresentation> userStream = Stream.of(userRepresentation); + + @BeforeEach + void init() { + doReturn(userStream).when(service).getAllUserRepresentation(); + } + + @Test + void shouldCreateIteratorWithRealmResource() { + service.findAllUser(); + + verify(service).getAllUserRepresentation(); + } + + @Test + void shouldCallMapper() { + when(userResourceMapper.toKopUser(any(UserResource.class))).thenReturn(user); + when(realmResource.users()).thenReturn(usersResource); + when(usersResource.get(anyString())).thenReturn(userResource); + + service.findAllUser().toList(); + + verify(userResourceMapper).toKopUser(any(UserResource.class)); + } + } + + @Nested + @DisplayName("Find user by id") + class TestFindUserById { + + private static final String USER_ID = "user_id"; + + @Mock + private UsersResource usersResource; + + @BeforeEach + void beforeEach() { + when(realmResource.users()).thenReturn(usersResource); + } + + @Test + void shouldCallUsersResource() { + when(usersResource.get(anyString())).thenReturn(userResource); + + service.findUserById(EXTERNAL_ID); + + verify(usersResource).get(EXTERNAL_ID); + } + + @Test + void shouldCallMapper() { + when(usersResource.get(anyString())).thenReturn(userResource); + + service.findUserById(EXTERNAL_ID); + + verify(userResourceMapper).toKopUser(any()); + } + + @Test + @DisplayName("should not call mapper when user not found") + void shouldNotCallMapper() { + when(usersResource.get(anyString())).thenThrow(new NotFoundException()); + + service.findUserById("unknown_user"); + + verify(userResourceMapper, never()).toKopUser(any()); + } + + @Test + void shoulReturnEmpty() { + when(usersResource.get(USER_ID)).thenThrow(new NotFoundException()); + + var user = service.findUserById(USER_ID); + + assertThat(user).isEmpty(); + } + } + + @DisplayName("handling keycloak exception") + @Nested + class TestHandlingKeycloakException { + + @Test + void shouldThrowOnClientErrorException() { + assertThatThrownBy(() -> handlingKeyCloakException(() -> { + throw new ClientErrorException(403); + })).isInstanceOf(KeycloakUnavailableException.class); + } + + @Test + void shouldThrowOnProcessingException() { + assertThatThrownBy(() -> handlingKeyCloakException(() -> { + throw new ProcessingException(new RuntimeException()); + })).isInstanceOf(KeycloakUnavailableException.class); + } + + @Test + void shouldThrowIllegalStateException() { + assertThatThrownBy(() -> handlingKeyCloakException(() -> { + throw new IllegalStateException(new RuntimeException()); + })).isInstanceOf(KeycloakUnavailableException.class); + } + + private <T> T handlingKeyCloakException(Supplier<T> runnable) { + return service.handlingKeycloakException(runnable); + } + } + + @DisplayName("Set user attribute") + @Nested + class TestUpdateUserAttribute { + + private static final String KEYCLOAK_USER_ID = "1ae2-b123"; + private static final String ATTRIBUTE_NAME_USER_ID = "userId"; + private static final String ATTRIBUTE_VALUE_USER_ID = "10"; + private static final String NEW_USER_ID = "1010"; + + @Mock + private UsersResource usersResource; + @Mock + private UserResource userResource; + @Mock + private UserRepresentation userRepresentation; + + @BeforeEach + void beforeEach() { + when(realmResource.users()).thenReturn(usersResource); + when(usersResource.get(KEYCLOAK_USER_ID)).thenReturn(userResource); + when(userResource.toRepresentation()).thenReturn(userRepresentation); + when(userRepresentation.firstAttribute(ATTRIBUTE_NAME_USER_ID)).thenReturn(ATTRIBUTE_VALUE_USER_ID); + } + + @Test + void shouldGetUsersResource() { + service.updateAttribute(KEYCLOAK_USER_ID, ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + + verify(realmResource).users(); + } + + @Test + void shouldGetUserResource() { + service.updateAttribute(KEYCLOAK_USER_ID, ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + + verify(usersResource).get(KEYCLOAK_USER_ID); + } + + @Test + void shouldGetUserRepresentation() { + service.updateAttribute(KEYCLOAK_USER_ID, ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + + verify(userResource).toRepresentation(); + } + + @Test + void shouldUpdateAttributeIfNotExist() { + when(userRepresentation.firstAttribute(ATTRIBUTE_NAME_USER_ID)).thenReturn(null); + + service.updateAttribute(KEYCLOAK_USER_ID, ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + + verify(userRepresentation).singleAttribute(ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + verify(service).tryUpdateUserResource(userResource, userRepresentation, ATTRIBUTE_NAME_USER_ID); + } + + @Test + void shouldUpdateAttributeIfExistsWithDifferentValue() { + when(userRepresentation.firstAttribute(ATTRIBUTE_NAME_USER_ID)).thenReturn(NEW_USER_ID); + + service.updateAttribute(KEYCLOAK_USER_ID, ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + + verify(userRepresentation).singleAttribute(ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + verify(service).tryUpdateUserResource(userResource, userRepresentation, ATTRIBUTE_NAME_USER_ID); + } + + @Test + void shouldUpdateAttributeIfNewOneGiven() { + service.updateAttribute(KEYCLOAK_USER_ID, ATTRIBUTE_NAME_USER_ID, NEW_USER_ID); + + verify(userRepresentation).singleAttribute(ATTRIBUTE_NAME_USER_ID, NEW_USER_ID); + verify(service).tryUpdateUserResource(userResource, userRepresentation, ATTRIBUTE_NAME_USER_ID); + } + + @Test + void shouldNotSetAttributeIfExistsWithSameValue() { + service.updateAttribute(KEYCLOAK_USER_ID, ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + + verify(userRepresentation, never()).singleAttribute(ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID); + verify(service, never()).tryUpdateUserResource(userResource, userRepresentation, ATTRIBUTE_NAME_USER_ID); + } + + @Test + void shouldCatchBadRequestException() { + when(userRepresentation.firstAttribute(ATTRIBUTE_NAME_USER_ID)).thenReturn(NEW_USER_ID); + doThrow(new BadRequestException("error message")).when(userResource).update(any(OlderUserRepresentation.class)); + + assertThatCode( + () -> service.updateAttribute(KEYCLOAK_USER_ID, ATTRIBUTE_NAME_USER_ID, ATTRIBUTE_VALUE_USER_ID)).doesNotThrowAnyException(); + } + } + + @Nested + class TestTryUpdateUserResource { + + private static final String ATTRIBUTE_NAME_USER_ID = "userId"; + + @Captor + private ArgumentCaptor<UserRepresentation> userRepresentationArgumentCaptor; + + @Mock + private UserRepresentation userRepresentation; + + @Test + void shouldUpdateUserResource() { + service.tryUpdateUserResource(userResource, userRepresentation, ATTRIBUTE_NAME_USER_ID); + + verify(userResource).update(any(OlderUserRepresentation.class)); + } + + @Test + void shouldCreateOlderUserRepresentation() { + service.tryUpdateUserResource(userResource, UserRepresentationTestFactory.create(), ATTRIBUTE_NAME_USER_ID); + + verify(userResource).update(userRepresentationArgumentCaptor.capture()); + assertThat(userRepresentationArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(UserRepresentationTestFactory.create()); + } + + } +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakProviderITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakProviderITCase.java similarity index 90% rename from user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakProviderITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakProviderITCase.java index 19b26b81ea0b7c438b43a240ff57b191e5bc6246..46feb351cd38acceec8a6dfa0b3664cd0a3c81f5 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakProviderITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakProviderITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,11 +21,11 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.keycloak; import static org.assertj.core.api.Assertions.*; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.junit.jupiter.api.Test; import org.keycloak.admin.client.resource.RealmResource; diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncSchedulerTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakProviderTest.java similarity index 56% rename from user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncSchedulerTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakProviderTest.java index ae6b33c1a29dfc6866105d126fc8f9c0b9c54f65..d8c24f23371c3fde8a7dcf78c9bd31f3e15e1399 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncSchedulerTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,65 +21,51 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.sync; +package de.ozgcloud.user.keycloak; +import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.lang.reflect.Field; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; -import de.itvsh.kop.user.common.lock.LockService; +import lombok.SneakyThrows; -class SyncSchedulerTest { +class KeycloakProviderTest { - @Spy @InjectMocks - private SyncScheduler scheduler; - @Mock - private SyncService service; + KeycloakProvider keycloakProvider; @Mock - private LockService syncLockService; + KeycloakApiProperties properties; - @DisplayName("Start Scheduler") + @DisplayName("Test providing keycloak admin client") @Nested - class TestStart { - - @Test - void shouldDoSyncIfNotLocked() { - when(syncLockService.isNotLocked()).thenReturn(true); - - scheduler.start(); - - verify(service).sync(); + class TestProvider { + @BeforeEach + void initProperties() { + setServerUrl(); + when(properties.realm()).thenReturn("realm"); + when(properties.user()).thenReturn("user"); + when(properties.password()).thenReturn("password"); } - @DisplayName("If Locked") - @Nested - class TestIfLocked { - - @BeforeEach - void mockTimeStamp() { - when(syncLockService.isNotLocked()).thenReturn(false); - } - - @Test - void shouldNotDoSync() { - scheduler.start(); - - verify(service, never()).sync(); - } + @SneakyThrows + private void setServerUrl() { + Field url = keycloakProvider.getClass().getDeclaredField("keycloakUrl"); + url.set(keycloakProvider, "url"); + } - @Test - void shouldCheckIfLockIsOlderThanADay() { - scheduler.start(); + @Test + void shouldCreateRealmResource() { + var resource = keycloakProvider.provide(); - verify(syncLockService).isLockOlderThanADay(); - } + assertThat(resource).isNotNull(); } } -} \ No newline at end of file +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakTestProfile.java b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakTestProfile.java similarity index 70% rename from user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakTestProfile.java rename to user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakTestProfile.java index e7aa623bc49d7bc99e8758141269fde56bc548df..f808c700d8676eef9bffdcd94845b4678c095b5a 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakTestProfile.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakTestProfile.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.keycloak; import java.util.Map; @@ -29,17 +29,17 @@ import io.quarkus.test.junit.QuarkusTestProfile; public class KeycloakTestProfile implements QuarkusTestProfile { - private final String userKey = "kop.keycloak.api.user"; - private final String userValue = "goofyApiUser"; + private final String userKey = "ozgcloud.keycloak.api.user"; + private final String userValue = "userManagerApiUser"; - private final String passwordKey = "kop.keycloak.api.password"; - private final String passwordValue = "S9UEMuLG9y9ev99"; + private final String passwordKey = "ozgcloud.keycloak.api.password"; + private final String passwordValue = "hlc_j1I1Ji0trC0"; - private final String realmKey = "kop.keycloak.api.realm"; - private final String realmValue = "sh-kiel-dev"; + private final String realmKey = "ozgcloud.keycloak.api.realm"; + private final String realmValue = "by-kiel-dev"; private final String urlKey = "keycloak.url"; - private final String urlValue = "https://sso.dev.ozg-sh.de"; + private final String urlValue = "https://sso.dev.by.ozg-cloud.de"; @Override public Map<String, String> getConfigOverrides() { diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteServiceITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteServiceITCase.java similarity index 89% rename from user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteServiceITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteServiceITCase.java index 272a07ef904bb710f3af10f0d5e678c0752fda30..23da1df68fe7663777713f8753fa938a23ca8f37 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteServiceITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteServiceITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,14 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.keycloak; import static org.mockito.Mockito.*; import org.junit.jupiter.api.Test; +import io.quarkus.test.InjectMock; import io.quarkus.test.junit.QuarkusTest; -import io.quarkus.test.junit.mockito.InjectMock; import io.quarkus.test.junit.mockito.InjectSpy; @QuarkusTest diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ebc6f83189bf71ee900232727fc556613a132bd6 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/keycloak/KeycloakUserRemoteServiceTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.keycloak; + +import static org.mockito.Mockito.*; + +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import de.ozgcloud.user.UserTestFactory; + +class KeycloakUserRemoteServiceTest { + + @InjectMocks + private KeycloakUserRemoteService remoteService; + @Mock + private KeycloakApiService apiService; + + @DisplayName("Get all users") + @Nested + class TestGetAllUsers { + + @Test + void shouldCallApiService() { + remoteService.getAllUsers(); + + verify(apiService).findAllUser(); + } + } + + @DisplayName("Update ozgCloudUserId attribute in keycloak") + @Nested + class TestUpdateOzgCloudUserId { + + @Test + void shouldCallApiService() { + remoteService.updateOzgCloudUserId(UserTestFactory.create()); + + verify(apiService).updateAttribute( + UserTestFactory.KEYCLOAK_USER_ID, + KeycloakUserRemoteService.ATTRIBUTE_NAME_OZG_CLOUD_USER_ID, + UserTestFactory.ID.toString()); + } + } + + @Nested + @DisplayName("Get user by id") + class TestGetUser { + + private static final String USER_ID = "12345"; + + @Test + void shouldCallApiService() { + when(apiService.findUserById(any())).thenReturn(Optional.of(UserTestFactory.create())); + + remoteService.findUserById(USER_ID); + + verify(apiService).findUserById(USER_ID); + } + } +} diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepositoryITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepositoryITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..e8f54e83ff50099758d911c21ca2495e7846bcd8 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepositoryITCase.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.organisationseinheit; + +import static org.assertj.core.api.Assertions.*; + +import de.ozgcloud.user.TestDatabaseUtils; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.mongodb.client.MongoClient; + +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.MongoDbTestProfile; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +@QuarkusTest +@TestProfile(MongoDbTestProfile.class) +class OrganisationsEinheitRepositoryITCase { + + @Inject + OrganisationsEinheitRepository repository; + + @Inject + MongoClient mongoClient; + + @Nested + @DisplayName("Test finding all Organisationseinheiten IDs") + class TestFindAllOrganisationsEinheitIds { + + @BeforeEach + void init() { + var mongoDb = TestDatabaseUtils.getDatabase(mongoClient); + mongoDb.getCollection("User").drop(); + } + + @Test + void shouldNotLoadDeletedUser() { + repository.persist(UserTestFactory.createBuilder().deleted(true).build()); + + var result = repository.findAllOrganisationsEinheitIds(); + + assertThat(result).isEmpty(); + } + + @Test + void shouldLoadDistinct() { + repository.persist(UserTestFactory.create()); + repository.persist(UserTestFactory.createBuilder().id(null).build()); + + var result = repository.findAllOrganisationsEinheitIds(); + + assertThat(result) + .hasSize(1) + .containsExactlyInAnyOrder(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); + } + } + +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepositoryTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7904540448fa578452f9fc104b160f09a113f228 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitRepositoryTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.organisationseinheit; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.bson.conversions.Bson; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Spy; + +import com.mongodb.client.DistinctIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.model.Filters; + +import de.ozgcloud.user.User; + +class OrganisationsEinheitRepositoryTest { + + @Spy + private OrganisationsEinheitRepository organisationsEinheitRepository; + + @DisplayName("Test find Organisationseinheiten Ids") + @Nested + class TestFindOrganisationsEinheitIds { + @Mock + private MongoCollection<?> mongoCollection; + @Mock + private MongoCursor<String> mongoCursor; + + @Test + void shouldFindAllOrganisationsEinheitIds() { + var iterable = mock(DistinctIterable.class); + when(iterable.iterator()).thenReturn(mongoCursor); + doReturn(mongoCollection).when(organisationsEinheitRepository).mongoCollection(); + when(mongoCollection.distinct(anyString(), any(Bson.class), any())).thenReturn(iterable); + + organisationsEinheitRepository.findAllOrganisationsEinheitIds(); + + verify(mongoCollection).distinct(User.ORGANISATIONS_EINHEIT_IDS_FIELD, Filters.eq(User.DELETED_FIELD, false), String.class); + } + } + +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitServiceTest.java similarity index 70% rename from user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteServiceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitServiceTest.java index bd8ae376086c1052335ea137ef625ed0143f3d2d..4939b94c9de12896f2ad308f1fa1ecce78553e50 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/keycloak/KeycloakUserRemoteServiceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationsEinheitServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.keycloak; +package de.ozgcloud.user.organisationseinheit; import static org.mockito.Mockito.*; @@ -31,22 +31,24 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; -class KeycloakUserRemoteServiceTest { +class OrganisationsEinheitServiceTest { @InjectMocks - private KeycloakUserRemoteService remoteService; + private OrganisationsEinheitService service; + @Mock - private KeycloakApiService apiService; + private OrganisationsEinheitRepository repository; - @DisplayName("Get all userrs") + @DisplayName("Get Organisationseinheiten") @Nested - class TestGetAllUsers { + class TestGetOrganisationsEinheiten { @Test - void shouldCallApiService() { - remoteService.getAllUsers(); + void shouldGetAllOrganisationsEinheitenForAllUsers() { + service.findAllOrganisationsEinheitIds(); - verify(apiService).findAllUser(); + verify(repository).findAllOrganisationsEinheitIds(); } } -} + +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationseinheitGrpcServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationseinheitGrpcServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5c081f604073396a9bc33adec81db50b546d8f32 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/organisationseinheit/OrganisationseinheitGrpcServiceTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.organisationseinheit; + +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import de.ozgcloud.user.grpc.organisationseinheit.GrpcGetSupportedOrganisationsEinheitenResponse; +import io.grpc.stub.StreamObserver; + +public class OrganisationseinheitGrpcServiceTest { + + @InjectMocks + private OrganisationsEinheitGrpcService organisationsEinheitGrpcService; + + @Mock + private OrganisationsEinheitService organisationsEinheitService; + + @Nested + @DisplayName("Get supported Organisationseinheiten") + class GetSupportedOrganisationsEinheiten { + + @Mock + private StreamObserver<GrpcGetSupportedOrganisationsEinheitenResponse> streamObserver; + + @Test + void shouldGetOrganisationsEinheiten() { + organisationsEinheitGrpcService.getSupportedOrganisationsEinheiten( + GrpcGetSupportedOrganisationsEinheitenRequest.newBuilder().build(), + streamObserver); + + verify(organisationsEinheitService).findAllOrganisationsEinheitIds(); + } + } + +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientGrpcServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientGrpcServiceTest.java similarity index 81% rename from user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientGrpcServiceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientGrpcServiceTest.java index 360abd0df1e5cc822478891d557517d42205975c..21ad819f803300d192f47406da7695a09e9a9705 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientGrpcServiceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientGrpcServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.recipient; +package de.ozgcloud.user.recipient; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -35,8 +35,8 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; -import de.itvsh.kop.user.UserTestFactory; -import de.itvsh.kop.user.grpc.recipient.GrpcFindRecipientResponse; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.grpc.recipient.GrpcFindRecipientResponse; import io.grpc.stub.StreamObserver; class RecipientGrpcServiceTest { @@ -62,11 +62,11 @@ class RecipientGrpcServiceTest { @Test void shouldGetUsersFromRepository() { - when(recipientService.findRecipientByOrganisationsEinheitId(any())).thenReturn(List.of(UserTestFactory.create())); + when(recipientService.findByOrganisationsEinheitId(any())).thenReturn(List.of(UserTestFactory.create())); recipientGrpcService.findRecipientByOrganisationsEinheitId(RecipientTestFactory.FIND_REQUEST, streamObserver); - verify(recipientService).findRecipientByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); + verify(recipientService).findByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); } } } \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientMapperTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientMapperTest.java similarity index 87% rename from user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientMapperTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientMapperTest.java index 721c12a4f697c95b9dbaa14a5ee10dc9253d8bba..11707b8eacc350549028011715eb19096d919b3a 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientMapperTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientMapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,17 +21,18 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.recipient; +package de.ozgcloud.user.recipient; import static org.assertj.core.api.Assertions.*; import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; -import de.itvsh.kop.user.UserTestFactory; +import de.ozgcloud.user.UserTestFactory; class RecipientMapperTest { @@ -68,5 +69,10 @@ class RecipientMapperTest { assertThat(recipient.getEmail()).isEqualTo(StringUtils.EMPTY); } + + @Test + void shouldNotThrowExceptionOnNull() { + Assertions.assertDoesNotThrow(() -> mapper.toRecipient(null)); + } } } \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientRepositoryITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientRepositoryITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..8965f84dda768a818b79f252da112bba20de4d10 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientRepositoryITCase.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.recipient; + +import static de.ozgcloud.user.settings.NotificationsSendFor.*; +import static org.assertj.core.api.Assertions.*; + +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.settings.UserSettingsTestFactory; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.EnumSource.Mode; + +import de.ozgcloud.user.User; +import de.ozgcloud.user.common.MongoDbTestProfile; +import de.ozgcloud.user.settings.NotificationsSendFor; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +@QuarkusTest +@TestProfile(MongoDbTestProfile.class) +class RecipientRepositoryITCase { + + @Inject + RecipientRepository repository; + + @DisplayName("Find by organisationsEinheitId") + @Nested + class TestFindByOrganisationsEinheitId { + + @BeforeEach + void clearDb() { + repository.deleteAll(); + } + + @DisplayName("with given organisationsEinheitId") + @Nested + class TestWithGivenOrganisationsEinheitId { + + private static final User USER_NOTIFICATION_SEND_FOR_ALL = UserTestFactory.createBuilder().userSettings( + UserSettingsTestFactory.createBuilder().notificationsSendFor(ALL).build()) + .build(); + + @Test + void shouldReturnOnMatch() { + persist(USER_NOTIFICATION_SEND_FOR_ALL); + + var userList = repository.findByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); + + assertThat(userList).hasSize(1); + assertThat(userList.get(0)).usingRecursiveComparison().isEqualTo(USER_NOTIFICATION_SEND_FOR_ALL); + } + + @Test + void shouldReturnEmptyListOnNonMatch() { + persist(USER_NOTIFICATION_SEND_FOR_ALL); + + var userList = repository.findByOrganisationsEinheitId("nonMatch"); + + assertThat(userList).isEmpty(); + } + } + + @DisplayName("by notificationSendFor") + @Nested + class TestByNotificationSendFor { + + private static final User USER_NOTIFICATION_SEND_FOR_ALL = UserTestFactory.createBuilder().userSettings( + UserSettingsTestFactory.createBuilder().notificationsSendFor(ALL).build()) + .build(); + + @Test + void shouldReturnOnAll() { + persist(USER_NOTIFICATION_SEND_FOR_ALL); + + var userList = repository.findByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); + + assertThat(userList).hasSize(1); + assertThat(userList.get(0)).usingRecursiveComparison().isEqualTo(USER_NOTIFICATION_SEND_FOR_ALL); + } + + @ParameterizedTest + @EnumSource(mode = Mode.EXCLUDE, names = { "ALL" }) + void shouldNotReturnOn(NotificationsSendFor sendFor) { + var user = UserTestFactory.createBuilder().userSettings( + UserSettingsTestFactory.createBuilder().notificationsSendFor(sendFor).build()) + .build(); + persist(user); + + var userList = repository.findByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); + + assertThat(userList).isEmpty(); + } + } + + private void persist(User user) { + repository.persist(user); + } + } +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientRepositoryTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3200e8c2464894a70014f7099c1627ca584be093 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientRepositoryTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.recipient; + +import static de.ozgcloud.user.User.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.settings.NotificationsSendFor; +import io.quarkus.mongodb.panache.PanacheQuery; + +class RecipientRepositoryTest { + @Spy + RecipientRepository recipientRepository; + + @Mock + PanacheQuery<User> panacheQuery; + + @DisplayName("Test finding users by Organistationseinheit") + @Nested + class TestFindByOrganisationsEinheit { + private static final String QUERY = ORGANISATIONS_EINHEIT_IDS_FIELD + " = ?1 and " + NOTIFICATION_SEND_FOR_FIELD + " = ?2"; + + @Test + void shouldCallFind() { + when(panacheQuery.list()).thenReturn(List.of(UserTestFactory.create())); + doReturn(panacheQuery).when(recipientRepository).find(anyString(), anyString(), anyString()); + + recipientRepository.findByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); + + verify(recipientRepository).find(QUERY, UserTestFactory.ORGANISTATIONSEINHEITEN_ID, NotificationsSendFor.ALL.name()); + } + } +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientServiceTest.java similarity index 71% rename from user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientServiceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientServiceTest.java index e5a37bbed38e58de0d59d7ec4dc976d22b496d0c..23c85ad09bf3fd423777ee4cc474dabae4f7a769 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientServiceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.recipient; +package de.ozgcloud.user.recipient; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; @@ -34,20 +34,19 @@ import org.mockito.Mock; import com.cronutils.utils.StringUtils; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.UserTestFactory; -import de.itvsh.kop.user.common.errorhandling.FunctionalException; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.errorhandling.FunctionalException; class RecipientServiceTest { @InjectMocks RecipientService service; @Mock - UserService userService; + RecipientRepository repository; - @DisplayName("Find recipient by organisationsEinheitId") + @DisplayName("Find by organisationsEinheitId") @Nested - class TestFindRecipientByOrganisationsEinheitId { + class TestFindByOrganisationsEinheitId { private static final String EXPECTED_EXCEPTION_MESSAGE_TEMPLATE = "Functional error: " + RecipientService.MISSING_ORGANISATIONS_EINHEIT_ID_MESSAGE_TEMPLATE; @@ -57,7 +56,7 @@ class RecipientServiceTest { var expectedMessage = String.format(EXPECTED_EXCEPTION_MESSAGE_TEMPLATE, "null"); assertThatExceptionOfType(FunctionalException.class) - .isThrownBy(() -> service.findRecipientByOrganisationsEinheitId(null)) + .isThrownBy(() -> service.findByOrganisationsEinheitId(null)) .withMessageStartingWith(expectedMessage); } @@ -66,15 +65,15 @@ class RecipientServiceTest { var expectedMessage = String.format(EXPECTED_EXCEPTION_MESSAGE_TEMPLATE, StringUtils.EMPTY); assertThatExceptionOfType(FunctionalException.class) - .isThrownBy(() -> service.findRecipientByOrganisationsEinheitId(StringUtils.EMPTY)) + .isThrownBy(() -> service.findByOrganisationsEinheitId(StringUtils.EMPTY)) .withMessageStartingWith(expectedMessage); } @Test - void shouldCallUserService() { - service.findRecipientByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); + void shouldCallRepository() { + service.findByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); - verify(userService).findRecipientByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); + verify(repository).findByOrganisationsEinheitId(UserTestFactory.ORGANISTATIONSEINHEITEN_ID); } } } \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientTestFactory.java similarity index 84% rename from user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientTestFactory.java index f90a1b5ec07dc2327bd3c3d7e4a0902278fcc6fb..73c457d6f0e9bdb13999961b8de59cf922b387da 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/recipient/RecipientTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/recipient/RecipientTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,12 +21,12 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.recipient; +package de.ozgcloud.user.recipient; -import static de.itvsh.kop.user.UserTestFactory.*; +import static de.ozgcloud.user.UserTestFactory.*; -import de.itvsh.kop.user.UserTestFactory; -import de.itvsh.kop.user.grpc.recipient.GrpcFindRecipientRequest; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.grpc.recipient.GrpcFindRecipientRequest; public class RecipientTestFactory { diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsRepositoryITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsRepositoryITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..f5b7e9fe678d26e3b8bfc036a53fc0563538a8c5 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsRepositoryITCase.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.settings; + +import static org.assertj.core.api.Assertions.*; + +import jakarta.inject.Inject; + +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.MongoDbTestProfile; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +@QuarkusTest +@TestProfile(MongoDbTestProfile.class) +class UserSettingsRepositoryITCase { + + @Inject + UserSettingsRepository repository; + + @Nested + class TestUpdateByUserId { + + @BeforeEach + void beforeEach() { + repository.deleteAll(); + } + + @Test + void shouldUpdateUserSettings() { + var user = UserTestFactory.create(); + repository.persist(user); + + var settings = repository.updateByUserId( + user.getId().toString(), + UserSettings.builder().notificationsSendFor(NotificationsSendFor.ALL).build()); + + assertThat(settings) + .isPresent() + .map(UserSettings::getNotificationsSendFor) + .hasValue(NotificationsSendFor.ALL); + } + + @Test + void shouldReturnEmptyIfUserNotExist() { + var user = UserTestFactory.create(); + repository.persist(user); + + var settings = repository.updateByUserId( + new ObjectId().toString(), + UserSettings.builder().notificationsSendFor(NotificationsSendFor.ALL).build()); + + assertThat(settings).isEmpty(); + } + + @Test + void shouldReturnEmptyIfInvalidUserId() { + var user = UserTestFactory.create(); + repository.persist(user); + + var settings = repository.updateByUserId( + "wrong_id", + UserSettings.builder().notificationsSendFor(NotificationsSendFor.ALL).build()); + + assertThat(settings).isEmpty(); + } + + @Test + void shouldReturnEmptyIfUserIdNull() { + var user = UserTestFactory.create(); + repository.persist(user); + + var settings = repository.updateByUserId( + null, + UserSettings.builder().notificationsSendFor(NotificationsSendFor.ALL).build()); + + assertThat(settings).isEmpty(); + } + } + +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceAssemblerTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceAssemblerTest.java similarity index 93% rename from user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceAssemblerTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceAssemblerTest.java index 3a20f53af8af9fd114f4006285ec345f1eea37fb..d7a02b9cc95111044da50cfba1582da0cb52847f 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceAssemblerTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceAssemblerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -39,8 +39,8 @@ import org.mockito.Spy; import com.thedeanda.lorem.LoremIpsum; -import de.itvsh.kop.user.common.callcontext.CallContextUserTestFactory; -import de.itvsh.kop.user.common.callcontext.CurrentCallContextUserService; +import de.ozgcloud.user.common.callcontext.CallContextUserTestFactory; +import de.ozgcloud.user.common.callcontext.CurrentCallContextUserService; import io.quarkus.hal.HalEntityWrapper; class UserSettingsResourceAssemblerTest { diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceITCase.java similarity index 86% rename from user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceITCase.java index 38da0a0cf208f694827c2e1e2f5829ae2af79a13..66d7dbb57b21a0b9ffdf8310b01ecc6eb499977e 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,15 +21,16 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; -import static de.itvsh.kop.user.settings.UserSettings.*; -import static de.itvsh.kop.user.settings.UserSettingsResource.*; +import static de.ozgcloud.user.settings.UserSettings.*; +import static de.ozgcloud.user.settings.UserSettingsResource.*; import static io.restassured.RestAssured.*; import static org.hamcrest.CoreMatchers.*; -import javax.inject.Inject; -import javax.ws.rs.core.MediaType; +import de.ozgcloud.user.TestDatabaseUtils; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.MediaType; import org.apache.http.HttpStatus; import org.eclipse.microprofile.jwt.JsonWebToken; @@ -38,9 +39,8 @@ import org.junit.jupiter.api.Test; import com.mongodb.client.MongoClient; -import de.itvsh.kop.user.TestDatabaseUtils; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.UserTestFactory; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.UserTestFactory; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; @@ -68,6 +68,7 @@ class UserSettingsResourceITCase { var user = UserTestFactory.createBuilder() .externalId(jwt.getSubject()) + .keycloakUserId(jwt.getSubject()) .userSettings(new UserSettings(NotificationsSendFor.ALL)).build(); var savedUser = userService.save(user); diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceTest.java similarity index 76% rename from user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceTest.java index f3e3f10ee3f2a1d586bbfd1dae1108e3ef9c1ae9..f0ee57d9a9324e4b55b0e18ccab3d8e7f9c01090 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,15 +21,16 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.util.Optional; import java.util.UUID; -import javax.ws.rs.core.UriInfo; +import jakarta.ws.rs.core.UriInfo; import org.bson.types.ObjectId; import org.eclipse.microprofile.jwt.JsonWebToken; @@ -40,15 +41,15 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import org.springframework.util.ReflectionUtils; import com.thedeanda.lorem.LoremIpsum; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.UserTestFactory; -import de.itvsh.kop.user.common.errorhandling.AccessForbiddenException; -import de.itvsh.kop.user.common.errorhandling.FunctionalException; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.errorhandling.AccessForbiddenException; +import de.ozgcloud.user.common.errorhandling.FunctionalException; +import io.quarkus.hal.HalEntityWrapper; class UserSettingsResourceTest { @@ -74,6 +75,11 @@ class UserSettingsResourceTest { private final String USER_MANAGER_URL = LoremIpsum.getInstance().getUrl(); private final String USER_ID = UUID.randomUUID().toString(); + @BeforeEach + void setUp() { + resource.userManagerUrl = USER_MANAGER_URL; + } + @DisplayName("Get Usersettings") @Nested class TestGetUserSettings { @@ -84,8 +90,6 @@ class UserSettingsResourceTest { void mockAccess() { doNothing().when(resource).checkUserAccess(anyString()); when(userSettingsService.getByUserId(anyString())).thenReturn(userSettings); - - mockUserManagerUrl(); } @Test @@ -133,6 +137,30 @@ class UserSettingsResourceTest { } } + @Nested + class TestUserIdNotExist { + @BeforeEach + void mockAccess() { + doNothing().when(resource).checkUserAccess(anyString()); + } + + @Test + void shouldThrowFunctionalExceptionIfInvalidUserId() { + var user = UserSettingsTestFactory.create(); + assertThatExceptionOfType(FunctionalException.class) + .isThrownBy(() -> resource.updateUserSettings("wrong_id", user)) + .withMessageStartingWith("Functional error: Invalid user id"); + } + + @Test + void shouldThrowFunctionalExceptionIfEmptyUserId() { + var user = UserSettingsTestFactory.create(); + assertThatExceptionOfType(FunctionalException.class) + .isThrownBy(() -> resource.updateUserSettings("", user)) + .withMessageStartingWith("Functional error: Invalid user id"); + } + } + @DisplayName("with filled body") @Nested class TestFilledBody { @@ -140,13 +168,12 @@ class UserSettingsResourceTest { @BeforeEach void mockAccess() { doNothing().when(resource).checkUserAccess(anyString()); - when(userSettingsService.updateByUserId(any(UserSettings.class), anyString())).thenReturn(updatedUserSettings); - - mockUserManagerUrl(); + when(userSettingsService.updateByUserId(any(UserSettings.class), anyString())).thenReturn(Optional.of(updatedUserSettings)); } @Test void shouldCheckAccess() { + when(resourceAssembler.toResource(any(), anyString(), anyString())).thenReturn(new HalEntityWrapper(null)); resource.updateUserSettings(USER_ID, userSettings); verify(resource).checkUserAccess(USER_ID); @@ -154,13 +181,16 @@ class UserSettingsResourceTest { @Test void shouldCallUserSettingsService() { + when(resourceAssembler.toResource(any(), anyString(), anyString())).thenReturn(new HalEntityWrapper(null)); resource.updateUserSettings(USER_ID, userSettings); verify(userSettingsService).updateByUserId(userSettings, USER_ID); } @Test - void shouldCallResourceAssembler() { + void + shouldCallResourceAssembler() { + when(resourceAssembler.toResource(any(), anyString(), anyString())).thenReturn(new HalEntityWrapper(null)); resource.updateUserSettings(USER_ID, userSettings); verify(resourceAssembler).toResource(updatedUserSettings, USER_ID, USER_MANAGER_URL); @@ -168,12 +198,6 @@ class UserSettingsResourceTest { } } - private void mockUserManagerUrl() { - var field = ReflectionUtils.findField(UserSettingsResource.class, "userManagerUrl"); - field.setAccessible(true); - ReflectionUtils.setField(field, resource, USER_MANAGER_URL); - } - @DisplayName("Check User access") @Nested class TestCheckUserAccess { diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceTestProfile.java b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceTestProfile.java similarity index 86% rename from user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceTestProfile.java rename to user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceTestProfile.java index 4561905e6af0507c509e06b58f93b512da2d3839..5ebaeb9a56bf727f875856315563189296377556 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsResourceTestProfile.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsResourceTestProfile.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import java.util.Map; @@ -31,7 +31,8 @@ public class UserSettingsResourceTestProfile implements QuarkusTestProfile { @Override public Map<String, String> getConfigOverrides() { - return Map.of("quarkus.http.auth.permission.deny-api.enabled", "false", + return Map.of("quarkus.mongodb.devservices.enabled", "true", + "quarkus.http.auth.permission.deny-api.enabled", "false", "quarkus.http.auth.permission.deny-api.policy", "permit", "quarkus.http.auth.permission.permit-migration.enabled", "false", "quarkus.http.auth.permission.permit-migration.policy", "permit", diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsServiceITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsServiceITCase.java similarity index 77% rename from user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsServiceITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsServiceITCase.java index 73c1632b5ffbf8113f9d10a507ab39178d3c6222..a95e464d50eca0e65f8858dca98488f138b00354 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsServiceITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsServiceITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,21 +21,24 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import static org.assertj.core.api.Assertions.*; -import javax.inject.Inject; +import jakarta.inject.Inject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import de.itvsh.kop.user.UserTestFactory; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.MongoDbTestProfile; import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; @QuarkusTest +@TestProfile(MongoDbTestProfile.class) class UserSettingsServiceITCase { @Inject @@ -52,7 +55,7 @@ class UserSettingsServiceITCase { void fillDatabase() { repository.deleteAll(); - repository.persist(UserTestFactory.createWithId().toBuilder() + repository.persist(UserTestFactory.create().toBuilder() .userSettings(UserSettingsTestFactory.create()) .build()); } @@ -65,7 +68,10 @@ class UserSettingsServiceITCase { var savedUserSettings = service.updateByUserId(userSettingsToSave, UserTestFactory.ID.toHexString()); - assertThat(savedUserSettings.getNotificationsSendFor()).isEqualTo(NotificationsSendFor.ALL); + assertThat(savedUserSettings) + .isPresent() + .map(UserSettings::getNotificationsSendFor) + .hasValue(NotificationsSendFor.ALL); } } } diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsServiceTest.java similarity index 91% rename from user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsServiceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsServiceTest.java index 48a873ab8f6aa326de0ae92648e450a15af2f687..098cb3b5cca264ed0247f1c8536aadf0479d3355 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsServiceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -36,8 +36,8 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.UserTestFactory; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.UserTestFactory; class UserSettingsServiceTest { @@ -103,7 +103,7 @@ class UserSettingsServiceTest { @BeforeEach void mockUserService() { when(userService.getById(anyString())) - .thenReturn(UserTestFactory.createBuilder().userSettings(UserSettingsTestFactory.create()).build()); + .thenReturn(UserTestFactory.createBuilder().userSettings(null).build()); } @Test diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsTestFactory.java similarity index 92% rename from user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsTestFactory.java index 50bb9d2763e70ccb1d999c31d52cac0d9c1a54a0..31a44009e35988a31d635c5376c8300b7e964ca7 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/settings/UserSettingsTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/settings/UserSettingsTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.settings; +package de.ozgcloud.user.settings; public class UserSettingsTestFactory { diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncSchedulerITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncSchedulerITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..0bcfccc8f1d547877d9fb1cba773738c64978c61 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncSchedulerITCase.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.sync; + +import static de.ozgcloud.user.User.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Stream; + +import de.ozgcloud.user.TestDatabaseUtils; +import jakarta.inject.Inject; + +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoDatabase; + +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.MongoDbTestProfile; +import de.ozgcloud.user.common.lock.Lock; +import de.ozgcloud.user.keycloak.KeycloakUserRemoteService; +import io.quarkus.test.InjectMock; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.quarkus.test.junit.mockito.InjectSpy; + +@QuarkusTest +@TestProfile(MongoDbTestProfile.class) +class SyncSchedulerITCase { + private static final String USER_KEY = "User"; + private static final String LOCK_KEY = "Lock"; + + @InjectSpy + SyncScheduler scheduler; + + @Inject + MongoClient mongoClient; + + @Inject + UserService userService; + + @InjectMock + KeycloakUserRemoteService keycloakUserRemoteService; + + private MongoDatabase mongoDb; + + @BeforeEach + void init() { + when(keycloakUserRemoteService.getAllUsers()).thenReturn(Stream.of(UserTestFactory.create())); + + mongoDb = TestDatabaseUtils.getDatabase(mongoClient); + mongoDb.drop(); + + prepareData(); + } + + private void prepareData() { + User user1 = UserTestFactory.createBuilder().externalId("aaaaa").build(); + User user2 = UserTestFactory.createBuilder().externalId("bbbbb").build(); + persist(user1, user2); + when(keycloakUserRemoteService.getAllUsers()).thenReturn(Stream.of(user1, user2)); + } + + private void persist(User... users) { + Arrays.asList(users).forEach((user) -> { + userService.save(user); + }); + } + + @DisplayName("Test the SyncScheduler") + @Nested + class TestSyncScheduler { + + @Test + void shouldSync() { + scheduler.start(); + + var syncedUsers = mongoDb.getCollection(USER_KEY).find().iterator(); + var val = syncedUsers.next().getLong(LAST_SYNC_TIMESTAMP_FIELD); + assertThat(val).isGreaterThan(UserTestFactory.LAST_SYNC_TIMESTAMP); + } + + @Test + void shouldRemoveLockAfterSync() { + scheduler.start(); + + var count = mongoDb.getCollection(LOCK_KEY).countDocuments(); + assertThat(count).isZero(); + } + + @Test + void shouldNotRemoveExistingLock() { + insertLock(Instant.now().minus(30, ChronoUnit.MINUTES).toEpochMilli()); + + scheduler.start(); + + var count = mongoDb.getCollection(LOCK_KEY).countDocuments(); + assertThat(count).isOne(); + } + + @Test + void shouldRemoveExistingLockOlderOneDay() { + insertLock(Instant.now().minus(2, ChronoUnit.DAYS).toEpochMilli()); + + scheduler.start(); + + var count = mongoDb.getCollection(LOCK_KEY).countDocuments(); + assertThat(count).isZero(); + } + + @Test + void shouldSyncAfterRemovingLock() { + insertLock(Instant.now().minus(2, ChronoUnit.DAYS).toEpochMilli()); + + scheduler.start(); + + var count = mongoDb.getCollection(LOCK_KEY).countDocuments(); + assertThat(count).isZero(); + + scheduler.start(); + + var syncedUsers = mongoDb.getCollection(USER_KEY).find().iterator(); + var val = syncedUsers.next().getLong(LAST_SYNC_TIMESTAMP_FIELD); + assertThat(val).isGreaterThan(UserTestFactory.LAST_SYNC_TIMESTAMP); + } + + private void insertLock(long timestamp) { + var lockDoc = new Document(Map.of(Lock.TIMESTAMP_FIELD, timestamp)); + mongoDb.getCollection(LOCK_KEY).insertOne(lockDoc); + } + + } + +} diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncSchedulerTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncSchedulerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5fd50c0409104eca9fdc97a5b1d0c6414b3162d7 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncSchedulerTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.sync; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.time.Instant; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.user.common.lock.Lock; +import de.ozgcloud.user.common.lock.LockService; + +class SyncSchedulerTest { + + @Spy + @InjectMocks + private SyncScheduler scheduler; + @Mock + private SyncService service; + @Mock + private LockService syncLockService; + + @DisplayName("Start Scheduler") + @Nested + class TestStart { + + @BeforeEach + void init() { + when(syncLockService.isNotLocked()).thenReturn(true); + when(syncLockService.lockCollection()).thenReturn(Lock.builder().timestamp(Instant.now().toEpochMilli()).build()); + } + + @Test + void shouldDoSyncIfNotLocked() { + scheduler.start(); + + verify(service).sync(anyLong()); + } + + @Test + void shouldCallLockServiceLockCollection() { + scheduler.start(); + + verify(syncLockService).lockCollection(); + } + + @Test + void shouldUnlockLock() { + scheduler.start(); + + verify(syncLockService).unlock(); + } + + @Test + void shouldUnlockLockOnException() { + doThrow(new RuntimeException()).when(service).sync(anyLong()); + + try { + scheduler.start(); + } catch (Exception e) { + verify(syncLockService).unlock(); + } + } + } + + @DisplayName("If Locked") + @Nested + class TestIfLocked { + + @BeforeEach + void mockTimeStamp() { + when(syncLockService.isNotLocked()).thenReturn(false); + when(syncLockService.isLockOlderThanADay()).thenReturn(true); + + } + + @Test + void shouldNotDoSync() { + scheduler.start(); + + verify(service, never()).sync(anyLong()); + } + + @Test + void shouldCheckIfLockIsOlderThanADay() { + scheduler.start(); + + verify(syncLockService).isLockOlderThanADay(); + } + + @Test + void shouldRemoveLockWhenLockIsOlderThanADay() { + scheduler.start(); + + verify(syncLockService).unlock(); + } + } +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncServiceITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncServiceITCase.java similarity index 69% rename from user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncServiceITCase.java rename to user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncServiceITCase.java index 9bd639513506cdc884bdd3f9f8b2e2f3d18960aa..8fcea0538fef25542c52d47da180ad766ff0d824 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncServiceITCase.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncServiceITCase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,16 +21,19 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.sync; +package de.ozgcloud.user.sync; -import static de.itvsh.kop.user.User.*; +import static de.ozgcloud.user.User.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.time.Instant; import java.util.Arrays; import java.util.List; +import java.util.stream.Stream; -import javax.inject.Inject; +import de.ozgcloud.user.TestDatabaseUtils; +import jakarta.inject.Inject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -38,21 +41,23 @@ import org.junit.jupiter.api.Test; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; -import de.itvsh.kop.user.TestDatabaseUtils; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.UserTestFactory; -import de.itvsh.kop.user.keycloak.KeycloakUserRemoteService; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.MongoDbTestProfile; +import de.ozgcloud.user.keycloak.KeycloakUserRemoteService; +import io.quarkus.test.InjectMock; import io.quarkus.test.junit.QuarkusTest; -import io.quarkus.test.junit.mockito.InjectMock; +import io.quarkus.test.junit.TestProfile; import io.quarkus.test.junit.mockito.InjectSpy; @QuarkusTest +@TestProfile(MongoDbTestProfile.class) class SyncServiceITCase { private static final String USER_KEY = "User"; @InjectSpy - private SyncService service; + SyncService service; @Inject MongoClient mongoClient; @@ -61,13 +66,13 @@ class SyncServiceITCase { UserService userService; @InjectMock - private KeycloakUserRemoteService keycloakUserRemoteService; + KeycloakUserRemoteService keycloakUserRemoteService; private MongoDatabase mongoDb; @BeforeEach void init() { - when(keycloakUserRemoteService.getAllUsers()).thenReturn(List.of(UserTestFactory.create()).stream()); + when(keycloakUserRemoteService.getAllUsers()).thenReturn(Stream.of(UserTestFactory.create())); mongoDb = TestDatabaseUtils.getDatabase(mongoClient); mongoDb.drop(); @@ -77,11 +82,11 @@ class SyncServiceITCase { void shouldMarkNotSyncUsersAsDeleted() { prepareData(); - service.sync(); + service.sync(Instant.now().toEpochMilli()); prepareKeycloakUserWithoutRoles(); - service.sync(); + service.sync(Instant.now().toEpochMilli()); var syncedUser = mongoDb.getCollection(USER_KEY).find().first(); assertThat(syncedUser.getBoolean(DELETED_FIELD)).isTrue(); @@ -89,14 +94,14 @@ class SyncServiceITCase { private void prepareKeycloakUserWithoutRoles() { User user = UserTestFactory.create(); - when(keycloakUserRemoteService.getAllUsers()).thenReturn(List.of(user.toBuilder().roles(List.of()).build()).stream()); + when(keycloakUserRemoteService.getAllUsers()).thenReturn(Stream.of(user.toBuilder().roles(List.of()).build())); } @Test void shouldSync() { prepareData(); - service.sync(); + service.sync(Instant.now().toEpochMilli()); var syncedUsers = mongoDb.getCollection(USER_KEY).find().iterator(); var val = syncedUsers.next().getLong(LAST_SYNC_TIMESTAMP_FIELD); @@ -107,7 +112,7 @@ class SyncServiceITCase { User user1 = UserTestFactory.createBuilder().externalId("aaaaa").build(); User user2 = UserTestFactory.createBuilder().externalId("bbbbb").build(); persist(user1, user2); - when(keycloakUserRemoteService.getAllUsers()).thenReturn(List.of(user1, user2).stream()); + when(keycloakUserRemoteService.getAllUsers()).thenReturn(Stream.of(user1, user2)); } private void persist(User... users) { diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncServiceTest.java similarity index 54% rename from user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncServiceTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncServiceTest.java index 44b57ee8b1023c2d21b2113f530020b2b5e109f4..a6caa28b9ea8f858d73391dfdba95efa7e3cb90a 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/sync/SyncServiceTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/sync/SyncServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.sync; +package de.ozgcloud.user.sync; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -30,7 +30,6 @@ import static org.mockito.Mockito.*; import java.time.Instant; import java.util.stream.Stream; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -40,13 +39,11 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserService; -import de.itvsh.kop.user.UserTestFactory; -import de.itvsh.kop.user.common.lock.Lock; -import de.itvsh.kop.user.common.lock.LockService; -import de.itvsh.kop.user.common.lock.LockTestFactory; -import de.itvsh.kop.user.keycloak.KeycloakUserRemoteService; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.lock.LockService; +import de.ozgcloud.user.keycloak.KeycloakUserRemoteService; class SyncServiceTest { @@ -61,49 +58,10 @@ class SyncServiceTest { @Mock private UserService userService; - @DisplayName("Sync") - @Nested - class TestSync { - - @DisplayName("With successful lock creation") - @Nested - class TestWithSuccessfulLockCreation { - - private final Lock lock = LockTestFactory.create(); - - @BeforeEach - void mockLock() { - when(lockService.getByTimestamp(any(Instant.class))).thenReturn(lock); - } - - @Test - void shouldCallLockServiceLock() { - service.sync(); - - verify(lockService).lock(any(Instant.class)); - } - - @Test - void shouldCallLockServiceFind() { - service.sync(); - - verify(lockService).getByTimestamp(any(Instant.class)); - } - - @Test - void shouldDoSync() { - service.sync(); - - verify(service).doSync(lock); - } - } - } - @DisplayName("Do the sync") @Nested class TestDoSync { - private final Lock lock = LockTestFactory.create(); private final User user = UserTestFactory.create(); @Captor @@ -112,54 +70,42 @@ class SyncServiceTest { @DisplayName("should get all users from keycloak") @Test void shouldCallKeycloakService() { - service.doSync(lock); + service.sync(Instant.now().toEpochMilli()); verify(keycloakService).getAllUsers(); } @Test - void shouldCallUserServiceSave() { + void shouldCallSaveAndSync() { + var syncTimestamp = Instant.now().toEpochMilli(); + var updatedUser = UserTestFactory.createBuilder().lastSyncTimestamp(syncTimestamp).build(); when(keycloakService.getAllUsers()).thenReturn(Stream.of(user, user)); + doReturn(updatedUser).when(service).addLastSyncTimestamp(user, syncTimestamp); - service.doSync(lock); + service.sync(syncTimestamp); - verify(userService, times(2)).save(any(User.class)); + verify(userService, times(2)).saveAndSync(updatedUser); } @Test void shouldAddLasSyncToUser() { when(keycloakService.getAllUsers()).thenReturn(Stream.of(user)); + when(userService.saveAndSync(any())).thenReturn(user); + + var timestamp = Instant.now().toEpochMilli(); - service.doSync(lock); + service.sync(timestamp); - verify(userService).save(userCaptor.capture()); - assertThat(userCaptor.getValue().getLastSyncTimestamp()).isEqualTo(lock.getTimestamp()); + verify(userService).saveAndSync(userCaptor.capture()); + assertThat(userCaptor.getValue().getLastSyncTimestamp()).isEqualTo(timestamp); } @DisplayName("should mark all unsynced users as deleted") @Test void shouldMarkUnsyncedUsersAsDeleted() { - service.doSync(lock); - - verify(userService).markUnsyncedUsersAsDeleted(lock.getTimestamp()); - } + service.sync(Instant.now().toEpochMilli()); - @Test - void shouldUnlockLock() { - service.doSync(lock); - - verify(lockService).unlock(lock); - } - - @Test - void shouldUnlockLockOnException() { - when(keycloakService.getAllUsers()).thenThrow(new RuntimeException()); - - try { - service.doSync(lock); - } catch (Exception e) { - verify(lockService).unlock(lock); - } + verify(userService).markUnsyncedUsersAsDeleted(anyLong()); } } } \ No newline at end of file diff --git a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/KeycloakClientException.java b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcDeleteInactiveUserRequestTestFactory.java similarity index 64% rename from user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/KeycloakClientException.java rename to user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcDeleteInactiveUserRequestTestFactory.java index 36ac5c5f33c54ad7c6b6bade0f67477ff6858028..c4f6f17851e80587f966c47c4951f01e999b7ac3 100644 --- a/user-manager-server/src/main/java/de/itvsh/kop/user/common/errorhandling/KeycloakClientException.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcDeleteInactiveUserRequestTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,15 +21,19 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.common.errorhandling; +package de.ozgcloud.user.userprofile; -public class KeycloakClientException extends TechnicalException { +import de.ozgcloud.user.UserTestFactory; - private static final long serialVersionUID = 1L; +public class GrpcDeleteInactiveUserRequestTestFactory { - private static final String MESSAGE_TEMPLATE = "Access Denied for admin user: %s, realm: %s, url: %s"; + public static final String USER_ID = UserTestFactory.ID_STR; - public KeycloakClientException(String user, String realm, String url, Throwable cause) { - super(String.format(MESSAGE_TEMPLATE, user, realm, url), cause); + public static GrpcDeleteInactiveUserRequest create() { + return createBuilder().build(); } -} \ No newline at end of file + + public static GrpcDeleteInactiveUserRequest.Builder createBuilder() { + return GrpcDeleteInactiveUserRequest.newBuilder().setUserId(USER_ID); + } +} diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcGetInactiveUserIdsResponseTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcGetInactiveUserIdsResponseTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..775ca65022bd4ebf74add0fc44ffbafbafba7bd5 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcGetInactiveUserIdsResponseTestFactory.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.userprofile; + +class GrpcGetInactiveUserIdsResponseTestFactory { + + public static GrpcFindInactiveUserIdsResponse create() { + return createBuilder().build(); + } + + public static GrpcFindInactiveUserIdsResponse.Builder createBuilder() { + return GrpcFindInactiveUserIdsResponse.newBuilder(); + } +} diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcUserProfileIdTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcUserProfileIdTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..a7b8546e8805747def4512c6700caf156621021e --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcUserProfileIdTestFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.userprofile; + +import de.ozgcloud.user.UserTestFactory; + +class GrpcUserProfileIdTestFactory { + + public static GrpcUserProfileId create() { + return createBuilder().build(); + } + + public static GrpcUserProfileId.Builder createBuilder() { + return GrpcUserProfileId.newBuilder().setId(UserTestFactory.ID_STR); + } +} diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/GrpcUserProfileTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcUserProfileTestFactory.java similarity index 89% rename from user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/GrpcUserProfileTestFactory.java rename to user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcUserProfileTestFactory.java index 1ebb5779b5959aeb1efe4e37cab57b02009c1918..d36328a47b707ffa28f18b0a81b3044b2d594fbb 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/GrpcUserProfileTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/GrpcUserProfileTestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,9 +21,9 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.userprofile; +package de.ozgcloud.user.userprofile; -import de.itvsh.kop.user.UserTestFactory; +import de.ozgcloud.user.UserTestFactory; public class GrpcUserProfileTestFactory { diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileGrpcServiceITCase.java b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileGrpcServiceITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..2cc4a42a093fb96ac2f1daa9c029ba696c64fc92 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileGrpcServiceITCase.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.userprofile; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.google.rpc.Code; + +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.UserTestFactory; +import de.ozgcloud.user.common.callcontext.CallContextInterceptorTestFactory; +import de.ozgcloud.user.grpc.userprofile.UserProfileServiceGrpc.UserProfileServiceBlockingStub; +import io.grpc.StatusRuntimeException; +import io.quarkus.grpc.GrpcClient; +import io.quarkus.test.InjectMock; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +class UserProfileGrpcServiceITCase { + + @GrpcClient + UserProfileServiceBlockingStub serviceStub; + + @InjectMock + UserService userService; + + @DisplayName("Get by id") + @Nested + class TestGetById { + + private GrpcGetUserProfileRequest request = GrpcGetUserProfileRequest.newBuilder().setUserId("73").build(); + + @Test + void shouldReturnUserProfile() { + when(userService.getById(anyString())).thenReturn(UserTestFactory.create()); + + var response = serviceStub.withInterceptors(CallContextInterceptorTestFactory.createClientInterceptorWithMetadata()).getById(request); + + assertThat(response.getUserProfile().getFirstName()).isEqualTo(UserTestFactory.FIRST_NAME); + } + + @Test + void shouldReturnStatusRuntimeExceptionOnMissingClientName() { + var preparedServiceStub = serviceStub.withInterceptors(CallContextInterceptorTestFactory.createClientInterceptor()); + + assertThatThrownBy(() -> preparedServiceStub.getById(request)) + .isInstanceOf(StatusRuntimeException.class) + .hasMessageContaining("Missing client name in grpc header for request") + .extracting(ex -> ((StatusRuntimeException) ex).getStatus().getCode().value()).isEqualTo(Code.PERMISSION_DENIED_VALUE); + } + } +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileGrpcServiceTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileGrpcServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6dcceb911e3a61b8bd7719ec6b4bcbeb1e651e59 --- /dev/null +++ b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileGrpcServiceTest.java @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.user.userprofile; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.UUID; +import java.util.stream.Stream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserService; +import de.ozgcloud.user.UserTestFactory; +import io.grpc.stub.StreamObserver; +import lombok.SneakyThrows; + +class UserProfileGrpcServiceTest { + + @Spy + @InjectMocks + private UserProfileGrpcService grpcService; + @Mock + private UserService userService; + + @Mock + private UserProfileMapper mapper; + + @DisplayName("Get userprofile by id") + @Nested + class TestGetUserProfileById { + + @Mock + private StreamObserver<GrpcGetUserProfileResponse> streamObserver; + + @Captor + private ArgumentCaptor<GrpcGetUserProfileResponse> responseCaptor; + + private final User userProfile = UserTestFactory.create(); + private final String userId = UUID.randomUUID().toString(); + private final GrpcGetUserProfileRequest request = GrpcGetUserProfileRequest.newBuilder().setUserId(userId).build(); + private final GrpcUserProfile grpcUserProfile = GrpcUserProfileTestFactory.create(); + + @BeforeEach + void init() { + when(userService.getById(anyString())).thenReturn(userProfile); + when(mapper.mapTo(any())).thenReturn(grpcUserProfile); + } + + @Test + void shouldCallService() { + callGetById(); + + verify(userService).getById(userId); + } + + @Test + void shouldMapUserProfile() { + callGetById(); + + verify(mapper).mapTo(userProfile); + } + + @Test + void shouldCallOnNext() { + callGetById(); + + verify(streamObserver).onNext(any(GrpcGetUserProfileResponse.class)); + } + + @Test + void shouldCallOnCompleted() { + callGetById(); + + verify(streamObserver).onCompleted(); + } + + @Test + void shouldReturnUserProfile() { + callGetById(); + + verify(streamObserver).onNext(responseCaptor.capture()); + assertThat(responseCaptor.getValue().getUserProfile().getFirstName()).isEqualTo(UserTestFactory.FIRST_NAME); + assertThat(responseCaptor.getValue().getUserProfile().getLastName()).isEqualTo(UserTestFactory.LAST_NAME); + } + + @SneakyThrows + private void callGetById() { + grpcService.getById(request, streamObserver); + } + } + + @Nested + class TestGetByExternalId { + + private static final String EXTERNAL_ID = "42"; + + @Mock + private StreamObserver<GrpcGetUserProfileResponse> streamObserver; + + @Captor + private ArgumentCaptor<GrpcGetUserProfileResponse> responseCaptor; + + @Test + void shouldCallService() { + when(mapper.mapTo(any())).thenReturn(GrpcUserProfileTestFactory.create()); + grpcService.getByExternalId(GrpcGetUserProfileRequest.newBuilder().setUserId(EXTERNAL_ID).build(), streamObserver); + + verify(userService).findByExternalId(EXTERNAL_ID); + } + + @Test + void shouldEmitUserProfile() { + when(mapper.mapTo(any())).thenReturn(GrpcUserProfileTestFactory.create()); + grpcService.getByExternalId(GrpcGetUserProfileRequest.newBuilder().setUserId(EXTERNAL_ID).build(), streamObserver); + + verify(streamObserver).onNext(any()); + } + + @Test + void shouldCompleteResponse() { + when(mapper.mapTo(any())).thenReturn(GrpcUserProfileTestFactory.create()); + grpcService.getByExternalId(GrpcGetUserProfileRequest.newBuilder().setUserId(EXTERNAL_ID).build(), streamObserver); + + verify(streamObserver).onCompleted(); + } + } + + @Nested + class TestBuildGrpcGetInactiveUserIdsResponse { + + @Test + void shouldBuildResponse() { + var response = grpcService.buildGrpcGetInactiveUserIdsResponse(Stream.of(UserTestFactory.ID_STR)); + + assertThat(response.getUserProfileIdsList()).first().extracting(GrpcUserProfileId::getId).isEqualTo(UserTestFactory.ID_STR); + } + + } + + @Nested + class TestFindInactiveUserIds { + + @Mock + private StreamObserver<GrpcFindInactiveUserIdsResponse> streamObserver; + + private GrpcFindInactiveUserIdsResponse grpcResponse = GrpcGetInactiveUserIdsResponseTestFactory.create(); + + private final Stream<String> userIds = Stream.of(UserTestFactory.ID_STR); + + @BeforeEach + void init() { + when(userService.findAllInactiveUserIds()).thenReturn(userIds); + doReturn(grpcResponse).when(grpcService).buildGrpcGetInactiveUserIdsResponse(userIds); + } + + @Test + void shouldCallService() { + callService(); + + verify(userService).findAllInactiveUserIds(); + } + + @Test + void shouldBuildResponse() { + callService(); + + verify(grpcService).buildGrpcGetInactiveUserIdsResponse(userIds); + } + + @Test + void shouldCallOnNext() { + callService(); + + verify(streamObserver).onNext(grpcResponse); + } + + @Test + void shouldCompleteResponse() { + callService(); + + verify(streamObserver).onCompleted(); + } + + private void callService() { + grpcService.findInactiveUserIds(GrpcFindInactiveUserIdsRequest.newBuilder().build(), streamObserver); + } + } + + @Nested + class TestDeleteInactiveUser { + + @Mock + private StreamObserver<GrpcDeleteInactiveUserResponse> streamObserver; + + @Test + void shouldCallService() { + callService(); + + verify(userService).deleteInactive(GrpcDeleteInactiveUserRequestTestFactory.USER_ID); + } + + @Test + void shouldCallOnNext() { + callService(); + + verify(streamObserver).onNext(GrpcDeleteInactiveUserResponse.newBuilder().build()); + } + + @Test + void shouldCompleteResponse() { + callService(); + + verify(streamObserver).onCompleted(); + } + + private void callService() { + grpcService.deleteInactiveUser(GrpcDeleteInactiveUserRequestTestFactory.create(), streamObserver); + } + } +} \ No newline at end of file diff --git a/user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/UserProfileMapperTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileMapperTest.java similarity index 73% rename from user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/UserProfileMapperTest.java rename to user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileMapperTest.java index 4b00ecff7de61ff31f80086994e2d7a8dc25f06c..a1fcc8defaa2dbd41d3c78894f116bb9f3170679 100644 --- a/user-manager-server/src/test/java/de/itvsh/kop/user/userprofile/UserProfileMapperTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/userprofile/UserProfileMapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.itvsh.kop.user.userprofile; +package de.ozgcloud.user.userprofile; import static org.assertj.core.api.Assertions.*; @@ -31,8 +31,8 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; -import de.itvsh.kop.user.User; -import de.itvsh.kop.user.UserTestFactory; +import de.ozgcloud.user.User; +import de.ozgcloud.user.UserTestFactory; class UserProfileMapperTest { @@ -44,18 +44,36 @@ class UserProfileMapperTest { @Test void shouldMapFirstName() { - var userProfile = mapper.mapTo(UserTestFactory.create()); + var userProfile = map(); assertThat(userProfile.getFirstName()).isEqualTo(UserTestFactory.FIRST_NAME); } @Test void shouldMapLastName() { - var userProfile = mapper.mapTo(UserTestFactory.create()); + var userProfile = map(); assertThat(userProfile.getLastName()).isEqualTo(UserTestFactory.LAST_NAME); } + @Test + void shouldMapEMail() { + var userProfile = map(); + + assertThat(userProfile.getEmail()).isEqualTo(UserTestFactory.EMAIL); + } + + @Test + void shouldMapId() { + var userProfile = map(); + + assertThat(userProfile.getId()).isEqualTo(UserTestFactory.ID.toString()); + } + + private GrpcUserProfile map() { + return mapper.mapTo(UserTestFactory.create()); + } + @Test void shouldProceedWithNull() { Assertions.assertDoesNotThrow(() -> mapper.mapTo(User.builder().build())); diff --git a/user-manager-server/src/test/resources/META-INF/keycloak/dev-realm.json b/user-manager-server/src/test/resources/META-INF/keycloak/dev-realm.json deleted file mode 100644 index f20238e3e85e0199d93fbb4c418570d879759775..0000000000000000000000000000000000000000 --- a/user-manager-server/src/test/resources/META-INF/keycloak/dev-realm.json +++ /dev/null @@ -1,3913 +0,0 @@ -[ { - "id" : "1964b9ab-c6d6-42cf-8bdb-c9a76523a57f", - "realm" : "dev", - "displayName" : "", - "displayNameHtml" : "", - "notBefore" : 0, - "defaultSignatureAlgorithm" : "RS256", - "revokeRefreshToken" : false, - "refreshTokenMaxReuse" : 0, - "accessTokenLifespan" : 300, - "accessTokenLifespanForImplicitFlow" : 900, - "ssoSessionIdleTimeout" : 1800, - "ssoSessionMaxLifespan" : 36000, - "ssoSessionIdleTimeoutRememberMe" : 0, - "ssoSessionMaxLifespanRememberMe" : 0, - "offlineSessionIdleTimeout" : 2592000, - "offlineSessionMaxLifespanEnabled" : false, - "offlineSessionMaxLifespan" : 5184000, - "clientSessionIdleTimeout" : 0, - "clientSessionMaxLifespan" : 0, - "clientOfflineSessionIdleTimeout" : 0, - "clientOfflineSessionMaxLifespan" : 0, - "accessCodeLifespan" : 60, - "accessCodeLifespanUserAction" : 300, - "accessCodeLifespanLogin" : 1800, - "actionTokenGeneratedByAdminLifespan" : 43200, - "actionTokenGeneratedByUserLifespan" : 300, - "oauth2DeviceCodeLifespan" : 600, - "oauth2DevicePollingInterval" : 5, - "enabled" : true, - "sslRequired" : "none", - "registrationAllowed" : false, - "registrationEmailAsUsername" : false, - "rememberMe" : false, - "verifyEmail" : false, - "loginWithEmailAllowed" : true, - "duplicateEmailsAllowed" : false, - "resetPasswordAllowed" : false, - "editUsernameAllowed" : false, - "bruteForceProtected" : false, - "permanentLockout" : false, - "maxFailureWaitSeconds" : 900, - "minimumQuickLoginWaitSeconds" : 60, - "waitIncrementSeconds" : 60, - "quickLoginCheckMilliSeconds" : 1000, - "maxDeltaTimeSeconds" : 43200, - "failureFactor" : 30, - "roles" : { - "realm" : [ { - "id" : "ccc97175-19ca-45ec-a64d-438b63359092", - "name" : "offline_access", - "description" : "${role_offline-access}", - "composite" : false, - "clientRole" : false, - "containerId" : "1964b9ab-c6d6-42cf-8bdb-c9a76523a57f", - "attributes" : { } - }, { - "id" : "5e95a9f9-eaaf-46f2-8050-c749de58d2b9", - "name" : "default-roles-kop-apitest-verw", - "description" : "${role_default-roles}", - "composite" : true, - "composites" : { - "realm" : [ "offline_access", "uma_authorization" ], - "client" : { - "account" : [ "view-profile", "manage-account" ] - } - }, - "clientRole" : false, - "containerId" : "1964b9ab-c6d6-42cf-8bdb-c9a76523a57f", - "attributes" : { } - }, { - "id" : "6ea8c433-be43-475c-818b-1fd269da77e6", - "name" : "uma_authorization", - "description" : "${role_uma_authorization}", - "composite" : false, - "clientRole" : false, - "containerId" : "1964b9ab-c6d6-42cf-8bdb-c9a76523a57f", - "attributes" : { } - } ], - "client" : { - "realm-management" : [ { - "id" : "9e29328f-4cf1-411b-bbe6-ee19f527aec4", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "realm-management" : [ "query-clients" ] - } - }, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "85d15b74-e658-4cc0-9195-5fedff3e122a", - "name" : "query-users", - "description" : "${role_query-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "ed386119-807b-4074-b1c4-e3ed4e0498d3", - "name" : "view-authorization", - "description" : "${role_view-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "ea91197e-dfcd-4a09-b251-b7735a48a51d", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "a906d81e-6648-4b7e-8b6b-fe6ae3a8aa6c", - "name" : "view-realm", - "description" : "${role_view-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "aff1bccc-3716-425a-bd13-5af791d7b5f1", - "name" : "manage-events", - "description" : "${role_manage-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "9b9f6be3-5171-4d4c-ae81-6f1293e02112", - "name" : "query-groups", - "description" : "${role_query-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "cbb6fa87-ebe3-403e-9ea9-1003a97ffa07", - "name" : "realm-admin", - "description" : "${role_realm-admin}", - "composite" : true, - "composites" : { - "client" : { - "realm-management" : [ "view-clients", "query-users", "view-authorization", "manage-identity-providers", "view-realm", "query-groups", "manage-events", "manage-users", "query-clients", "view-users", "impersonation", "create-client", "view-events", "manage-clients", "view-identity-providers", "query-realms", "manage-realm", "manage-authorization" ] - } - }, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "599fedc0-c913-44d3-b90d-ae9e28d1e411", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "571ca0ed-b44f-4669-aa08-e097a4b3772e", - "name" : "query-clients", - "description" : "${role_query-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "c0bc2b45-2a3a-4608-a615-4554889c0f39", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "realm-management" : [ "query-users", "query-groups" ] - } - }, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "3bb7c458-44bb-490a-a961-725a7f62d108", - "name" : "impersonation", - "description" : "${role_impersonation}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "4338efa1-28e5-46ed-b7d3-faa5af778861", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "57bdcfc7-05db-4ae4-892b-9d3996bae0bc", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "049ddb7a-a0ac-4b33-8825-b23627d2755b", - "name" : "manage-clients", - "description" : "${role_manage-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "b4bf7daf-2a6c-4ef8-aa2d-15c948d49066", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "0da10f4a-d086-49c5-976a-dba273a13755", - "name" : "query-realms", - "description" : "${role_query-realms}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "8d41f3df-1f41-453d-8170-b0066e9020f3", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - }, { - "id" : "4e1bd596-4a2c-4024-aa35-ad13d06ace28", - "name" : "manage-realm", - "description" : "${role_manage-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "attributes" : { } - } ], - "goofy" : [ { - "id" : "598141f9-eb6f-4adb-8f6d-d21e1db7abfe", - "name" : "VERWALTUNG_USER", - "composite" : false, - "clientRole" : true, - "containerId" : "73cec8d5-6e03-4589-86eb-8f58e758d730", - "attributes" : { } - }, { - "id" : "7a829180-2acc-47a4-a82a-13d1807559f2", - "name" : "VERWALTUNG_POSTSTELLE", - "composite" : false, - "clientRole" : true, - "containerId" : "73cec8d5-6e03-4589-86eb-8f58e758d730", - "attributes" : { } - } ], - "security-admin-console" : [ ], - "admin-cli" : [ ], - "account-console" : [ ], - "broker" : [ { - "id" : "72ce150c-45af-485d-9fc3-f43877fc1949", - "name" : "read-token", - "description" : "${role_read-token}", - "composite" : false, - "clientRole" : true, - "containerId" : "8333205e-d5a6-4d2b-9de9-bd07c9c8579c", - "attributes" : { } - } ], - "account" : [ { - "id" : "ca5a931e-679b-41ac-949e-5468c68a4015", - "name" : "manage-consent", - "description" : "${role_manage-consent}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "view-consent" ] - } - }, - "clientRole" : true, - "containerId" : "bf8f95db-6141-419f-adab-7e951659d989", - "attributes" : { } - }, { - "id" : "8ac3ab69-c53a-49e0-8c70-8ec6bf47008e", - "name" : "view-profile", - "description" : "${role_view-profile}", - "composite" : false, - "clientRole" : true, - "containerId" : "bf8f95db-6141-419f-adab-7e951659d989", - "attributes" : { } - }, { - "id" : "788bd93a-6208-4135-88f2-3be3ef5ed7b4", - "name" : "manage-account", - "description" : "${role_manage-account}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "manage-account-links" ] - } - }, - "clientRole" : true, - "containerId" : "bf8f95db-6141-419f-adab-7e951659d989", - "attributes" : { } - }, { - "id" : "dafbb791-d2b4-47bb-b33d-d212a90792bb", - "name" : "view-consent", - "description" : "${role_view-consent}", - "composite" : false, - "clientRole" : true, - "containerId" : "bf8f95db-6141-419f-adab-7e951659d989", - "attributes" : { } - }, { - "id" : "e5bca3d3-b9ae-4e25-b2be-93a11da4ad64", - "name" : "delete-account", - "description" : "${role_delete-account}", - "composite" : false, - "clientRole" : true, - "containerId" : "bf8f95db-6141-419f-adab-7e951659d989", - "attributes" : { } - }, { - "id" : "a3f2f757-383f-4092-a148-9fb1b9ad1867", - "name" : "manage-account-links", - "description" : "${role_manage-account-links}", - "composite" : false, - "clientRole" : true, - "containerId" : "bf8f95db-6141-419f-adab-7e951659d989", - "attributes" : { } - }, { - "id" : "60db677c-b10e-4b77-8fa9-3f5148cee2ae", - "name" : "view-applications", - "description" : "${role_view-applications}", - "composite" : false, - "clientRole" : true, - "containerId" : "bf8f95db-6141-419f-adab-7e951659d989", - "attributes" : { } - } ] - } - }, - "groups" : [ { - "id" : "52be1d46-1bae-4f00-922e-02efd6838dcf", - "name" : "Ordnungsamt", - "path" : "/Ordnungsamt", - "attributes" : { - "organisationsEinheitId" : [ "9030229" ] - }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ ] - } ], - "defaultRole" : { - "id" : "5e95a9f9-eaaf-46f2-8050-c749de58d2b9", - "name" : "default-roles-kop-apitest-verw", - "description" : "${role_default-roles}", - "composite" : true, - "clientRole" : false, - "containerId" : "1964b9ab-c6d6-42cf-8bdb-c9a76523a57f" - }, - "requiredCredentials" : [ "password" ], - "otpPolicyType" : "totp", - "otpPolicyAlgorithm" : "HmacSHA1", - "otpPolicyInitialCounter" : 0, - "otpPolicyDigits" : 6, - "otpPolicyLookAheadWindow" : 1, - "otpPolicyPeriod" : 30, - "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ], - "webAuthnPolicyRpEntityName" : "keycloak", - "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyRpId" : "", - "webAuthnPolicyAttestationConveyancePreference" : "not specified", - "webAuthnPolicyAuthenticatorAttachment" : "not specified", - "webAuthnPolicyRequireResidentKey" : "not specified", - "webAuthnPolicyUserVerificationRequirement" : "not specified", - "webAuthnPolicyCreateTimeout" : 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyAcceptableAaguids" : [ ], - "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyPasswordlessRpId" : "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", - "webAuthnPolicyPasswordlessCreateTimeout" : 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], - "users" : [ { - "id" : "26c16229-0f37-40ce-b44d-27bf1b63141a", - "createdTimestamp" : 1660890501831, - "username" : "alice", - "enabled" : true, - "totp" : false, - "emailVerified" : true, - "firstName" : "Alice", - "lastName" : "Wunder", - "email" : "alice@dev.local", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "default-roles-kop-apitest-verw" ], - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "9d7633d2-ddf0-4d18-8384-5c9581bc4635", - "createdTimestamp" : 1660890535597, - "username" : "bob", - "enabled" : true, - "totp" : false, - "emailVerified" : true, - "firstName" : "Bob", - "lastName" : "Bobster", - "email" : "bob@dev.local", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "default-roles-kop-apitest-verw" ], - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "0592dc73-cb01-405a-be10-cc6a204ecf1c", - "createdTimestamp" : 1660890234315, - "username" : "goofyapiuser", - "enabled" : true, - "totp" : false, - "emailVerified" : true, - "firstName" : "goofy", - "lastName" : "client", - "email" : "goofy@dev.local", - "credentials" : [ { - "id" : "8cf11911-615a-4fe4-ae0b-37eafac7d8ff", - "type" : "password", - "createdDate" : 1660890249119, - "secretData" : "{\"value\":\"wF2IlMsSnwFvz2I46UOIjeqe0HKzbRIp8s5mymeVxF+H0iU6bVm6qBYT1PXYT3v45AJFPSHtQpG0lA6FxN2F4A==\",\"salt\":\"Cw1vL4Rx1rOwgB6Qn15Pyw==\",\"additionalParameters\":{}}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "default-roles-kop-apitest-verw" ], - "clientRoles" : { - "realm-management" : [ "view-users" ] - }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "c970c2c4-ec0b-4f1e-8a58-769fbc8518f9", - "createdTimestamp" : 1660655234752, - "username" : "sabine", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Sabine", - "lastName" : "Sach", - "credentials" : [ { - "id" : "98297f4d-3aff-4407-9c82-5c25b4e0406e", - "type" : "password", - "userLabel" : "My password", - "createdDate" : 1660655259975, - "secretData" : "{\"value\":\"rbnkjLAt+dxo9k7F8hHKKZ8EN4kMPLHVAhTTcAHLtE7e2wLgc9qnqelAlQeWZZXwXSnHDIxHjqjVW968JPVNTA==\",\"salt\":\"qEBm+fok7trlVRYPHrQfJQ==\",\"additionalParameters\":{}}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "default-roles-kop-apitest-verw" ], - "clientRoles" : { - "goofy" : [ "VERWALTUNG_USER" ] - }, - "notBefore" : 0, - "groups" : [ "Ordnungsamt" ] - } ], - "scopeMappings" : [ { - "clientScope" : "offline_access", - "roles" : [ "offline_access" ] - } ], - "clientScopeMappings" : { - "account" : [ { - "client" : "account-console", - "roles" : [ "manage-account" ] - } ] - }, - "clients" : [ { - "id" : "bf8f95db-6141-419f-adab-7e951659d989", - "clientId" : "account", - "name" : "${client_account}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/kop-apitest-verw/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/realms/kop-apitest-verw/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "post.logout.redirect.uris" : "+" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "97f52335-14d4-4db6-a120-a0a3e5b96dc4", - "clientId" : "account-console", - "name" : "${client_account-console}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/kop-apitest-verw/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/realms/kop-apitest-verw/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "post.logout.redirect.uris" : "+", - "pkce.code.challenge.method" : "S256" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "92b4e98f-126e-4734-bfaf-f2aa2b1c665d", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - } ], - "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "3653296a-de2f-4faf-b72c-ddbba60fa529", - "clientId" : "admin-cli", - "name" : "${client_admin-cli}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "8333205e-d5a6-4d2b-9de9-bd07c9c8579c", - "clientId" : "broker", - "name" : "${client_broker}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "73cec8d5-6e03-4589-86eb-8f58e758d730", - "clientId" : "goofy", - "name" : "Goofy", - "description" : "", - "rootUrl" : "", - "adminUrl" : "", - "baseUrl" : "", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "http://goofy/**" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : true, - "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : true, - "protocol" : "openid-connect", - "attributes" : { - "tls-client-certificate-bound-access-tokens" : "false", - "oidc.ciba.grant.enabled" : "false", - "backchannel.logout.session.required" : "true", - "client_credentials.use_refresh_token" : "false", - "acr.loa.map" : "{}", - "require.pushed.authorization.requests" : "false", - "display.on.consent.screen" : "false", - "oauth2.device.authorization.grant.enabled" : "false", - "backchannel.logout.revoke.offline.tokens" : "false", - "token.response.type.bearer.lower-case" : "false", - "use.refresh.tokens" : "true" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "472c7034-421c-4634-9ae0-e5a9951158d4", - "name" : "orgaIdMapper", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "aggregate.attrs" : "false", - "multivalued" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "organisationsEinheitId", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "organisationseinheitId" - } - } ], - "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "87aeb7a3-5be5-486a-93b3-7fab9f0f55e3", - "clientId" : "realm-management", - "name" : "${client_realm-management}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "2b73fff6-0e4b-402e-9242-9a5ccc8b7281", - "clientId" : "security-admin-console", - "name" : "${client_security-admin-console}", - "rootUrl" : "${authAdminUrl}", - "baseUrl" : "/admin/kop-apitest-verw/console/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/admin/kop-apitest-verw/console/*" ], - "webOrigins" : [ "+" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "post.logout.redirect.uris" : "+", - "pkce.code.challenge.method" : "S256" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "6f7a8a07-e8ed-4721-b2be-e38d7ac34877", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - } ], - "clientScopes" : [ { - "id" : "1a510ca2-38aa-4667-b0dc-8c9dbda92f21", - "name" : "offline_access", - "description" : "OpenID Connect built-in scope: offline_access", - "protocol" : "openid-connect", - "attributes" : { - "consent.screen.text" : "${offlineAccessScopeConsentText}", - "display.on.consent.screen" : "true" - } - }, { - "id" : "7f215868-55b7-4442-bbd0-7373cf08ed83", - "name" : "acr", - "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false" - }, - "protocolMappers" : [ { - "id" : "6b09d606-3bed-4f41-a4d2-1df0a071246c", - "name" : "acr loa level", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-acr-mapper", - "consentRequired" : false, - "config" : { - "id.token.claim" : "true", - "access.token.claim" : "true", - "userinfo.token.claim" : "true" - } - } ] - }, { - "id" : "434ba9b5-8a99-4aa6-b609-6604b06105eb", - "name" : "email", - "description" : "OpenID Connect built-in scope: email", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${emailScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "80ebd080-acba-4f6d-934d-a4beff935fce", - "name" : "email", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "email", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email", - "jsonType.label" : "String" - } - }, { - "id" : "24938eb7-e2ff-40d6-8ce4-27e4ff2301db", - "name" : "email verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "emailVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email_verified", - "jsonType.label" : "boolean" - } - } ] - }, { - "id" : "cf37db2b-fbc1-4fd9-b674-851f70064434", - "name" : "roles", - "description" : "OpenID Connect scope for add user roles to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${rolesScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "ba257d57-f147-4c06-ad0a-6ea174fd5a34", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - }, { - "id" : "9ce3f4c8-fe15-4b31-90aa-1382a1688e31", - "name" : "client roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-client-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "resource_access.${client_id}.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - }, { - "id" : "cd3cc8d0-113b-47d1-aa12-56cee9c5db78", - "name" : "realm roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "realm_access.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - } ] - }, { - "id" : "4119f432-10e6-4656-aef8-bee2917f355b", - "name" : "role_list", - "description" : "SAML role list", - "protocol" : "saml", - "attributes" : { - "consent.screen.text" : "${samlRoleListScopeConsentText}", - "display.on.consent.screen" : "true" - }, - "protocolMappers" : [ { - "id" : "59c7a142-532f-4759-b487-f858722a79c3", - "name" : "role list", - "protocol" : "saml", - "protocolMapper" : "saml-role-list-mapper", - "consentRequired" : false, - "config" : { - "single" : "false", - "attribute.nameformat" : "Basic", - "attribute.name" : "Role" - } - } ] - }, { - "id" : "ba4f7ffe-5b2c-4c20-9806-541b3f0605a3", - "name" : "address", - "description" : "OpenID Connect built-in scope: address", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${addressScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "9f32604f-2419-4c9c-8b41-4a83559d3de4", - "name" : "address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-address-mapper", - "consentRequired" : false, - "config" : { - "user.attribute.formatted" : "formatted", - "user.attribute.country" : "country", - "user.attribute.postal_code" : "postal_code", - "userinfo.token.claim" : "true", - "user.attribute.street" : "street", - "id.token.claim" : "true", - "user.attribute.region" : "region", - "access.token.claim" : "true", - "user.attribute.locality" : "locality" - } - } ] - }, { - "id" : "16a358c4-29ac-42ad-856a-b4444e93826a", - "name" : "microprofile-jwt", - "description" : "Microprofile - JWT built-in scope", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "false" - }, - "protocolMappers" : [ { - "id" : "78e09dfb-a7be-4eea-bd06-3f7bd871235b", - "name" : "groups", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "multivalued" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "foo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "groups", - "jsonType.label" : "String" - } - }, { - "id" : "f38911b8-b4dc-4851-ad33-9f9b6dfff4d6", - "name" : "upn", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "upn", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "f755d172-09d2-4a6e-8c6c-86bfb09ba4f8", - "name" : "profile", - "description" : "OpenID Connect built-in scope: profile", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${profileScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "0fd832a5-c891-473e-bea5-443bbabfa2e4", - "name" : "website", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "website", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "website", - "jsonType.label" : "String" - } - }, { - "id" : "40b5cdcd-d7d4-4174-b26a-4a9ec8caafa5", - "name" : "birthdate", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "birthdate", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "birthdate", - "jsonType.label" : "String" - } - }, { - "id" : "03b88607-446d-4ac1-a08d-7ba6e0cca404", - "name" : "nickname", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "nickname", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "nickname", - "jsonType.label" : "String" - } - }, { - "id" : "9ba9e659-dfa7-45de-b966-6fc4f2f7db29", - "name" : "profile", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "profile", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "profile", - "jsonType.label" : "String" - } - }, { - "id" : "b857001f-4a72-4a97-b157-bb58b4c4eef9", - "name" : "family name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "lastName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "family_name", - "jsonType.label" : "String" - } - }, { - "id" : "30c69082-2d00-436e-a86e-2419b573c074", - "name" : "middle name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "middleName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "middle_name", - "jsonType.label" : "String" - } - }, { - "id" : "e038046e-356b-42b8-bb10-8435c66a24ae", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - }, { - "id" : "44ec36e2-cb7c-46e7-9955-57b9b1e59f1a", - "name" : "updated at", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "updatedAt", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "updated_at", - "jsonType.label" : "long" - } - }, { - "id" : "31b90dab-111c-465d-b703-847c8103db5c", - "name" : "full name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-full-name-mapper", - "consentRequired" : false, - "config" : { - "id.token.claim" : "true", - "access.token.claim" : "true", - "userinfo.token.claim" : "true" - } - }, { - "id" : "2acde2b0-3272-40d7-8c2e-0acb4483fabb", - "name" : "username", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "preferred_username", - "jsonType.label" : "String" - } - }, { - "id" : "13536367-e731-41ed-be86-eb3bcf68c503", - "name" : "picture", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "picture", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "picture", - "jsonType.label" : "String" - } - }, { - "id" : "cb107c43-10a7-4794-a677-3492b24f6c2e", - "name" : "given name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "firstName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "given_name", - "jsonType.label" : "String" - } - }, { - "id" : "73a14943-3e56-4092-9fb9-f9a35146c9c9", - "name" : "zoneinfo", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "zoneinfo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "zoneinfo", - "jsonType.label" : "String" - } - }, { - "id" : "81d10ca9-5412-4253-8bcf-93364345b64d", - "name" : "gender", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "gender", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "gender", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "1809e1d2-479f-4510-bda6-43c1ea1f98b2", - "name" : "web-origins", - "description" : "OpenID Connect scope for add allowed web origins to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false", - "consent.screen.text" : "" - }, - "protocolMappers" : [ { - "id" : "0483a09e-a5ef-4e8a-bae4-ce801423e065", - "name" : "allowed web origins", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-allowed-origins-mapper", - "consentRequired" : false, - "config" : { } - } ] - }, { - "id" : "7b0c2a1d-7674-4b3e-92f6-9614f65e06a3", - "name" : "phone", - "description" : "OpenID Connect built-in scope: phone", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${phoneScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "4e487a9a-54b8-4361-985a-080c196ba714", - "name" : "phone number", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumber", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number", - "jsonType.label" : "String" - } - }, { - "id" : "7f02b25b-3f3a-4a90-8152-557a263b5eea", - "name" : "phone number verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumberVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number_verified", - "jsonType.label" : "boolean" - } - } ] - } ], - "defaultDefaultClientScopes" : [ "web-origins", "role_list", "email", "acr", "roles", "profile" ], - "defaultOptionalClientScopes" : [ "microprofile-jwt", "offline_access", "phone", "address" ], - "browserSecurityHeaders" : { - "contentSecurityPolicyReportOnly" : "", - "xContentTypeOptions" : "nosniff", - "xRobotsTag" : "none", - "xFrameOptions" : "SAMEORIGIN", - "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection" : "1; mode=block", - "strictTransportSecurity" : "max-age=31536000; includeSubDomains" - }, - "smtpServer" : { }, - "eventsEnabled" : false, - "eventsListeners" : [ "jboss-logging" ], - "enabledEventTypes" : [ ], - "adminEventsEnabled" : false, - "adminEventsDetailsEnabled" : false, - "identityProviders" : [ ], - "identityProviderMappers" : [ ], - "components" : { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { - "id" : "4a3058a3-8aa4-4e42-98d5-d51ddc7f8215", - "name" : "Trusted Hosts", - "providerId" : "trusted-hosts", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "host-sending-registration-request-must-match" : [ "true" ], - "client-uris-must-match" : [ "true" ] - } - }, { - "id" : "f2fdaf71-797e-4901-8889-02a05ec6257b", - "name" : "Max Clients Limit", - "providerId" : "max-clients", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "max-clients" : [ "200" ] - } - }, { - "id" : "775070ec-69b2-4faf-ac87-7a77115f8649", - "name" : "Consent Required", - "providerId" : "consent-required", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "5543c38f-8399-40e2-a70a-082f96de18a5", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper" ] - } - }, { - "id" : "5088e788-f3e6-4dc2-8fe5-c464d5d527f5", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "e7d9c16b-7dc0-49ec-b121-e2d6a37481cb", - "name" : "Full Scope Disabled", - "providerId" : "scope", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "cda5c120-5627-4d88-9aa9-c6b64b8fcb3c", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper" ] - } - }, { - "id" : "759d5b40-45b6-4acf-acdf-d9ebf49576dd", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - } ], - "org.keycloak.userprofile.UserProfileProvider" : [ { - "id" : "95cfc09b-6e7d-4adf-8e9e-3b7a02f02b67", - "providerId" : "declarative-user-profile", - "subComponents" : { }, - "config" : { } - } ], - "org.keycloak.keys.KeyProvider" : [ { - "id" : "4bd3752e-313c-44e0-a511-0977b9aa002b", - "name" : "hmac-generated", - "providerId" : "hmac-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "7fcf5141-b805-4db2-8b79-6b14caff09fd" ], - "secret" : [ "cBWGKkHpHRRT8EDIn913r4cnjyS_sSo70h5-cMb8fOjvtCzce3ujnZLaXzyIfYZGjEF6d4_oeDtMdBtie9u61g" ], - "priority" : [ "100" ], - "algorithm" : [ "HS256" ] - } - }, { - "id" : "0ffe2318-6296-43c6-aa58-498303905d6d", - "name" : "rsa-generated", - "providerId" : "rsa-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEowIBAAKCAQEAmcaRhxoBQ+bGtC0ZoEEsQH0tFWV58iJBl9cJzRjVD4UfDEpMP40nkXMpH/vhMm1bQAClViOcqEctv1QQoH7zIDFxH694vz3ymlot3wCIV3rcCrq2cb9wyq4CIccH+bswL8/TLrYd5a0W3BmNpGNrTqFiB6GcuJhfoD+bq4wD51lwInN9h/tKHhtWxySuQkTPQm75Tu9Phxlqac4pgFCBacCMG2tVSBUIJBNT4FS91y05mH1Wuu4CILyo6AQ0socB3K+7lc0hY7zC1cyQyaR2JGM8n7wFUazVdPZBp8bffKxHzfpPscY33Dt2IhP3rILSS+bTjvoJh98HaO2S31L+JwIDAQABAoIBABxXk9Txvw/zxeXJdjKqMGzGZXvPEzXEiJBiyuSpUgOlRn6uZvVDn+pX7ll9xBjWPP5D4DVLJQGC9PSRmurp2wew9Seg4MFmuoMmYdP7NiXheBLmLOA0J6bDgZMWKuslTBFT3Zl7aXE+gLsaXpfQ1yNL7VR4vfjr5JwVfSyWBtYpxYUwfRmVI/c2gSlJYU0s5et2X0eNdwIgQ5+NakI3mo5zlM5eYQSuK1VuhAA+hGWmz9bPzjMk24hofNkODuwPWHv4JtR5c7OLcwo9op5Pc9X0KHH0pjEW14Ir5g6umu4Q9WmrZnREgKphrODZ0DnPl/k292T5AtZEvrFpRFqQxyECgYEA1RAjCuvqoLY0BiN7zk3Me2a30YkDA0y0ctYVWAAHjP1wqN8dFS8r7xkIyLZRj15EPM3IhVQnqcjtQEUAoaV9n9KSmBbbZqyOoOntMO5phIb2TsIzwDAMNB23NJd53vPN87TeBG1JdnzjXiZsMFDkB353HXa7b4lqnbQh/4/KofcCgYEAuMPP7By6Q6AvMktP+bxt6116nDE7kmjTArqXMBNfd6drLgeSURKBi2nStb9gGlA8GWPnFuWjw35Gybw8kKdM+sw8Uan2MpEMokcTjnvgt/r5oFtxVdEBaOFWJb39vtc+2yySBeLTweIv/U9goSdGgNyBpkkRBIeAtMV5wEmYeVECgYEAilQIvE2Arki9LAMbnUyLZs7ApyySJTFGsovlnZWfUV02KJ16b0eJ+ZjCSDV+bFtiaCuedVm2ypel2SUzjL85+WqoPFASr+12SGi30x3mqeFJxsZ0/OD0+10TlfSGbkbRvtj9j9g4atIYeAbwFMpf0bG8ugddF8Qa0TqjHB4KC+8CgYA9OQUoo8xEpEt/St1RT1LM7si2AMpQlVN2UAXQ9Fpp95vYQMIHAy7R11ruxl892OBROX1VZPqCyNED/8/Bzu3/HLXQCZV+4/lfvFWKnRm1XQBiVmqTmRHygthc4Tu3hPNbBMXOFX89e4mTUj4eqDkAchCz3Po6mfvX6qeRQ9G2QQKBgFtKWV6t/zEJ+5PWNc1u7sMllRi5HVhuqjhIY1N0nqSnwyn8p6bs5OUFlaqvXXO9cpsHDrLhO4ioT+Frs6EJIFQoPlU2pVzFXGRsaRq44qG5f7KQ43irSoRMOoJToHoGxh0E9dq6Bo+Jkg3u242l8GwZL6xZw/TSRKgwGsKoD6Gi" ], - "keyUse" : [ "SIG" ], - "certificate" : [ "MIICrzCCAZcCBgGCpsFoxDANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBrb3AtYXBpdGVzdC12ZXJ3MB4XDTIyMDgxNjEzMDI0OVoXDTMyMDgxNjEzMDQyOVowGzEZMBcGA1UEAwwQa29wLWFwaXRlc3QtdmVydzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnGkYcaAUPmxrQtGaBBLEB9LRVlefIiQZfXCc0Y1Q+FHwxKTD+NJ5FzKR/74TJtW0AApVYjnKhHLb9UEKB+8yAxcR+veL898ppaLd8AiFd63Aq6tnG/cMquAiHHB/m7MC/P0y62HeWtFtwZjaRja06hYgehnLiYX6A/m6uMA+dZcCJzfYf7Sh4bVsckrkJEz0Ju+U7vT4cZamnOKYBQgWnAjBtrVUgVCCQTU+BUvdctOZh9VrruAiC8qOgENLKHAdyvu5XNIWO8wtXMkMmkdiRjPJ+8BVGs1XT2QafG33ysR836T7HGN9w7diIT96yC0kvm0476CYffB2jtkt9S/icCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAArGwmbI8BvL9BbnxZr+E2lOcCnPVctTreuQGECP69WvmNqpMzfClESvvLdq7al54s3WLfXqI1L2Q4FEMw1AmTQtuGsIwYUn8DA2VMiU2fHV5YxL99yNY2iKenWqvOgC4rWu6+Jk62dosUYo/Rk5a1wvHhIQqORVerfHnZqEcT2SGtdFUioA2KiKvx9aEGa7xbcYqWpZCZ0hBwM6BSmdGGTV2sBOXulDsKl6rf7jZJbg3EVW7MUabDIcII6askYeQP0DvC/qEutCH/x/Ei6YDOF4nMGpvJUqN4v3aDDfqwesO0mfgY143qr8iG9WI8wyOahZ+Z8RJTaAmqIVIM97dQQ==" ], - "priority" : [ "100" ] - } - }, { - "id" : "17db465e-c349-4b34-874d-a4671e68206f", - "name" : "aes-generated", - "providerId" : "aes-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "abc0b43d-3f75-4927-a38e-8f579de7ad20" ], - "secret" : [ "gcvgiVD4NA0jTxMiU2LuTw" ], - "priority" : [ "100" ] - } - }, { - "id" : "8d29912c-0f8f-4c64-823c-9992720476b1", - "name" : "rsa-enc-generated", - "providerId" : "rsa-enc-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEowIBAAKCAQEAtORIUr4zt9vlb5wXm6jBAqekzRuYnaJwoka/NrN+x1N6yDBzAn8mFFGMXsKJENHJc0Vt0JkXvjjiqFBekttIzODfgEh7ZBvg4gK9r7XR++jA/gXZetlg5J8L6WToLVOPm0MZ0Df07WAFtF/z03C7gsS0wd3Nhp/VGzThdjvLuq0XVMythrTZGh7V19IvahawAxDA0vWxqOK3MaEmlArFEpz2erEgbGq7KW23In6fUqnpLBSGMVULPmiv/8FYtRr66tOHYopE6kuqk+OUaX+ih+5/ATVdvA3XM0h5fgxkXj7eBLlpJuuy3ejAn7XPSjfULkKSzJseM9dHlTtVARntvwIDAQABAoIBADRS+CyfAfzD6bkAEMAg7zuiXIRL4DhwvV3jUvoyr5BesFxpz0rAlrY35H+gi99Gn5vtUFePgROwBrgjD0gxj/xba6sCzFZnzgPyQQYrdMMGT5TrAj6L1IAtFVf8rUA3NIn3vebB2OI07VGAk9nseQDZf2O4kfPIFe+Zu0HlCAhF/oO8Fg2/nH7DQRdtO3gTnDfJnpQiV7IE7wKB/1v/M1ebRj4gv5yPq39XA1pNHtBmZqneyhmz+9f7ml1LvqJ+LPrhYmqphlVJzShSsi1kbKfuD3nbRql8xg/p+xIeiZ1yCeEZflh3ovw9YYe4Ehs4IivJk6FRq4OjK3K4L4nTAcECgYEA5VKK+7IQAo+L5Q91c8zGuBi6FsmvORN7rkhXGFmzOhiYTi7ihzZcM+1vkH+Owgt5Thc534QPNN2RgZm7rW9iMzCQyMLA17OY85/Hp7GKPdv1L14RrWfEdRUO3Hw5EtZJjzfaAdaSvFX16zwdEvKh5447O2RCMxNFIyN7k0fhkaECgYEAye9scD4kwq9c6XsuXFZ+usov5u4h/5SmuG77MUxqpZUlitMNWzIKzOAoMZx2SLlu0al2VBQGhanyTnxpJGptzFhj+X0RdVUNyAH63AommiFbStueFZLi7sFo58de8UXmb2y3p5FNnQNYbdnDoKeN9w0sZDYGxj40FYmCCfGwA18CgYAGo0oEmRXfjRomijkDHhVOdODGEhZxV4AH/m4O9WG7t8SI1tCVy1wF4MSO8TJHqZ9cRE3Xi3IJPLSehL2q+oNkKe628PQ2CivOOXzE/N2chsZlFZr7YvqLzQ0+EpZwViWQ8LPtw7FBpFdW9Ml+p+lJ05MhV/iWk+M3biqAi98aoQKBgGsOxSXIvIJ+qDqcdNq9fJiZAsZir6GpdK5JIGFlixDYPrwX4nfb0wAFQynyMn+h18/OEQ7IQyDwFadoq/GDf0yb+/zUQsI64oCMFCw+MXL7hkPspSX45tj/rxdaispNbbrbH472KPi6QlKS5fUxf8FfuY4zWmoVplVYvpl5CgDvAoGBAKDg+imoQPMREFXhtSwu7qJNx6vu1By2RfnjffcCBXJjf81uGDfn6zE9H1WdbazxmfSU5zqY5aC7YQ+ilkwKw3O80ScNHqkXYqEdNKtbwD5BpJJxGo1sQkmY+gb6bqV0rTjMI0n2qb15K9OYMFvBcQoVJdmMqeFLGTMciiqyMXjN" ], - "keyUse" : [ "ENC" ], - "certificate" : [ "MIICrzCCAZcCBgGCpsFqfjANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBrb3AtYXBpdGVzdC12ZXJ3MB4XDTIyMDgxNjEzMDI0OVoXDTMyMDgxNjEzMDQyOVowGzEZMBcGA1UEAwwQa29wLWFwaXRlc3QtdmVydzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTkSFK+M7fb5W+cF5uowQKnpM0bmJ2icKJGvzazfsdTesgwcwJ/JhRRjF7CiRDRyXNFbdCZF7444qhQXpLbSMzg34BIe2Qb4OICva+10fvowP4F2XrZYOSfC+lk6C1Tj5tDGdA39O1gBbRf89Nwu4LEtMHdzYaf1Rs04XY7y7qtF1TMrYa02Roe1dfSL2oWsAMQwNL1sajitzGhJpQKxRKc9nqxIGxquylttyJ+n1Kp6SwUhjFVCz5or//BWLUa+urTh2KKROpLqpPjlGl/oofufwE1XbwN1zNIeX4MZF4+3gS5aSbrst3owJ+1z0o31C5CksybHjPXR5U7VQEZ7b8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAOcMuNdJDra77bySvC/5/oIqpWUAFsM0ssUTBpuVe2pc/8JcoSFLwsOZn8uBb8by+qPyYAQmJ+CnsSgicQaW8inYraeE3KUA+VI0D5U0FPq6emI7hJXczRj2DtlNE7Mvp7aXMkuZp0xlKzktyUg8EjUYd21mr678EwjOdOvgUMtPLZKvyyCpvE6OVXSsIZq10+4i0UdJyR2bD6sqOcdSapAwj3kqwH6+p5EHQL0Km+JFR4eyPedANm6kZXp6WfxMHHziWvT8WupfCIw/pjtRGXoyn31+kAzs0O6LtCeFW5yFgIPwL+6xbtM+ThFUyhNg1TGny0/fMRfLptrvriinotQ==" ], - "priority" : [ "100" ], - "algorithm" : [ "RSA-OAEP" ] - } - } ] - }, - "internationalizationEnabled" : false, - "supportedLocales" : [ ], - "authenticationFlows" : [ { - "id" : "8b4babf7-5560-4470-94ec-be1e391a5a1f", - "alias" : "Account verification options", - "description" : "Method with which to verity the existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-email-verification", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Verify Existing Account by Re-authentication", - "userSetupAllowed" : false - } ] - }, { - "id" : "9ab76242-a2a7-4e7f-b0c7-679eb20a8d8e", - "alias" : "Authentication Options", - "description" : "Authentication options.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "basic-auth", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "basic-auth-otp", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-spnego", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "e7e84029-12ae-43b8-8d7f-53178b711829", - "alias" : "Browser - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-otp-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "056e9e36-9ad5-4113-90a6-a3f84df31fc5", - "alias" : "Direct Grant - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "direct-grant-validate-otp", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "e3f140c8-ccd6-4002-a3d9-fb4acd9e5812", - "alias" : "First broker login - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-otp-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "078dcee4-009f-4da5-a11c-d89daf371a6d", - "alias" : "Handle Existing Account", - "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-confirm-link", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Account verification options", - "userSetupAllowed" : false - } ] - }, { - "id" : "45dcb4e7-3d3a-4dd7-8a9f-002512e1ec24", - "alias" : "Reset - Conditional OTP", - "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-otp", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "246f0b4a-7837-48ce-bdea-239c5c0f3d56", - "alias" : "User creation or linking", - "description" : "Flow for the existing/non-existing user alternatives", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "create unique user config", - "authenticator" : "idp-create-user-if-unique", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Handle Existing Account", - "userSetupAllowed" : false - } ] - }, { - "id" : "1d6a6368-4743-4187-92b5-d7c75800737a", - "alias" : "Verify Existing Account by Re-authentication", - "description" : "Reauthentication of existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-username-password-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "First broker login - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "db3b1215-d705-4419-8268-546d49178ca2", - "alias" : "browser", - "description" : "browser based authentication", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-cookie", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-spnego", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "identity-provider-redirector", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 25, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 30, - "autheticatorFlow" : true, - "flowAlias" : "forms", - "userSetupAllowed" : false - } ] - }, { - "id" : "df2bb008-c488-42d6-95ef-6e5b4416f933", - "alias" : "clients", - "description" : "Base authentication for clients", - "providerId" : "client-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "client-secret", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-jwt", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-secret-jwt", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-x509", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 40, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "e753ea55-9489-4039-91e4-1504d2726fc2", - "alias" : "direct grant", - "description" : "OpenID Connect Resource Owner Grant", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "direct-grant-validate-username", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "direct-grant-validate-password", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 30, - "autheticatorFlow" : true, - "flowAlias" : "Direct Grant - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "f8b06555-3bdd-4f40-91ac-f5bdd6993a40", - "alias" : "docker auth", - "description" : "Used by Docker clients to authenticate against the IDP", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "docker-http-basic-authenticator", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "1ec385b4-b7f7-466d-8a4d-e996a34aa72f", - "alias" : "first broker login", - "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "review profile config", - "authenticator" : "idp-review-profile", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "User creation or linking", - "userSetupAllowed" : false - } ] - }, { - "id" : "cad74125-0f95-4bbe-9448-7a9bb9eb01d6", - "alias" : "forms", - "description" : "Username, password, otp and other auth forms.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-username-password-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Browser - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "615612e6-0085-4a94-8fb3-7b616b0dffab", - "alias" : "http challenge", - "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "no-cookie-redirect", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Authentication Options", - "userSetupAllowed" : false - } ] - }, { - "id" : "fbeac131-7098-470a-b12c-552166b90c81", - "alias" : "registration", - "description" : "registration flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-page-form", - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : true, - "flowAlias" : "registration form", - "userSetupAllowed" : false - } ] - }, { - "id" : "17ff9178-b88b-4646-a32e-9edc28bb714d", - "alias" : "registration form", - "description" : "registration form", - "providerId" : "form-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-user-creation", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-profile-action", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 40, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-password-action", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 50, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-recaptcha-action", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 60, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "86b9197c-c1eb-4354-b036-d573d2407adb", - "alias" : "reset credentials", - "description" : "Reset credentials for a user if they forgot their password or something", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "reset-credentials-choose-user", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-credential-email", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-password", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 40, - "autheticatorFlow" : true, - "flowAlias" : "Reset - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "cac02a4f-7918-4ad4-aae6-f2948bfbd218", - "alias" : "saml ecp", - "description" : "SAML ECP Profile Authentication Flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "http-basic-authenticator", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - } ], - "authenticatorConfig" : [ { - "id" : "e3b68ed0-580e-45f8-a36e-21f169427f58", - "alias" : "create unique user config", - "config" : { - "require.password.update.after.registration" : "false" - } - }, { - "id" : "6b17fb91-bf25-4ddc-8dc9-85d53ca0f71c", - "alias" : "review profile config", - "config" : { - "update.profile.on.first.login" : "missing" - } - } ], - "requiredActions" : [ { - "alias" : "CONFIGURE_TOTP", - "name" : "Configure OTP", - "providerId" : "CONFIGURE_TOTP", - "enabled" : true, - "defaultAction" : false, - "priority" : 10, - "config" : { } - }, { - "alias" : "terms_and_conditions", - "name" : "Terms and Conditions", - "providerId" : "terms_and_conditions", - "enabled" : false, - "defaultAction" : false, - "priority" : 20, - "config" : { } - }, { - "alias" : "UPDATE_PASSWORD", - "name" : "Update Password", - "providerId" : "UPDATE_PASSWORD", - "enabled" : true, - "defaultAction" : false, - "priority" : 30, - "config" : { } - }, { - "alias" : "UPDATE_PROFILE", - "name" : "Update Profile", - "providerId" : "UPDATE_PROFILE", - "enabled" : true, - "defaultAction" : false, - "priority" : 40, - "config" : { } - }, { - "alias" : "VERIFY_EMAIL", - "name" : "Verify Email", - "providerId" : "VERIFY_EMAIL", - "enabled" : true, - "defaultAction" : false, - "priority" : 50, - "config" : { } - }, { - "alias" : "delete_account", - "name" : "Delete Account", - "providerId" : "delete_account", - "enabled" : false, - "defaultAction" : false, - "priority" : 60, - "config" : { } - }, { - "alias" : "webauthn-register", - "name" : "Webauthn Register", - "providerId" : "webauthn-register", - "enabled" : true, - "defaultAction" : false, - "priority" : 70, - "config" : { } - }, { - "alias" : "webauthn-register-passwordless", - "name" : "Webauthn Register Passwordless", - "providerId" : "webauthn-register-passwordless", - "enabled" : true, - "defaultAction" : false, - "priority" : 80, - "config" : { } - }, { - "alias" : "update_user_locale", - "name" : "Update User Locale", - "providerId" : "update_user_locale", - "enabled" : true, - "defaultAction" : false, - "priority" : 1000, - "config" : { } - } ], - "browserFlow" : "browser", - "registrationFlow" : "registration", - "directGrantFlow" : "direct grant", - "resetCredentialsFlow" : "reset credentials", - "clientAuthenticationFlow" : "clients", - "dockerAuthenticationFlow" : "docker auth", - "attributes" : { - "cibaBackchannelTokenDeliveryMode" : "poll", - "cibaAuthRequestedUserHint" : "login_hint", - "clientOfflineSessionMaxLifespan" : "0", - "oauth2DevicePollingInterval" : "5", - "clientSessionIdleTimeout" : "0", - "clientOfflineSessionIdleTimeout" : "0", - "cibaInterval" : "5", - "cibaExpiresIn" : "120", - "oauth2DeviceCodeLifespan" : "600", - "parRequestUriLifespan" : "60", - "clientSessionMaxLifespan" : "0", - "frontendUrl" : "", - "acr.loa.map" : "[]" - }, - "keycloakVersion" : "18.0.2", - "userManagedAccessAllowed" : false, - "clientProfiles" : { - "profiles" : [ ] - }, - "clientPolicies" : { - "policies" : [ ] - } -}, { - "id" : "e81ed749-e62d-4dd0-a200-8a1406152032", - "realm" : "master", - "displayName" : "Keycloak", - "displayNameHtml" : "<div class=\"kc-logo-text\"><span>Keycloak</span></div>", - "notBefore" : 0, - "defaultSignatureAlgorithm" : "RS256", - "revokeRefreshToken" : false, - "refreshTokenMaxReuse" : 0, - "accessTokenLifespan" : 60, - "accessTokenLifespanForImplicitFlow" : 900, - "ssoSessionIdleTimeout" : 1800, - "ssoSessionMaxLifespan" : 36000, - "ssoSessionIdleTimeoutRememberMe" : 0, - "ssoSessionMaxLifespanRememberMe" : 0, - "offlineSessionIdleTimeout" : 2592000, - "offlineSessionMaxLifespanEnabled" : false, - "offlineSessionMaxLifespan" : 5184000, - "clientSessionIdleTimeout" : 0, - "clientSessionMaxLifespan" : 0, - "clientOfflineSessionIdleTimeout" : 0, - "clientOfflineSessionMaxLifespan" : 0, - "accessCodeLifespan" : 60, - "accessCodeLifespanUserAction" : 300, - "accessCodeLifespanLogin" : 1800, - "actionTokenGeneratedByAdminLifespan" : 43200, - "actionTokenGeneratedByUserLifespan" : 300, - "oauth2DeviceCodeLifespan" : 600, - "oauth2DevicePollingInterval" : 600, - "enabled" : true, - "sslRequired" : "external", - "registrationAllowed" : false, - "registrationEmailAsUsername" : false, - "rememberMe" : false, - "verifyEmail" : false, - "loginWithEmailAllowed" : true, - "duplicateEmailsAllowed" : false, - "resetPasswordAllowed" : false, - "editUsernameAllowed" : false, - "bruteForceProtected" : false, - "permanentLockout" : false, - "maxFailureWaitSeconds" : 900, - "minimumQuickLoginWaitSeconds" : 60, - "waitIncrementSeconds" : 60, - "quickLoginCheckMilliSeconds" : 1000, - "maxDeltaTimeSeconds" : 43200, - "failureFactor" : 30, - "roles" : { - "realm" : [ { - "id" : "c03d1d72-4237-4da2-b4a8-afe18ed88907", - "name" : "admin", - "description" : "${role_admin}", - "composite" : true, - "composites" : { - "realm" : [ "create-realm" ], - "client" : { - "master-realm" : [ "manage-realm", "view-events", "view-authorization", "manage-users", "impersonation", "manage-identity-providers", "query-realms", "view-users", "view-identity-providers", "view-clients", "query-groups", "create-client", "view-realm", "manage-clients", "query-users", "manage-events", "manage-authorization", "query-clients" ], - "kop-apitest-verw-realm" : [ "manage-identity-providers", "view-users", "query-users", "view-authorization", "manage-realm", "view-realm", "manage-clients", "manage-events", "query-clients", "query-groups", "create-client", "query-realms", "view-events", "manage-users", "manage-authorization", "view-identity-providers", "impersonation", "view-clients" ] - } - }, - "clientRole" : false, - "containerId" : "e81ed749-e62d-4dd0-a200-8a1406152032", - "attributes" : { } - }, { - "id" : "000d8005-a3ec-4f47-8e97-23d644a117cf", - "name" : "default-roles-master", - "description" : "${role_default-roles}", - "composite" : true, - "composites" : { - "realm" : [ "offline_access", "uma_authorization" ], - "client" : { - "account" : [ "view-profile", "manage-account" ] - } - }, - "clientRole" : false, - "containerId" : "e81ed749-e62d-4dd0-a200-8a1406152032", - "attributes" : { } - }, { - "id" : "0162b5b8-5461-48c7-b253-f4ceaf603b1a", - "name" : "create-realm", - "description" : "${role_create-realm}", - "composite" : false, - "clientRole" : false, - "containerId" : "e81ed749-e62d-4dd0-a200-8a1406152032", - "attributes" : { } - }, { - "id" : "5ca51565-71f0-47ce-9372-287c9bd54f5a", - "name" : "offline_access", - "description" : "${role_offline-access}", - "composite" : false, - "clientRole" : false, - "containerId" : "e81ed749-e62d-4dd0-a200-8a1406152032", - "attributes" : { } - }, { - "id" : "c4200c9d-0478-4709-9981-7240d7bb550f", - "name" : "uma_authorization", - "description" : "${role_uma_authorization}", - "composite" : false, - "clientRole" : false, - "containerId" : "e81ed749-e62d-4dd0-a200-8a1406152032", - "attributes" : { } - } ], - "client" : { - "security-admin-console" : [ ], - "admin-cli" : [ ], - "account-console" : [ ], - "broker" : [ { - "id" : "4e01b517-610b-4f9f-9d78-bf97f0bd854f", - "name" : "read-token", - "description" : "${role_read-token}", - "composite" : false, - "clientRole" : true, - "containerId" : "d0de7847-0f54-4933-8796-7dbf3c6042a7", - "attributes" : { } - } ], - "kop-apitest-verw-realm" : [ { - "id" : "ccd6f26c-0400-4dde-85bd-d80a705f6515", - "name" : "query-clients", - "description" : "${role_query-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "d5662b9c-adb8-4ece-a7f0-30347024de44", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "59d5a221-ebcb-4539-a642-f32c2ab8a1fd", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "9f48bcad-dab5-4e67-879f-922b654e574a", - "name" : "query-groups", - "description" : "${role_query-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "be8bcea6-f795-49d3-abb7-627026f85d28", - "name" : "query-realms", - "description" : "${role_query-realms}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "24aca00d-d3a2-4503-98a3-9073705748b9", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "kop-apitest-verw-realm" : [ "query-users", "query-groups" ] - } - }, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "3d68d987-f0fc-4781-838d-7baf5e974659", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "2e3a35e1-0356-4a26-b6ca-f6e5a3b0cfbc", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "29530ef0-2018-4156-829a-acf9b5ff5da2", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "7823b717-dbbc-403c-9713-2db3eb784a08", - "name" : "query-users", - "description" : "${role_query-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "9e3caf25-82b8-4e84-b19f-cf4519054925", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "90dba6b2-d628-4824-8e02-8208dfe3f162", - "name" : "impersonation", - "description" : "${role_impersonation}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "1d5929ae-1dce-421f-9a5d-7aca1a872e52", - "name" : "view-authorization", - "description" : "${role_view-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "003b3af2-6856-4c5c-a005-153770863fae", - "name" : "manage-realm", - "description" : "${role_manage-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "6875fd3c-4c51-4780-85e9-6a8a4fb7fc20", - "name" : "view-realm", - "description" : "${role_view-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "4b5f482e-8b78-41b3-b9c8-aaf6e76819e1", - "name" : "manage-clients", - "description" : "${role_manage-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "29d9cfe0-ecc6-4c99-8300-d82465beb7df", - "name" : "manage-events", - "description" : "${role_manage-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - }, { - "id" : "51733859-c072-4f9d-bc7f-fabeca52a34e", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "kop-apitest-verw-realm" : [ "query-clients" ] - } - }, - "clientRole" : true, - "containerId" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "attributes" : { } - } ], - "master-realm" : [ { - "id" : "332b2182-e47e-46b3-b0d4-27c809ec9166", - "name" : "query-realms", - "description" : "${role_query-realms}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "929317c0-4e94-4044-b51f-833f55768bc5", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "master-realm" : [ "query-users", "query-groups" ] - } - }, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "5867e198-5144-4b8f-a77e-79defd2b7ebb", - "name" : "manage-realm", - "description" : "${role_manage-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "773c6077-175e-4da3-8276-f86b360615a8", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "master-realm" : [ "query-clients" ] - } - }, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "2a669505-d12e-407a-be22-f2a2a2ad3050", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "20efe9e9-469e-43d5-8d9e-d0132586db6d", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "a82d2a8b-3b61-43cd-9ccf-1b1bd99e5964", - "name" : "view-authorization", - "description" : "${role_view-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "cf8aef6f-6d68-46fe-a2a2-f5b964be8363", - "name" : "query-groups", - "description" : "${role_query-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "1b98e3b5-3c33-4db2-a7a6-45fc7e1578d9", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "d8782c70-31f8-486c-be81-cba0deebe000", - "name" : "manage-clients", - "description" : "${role_manage-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "27c1c898-50ee-423e-bfcc-968bb13b2402", - "name" : "view-realm", - "description" : "${role_view-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "df36f0a1-eaea-4921-905a-cd9ce5221135", - "name" : "query-users", - "description" : "${role_query-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "5168578d-2aa3-4723-a57e-421d089e24f7", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "9890dd8c-642d-45d2-8826-7bd92f21d346", - "name" : "impersonation", - "description" : "${role_impersonation}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "b5dde334-ef65-40ed-8515-032a77ea76f3", - "name" : "manage-events", - "description" : "${role_manage-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "1dedc1c6-9b01-420f-852f-a5c4f42bbaed", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "076a68b1-77ab-4b98-a86d-55524917e713", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - }, { - "id" : "a8ad610f-7f11-4c3f-8966-01162b0f04b4", - "name" : "query-clients", - "description" : "${role_query-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "attributes" : { } - } ], - "account" : [ { - "id" : "20c66340-95ee-4372-80df-f2071ad9cb25", - "name" : "view-consent", - "description" : "${role_view-consent}", - "composite" : false, - "clientRole" : true, - "containerId" : "816a0f6b-5f92-4014-af04-c9c6445c969b", - "attributes" : { } - }, { - "id" : "c3fffedc-6641-42f4-8fd2-820195c73a4f", - "name" : "manage-account-links", - "description" : "${role_manage-account-links}", - "composite" : false, - "clientRole" : true, - "containerId" : "816a0f6b-5f92-4014-af04-c9c6445c969b", - "attributes" : { } - }, { - "id" : "deaea61a-7681-4f26-af62-8ca8f63d3d70", - "name" : "delete-account", - "description" : "${role_delete-account}", - "composite" : false, - "clientRole" : true, - "containerId" : "816a0f6b-5f92-4014-af04-c9c6445c969b", - "attributes" : { } - }, { - "id" : "0683711d-34d5-4966-88cc-87c7e57db7ba", - "name" : "view-profile", - "description" : "${role_view-profile}", - "composite" : false, - "clientRole" : true, - "containerId" : "816a0f6b-5f92-4014-af04-c9c6445c969b", - "attributes" : { } - }, { - "id" : "ce17b81e-17e1-47d2-8cf0-c1d39088af0c", - "name" : "manage-consent", - "description" : "${role_manage-consent}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "view-consent" ] - } - }, - "clientRole" : true, - "containerId" : "816a0f6b-5f92-4014-af04-c9c6445c969b", - "attributes" : { } - }, { - "id" : "9526bdba-d1e9-4501-8e3b-12faa10db6b4", - "name" : "manage-account", - "description" : "${role_manage-account}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "manage-account-links" ] - } - }, - "clientRole" : true, - "containerId" : "816a0f6b-5f92-4014-af04-c9c6445c969b", - "attributes" : { } - }, { - "id" : "10f559dd-a86f-4fcc-964b-189a8c050884", - "name" : "view-applications", - "description" : "${role_view-applications}", - "composite" : false, - "clientRole" : true, - "containerId" : "816a0f6b-5f92-4014-af04-c9c6445c969b", - "attributes" : { } - } ] - } - }, - "groups" : [ ], - "defaultRole" : { - "id" : "000d8005-a3ec-4f47-8e97-23d644a117cf", - "name" : "default-roles-master", - "description" : "${role_default-roles}", - "composite" : true, - "clientRole" : false, - "containerId" : "e81ed749-e62d-4dd0-a200-8a1406152032" - }, - "requiredCredentials" : [ "password" ], - "otpPolicyType" : "totp", - "otpPolicyAlgorithm" : "HmacSHA1", - "otpPolicyInitialCounter" : 0, - "otpPolicyDigits" : 6, - "otpPolicyLookAheadWindow" : 1, - "otpPolicyPeriod" : 30, - "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ], - "webAuthnPolicyRpEntityName" : "keycloak", - "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyRpId" : "", - "webAuthnPolicyAttestationConveyancePreference" : "not specified", - "webAuthnPolicyAuthenticatorAttachment" : "not specified", - "webAuthnPolicyRequireResidentKey" : "not specified", - "webAuthnPolicyUserVerificationRequirement" : "not specified", - "webAuthnPolicyCreateTimeout" : 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyAcceptableAaguids" : [ ], - "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyPasswordlessRpId" : "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", - "webAuthnPolicyPasswordlessCreateTimeout" : 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], - "users" : [ { - "id" : "6314093b-975f-4e83-a1a5-81e5ebaff3fb", - "createdTimestamp" : 1660890109214, - "username" : "admin", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "credentials" : [ { - "id" : "023812f6-e9d2-4588-84eb-db5676579068", - "type" : "password", - "createdDate" : 1660890109412, - "secretData" : "{\"value\":\"kwvQW91WpNbg6SwNerhqSNb1fmmR1sut54bGXEOiIu1MaZtB4odDivEPTSzLLx/b5QN60Ek5am0avh180Wl0Rg==\",\"salt\":\"ARAVPQWDMYd1E7Eot8wPtQ==\",\"additionalParameters\":{}}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "default-roles-master", "admin" ], - "clientRoles" : { - "kop-apitest-verw-realm" : [ "query-clients", "create-client", "manage-identity-providers", "query-groups", "query-realms", "view-users", "view-events", "manage-users", "manage-authorization", "view-identity-providers", "query-users", "view-authorization", "manage-realm", "view-realm", "manage-clients", "manage-events", "view-clients" ] - }, - "notBefore" : 0, - "groups" : [ ] - } ], - "scopeMappings" : [ { - "clientScope" : "offline_access", - "roles" : [ "offline_access" ] - } ], - "clientScopeMappings" : { - "account" : [ { - "client" : "account-console", - "roles" : [ "manage-account" ] - } ] - }, - "clients" : [ { - "id" : "816a0f6b-5f92-4014-af04-c9c6445c969b", - "clientId" : "account", - "name" : "${client_account}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/master/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/realms/master/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "e82aa78d-b4d4-4b9c-b305-b36c1c29e274", - "clientId" : "account-console", - "name" : "${client_account-console}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/master/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/realms/master/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "pkce.code.challenge.method" : "S256" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "6bceba1e-e804-4bab-9fdd-9183f8194379", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "851c207a-076b-45af-af0a-df374c43dee5", - "clientId" : "admin-cli", - "name" : "${client_admin-cli}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "d0de7847-0f54-4933-8796-7dbf3c6042a7", - "clientId" : "broker", - "name" : "${client_broker}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "80711f4c-5abf-4fb1-8dc8-f500115011dc", - "clientId" : "kop-apitest-verw-realm", - "name" : "kop-apitest-verw Realm", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ ], - "optionalClientScopes" : [ ] - }, { - "id" : "820e5013-a22f-402b-bdc0-d382d9e5bc64", - "clientId" : "master-realm", - "name" : "master Realm", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "5604a389-a474-4e56-a4ba-7af9209643b4", - "clientId" : "security-admin-console", - "name" : "${client_security-admin-console}", - "rootUrl" : "${authAdminUrl}", - "baseUrl" : "/admin/master/console/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/admin/master/console/*" ], - "webOrigins" : [ "+" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "pkce.code.challenge.method" : "S256" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "9dee6645-3070-4af0-bb4a-6bfa356827ad", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - } ], - "clientScopes" : [ { - "id" : "9408ce58-2a52-4b1c-b4ff-515e91e9efc3", - "name" : "acr", - "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false" - }, - "protocolMappers" : [ { - "id" : "94c500cb-0358-477a-968f-82a5aea6c6b3", - "name" : "acr loa level", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-acr-mapper", - "consentRequired" : false, - "config" : { - "id.token.claim" : "true", - "access.token.claim" : "true" - } - } ] - }, { - "id" : "388bc69d-1f54-4385-8c1a-e718ce4ca542", - "name" : "email", - "description" : "OpenID Connect built-in scope: email", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${emailScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "ee33d532-8b55-44b8-93e2-523ac9e60b38", - "name" : "email", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "email", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email", - "jsonType.label" : "String" - } - }, { - "id" : "26004e1a-4aae-40d8-b85c-91e120efd172", - "name" : "email verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "emailVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email_verified", - "jsonType.label" : "boolean" - } - } ] - }, { - "id" : "119dd2f4-f91d-418a-a1f5-a31bf9f584cd", - "name" : "phone", - "description" : "OpenID Connect built-in scope: phone", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${phoneScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "19d30839-7a1b-4216-b12f-6c65284717d8", - "name" : "phone number verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumberVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number_verified", - "jsonType.label" : "boolean" - } - }, { - "id" : "c1b516e2-e7ac-436e-b876-da22083efea2", - "name" : "phone number", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumber", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "e472ee44-5b9c-4ab1-82d7-fc9a2b62bb71", - "name" : "address", - "description" : "OpenID Connect built-in scope: address", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${addressScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "dd5e2bf8-61d6-4b42-b06f-0330f32356a0", - "name" : "address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-address-mapper", - "consentRequired" : false, - "config" : { - "user.attribute.formatted" : "formatted", - "user.attribute.country" : "country", - "user.attribute.postal_code" : "postal_code", - "userinfo.token.claim" : "true", - "user.attribute.street" : "street", - "id.token.claim" : "true", - "user.attribute.region" : "region", - "access.token.claim" : "true", - "user.attribute.locality" : "locality" - } - } ] - }, { - "id" : "755ff7b9-dd91-47a3-b8ea-1fd0ce439dae", - "name" : "offline_access", - "description" : "OpenID Connect built-in scope: offline_access", - "protocol" : "openid-connect", - "attributes" : { - "consent.screen.text" : "${offlineAccessScopeConsentText}", - "display.on.consent.screen" : "true" - } - }, { - "id" : "ae39ed0c-07fd-4bff-8d52-af4ea1daae2e", - "name" : "profile", - "description" : "OpenID Connect built-in scope: profile", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${profileScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "7beceec4-c579-440d-ae1e-934aab4383c0", - "name" : "profile", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "profile", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "profile", - "jsonType.label" : "String" - } - }, { - "id" : "82e09e62-6449-41fa-8192-a5610e8fce69", - "name" : "family name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "lastName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "family_name", - "jsonType.label" : "String" - } - }, { - "id" : "111dfd6a-a2c8-4884-9bb8-8d2120aa5138", - "name" : "given name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "firstName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "given_name", - "jsonType.label" : "String" - } - }, { - "id" : "eec97836-6bd9-4073-8c97-e76d4ce2b749", - "name" : "picture", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "picture", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "picture", - "jsonType.label" : "String" - } - }, { - "id" : "2d39ee08-9ae2-46ee-92dd-0f58b03ef86f", - "name" : "full name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-full-name-mapper", - "consentRequired" : false, - "config" : { - "id.token.claim" : "true", - "access.token.claim" : "true", - "userinfo.token.claim" : "true" - } - }, { - "id" : "fda1318b-802a-4711-990f-b8b4e52ac45b", - "name" : "middle name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "middleName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "middle_name", - "jsonType.label" : "String" - } - }, { - "id" : "d0a14859-586d-42f2-b0ba-1956348c30dc", - "name" : "zoneinfo", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "zoneinfo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "zoneinfo", - "jsonType.label" : "String" - } - }, { - "id" : "b2ff65b7-8606-4440-99d3-1dc509cd0479", - "name" : "updated at", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "updatedAt", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "updated_at", - "jsonType.label" : "long" - } - }, { - "id" : "84d8cbfc-f5d0-453f-9b72-84b1a443864a", - "name" : "gender", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "gender", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "gender", - "jsonType.label" : "String" - } - }, { - "id" : "9d670b5b-5c37-4af4-b832-75a14fff3573", - "name" : "website", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "website", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "website", - "jsonType.label" : "String" - } - }, { - "id" : "5935fb83-737a-456d-9bd6-45ec5d1ef8c4", - "name" : "username", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "preferred_username", - "jsonType.label" : "String" - } - }, { - "id" : "a044140c-f4b0-421a-9e2c-1a9c9237ff4a", - "name" : "nickname", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "nickname", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "nickname", - "jsonType.label" : "String" - } - }, { - "id" : "2bae9756-deef-4e5b-acf1-7ba58fb82e71", - "name" : "birthdate", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "birthdate", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "birthdate", - "jsonType.label" : "String" - } - }, { - "id" : "c61b1f2a-1c31-41c4-89dc-326012c0d0ba", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "3ec0a858-4e22-4330-acc7-ec8b34797062", - "name" : "roles", - "description" : "OpenID Connect scope for add user roles to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${rolesScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "16f6505d-36f9-4a88-92a6-1e2602822531", - "name" : "realm roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "realm_access.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - }, { - "id" : "5149261b-6018-4afd-8635-09ee0ff905c7", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - }, { - "id" : "2b7a0ce8-7cfd-47eb-9a34-b08787dc9eff", - "name" : "client roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-client-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "resource_access.${client_id}.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - } ] - }, { - "id" : "c722b9d1-c67f-492e-b75d-e614f791d7cb", - "name" : "microprofile-jwt", - "description" : "Microprofile - JWT built-in scope", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "false" - }, - "protocolMappers" : [ { - "id" : "1d8da349-319d-465d-bd9c-dfa731b6efde", - "name" : "upn", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "upn", - "jsonType.label" : "String" - } - }, { - "id" : "c3c1ae73-ac3c-4a53-9cc1-c78ed646722f", - "name" : "groups", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "multivalued" : "true", - "user.attribute" : "foo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "groups", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "08f3e0e4-f228-4c5b-b6a3-d960e689be1a", - "name" : "web-origins", - "description" : "OpenID Connect scope for add allowed web origins to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false", - "consent.screen.text" : "" - }, - "protocolMappers" : [ { - "id" : "16b2017f-dd76-4ae1-84b6-0ea63ac4e89e", - "name" : "allowed web origins", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-allowed-origins-mapper", - "consentRequired" : false, - "config" : { } - } ] - }, { - "id" : "f356a880-f40b-4c9f-9b0d-064ff3925734", - "name" : "role_list", - "description" : "SAML role list", - "protocol" : "saml", - "attributes" : { - "consent.screen.text" : "${samlRoleListScopeConsentText}", - "display.on.consent.screen" : "true" - }, - "protocolMappers" : [ { - "id" : "8cbcb253-b64d-4da8-85d7-29ef50e9a657", - "name" : "role list", - "protocol" : "saml", - "protocolMapper" : "saml-role-list-mapper", - "consentRequired" : false, - "config" : { - "single" : "false", - "attribute.nameformat" : "Basic", - "attribute.name" : "Role" - } - } ] - } ], - "defaultDefaultClientScopes" : [ "web-origins", "email", "roles", "acr", "profile", "role_list" ], - "defaultOptionalClientScopes" : [ "phone", "offline_access", "microprofile-jwt", "address" ], - "browserSecurityHeaders" : { - "contentSecurityPolicyReportOnly" : "", - "xContentTypeOptions" : "nosniff", - "xRobotsTag" : "none", - "xFrameOptions" : "SAMEORIGIN", - "xXSSProtection" : "1; mode=block", - "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "strictTransportSecurity" : "max-age=31536000; includeSubDomains" - }, - "smtpServer" : { }, - "eventsEnabled" : false, - "eventsListeners" : [ "jboss-logging" ], - "enabledEventTypes" : [ ], - "adminEventsEnabled" : false, - "adminEventsDetailsEnabled" : false, - "identityProviders" : [ ], - "identityProviderMappers" : [ ], - "components" : { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { - "id" : "8b89de8d-1fef-4a65-b4ee-c402c803d187", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper" ] - } - }, { - "id" : "adafd8a4-151c-43c3-bab2-98bd9d3c8b89", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "94c0848a-617a-4706-bc42-102ca2b2496a", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper" ] - } - }, { - "id" : "c6cc93f0-7092-4ace-b012-c3813d4edff1", - "name" : "Full Scope Disabled", - "providerId" : "scope", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "d2bc0e39-1428-434c-925d-d558845e1697", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "8b4ae70c-67b7-4cb8-801d-8b5ab357b4d2", - "name" : "Trusted Hosts", - "providerId" : "trusted-hosts", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "host-sending-registration-request-must-match" : [ "true" ], - "client-uris-must-match" : [ "true" ] - } - }, { - "id" : "d5961ff8-c1b2-421b-9000-850fd5d000d6", - "name" : "Max Clients Limit", - "providerId" : "max-clients", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "max-clients" : [ "200" ] - } - }, { - "id" : "7716d0ff-3c75-4158-8d79-410f15586d49", - "name" : "Consent Required", - "providerId" : "consent-required", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - } ], - "org.keycloak.keys.KeyProvider" : [ { - "id" : "467045d7-ad14-4a25-92ca-047608aa0cfa", - "name" : "hmac-generated", - "providerId" : "hmac-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "cd753a25-9bd0-4643-aa08-091dcab19bdc" ], - "secret" : [ "ZMruEVEqsgkD6OD8f7oFpokHIW_wwmwUnNX9vbDv0COuuhxA3EUZ6KY9ihiKdkB7SWXXuYRJhXSe_DEJB5yMBA" ], - "priority" : [ "100" ], - "algorithm" : [ "HS256" ] - } - }, { - "id" : "2588c88f-2b4d-4461-aead-64ef172c1101", - "name" : "rsa-generated", - "providerId" : "rsa-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEowIBAAKCAQEArGeuuZIo0ihMH8aba6PIiV97w9YqZl+gWmuSRUIZaQ+FhzSe2AKQb6FGrdyEE7y3rj85x1RepxMhyKMZiq9vX/KgA/TsShmjAW2zuwnoJzoM5xyzsWolu2F8jrOo9NwDVG+LzSankfov5QsTgGw/Ndb2v1YrlpNKeke7vwBle3lj/XMdgcTel8fXSQtdsHpNz11GlK7g1WjkmbuoRdgkxtoCtqkwFlLRa4AzqQip4cqW2ej7/nLHQcoW4YMdfMsFsWXjk6y7mK7DzrytVoqy2RTCKg/MFho7Q0eKLSHtkivBJnBIBAFf7Rf0RNEo4kLU1HBep1lH8vxPVRp14cS+rQIDAQABAoIBAGNiJXu+AKAdMLzEjYWAVbKzAzKCO9Dl4RcemaQpFWLV2sB1GfglikN/cbH5w31pNW1R7ymzvhiL09bIBopG1Wo2//0n7CpPGwNQzOHONTCfqx5zEjb8nKGm8dmFQaldRuIepzVsyf5BfeiH+Qb333xW3ciwkNHtOGrC/Tx+qwGApz04Jh2fb2jx4xcOlRfXT7kpM5phqwVE8QWSW242TJZn1CFL2VKu/s9UFF/qJf4Ds2/o89HTkzklbF+CkFBpBGvH/7ZQ7ePB5f97qSck0V/Nxyo4DQMnLIYMZSfHWjg1fsrmDRd5DHkeGn+Jx9srsvIs1wSO0vzJBPRMq3shOCECgYEA2gpgnTrfhTbMytDz9n3WrVdwmlTNV99c5iFLxRB1Ik9ANXkp+Zm9GazPHfjSSDPd5g2atRWk4K6a2dpxRr+2rJtYMeRyMApXC60Uk5+jQrHtVn98K6unybboJlJoA7sFTxLHAJx7FpEjqokUpLKX0Wualx4Jpz2uVK2ZM5OpLNUCgYEAymtsMjBf6vGVdzc89n4JKIoGPcJBFY4iH4/rxVyw20g5pl0wiU8l3ZhHJZXgWdTV/LOVV2QHGv928qwZU+jhAWcfKPAGkCjC5OSOuBVkbefiEpeu2h74ziTwwnTa+0dYtH607WfLbooTh3Xs8YxnbtdPS/EOeG0R2TKjMG5DVnkCgYAT0Z+oiwJoNGv2/3k9bYDG7szAanbjxtzF2j7t4aoT/Uoj0iiblHrYy5lj6wsKHxTLZW8riJUdCyHuLWngeWqcU953YoFylm4FFK1rIbaQSGX/V8UsnwS4VBTT7uefdy9rWZSXHKIfkf/A74bd1ZHxKiu6ErPj7Lpc3g6v3nshJQKBgQC9FG8yyqEuc5Asljqp/b1MUvHVirkFC4mwdd3Es/q4OtUvI+mMuZQjVHVRFJlHEFr6/D1KLrO8clmIAV5/VQ+pIcynjt5ylsDG0wDFz6XKTEqPF4VLVpcO6M7Etic/hbvEjn8vLD+I+A2aAXvdfku37AO0am4b67Y6buSk/rqD8QKBgGmaVPqViroiqRnYf5zcuMiYh1UXecrIyZTXSg/DTscHAR6wMg5FH+DZdTb/1i9ECF6OEJowqjt12xzm3/JzU8rEWlmEpyuA5dB5kzMxqdKyhPTGbexqiyWEBP+bv3u1UTrGBrzvBkMNppkp+qP2YIEnjM2g6GpH05LqNOPY9hcp" ], - "keyUse" : [ "SIG" ], - "certificate" : [ "MIICmzCCAYMCBgGCtMPTnDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjIwODE5MDYyMDA4WhcNMzIwODE5MDYyMTQ4WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsZ665kijSKEwfxptro8iJX3vD1ipmX6Baa5JFQhlpD4WHNJ7YApBvoUat3IQTvLeuPznHVF6nEyHIoxmKr29f8qAD9OxKGaMBbbO7CegnOgznHLOxaiW7YXyOs6j03ANUb4vNJqeR+i/lCxOAbD811va/ViuWk0p6R7u/AGV7eWP9cx2BxN6Xx9dJC12wek3PXUaUruDVaOSZu6hF2CTG2gK2qTAWUtFrgDOpCKnhypbZ6Pv+csdByhbhgx18ywWxZeOTrLuYrsPOvK1WirLZFMIqD8wWGjtDR4otIe2SK8EmcEgEAV/tF/RE0SjiQtTUcF6nWUfy/E9VGnXhxL6tAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAJjTBsIwSryLhOj6e/bczs6IKAz8ZKRsB/NoV0GLHN2MTbP1MiThj3urXddNrAOaOp5DcYmh4rhLAbhe1AVy1OuQVL8MYXi0gT+vlkuoPQwtYbcAkadQ8EBo0Vb4rG3kyE5WgVKev2mdFlnRXMRJxjE066Y+tCKvA9tyI/z+QxOCKGoU/pEhXhDpFRU/AOSOAskv3rlL4t0rO8q7JdUAA39U0LBf2ptCvDlHl9oA0xZxS53VuZ990dXR8dTfuM4/IcA2BlAg5zBsmPp8rkz+X088SJ8XWFwRNuWNq6LVxb7atchGdJAOdv8enYWJJHUPd4B78BxgiUtVFWbnXaq98qU=" ], - "priority" : [ "100" ] - } - }, { - "id" : "576ffb1e-1a68-4b3c-b593-d48957e6032f", - "name" : "rsa-enc-generated", - "providerId" : "rsa-enc-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEpAIBAAKCAQEAsfUHnfqhyPvT13cTkd96CnoX9QyxsLCw1cJ71b1SHkrJsVUHwIhgoUhriH0ZphM8MCMlWtia+icvDsuXSTaMqcQzv57rfaU5OXHOEQJnIzUgu/YObD92Scrb8xY0ZenWFpjIAF4+l6EF7EGt5XsmFuRrgjHYwkLxnHvE7sONJv9/lwufB9T1YWj59y+xTifrTFvLCOcgMjloWh/pkoe/HrIagSZ6QgIEKCw6T5oRJ/uMvNSKl2zelHfLsPaUu9fW9mp/Zh9ZqttbPHrKgM+X/YYpxjoIbTDt/wJ+BBsXue/39EDUZFRuhUg1oDlDE6HISsj69xbqMaBCUOthGxNpCwIDAQABAoIBAQCOSb4yacDMQ9apVDOYklgxYlgffmvhPBXYhO2hBARR5jiIitVs815X9uDMPEKy0HRyhNeMYN7hn0z4Bn9Lcctcvl0mHPpr9xzfOoiqfwJaW1N2FpKHqOJ6tDHTlvCEgEjGvphD+xcPBBgJRKa3cxUMfs0bR6HqCb7IAQqAYmlNQO2JzHwjP/yCMvcMgvcVFi/birhn5HkWlybMoxb3Jd4p9tgAjGSZvqHeJj74LnCYXvL771ZTgt8djnEctEVRWryuBMd+uAe/Ar0dba40HbnL6u3WPtXRj/YcR/OMMK1scmi2BqJwrTlcqB9KfOcbR8/JEwGw6FOqib4WoGGqfYO5AoGBAN0QX4tZmllJxzfiVc4GxYYbRBr46xItBUEtztupi7su/X+Q7eiSRJYSt10ESPElBtjb45KHkg/ffh4QPvPEjq2R8ROQMxkfn+TC3jCvK0kEddqzGXKtuP5i3mwwa4MkhWSSFUq6W5b11hWWEJvzwoPiadw2gpIYcfujzifszgMFAoGBAM4UrRLlNCrFBHOrHIRUrl0S1Ft8/QCsUAl4jIp7WNdlnpn+Wj5SQHLaYHPf+QrVkVxzN+xd9Ol3kqWOcGtFtz1Kuxpb/YtPVHm2l6JazgP+VN3wDTvKgrW7OzZuulhHEyaRmwt3s/AorxIgwfpxs/oy8OCUv1840Q89YLf6JJjPAoGARQw2K5pjIXxv4z6oul9XFtoxXZNeKSEywPcD44yDfoXg3BVymfAFyDI0X7NU7S05hEa6QCxkLN0L0WwVnaJJRmGNQSULMM+164gKSn6MMJRaE2NZkX49iAdtnbFKA35Gw/D1AZBPx0kmAzwKGAv9N6BinEvSYLuN7qFtZP8MIdkCgYEAohuvnbqBE9fRTa/fidUXKA3k0Gb8mmfxudGDNHgdBathXJ+xm26WVgKkduJLhJNFemUEK8IpIvI1gFgQ5MF9iBBeKDkOtGRd/jR9CXDGuGt7lO39avg9Y/l5dbMakNCwJtnJDfdGq3dFaEwuavTAb+Ncij1YYO5Pvd45U9/IpA8CgYBNQUhzKpE1TG+q75UAs3O6BvN4fldxWMjgMlkApfmnPWUuNPhioMyUeHUt/GllE0mm7F+QU7MSWXZO6VHw5nkCuOObfib+OPmau7C4SsHCd8czd+T+9kyLJK0ZC6s5+IgFCImVqkySM9UuptmPWsdz9NbzGtYkcuwJrVHxoevtOQ==" ], - "keyUse" : [ "ENC" ], - "certificate" : [ "MIICmzCCAYMCBgGCtMPUHDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjIwODE5MDYyMDA4WhcNMzIwODE5MDYyMTQ4WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx9Qed+qHI+9PXdxOR33oKehf1DLGwsLDVwnvVvVIeSsmxVQfAiGChSGuIfRmmEzwwIyVa2Jr6Jy8Oy5dJNoypxDO/nut9pTk5cc4RAmcjNSC79g5sP3ZJytvzFjRl6dYWmMgAXj6XoQXsQa3leyYW5GuCMdjCQvGce8Tuw40m/3+XC58H1PVhaPn3L7FOJ+tMW8sI5yAyOWhaH+mSh78eshqBJnpCAgQoLDpPmhEn+4y81IqXbN6Ud8uw9pS719b2an9mH1mq21s8esqAz5f9hinGOghtMO3/An4EGxe57/f0QNRkVG6FSDWgOUMTochKyPr3FuoxoEJQ62EbE2kLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAfhCLcbGQIeOeRono42Bx/dp7IlVZbCFcdwB83awD/W8ACaRmnwQYL+3XyJlCOLjLGUvQnvPONp9yEK09dZxQvILv5WNeJ2IyH7uNMB6o7POBMnxFVkVTa03T13lQur9t/MmyF6XD9uMSEsb22F5/CAham1FZ02P/E7bnnkubFoNR7z6aWC/D0wTxDXzUe6DdTdthJpJpw+JQkq0tb+GW0MP3vxIjlEpbIye6ETlGtn5zjlSF1Nswv84/MSI367nb1982UVJWvsHGjyF2iVcei24DR99RM632llV7y5rzCRBleyZmRXriEDF114JrLcWwvVTUyRTdEzKHrZx0RP5Ak=" ], - "priority" : [ "100" ], - "algorithm" : [ "RSA-OAEP" ] - } - }, { - "id" : "bc87ad24-becc-4c81-b062-164fe7206668", - "name" : "aes-generated", - "providerId" : "aes-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "e94955c6-2815-4d38-b90d-dc245115d6cb" ], - "secret" : [ "2ZU_Dx4DTO6wcqbYKMCWBw" ], - "priority" : [ "100" ] - } - } ] - }, - "internationalizationEnabled" : false, - "supportedLocales" : [ ], - "authenticationFlows" : [ { - "id" : "88de600a-fb85-46a3-8729-7c81827943ee", - "alias" : "Account verification options", - "description" : "Method with which to verity the existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-email-verification", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Verify Existing Account by Re-authentication", - "userSetupAllowed" : false - } ] - }, { - "id" : "a63f756d-163f-46b1-a7b8-102f7daac662", - "alias" : "Authentication Options", - "description" : "Authentication options.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "basic-auth", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "basic-auth-otp", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-spnego", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "c3b7632e-0417-447a-a20d-c0c7880ed4b5", - "alias" : "Browser - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-otp-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "35890077-9430-4bbd-8a67-bcd4f855a33b", - "alias" : "Direct Grant - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "direct-grant-validate-otp", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "2fb70949-779b-4881-9f62-f89f3ff1ca36", - "alias" : "First broker login - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-otp-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "c23477cd-6e3f-444f-b9d9-b355d92163ef", - "alias" : "Handle Existing Account", - "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-confirm-link", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Account verification options", - "userSetupAllowed" : false - } ] - }, { - "id" : "1336e226-e4ea-4b02-b922-751bc5fb7965", - "alias" : "Reset - Conditional OTP", - "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-otp", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "99bf6afa-2b89-453f-bb15-5f837b4c2ab1", - "alias" : "User creation or linking", - "description" : "Flow for the existing/non-existing user alternatives", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "create unique user config", - "authenticator" : "idp-create-user-if-unique", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Handle Existing Account", - "userSetupAllowed" : false - } ] - }, { - "id" : "a3cabd98-262d-43d7-bba4-df6476444b40", - "alias" : "Verify Existing Account by Re-authentication", - "description" : "Reauthentication of existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-username-password-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "First broker login - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "cabd2c42-5145-452a-ab08-d3c87a40afa3", - "alias" : "browser", - "description" : "browser based authentication", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-cookie", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-spnego", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "identity-provider-redirector", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 25, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 30, - "autheticatorFlow" : true, - "flowAlias" : "forms", - "userSetupAllowed" : false - } ] - }, { - "id" : "7749f55c-3218-4ce7-9d52-0411de70dab1", - "alias" : "clients", - "description" : "Base authentication for clients", - "providerId" : "client-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "client-secret", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-jwt", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-secret-jwt", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-x509", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 40, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "34462526-355a-406a-9cc7-056f69f4ed13", - "alias" : "direct grant", - "description" : "OpenID Connect Resource Owner Grant", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "direct-grant-validate-username", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "direct-grant-validate-password", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 30, - "autheticatorFlow" : true, - "flowAlias" : "Direct Grant - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "89c54236-bee8-453b-ac0d-d5d5b293b301", - "alias" : "docker auth", - "description" : "Used by Docker clients to authenticate against the IDP", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "docker-http-basic-authenticator", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "4f5178b5-8b7c-4ba2-8fe1-46856d50395a", - "alias" : "first broker login", - "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "review profile config", - "authenticator" : "idp-review-profile", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "User creation or linking", - "userSetupAllowed" : false - } ] - }, { - "id" : "2c53dfdb-dffb-4d23-8d71-eb8588528ede", - "alias" : "forms", - "description" : "Username, password, otp and other auth forms.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-username-password-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Browser - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "5fc8c202-b566-497f-9290-8ec8fceef0a5", - "alias" : "http challenge", - "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "no-cookie-redirect", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Authentication Options", - "userSetupAllowed" : false - } ] - }, { - "id" : "bc8a31cd-ca15-4eaf-89b0-27e85cd2bf95", - "alias" : "registration", - "description" : "registration flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-page-form", - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : true, - "flowAlias" : "registration form", - "userSetupAllowed" : false - } ] - }, { - "id" : "aa4c56c3-9b58-4bce-afd2-0903488919bd", - "alias" : "registration form", - "description" : "registration form", - "providerId" : "form-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-user-creation", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-profile-action", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 40, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-password-action", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 50, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-recaptcha-action", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 60, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "a8bec154-7966-4de2-a8ff-447182f7d971", - "alias" : "reset credentials", - "description" : "Reset credentials for a user if they forgot their password or something", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "reset-credentials-choose-user", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-credential-email", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-password", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 40, - "autheticatorFlow" : true, - "flowAlias" : "Reset - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "70bb30f8-b553-4a17-aa33-4195e9c93904", - "alias" : "saml ecp", - "description" : "SAML ECP Profile Authentication Flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "http-basic-authenticator", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - } ], - "authenticatorConfig" : [ { - "id" : "2f0a7833-c6dc-4c22-976a-8a8c896a09cf", - "alias" : "create unique user config", - "config" : { - "require.password.update.after.registration" : "false" - } - }, { - "id" : "1243d693-d577-4b7f-b544-ad9e4b369faf", - "alias" : "review profile config", - "config" : { - "update.profile.on.first.login" : "missing" - } - } ], - "requiredActions" : [ { - "alias" : "CONFIGURE_TOTP", - "name" : "Configure OTP", - "providerId" : "CONFIGURE_TOTP", - "enabled" : true, - "defaultAction" : false, - "priority" : 10, - "config" : { } - }, { - "alias" : "terms_and_conditions", - "name" : "Terms and Conditions", - "providerId" : "terms_and_conditions", - "enabled" : false, - "defaultAction" : false, - "priority" : 20, - "config" : { } - }, { - "alias" : "UPDATE_PASSWORD", - "name" : "Update Password", - "providerId" : "UPDATE_PASSWORD", - "enabled" : true, - "defaultAction" : false, - "priority" : 30, - "config" : { } - }, { - "alias" : "UPDATE_PROFILE", - "name" : "Update Profile", - "providerId" : "UPDATE_PROFILE", - "enabled" : true, - "defaultAction" : false, - "priority" : 40, - "config" : { } - }, { - "alias" : "VERIFY_EMAIL", - "name" : "Verify Email", - "providerId" : "VERIFY_EMAIL", - "enabled" : true, - "defaultAction" : false, - "priority" : 50, - "config" : { } - }, { - "alias" : "delete_account", - "name" : "Delete Account", - "providerId" : "delete_account", - "enabled" : false, - "defaultAction" : false, - "priority" : 60, - "config" : { } - }, { - "alias" : "update_user_locale", - "name" : "Update User Locale", - "providerId" : "update_user_locale", - "enabled" : true, - "defaultAction" : false, - "priority" : 1000, - "config" : { } - } ], - "browserFlow" : "browser", - "registrationFlow" : "registration", - "directGrantFlow" : "direct grant", - "resetCredentialsFlow" : "reset credentials", - "clientAuthenticationFlow" : "clients", - "dockerAuthenticationFlow" : "docker auth", - "attributes" : { - "cibaBackchannelTokenDeliveryMode" : "poll", - "cibaExpiresIn" : "120", - "cibaAuthRequestedUserHint" : "login_hint", - "parRequestUriLifespan" : "60", - "cibaInterval" : "5" - }, - "keycloakVersion" : "18.0.2", - "userManagedAccessAllowed" : false, - "clientProfiles" : { - "profiles" : [ ] - }, - "clientPolicies" : { - "policies" : [ ] - } -} ] diff --git a/user-manager-server/src/test/resources/Usermanager-REST-Last.xml b/user-manager-server/src/test/resources/Usermanager-REST-Last.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e7e78ea55fa3a02fee790342e5d9f5f320c38cd --- /dev/null +++ b/user-manager-server/src/test/resources/Usermanager-REST-Last.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<con:soapui-project id="8f0c8930-b60c-4e6a-aaca-617439bd0b82" activeEnvironment="Default" name="UserManager" resourceRoot="" soapui-version="5.7.0" abortOnError="false" runType="SEQUENTIAL" xmlns:con="http://eviware.com/soapui/config"><con:settings/><con:interface xsi:type="con:RestService" id="1943d3b9-622d-4898-a9bf-972e042b3144" wadlVersion="http://wadl.dev.java.net/2009/02" name="http://localhost:8080" type="rest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><con:settings/><con:definitionCache type="TEXT" rootPart=""/><con:endpoints><con:endpoint>http://localhost:8080</con:endpoint></con:endpoints><con:resource name="UserProfiles" path="/api/userProfiles/" id="2209d8ca-0bfc-421a-b72b-304246765a8a"><con:settings/><con:parameters/><con:method name="Search UserProfiles 1" id="3919bd1c-86e4-4644-a4cb-e9ffd05410bb" method="GET"><con:settings/><con:parameters><con:parameter><con:name>searchBy</con:name><con:value>dd</con:value><con:style>QUERY</con:style><con:default>dd</con:default><con:path xsi:nil="true"/><con:description xsi:nil="true"/></con:parameter><con:parameter><con:name>deleted</con:name><con:value>false</con:value><con:style>QUERY</con:style><con:default>false</con:default><con:path xsi:nil="true"/><con:description xsi:nil="true"/></con:parameter><con:parameter><con:name>Authorization</con:name><con:value>Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE1MjEyNTUsImlhdCI6MTY3MTUyMDk1NSwiYXV0aF90aW1lIjoxNjcxNTE5NzEzLCJqdGkiOiIyMTNhNzVlNy1iYmU5LTQzYjgtYTZmZS1iYTJkZGM1Yzc4M2MiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.AEU-91vBL-oWUwk0hHR0Fge759LAPRVbraO46wfoIbi8XSOoZmY0mF7g_pOVQoW3Fd-mNmsm3kq84mW0d7EQVS0OO2x6W4fW1iOAAaABI3yMfdG-T0BA_BTWNkJOtiENbJ9VoCLbbu7cf_GQv1T_TW8jqJO1Yzkr2Kn1tWAkR-LLewRtZVBBnWM1pSawu6K1miDnOaOrbmJFMrmo4_m9tS72OEsFswuJY1IL777NP3CnA7fHDr7Aa0v41Lyc5Aqc4m_7wWMCiB7uZosXIAAMHAA508AGhcD-4OarUexqxXHVO59GQhIcYjpRf9Hbzgf_tUEyevTP90K3THFqGDKieA</con:value><con:style>HEADER</con:style><con:default>Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE1MjEyNTUsImlhdCI6MTY3MTUyMDk1NSwiYXV0aF90aW1lIjoxNjcxNTE5NzEzLCJqdGkiOiIyMTNhNzVlNy1iYmU5LTQzYjgtYTZmZS1iYTJkZGM1Yzc4M2MiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.AEU-91vBL-oWUwk0hHR0Fge759LAPRVbraO46wfoIbi8XSOoZmY0mF7g_pOVQoW3Fd-mNmsm3kq84mW0d7EQVS0OO2x6W4fW1iOAAaABI3yMfdG-T0BA_BTWNkJOtiENbJ9VoCLbbu7cf_GQv1T_TW8jqJO1Yzkr2Kn1tWAkR-LLewRtZVBBnWM1pSawu6K1miDnOaOrbmJFMrmo4_m9tS72OEsFswuJY1IL777NP3CnA7fHDr7Aa0v41Lyc5Aqc4m_7wWMCiB7uZosXIAAMHAA508AGhcD-4OarUexqxXHVO59GQhIcYjpRf9Hbzgf_tUEyevTP90K3THFqGDKieA</con:default></con:parameter></con:parameters><con:representation type="RESPONSE"><con:mediaType>application/json;charset=UTF-8</con:mediaType><con:status>200</con:status><con:params/><con:element xmlns:user="http://localhost/api/userProfiles/">user:Response</con:element></con:representation><con:representation type="FAULT"><con:mediaType xsi:nil="true"/><con:status>401</con:status><con:params/><con:element>data</con:element></con:representation><con:representation type="RESPONSE"><con:mediaType xsi:nil="true"/><con:status>0</con:status><con:params/><con:element>data</con:element></con:representation><con:representation type="RESPONSE"><con:mediaType xsi:nil="true"/><con:status>0</con:status><con:params/><con:element>data</con:element></con:representation><con:representation type="RESPONSE"><con:mediaType xsi:nil="true"/><con:status>0</con:status><con:params/><con:element>data</con:element></con:representation><con:representation type="RESPONSE"><con:mediaType xsi:nil="true"/><con:status>0</con:status><con:params/><con:element>data</con:element></con:representation><con:representation type="FAULT"><con:mediaType>application/json; charset=utf-8</con:mediaType><con:status>500</con:status><con:params/><con:element xmlns:user="http://localhost/api/userProfiles/">user:Fault</con:element></con:representation><con:representation type="RESPONSE"><con:mediaType xsi:nil="true"/><con:status>0</con:status><con:params/><con:element>data</con:element></con:representation><con:representation type="FAULT"><con:mediaType xsi:nil="true"/><con:status>401</con:status><con:params/><con:element>data</con:element></con:representation><con:request name="Search User" id="fb4b7380-fc6d-48ff-9d90-9078b00c6e1a" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting></con:settings><con:endpoint>http://localhost:8080</con:endpoint><con:request/><con:originalUri>http://localhost/api/userProfiles/</con:originalUri><con:credentials><con:selectedAuthProfile>kiel-dev</con:selectedAuthProfile><con:authType>OAuth 2.0</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters> + <con:entry key="Authorization" value="Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE1MjEyNTUsImlhdCI6MTY3MTUyMDk1NSwiYXV0aF90aW1lIjoxNjcxNTE5NzEzLCJqdGkiOiIyMTNhNzVlNy1iYmU5LTQzYjgtYTZmZS1iYTJkZGM1Yzc4M2MiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.AEU-91vBL-oWUwk0hHR0Fge759LAPRVbraO46wfoIbi8XSOoZmY0mF7g_pOVQoW3Fd-mNmsm3kq84mW0d7EQVS0OO2x6W4fW1iOAAaABI3yMfdG-T0BA_BTWNkJOtiENbJ9VoCLbbu7cf_GQv1T_TW8jqJO1Yzkr2Kn1tWAkR-LLewRtZVBBnWM1pSawu6K1miDnOaOrbmJFMrmo4_m9tS72OEsFswuJY1IL777NP3CnA7fHDr7Aa0v41Lyc5Aqc4m_7wWMCiB7uZosXIAAMHAA508AGhcD-4OarUexqxXHVO59GQhIcYjpRf9Hbzgf_tUEyevTP90K3THFqGDKieA"/> + <con:entry key="deleted" value="false"/> + <con:entry key="searchBy" value="dd"/> +</con:parameters><con:parameterOrder><con:entry>searchBy</con:entry><con:entry>deleted</con:entry><con:entry>Authorization</con:entry></con:parameterOrder></con:request></con:method><con:method name="Search UserProfiles 2" id="3919bd1c-86e4-4644-a4cb-e9ffd05410bb" method="GET"><con:settings/><con:parameters><con:parameter><con:name>searchBy</con:name><con:value>emil</con:value><con:style>QUERY</con:style><con:default>emil</con:default><con:path xsi:nil="true"/><con:description xsi:nil="true"/></con:parameter><con:parameter><con:name>deleted</con:name><con:value>true</con:value><con:style>QUERY</con:style><con:default>true</con:default><con:path xsi:nil="true"/><con:description xsi:nil="true"/></con:parameter><con:parameter><con:name>Authorization</con:name><con:value>Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE1MjEyNTUsImlhdCI6MTY3MTUyMDk1NSwiYXV0aF90aW1lIjoxNjcxNTE5NzEzLCJqdGkiOiIyMTNhNzVlNy1iYmU5LTQzYjgtYTZmZS1iYTJkZGM1Yzc4M2MiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.AEU-91vBL-oWUwk0hHR0Fge759LAPRVbraO46wfoIbi8XSOoZmY0mF7g_pOVQoW3Fd-mNmsm3kq84mW0d7EQVS0OO2x6W4fW1iOAAaABI3yMfdG-T0BA_BTWNkJOtiENbJ9VoCLbbu7cf_GQv1T_TW8jqJO1Yzkr2Kn1tWAkR-LLewRtZVBBnWM1pSawu6K1miDnOaOrbmJFMrmo4_m9tS72OEsFswuJY1IL777NP3CnA7fHDr7Aa0v41Lyc5Aqc4m_7wWMCiB7uZosXIAAMHAA508AGhcD-4OarUexqxXHVO59GQhIcYjpRf9Hbzgf_tUEyevTP90K3THFqGDKieA</con:value><con:style>HEADER</con:style><con:default>Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE1MjEyNTUsImlhdCI6MTY3MTUyMDk1NSwiYXV0aF90aW1lIjoxNjcxNTE5NzEzLCJqdGkiOiIyMTNhNzVlNy1iYmU5LTQzYjgtYTZmZS1iYTJkZGM1Yzc4M2MiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.AEU-91vBL-oWUwk0hHR0Fge759LAPRVbraO46wfoIbi8XSOoZmY0mF7g_pOVQoW3Fd-mNmsm3kq84mW0d7EQVS0OO2x6W4fW1iOAAaABI3yMfdG-T0BA_BTWNkJOtiENbJ9VoCLbbu7cf_GQv1T_TW8jqJO1Yzkr2Kn1tWAkR-LLewRtZVBBnWM1pSawu6K1miDnOaOrbmJFMrmo4_m9tS72OEsFswuJY1IL777NP3CnA7fHDr7Aa0v41Lyc5Aqc4m_7wWMCiB7uZosXIAAMHAA508AGhcD-4OarUexqxXHVO59GQhIcYjpRf9Hbzgf_tUEyevTP90K3THFqGDKieA</con:default></con:parameter></con:parameters><con:representation type="RESPONSE"><con:mediaType>application/json;charset=UTF-8</con:mediaType><con:status>200</con:status><con:params/><con:element xmlns:user="http://localhost/api/userProfiles/">user:Response</con:element></con:representation><con:request name="Search User" id="fb4b7380-fc6d-48ff-9d90-9078b00c6e1a" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting></con:settings><con:endpoint>http://localhost:8080</con:endpoint><con:request/><con:originalUri>http://localhost/api/userProfiles/</con:originalUri><con:credentials><con:selectedAuthProfile>kiel-dev</con:selectedAuthProfile><con:authType>OAuth 2.0</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters> + <con:entry key="Authorization" value="Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE1MjEyNTUsImlhdCI6MTY3MTUyMDk1NSwiYXV0aF90aW1lIjoxNjcxNTE5NzEzLCJqdGkiOiIyMTNhNzVlNy1iYmU5LTQzYjgtYTZmZS1iYTJkZGM1Yzc4M2MiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.AEU-91vBL-oWUwk0hHR0Fge759LAPRVbraO46wfoIbi8XSOoZmY0mF7g_pOVQoW3Fd-mNmsm3kq84mW0d7EQVS0OO2x6W4fW1iOAAaABI3yMfdG-T0BA_BTWNkJOtiENbJ9VoCLbbu7cf_GQv1T_TW8jqJO1Yzkr2Kn1tWAkR-LLewRtZVBBnWM1pSawu6K1miDnOaOrbmJFMrmo4_m9tS72OEsFswuJY1IL777NP3CnA7fHDr7Aa0v41Lyc5Aqc4m_7wWMCiB7uZosXIAAMHAA508AGhcD-4OarUexqxXHVO59GQhIcYjpRf9Hbzgf_tUEyevTP90K3THFqGDKieA"/> + <con:entry key="deleted" value="false"/> + <con:entry key="searchBy" value="dd"/> +</con:parameters><con:parameterOrder><con:entry>searchBy</con:entry><con:entry>deleted</con:entry><con:entry>Authorization</con:entry></con:parameterOrder></con:request></con:method></con:resource><con:resource name="User Settings Dorothea" path="/api/user/63a06e67ea24a6618e91c273/settings" id="c685e421-27ed-47d6-9bef-126b59c7d036"><con:settings/><con:parameters/><con:method name="Method 1" id="e7dfa4b7-8d3a-4c87-94b6-12611934e544" method="GET"><con:settings/><con:parameters/><con:representation type="FAULT"><con:mediaType xsi:nil="true"/><con:status>401</con:status><con:params/><con:element>data</con:element></con:representation><con:representation type="RESPONSE"><con:mediaType>application/json;charset=UTF-8</con:mediaType><con:status>200</con:status><con:params/><con:element xmlns:a06="http://localhost/api/user/63a06e67ea24a6618e91c273">a06:Response</con:element></con:representation><con:representation type="FAULT"><con:mediaType xsi:nil="true"/><con:status>401</con:status><con:params/><con:element>data</con:element></con:representation><con:request name="Get UserSettings" id="8b098a1e-2de9-4127-a977-8fdd147d8c7d" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting></con:settings><con:endpoint>http://localhost:8080</con:endpoint><con:request/><con:originalUri>http://localhost/api/user/63a06e67ea24a6618e91c273</con:originalUri><con:credentials><con:selectedAuthProfile>kiel-dev</con:selectedAuthProfile><con:authType>OAuth 2.0</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters/></con:request></con:method></con:resource><con:resource name="1993ca0c-2a7a-4f1c-9eca-3d658f3d175b" path="/migration/user/1993ca0c-2a7a-4f1c-9eca-3d658f3d175b" id="4dd08adf-e247-49c8-b196-187eecea63a7"><con:settings/><con:parameters/><con:method name="Method 1" id="8c8162ad-1467-411e-9bcb-4a1e64e26191" method="GET"><con:settings/><con:parameters/><con:representation type="RESPONSE"><con:mediaType>text/plain;charset=UTF-8</con:mediaType><con:status>200</con:status><con:params/><con:element>data</con:element></con:representation><con:request name="Request 1" id="f5e7933b-f91b-43b9-87f5-e3c616d605d8" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting></con:settings><con:endpoint>http://localhost:8080</con:endpoint><con:request/><con:originalUri>http://localhost/migration/user/1993ca0c-2a7a-4f1c-9eca-3d658f3d175b</con:originalUri><con:credentials><con:authType>No Authorization</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters/></con:request></con:method></con:resource></con:interface><con:testSuite id="7b941e68-bc96-4b5a-b4f9-e571cceaa30c" name="SearchUsers"><con:settings/><con:runType>SEQUENTIAL</con:runType><con:testCase id="11375c12-ebbd-46ca-a2e1-ca4e2242c4fa" failOnError="true" failTestCaseOnErrors="true" keepSession="false" maxResults="0" name="Search DD" searchProperties="true"><con:settings/><con:testStep type="restrequest" name="UserProfiles 1 - Search User" id="f66edac7-e0f1-477c-9d2b-740943b0e53a"><con:settings/><con:config service="http://localhost:8080" resourcePath="/api/userProfiles/" methodName="Search UserProfiles 1" xsi:type="con:RestRequestStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><con:restRequest name="UserProfiles 1 - Search User" id="fb4b7380-fc6d-48ff-9d90-9078b00c6e1a" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting></con:settings><con:endpoint>http://localhost:8080</con:endpoint><con:request/><con:originalUri>http://localhost/api/userProfiles/</con:originalUri><con:credentials><con:selectedAuthProfile>kiel-dev</con:selectedAuthProfile><con:authType>OAuth 2.0</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters> + <con:entry key="Authorization" value="Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE1MjEyNTUsImlhdCI6MTY3MTUyMDk1NSwiYXV0aF90aW1lIjoxNjcxNTE5NzEzLCJqdGkiOiIyMTNhNzVlNy1iYmU5LTQzYjgtYTZmZS1iYTJkZGM1Yzc4M2MiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.AEU-91vBL-oWUwk0hHR0Fge759LAPRVbraO46wfoIbi8XSOoZmY0mF7g_pOVQoW3Fd-mNmsm3kq84mW0d7EQVS0OO2x6W4fW1iOAAaABI3yMfdG-T0BA_BTWNkJOtiENbJ9VoCLbbu7cf_GQv1T_TW8jqJO1Yzkr2Kn1tWAkR-LLewRtZVBBnWM1pSawu6K1miDnOaOrbmJFMrmo4_m9tS72OEsFswuJY1IL777NP3CnA7fHDr7Aa0v41Lyc5Aqc4m_7wWMCiB7uZosXIAAMHAA508AGhcD-4OarUexqxXHVO59GQhIcYjpRf9Hbzgf_tUEyevTP90K3THFqGDKieA"/> + <con:entry key="deleted" value="false"/> + <con:entry key="searchBy" value="dd"/> +</con:parameters><con:parameterOrder><con:entry>searchBy</con:entry><con:entry>deleted</con:entry><con:entry>Authorization</con:entry></con:parameterOrder></con:restRequest></con:config></con:testStep><con:testStep type="restrequest" name="Get User settings" id="ea30343a-0e90-46de-985d-cb741cfad36c"><con:settings/><con:config service="http://localhost:8080" resourcePath="/api/user/63a06e67ea24a6618e91c273/settings" methodName="Method 1" xsi:type="con:RestRequestStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><con:restRequest name="Get User settings" id="8b098a1e-2de9-4127-a977-8fdd147d8c7d" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting></con:settings><con:endpoint>http://localhost:8080</con:endpoint><con:request/><con:originalUri>http://localhost/api/user/63a06e67ea24a6618e91c273</con:originalUri><con:credentials><con:selectedAuthProfile>kiel-dev</con:selectedAuthProfile><con:authType>OAuth 2.0</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters/></con:restRequest></con:config></con:testStep><con:testStep type="restrequest" name="Search UserProfiles 2 - Search User" id="dbdd2b3a-7d12-49c9-8da1-4679ccf0fb44"><con:settings/><con:config service="http://localhost:8080" resourcePath="/api/userProfiles/" methodName="Search UserProfiles 2" xsi:type="con:RestRequestStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><con:restRequest name="Search UserProfiles 2 - Search User" id="fb4b7380-fc6d-48ff-9d90-9078b00c6e1a" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting></con:settings><con:endpoint>http://localhost:8080</con:endpoint><con:request/><con:originalUri>http://localhost/api/userProfiles/</con:originalUri><con:credentials><con:selectedAuthProfile>kiel-dev</con:selectedAuthProfile><con:authType>OAuth 2.0</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters> + <con:entry key="Authorization" value="Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE1MjEyNTUsImlhdCI6MTY3MTUyMDk1NSwiYXV0aF90aW1lIjoxNjcxNTE5NzEzLCJqdGkiOiIyMTNhNzVlNy1iYmU5LTQzYjgtYTZmZS1iYTJkZGM1Yzc4M2MiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJhOWM4YWUyYy02Mzc5LTQzNTQtOGRkOS1mMzI4Nzk2YWY0YzQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.AEU-91vBL-oWUwk0hHR0Fge759LAPRVbraO46wfoIbi8XSOoZmY0mF7g_pOVQoW3Fd-mNmsm3kq84mW0d7EQVS0OO2x6W4fW1iOAAaABI3yMfdG-T0BA_BTWNkJOtiENbJ9VoCLbbu7cf_GQv1T_TW8jqJO1Yzkr2Kn1tWAkR-LLewRtZVBBnWM1pSawu6K1miDnOaOrbmJFMrmo4_m9tS72OEsFswuJY1IL777NP3CnA7fHDr7Aa0v41Lyc5Aqc4m_7wWMCiB7uZosXIAAMHAA508AGhcD-4OarUexqxXHVO59GQhIcYjpRf9Hbzgf_tUEyevTP90K3THFqGDKieA"/> + <con:entry key="deleted" value="false"/> + <con:entry key="searchBy" value="dd"/> +</con:parameters><con:parameterOrder><con:entry>searchBy</con:entry><con:entry>deleted</con:entry><con:entry>Authorization</con:entry></con:parameterOrder></con:restRequest></con:config></con:testStep><con:testStep type="restrequest" name="Get Internal Id" id="281ea46d-dba5-4b10-9ce4-b75b29f60350"><con:settings/><con:config service="http://localhost:8080" resourcePath="/migration/user/1993ca0c-2a7a-4f1c-9eca-3d658f3d175b" methodName="Method 1" xsi:type="con:RestRequestStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><con:restRequest name="Get Internal Id" id="f5e7933b-f91b-43b9-87f5-e3c616d605d8" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers"><xml-fragment/></con:setting></con:settings><con:endpoint>http://localhost:8080</con:endpoint><con:request/><con:originalUri>http://localhost/migration/user/1993ca0c-2a7a-4f1c-9eca-3d658f3d175b</con:originalUri><con:credentials><con:authType>No Authorization</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters/></con:restRequest></con:config></con:testStep><con:loadTest id="6b72bfca-869d-4706-89d8-2ba9c1bfed45" name="LoadTest 1"><con:settings><con:setting id="HttpSettings@close-connections">false</con:setting></con:settings><con:threadCount>100</con:threadCount><con:startDelay>10</con:startDelay><con:sampleInterval>250</con:sampleInterval><con:calculateTPSOnTimePassed>true</con:calculateTPSOnTimePassed><con:resetStatisticsOnThreadCountChange>true</con:resetStatisticsOnThreadCountChange><con:historyLimit>-1</con:historyLimit><con:testLimit>300</con:testLimit><con:limitType>TIME</con:limitType><con:loadStrategy><con:type>Simple</con:type><con:config><testDelay>100</testDelay><randomFactor>0.5</randomFactor></con:config></con:loadStrategy><con:assertion type="Step Status" name="Step Status"/><con:maxAssertionErrors>100</con:maxAssertionErrors><con:statisticsLogFolder/><con:statisticsLogInterval>0</con:statisticsLogInterval><con:logStatisticsOnThreadChange>false</con:logStatisticsOnThreadChange><con:cancelOnReachedLimit>false</con:cancelOnReachedLimit><con:cancelExcessiveThreads>true</con:cancelExcessiveThreads><con:strategyInterval>500</con:strategyInterval><con:updateStatisticsPerTestStep>false</con:updateStatisticsPerTestStep></con:loadTest><con:properties/></con:testCase><con:properties/></con:testSuite><con:properties/><con:wssContainer/><con:oAuth2ProfileContainer><con:oAuth2Profile><con:name>kiel-dev</con:name><con:clientID>alfa</con:clientID><con:clientSecret>S9UEMuLG9y9ev99</con:clientSecret><con:authorizationURI>https://sso.dev.by.ozg-cloud.de/realms/by-kiel-dev/protocol/openid-connect/auth</con:authorizationURI><con:accessTokenURI>https://sso.dev.by.ozg-cloud.de/realms/by-kiel-dev/protocol/openid-connect/token</con:accessTokenURI><con:redirectURI>http://localhost:4300</con:redirectURI><con:accessToken>eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVVWtEeUZfVlRXenpDNU82WkNUcmRSMm5FV3pZekNCbFdvaXEySjMxbjdNIn0.eyJleHAiOjE2NzE2MTE1NzEsImlhdCI6MTY3MTYxMTI3MSwiYXV0aF90aW1lIjoxNjcxNjEwODQ4LCJqdGkiOiJmMTFjMTZkMC1iOTE4LTQ1NDQtYTMzNS0yMzE2MzYxNTg5ZDMiLCJpc3MiOiJodHRwczovL3Nzby5kZXYuYnkua29wLWNsb3VkLmRlL3JlYWxtcy9zaC1raWVsLWRldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIxOTYzZTZhZi01MDU2LTQ0NjItOTZlNC1mYjMyOTE5OTVlN2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzaC1raWVsLWRldi1nb29meSIsInNlc3Npb25fc3RhdGUiOiIzY2UxMjk0My02ZDdiLTQ3ZGUtYjEzZi02N2Y2MWY1ZjU1MGYiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9raWVsLmRldi5ieS5rb3AtY2xvdWQuZGUiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXNoLWtpZWwtZGV2Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsic2gta2llbC1kZXYtZ29vZnkiOnsicm9sZXMiOlsiVkVSV0FMVFVOR19VU0VSIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiIzY2UxMjk0My02ZDdiLTQ3ZGUtYjEzZi02N2Y2MWY1ZjU1MGYiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwib3JnYW5pc2F0aW9uc2VpbmhlaXRJZCI6WzI0ODI0MDg4Niw5MDMwMjI5LDEwMzYzNDU1XSwibmFtZSI6IkRvcm90aGVhIERvZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImRvcm90aGVhIiwiZ2l2ZW5fbmFtZSI6IkRvcm90aGVhIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJlbWFpbCI6InN1c2FubmUuZmlzY2hlckBkYXRhcG9ydC5kZSJ9.lBO6RW3QrYu1xRfVO2jd2T4udJzjFoLj_7OX6Sv65lgZZZ5FHIM3asQDMfWx5R9VC20JGbzr6YBBGechqe2FCvISSF9YpTCioz4SwU2984c47b0ducjpMsX_yzMYvOq8-66y0DTQDFxmj_QP3KiWH5CnOSyCMNVOY-HgLoYtqm2zQwB3usZGbcSM3R57kRU7lFlBtVpDtmeTCzxTkUSfVkEHkfTkbBsnRi7TNCUzTg9h-Jihz8IWf3s3qMxeSZ1Q4jyFqx1aikDjOan-jhDwsUyOvC5-8zIdzj-TwejHR3F7aAeNUvZrFYEiXBkNSCIHiMfMki98dycHAsyjl4W4Uw</con:accessToken><con:accessTokenPosition>HEADER</con:accessTokenPosition><con:oAuth2Flow>AUTHORIZATION_CODE_GRANT</con:oAuth2Flow><con:refreshAccessTokenMethod>AUTOMATIC</con:refreshAccessTokenMethod><con:scope/><con:accessTokenStatus>ENTERED_MANUALLY</con:accessTokenStatus><con:accessTokenStartingStatus>ENTERED_MANUALLY</con:accessTokenStartingStatus><con:javaScripts><con:entry/></con:javaScripts><con:manualAccessTokenExpirationTime>60</con:manualAccessTokenExpirationTime><con:useManualAccessTokenExpirationTime>true</con:useManualAccessTokenExpirationTime><con:manualAccessTokenExpirationTimeUnit>SECONDS</con:manualAccessTokenExpirationTimeUnit></con:oAuth2Profile></con:oAuth2ProfileContainer><con:oAuth1ProfileContainer/></con:soapui-project> \ No newline at end of file diff --git a/user-manager-server/src/test/resources/application.yml b/user-manager-server/src/test/resources/application.yml index 62da329a75e448a3a2590e51f6f3a2e7950ffcf2..46b99472074ade5ea9df92f4b9a8baf2525e6598 100644 --- a/user-manager-server/src/test/resources/application.yml +++ b/user-manager-server/src/test/resources/application.yml @@ -1,28 +1,34 @@ quarkus: - application: - name: kopusermanager - mongodb: - database: usermanager - scheduler: - metrics: - enabled: true - log: - level: INFO - console: - json: - fields: - level: - field-name: log.level -kop: - keycloak: - sync: - cron: "0 15 13 * * ?" - api: - user: "-" - password: "-" - realm: sh-kiel-dev - organisations-einheit-id-key: organisationseinheitId - ldap-id-key: LDAP_ID - client: sh-kiel-dev-goofy - user-manager: - url: http://localhost:9092 \ No newline at end of file + keycloak: + devservices: + enabled: false + application: + name: ozgcloud_usermanager + mongodb: + devservices: + enabled: false + database: usermanager + scheduler: + metrics: + enabled: true + log: + level: INFO + oidc: + auth-server-url: https://sso.dev.by.ozg-cloud.de/realms/by-kiel-dev + +keycloak: + url: http://localhost:8088 + +ozgcloud: + keycloak: + api: + user: "-" + password: "-" + realm: by-kiel-dev + organisations-einheit-id-key: organisationseinheitId + ldap-id-key: LDAP_ID + client: alfa + user-manager: + url: http://localhost:9092 + usersync: + period: disabled \ No newline at end of file