diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..fa33427cb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "compose/voms-replica/voms-testsuite"] + path = compose/voms-replica/voms-testsuite + url = git@github.com:italiangrid/voms-testsuite.git diff --git a/compose/voms-replica/.env b/compose/voms-replica/.env new file mode 100644 index 000000000..b515d9f7a --- /dev/null +++ b/compose/voms-replica/.env @@ -0,0 +1,14 @@ +COMPOSE_PROJECT_NAME=voms +TRUST_IMAGE=indigoiam/egi-trustanchors +TRUST_IMAGE_TAG=igi-test-ca +DB_IMAGE=mysql +DB_IMAGE_TAG=8.3 +NGINX_IMAGE=baltig.infn.it:4567/cnafsd/ngx_http_voms_module/nginx-httpg-voms +NGINX_IMAGE_TAG=latest +VOMS_AA_IMAGE=indigoiam/voms-aa-bp +VOMS_AA_IMAGE_TAG=v1.8.3 +GRID_CLIENTS_IMAGE=indigoiam/robot-framework +GRID_CLIENTS_IMAGE_TAG=latest +IAM_IMAGE=indigoiam/iam-login-service +IAM_IMAGE_TAG=v1.8.3 + diff --git a/compose/voms-replica/README.md b/compose/voms-replica/README.md new file mode 100644 index 000000000..f88bee613 --- /dev/null +++ b/compose/voms-replica/README.md @@ -0,0 +1,95 @@ +# VOMS-AA Replica + +This folder contains a docker compose example to deploy three instances of VOMS-AA in two sites with a DB replica. + +![Setup schema.](VOMS-AA_replica.png) + +With this setup the VOMS-AA service can be replicated on one or more remote locations. If one location fails or is overloaded, a VOMS client can connect to the other locations. + +## Deployment description + +The `compose` file definises a few containers: + +* `trust`: docker image for the GRID CA certificates plus the `igi-test-ca` used in this deployment for test certificates. + +The actual VOMS services are virtually divided between three sites: + +#### Site 1: CERN +* `db-primary`: a dump of the IAM db for test environment. In addition to the db populated with the iam `mysql-dev` profile, the user `test` has a certificate with DN `/C=IT/O=IGI/CN=test0` linked to his account and he also is part of the `indigo-dc` group (necessary to obtain VOMS proxies). A second SQL script creates a `replicator` user for replica. +* `db-replica`: a DB configured to replicate the statements of `db-primary`, from the initial one. It conects with SSL and is configured to be read-only. Only the IAM DB tables which are used by VOMS-AA are replicated. You can see them [here](assets/mysql-conf/replica.cnf). +* `vomsaa-primary` and `vomsaa-replica`: the main voms-aa microservices, each connected to their own DB. +* `ngx-primary` and `ngx-replica`: an extension to NGINX, used for TLS termination, reverse proxy and possibly VOMS proxies validation. They sends requests to the corresponding `vomsaa-primary` and `vomsaa-replica` services. + + +#### Site 2: CNAF +* `db-remote`: this is a full replica of `db-replica`. Only the tables used by VOMS-AA are present in `db-replica`, and thus we avoiding transmitting over the remote network useless information. +* `vomsaa-remote` +* `ngx-remote` + +#### Site 3: Anywhere else +* `client`: it is a single container containing GRID clients (in particular `voms-proxy-init`) used to query both the VOMS services. It connects in round-robin fashion to each endpoint and when one fails it falls back to the others. Here a p12 file for the test user encrypted with the `pass` password is present in the well-known directory (`/home/test/.globus/usercred.p12`). It can be used to obtain a VOMS proxy by `voms-aa` serving a VO named `indigo-dc`. + +### Networking + +We use a few distinct networks, similar to a real scenario: + +* `site1-lan` and `site2-lan`: The internal LAN of the two sites. These are used to connect the DB, VOMS-AA and NGINX between them inside the same site. +* `site-to-site-tunnel`: This is a VPN network or any tunnel network between the two sites, used by `db-remote` to connect to `db-replica`. +* `wan`: The NGINX servers are exposed on the public network so that the clients can connect from anywhere. + +## Test + +Run the docker-compose with + +``` +$ docker compose up -d +``` + +and wait for the `trust` service to finish; all the services will be available shortly afterwards. + +To query the voms-aa using the VOMS client, run: + +``` +$ docker compose exec client voms-proxy-init -voms indigo-dc +Enter GRID pass phrase for this identity: +Contacting voms-remote.test.example:443 [/C=IT/O=IGI/CN=*.test.example] "indigo-dc"... +Remote VOMS server contacted succesfully. + + +Created proxy in /tmp/x509up_u1000. + +Your proxy is valid until Sat Mar 16 03:54:38 CET 2024 +``` + +Check the content of the proxy with + +``` +$ docker compose exec client voms-proxy-info -all +subject : /C=IT/O=IGI/CN=test0/CN=441572696 +issuer : /C=IT/O=IGI/CN=test0 +identity : /C=IT/O=IGI/CN=test0 +type : RFC3820 compliant impersonation proxy +strength : 2048 +path : /tmp/x509up_u1000 +timeleft : 11:59:45 +key usage : Digital Signature, Non Repudiation, Key Encipherment +=== VO indigo-dc extension information === +VO : indigo-dc +subject : /C=IT/O=IGI/CN=test0 +issuer : /C=IT/O=IGI/CN=*.test.example +attribute : /indigo-dc/Role=NULL/Capability=NULL +timeleft : 11:59:45 +uri : voms-remote.test.example:8080 + +``` +If you want to force the query to one voms-aa use one of the followings: +``` +$ docker compose exec client voms-proxy-init -voms voms-primary +$ docker compose exec client voms-proxy-init -voms voms-replica +$ docker compose exec client voms-proxy-init -voms voms-remote +``` + +To run the testsuite: +``` +$ docker compose exec testsuite bash run-testsuite.sh +``` \ No newline at end of file diff --git a/compose/voms-replica/VOMS-AA_replica.png b/compose/voms-replica/VOMS-AA_replica.png new file mode 100644 index 000000000..85f130ef9 Binary files /dev/null and b/compose/voms-replica/VOMS-AA_replica.png differ diff --git a/compose/voms-replica/assets/certs/voms.test.example.cert.pem b/compose/voms-replica/assets/certs/voms.test.example.cert.pem new file mode 100644 index 000000000..3cbd4774c --- /dev/null +++ b/compose/voms-replica/assets/certs/voms.test.example.cert.pem @@ -0,0 +1,85 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 19 (0x13) + Signature Algorithm: sha512WithRSAEncryption + Issuer: C=IT, O=IGI, CN=Test CA + Validity + Not Before: Oct 19 08:55:57 2022 GMT + Not After : Oct 16 08:55:57 2032 GMT + Subject: C=IT, O=IGI, CN=*.test.example + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:e7:3a:01:a8:93:12:08:f4:a6:c9:89:10:a2:f6: + 6a:6a:d3:93:98:c7:31:c0:e5:8a:3a:44:9b:cf:ef: + b9:3d:05:86:03:61:0e:6e:fc:c6:f9:9a:9e:35:d6: + 3d:38:27:48:cb:77:26:97:15:34:a0:0b:1d:97:31: + dd:18:ec:bf:78:d9:32:9e:00:1a:44:6a:78:15:1f: + ac:7b:3e:bb:ad:b2:b4:32:75:8c:11:d8:31:ec:19: + 7d:bf:ba:5d:1e:70:38:62:10:cf:3a:8a:a4:98:83: + b4:df:e0:50:3b:e5:ec:24:a0:89:14:2c:19:27:48: + 66:c3:d4:1d:74:63:be:63:38:95:3f:64:d0:91:ac: + 95:f7:d9:ca:96:b5:1b:e7:71:70:7b:5f:3b:12:30: + 2c:b8:3a:28:79:84:9c:81:12:db:38:31:6d:2d:2a: + e2:80:05:5c:29:77:53:58:10:19:ee:f9:50:e1:8d: + 3b:2b:e2:c0:0b:d2:9f:3c:a0:95:33:f8:33:17:ce: + 23:0e:31:e8:1e:3d:7e:6a:c9:6d:83:9e:0b:fa:43: + d2:4a:3f:be:d3:19:07:1e:8c:e4:f6:dc:8f:c3:3e: + 3a:8e:66:4a:87:ef:0b:39:db:e8:3e:30:1c:91:9e: + b3:1e:d3:a0:1e:1b:9a:b1:58:99:de:a5:bb:53:3b: + 3b:5d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + 60:FA:21:CE:1C:B5:31:8D:9B:01:F6:08:5B:72:4D:59:5A:F8:71:8C + X509v3 Key Usage: critical + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication, Microsoft Server Gated Crypto, Netscape Server Gated Crypto, E-mail Protection + X509v3 Authority Key Identifier: + keyid:50:9B:6F:74:01:E3:1A:03:57:AB:D9:D5:7D:15:64:4C:25:F3:F8:F4 + + X509v3 Subject Alternative Name: + DNS:*.test.example + Signature Algorithm: sha512WithRSAEncryption + 79:82:f2:54:44:98:96:25:c2:83:c9:0f:19:69:1c:f6:a7:19: + 0d:61:90:f9:96:23:e2:ab:5a:30:db:55:d7:4f:b0:ff:b2:7b: + 41:da:35:97:47:86:e4:85:00:6d:11:64:ee:32:a4:64:ee:fe: + b2:83:a5:24:4a:ce:c3:91:ae:db:3d:5b:af:fa:7e:81:1a:1c: + 69:d0:1a:9e:70:0e:9e:74:85:6b:48:90:6a:1b:62:ff:6e:b3: + 84:30:b7:7f:fa:c0:3e:ee:91:70:0b:f2:13:ea:c8:2c:aa:d8: + cb:3c:60:b1:08:f9:8e:bf:c2:e4:ce:92:6a:7e:0a:41:49:94: + 8f:e5:6e:71:f9:47:04:1a:18:1f:65:47:d6:1c:ea:a9:90:71: + 82:1b:3b:1f:a5:f2:02:ce:5c:d6:2e:5d:1e:05:c4:92:9e:3d: + 8e:ce:fa:00:83:01:d5:c3:c1:cf:e2:e5:fb:08:80:08:f4:6c: + 26:64:96:db:cd:be:4c:e7:bc:8f:af:3d:0e:0c:f7:d2:52:15: + 9c:d5:15:0d:51:b3:95:72:78:1d:8c:ca:37:55:7a:c0:b0:0f: + 18:ae:de:d0:27:6f:1b:e4:5d:1d:4b:f9:4c:5d:44:49:ed:cf: + c2:9e:e7:c6:55:72:ce:2f:43:a7:2f:88:de:b7:da:9f:82:a6: + 54:77:c2:2e +-----BEGIN CERTIFICATE----- +MIIDmTCCAoGgAwIBAgIBEzANBgkqhkiG9w0BAQ0FADAtMQswCQYDVQQGEwJJVDEM +MAoGA1UECgwDSUdJMRAwDgYDVQQDDAdUZXN0IENBMB4XDTIyMTAxOTA4NTU1N1oX +DTMyMTAxNjA4NTU1N1owNDELMAkGA1UEBhMCSVQxDDAKBgNVBAoMA0lHSTEXMBUG +A1UEAwwOKi50ZXN0LmV4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDnOgGokxII9KbJiRCi9mpq05OYxzHA5Yo6RJvP77k9BYYDYQ5u/Mb5mp41 +1j04J0jLdyaXFTSgCx2XMd0Y7L942TKeABpEangVH6x7PrutsrQydYwR2DHsGX2/ +ul0ecDhiEM86iqSYg7Tf4FA75ewkoIkULBknSGbD1B10Y75jOJU/ZNCRrJX32cqW +tRvncXB7XzsSMCy4Oih5hJyBEts4MW0tKuKABVwpd1NYEBnu+VDhjTsr4sAL0p88 +oJUz+DMXziMOMegePX5qyW2Dngv6Q9JKP77TGQcejOT23I/DPjqOZkqH7ws52+g+ +MByRnrMe06AeG5qxWJnepbtTOztdAgMBAAGjgbwwgbkwDAYDVR0TAQH/BAIwADAd +BgNVHQ4EFgQUYPohzhy1MY2bAfYIW3JNWVr4cYwwDgYDVR0PAQH/BAQDAgXgMD4G +A1UdJQQ3MDUGCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJYIZIAYb4 +QgQBBggrBgEFBQcDBDAfBgNVHSMEGDAWgBRQm290AeMaA1er2dV9FWRMJfP49DAZ +BgNVHREEEjAQgg4qLnRlc3QuZXhhbXBsZTANBgkqhkiG9w0BAQ0FAAOCAQEAeYLy +VESYliXCg8kPGWkc9qcZDWGQ+ZYj4qtaMNtV10+w/7J7Qdo1l0eG5IUAbRFk7jKk +ZO7+soOlJErOw5Gu2z1br/p+gRocadAannAOnnSFa0iQahti/26zhDC3f/rAPu6R +cAvyE+rILKrYyzxgsQj5jr/C5M6San4KQUmUj+VucflHBBoYH2VH1hzqqZBxghs7 +H6XyAs5c1i5dHgXEkp49js76AIMB1cPBz+Ll+wiACPRsJmSW282+TOe8j689Dgz3 +0lIVnNUVDVGzlXJ4HYzKN1V6wLAPGK7e0CdvG+RdHUv5TF1ESe3Pwp7nxlVyzi9D +py+I3rfan4KmVHfCLg== +-----END CERTIFICATE----- diff --git a/compose/voms-replica/assets/certs/voms.test.example.key.pem b/compose/voms-replica/assets/certs/voms.test.example.key.pem new file mode 100644 index 000000000..610502b89 --- /dev/null +++ b/compose/voms-replica/assets/certs/voms.test.example.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA5zoBqJMSCPSmyYkQovZqatOTmMcxwOWKOkSbz++5PQWGA2EO +bvzG+ZqeNdY9OCdIy3cmlxU0oAsdlzHdGOy/eNkyngAaRGp4FR+sez67rbK0MnWM +Edgx7Bl9v7pdHnA4YhDPOoqkmIO03+BQO+XsJKCJFCwZJ0hmw9QddGO+YziVP2TQ +kayV99nKlrUb53Fwe187EjAsuDooeYScgRLbODFtLSrigAVcKXdTWBAZ7vlQ4Y07 +K+LAC9KfPKCVM/gzF84jDjHoHj1+asltg54L+kPSSj++0xkHHozk9tyPwz46jmZK +h+8LOdvoPjAckZ6zHtOgHhuasViZ3qW7Uzs7XQIDAQABAoIBAAx5xL0jskVpbdZR +3uPsB7Hb2IrVtImD2QFr0jxV4ti4A5MLGYxDdzjgbsjY1lTBSdwwgZSFQGGiN+aA +ej1uCKaskV6VAtXOKMx6+QNtTxMAIVjXnscXsxnaBj7h/0Q1KdWgso2mDVttP8UU +hT+2GBeh0cOU3YaREXpfZ3dwKkWQHbtO/UYwVzu+XVFt8kApPoLMMHoXZfetP6Yp +7YSCuI6id44mwqkP7aY8iGhcUpVTkP3LD7z8nUp4LaG9my6T1Wev8x7hstb/NIsZ +DPiXAzfDUkHWqpMthnoWyOdghGc6JzKGFeJVHqrW4byJ4hNU3WvNIdvZ8tyIEpd1 +56uP/gECgYEA92oUhzHjvw87qfo6tPDai2I8AghXJoPGB6xYYhchlirYMGPx9fU/ +rcVEGbmSBDqXMg9eZUqiXB+E/hukCOrFZJt4kt656Nm/Xy68IDwSifmf5vcUde6q +j0pD6i0vwJFjYWBjjS7gRBK83pr/jHhy8aK1+79lZ0GfbQkLxF/2TxkCgYEA70Af +A387tHDmct7ZH0gAZx9QKYZhtS+WWVCIoZ81028DEeGri0By83KFkU0QZ9RfWKQi +RajBYkB35xJFv4fSX5s4+tcVaTVJKOn7V5YGmUIxrGY3IMuE77+h9SEHd8GY723q +9qgwTF5SQP3cGiVpGFB99M44CBuHbbypFh67iuUCgYEA3Zp6QI2C/AJc4mZqZt7E +IMwgC4IE7U5h9UV89H7banF9qfobIr5EBxUFZjU8f+Uqv3/cgMVUn0bsC94eEo6V +twM5//LWeaVvL4Xgos6rnEGl422zOd5HjohqRDms58JRTUrUYAR4gwB1gr0530uT +SLMAZTiNTusMLNFJZN6+8yECgYAulAY1sRSXmY9T98y/iU4CxZberrnhA2W697HR +/WQGSMuJNK0oDCEVAku8sQsrm64AXNwLQcJ8dV6iju0jT7cGQ/sA4tTZSbV3kK4N +LDkWp0tya+f5q4WzA1Ttm0OP7hHvMzAWW0Ij7A0JeCLcuEHQqQMMoQVJlspz89Hb +a5pJfQKBgFZb6XnLMTSCs/SQe38PQiawIQcA+zXmhG83xkEKspQGm2KqyJL+AdKQ +fXQKoKa/Ubyp7PKRJVZ8raX1/kvtFDQIQ+G3L/hps5rhZgDh5S2n0xd4zlbK/Sw6 +l3RjOUpHSe8oz+X3Jinl/Rwr39I9hrRAW2xj7vkFb84IE98mJu2X +-----END RSA PRIVATE KEY----- diff --git a/compose/voms-replica/assets/db-logs/.gitignore b/compose/voms-replica/assets/db-logs/.gitignore new file mode 100644 index 000000000..bf0824e59 --- /dev/null +++ b/compose/voms-replica/assets/db-logs/.gitignore @@ -0,0 +1 @@ +*.log \ No newline at end of file diff --git a/compose/voms-replica/assets/db-primary/iam-test-dump.sql b/compose/voms-replica/assets/db-primary/iam-test-dump.sql new file mode 100644 index 000000000..f4bc1e825 --- /dev/null +++ b/compose/voms-replica/assets/db-primary/iam-test-dump.sql @@ -0,0 +1,2366 @@ +-- MySQL dump 10.13 Distrib 8.0.36, for Linux (x86_64) +-- +-- Host: iam.local.io Database: iam +-- ------------------------------------------------------ +-- Server version 5.7.34 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `access_token` +-- + +DROP TABLE IF EXISTS `access_token`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `access_token` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `token_value` varchar(4096) DEFAULT NULL, + `expiration` timestamp NULL DEFAULT NULL, + `token_type` varchar(256) DEFAULT NULL, + `refresh_token_id` bigint(20) DEFAULT NULL, + `client_id` bigint(20) DEFAULT NULL, + `auth_holder_id` bigint(20) DEFAULT NULL, + `id_token_id` bigint(20) DEFAULT NULL, + `approved_site_id` bigint(20) DEFAULT NULL, + `token_value_hash` char(64) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `at_tvh_idx` (`token_value_hash`), + KEY `at_tv_idx` (`token_value`(767)), + KEY `at_exp_idx` (`expiration`), + KEY `at_ahi_idx` (`auth_holder_id`), + KEY `FK_access_token_refresh_token_id` (`refresh_token_id`), + KEY `FK_access_token_client_id` (`client_id`), + CONSTRAINT `FK_access_token_auth_holder_id` FOREIGN KEY (`auth_holder_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE, + CONSTRAINT `FK_access_token_client_id` FOREIGN KEY (`client_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE, + CONSTRAINT `FK_access_token_refresh_token_id` FOREIGN KEY (`refresh_token_id`) REFERENCES `refresh_token` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `access_token` +-- + +LOCK TABLES `access_token` WRITE; +/*!40000 ALTER TABLE `access_token` DISABLE KEYS */; +/*!40000 ALTER TABLE `access_token` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `access_token_permissions` +-- + +DROP TABLE IF EXISTS `access_token_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `access_token_permissions` ( + `access_token_id` bigint(20) NOT NULL, + `permission_id` bigint(20) NOT NULL, + PRIMARY KEY (`access_token_id`,`permission_id`), + KEY `FK_access_token_permissions_permission_id` (`permission_id`), + CONSTRAINT `FK_access_token_permissions_access_token_id` FOREIGN KEY (`access_token_id`) REFERENCES `access_token` (`id`) ON DELETE CASCADE, + CONSTRAINT `FK_access_token_permissions_permission_id` FOREIGN KEY (`permission_id`) REFERENCES `permission` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `access_token_permissions` +-- + +LOCK TABLES `access_token_permissions` WRITE; +/*!40000 ALTER TABLE `access_token_permissions` DISABLE KEYS */; +/*!40000 ALTER TABLE `access_token_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `address` +-- + +DROP TABLE IF EXISTS `address`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `address` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `formatted` varchar(256) DEFAULT NULL, + `street_address` varchar(256) DEFAULT NULL, + `locality` varchar(256) DEFAULT NULL, + `region` varchar(256) DEFAULT NULL, + `postal_code` varchar(256) DEFAULT NULL, + `country` varchar(256) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `address` +-- + +LOCK TABLES `address` WRITE; +/*!40000 ALTER TABLE `address` DISABLE KEYS */; +/*!40000 ALTER TABLE `address` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `approved_site` +-- + +DROP TABLE IF EXISTS `approved_site`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `approved_site` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `user_id` varchar(256) DEFAULT NULL, + `client_id` varchar(256) DEFAULT NULL, + `creation_date` timestamp NULL DEFAULT NULL, + `access_date` timestamp NULL DEFAULT NULL, + `timeout_date` timestamp NULL DEFAULT NULL, + `whitelisted_site_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `FK_approved_site_client_id` (`client_id`), + CONSTRAINT `FK_approved_site_client_id` FOREIGN KEY (`client_id`) REFERENCES `client_details` (`client_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `approved_site` +-- + +LOCK TABLES `approved_site` WRITE; +/*!40000 ALTER TABLE `approved_site` DISABLE KEYS */; +/*!40000 ALTER TABLE `approved_site` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `approved_site_scope` +-- + +DROP TABLE IF EXISTS `approved_site_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `approved_site_scope` ( + `owner_id` bigint(20) DEFAULT NULL, + `scope` varchar(256) DEFAULT NULL, + KEY `FK_approved_site_scope_owner_id` (`owner_id`), + CONSTRAINT `FK_approved_site_scope_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `approved_site` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `approved_site_scope` +-- + +LOCK TABLES `approved_site_scope` WRITE; +/*!40000 ALTER TABLE `approved_site_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `approved_site_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `authentication_holder` +-- + +DROP TABLE IF EXISTS `authentication_holder`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `authentication_holder` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `user_auth_id` bigint(20) DEFAULT NULL, + `approved` tinyint(1) DEFAULT NULL, + `redirect_uri` varchar(2048) DEFAULT NULL, + `client_id` varchar(256) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `FK_authentication_holder_user_auth_id` (`user_auth_id`), + KEY `FK_authentication_holder_client_id` (`client_id`), + CONSTRAINT `FK_authentication_holder_client_id` FOREIGN KEY (`client_id`) REFERENCES `client_details` (`client_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `FK_authentication_holder_user_auth_id` FOREIGN KEY (`user_auth_id`) REFERENCES `saved_user_auth` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `authentication_holder` +-- + +LOCK TABLES `authentication_holder` WRITE; +/*!40000 ALTER TABLE `authentication_holder` DISABLE KEYS */; +/*!40000 ALTER TABLE `authentication_holder` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `authentication_holder_authority` +-- + +DROP TABLE IF EXISTS `authentication_holder_authority`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `authentication_holder_authority` ( + `owner_id` bigint(20) DEFAULT NULL, + `authority` varchar(256) DEFAULT NULL, + KEY `aha_oi_idx` (`owner_id`), + CONSTRAINT `FK_authentication_holder_authority_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `authentication_holder_authority` +-- + +LOCK TABLES `authentication_holder_authority` WRITE; +/*!40000 ALTER TABLE `authentication_holder_authority` DISABLE KEYS */; +/*!40000 ALTER TABLE `authentication_holder_authority` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `authentication_holder_extension` +-- + +DROP TABLE IF EXISTS `authentication_holder_extension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `authentication_holder_extension` ( + `owner_id` bigint(20) DEFAULT NULL, + `extension` varchar(2048) DEFAULT NULL, + `val` varchar(2048) DEFAULT NULL, + KEY `ahe_oi_idx` (`owner_id`), + CONSTRAINT `FK_authentication_holder_extension_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `authentication_holder_extension` +-- + +LOCK TABLES `authentication_holder_extension` WRITE; +/*!40000 ALTER TABLE `authentication_holder_extension` DISABLE KEYS */; +/*!40000 ALTER TABLE `authentication_holder_extension` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `authentication_holder_request_parameter` +-- + +DROP TABLE IF EXISTS `authentication_holder_request_parameter`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `authentication_holder_request_parameter` ( + `owner_id` bigint(20) DEFAULT NULL, + `param` varchar(2048) DEFAULT NULL, + `val` varchar(2048) DEFAULT NULL, + KEY `ahrp_oi_idx` (`owner_id`), + CONSTRAINT `FK_authentication_holder_request_parameter_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `authentication_holder_request_parameter` +-- + +LOCK TABLES `authentication_holder_request_parameter` WRITE; +/*!40000 ALTER TABLE `authentication_holder_request_parameter` DISABLE KEYS */; +/*!40000 ALTER TABLE `authentication_holder_request_parameter` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `authentication_holder_resource_id` +-- + +DROP TABLE IF EXISTS `authentication_holder_resource_id`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `authentication_holder_resource_id` ( + `owner_id` bigint(20) DEFAULT NULL, + `resource_id` varchar(2048) DEFAULT NULL, + KEY `ahri_oi_idx` (`owner_id`), + CONSTRAINT `FK_authentication_holder_resource_id_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `authentication_holder_resource_id` +-- + +LOCK TABLES `authentication_holder_resource_id` WRITE; +/*!40000 ALTER TABLE `authentication_holder_resource_id` DISABLE KEYS */; +/*!40000 ALTER TABLE `authentication_holder_resource_id` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `authentication_holder_response_type` +-- + +DROP TABLE IF EXISTS `authentication_holder_response_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `authentication_holder_response_type` ( + `owner_id` bigint(20) DEFAULT NULL, + `response_type` varchar(2048) DEFAULT NULL, + KEY `ahrt_oi_idx` (`owner_id`), + CONSTRAINT `FK_authentication_holder_response_type_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `authentication_holder_response_type` +-- + +LOCK TABLES `authentication_holder_response_type` WRITE; +/*!40000 ALTER TABLE `authentication_holder_response_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `authentication_holder_response_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `authentication_holder_scope` +-- + +DROP TABLE IF EXISTS `authentication_holder_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `authentication_holder_scope` ( + `owner_id` bigint(20) DEFAULT NULL, + `scope` varchar(2048) DEFAULT NULL, + KEY `ahs_oi_idx` (`owner_id`), + CONSTRAINT `FK_authentication_holder_scope_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `authentication_holder_scope` +-- + +LOCK TABLES `authentication_holder_scope` WRITE; +/*!40000 ALTER TABLE `authentication_holder_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `authentication_holder_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `authorization_code` +-- + +DROP TABLE IF EXISTS `authorization_code`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `authorization_code` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `code` varchar(256) DEFAULT NULL, + `auth_holder_id` bigint(20) DEFAULT NULL, + `expiration` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `ac_ahi_idx` (`auth_holder_id`), + CONSTRAINT `FK_authorization_code_auth_holder_id` FOREIGN KEY (`auth_holder_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `authorization_code` +-- + +LOCK TABLES `authorization_code` WRITE; +/*!40000 ALTER TABLE `authorization_code` DISABLE KEYS */; +/*!40000 ALTER TABLE `authorization_code` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `blacklisted_site` +-- + +DROP TABLE IF EXISTS `blacklisted_site`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `blacklisted_site` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `uri` varchar(2048) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `blacklisted_site` +-- + +LOCK TABLES `blacklisted_site` WRITE; +/*!40000 ALTER TABLE `blacklisted_site` DISABLE KEYS */; +/*!40000 ALTER TABLE `blacklisted_site` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `claim` +-- + +DROP TABLE IF EXISTS `claim`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `claim` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(256) DEFAULT NULL, + `friendly_name` varchar(1024) DEFAULT NULL, + `claim_type` varchar(1024) DEFAULT NULL, + `claim_value` varchar(1024) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `claim` +-- + +LOCK TABLES `claim` WRITE; +/*!40000 ALTER TABLE `claim` DISABLE KEYS */; +/*!40000 ALTER TABLE `claim` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `claim_issuer` +-- + +DROP TABLE IF EXISTS `claim_issuer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `claim_issuer` ( + `owner_id` bigint(20) NOT NULL, + `issuer` varchar(1024) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `claim_issuer` +-- + +LOCK TABLES `claim_issuer` WRITE; +/*!40000 ALTER TABLE `claim_issuer` DISABLE KEYS */; +/*!40000 ALTER TABLE `claim_issuer` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `claim_to_permission_ticket` +-- + +DROP TABLE IF EXISTS `claim_to_permission_ticket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `claim_to_permission_ticket` ( + `permission_ticket_id` bigint(20) NOT NULL, + `claim_id` bigint(20) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `claim_to_permission_ticket` +-- + +LOCK TABLES `claim_to_permission_ticket` WRITE; +/*!40000 ALTER TABLE `claim_to_permission_ticket` DISABLE KEYS */; +/*!40000 ALTER TABLE `claim_to_permission_ticket` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `claim_to_policy` +-- + +DROP TABLE IF EXISTS `claim_to_policy`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `claim_to_policy` ( + `policy_id` bigint(20) NOT NULL, + `claim_id` bigint(20) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `claim_to_policy` +-- + +LOCK TABLES `claim_to_policy` WRITE; +/*!40000 ALTER TABLE `claim_to_policy` DISABLE KEYS */; +/*!40000 ALTER TABLE `claim_to_policy` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `claim_token_format` +-- + +DROP TABLE IF EXISTS `claim_token_format`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `claim_token_format` ( + `owner_id` bigint(20) NOT NULL, + `claim_token_format` varchar(1024) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `claim_token_format` +-- + +LOCK TABLES `claim_token_format` WRITE; +/*!40000 ALTER TABLE `claim_token_format` DISABLE KEYS */; +/*!40000 ALTER TABLE `claim_token_format` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_authority` +-- + +DROP TABLE IF EXISTS `client_authority`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_authority` ( + `owner_id` bigint(20) DEFAULT NULL, + `authority` varchar(256) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_authority` +-- + +LOCK TABLES `client_authority` WRITE; +/*!40000 ALTER TABLE `client_authority` DISABLE KEYS */; +/*!40000 ALTER TABLE `client_authority` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_claims_redirect_uri` +-- + +DROP TABLE IF EXISTS `client_claims_redirect_uri`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_claims_redirect_uri` ( + `owner_id` bigint(20) DEFAULT NULL, + `redirect_uri` varchar(2048) DEFAULT NULL, + KEY `FK_client_claims_redirect_uri_owner_id` (`owner_id`), + CONSTRAINT `FK_client_claims_redirect_uri_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_claims_redirect_uri` +-- + +LOCK TABLES `client_claims_redirect_uri` WRITE; +/*!40000 ALTER TABLE `client_claims_redirect_uri` DISABLE KEYS */; +/*!40000 ALTER TABLE `client_claims_redirect_uri` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_contact` +-- + +DROP TABLE IF EXISTS `client_contact`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_contact` ( + `owner_id` bigint(20) DEFAULT NULL, + `contact` varchar(256) DEFAULT NULL, + KEY `FK_client_contact_owner_id` (`owner_id`), + CONSTRAINT `FK_client_contact_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_contact` +-- + +LOCK TABLES `client_contact` WRITE; +/*!40000 ALTER TABLE `client_contact` DISABLE KEYS */; +/*!40000 ALTER TABLE `client_contact` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_default_acr_value` +-- + +DROP TABLE IF EXISTS `client_default_acr_value`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_default_acr_value` ( + `owner_id` bigint(20) DEFAULT NULL, + `default_acr_value` varchar(2000) DEFAULT NULL, + KEY `FK_client_default_acr_value_owner_id` (`owner_id`), + CONSTRAINT `FK_client_default_acr_value_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_default_acr_value` +-- + +LOCK TABLES `client_default_acr_value` WRITE; +/*!40000 ALTER TABLE `client_default_acr_value` DISABLE KEYS */; +/*!40000 ALTER TABLE `client_default_acr_value` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_details` +-- + +DROP TABLE IF EXISTS `client_details`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_details` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `client_description` varchar(1024) DEFAULT NULL, + `reuse_refresh_tokens` tinyint(1) NOT NULL DEFAULT '1', + `dynamically_registered` tinyint(1) NOT NULL DEFAULT '0', + `allow_introspection` tinyint(1) NOT NULL DEFAULT '0', + `id_token_validity_seconds` bigint(20) NOT NULL DEFAULT '600', + `client_id` varchar(256) DEFAULT NULL, + `client_secret` text, + `access_token_validity_seconds` bigint(20) DEFAULT NULL, + `refresh_token_validity_seconds` bigint(20) DEFAULT NULL, + `application_type` varchar(256) DEFAULT NULL, + `client_name` varchar(256) DEFAULT NULL, + `token_endpoint_auth_method` varchar(256) DEFAULT NULL, + `subject_type` varchar(256) DEFAULT NULL, + `logo_uri` text, + `policy_uri` text, + `client_uri` text, + `tos_uri` text, + `jwks_uri` text, + `jwks` text, + `sector_identifier_uri` text, + `request_object_signing_alg` varchar(256) DEFAULT NULL, + `user_info_signed_response_alg` varchar(256) DEFAULT NULL, + `user_info_encrypted_response_alg` varchar(256) DEFAULT NULL, + `user_info_encrypted_response_enc` varchar(256) DEFAULT NULL, + `id_token_signed_response_alg` varchar(256) DEFAULT NULL, + `id_token_encrypted_response_alg` varchar(256) DEFAULT NULL, + `id_token_encrypted_response_enc` varchar(256) DEFAULT NULL, + `token_endpoint_auth_signing_alg` varchar(256) DEFAULT NULL, + `default_max_age` bigint(20) DEFAULT NULL, + `require_auth_time` tinyint(1) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `initiate_login_uri` varchar(2048) DEFAULT NULL, + `clear_access_tokens_on_refresh` tinyint(1) NOT NULL DEFAULT '1', + `software_statement` text, + `code_challenge_method` varchar(256) DEFAULT NULL, + `software_id` text, + `software_version` text, + `device_code_validity_seconds` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `client_id` (`client_id`), + KEY `cd_ci_idx` (`client_id`) +) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_details` +-- + +LOCK TABLES `client_details` WRITE; +/*!40000 ALTER TABLE `client_details` DISABLE KEYS */; +INSERT INTO `client_details` VALUES (1,NULL,1,0,1,600,'client','secret',3600,NULL,NULL,'Test Client','SECRET_BASIC',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(2,NULL,1,0,1,0,'tasks-app','secret',0,NULL,NULL,'Tasks App','SECRET_BASIC',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(3,NULL,1,0,1,600,'post-client','secret',3600,NULL,NULL,'Post client','SECRET_POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(4,NULL,1,0,1,600,'client-cred','secret',3600,NULL,NULL,'Client credentials','SECRET_BASIC',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(5,NULL,1,0,1,600,'password-grant','secret',3600,NULL,NULL,'Password grant client','SECRET_BASIC',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(6,NULL,1,0,1,600,'scim-client-ro','secret',3600,NULL,NULL,'SCIM client (read-only)','SECRET_POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,600),(7,NULL,1,0,1,600,'scim-client-rw','secret',3600,NULL,NULL,'SCIM client (read-write)','SECRET_POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,600),(8,NULL,1,0,1,600,'token-exchange-actor','secret',3600,NULL,NULL,'Token Exchange grant client actor','SECRET_POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(9,NULL,1,0,1,600,'token-exchange-subject','secret',3600,NULL,NULL,'Token Exchange grant client subject','SECRET_POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(10,NULL,1,0,1,600,'registration-client','secret',3600,NULL,NULL,'Registration service test client','SECRET_POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(11,NULL,1,0,1,600,'token-lookup-client','secret',3600,NULL,NULL,'Token lookup client','SECRET_BASIC',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(12,NULL,1,0,1,600,'device-code-client','secret',3600,NULL,NULL,'Device code client','SECRET_BASIC',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,600),(13,NULL,1,0,0,600,'implicit-flow-client',NULL,3600,NULL,NULL,'Implicit Flow client',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,600),(14,NULL,1,0,0,600,'public-dc-client',NULL,3600,NULL,NULL,'Public Device Code client',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,600),(15,NULL,1,0,1,600,'jwt-auth-client_secret_jwt','c8e9eed0-e6e4-4a66-b16e-6f37096356a7',3600,NULL,NULL,'JWT Bearer Auth Client (client_secret_jwt)','SECRET_JWT',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'HS256',NULL,0,NULL,NULL,1,NULL,NULL,NULL,NULL,NULL),(16,NULL,1,0,1,600,'jwt-auth-private_key_jwt','secret',3600,NULL,NULL,'JWT Bearer Auth Client (private_key_jwt)','PRIVATE_KEY',NULL,NULL,NULL,NULL,NULL,NULL,'{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"kid\":\"rsa1\",\"n\":\"1y1CP181zqPNPlV1JDM7Xv0QnGswhSTHe8_XPZHxDTJkykpk_1BmgA3ovP62QRE2ORgsv5oSBI_Z_RaOc4Zx2FonjEJF2oBHtBjsAiF-pxGkM5ZPjFNgFTGp1yUUBjFDcEeIGCwPEyYSt93sQIP_0DRbViMUnpyn3xgM_a1dO5brEWR2n1Uqff1yA5NXfLS03qpl2dpH4HFY5-Zs4bvtJykpAOhoHuIQbz-hmxb9MZ3uTAwsx2HiyEJtz-suyTBHO3BM2o8UcCeyfa34ShPB8i86-sf78fOk2KeRIW1Bju3ANmdV3sxL0j29cesxKCZ06u2ZiGR3Srbft8EdLPzf-w\"}]}',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'RS256',NULL,0,NULL,NULL,1,NULL,NULL,NULL,NULL,NULL),(17,NULL,1,0,1,600,'admin-client-ro','secret',3600,NULL,NULL,'Admin client (read-only)','SECRET_POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(18,NULL,1,0,1,600,'admin-client-rw','secret',3600,NULL,NULL,'Admin client (read-write)','SECRET_POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL),(19,NULL,1,0,1,600,'public-client',NULL,3600,3600,NULL,'Public client','NONE',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,'2024-03-27 17:43:07',NULL,1,NULL,NULL,NULL,NULL,NULL); +/*!40000 ALTER TABLE `client_details` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_grant_type` +-- + +DROP TABLE IF EXISTS `client_grant_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_grant_type` ( + `owner_id` bigint(20) DEFAULT NULL, + `grant_type` varchar(2000) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_grant_type` +-- + +LOCK TABLES `client_grant_type` WRITE; +/*!40000 ALTER TABLE `client_grant_type` DISABLE KEYS */; +INSERT INTO `client_grant_type` VALUES (1,'authorization_code'),(1,'urn:ietf:params:oauth:grant_type:redelegate'),(1,'implicit'),(1,'refresh_token'),(3,'authorization_code'),(3,'client_credentials'),(4,'password'),(4,'client_credentials'),(5,'password'),(5,'refresh_token'),(6,'client_credentials'),(7,'client_credentials'),(7,'refresh_token'),(7,'urn:ietf:params:oauth:grant-type:device_code'),(8,'urn:ietf:params:oauth:grant-type:token-exchange'),(8,'client_credentials'),(8,'password'),(8,'refresh_token'),(9,'password'),(9,'refresh_token'),(9,'client_credentials'),(10,'client_credentials'),(10,'refresh_token'),(11,'authorization_code'),(11,'refresh_token'),(11,'client_credentials'),(11,'urn:ietf:params:oauth:grant-type:token-exchange'),(12,'refresh_token'),(12,'urn:ietf:params:oauth:grant-type:device_code'),(13,'implicit'),(14,'urn:ietf:params:oauth:grant-type:device_code'),(17,'client_credentials'),(17,'urn:ietf:params:oauth:grant-type:device_code'),(17,'authorization_code'),(18,'client_credentials'),(18,'urn:ietf:params:oauth:grant-type:device_code'),(18,'authorization_code'),(19,'client_credentials'); +/*!40000 ALTER TABLE `client_grant_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_post_logout_redirect_uri` +-- + +DROP TABLE IF EXISTS `client_post_logout_redirect_uri`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_post_logout_redirect_uri` ( + `owner_id` bigint(20) DEFAULT NULL, + `post_logout_redirect_uri` varchar(2000) DEFAULT NULL, + KEY `FK_client_post_logout_redirect_uri_owner_id` (`owner_id`), + CONSTRAINT `FK_client_post_logout_redirect_uri_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_post_logout_redirect_uri` +-- + +LOCK TABLES `client_post_logout_redirect_uri` WRITE; +/*!40000 ALTER TABLE `client_post_logout_redirect_uri` DISABLE KEYS */; +/*!40000 ALTER TABLE `client_post_logout_redirect_uri` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_redirect_uri` +-- + +DROP TABLE IF EXISTS `client_redirect_uri`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_redirect_uri` ( + `owner_id` bigint(20) DEFAULT NULL, + `redirect_uri` varchar(2048) DEFAULT NULL, + KEY `FK_client_redirect_uri_owner_id` (`owner_id`), + CONSTRAINT `FK_client_redirect_uri_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_redirect_uri` +-- + +LOCK TABLES `client_redirect_uri` WRITE; +/*!40000 ALTER TABLE `client_redirect_uri` DISABLE KEYS */; +INSERT INTO `client_redirect_uri` VALUES (1,'http://localhost:9090/iam-test-client/openid_connect_login'),(1,'https://iam.local.io/iam-test-client/openid_connect_login'),(3,'http://localhost:4000/callback'),(4,'http://localhost:5000/callback'),(11,'http://localhost:1234/callback'),(13,'http://localhost:9876/implicit'); +/*!40000 ALTER TABLE `client_redirect_uri` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_request_uri` +-- + +DROP TABLE IF EXISTS `client_request_uri`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_request_uri` ( + `owner_id` bigint(20) DEFAULT NULL, + `request_uri` varchar(2000) DEFAULT NULL, + KEY `FK_client_request_uri_owner_id` (`owner_id`), + CONSTRAINT `FK_client_request_uri_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_request_uri` +-- + +LOCK TABLES `client_request_uri` WRITE; +/*!40000 ALTER TABLE `client_request_uri` DISABLE KEYS */; +/*!40000 ALTER TABLE `client_request_uri` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_resource` +-- + +DROP TABLE IF EXISTS `client_resource`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_resource` ( + `owner_id` bigint(20) DEFAULT NULL, + `resource_id` varchar(256) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_resource` +-- + +LOCK TABLES `client_resource` WRITE; +/*!40000 ALTER TABLE `client_resource` DISABLE KEYS */; +/*!40000 ALTER TABLE `client_resource` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_response_type` +-- + +DROP TABLE IF EXISTS `client_response_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_response_type` ( + `owner_id` bigint(20) DEFAULT NULL, + `response_type` varchar(2000) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_response_type` +-- + +LOCK TABLES `client_response_type` WRITE; +/*!40000 ALTER TABLE `client_response_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `client_response_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `client_scope` +-- + +DROP TABLE IF EXISTS `client_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `client_scope` ( + `owner_id` bigint(20) DEFAULT NULL, + `scope` varchar(2048) DEFAULT NULL, + KEY `FK_client_scope_owner_id` (`owner_id`), + CONSTRAINT `FK_client_scope_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `client_scope` +-- + +LOCK TABLES `client_scope` WRITE; +/*!40000 ALTER TABLE `client_scope` DISABLE KEYS */; +INSERT INTO `client_scope` VALUES (1,'openid'),(1,'profile'),(1,'email'),(1,'address'),(1,'phone'),(1,'offline_access'),(1,'read-tasks'),(1,'write-tasks'),(1,'read:/'),(1,'write:/'),(1,'attr'),(1,'scim:read'),(1,'scim:write'),(1,'iam:admin.read'),(1,'iam:admin.write'),(2,'openid'),(2,'profile'),(2,'read-tasks'),(2,'write-tasks'),(3,'openid'),(3,'profile'),(3,'read-tasks'),(3,'write-tasks'),(4,'openid'),(4,'profile'),(4,'read-tasks'),(4,'write-tasks'),(4,'offline_access'),(4,'storage.read:/'),(4,'storage.write:/'),(4,'wlcg.groups'),(5,'openid'),(5,'profile'),(5,'email'),(5,'address'),(5,'phone'),(5,'offline_access'),(5,'scim:read'),(5,'scim:write'),(5,'proxy:generate'),(5,'wlcg.groups'),(5,'storage.read:/'),(5,'storage.modify:/'),(5,'storage.create:/'),(5,'attr'),(6,'openid'),(6,'profile'),(6,'email'),(6,'address'),(6,'phone'),(6,'offline_access'),(6,'scim:read'),(7,'openid'),(7,'profile'),(7,'email'),(7,'address'),(7,'phone'),(7,'offline_access'),(7,'scim:read'),(7,'scim:write'),(8,'openid'),(8,'profile'),(8,'email'),(8,'address'),(8,'phone'),(8,'offline_access'),(8,'read-tasks'),(8,'storage.read:/'),(8,'storage.write:/'),(9,'openid'),(9,'profile'),(9,'offline_access'),(9,'storage.read:/'),(9,'storage.write:/'),(10,'openid'),(10,'profile'),(10,'registration:read'),(10,'registration:write'),(10,'scim:write'),(10,'scim:read'),(11,'openid'),(11,'profile'),(11,'email'),(11,'address'),(11,'phone'),(11,'offline_access'),(11,'read-tasks'),(11,'write-tasks'),(12,'openid'),(12,'profile'),(12,'email'),(12,'address'),(12,'phone'),(12,'offline_access'),(13,'openid'),(13,'profile'),(13,'email'),(13,'address'),(13,'phone'),(14,'profile'),(14,'email'),(14,'address'),(14,'phone'),(17,'iam:admin.read'),(18,'iam:admin.read'),(18,'iam:admin.write'),(19,'profile'),(19,'email'),(5,'eduperson_scoped_affiliation'),(5,'eduperson_entitlement'),(5,'eduperson_assurance'),(5,'entitlements'); +/*!40000 ALTER TABLE `client_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `device_code` +-- + +DROP TABLE IF EXISTS `device_code`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `device_code` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `device_code` varchar(1024) DEFAULT NULL, + `user_code` varchar(1024) DEFAULT NULL, + `expiration` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `client_id` varchar(256) DEFAULT NULL, + `approved` tinyint(1) DEFAULT NULL, + `auth_holder_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `device_code` +-- + +LOCK TABLES `device_code` WRITE; +/*!40000 ALTER TABLE `device_code` DISABLE KEYS */; +/*!40000 ALTER TABLE `device_code` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `device_code_request_parameter` +-- + +DROP TABLE IF EXISTS `device_code_request_parameter`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `device_code_request_parameter` ( + `owner_id` bigint(20) DEFAULT NULL, + `param` varchar(2048) DEFAULT NULL, + `val` varchar(2048) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `device_code_request_parameter` +-- + +LOCK TABLES `device_code_request_parameter` WRITE; +/*!40000 ALTER TABLE `device_code_request_parameter` DISABLE KEYS */; +/*!40000 ALTER TABLE `device_code_request_parameter` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `device_code_scope` +-- + +DROP TABLE IF EXISTS `device_code_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `device_code_scope` ( + `owner_id` bigint(20) NOT NULL, + `scope` varchar(256) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `device_code_scope` +-- + +LOCK TABLES `device_code_scope` WRITE; +/*!40000 ALTER TABLE `device_code_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `device_code_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_account` +-- + +DROP TABLE IF EXISTS `iam_account`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_account` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `active` tinyint(1) NOT NULL DEFAULT '0', + `CREATIONTIME` datetime NOT NULL, + `LASTUPDATETIME` datetime NOT NULL, + `PASSWORD` varchar(128) DEFAULT NULL, + `USERNAME` varchar(128) NOT NULL, + `UUID` varchar(36) NOT NULL, + `user_info_id` bigint(20) DEFAULT NULL, + `confirmation_key` varchar(36) DEFAULT NULL, + `reset_key` varchar(36) DEFAULT NULL, + `provisioned` tinyint(1) NOT NULL DEFAULT '0', + `last_login_time` datetime DEFAULT NULL, + `end_time` datetime DEFAULT NULL, + PRIMARY KEY (`ID`), + UNIQUE KEY `USERNAME` (`USERNAME`), + UNIQUE KEY `UUID` (`UUID`), + KEY `FK_iam_account_user_info_id` (`user_info_id`), + KEY `ia_ct_idx` (`CREATIONTIME`), + KEY `ia_lut_idx` (`LASTUPDATETIME`), + KEY `ia_llt_idx` (`last_login_time`), + KEY `ia_et_idx` (`end_time`), + CONSTRAINT `FK_iam_account_user_info_id` FOREIGN KEY (`user_info_id`) REFERENCES `iam_user_info` (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_account` +-- + +LOCK TABLES `iam_account` WRITE; +/*!40000 ALTER TABLE `iam_account` DISABLE KEYS */; +INSERT INTO `iam_account` VALUES (1,1,'2024-03-27 18:42:54','2024-03-27 18:42:54','$2a$10$2wYm8dK5PL5t9HAI.mWVyuJY8bzsir5TaugC701G4P4zzghtAt9Ty','admin','73f16d93-2441-4a50-88ff-85360d78c6b5',1,NULL,NULL,0,NULL,NULL),(2,1,'2024-03-27 18:43:07','2024-03-27 18:47:59','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test','80e5fb8d-b7c8-451a-89ba-346ae278a66f',2,NULL,NULL,0,NULL,NULL),(3,1,'2024-03-27 18:42:54','2024-03-27 18:42:54','$2a$10$nX.oUqHSe47/0mE3Yr6JYeSsQWhEbruVlPn0h1CCXVHM/aR5pUmee','dup_email_0','bffc67b7-47fe-410c-a6a0-cf00173a8fbb',3,NULL,NULL,0,NULL,NULL),(4,1,'2024-03-27 18:42:54','2024-03-27 18:42:54','$2a$10$cGwVNB2oUJYT7YyE0EE37eWExMNaWvzsrgNwG7fGeAEqO69l2HC6u','dup_email_1','0a6fa72a-fb75-4a6c-9734-bfe673df70b3',4,NULL,NULL,0,NULL,NULL),(5,1,'2024-03-27 18:42:54','2024-03-27 18:42:54','$2a$10$ok8I22EhzEavrRs7xnT31.VtlpGhjPoWIDyNZbwHlmx3gfhdGeeWi','dup_email_2','d836e5ec-246c-456c-8476-923ee2f831c8',5,NULL,NULL,0,NULL,NULL),(100,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_100','f2ce8cb2-a1db-4884-9ef0-d8842cc02b4a',100,NULL,NULL,0,NULL,NULL),(101,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_101','1a78b3b8-22d2-4746-9269-df55aceb036f',101,NULL,NULL,0,NULL,NULL),(102,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_102','a07d60c6-7ffa-475f-98e4-f9f648aa278b',102,NULL,NULL,0,NULL,NULL),(103,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_103','56e1b885-ea25-4ffc-ba17-fcde2b097d02',103,NULL,NULL,0,NULL,NULL),(104,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_104','67d2794d-c7fb-406e-9bc1-b66f43cbe60f',104,NULL,NULL,0,NULL,NULL),(105,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_105','d11e04f7-f369-4de6-9375-394f7d886ac7',105,NULL,NULL,0,NULL,NULL),(106,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_106','bbc76b76-9f9e-443b-8c63-cd775c50c6f3',106,NULL,NULL,0,NULL,NULL),(107,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_107','b15c850c-e6e0-4afb-a02d-374653bb102e',107,NULL,NULL,0,NULL,NULL),(108,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_108','afada6e8-d50d-47f6-912e-d6261605c771',108,NULL,NULL,0,NULL,NULL),(109,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_109','fa3b4c97-4787-4b49-a32c-5b4c74d5a7c8',109,NULL,NULL,0,NULL,NULL),(110,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_110','33165df6-4d49-4728-883c-3fd42720d46b',110,NULL,NULL,0,NULL,NULL),(111,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_111','15fb8d3a-003d-4ef9-8349-867d81d4ae9c',111,NULL,NULL,0,NULL,NULL),(112,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_112','7a4dda33-c2e5-4304-998a-3fa4df481123',112,NULL,NULL,0,NULL,NULL),(113,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_113','7013f989-0a95-43b5-8637-2e2360a73bb3',113,NULL,NULL,0,NULL,NULL),(114,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_114','12caabc8-4766-4028-98ff-f4d7f288a5f0',114,NULL,NULL,0,NULL,NULL),(115,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_115','f463ad2b-5814-4877-bb62-f954c67a8044',115,NULL,NULL,0,NULL,NULL),(116,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_116','28c656c4-5489-4654-a257-0806c6bab905',116,NULL,NULL,0,NULL,NULL),(117,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_117','11be5a72-9416-45fc-a0a7-f3e23c54bfda',117,NULL,NULL,0,NULL,NULL),(118,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_118','3cea2c01-786e-41a3-8fdf-4229cc4e3742',118,NULL,NULL,0,NULL,NULL),(119,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_119','e0247677-4542-4df3-8d75-8efa11e70911',119,NULL,NULL,0,NULL,NULL),(120,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_120','d905a115-d726-4e11-ba1f-b8482177bb05',120,NULL,NULL,0,NULL,NULL),(121,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_121','3479afd1-584c-4479-b6e2-25f6cef2f842',121,NULL,NULL,0,NULL,NULL),(122,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_122','8d4f467d-cb68-4feb-b898-71e4487e6820',122,NULL,NULL,0,NULL,NULL),(123,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_123','0ddee1c2-1426-4b83-b520-e20bdd8ef9b3',123,NULL,NULL,0,NULL,NULL),(124,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_124','b8b638be-6e09-4dbe-bcc0-776c2403e8c7',124,NULL,NULL,0,NULL,NULL),(125,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_125','1dc3108a-b5c0-4e5b-accd-925054075bc4',125,NULL,NULL,0,NULL,NULL),(126,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_126','5eed3374-c131-4513-84b7-dd0ff965da35',126,NULL,NULL,0,NULL,NULL),(127,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_127','2d0b4c36-0301-49f6-a20b-23b6ca48cee2',127,NULL,NULL,0,NULL,NULL),(128,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_128','db46065a-ba62-423d-9397-7bc6fab371a5',128,NULL,NULL,0,NULL,NULL),(129,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_129','d9dbaabf-c51a-45e5-aee1-25134ba283ac',129,NULL,NULL,0,NULL,NULL),(130,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_130','5678f40a-f361-464c-aa71-ffb48d163aaa',130,NULL,NULL,0,NULL,NULL),(131,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_131','209ae3b9-e266-4e57-a639-db29f61a7594',131,NULL,NULL,0,NULL,NULL),(132,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_132','f3fac505-d5c9-4d9c-83af-3976f357f19c',132,NULL,NULL,0,NULL,NULL),(133,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_133','13bfd34b-1dda-452e-bd9a-284aabccf07d',133,NULL,NULL,0,NULL,NULL),(134,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_134','15ccd152-1537-48d4-a55a-fd6565e5d86f',134,NULL,NULL,0,NULL,NULL),(135,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_135','6b2f4fc1-3e98-4f64-8fb4-517d2d4b3fa3',135,NULL,NULL,0,NULL,NULL),(136,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_136','398081ee-9c3c-4e5d-802c-90a4579030d4',136,NULL,NULL,0,NULL,NULL),(137,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_137','89a32317-dd45-481d-91a4-080e30c1f29e',137,NULL,NULL,0,NULL,NULL),(138,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_138','6dc0aa56-011d-45b8-bf26-cb03e8b40ccf',138,NULL,NULL,0,NULL,NULL),(139,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_139','cd62277e-5acf-41af-acea-b4d208cba29e',139,NULL,NULL,0,NULL,NULL),(140,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_140','0ae29eac-64ee-45b4-a2e7-e58b34c7ff0e',140,NULL,NULL,0,NULL,NULL),(141,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_141','0f7fe907-fa84-429e-8057-02d809375ba3',141,NULL,NULL,0,NULL,NULL),(142,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_142','7aa4a733-d318-4392-b3d3-6618263f667d',142,NULL,NULL,0,NULL,NULL),(143,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_143','b1d9b1ac-e77c-4d55-a895-cf0788ed2174',143,NULL,NULL,0,NULL,NULL),(144,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_144','f975f1f7-ad05-4d66-9905-d44c13cbd08b',144,NULL,NULL,0,NULL,NULL),(145,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_145','857f6e6d-e415-4850-a82b-59d557864910',145,NULL,NULL,0,NULL,NULL),(146,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_146','4e1c059c-1d06-4997-8bfa-5bd09fdb4571',146,NULL,NULL,0,NULL,NULL),(147,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_147','f4a0bc7f-b279-4caf-b8d1-c86a3c106f62',147,NULL,NULL,0,NULL,NULL),(148,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_148','007bbb9d-55b1-4f5e-80a5-bbcb22073db4',148,NULL,NULL,0,NULL,NULL),(149,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_149','a1d22bbf-9afe-49da-b75d-b58f825db351',149,NULL,NULL,0,NULL,NULL),(150,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_150','8c2351d5-5460-4b2d-b1bb-7b086130090e',150,NULL,NULL,0,NULL,NULL),(151,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_151','e6651896-66f8-4f63-b44f-71710fdb947c',151,NULL,NULL,0,NULL,NULL),(152,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_152','caf04a3c-8f35-40a3-99b6-48ba6a05d8b8',152,NULL,NULL,0,NULL,NULL),(153,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_153','d501e485-a306-4c9d-9baf-cc75f2321cfd',153,NULL,NULL,0,NULL,NULL),(154,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_154','57466d38-cae8-48bf-ac67-2cfc0266b5b0',154,NULL,NULL,0,NULL,NULL),(155,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_155','4bd5f059-f014-4356-8083-9c1a77adb6fd',155,NULL,NULL,0,NULL,NULL),(156,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_156','69130f52-f251-46fd-99ee-d646938e5f3f',156,NULL,NULL,0,NULL,NULL),(157,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_157','dedfb4f0-a545-44b3-abba-dd77103db894',157,NULL,NULL,0,NULL,NULL),(158,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_158','b5d98a8b-3780-4ace-ace1-ac12829dc469',158,NULL,NULL,0,NULL,NULL),(159,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_159','17de2f08-37fe-469d-b7b1-0e9ea9c6d2d8',159,NULL,NULL,0,NULL,NULL),(160,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_160','313abc40-4c88-45df-89e7-bd7bbf97b0fd',160,NULL,NULL,0,NULL,NULL),(161,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_161','c5d7fc06-16fc-4711-be37-27bbf2c2c07c',161,NULL,NULL,0,NULL,NULL),(162,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_162','ca31bf4d-f5da-4fc4-ae36-fd3cc0d35d7f',162,NULL,NULL,0,NULL,NULL),(163,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_163','dc98bb8e-4b91-4915-86fb-476c9503a936',163,NULL,NULL,0,NULL,NULL),(164,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_164','79dd006c-0e4c-4a79-8600-ef8a0ae5bc04',164,NULL,NULL,0,NULL,NULL),(165,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_165','05cdc1f7-7787-43d6-80c6-588277fefb9b',165,NULL,NULL,0,NULL,NULL),(166,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_166','dcdeb139-71ab-44f5-a709-ab33fec49882',166,NULL,NULL,0,NULL,NULL),(167,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_167','35a98804-b05e-47b0-917b-d72a4d4a5240',167,NULL,NULL,0,NULL,NULL),(168,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_168','5e4d4351-82c7-438d-8f83-ee2b7ebe1fe3',168,NULL,NULL,0,NULL,NULL),(169,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_169','e1a205e2-f202-402d-8542-4cfc529ef514',169,NULL,NULL,0,NULL,NULL),(170,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_170','a2e6271e-5b30-42d1-a211-494b98832676',170,NULL,NULL,0,NULL,NULL),(171,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_171','68515954-75ea-4022-9581-4cb4d28c6d6d',171,NULL,NULL,0,NULL,NULL),(172,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_172','41663b84-06b5-4787-a49e-1f745ca1eab3',172,NULL,NULL,0,NULL,NULL),(173,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_173','b257f456-bdae-4c58-8519-756abbda462a',173,NULL,NULL,0,NULL,NULL),(174,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_174','d848b9cb-05e4-4dcf-b9b7-431d83c41810',174,NULL,NULL,0,NULL,NULL),(175,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_175','b6859250-dcca-47ef-b013-f609468d2389',175,NULL,NULL,0,NULL,NULL),(176,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_176','e18bc682-897b-4696-a5ef-eee37a52a3de',176,NULL,NULL,0,NULL,NULL),(177,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_177','6b00471d-f496-4335-8209-5a9e13d18b9e',177,NULL,NULL,0,NULL,NULL),(178,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_178','35664644-7b32-4503-86f4-76adbb57762c',178,NULL,NULL,0,NULL,NULL),(179,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_179','7890415f-6563-4f25-bdf3-a5f45159a1b1',179,NULL,NULL,0,NULL,NULL),(180,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_180','a1edf880-e270-4dac-b69f-73e61c517397',180,NULL,NULL,0,NULL,NULL),(181,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_181','73520029-5901-4022-b9da-38ccd73fe799',181,NULL,NULL,0,NULL,NULL),(182,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_182','de5825a3-c585-45b3-88a1-7e5e80686826',182,NULL,NULL,0,NULL,NULL),(183,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_183','bb50b80a-f471-4f64-85fb-4e5051708a4a',183,NULL,NULL,0,NULL,NULL),(184,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_184','b7aa98b9-30da-468c-8566-06a5b804c4b9',184,NULL,NULL,0,NULL,NULL),(185,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_185','c230e253-f874-4365-8b0e-7ba5ebc1cc26',185,NULL,NULL,0,NULL,NULL),(186,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_186','7593dbbf-9286-460b-a234-32b560817f60',186,NULL,NULL,0,NULL,NULL),(187,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_187','ee1e2ce5-da23-4576-84e3-ad7cf4e0ce26',187,NULL,NULL,0,NULL,NULL),(188,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_188','bf1cc1be-f405-4282-b7be-9a4578670046',188,NULL,NULL,0,NULL,NULL),(189,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_189','e5ed670a-f944-40f0-8c10-d41c3350ead5',189,NULL,NULL,0,NULL,NULL),(190,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_190','8370db5c-e196-451a-9f5f-9b99c570cf46',190,NULL,NULL,0,NULL,NULL),(191,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_191','81498342-d247-4a60-80de-2c4cb4b1a84d',191,NULL,NULL,0,NULL,NULL),(192,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_192','213f1b3c-516e-4a6f-9785-d8c85d32f83e',192,NULL,NULL,0,NULL,NULL),(193,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_193','08ba27e6-b1b5-4d9e-a64a-6b5bc538bf43',193,NULL,NULL,0,NULL,NULL),(194,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_194','cf0cfa8e-377c-44a0-a6d1-a74ce1de08fb',194,NULL,NULL,0,NULL,NULL),(195,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_195','2ea66412-8dc2-4081-8d48-e3637ca82604',195,NULL,NULL,0,NULL,NULL),(196,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_196','4ed466eb-ee51-4433-9d0f-3a56216698a2',196,NULL,NULL,0,NULL,NULL),(197,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_197','cc03fc51-097d-43d6-bb6c-a0df72ec4838',197,NULL,NULL,0,NULL,NULL),(198,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_198','11844e66-8146-4263-aaa6-1fde7e5cfc58',198,NULL,NULL,0,NULL,NULL),(199,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_199','b5a954c6-69a9-473c-a4c4-83c4f7a88c1c',199,NULL,NULL,0,NULL,NULL),(200,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_200','167e359e-7833-4ce2-9f8b-f035cee39505',200,NULL,NULL,0,NULL,NULL),(201,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_201','5afb5430-a023-4a50-aa92-b134a0fb68b3',201,NULL,NULL,0,NULL,NULL),(202,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_202','de17b155-307c-4f9b-81f3-7f8b73d2526a',202,NULL,NULL,0,NULL,NULL),(203,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_203','c966145b-ac05-4a2c-874d-f7b585d1d03b',203,NULL,NULL,0,NULL,NULL),(204,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_204','1d88ea5a-ab5f-40b1-bd48-f18f86eef5d9',204,NULL,NULL,0,NULL,NULL),(205,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_205','6cb0be93-7829-4bfc-ba4a-4d2cdff45447',205,NULL,NULL,0,NULL,NULL),(206,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_206','e31a2ca7-fcaa-4b98-aac9-7e78f8605851',206,NULL,NULL,0,NULL,NULL),(207,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_207','f26899b7-64e0-4c16-9134-cef3774f1614',207,NULL,NULL,0,NULL,NULL),(208,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_208','606cf6ab-6b5e-45d1-83b8-e535b197d2f0',208,NULL,NULL,0,NULL,NULL),(209,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_209','617bfc4e-17b1-4ca7-b736-58a74c267747',209,NULL,NULL,0,NULL,NULL),(210,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_210','e5c26b7a-17bd-47ce-aac8-1430c57b8152',210,NULL,NULL,0,NULL,NULL),(211,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_211','7747bff5-b1e5-49b9-9a87-f93a5b790df0',211,NULL,NULL,0,NULL,NULL),(212,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_212','c6e5b631-1e91-4ecd-8358-214eec07a91d',212,NULL,NULL,0,NULL,NULL),(213,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_213','a874c7bd-97ac-4f48-bda5-7d3305d9067d',213,NULL,NULL,0,NULL,NULL),(214,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_214','c7938cc2-8032-424b-8f49-85558f95364b',214,NULL,NULL,0,NULL,NULL),(215,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_215','46017ce9-d4dd-4ddc-8b73-d596e23d25ad',215,NULL,NULL,0,NULL,NULL),(216,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_216','d5e66fd2-232e-476d-8de0-2bc1eb59630d',216,NULL,NULL,0,NULL,NULL),(217,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_217','097dc614-bc56-4f5f-a190-3ca1716a6400',217,NULL,NULL,0,NULL,NULL),(218,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_218','a3b97132-067f-4839-9b99-830a7fb659d4',218,NULL,NULL,0,NULL,NULL),(219,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_219','8d35557f-7451-4c54-bb17-9c3d204c48d3',219,NULL,NULL,0,NULL,NULL),(220,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_220','a6fba1ff-a5d7-4907-8cd4-1caa27cad85d',220,NULL,NULL,0,NULL,NULL),(221,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_221','427feb36-4401-4971-83de-f93672c028aa',221,NULL,NULL,0,NULL,NULL),(222,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_222','66541083-b1ab-4966-9f8b-8a1109fce0e0',222,NULL,NULL,0,NULL,NULL),(223,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_223','9939c37c-a9b9-43b7-9a4b-aacc470d47c4',223,NULL,NULL,0,NULL,NULL),(224,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_224','754379a0-bdc2-4a2d-9828-9480926b30ad',224,NULL,NULL,0,NULL,NULL),(225,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_225','18c870a1-9e2c-48fb-8a52-259e55e2052e',225,NULL,NULL,0,NULL,NULL),(226,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_226','02df9a97-b44c-4c46-ab3a-c11010d45e18',226,NULL,NULL,0,NULL,NULL),(227,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_227','20f609f7-c128-46b5-abeb-d16d46aab9ad',227,NULL,NULL,0,NULL,NULL),(228,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_228','75067ca5-872c-4149-85ad-f6685f14efc0',228,NULL,NULL,0,NULL,NULL),(229,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_229','b8639303-d15f-4c81-b9d2-2863f53737c3',229,NULL,NULL,0,NULL,NULL),(230,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_230','a0c4d9ea-7659-4009-ac7c-a3f089def76d',230,NULL,NULL,0,NULL,NULL),(231,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_231','d3605113-fb9a-4640-b6fe-9931594eba6c',231,NULL,NULL,0,NULL,NULL),(232,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_232','bf59d2cc-dd79-4ad6-9637-b04098768600',232,NULL,NULL,0,NULL,NULL),(233,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_233','304d5f24-274e-4fd6-aca4-97b761d1bd0c',233,NULL,NULL,0,NULL,NULL),(234,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_234','0d9491c3-c28b-4c11-8e28-14d93e612e35',234,NULL,NULL,0,NULL,NULL),(235,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_235','f73a809f-78a6-4214-8060-d6037fe391aa',235,NULL,NULL,0,NULL,NULL),(236,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_236','11cc494a-86a4-44d2-b5fd-06438f95d6a4',236,NULL,NULL,0,NULL,NULL),(237,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_237','55b2e8cc-aaa4-4a8b-8a83-f732188cfab2',237,NULL,NULL,0,NULL,NULL),(238,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_238','ebe14f0a-7bf7-4614-83c8-1e2da963139a',238,NULL,NULL,0,NULL,NULL),(239,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_239','3e83b092-95a1-4ee4-ac1f-e9df2f3954ad',239,NULL,NULL,0,NULL,NULL),(240,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_240','7304efcc-7974-453e-b2db-fdcc848f8a24',240,NULL,NULL,0,NULL,NULL),(241,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_241','6b0b51e8-f058-42a6-a9ed-3b6ebde935d8',241,NULL,NULL,0,NULL,NULL),(242,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_242','c10f6de1-a64d-4f8f-bd0a-47bcd72ab8f7',242,NULL,NULL,0,NULL,NULL),(243,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_243','5537408c-41c6-4ee5-8f59-ca70fcdbd0ae',243,NULL,NULL,0,NULL,NULL),(244,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_244','0a920520-e271-42a6-8dc1-89f090023c89',244,NULL,NULL,0,NULL,NULL),(245,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_245','a5120b27-cdd5-4209-b3da-bdf4b53db140',245,NULL,NULL,0,NULL,NULL),(246,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_246','cd0f900a-dab8-4a49-805d-97e57cb5ad4c',246,NULL,NULL,0,NULL,NULL),(247,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_247','53b8b68c-0a11-411a-9b4d-01d58c9c0ff0',247,NULL,NULL,0,NULL,NULL),(248,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_248','57114ddf-7bb8-4e68-952a-faa83bf276bf',248,NULL,NULL,0,NULL,NULL),(249,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_249','fa04c6fe-1bf0-489e-b0df-9fa4756bb90b',249,NULL,NULL,0,NULL,NULL),(250,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_250','5bf5b365-962e-4f6d-9576-94d5ac66cc3c',250,NULL,NULL,0,NULL,NULL),(251,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_251','eca96575-798c-4919-ba93-4f0eca487490',251,NULL,NULL,0,NULL,NULL),(252,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_252','d4e52ad1-ac1c-4f68-8d97-6858c8534f84',252,NULL,NULL,0,NULL,NULL),(253,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_253','74f88528-b57b-4482-a417-e7e8cf5ccd87',253,NULL,NULL,0,NULL,NULL),(254,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_254','f1b969bd-2e43-4981-80d1-baeba6afd456',254,NULL,NULL,0,NULL,NULL),(255,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_255','11f5bcd3-096b-4b0f-8f1b-fa9292e3f5f3',255,NULL,NULL,0,NULL,NULL),(256,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_256','b937e637-c00b-48de-8dd4-fae260cd9fb9',256,NULL,NULL,0,NULL,NULL),(257,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_257','49886ca5-c9a8-4c1f-9ef0-4784495e943c',257,NULL,NULL,0,NULL,NULL),(258,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_258','5cf6bbba-f2bf-4704-b288-36edb49a3c7a',258,NULL,NULL,0,NULL,NULL),(259,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_259','0a246675-78f2-47d3-a716-f9b85de0e885',259,NULL,NULL,0,NULL,NULL),(260,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_260','b1e2509b-e9e4-40f8-b5c3-4e230e675ca8',260,NULL,NULL,0,NULL,NULL),(261,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_261','c423ca4a-54b4-40f3-859d-d39f7d4cf266',261,NULL,NULL,0,NULL,NULL),(262,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_262','1452d005-8038-4092-ba0d-bd690dfdb2e2',262,NULL,NULL,0,NULL,NULL),(263,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_263','f39a1721-6aeb-4f1e-90be-f54684ece8f0',263,NULL,NULL,0,NULL,NULL),(264,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_264','ec2b02db-6eb2-4b9e-aa3b-ef53b6daf005',264,NULL,NULL,0,NULL,NULL),(265,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_265','a6809581-e7b7-4d70-bfdd-c1f302322ee3',265,NULL,NULL,0,NULL,NULL),(266,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_266','794e2ba9-518d-4494-8ef0-01669807e10a',266,NULL,NULL,0,NULL,NULL),(267,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_267','c258f48e-7f30-4c16-bd2d-6eed81529157',267,NULL,NULL,0,NULL,NULL),(268,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_268','b7501b84-3a14-44d7-97da-271c416cbd16',268,NULL,NULL,0,NULL,NULL),(269,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_269','88b529d5-7804-4c4d-9f35-aa7dd1df0a37',269,NULL,NULL,0,NULL,NULL),(270,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_270','0c1b65d3-dee3-4429-864f-115fbbc6a2f4',270,NULL,NULL,0,NULL,NULL),(271,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_271','01667b0f-b397-47c1-8cdb-adb3ea7cba06',271,NULL,NULL,0,NULL,NULL),(272,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_272','c8909fda-0453-4f74-a683-bd613fdc70c5',272,NULL,NULL,0,NULL,NULL),(273,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_273','796b8703-6f42-433f-b9e6-b115b4df25b0',273,NULL,NULL,0,NULL,NULL),(274,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_274','de8f11f6-7298-4633-ad38-cc94e03314fd',274,NULL,NULL,0,NULL,NULL),(275,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_275','e097f4e6-9c2d-4f35-912e-bd37f5cdec00',275,NULL,NULL,0,NULL,NULL),(276,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_276','3e0dab1e-c41f-4c0d-b2e3-d056ba6a3c60',276,NULL,NULL,0,NULL,NULL),(277,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_277','b24cb998-40b7-471c-b55a-48b58b98b2e5',277,NULL,NULL,0,NULL,NULL),(278,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_278','ab2113f4-56a2-4d1d-83a6-a54a763e371e',278,NULL,NULL,0,NULL,NULL),(279,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_279','2a2beb83-ccbf-413f-ade2-2fd2f79e5f49',279,NULL,NULL,0,NULL,NULL),(280,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_280','ac53405d-8813-4cf7-ac12-fad7629d5602',280,NULL,NULL,0,NULL,NULL),(281,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_281','b6c7b0e1-38b5-4e00-a22d-45c03d5fdeac',281,NULL,NULL,0,NULL,NULL),(282,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_282','8e41ff90-42f5-4736-89a6-24246917555c',282,NULL,NULL,0,NULL,NULL),(283,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_283','2b46023a-316f-41ae-955e-01185d67d7a5',283,NULL,NULL,0,NULL,NULL),(284,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_284','74c72c06-391e-4c72-92e7-92a5b75ac2da',284,NULL,NULL,0,NULL,NULL),(285,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_285','3e1246c2-96f9-4937-be0c-eb187822c3c7',285,NULL,NULL,0,NULL,NULL),(286,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_286','7f0e0193-b743-4394-b3e5-86e01813c094',286,NULL,NULL,0,NULL,NULL),(287,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_287','886cd06c-c30a-48df-b793-be4bfa2c1eb9',287,NULL,NULL,0,NULL,NULL),(288,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_288','cb7cf6cd-bd2e-4956-be86-5d5935417098',288,NULL,NULL,0,NULL,NULL),(289,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_289','d2e92f17-c26b-44dd-9c60-ca69b0f55b6d',289,NULL,NULL,0,NULL,NULL),(290,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_290','ea3a53a1-b451-4d7b-9b9f-2b6790de314d',290,NULL,NULL,0,NULL,NULL),(291,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_291','723f2b0d-3473-445c-a6f2-9c8bb12b6019',291,NULL,NULL,0,NULL,NULL),(292,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_292','8f04e723-bb30-4952-a8f5-214845e525dc',292,NULL,NULL,0,NULL,NULL),(293,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_293','56e1991e-47e1-4136-9bd0-cd94fa40b3c8',293,NULL,NULL,0,NULL,NULL),(294,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_294','b5ef5b82-483e-4331-ba84-78ece1f72602',294,NULL,NULL,0,NULL,NULL),(295,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_295','8238ae4e-5f13-42a3-9d6c-ea60f0ee64a1',295,NULL,NULL,0,NULL,NULL),(296,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_296','800a6a1d-1f63-4052-a14a-fcb56ab7e98b',296,NULL,NULL,0,NULL,NULL),(297,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_297','2eb884c0-8953-434d-898f-a162ffd44102',297,NULL,NULL,0,NULL,NULL),(298,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_298','06363941-bac6-4cc1-b56f-82d9d64d7c12',298,NULL,NULL,0,NULL,NULL),(299,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_299','d8468131-79a2-4003-bf0a-e034a3455af9',299,NULL,NULL,0,NULL,NULL),(300,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_300','e8e5f9d3-4473-46d9-b893-a195d5ccc6b4',300,NULL,NULL,0,NULL,NULL),(301,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_301','57db1144-49b7-4930-a214-9bba56c0eab6',301,NULL,NULL,0,NULL,NULL),(302,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_302','668a6ec5-142f-467d-891a-57fe10faf4bb',302,NULL,NULL,0,NULL,NULL),(303,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_303','9bcd9772-6c90-4c14-8ff4-16fa54744c87',303,NULL,NULL,0,NULL,NULL),(304,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_304','6c37ac4e-5213-4d60-8070-fadf3fa3ca38',304,NULL,NULL,0,NULL,NULL),(305,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_305','fb5d7ea0-249f-4a0e-97aa-caa015d148e4',305,NULL,NULL,0,NULL,NULL),(306,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_306','26035205-595c-433a-8aba-4e0d6ce103a3',306,NULL,NULL,0,NULL,NULL),(307,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_307','1e4a6346-9da9-417c-bfbf-1a3cded61e12',307,NULL,NULL,0,NULL,NULL),(308,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_308','3af98cba-0cd4-4ea1-bcdc-c4c91672f038',308,NULL,NULL,0,NULL,NULL),(309,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_309','a073f7ce-dfdc-424c-b4d0-bec7acaae445',309,NULL,NULL,0,NULL,NULL),(310,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_310','6524988e-5916-4410-a740-58d1e57d3f93',310,NULL,NULL,0,NULL,NULL),(311,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_311','58a190c4-789e-4c97-9fbb-245d3a58c8fe',311,NULL,NULL,0,NULL,NULL),(312,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_312','3244773f-b74b-461d-bf9a-916a05980c99',312,NULL,NULL,0,NULL,NULL),(313,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_313','aaed5fa8-6555-43d2-adf4-c672008f8c92',313,NULL,NULL,0,NULL,NULL),(314,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_314','f32415ac-f0fb-4815-bbef-27ba6115a1cc',314,NULL,NULL,0,NULL,NULL),(315,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_315','2030b697-b729-40c4-91b1-592e19fd4e73',315,NULL,NULL,0,NULL,NULL),(316,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_316','ee47b98e-ebd5-44ae-8c9a-cbec609415b0',316,NULL,NULL,0,NULL,NULL),(317,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_317','a47459c2-a709-4601-9151-cb57ae13bc8c',317,NULL,NULL,0,NULL,NULL),(318,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_318','5e274495-2c02-4f75-9ce2-c730e2686be9',318,NULL,NULL,0,NULL,NULL),(319,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_319','f5f04ca8-f693-4758-9aa6-9a3c55938937',319,NULL,NULL,0,NULL,NULL),(320,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_320','5f876faf-2ad7-41f3-906d-2edd9fd2907d',320,NULL,NULL,0,NULL,NULL),(321,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_321','3d0665c6-db74-4d48-91cc-ebe39bbae605',321,NULL,NULL,0,NULL,NULL),(322,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_322','86c19bce-cb25-47a4-8aba-29c8ad4fc87d',322,NULL,NULL,0,NULL,NULL),(323,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_323','efa06619-2301-4cb4-b9fa-6e9bddef94d7',323,NULL,NULL,0,NULL,NULL),(324,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_324','3cfc5976-aa7f-4281-8b43-6ea6eee1ac80',324,NULL,NULL,0,NULL,NULL),(325,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_325','19a56d56-1f57-45e6-9c2e-466a17d8c7ba',325,NULL,NULL,0,NULL,NULL),(326,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_326','026a45cf-cbeb-4ea9-8d20-21efbe206bad',326,NULL,NULL,0,NULL,NULL),(327,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_327','48312cae-f61d-4f87-9b20-a957d1e919ce',327,NULL,NULL,0,NULL,NULL),(328,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_328','e06abc58-f451-4e9e-ac4f-51d5e9d424a6',328,NULL,NULL,0,NULL,NULL),(329,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_329','10b58273-4b30-4caf-954c-a1873ca4d6b5',329,NULL,NULL,0,NULL,NULL),(330,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_330','008892b7-6479-4e68-adf2-39e7ac29e66e',330,NULL,NULL,0,NULL,NULL),(331,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_331','7f864422-153c-4681-8c9e-4e942dce9548',331,NULL,NULL,0,NULL,NULL),(332,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_332','67c5538e-0363-4650-a42e-ba25746b4239',332,NULL,NULL,0,NULL,NULL),(333,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_333','208210c1-1601-47ae-883f-cdb16e0f802b',333,NULL,NULL,0,NULL,NULL),(334,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_334','bb08395a-a0f0-490d-9d23-6f2f76b41514',334,NULL,NULL,0,NULL,NULL),(335,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_335','050c1a8e-256d-41ab-bd3a-3abe54d01b32',335,NULL,NULL,0,NULL,NULL),(336,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_336','cf016005-9207-4a2d-a8fe-91c278029a18',336,NULL,NULL,0,NULL,NULL),(337,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_337','950a5d40-e604-4f6c-82dd-2b60a578d9aa',337,NULL,NULL,0,NULL,NULL),(338,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_338','3e00662d-6917-4759-b9a9-be8eda02f63b',338,NULL,NULL,0,NULL,NULL),(339,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_339','bb339af3-2038-4f17-b489-46d4b7542cb6',339,NULL,NULL,0,NULL,NULL),(340,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_340','3927f6d5-5d90-4192-b84c-cebda90c0b0a',340,NULL,NULL,0,NULL,NULL),(341,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_341','e6b29f71-bb4a-420b-8442-1f7639109465',341,NULL,NULL,0,NULL,NULL),(342,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_342','ff7909b6-a90c-43c7-96fc-c375d439e373',342,NULL,NULL,0,NULL,NULL),(343,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_343','6f9902ca-7674-4f2f-b2e1-aeb3701bae14',343,NULL,NULL,0,NULL,NULL),(344,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_344','36d75eda-7573-474a-8aeb-f8555464154f',344,NULL,NULL,0,NULL,NULL),(345,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_345','d3c489ae-3f03-48fe-9248-927a8bb3297f',345,NULL,NULL,0,NULL,NULL),(346,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_346','18764a4e-8b01-478e-80b3-217cc37d49c7',346,NULL,NULL,0,NULL,NULL),(347,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$10$UZeOZKD1.dj5oiTsZKD03OETA9FXCKGqBuuijhsxYygZpOPtWMUni','test_347','00075d1c-f486-41a0-98f8-06f0354b8416',347,NULL,NULL,0,NULL,NULL),(1000,1,'2024-03-27 18:43:07','2024-03-27 18:43:07','$2a$12$S3lUZw/ESq9lULn5he6bBu9KNGCvs7C2rWo0XdVC6t65ITwAc22w2','test-with-mfa','467c882e-90da-11ec-b909-0242ac120002',1000,NULL,NULL,0,NULL,NULL); +/*!40000 ALTER TABLE `iam_account` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_account_attrs` +-- + +DROP TABLE IF EXISTS `iam_account_attrs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_account_attrs` ( + `NAME` varchar(64) NOT NULL, + `val` varchar(256) DEFAULT NULL, + `account_id` bigint(20) DEFAULT NULL, + KEY `INDEX_iam_account_attrs_name` (`NAME`), + KEY `INDEX_iam_account_attrs_name_val` (`NAME`,`val`), + KEY `FK_iam_account_attrs_account_id` (`account_id`), + CONSTRAINT `FK_iam_account_attrs_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_account_attrs` +-- + +LOCK TABLES `iam_account_attrs` WRITE; +/*!40000 ALTER TABLE `iam_account_attrs` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_account_attrs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_account_authority` +-- + +DROP TABLE IF EXISTS `iam_account_authority`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_account_authority` ( + `account_id` bigint(20) NOT NULL, + `authority_id` bigint(20) NOT NULL, + PRIMARY KEY (`account_id`,`authority_id`), + KEY `FK_iam_account_authority_authority_id` (`authority_id`), + CONSTRAINT `FK_iam_account_authority_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`), + CONSTRAINT `FK_iam_account_authority_authority_id` FOREIGN KEY (`authority_id`) REFERENCES `iam_authority` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_account_authority` +-- + +LOCK TABLES `iam_account_authority` WRITE; +/*!40000 ALTER TABLE `iam_account_authority` DISABLE KEYS */; +INSERT INTO `iam_account_authority` VALUES (1,1),(1,2),(2,2),(100,2),(101,2),(102,2),(103,2),(104,2),(105,2),(106,2),(107,2),(108,2),(109,2),(110,2),(111,2),(112,2),(113,2),(114,2),(115,2),(116,2),(117,2),(118,2),(119,2),(120,2),(121,2),(122,2),(123,2),(124,2),(125,2),(126,2),(127,2),(128,2),(129,2),(130,2),(131,2),(132,2),(133,2),(134,2),(135,2),(136,2),(137,2),(138,2),(139,2),(140,2),(141,2),(142,2),(143,2),(144,2),(145,2),(146,2),(147,2),(148,2),(149,2),(150,2),(151,2),(152,2),(153,2),(154,2),(155,2),(156,2),(157,2),(158,2),(159,2),(160,2),(161,2),(162,2),(163,2),(164,2),(165,2),(166,2),(167,2),(168,2),(169,2),(170,2),(171,2),(172,2),(173,2),(174,2),(175,2),(176,2),(177,2),(178,2),(179,2),(180,2),(181,2),(182,2),(183,2),(184,2),(185,2),(186,2),(187,2),(188,2),(189,2),(190,2),(191,2),(192,2),(193,2),(194,2),(195,2),(196,2),(197,2),(198,2),(199,2),(200,2),(201,2),(202,2),(203,2),(204,2),(205,2),(206,2),(207,2),(208,2),(209,2),(210,2),(211,2),(212,2),(213,2),(214,2),(215,2),(216,2),(217,2),(218,2),(219,2),(220,2),(221,2),(222,2),(223,2),(224,2),(225,2),(226,2),(227,2),(228,2),(229,2),(230,2),(231,2),(232,2),(233,2),(234,2),(235,2),(236,2),(237,2),(238,2),(239,2),(240,2),(241,2),(242,2),(243,2),(244,2),(245,2),(246,2),(247,2),(248,2),(249,2),(250,2),(251,2),(252,2),(253,2),(254,2),(255,2),(256,2),(257,2),(258,2),(259,2),(260,2),(261,2),(262,2),(263,2),(264,2),(265,2),(266,2),(267,2),(268,2),(269,2),(270,2),(271,2),(272,2),(273,2),(274,2),(275,2),(276,2),(277,2),(278,2),(279,2),(280,2),(281,2),(282,2),(283,2),(284,2),(285,2),(286,2),(287,2),(288,2),(289,2),(290,2),(291,2),(292,2),(293,2),(294,2),(295,2),(296,2),(297,2),(298,2),(299,2),(300,2),(301,2),(302,2),(303,2),(304,2),(305,2),(306,2),(307,2),(308,2),(309,2),(310,2),(311,2),(312,2),(313,2),(314,2),(315,2),(316,2),(317,2),(318,2),(319,2),(320,2),(321,2),(322,2),(323,2),(324,2),(325,2),(326,2),(327,2),(328,2),(329,2),(330,2),(331,2),(332,2),(333,2),(334,2),(335,2),(336,2),(337,2),(338,2),(339,2),(340,2),(341,2),(342,2),(343,2),(344,2),(345,2),(346,2),(347,2); +/*!40000 ALTER TABLE `iam_account_authority` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_account_client` +-- + +DROP TABLE IF EXISTS `iam_account_client`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_account_client` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `creation_time` datetime NOT NULL, + `account_id` bigint(20) NOT NULL, + `client_id` bigint(20) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UNQ_iam_account_client_0` (`account_id`,`client_id`), + KEY `FK_iam_account_client_client_id` (`client_id`), + CONSTRAINT `FK_iam_account_client_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`), + CONSTRAINT `FK_iam_account_client_client_id` FOREIGN KEY (`client_id`) REFERENCES `client_details` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_account_client` +-- + +LOCK TABLES `iam_account_client` WRITE; +/*!40000 ALTER TABLE `iam_account_client` DISABLE KEYS */; +INSERT INTO `iam_account_client` VALUES (1,'2024-03-27 18:43:07',200,1),(2,'2024-03-27 18:43:07',200,2),(3,'2024-03-27 18:43:07',199,1),(4,'2024-03-27 18:43:07',199,2); +/*!40000 ALTER TABLE `iam_account_client` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_account_group` +-- + +DROP TABLE IF EXISTS `iam_account_group`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_account_group` ( + `account_id` bigint(20) NOT NULL, + `group_id` bigint(20) NOT NULL, + `creation_time` datetime DEFAULT NULL, + `end_time` datetime DEFAULT NULL, + PRIMARY KEY (`account_id`,`group_id`), + KEY `FK_iam_account_group_group_id` (`group_id`), + CONSTRAINT `FK_iam_account_group_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`), + CONSTRAINT `FK_iam_account_group_group_id` FOREIGN KEY (`group_id`) REFERENCES `iam_group` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_account_group` +-- + +LOCK TABLES `iam_account_group` WRITE; +/*!40000 ALTER TABLE `iam_account_group` DISABLE KEYS */; +INSERT INTO `iam_account_group` VALUES (2,1,NULL,NULL),(2,2,NULL,NULL),(2,121,'2024-03-27 18:47:36',NULL),(2,122,'2024-03-27 18:47:36',NULL),(2,123,'2024-03-27 18:47:39',NULL),(2,124,'2024-03-27 18:47:59',NULL),(2,125,'2024-03-27 18:47:36',NULL),(2,126,'2024-03-27 18:47:59',NULL),(2,127,'2024-03-27 18:47:39',NULL),(100,1,NULL,NULL),(100,2,NULL,NULL),(101,1,NULL,NULL),(101,2,NULL,NULL),(102,1,NULL,NULL),(102,2,NULL,NULL),(103,1,NULL,NULL),(103,2,NULL,NULL),(104,1,NULL,NULL),(104,2,NULL,NULL),(105,1,NULL,NULL),(105,2,NULL,NULL),(106,1,NULL,NULL),(106,2,NULL,NULL),(107,1,NULL,NULL),(107,2,NULL,NULL),(108,1,NULL,NULL),(108,2,NULL,NULL),(109,1,NULL,NULL),(109,2,NULL,NULL),(110,1,NULL,NULL),(110,2,NULL,NULL),(111,1,NULL,NULL),(111,2,NULL,NULL),(112,1,NULL,NULL),(112,2,NULL,NULL),(113,1,NULL,NULL),(113,2,NULL,NULL),(114,1,NULL,NULL),(114,2,NULL,NULL),(115,1,NULL,NULL),(115,2,NULL,NULL),(116,1,NULL,NULL),(116,2,NULL,NULL),(117,1,NULL,NULL),(117,2,NULL,NULL),(118,1,NULL,NULL),(118,2,NULL,NULL),(119,1,NULL,NULL),(119,2,NULL,NULL),(120,1,NULL,NULL),(120,2,NULL,NULL),(121,1,NULL,NULL),(121,2,NULL,NULL),(122,1,NULL,NULL),(122,2,NULL,NULL),(123,1,NULL,NULL),(123,2,NULL,NULL),(124,1,NULL,NULL),(124,2,NULL,NULL),(125,1,NULL,NULL),(125,2,NULL,NULL),(126,1,NULL,NULL),(126,2,NULL,NULL),(127,1,NULL,NULL),(127,2,NULL,NULL),(128,1,NULL,NULL),(128,2,NULL,NULL),(129,1,NULL,NULL),(129,2,NULL,NULL),(130,1,NULL,NULL),(130,2,NULL,NULL),(131,1,NULL,NULL),(131,2,NULL,NULL),(132,1,NULL,NULL),(132,2,NULL,NULL),(133,1,NULL,NULL),(133,2,NULL,NULL),(134,1,NULL,NULL),(134,2,NULL,NULL),(135,1,NULL,NULL),(135,2,NULL,NULL),(136,1,NULL,NULL),(136,2,NULL,NULL),(137,1,NULL,NULL),(137,2,NULL,NULL),(138,1,NULL,NULL),(138,2,NULL,NULL),(139,1,NULL,NULL),(139,2,NULL,NULL),(140,1,NULL,NULL),(140,2,NULL,NULL),(141,1,NULL,NULL),(141,2,NULL,NULL),(142,1,NULL,NULL),(142,2,NULL,NULL),(143,1,NULL,NULL),(143,2,NULL,NULL),(144,1,NULL,NULL),(144,2,NULL,NULL),(145,1,NULL,NULL),(145,2,NULL,NULL),(146,1,NULL,NULL),(146,2,NULL,NULL),(147,1,NULL,NULL),(147,2,NULL,NULL),(148,1,NULL,NULL),(148,2,NULL,NULL),(149,1,NULL,NULL),(149,2,NULL,NULL),(150,1,NULL,NULL),(150,2,NULL,NULL),(151,1,NULL,NULL),(151,2,NULL,NULL),(152,1,NULL,NULL),(152,2,NULL,NULL),(153,1,NULL,NULL),(153,2,NULL,NULL),(154,1,NULL,NULL),(154,2,NULL,NULL),(155,1,NULL,NULL),(155,2,NULL,NULL),(156,1,NULL,NULL),(156,2,NULL,NULL),(157,1,NULL,NULL),(157,2,NULL,NULL),(158,1,NULL,NULL),(158,2,NULL,NULL),(159,1,NULL,NULL),(159,2,NULL,NULL),(160,1,NULL,NULL),(160,2,NULL,NULL),(161,1,NULL,NULL),(161,2,NULL,NULL),(162,1,NULL,NULL),(162,2,NULL,NULL),(163,1,NULL,NULL),(163,2,NULL,NULL),(164,1,NULL,NULL),(164,2,NULL,NULL),(165,1,NULL,NULL),(165,2,NULL,NULL),(166,1,NULL,NULL),(166,2,NULL,NULL),(167,1,NULL,NULL),(167,2,NULL,NULL),(168,1,NULL,NULL),(168,2,NULL,NULL),(169,1,NULL,NULL),(169,2,NULL,NULL),(170,1,NULL,NULL),(170,2,NULL,NULL),(171,1,NULL,NULL),(171,2,NULL,NULL),(172,1,NULL,NULL),(172,2,NULL,NULL),(173,1,NULL,NULL),(173,2,NULL,NULL),(174,1,NULL,NULL),(174,2,NULL,NULL),(175,1,NULL,NULL),(175,2,NULL,NULL),(176,1,NULL,NULL),(176,2,NULL,NULL),(177,1,NULL,NULL),(177,2,NULL,NULL),(178,1,NULL,NULL),(178,2,NULL,NULL),(179,1,NULL,NULL),(179,2,NULL,NULL),(180,1,NULL,NULL),(180,2,NULL,NULL),(181,1,NULL,NULL),(181,2,NULL,NULL),(182,1,NULL,NULL),(182,2,NULL,NULL),(183,1,NULL,NULL),(183,2,NULL,NULL),(184,1,NULL,NULL),(184,2,NULL,NULL),(185,1,NULL,NULL),(185,2,NULL,NULL),(186,1,NULL,NULL),(186,2,NULL,NULL),(187,1,NULL,NULL),(187,2,NULL,NULL),(188,1,NULL,NULL),(188,2,NULL,NULL),(189,1,NULL,NULL),(189,2,NULL,NULL),(190,1,NULL,NULL),(190,2,NULL,NULL),(191,1,NULL,NULL),(191,2,NULL,NULL),(192,1,NULL,NULL),(192,2,NULL,NULL),(193,1,NULL,NULL),(193,2,NULL,NULL),(194,1,NULL,NULL),(194,2,NULL,NULL),(195,1,NULL,NULL),(195,2,NULL,NULL),(196,1,NULL,NULL),(196,2,NULL,NULL),(197,1,NULL,NULL),(197,2,NULL,NULL),(198,1,NULL,NULL),(198,2,NULL,NULL),(199,1,NULL,NULL),(199,2,NULL,NULL),(200,1,NULL,NULL),(200,2,NULL,NULL),(201,1,NULL,NULL),(201,2,NULL,NULL),(202,1,NULL,NULL),(202,2,NULL,NULL),(203,1,NULL,NULL),(203,2,NULL,NULL),(204,1,NULL,NULL),(204,2,NULL,NULL),(205,1,NULL,NULL),(205,2,NULL,NULL),(206,1,NULL,NULL),(206,2,NULL,NULL),(207,1,NULL,NULL),(207,2,NULL,NULL),(208,1,NULL,NULL),(208,2,NULL,NULL),(209,1,NULL,NULL),(209,2,NULL,NULL),(210,1,NULL,NULL),(210,2,NULL,NULL),(211,1,NULL,NULL),(211,2,NULL,NULL),(212,1,NULL,NULL),(212,2,NULL,NULL),(213,1,NULL,NULL),(213,2,NULL,NULL),(214,1,NULL,NULL),(214,2,NULL,NULL),(215,1,NULL,NULL),(215,2,NULL,NULL),(216,1,NULL,NULL),(216,2,NULL,NULL),(217,1,NULL,NULL),(217,2,NULL,NULL),(218,1,NULL,NULL),(218,2,NULL,NULL),(219,1,NULL,NULL),(219,2,NULL,NULL),(220,1,NULL,NULL),(220,2,NULL,NULL),(221,1,NULL,NULL),(221,2,NULL,NULL),(222,1,NULL,NULL),(222,2,NULL,NULL),(223,1,NULL,NULL),(223,2,NULL,NULL),(224,1,NULL,NULL),(224,2,NULL,NULL),(225,1,NULL,NULL),(225,2,NULL,NULL),(226,1,NULL,NULL),(226,2,NULL,NULL),(227,1,NULL,NULL),(227,2,NULL,NULL),(228,1,NULL,NULL),(228,2,NULL,NULL),(229,1,NULL,NULL),(229,2,NULL,NULL),(230,1,NULL,NULL),(230,2,NULL,NULL),(231,1,NULL,NULL),(231,2,NULL,NULL),(232,1,NULL,NULL),(232,2,NULL,NULL),(233,1,NULL,NULL),(233,2,NULL,NULL),(234,1,NULL,NULL),(234,2,NULL,NULL),(235,1,NULL,NULL),(235,2,NULL,NULL),(236,1,NULL,NULL),(236,2,NULL,NULL),(237,1,NULL,NULL),(237,2,NULL,NULL),(238,1,NULL,NULL),(238,2,NULL,NULL),(239,1,NULL,NULL),(239,2,NULL,NULL),(240,1,NULL,NULL),(240,2,NULL,NULL),(241,1,NULL,NULL),(241,2,NULL,NULL),(242,1,NULL,NULL),(242,2,NULL,NULL),(243,1,NULL,NULL),(243,2,NULL,NULL),(244,1,NULL,NULL),(244,2,NULL,NULL),(245,1,NULL,NULL),(245,2,NULL,NULL),(246,1,NULL,NULL),(246,2,NULL,NULL),(247,1,NULL,NULL),(247,2,NULL,NULL),(248,1,NULL,NULL),(248,2,NULL,NULL),(249,1,NULL,NULL),(249,2,NULL,NULL),(250,1,NULL,NULL),(250,2,NULL,NULL),(251,1,NULL,NULL),(251,2,NULL,NULL),(252,1,NULL,NULL),(252,2,NULL,NULL),(253,1,NULL,NULL),(253,2,NULL,NULL),(254,1,NULL,NULL),(254,2,NULL,NULL),(255,1,NULL,NULL),(255,2,NULL,NULL),(256,1,NULL,NULL),(256,2,NULL,NULL),(257,1,NULL,NULL),(257,2,NULL,NULL),(258,1,NULL,NULL),(258,2,NULL,NULL),(259,1,NULL,NULL),(259,2,NULL,NULL),(260,1,NULL,NULL),(260,2,NULL,NULL),(261,1,NULL,NULL),(261,2,NULL,NULL),(262,1,NULL,NULL),(262,2,NULL,NULL),(263,1,NULL,NULL),(263,2,NULL,NULL),(264,1,NULL,NULL),(264,2,NULL,NULL),(265,1,NULL,NULL),(265,2,NULL,NULL),(266,1,NULL,NULL),(266,2,NULL,NULL),(267,1,NULL,NULL),(267,2,NULL,NULL),(268,1,NULL,NULL),(268,2,NULL,NULL),(269,1,NULL,NULL),(269,2,NULL,NULL),(270,1,NULL,NULL),(270,2,NULL,NULL),(271,1,NULL,NULL),(271,2,NULL,NULL),(272,1,NULL,NULL),(272,2,NULL,NULL),(273,1,NULL,NULL),(273,2,NULL,NULL),(274,1,NULL,NULL),(274,2,NULL,NULL),(275,1,NULL,NULL),(275,2,NULL,NULL),(276,1,NULL,NULL),(276,2,NULL,NULL),(277,1,NULL,NULL),(277,2,NULL,NULL),(278,1,NULL,NULL),(278,2,NULL,NULL),(279,1,NULL,NULL),(279,2,NULL,NULL),(280,1,NULL,NULL),(280,2,NULL,NULL),(281,1,NULL,NULL),(281,2,NULL,NULL),(282,1,NULL,NULL),(282,2,NULL,NULL),(283,1,NULL,NULL),(283,2,NULL,NULL),(284,1,NULL,NULL),(284,2,NULL,NULL),(285,1,NULL,NULL),(285,2,NULL,NULL),(286,1,NULL,NULL),(286,2,NULL,NULL),(287,1,NULL,NULL),(287,2,NULL,NULL),(288,1,NULL,NULL),(288,2,NULL,NULL),(289,1,NULL,NULL),(289,2,NULL,NULL),(290,1,NULL,NULL),(290,2,NULL,NULL),(291,1,NULL,NULL),(291,2,NULL,NULL),(292,1,NULL,NULL),(292,2,NULL,NULL),(293,1,NULL,NULL),(293,2,NULL,NULL),(294,1,NULL,NULL),(294,2,NULL,NULL),(295,1,NULL,NULL),(295,2,NULL,NULL),(296,1,NULL,NULL),(296,2,NULL,NULL),(297,1,NULL,NULL),(297,2,NULL,NULL),(298,1,NULL,NULL),(298,2,NULL,NULL),(299,1,NULL,NULL),(299,2,NULL,NULL),(300,1,NULL,NULL),(300,2,NULL,NULL),(301,1,NULL,NULL),(301,2,NULL,NULL),(302,1,NULL,NULL),(302,2,NULL,NULL),(303,1,NULL,NULL),(303,2,NULL,NULL),(304,1,NULL,NULL),(304,2,NULL,NULL),(305,1,NULL,NULL),(305,2,NULL,NULL),(306,1,NULL,NULL),(306,2,NULL,NULL),(307,1,NULL,NULL),(307,2,NULL,NULL),(308,1,NULL,NULL),(308,2,NULL,NULL),(309,1,NULL,NULL),(309,2,NULL,NULL),(310,1,NULL,NULL),(310,2,NULL,NULL),(311,1,NULL,NULL),(311,2,NULL,NULL),(312,1,NULL,NULL),(312,2,NULL,NULL),(313,1,NULL,NULL),(313,2,NULL,NULL),(314,1,NULL,NULL),(314,2,NULL,NULL),(315,1,NULL,NULL),(315,2,NULL,NULL),(316,1,NULL,NULL),(316,2,NULL,NULL),(317,1,NULL,NULL),(317,2,NULL,NULL),(318,1,NULL,NULL),(318,2,NULL,NULL),(319,1,NULL,NULL),(319,2,NULL,NULL),(320,1,NULL,NULL),(320,2,NULL,NULL),(321,1,NULL,NULL),(321,2,NULL,NULL),(322,1,NULL,NULL),(322,2,NULL,NULL),(323,1,NULL,NULL),(323,2,NULL,NULL),(324,1,NULL,NULL),(324,2,NULL,NULL),(325,1,NULL,NULL),(325,2,NULL,NULL),(326,1,NULL,NULL),(326,2,NULL,NULL),(327,1,NULL,NULL),(327,2,NULL,NULL),(328,1,NULL,NULL),(328,2,NULL,NULL),(329,1,NULL,NULL),(329,2,NULL,NULL),(330,1,NULL,NULL),(330,2,NULL,NULL),(331,1,NULL,NULL),(331,2,NULL,NULL),(332,1,NULL,NULL),(332,2,NULL,NULL),(333,1,NULL,NULL),(333,2,NULL,NULL),(334,1,NULL,NULL),(334,2,NULL,NULL),(335,1,NULL,NULL),(335,2,NULL,NULL),(336,1,NULL,NULL),(336,2,NULL,NULL),(337,1,NULL,NULL),(337,2,NULL,NULL),(338,1,NULL,NULL),(338,2,NULL,NULL),(339,1,NULL,NULL),(339,2,NULL,NULL),(340,1,NULL,NULL),(340,2,NULL,NULL),(341,1,NULL,NULL),(341,2,NULL,NULL),(342,1,NULL,NULL),(342,2,NULL,NULL),(343,1,NULL,NULL),(343,2,NULL,NULL),(344,1,NULL,NULL),(344,2,NULL,NULL),(345,1,NULL,NULL),(345,2,NULL,NULL),(346,1,NULL,NULL),(346,2,NULL,NULL),(347,1,NULL,NULL),(347,2,NULL,NULL); +/*!40000 ALTER TABLE `iam_account_group` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_account_labels` +-- + +DROP TABLE IF EXISTS `iam_account_labels`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_account_labels` ( + `NAME` varchar(64) NOT NULL, + `PREFIX` varchar(256) DEFAULT NULL, + `val` varchar(64) DEFAULT NULL, + `account_id` bigint(20) DEFAULT NULL, + KEY `INDEX_iam_account_labels_prefix_name_val` (`PREFIX`,`NAME`,`val`), + KEY `INDEX_iam_account_labels_prefix_name` (`PREFIX`,`NAME`), + KEY `FK_iam_account_labels_account_id` (`account_id`), + CONSTRAINT `FK_iam_account_labels_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_account_labels` +-- + +LOCK TABLES `iam_account_labels` WRITE; +/*!40000 ALTER TABLE `iam_account_labels` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_account_labels` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_address` +-- + +DROP TABLE IF EXISTS `iam_address`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_address` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `COUNTRY` varchar(2) DEFAULT NULL, + `FORMATTED` varchar(128) DEFAULT NULL, + `LOCALITY` varchar(128) DEFAULT NULL, + `POSTALCODE` varchar(16) DEFAULT NULL, + `REGION` varchar(128) DEFAULT NULL, + `STREETADDRESS` varchar(128) DEFAULT NULL, + PRIMARY KEY (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_address` +-- + +LOCK TABLES `iam_address` WRITE; +/*!40000 ALTER TABLE `iam_address` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_address` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_aup` +-- + +DROP TABLE IF EXISTS `iam_aup`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_aup` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `creation_time` datetime NOT NULL, + `description` varchar(128) DEFAULT NULL, + `last_update_time` datetime NOT NULL, + `name` varchar(36) NOT NULL, + `sig_validity_days` bigint(20) NOT NULL, + `text` longtext, + `url` varchar(256) DEFAULT NULL, + PRIMARY KEY (`ID`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_aup` +-- + +LOCK TABLES `iam_aup` WRITE; +/*!40000 ALTER TABLE `iam_aup` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_aup` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_aup_signature` +-- + +DROP TABLE IF EXISTS `iam_aup_signature`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_aup_signature` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `signature_time` datetime NOT NULL, + `account_id` bigint(20) DEFAULT NULL, + `aup_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`ID`), + UNIQUE KEY `UNQ_iam_aup_signature_0` (`aup_id`,`account_id`), + KEY `FK_iam_aup_signature_account_id` (`account_id`), + CONSTRAINT `FK_iam_aup_signature_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`), + CONSTRAINT `FK_iam_aup_signature_aup_id` FOREIGN KEY (`aup_id`) REFERENCES `iam_aup` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_aup_signature` +-- + +LOCK TABLES `iam_aup_signature` WRITE; +/*!40000 ALTER TABLE `iam_aup_signature` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_aup_signature` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_authority` +-- + +DROP TABLE IF EXISTS `iam_authority`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_authority` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `auth` varchar(128) NOT NULL, + PRIMARY KEY (`ID`), + UNIQUE KEY `auth` (`auth`) +) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_authority` +-- + +LOCK TABLES `iam_authority` WRITE; +/*!40000 ALTER TABLE `iam_authority` DISABLE KEYS */; +INSERT INTO `iam_authority` VALUES (1,'ROLE_ADMIN'),(27,'ROLE_GM:28c111d8-4a0c-4969-8a80-64a9c406702d'),(30,'ROLE_GM:3534a378-eaf2-46cb-9d6e-9fc761f5262f'),(28,'ROLE_GM:373a768a-daba-4b66-a47d-63458db9a087'),(29,'ROLE_GM:67ee6763-e914-4b5a-93d7-a9000bbfe1f9'),(5,'ROLE_GM:6a384bcd-d4b3-4b7f-a2fe-7d897ada0dd1'),(26,'ROLE_GM:728b82da-751a-46fe-a4c0-44391837991a'),(32,'ROLE_GM:843f6b10-151c-4ea8-9123-686640b58dcb'),(31,'ROLE_GM:85d573fd-cdbd-41fb-9eca-8dabc481ba1d'),(6,'ROLE_GM:c617d586-54e6-411d-8e38-649677980001'),(7,'ROLE_GM:c617d586-54e6-411d-8e38-649677980002'),(8,'ROLE_GM:c617d586-54e6-411d-8e38-649677980003'),(9,'ROLE_GM:c617d586-54e6-411d-8e38-649677980004'),(10,'ROLE_GM:c617d586-54e6-411d-8e38-649677980005'),(11,'ROLE_GM:c617d586-54e6-411d-8e38-649677980006'),(12,'ROLE_GM:c617d586-54e6-411d-8e38-649677980007'),(13,'ROLE_GM:c617d586-54e6-411d-8e38-649677980008'),(14,'ROLE_GM:c617d586-54e6-411d-8e38-649677980009'),(15,'ROLE_GM:c617d586-54e6-411d-8e38-649677980010'),(16,'ROLE_GM:c617d586-54e6-411d-8e38-649677980011'),(17,'ROLE_GM:c617d586-54e6-411d-8e38-649677980012'),(18,'ROLE_GM:c617d586-54e6-411d-8e38-649677980013'),(19,'ROLE_GM:c617d586-54e6-411d-8e38-649677980014'),(20,'ROLE_GM:c617d586-54e6-411d-8e38-649677980015'),(21,'ROLE_GM:c617d586-54e6-411d-8e38-649677980016'),(22,'ROLE_GM:c617d586-54e6-411d-8e38-649677980017'),(23,'ROLE_GM:c617d586-54e6-411d-8e38-649677980018'),(24,'ROLE_GM:c617d586-54e6-411d-8e38-649677980019'),(25,'ROLE_GM:c617d586-54e6-411d-8e38-649677980020'),(4,'ROLE_GM:c617d586-54e6-411d-8e38-64967798fa8a'),(3,'ROLE_PRE_AUTHENTICATED'),(2,'ROLE_USER'); +/*!40000 ALTER TABLE `iam_authority` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_email_notification` +-- + +DROP TABLE IF EXISTS `iam_email_notification`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_email_notification` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `UUID` varchar(36) NOT NULL, + `NOTIFICATION_TYPE` varchar(128) NOT NULL, + `SUBJECT` varchar(128) DEFAULT NULL, + `BODY` text, + `CREATION_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `DELIVERY_STATUS` varchar(128) DEFAULT NULL, + `LAST_UPDATE` timestamp NULL DEFAULT NULL, + `REQUEST_ID` bigint(20) DEFAULT NULL, + PRIMARY KEY (`ID`), + UNIQUE KEY `UUID` (`UUID`), + KEY `FK_iam_email_notification_request_id` (`REQUEST_ID`), + CONSTRAINT `FK_iam_email_notification_request_id` FOREIGN KEY (`REQUEST_ID`) REFERENCES `iam_reg_request` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_email_notification` +-- + +LOCK TABLES `iam_email_notification` WRITE; +/*!40000 ALTER TABLE `iam_email_notification` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_email_notification` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_exchange_policy` +-- + +DROP TABLE IF EXISTS `iam_exchange_policy`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_exchange_policy` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `creation_time` datetime NOT NULL, + `description` varchar(512) DEFAULT NULL, + `last_update_time` datetime NOT NULL, + `rule` varchar(6) NOT NULL, + `dest_m_param` varchar(256) DEFAULT NULL, + `dest_m_type` varchar(8) NOT NULL, + `origin_m_param` varchar(256) DEFAULT NULL, + `origin_m_type` varchar(8) NOT NULL, + PRIMARY KEY (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_exchange_policy` +-- + +LOCK TABLES `iam_exchange_policy` WRITE; +/*!40000 ALTER TABLE `iam_exchange_policy` DISABLE KEYS */; +INSERT INTO `iam_exchange_policy` VALUES (1,'2024-03-27 18:43:02','Allow all exchanges','2024-03-27 18:43:02','PERMIT',NULL,'ANY',NULL,'ANY'); +/*!40000 ALTER TABLE `iam_exchange_policy` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_exchange_scope_policies` +-- + +DROP TABLE IF EXISTS `iam_exchange_scope_policies`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_exchange_scope_policies` ( + `param` varchar(256) DEFAULT NULL, + `rule` varchar(6) NOT NULL, + `type` varchar(6) NOT NULL, + `exchange_policy_id` bigint(20) DEFAULT NULL, + KEY `FK_iam_exchange_scope_policies_exchange_policy_id` (`exchange_policy_id`), + CONSTRAINT `FK_iam_exchange_scope_policies_exchange_policy_id` FOREIGN KEY (`exchange_policy_id`) REFERENCES `iam_exchange_policy` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_exchange_scope_policies` +-- + +LOCK TABLES `iam_exchange_scope_policies` WRITE; +/*!40000 ALTER TABLE `iam_exchange_scope_policies` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_exchange_scope_policies` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_ext_authn` +-- + +DROP TABLE IF EXISTS `iam_ext_authn`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_ext_authn` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `authentication_time` datetime NOT NULL, + `expiration_time` datetime NOT NULL, + `saved_authn_id` bigint(20) DEFAULT NULL, + `type` varchar(32) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `saved_authn_id` (`saved_authn_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_ext_authn` +-- + +LOCK TABLES `iam_ext_authn` WRITE; +/*!40000 ALTER TABLE `iam_ext_authn` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_ext_authn` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_ext_authn_attr` +-- + +DROP TABLE IF EXISTS `iam_ext_authn_attr`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_ext_authn_attr` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `value` varchar(512) NOT NULL, + `details_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `FK_iam_ext_authn_attr_details_id` (`details_id`), + CONSTRAINT `FK_iam_ext_authn_attr_details_id` FOREIGN KEY (`details_id`) REFERENCES `iam_ext_authn` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_ext_authn_attr` +-- + +LOCK TABLES `iam_ext_authn_attr` WRITE; +/*!40000 ALTER TABLE `iam_ext_authn_attr` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_ext_authn_attr` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_group` +-- + +DROP TABLE IF EXISTS `iam_group`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_group` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `CREATIONTIME` datetime NOT NULL, + `DESCRIPTION` varchar(512) DEFAULT NULL, + `LASTUPDATETIME` datetime NOT NULL, + `name` varchar(512) NOT NULL, + `UUID` varchar(36) NOT NULL, + `parent_group_id` bigint(20) DEFAULT NULL, + `default_group` tinyint(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`), + UNIQUE KEY `NAME` (`name`), + UNIQUE KEY `UUID` (`UUID`), + KEY `FK_iam_group_parent_id` (`parent_group_id`), + CONSTRAINT `FK_iam_group_parent_id` FOREIGN KEY (`parent_group_id`) REFERENCES `iam_group` (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=128 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_group` +-- + +LOCK TABLES `iam_group` WRITE; +/*!40000 ALTER TABLE `iam_group` DISABLE KEYS */; +INSERT INTO `iam_group` VALUES (1,'2024-03-27 18:43:07','The production group','2024-03-27 18:43:07','Production','c617d586-54e6-411d-8e38-64967798fa8a',NULL,0),(2,'2024-03-27 18:43:07','The analysis group','2024-03-27 18:43:07','Analysis','6a384bcd-d4b3-4b7f-a2fe-7d897ada0dd1',NULL,0),(101,'2024-03-27 18:43:07','Test group-001','2024-03-27 18:43:07','Test-001','c617d586-54e6-411d-8e38-649677980001',NULL,0),(102,'2024-03-27 18:43:07','Test group-002','2024-03-27 18:43:07','Test-002','c617d586-54e6-411d-8e38-649677980002',NULL,0),(103,'2024-03-27 18:43:07','Test group-003','2024-03-27 18:43:07','Test-003','c617d586-54e6-411d-8e38-649677980003',NULL,0),(104,'2024-03-27 18:43:07','Test group-004','2024-03-27 18:43:07','Test-004','c617d586-54e6-411d-8e38-649677980004',NULL,0),(105,'2024-03-27 18:43:07','Test group-005','2024-03-27 18:43:07','Test-005','c617d586-54e6-411d-8e38-649677980005',NULL,0),(106,'2024-03-27 18:43:07','Test group-006','2024-03-27 18:43:07','Test-006','c617d586-54e6-411d-8e38-649677980006',NULL,0),(107,'2024-03-27 18:43:07','Test group-007','2024-03-27 18:43:07','Test-007','c617d586-54e6-411d-8e38-649677980007',NULL,0),(108,'2024-03-27 18:43:07','Test group-008','2024-03-27 18:43:07','Test-008','c617d586-54e6-411d-8e38-649677980008',NULL,0),(109,'2024-03-27 18:43:07','Test group-009','2024-03-27 18:43:07','Test-009','c617d586-54e6-411d-8e38-649677980009',NULL,0),(110,'2024-03-27 18:43:07','Test group-010','2024-03-27 18:43:07','Test-010','c617d586-54e6-411d-8e38-649677980010',NULL,0),(111,'2024-03-27 18:43:07','Test group-011','2024-03-27 18:43:07','Test-011','c617d586-54e6-411d-8e38-649677980011',NULL,0),(112,'2024-03-27 18:43:07','Test group-012','2024-03-27 18:43:07','Test-012','c617d586-54e6-411d-8e38-649677980012',NULL,0),(113,'2024-03-27 18:43:07','Test group-013','2024-03-27 18:43:07','Test-013','c617d586-54e6-411d-8e38-649677980013',NULL,0),(114,'2024-03-27 18:43:07','Test group-014','2024-03-27 18:43:07','Test-014','c617d586-54e6-411d-8e38-649677980014',NULL,0),(115,'2024-03-27 18:43:07','Test group-015','2024-03-27 18:43:07','Test-015','c617d586-54e6-411d-8e38-649677980015',NULL,0),(116,'2024-03-27 18:43:07','Test group-016','2024-03-27 18:43:07','Test-016','c617d586-54e6-411d-8e38-649677980016',NULL,0),(117,'2024-03-27 18:43:07','Test group-017','2024-03-27 18:43:07','Test-017','c617d586-54e6-411d-8e38-649677980017',NULL,0),(118,'2024-03-27 18:43:07','Test group-018','2024-03-27 18:43:07','Test-018','c617d586-54e6-411d-8e38-649677980018',NULL,0),(119,'2024-03-27 18:43:07','Test group-019','2024-03-27 18:43:07','Test-019','c617d586-54e6-411d-8e38-649677980019',NULL,0),(120,'2024-03-27 18:43:07','Test group-020','2024-03-27 18:43:07','Test-020','c617d586-54e6-411d-8e38-649677980020',NULL,0),(121,'2024-03-27 18:44:41',NULL,'2024-03-27 18:47:36','indigo-dc','728b82da-751a-46fe-a4c0-44391837991a',NULL,0),(122,'2024-03-27 18:44:54',NULL,'2024-03-27 18:47:36','indigo-dc/G1','28c111d8-4a0c-4969-8a80-64a9c406702d',121,0),(123,'2024-03-27 18:45:00',NULL,'2024-03-27 18:47:39','indigo-dc/G2','373a768a-daba-4b66-a47d-63458db9a087',121,0),(124,'2024-03-27 18:45:05',NULL,'2024-03-27 18:47:59','indigo-dc/R1','67ee6763-e914-4b5a-93d7-a9000bbfe1f9',121,0),(125,'2024-03-27 18:45:29',NULL,'2024-03-27 18:47:36','indigo-dc/G1/R1','3534a378-eaf2-46cb-9d6e-9fc761f5262f',122,0),(126,'2024-03-27 18:46:00',NULL,'2024-03-27 18:47:59','indigo-dc/G2/G3','85d573fd-cdbd-41fb-9eca-8dabc481ba1d',123,0),(127,'2024-03-27 18:46:20',NULL,'2024-03-27 18:50:13','indigo-dc/G2/R1','843f6b10-151c-4ea8-9123-686640b58dcb',123,0); +/*!40000 ALTER TABLE `iam_group` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_group_attrs` +-- + +DROP TABLE IF EXISTS `iam_group_attrs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_group_attrs` ( + `NAME` varchar(64) NOT NULL, + `val` varchar(256) DEFAULT NULL, + `group_id` bigint(20) DEFAULT NULL, + KEY `INDEX_iam_group_attrs_name` (`NAME`), + KEY `INDEX_iam_group_attrs_name_val` (`NAME`,`val`), + KEY `FK_iam_group_attrs_group_id` (`group_id`), + CONSTRAINT `FK_iam_group_attrs_group_id` FOREIGN KEY (`group_id`) REFERENCES `iam_group` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_group_attrs` +-- + +LOCK TABLES `iam_group_attrs` WRITE; +/*!40000 ALTER TABLE `iam_group_attrs` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_group_attrs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_group_labels` +-- + +DROP TABLE IF EXISTS `iam_group_labels`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_group_labels` ( + `NAME` varchar(64) NOT NULL, + `PREFIX` varchar(256) DEFAULT NULL, + `val` varchar(64) DEFAULT NULL, + `group_id` bigint(20) DEFAULT NULL, + KEY `INDEX_iam_group_labels_prefix_name_val` (`PREFIX`,`NAME`,`val`), + KEY `INDEX_iam_group_labels_prefix_name` (`PREFIX`,`NAME`), + KEY `FK_iam_group_labels_group_id` (`group_id`), + CONSTRAINT `FK_iam_group_labels_group_id` FOREIGN KEY (`group_id`) REFERENCES `iam_group` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_group_labels` +-- + +LOCK TABLES `iam_group_labels` WRITE; +/*!40000 ALTER TABLE `iam_group_labels` DISABLE KEYS */; +INSERT INTO `iam_group_labels` VALUES ('voms.role',NULL,NULL,125),('wlcg.optional-group',NULL,NULL,125),('voms.role',NULL,NULL,124),('wlcg.optional-group',NULL,NULL,124),('voms.role',NULL,NULL,127),('wlcg.optional-group',NULL,NULL,127); +/*!40000 ALTER TABLE `iam_group_labels` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_group_request` +-- + +DROP TABLE IF EXISTS `iam_group_request`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_group_request` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `UUID` varchar(36) NOT NULL, + `ACCOUNT_ID` bigint(20) DEFAULT NULL, + `GROUP_ID` bigint(20) DEFAULT NULL, + `STATUS` varchar(50) DEFAULT NULL, + `NOTES` text, + `MOTIVATION` text, + `CREATIONTIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `LASTUPDATETIME` timestamp NOT NULL DEFAULT '1999-12-31 23:00:00', + PRIMARY KEY (`ID`), + UNIQUE KEY `UUID` (`UUID`), + KEY `FK_iam_group_request_account_id` (`ACCOUNT_ID`), + KEY `FK_iam_group_request_group_id` (`GROUP_ID`), + CONSTRAINT `FK_iam_group_request_account_id` FOREIGN KEY (`ACCOUNT_ID`) REFERENCES `iam_account` (`ID`), + CONSTRAINT `FK_iam_group_request_group_id` FOREIGN KEY (`GROUP_ID`) REFERENCES `iam_group` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_group_request` +-- + +LOCK TABLES `iam_group_request` WRITE; +/*!40000 ALTER TABLE `iam_group_request` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_group_request` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_notification_receiver` +-- + +DROP TABLE IF EXISTS `iam_notification_receiver`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_notification_receiver` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `NOTIFICATION_ID` bigint(20) DEFAULT NULL, + `EMAIL_ADDRESS` varchar(254) DEFAULT NULL, + PRIMARY KEY (`ID`), + KEY `FK_iam_notification_receiver_notification_id` (`NOTIFICATION_ID`), + CONSTRAINT `FK_iam_notification_receiver_notification_id` FOREIGN KEY (`NOTIFICATION_ID`) REFERENCES `iam_email_notification` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_notification_receiver` +-- + +LOCK TABLES `iam_notification_receiver` WRITE; +/*!40000 ALTER TABLE `iam_notification_receiver` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_notification_receiver` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_oidc_id` +-- + +DROP TABLE IF EXISTS `iam_oidc_id`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_oidc_id` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `ISSUER` varchar(256) NOT NULL, + `SUBJECT` varchar(256) NOT NULL, + `account_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`ID`), + KEY `FK_iam_oidc_id_account_id` (`account_id`), + CONSTRAINT `FK_iam_oidc_id_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_oidc_id` +-- + +LOCK TABLES `iam_oidc_id` WRITE; +/*!40000 ALTER TABLE `iam_oidc_id` DISABLE KEYS */; +INSERT INTO `iam_oidc_id` VALUES (1,'https://accounts.google.com','114132403455520317223',1),(2,'https://accounts.google.com','105440632287425289613',2),(3,'urn:test-oidc-issuer','test-user',2); +/*!40000 ALTER TABLE `iam_oidc_id` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_reg_request` +-- + +DROP TABLE IF EXISTS `iam_reg_request`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_reg_request` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `UUID` varchar(36) NOT NULL, + `CREATIONTIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `ACCOUNT_ID` bigint(20) DEFAULT NULL, + `STATUS` varchar(50) DEFAULT NULL, + `LASTUPDATETIME` timestamp NULL DEFAULT NULL, + `notes` text, + PRIMARY KEY (`ID`), + UNIQUE KEY `UUID` (`UUID`), + KEY `FK_iam_reg_request_account_id` (`ACCOUNT_ID`), + CONSTRAINT `FK_iam_reg_request_account_id` FOREIGN KEY (`ACCOUNT_ID`) REFERENCES `iam_account` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_reg_request` +-- + +LOCK TABLES `iam_reg_request` WRITE; +/*!40000 ALTER TABLE `iam_reg_request` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_reg_request` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_reg_request_labels` +-- + +DROP TABLE IF EXISTS `iam_reg_request_labels`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_reg_request_labels` ( + `NAME` varchar(64) NOT NULL, + `PREFIX` varchar(256) DEFAULT NULL, + `val` varchar(64) DEFAULT NULL, + `request_id` bigint(20) DEFAULT NULL, + KEY `INDEX_iam_reg_request_labels_prefix_name_val` (`PREFIX`,`NAME`,`val`), + KEY `INDEX_iam_reg_request_labels_prefix_name` (`PREFIX`,`NAME`), + KEY `FK_iam_reg_request_labels_request_id` (`request_id`), + CONSTRAINT `FK_iam_reg_request_labels_request_id` FOREIGN KEY (`request_id`) REFERENCES `iam_reg_request` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_reg_request_labels` +-- + +LOCK TABLES `iam_reg_request_labels` WRITE; +/*!40000 ALTER TABLE `iam_reg_request_labels` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_reg_request_labels` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_saml_id` +-- + +DROP TABLE IF EXISTS `iam_saml_id`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_saml_id` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `IDPID` varchar(256) NOT NULL, + `USERID` varchar(256) NOT NULL, + `account_id` bigint(20) DEFAULT NULL, + `attribute_id` varchar(256) NOT NULL, + PRIMARY KEY (`ID`), + KEY `FK_iam_saml_id_account_id` (`account_id`), + KEY `IDX_IAM_SAML_ID_1` (`IDPID`,`attribute_id`,`USERID`), + CONSTRAINT `FK_iam_saml_id_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_saml_id` +-- + +LOCK TABLES `iam_saml_id` WRITE; +/*!40000 ALTER TABLE `iam_saml_id` DISABLE KEYS */; +INSERT INTO `iam_saml_id` VALUES (1,'https://idptestbed/idp/shibboleth','admin@example.org',1,'urn:oid:1.3.6.1.4.1.5923.1.1.1.13'),(2,'https://idptestbed/idp/shibboleth','andrea.ceccanti@example.org',2,'urn:oid:0.9.2342.19200300.100.1.3'),(3,'https://idptestbed/idp/shibboleth','78901@idptestbed',2,'urn:oid:1.3.6.1.4.1.5923.1.1.1.13'); +/*!40000 ALTER TABLE `iam_saml_id` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_scope_policy` +-- + +DROP TABLE IF EXISTS `iam_scope_policy`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_scope_policy` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `creation_time` datetime NOT NULL, + `description` varchar(512) DEFAULT NULL, + `last_update_time` datetime NOT NULL, + `rule` varchar(6) NOT NULL, + `account_id` bigint(20) DEFAULT NULL, + `group_id` bigint(20) DEFAULT NULL, + `matching_policy` varchar(6) NOT NULL DEFAULT 'EQ', + PRIMARY KEY (`ID`), + KEY `FK_iam_scope_policy_group_id` (`group_id`), + KEY `FK_iam_scope_policy_account_id` (`account_id`), + CONSTRAINT `FK_iam_scope_policy_account_id` FOREIGN KEY (`account_id`) REFERENCES `iam_account` (`ID`), + CONSTRAINT `FK_iam_scope_policy_group_id` FOREIGN KEY (`group_id`) REFERENCES `iam_group` (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_scope_policy` +-- + +LOCK TABLES `iam_scope_policy` WRITE; +/*!40000 ALTER TABLE `iam_scope_policy` DISABLE KEYS */; +INSERT INTO `iam_scope_policy` VALUES (1,'2024-03-27 18:42:58','Default Permit ALL policy','2024-03-27 18:42:58','PERMIT',NULL,NULL,'EQ'); +/*!40000 ALTER TABLE `iam_scope_policy` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_scope_policy_scope` +-- + +DROP TABLE IF EXISTS `iam_scope_policy_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_scope_policy_scope` ( + `policy_id` bigint(20) DEFAULT NULL, + `scope` varchar(256) DEFAULT NULL, + UNIQUE KEY `INDEX_iam_scope_policy_scope_policy_id_scope` (`policy_id`,`scope`), + KEY `INDEX_iam_scope_policy_scope_scope` (`scope`), + CONSTRAINT `FK_iam_scope_policy_scope_policy_id` FOREIGN KEY (`policy_id`) REFERENCES `iam_scope_policy` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_scope_policy_scope` +-- + +LOCK TABLES `iam_scope_policy_scope` WRITE; +/*!40000 ALTER TABLE `iam_scope_policy_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_scope_policy_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_ssh_key` +-- + +DROP TABLE IF EXISTS `iam_ssh_key`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_ssh_key` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `fingerprint` varchar(48) NOT NULL, + `LABEL` varchar(36) NOT NULL, + `is_primary` tinyint(1) DEFAULT '0', + `val` longtext, + `ACCOUNT_ID` bigint(20) DEFAULT NULL, + `creation_time` datetime NOT NULL, + `last_update_time` datetime NOT NULL, + PRIMARY KEY (`ID`), + UNIQUE KEY `fingerprint` (`fingerprint`), + KEY `FK_iam_ssh_key_ACCOUNT_ID` (`ACCOUNT_ID`), + CONSTRAINT `FK_iam_ssh_key_ACCOUNT_ID` FOREIGN KEY (`ACCOUNT_ID`) REFERENCES `iam_account` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_ssh_key` +-- + +LOCK TABLES `iam_ssh_key` WRITE; +/*!40000 ALTER TABLE `iam_ssh_key` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_ssh_key` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_totp_mfa` +-- + +DROP TABLE IF EXISTS `iam_totp_mfa`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_totp_mfa` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `active` tinyint(1) NOT NULL DEFAULT '0', + `secret` varchar(255) NOT NULL, + `creation_time` datetime NOT NULL, + `last_update_time` datetime NOT NULL, + `ACCOUNT_ID` bigint(20) DEFAULT NULL, + PRIMARY KEY (`ID`), + KEY `FK_iam_totp_mfa_account_id` (`ACCOUNT_ID`), + CONSTRAINT `FK_iam_totp_mfa_account_id` FOREIGN KEY (`ACCOUNT_ID`) REFERENCES `iam_account` (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_totp_mfa` +-- + +LOCK TABLES `iam_totp_mfa` WRITE; +/*!40000 ALTER TABLE `iam_totp_mfa` DISABLE KEYS */; +INSERT INTO `iam_totp_mfa` VALUES (1,1,'secret','2024-03-27 18:43:07','2024-03-27 18:43:07',1000); +/*!40000 ALTER TABLE `iam_totp_mfa` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_totp_recovery_code` +-- + +DROP TABLE IF EXISTS `iam_totp_recovery_code`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_totp_recovery_code` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `code` varchar(255) NOT NULL, + `totp_mfa_id` bigint(20) NOT NULL, + PRIMARY KEY (`ID`), + KEY `FK_iam_totp_recovery_code_totp_mfa_id` (`totp_mfa_id`), + CONSTRAINT `FK_iam_totp_recovery_code_totp_mfa_id` FOREIGN KEY (`totp_mfa_id`) REFERENCES `iam_totp_mfa` (`ID`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_totp_recovery_code` +-- + +LOCK TABLES `iam_totp_recovery_code` WRITE; +/*!40000 ALTER TABLE `iam_totp_recovery_code` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_totp_recovery_code` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_user_info` +-- + +DROP TABLE IF EXISTS `iam_user_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_user_info` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `BIRTHDATE` varchar(255) DEFAULT NULL, + `EMAIL` varchar(128) NOT NULL, + `EMAILVERIFIED` tinyint(1) DEFAULT '0', + `FAMILYNAME` varchar(64) NOT NULL, + `GENDER` varchar(255) DEFAULT NULL, + `GIVENNAME` varchar(64) NOT NULL, + `LOCALE` varchar(255) DEFAULT NULL, + `MIDDLENAME` varchar(64) DEFAULT NULL, + `NICKNAME` varchar(255) DEFAULT NULL, + `PHONENUMBER` varchar(255) DEFAULT NULL, + `PHONENUMBERVERIFIED` tinyint(1) DEFAULT '0', + `PICTURE` varchar(255) DEFAULT NULL, + `PROFILE` varchar(255) DEFAULT NULL, + `WEBSITE` varchar(255) DEFAULT NULL, + `ZONEINFO` varchar(255) DEFAULT NULL, + `ADDRESS_ID` bigint(20) DEFAULT NULL, + `DTYPE` varchar(31) DEFAULT NULL, + PRIMARY KEY (`ID`), + KEY `iui_em_idx` (`EMAIL`), + KEY `iui_gn_fn_idx` (`GIVENNAME`,`FAMILYNAME`), + KEY `FK_iam_user_info_address_id` (`ADDRESS_ID`), + CONSTRAINT `FK_iam_user_info_address_id` FOREIGN KEY (`ADDRESS_ID`) REFERENCES `iam_address` (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_user_info` +-- + +LOCK TABLES `iam_user_info` WRITE; +/*!40000 ALTER TABLE `iam_user_info` DISABLE KEYS */; +INSERT INTO `iam_user_info` VALUES (1,'1950-01-01','1_admin@iam.test',1,'User','M','Admin',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(2,'1950-01-01','test@iam.test',1,'User','M','Test',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(3,'1950-01-01','3_admin@iam.test',1,'Email 0','M','Duplicate',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(4,'1950-01-01','4_duplicate@iam.test',1,'Email 1','M','Duplicate ',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(5,'1950-01-01','5_duplicate@iam.test',1,'Email 2','M','Duplicate ',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(100,NULL,'test-100@test.org',1,'User',NULL,'Test-100',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(101,NULL,'test-101@test.org',1,'User',NULL,'Test-101',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(102,NULL,'test-102@test.org',1,'User',NULL,'Test-102',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(103,NULL,'test-103@test.org',1,'User',NULL,'Test-103',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(104,NULL,'test-104@test.org',1,'User',NULL,'Test-104',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(105,NULL,'test-105@test.org',1,'User',NULL,'Test-105',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(106,NULL,'test-106@test.org',1,'User',NULL,'Test-106',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(107,NULL,'test-107@test.org',1,'User',NULL,'Test-107',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(108,NULL,'test-108@test.org',1,'User',NULL,'Test-108',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(109,NULL,'test-109@test.org',1,'User',NULL,'Test-109',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(110,NULL,'test-110@test.org',1,'User',NULL,'Test-110',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(111,NULL,'test-111@test.org',1,'User',NULL,'Test-111',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(112,NULL,'test-112@test.org',1,'User',NULL,'Test-112',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(113,NULL,'test-113@test.org',1,'User',NULL,'Test-113',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(114,NULL,'test-114@test.org',1,'User',NULL,'Test-114',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(115,NULL,'test-115@test.org',1,'User',NULL,'Test-115',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(116,NULL,'test-116@test.org',1,'User',NULL,'Test-116',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(117,NULL,'test-117@test.org',1,'User',NULL,'Test-117',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(118,NULL,'test-118@test.org',1,'User',NULL,'Test-118',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(119,NULL,'test-119@test.org',1,'User',NULL,'Test-119',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(120,NULL,'test-120@test.org',1,'User',NULL,'Test-120',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(121,NULL,'test-121@test.org',1,'User',NULL,'Test-121',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(122,NULL,'test-122@test.org',1,'User',NULL,'Test-122',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(123,NULL,'test-123@test.org',1,'User',NULL,'Test-123',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(124,NULL,'test-124@test.org',1,'User',NULL,'Test-124',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(125,NULL,'test-125@test.org',1,'User',NULL,'Test-125',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(126,NULL,'test-126@test.org',1,'User',NULL,'Test-126',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(127,NULL,'test-127@test.org',1,'User',NULL,'Test-127',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(128,NULL,'test-128@test.org',1,'User',NULL,'Test-128',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(129,NULL,'test-129@test.org',1,'User',NULL,'Test-129',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(130,NULL,'test-130@test.org',1,'User',NULL,'Test-130',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(131,NULL,'test-131@test.org',1,'User',NULL,'Test-131',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(132,NULL,'test-132@test.org',1,'User',NULL,'Test-132',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(133,NULL,'test-133@test.org',1,'User',NULL,'Test-133',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(134,NULL,'test-134@test.org',1,'User',NULL,'Test-134',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(135,NULL,'test-135@test.org',1,'User',NULL,'Test-135',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(136,NULL,'test-136@test.org',1,'User',NULL,'Test-136',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(137,NULL,'test-137@test.org',1,'User',NULL,'Test-137',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(138,NULL,'test-138@test.org',1,'User',NULL,'Test-138',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(139,NULL,'test-139@test.org',1,'User',NULL,'Test-139',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(140,NULL,'test-140@test.org',1,'User',NULL,'Test-140',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(141,NULL,'test-141@test.org',1,'User',NULL,'Test-141',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(142,NULL,'test-142@test.org',1,'User',NULL,'Test-142',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(143,NULL,'test-143@test.org',1,'User',NULL,'Test-143',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(144,NULL,'test-144@test.org',1,'User',NULL,'Test-144',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(145,NULL,'test-145@test.org',1,'User',NULL,'Test-145',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(146,NULL,'test-146@test.org',1,'User',NULL,'Test-146',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(147,NULL,'test-147@test.org',1,'User',NULL,'Test-147',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(148,NULL,'test-148@test.org',1,'User',NULL,'Test-148',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(149,NULL,'test-149@test.org',1,'User',NULL,'Test-149',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(150,NULL,'test-150@test.org',1,'User',NULL,'Test-150',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(151,NULL,'test-151@test.org',1,'User',NULL,'Test-151',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(152,NULL,'test-152@test.org',1,'User',NULL,'Test-152',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(153,NULL,'test-153@test.org',1,'User',NULL,'Test-153',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(154,NULL,'test-154@test.org',1,'User',NULL,'Test-154',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(155,NULL,'test-155@test.org',1,'User',NULL,'Test-155',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(156,NULL,'test-156@test.org',1,'User',NULL,'Test-156',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(157,NULL,'test-157@test.org',1,'User',NULL,'Test-157',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(158,NULL,'test-158@test.org',1,'User',NULL,'Test-158',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(159,NULL,'test-159@test.org',1,'User',NULL,'Test-159',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(160,NULL,'test-160@test.org',1,'User',NULL,'Test-160',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(161,NULL,'test-161@test.org',1,'User',NULL,'Test-161',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(162,NULL,'test-162@test.org',1,'User',NULL,'Test-162',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(163,NULL,'test-163@test.org',1,'User',NULL,'Test-163',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(164,NULL,'test-164@test.org',1,'User',NULL,'Test-164',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(165,NULL,'test-165@test.org',1,'User',NULL,'Test-165',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(166,NULL,'test-166@test.org',1,'User',NULL,'Test-166',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(167,NULL,'test-167@test.org',1,'User',NULL,'Test-167',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(168,NULL,'test-168@test.org',1,'User',NULL,'Test-168',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(169,NULL,'test-169@test.org',1,'User',NULL,'Test-169',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(170,NULL,'test-170@test.org',1,'User',NULL,'Test-170',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(171,NULL,'test-171@test.org',1,'User',NULL,'Test-171',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(172,NULL,'test-172@test.org',1,'User',NULL,'Test-172',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(173,NULL,'test-173@test.org',1,'User',NULL,'Test-173',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(174,NULL,'test-174@test.org',1,'User',NULL,'Test-174',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(175,NULL,'test-175@test.org',1,'User',NULL,'Test-175',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(176,NULL,'test-176@test.org',1,'User',NULL,'Test-176',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(177,NULL,'test-177@test.org',1,'User',NULL,'Test-177',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(178,NULL,'test-178@test.org',1,'User',NULL,'Test-178',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(179,NULL,'test-179@test.org',1,'User',NULL,'Test-179',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(180,NULL,'test-180@test.org',1,'User',NULL,'Test-180',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(181,NULL,'test-181@test.org',1,'User',NULL,'Test-181',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(182,NULL,'test-182@test.org',1,'User',NULL,'Test-182',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(183,NULL,'test-183@test.org',1,'User',NULL,'Test-183',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(184,NULL,'test-184@test.org',1,'User',NULL,'Test-184',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(185,NULL,'test-185@test.org',1,'User',NULL,'Test-185',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(186,NULL,'test-186@test.org',1,'User',NULL,'Test-186',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(187,NULL,'test-187@test.org',1,'User',NULL,'Test-187',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(188,NULL,'test-188@test.org',1,'User',NULL,'Test-188',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(189,NULL,'test-189@test.org',1,'User',NULL,'Test-189',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(190,NULL,'test-190@test.org',1,'User',NULL,'Test-190',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(191,NULL,'test-191@test.org',1,'User',NULL,'Test-191',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(192,NULL,'test-192@test.org',1,'User',NULL,'Test-192',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(193,NULL,'test-193@test.org',1,'User',NULL,'Test-193',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(194,NULL,'test-194@test.org',1,'User',NULL,'Test-194',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(195,NULL,'test-195@test.org',1,'User',NULL,'Test-195',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(196,NULL,'test-196@test.org',1,'User',NULL,'Test-196',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(197,NULL,'test-197@test.org',1,'User',NULL,'Test-197',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(198,NULL,'test-198@test.org',1,'User',NULL,'Test-198',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(199,NULL,'test-199@test.org',1,'User',NULL,'Test-199',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(200,NULL,'test-200@test.org',1,'User',NULL,'Test-200',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(201,NULL,'test-201@test.org',1,'User',NULL,'Test-201',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(202,NULL,'test-202@test.org',1,'User',NULL,'Test-202',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(203,NULL,'test-203@test.org',1,'User',NULL,'Test-203',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(204,NULL,'test-204@test.org',1,'User',NULL,'Test-204',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(205,NULL,'test-205@test.org',1,'User',NULL,'Test-205',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(206,NULL,'test-206@test.org',1,'User',NULL,'Test-206',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(207,NULL,'test-207@test.org',1,'User',NULL,'Test-207',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(208,NULL,'test-208@test.org',1,'User',NULL,'Test-208',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(209,NULL,'test-209@test.org',1,'User',NULL,'Test-209',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(210,NULL,'test-210@test.org',1,'User',NULL,'Test-210',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(211,NULL,'test-211@test.org',1,'User',NULL,'Test-211',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(212,NULL,'test-212@test.org',1,'User',NULL,'Test-212',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(213,NULL,'test-213@test.org',1,'User',NULL,'Test-213',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(214,NULL,'test-214@test.org',1,'User',NULL,'Test-214',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(215,NULL,'test-215@test.org',1,'User',NULL,'Test-215',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(216,NULL,'test-216@test.org',1,'User',NULL,'Test-216',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(217,NULL,'test-217@test.org',1,'User',NULL,'Test-217',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(218,NULL,'test-218@test.org',1,'User',NULL,'Test-218',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(219,NULL,'test-219@test.org',1,'User',NULL,'Test-219',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(220,NULL,'test-220@test.org',1,'User',NULL,'Test-220',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(221,NULL,'test-221@test.org',1,'User',NULL,'Test-221',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(222,NULL,'test-222@test.org',1,'User',NULL,'Test-222',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(223,NULL,'test-223@test.org',1,'User',NULL,'Test-223',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(224,NULL,'test-224@test.org',1,'User',NULL,'Test-224',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(225,NULL,'test-225@test.org',1,'User',NULL,'Test-225',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(226,NULL,'test-226@test.org',1,'User',NULL,'Test-226',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(227,NULL,'test-227@test.org',1,'User',NULL,'Test-227',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(228,NULL,'test-228@test.org',1,'User',NULL,'Test-228',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(229,NULL,'test-229@test.org',1,'User',NULL,'Test-229',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(230,NULL,'test-230@test.org',1,'User',NULL,'Test-230',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(231,NULL,'test-231@test.org',1,'User',NULL,'Test-231',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(232,NULL,'test-232@test.org',1,'User',NULL,'Test-232',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(233,NULL,'test-233@test.org',1,'User',NULL,'Test-233',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(234,NULL,'test-234@test.org',1,'User',NULL,'Test-234',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(235,NULL,'test-235@test.org',1,'User',NULL,'Test-235',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(236,NULL,'test-236@test.org',1,'User',NULL,'Test-236',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(237,NULL,'test-237@test.org',1,'User',NULL,'Test-237',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(238,NULL,'test-238@test.org',1,'User',NULL,'Test-238',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(239,NULL,'test-239@test.org',1,'User',NULL,'Test-239',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(240,NULL,'test-240@test.org',1,'User',NULL,'Test-240',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(241,NULL,'test-241@test.org',1,'User',NULL,'Test-241',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(242,NULL,'test-242@test.org',1,'User',NULL,'Test-242',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(243,NULL,'test-243@test.org',1,'User',NULL,'Test-243',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(244,NULL,'test-244@test.org',1,'User',NULL,'Test-244',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(245,NULL,'test-245@test.org',1,'User',NULL,'Test-245',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(246,NULL,'test-246@test.org',1,'User',NULL,'Test-246',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(247,NULL,'test-247@test.org',1,'User',NULL,'Test-247',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(248,NULL,'test-248@test.org',1,'User',NULL,'Test-248',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(249,NULL,'test-249@test.org',1,'User',NULL,'Test-249',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(250,NULL,'test-250@test.org',1,'User',NULL,'Test-250',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(251,NULL,'test-251@test.org',1,'User',NULL,'Test-251',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(252,NULL,'test-252@test.org',1,'User',NULL,'Test-252',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(253,NULL,'test-253@test.org',1,'User',NULL,'Test-253',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(254,NULL,'test-254@test.org',1,'User',NULL,'Test-254',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(255,NULL,'test-255@test.org',1,'User',NULL,'Test-255',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(256,NULL,'test-256@test.org',1,'User',NULL,'Test-256',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(257,NULL,'test-257@test.org',1,'User',NULL,'Test-257',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(258,NULL,'test-258@test.org',1,'User',NULL,'Test-258',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(259,NULL,'test-259@test.org',1,'User',NULL,'Test-259',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(260,NULL,'test-260@test.org',1,'User',NULL,'Test-260',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(261,NULL,'test-261@test.org',1,'User',NULL,'Test-261',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(262,NULL,'test-262@test.org',1,'User',NULL,'Test-262',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(263,NULL,'test-263@test.org',1,'User',NULL,'Test-263',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(264,NULL,'test-264@test.org',1,'User',NULL,'Test-264',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(265,NULL,'test-265@test.org',1,'User',NULL,'Test-265',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(266,NULL,'test-266@test.org',1,'User',NULL,'Test-266',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(267,NULL,'test-267@test.org',1,'User',NULL,'Test-267',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(268,NULL,'test-268@test.org',1,'User',NULL,'Test-268',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(269,NULL,'test-269@test.org',1,'User',NULL,'Test-269',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(270,NULL,'test-270@test.org',1,'User',NULL,'Test-270',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(271,NULL,'test-271@test.org',1,'User',NULL,'Test-271',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(272,NULL,'test-272@test.org',1,'User',NULL,'Test-272',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(273,NULL,'test-273@test.org',1,'User',NULL,'Test-273',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(274,NULL,'test-274@test.org',1,'User',NULL,'Test-274',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(275,NULL,'test-275@test.org',1,'User',NULL,'Test-275',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(276,NULL,'test-276@test.org',1,'User',NULL,'Test-276',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(277,NULL,'test-277@test.org',1,'User',NULL,'Test-277',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(278,NULL,'test-278@test.org',1,'User',NULL,'Test-278',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(279,NULL,'test-279@test.org',1,'User',NULL,'Test-279',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(280,NULL,'test-280@test.org',1,'User',NULL,'Test-280',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(281,NULL,'test-281@test.org',1,'User',NULL,'Test-281',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(282,NULL,'test-282@test.org',1,'User',NULL,'Test-282',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(283,NULL,'test-283@test.org',1,'User',NULL,'Test-283',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(284,NULL,'test-284@test.org',1,'User',NULL,'Test-284',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(285,NULL,'test-285@test.org',1,'User',NULL,'Test-285',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(286,NULL,'test-286@test.org',1,'User',NULL,'Test-286',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(287,NULL,'test-287@test.org',1,'User',NULL,'Test-287',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(288,NULL,'test-288@test.org',1,'User',NULL,'Test-288',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(289,NULL,'test-289@test.org',1,'User',NULL,'Test-289',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(290,NULL,'test-290@test.org',1,'User',NULL,'Test-290',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(291,NULL,'test-291@test.org',1,'User',NULL,'Test-291',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(292,NULL,'test-292@test.org',1,'User',NULL,'Test-292',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(293,NULL,'test-293@test.org',1,'User',NULL,'Test-293',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(294,NULL,'test-294@test.org',1,'User',NULL,'Test-294',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(295,NULL,'test-295@test.org',1,'User',NULL,'Test-295',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(296,NULL,'test-296@test.org',1,'User',NULL,'Test-296',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(297,NULL,'test-297@test.org',1,'User',NULL,'Test-297',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(298,NULL,'test-298@test.org',1,'User',NULL,'Test-298',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(299,NULL,'test-299@test.org',1,'User',NULL,'Test-299',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(300,NULL,'test-300@test.org',1,'User',NULL,'Test-300',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(301,NULL,'test-301@test.org',1,'User',NULL,'Test-301',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(302,NULL,'test-302@test.org',1,'User',NULL,'Test-302',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(303,NULL,'test-303@test.org',1,'User',NULL,'Test-303',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(304,NULL,'test-304@test.org',1,'User',NULL,'Test-304',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(305,NULL,'test-305@test.org',1,'User',NULL,'Test-305',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(306,NULL,'test-306@test.org',1,'User',NULL,'Test-306',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(307,NULL,'test-307@test.org',1,'User',NULL,'Test-307',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(308,NULL,'test-308@test.org',1,'User',NULL,'Test-308',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(309,NULL,'test-309@test.org',1,'User',NULL,'Test-309',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(310,NULL,'test-310@test.org',1,'User',NULL,'Test-310',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(311,NULL,'test-311@test.org',1,'User',NULL,'Test-311',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(312,NULL,'test-312@test.org',1,'User',NULL,'Test-312',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(313,NULL,'test-313@test.org',1,'User',NULL,'Test-313',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(314,NULL,'test-314@test.org',1,'User',NULL,'Test-314',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(315,NULL,'test-315@test.org',1,'User',NULL,'Test-315',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(316,NULL,'test-316@test.org',1,'User',NULL,'Test-316',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(317,NULL,'test-317@test.org',1,'User',NULL,'Test-317',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(318,NULL,'test-318@test.org',1,'User',NULL,'Test-318',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(319,NULL,'test-319@test.org',1,'User',NULL,'Test-319',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(320,NULL,'test-320@test.org',1,'User',NULL,'Test-320',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(321,NULL,'test-321@test.org',1,'User',NULL,'Test-321',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(322,NULL,'test-322@test.org',1,'User',NULL,'Test-322',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(323,NULL,'test-323@test.org',1,'User',NULL,'Test-323',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(324,NULL,'test-324@test.org',1,'User',NULL,'Test-324',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(325,NULL,'test-325@test.org',1,'User',NULL,'Test-325',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(326,NULL,'test-326@test.org',1,'User',NULL,'Test-326',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(327,NULL,'test-327@test.org',1,'User',NULL,'Test-327',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(328,NULL,'test-328@test.org',1,'User',NULL,'Test-328',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(329,NULL,'test-329@test.org',1,'User',NULL,'Test-329',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(330,NULL,'test-330@test.org',1,'User',NULL,'Test-330',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(331,NULL,'test-331@test.org',1,'User',NULL,'Test-331',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(332,NULL,'test-332@test.org',1,'User',NULL,'Test-332',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(333,NULL,'test-333@test.org',1,'User',NULL,'Test-333',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(334,NULL,'test-334@test.org',1,'User',NULL,'Test-334',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(335,NULL,'test-335@test.org',1,'User',NULL,'Test-335',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(336,NULL,'test-336@test.org',1,'User',NULL,'Test-336',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(337,NULL,'test-337@test.org',1,'User',NULL,'Test-337',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(338,NULL,'test-338@test.org',1,'User',NULL,'Test-338',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(339,NULL,'test-339@test.org',1,'User',NULL,'Test-339',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(340,NULL,'test-340@test.org',1,'User',NULL,'Test-340',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(341,NULL,'test-341@test.org',1,'User',NULL,'Test-341',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(342,NULL,'test-342@test.org',1,'User',NULL,'Test-342',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(343,NULL,'test-343@test.org',1,'User',NULL,'Test-343',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(344,NULL,'test-344@test.org',1,'User',NULL,'Test-344',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(345,NULL,'test-345@test.org',1,'User',NULL,'Test-345',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(346,NULL,'test-346@test.org',1,'User',NULL,'Test-346',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(347,NULL,'test-347@test.org',1,'User',NULL,'Test-347',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL),(1000,'2000-01-01','testwithmfa@iam.test',1,'MFA','F','Test',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL); +/*!40000 ALTER TABLE `iam_user_info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_x509_cert` +-- + +DROP TABLE IF EXISTS `iam_x509_cert`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_x509_cert` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `subject_dn` varchar(256) CHARACTER SET latin1 COLLATE latin1_general_cs DEFAULT NULL, + `LABEL` varchar(36) NOT NULL, + `is_primary` tinyint(1) DEFAULT '0', + `ACCOUNT_ID` bigint(20) DEFAULT NULL, + `CERTIFICATE` text, + `issuer_dn` varchar(256) CHARACTER SET latin1 COLLATE latin1_general_cs DEFAULT NULL, + `creation_time` datetime NOT NULL, + `last_update_time` datetime NOT NULL, + `proxy_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`ID`), + UNIQUE KEY `idx_iam_x509_cert_cerificate` (`CERTIFICATE`(256)), + KEY `FK_iam_x509_cert_ACCOUNT_ID` (`ACCOUNT_ID`), + KEY `FK_iam_x509_cert_proxy_id` (`proxy_id`), + KEY `idx_subject_dn` (`subject_dn`), + CONSTRAINT `FK_iam_x509_cert_ACCOUNT_ID` FOREIGN KEY (`ACCOUNT_ID`) REFERENCES `iam_account` (`ID`), + CONSTRAINT `FK_iam_x509_cert_proxy_id` FOREIGN KEY (`proxy_id`) REFERENCES `iam_x509_proxy` (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_x509_cert` +-- + +LOCK TABLES `iam_x509_cert` WRITE; +/*!40000 ALTER TABLE `iam_x509_cert` DISABLE KEYS */; +INSERT INTO `iam_x509_cert` VALUES (1,'CN=test2,O=IGI,C=IT','test2 cert',1,1,'-----BEGIN CERTIFICATE-----\nMIIDnjCCAoagAwIBAgIBCzANBgkqhkiG9w0BAQUFADAtMQswCQYDVQQGEwJJVDEM\nMAoGA1UECgwDSUdJMRAwDgYDVQQDDAdUZXN0IENBMB4XDTEyMDkyNjE1MzkzOFoX\nDTIyMDkyNDE1MzkzOFowKzELMAkGA1UEBhMCSVQxDDAKBgNVBAoTA0lHSTEOMAwG\nA1UEAxMFdGVzdDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEYYwo\neq5ucXGsIZqI5V30OmEZTLzz3TCtFSp+DWbFHAeiiZNNktK44udHV+kwTjSxHTUJ\nP9RIvCAIMggtvibesXrTp1UHAF6p1d2GaUmU+mc/y7zRESxuSXx+SqWCwBOVxOzj\nDhm9oWlg3TSNctV2qv0HR2t8hsnfsQShULwaUJmQZ1fBfDN6HL5ITe77ptXB84Hz\nMAmNv0ckoQmVGtlVhoasppTgMhoWvBSguT1FGw7A/a8ZzQZV8rC1BP/1LZtRitHm\nstErUyULBjQekpu3VhGFJLCFD3fcyjoBKsIxCm62NhzHLOF8RE+kW05MRGrUu007\nCuV3yCDZOixIAxKVAgMBAAGjgcowgccwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU\nXNkN/hv+aBr6hqNqYm1VaiEAvpcwDgYDVR0PAQH/BAQDAgXgMD4GA1UdJQQ3MDUG\nCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBBggrBgEF\nBQcDBDAfBgNVHSMEGDAWgBSRdzZ7LrRp8yfqt/YIi0ojohFJxjAnBgNVHREEIDAe\ngRxhbmRyZWEuY2VjY2FudGlAY25hZi5pbmZuLml0MA0GCSqGSIb3DQEBBQUAA4IB\nAQBOavmIRcBqWnGFmcEp8zJ+cR3k02UcM0Xg7/vAnxJ7JziniMJLyBrxAaW1j2f6\nqJrap9rK+aukhovInTSrdWKM6y5ceY0w7u4nsu8Y3lRf3g9e766iuY3NfflDZE2N\ns3JuHZljwx7NGEOrr/Wi5Q1g9JVJcK+A+aB3vPLoS/Uc95ibdqJKHVG0rcKLnqR6\nAVvzyPxJtpwk4yy4V+juBZib2SImBWJ7C5VHuHLMAOxtNV84CIXpdvLKfA1Bjf3W\nUMrcvhN03L72j9IR0WEZlFMfYbxv1gbNbo+fhVo3itHI3lTl0K0BD5bOP0LqtARL\ngZ9zFVlxWHcKUqQ41ZQXNg7U\n-----END CERTIFICATE-----','CN=Test CA,O=IGI,C=IT','2024-03-27 18:43:07','2024-03-27 18:43:07',NULL),(2,'CN=test0,O=IGI,C=IT','Test0',0,2,'-----BEGIN CERTIFICATE-----\nMIIDnjCCAoagAwIBAgIBCDANBgkqhkiG9w0BAQUFADAtMQswCQYDVQQGEwJJVDEM\nMAoGA1UECgwDSUdJMRAwDgYDVQQDDAdUZXN0IENBMB4XDTIyMTAwMTEzMTYzMloX\nDTMyMDkyODEzMTYzMlowKzELMAkGA1UEBhMCSVQxDDAKBgNVBAoMA0lHSTEOMAwG\nA1UEAwwFdGVzdDAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCoyIIN\nH7YaqKMIW4kI41E0gDqtaQKYKdCv1cDL9/ibg0QLO/hyak9u9zQnp7XlK6e9NwnM\nT3efn3o5xWyA4nY8UWvXQRxQjuQO1hxManxFxzVHYYkd5p4JDy3lrDSPgw8yojPZ\niAwVcDWZfVzXEC/EEAtbheSZcydQaEWSCLmY9rrriyvxrIlYaiAzXFhV0hRsxPy9\nFk85nq1JVzeAN7jVt3JVrDgHd17IQIySXz3JU7UYChGcW3CO4LNe4p39cbjW6wbi\nUqo+7caSJsOxwoS2RcHAahgd+BGegMkr48krmojuDcYrrkAL4AK0Uh5xXdWul1kG\n0SFf0WyN23CjuFEXAgMBAAGjgcowgccwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU\naognKvxLiK8OSA1F/9x+7qCDtuUwDgYDVR0PAQH/BAQDAgXgMD4GA1UdJQQ3MDUG\nCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBBggrBgEF\nBQcDBDAfBgNVHSMEGDAWgBRQm290AeMaA1er2dV9FWRMJfP49DAnBgNVHREEIDAe\ngRxhbmRyZWEuY2VjY2FudGlAY25hZi5pbmZuLml0MA0GCSqGSIb3DQEBBQUAA4IB\nAQBHBk5Pcr3EXJZedPeEQuXCdPMDAJpAcZTCTINfGRoQXDYQk6ce8bH8jHPmao6d\nqV/f/14y2Jmkz+aiFQhSSyDLk4ywTgGHT+kpWEsYGbN4AdcMlH1L9uaG7YbuAZzH\n6bkd8HLsTiwslXYHjyldbQL9ZU6DrGAdt/IuAfFrQjWWuJ21SfBlnp4OkWQK5wTk\nsTvfeZX6VwinpXzF6xIrtAfJ7OYRDuN7UIrwBl9G0hoQPuXFJeVRAzYRwDVbejSo\n/8OWCj17EXDO+tG6Md+JYIsqJ4wrytd4YeuYDVDzbVV8DHfMrk2+PeJ0nSOSyYV+\ndoaFzJ6837vw8+5gxDTHT/un\n-----END CERTIFICATE-----','CN=Test CA,O=IGI,C=IT','2024-03-27 18:44:27','2024-03-27 18:44:27',NULL); +/*!40000 ALTER TABLE `iam_x509_cert` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `iam_x509_proxy` +-- + +DROP TABLE IF EXISTS `iam_x509_proxy`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `iam_x509_proxy` ( + `ID` bigint(20) NOT NULL AUTO_INCREMENT, + `CHAIN` longtext NOT NULL, + `exp_time` datetime NOT NULL, + PRIMARY KEY (`ID`), + KEY `IDX_IAM_X509_PXY_EXP_T` (`exp_time`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `iam_x509_proxy` +-- + +LOCK TABLES `iam_x509_proxy` WRITE; +/*!40000 ALTER TABLE `iam_x509_proxy` DISABLE KEYS */; +/*!40000 ALTER TABLE `iam_x509_proxy` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pairwise_identifier` +-- + +DROP TABLE IF EXISTS `pairwise_identifier`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `pairwise_identifier` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `identifier` varchar(256) DEFAULT NULL, + `sub` varchar(256) DEFAULT NULL, + `sector_identifier` varchar(2048) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `pairwise_identifier` +-- + +LOCK TABLES `pairwise_identifier` WRITE; +/*!40000 ALTER TABLE `pairwise_identifier` DISABLE KEYS */; +/*!40000 ALTER TABLE `pairwise_identifier` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permission` +-- + +DROP TABLE IF EXISTS `permission`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `permission` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `resource_set_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permission` +-- + +LOCK TABLES `permission` WRITE; +/*!40000 ALTER TABLE `permission` DISABLE KEYS */; +/*!40000 ALTER TABLE `permission` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permission_scope` +-- + +DROP TABLE IF EXISTS `permission_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `permission_scope` ( + `owner_id` bigint(20) NOT NULL, + `scope` varchar(256) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permission_scope` +-- + +LOCK TABLES `permission_scope` WRITE; +/*!40000 ALTER TABLE `permission_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `permission_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permission_ticket` +-- + +DROP TABLE IF EXISTS `permission_ticket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `permission_ticket` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `ticket` varchar(256) NOT NULL, + `permission_id` bigint(20) NOT NULL, + `expiration` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permission_ticket` +-- + +LOCK TABLES `permission_ticket` WRITE; +/*!40000 ALTER TABLE `permission_ticket` DISABLE KEYS */; +/*!40000 ALTER TABLE `permission_ticket` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `policy` +-- + +DROP TABLE IF EXISTS `policy`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `policy` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(1024) DEFAULT NULL, + `resource_set_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `policy` +-- + +LOCK TABLES `policy` WRITE; +/*!40000 ALTER TABLE `policy` DISABLE KEYS */; +/*!40000 ALTER TABLE `policy` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `policy_scope` +-- + +DROP TABLE IF EXISTS `policy_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `policy_scope` ( + `owner_id` bigint(20) NOT NULL, + `scope` varchar(256) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `policy_scope` +-- + +LOCK TABLES `policy_scope` WRITE; +/*!40000 ALTER TABLE `policy_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `policy_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `refresh_token` +-- + +DROP TABLE IF EXISTS `refresh_token`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `refresh_token` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `token_value` varchar(4096) DEFAULT NULL, + `expiration` timestamp NULL DEFAULT NULL, + `auth_holder_id` bigint(20) DEFAULT NULL, + `client_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `rf_ahi_idx` (`auth_holder_id`), + KEY `FK_refresh_token_client_id` (`client_id`), + CONSTRAINT `FK_refresh_token_auth_holder_id` FOREIGN KEY (`auth_holder_id`) REFERENCES `authentication_holder` (`id`) ON DELETE CASCADE, + CONSTRAINT `FK_refresh_token_client_id` FOREIGN KEY (`client_id`) REFERENCES `client_details` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `refresh_token` +-- + +LOCK TABLES `refresh_token` WRITE; +/*!40000 ALTER TABLE `refresh_token` DISABLE KEYS */; +/*!40000 ALTER TABLE `refresh_token` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `resource_set` +-- + +DROP TABLE IF EXISTS `resource_set`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `resource_set` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(1024) NOT NULL, + `uri` varchar(1024) DEFAULT NULL, + `icon_uri` varchar(1024) DEFAULT NULL, + `rs_type` varchar(256) DEFAULT NULL, + `owner` varchar(256) NOT NULL, + `client_id` varchar(256) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `resource_set` +-- + +LOCK TABLES `resource_set` WRITE; +/*!40000 ALTER TABLE `resource_set` DISABLE KEYS */; +/*!40000 ALTER TABLE `resource_set` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `resource_set_scope` +-- + +DROP TABLE IF EXISTS `resource_set_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `resource_set_scope` ( + `owner_id` bigint(20) NOT NULL, + `scope` varchar(256) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `resource_set_scope` +-- + +LOCK TABLES `resource_set_scope` WRITE; +/*!40000 ALTER TABLE `resource_set_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `resource_set_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `saved_registered_client` +-- + +DROP TABLE IF EXISTS `saved_registered_client`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `saved_registered_client` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `issuer` varchar(1024) DEFAULT NULL, + `registered_client` varchar(8192) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `saved_registered_client` +-- + +LOCK TABLES `saved_registered_client` WRITE; +/*!40000 ALTER TABLE `saved_registered_client` DISABLE KEYS */; +/*!40000 ALTER TABLE `saved_registered_client` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `saved_user_auth` +-- + +DROP TABLE IF EXISTS `saved_user_auth`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `saved_user_auth` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(1024) DEFAULT NULL, + `authenticated` tinyint(1) DEFAULT NULL, + `source_class` varchar(2048) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `saved_user_auth` +-- + +LOCK TABLES `saved_user_auth` WRITE; +/*!40000 ALTER TABLE `saved_user_auth` DISABLE KEYS */; +/*!40000 ALTER TABLE `saved_user_auth` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `saved_user_auth_authority` +-- + +DROP TABLE IF EXISTS `saved_user_auth_authority`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `saved_user_auth_authority` ( + `owner_id` bigint(20) DEFAULT NULL, + `authority` varchar(256) DEFAULT NULL, + KEY `suaa_oi_idx` (`owner_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `saved_user_auth_authority` +-- + +LOCK TABLES `saved_user_auth_authority` WRITE; +/*!40000 ALTER TABLE `saved_user_auth_authority` DISABLE KEYS */; +/*!40000 ALTER TABLE `saved_user_auth_authority` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `saved_user_auth_info` +-- + +DROP TABLE IF EXISTS `saved_user_auth_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `saved_user_auth_info` ( + `owner_id` bigint(20) DEFAULT NULL, + `info_key` varchar(256) DEFAULT NULL, + `info_val` varchar(256) DEFAULT NULL, + UNIQUE KEY `owner_id` (`owner_id`,`info_key`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `saved_user_auth_info` +-- + +LOCK TABLES `saved_user_auth_info` WRITE; +/*!40000 ALTER TABLE `saved_user_auth_info` DISABLE KEYS */; +/*!40000 ALTER TABLE `saved_user_auth_info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `schema_version` +-- + +DROP TABLE IF EXISTS `schema_version`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `schema_version` ( + `installed_rank` int(11) NOT NULL, + `version` varchar(50) DEFAULT NULL, + `description` varchar(200) NOT NULL, + `type` varchar(20) NOT NULL, + `script` varchar(1000) NOT NULL, + `checksum` int(11) DEFAULT NULL, + `installed_by` varchar(100) NOT NULL, + `installed_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `execution_time` int(11) NOT NULL, + `success` tinyint(1) NOT NULL, + PRIMARY KEY (`installed_rank`), + KEY `schema_version_s_idx` (`success`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `schema_version` +-- + +LOCK TABLES `schema_version` WRITE; +/*!40000 ALTER TABLE `schema_version` DISABLE KEYS */; +INSERT INTO `schema_version` VALUES (1,'1',' init','SQL','V1___init.sql',-673105977,'iam','2024-03-27 17:42:53',2003,1),(2,'2',' iam tables','SQL','V2___iam_tables.sql',916872168,'iam','2024-03-27 17:42:54',1436,1),(3,'3','basic configuration','SQL','V3__basic_configuration.sql',-1952954691,'iam','2024-03-27 17:42:54',31,1),(4,'3.1',' duplicate email user','SQL','V3_1___duplicate_email_user.sql',-754234138,'iam','2024-03-27 17:42:54',14,1),(5,'4',' x509 updates','SQL','V4___x509_updates.sql',803590936,'iam','2024-03-27 17:42:54',84,1),(6,'5',' registration request','SQL','V5___registration_request.sql',844204664,'iam','2024-03-27 17:42:55',280,1),(7,'6',' remove wrong constraints','SQL','V6___remove_wrong_constraints.sql',2003434964,'iam','2024-03-27 17:42:55',40,1),(8,'7',' notification tables','SQL','V7___notification_tables.sql',-1136933843,'iam','2024-03-27 17:42:55',331,1),(9,'8',' mitre update','SQL','V8___mitre_update.sql',608617254,'iam','2024-03-27 17:42:55',69,1),(10,'9','mitre saved user authn changes','SQL','V9__mitre_saved_user_authn_changes.sql',302744444,'iam','2024-03-27 17:42:55',38,1),(11,'10','fix internal authz scopes','SQL','V10__fix_internal_authz_scopes.sql',-686432566,'iam','2024-03-27 17:42:55',2,1),(12,'10.1','Password Update','JDBC','db.migration.mysql.V10_1__Password_Update',NULL,'iam','2024-03-27 17:42:56',837,1),(13,'10.2',' CheckDuplicateEmails','JDBC','db.migration.mysql.V10_2___CheckDuplicateEmails',NULL,'iam','2024-03-27 17:42:56',7,1),(14,'11','fix base scim and reg scopes','SQL','V11__fix_base_scim_and_reg_scopes.sql',-2106952067,'iam','2024-03-27 17:42:56',1,1),(15,'11.1','no attr id saml account for admin user','SQL','V11_1__no_attr_id_saml_account_for_admin_user.sql',-448912898,'iam','2024-03-27 17:42:56',1,1),(16,'12','iam group nested groups','SQL','V12__iam_group_nested_groups.sql',-2140651111,'iam','2024-03-27 17:42:56',181,1),(17,'13','add attribute id to saml id table','SQL','V13__add_attribute_id_to_saml_id_table.sql',681840221,'iam','2024-03-27 17:42:57',292,1),(18,'14',' x509 certs table changes','SQL','V14___x509_certs_table_changes.sql',-310236366,'iam','2024-03-27 17:42:57',396,1),(19,'15','alter iam group','SQL','V15__alter_iam_group.sql',588116562,'iam','2024-03-27 17:42:57',96,1),(20,'16','add provisioned column to iam account','SQL','V16__add_provisioned_column_to_iam_account.sql',448586794,'iam','2024-03-27 17:42:57',395,1),(21,'17','add scope policy tables','SQL','V17__add_scope_policy_tables.sql',460278210,'iam','2024-03-27 17:42:58',416,1),(22,'18','mitre 1 3 x database changes','SQL','V18__mitre_1_3_x_database_changes.sql',449297336,'iam','2024-03-27 17:42:59',662,1),(23,'19','aup tables','SQL','V19__aup_tables.sql',567653912,'iam','2024-03-27 17:42:59',503,1),(24,'20','group membership request','SQL','V20__group_membership_request.sql',-924931434,'iam','2024-03-27 17:42:59',235,1),(25,'21',' device code default expiration','SQL','V21___device_code_default_expiration.sql',965164897,'iam','2024-03-27 17:42:59',1,1),(26,'22','add indexes for search queries','SQL','V22__add_indexes_for_search_queries.sql',-748445998,'iam','2024-03-27 17:43:00',212,1),(27,'23',' CreateGroupManagerAuthorities','JDBC','db.migration.mysql.V23___CreateGroupManagerAuthorities',NULL,'iam','2024-03-27 17:43:00',1,1),(28,'24',' set timestamp default','SQL','V24___set_timestamp_default.sql',234306337,'iam','2024-03-27 17:43:00',6,1),(29,'30',' default group support','SQL','V30___default_group_support.sql',-636476445,'iam','2024-03-27 17:43:01',1004,1),(30,'31',' address table fixes','SQL','V31___address_table_fixes.sql',323916075,'iam','2024-03-27 17:43:01',173,1),(31,'32',' proxy storage','SQL','V32___proxy_storage.sql',851904690,'iam','2024-03-27 17:43:01',259,1),(32,'33',' proxy api scopes','SQL','V33___proxy_api_scopes.sql',-394160567,'iam','2024-03-27 17:43:01',2,1),(33,'34',' req request labels','SQL','V34___req_request_labels.sql',-1247430935,'iam','2024-03-27 17:43:01',201,1),(34,'34.2',' RemoveOrphanTokens','JDBC','db.migration.mysql.V34_2___RemoveOrphanTokens',NULL,'iam','2024-03-27 17:43:01',5,1),(35,'35',' scope match policies','SQL','V35___scope_match_policies.sql',773238492,'iam','2024-03-27 17:43:02',257,1),(36,'40',' aup updates','SQL','V40___aup_updates.sql',-1574961084,'iam','2024-03-27 17:43:02',131,1),(37,'50',' token exchange policy','SQL','V50___token_exchange_policy.sql',708363568,'iam','2024-03-27 17:43:02',176,1),(38,'51',' fix scope match policies','SQL','V51___fix_scope_match_policies.sql',1742199118,'iam','2024-03-27 17:43:02',2,1),(39,'52','add eduperson system scopes','SQL','V52__add_eduperson_system_scopes.sql',-669332083,'iam','2024-03-27 17:43:02',1,1),(40,'53',' add end time to iam acccount','SQL','V53___add_end_time_to_iam_acccount.sql',795128555,'iam','2024-03-27 17:43:02',230,1),(41,'60',' fix certificate subject length','SQL','V60___fix_certificate_subject_length.sql',437826198,'iam','2024-03-27 17:43:02',222,1),(42,'61',' add dates for group membership','SQL','V61___add_dates_for_group_membership.sql',-1216009527,'iam','2024-03-27 17:43:03',138,1),(43,'62',' add dates to ssh keys table','SQL','V62___add_dates_to_ssh_keys_table.sql',345904759,'iam','2024-03-27 17:43:03',146,1),(44,'70',' totp mfa','SQL','V70___totp_mfa.sql',358166160,'iam','2024-03-27 17:43:03',268,1),(45,'71',' add pre authenticated authority','SQL','V71___add_pre_authenticated_authority.sql',234328656,'iam','2024-03-27 17:43:03',2,1),(46,'80',' account clients','SQL','V80___account_clients.sql',-2130998179,'iam','2024-03-27 17:43:03',269,1),(47,'81','add eduperson assurance scope','SQL','V81__add_eduperson_assurance_scope.sql',1118450873,'iam','2024-03-27 17:43:03',2,1),(48,'81.2',' RemoveOrphanTokens','JDBC','db.migration.mysql.V81_2___RemoveOrphanTokens',NULL,'iam','2024-03-27 17:43:03',1,1),(49,'90','fix eduperson entitlement scope','SQL','V90__fix_eduperson_entitlement_scope.sql',-543114581,'iam','2024-03-27 17:43:03',0,1),(50,'91','update client name','SQL','V91__update_client_name.sql',-113175668,'iam','2024-03-27 17:43:03',0,1),(51,'92','add iam api scopes','SQL','V92__add_iam_api_scopes.sql',1959900565,'iam','2024-03-27 17:43:03',1,1),(52,'93','add at hash','SQL','V93__add_at_hash.sql',-881840384,'iam','2024-03-27 17:43:04',244,1),(53,'94','alter x509 table','SQL','V94__alter_x509_table.sql',1887482211,'iam','2024-03-27 17:43:04',219,1),(54,'95','remove client response type','SQL','V95__remove_client_response_type.sql',-658578857,'iam','2024-03-27 17:43:04',3,1),(55,'96','add foreign keys','SQL','V96__add_foreign_keys.sql',-969456599,'iam','2024-03-27 17:43:07',2895,1),(56,'97','delete unique subject dn','SQL','V97__delete_unique_subject_dn.sql',1120054453,'iam','2024-03-27 17:43:07',51,1),(57,'98','fix rat hash value','SQL','V98__fix_rat_hash_value.sql',228664475,'iam','2024-03-27 17:43:07',0,1),(58,'99','clear client logo URI','SQL','V99__clear_client_logo_URI.sql',906005557,'iam','2024-03-27 17:43:07',0,1),(59,'100000',' test data','SQL','V100000___test_data.sql',-370556209,'iam','2024-03-27 17:43:07',108,1),(60,'100000.1',' CreateGroupManagerAuthorities','JDBC','db.migration.test.V100000_1___CreateGroupManagerAuthorities',NULL,'iam','2024-03-27 17:43:07',4,1),(61,'100000.3',' RemoveOrphanTokens','JDBC','db.migration.test.V100000_3___RemoveOrphanTokens',NULL,'iam','2024-03-27 17:43:07',2,1),(62,'100000.4',' remove data after orphan tokens test','SQL','V100000_4___remove_data_after_orphan_tokens_test.sql',-1771356196,'iam','2024-03-27 17:43:07',2,1),(63,'100000.6','add eduperson scopes to client','SQL','V100000_6__add_eduperson_scopes_to_client.sql',-1405718810,'iam','2024-03-27 17:43:07',0,1),(64,'100000.7','fix eduperson entitlement scope','SQL','V100000_7__fix_eduperson_entitlement_scope.sql',-880050935,'iam','2024-03-27 17:43:07',0,1); +/*!40000 ALTER TABLE `schema_version` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `system_scope` +-- + +DROP TABLE IF EXISTS `system_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `system_scope` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `scope` varchar(256) NOT NULL, + `description` varchar(4096) DEFAULT NULL, + `icon` varchar(256) DEFAULT NULL, + `restricted` tinyint(1) NOT NULL DEFAULT '0', + `default_scope` tinyint(1) NOT NULL DEFAULT '0', + `structured` tinyint(1) NOT NULL DEFAULT '0', + `structured_param_description` varchar(256) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `scope` (`scope`) +) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `system_scope` +-- + +LOCK TABLES `system_scope` WRITE; +/*!40000 ALTER TABLE `system_scope` DISABLE KEYS */; +INSERT INTO `system_scope` VALUES (1,'openid','log in using your identity','user',0,1,0,NULL),(2,'profile','basic profile information','list-alt',0,1,0,NULL),(3,'email','email address','envelope',0,1,0,NULL),(4,'address','physical address','home',0,1,0,NULL),(5,'phone','telephone number','bell',0,1,0,NULL),(6,'offline_access','offline access','time',0,0,0,NULL),(7,'scim:read','read access to SCIM user and groups',NULL,1,0,1,'read access to IAM SCIM APIs'),(8,'scim:write','write access to SCIM user and groups',NULL,1,0,1,'write access to IAM SCIM APIs'),(9,'registration:read','Grants read access to registration requests',NULL,1,0,1,'read access to IAM registration APIs'),(10,'registration:write','Grants write access to registration requests',NULL,1,0,1,'write access to IAM registration APIs'),(11,'scim','Authorizes access to IAM SCIM APIs',NULL,1,0,1,NULL),(12,'registration','Authorizes access to IAM registration APIs',NULL,1,0,1,NULL),(13,'proxy:generate','Authorizes access to IAM Proxy APIs',NULL,1,0,1,NULL),(16,'eduperson_scoped_affiliation','Access to EduPerson scoped affiliation information',NULL,0,0,0,NULL),(17,'eduperson_entitlement','Access to EduPerson entitlements information',NULL,0,0,0,NULL),(18,'ssh-keys','Authorizes access to SSH keys linked to IAM accounts via the IAM userinfo endpoint',NULL,1,0,1,NULL),(19,'eduperson_assurance','Access to EduPerson assurance information',NULL,0,0,0,NULL),(20,'entitlements','Access to entitlements information',NULL,0,0,0,NULL),(21,'iam:admin.read','Read access to IAM APIs',NULL,1,0,0,NULL),(22,'iam:admin.write','Write access to IAM APIs',NULL,1,0,0,NULL); +/*!40000 ALTER TABLE `system_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `token_scope` +-- + +DROP TABLE IF EXISTS `token_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `token_scope` ( + `owner_id` bigint(20) NOT NULL, + `scope` varchar(2048) NOT NULL, + KEY `ts_oi_idx` (`owner_id`), + CONSTRAINT `FK_token_scope_owner_id` FOREIGN KEY (`owner_id`) REFERENCES `access_token` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `token_scope` +-- + +LOCK TABLES `token_scope` WRITE; +/*!40000 ALTER TABLE `token_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `token_scope` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user_info` +-- + +DROP TABLE IF EXISTS `user_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `user_info` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `sub` varchar(256) DEFAULT NULL, + `preferred_username` varchar(256) DEFAULT NULL, + `name` varchar(256) DEFAULT NULL, + `given_name` varchar(256) DEFAULT NULL, + `family_name` varchar(256) DEFAULT NULL, + `middle_name` varchar(256) DEFAULT NULL, + `nickname` varchar(256) DEFAULT NULL, + `profile` varchar(256) DEFAULT NULL, + `picture` varchar(256) DEFAULT NULL, + `website` varchar(256) DEFAULT NULL, + `email` varchar(256) DEFAULT NULL, + `email_verified` tinyint(1) DEFAULT NULL, + `gender` varchar(256) DEFAULT NULL, + `zone_info` varchar(256) DEFAULT NULL, + `locale` varchar(256) DEFAULT NULL, + `phone_number` varchar(256) DEFAULT NULL, + `phone_number_verified` tinyint(1) DEFAULT NULL, + `address_id` varchar(256) DEFAULT NULL, + `updated_time` varchar(256) DEFAULT NULL, + `birthdate` varchar(256) DEFAULT NULL, + `src` varchar(4096) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user_info` +-- + +LOCK TABLES `user_info` WRITE; +/*!40000 ALTER TABLE `user_info` DISABLE KEYS */; +/*!40000 ALTER TABLE `user_info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `whitelisted_site` +-- + +DROP TABLE IF EXISTS `whitelisted_site`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `whitelisted_site` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `creator_user_id` varchar(256) DEFAULT NULL, + `client_id` varchar(256) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `whitelisted_site` +-- + +LOCK TABLES `whitelisted_site` WRITE; +/*!40000 ALTER TABLE `whitelisted_site` DISABLE KEYS */; +/*!40000 ALTER TABLE `whitelisted_site` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `whitelisted_site_scope` +-- + +DROP TABLE IF EXISTS `whitelisted_site_scope`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `whitelisted_site_scope` ( + `owner_id` bigint(20) DEFAULT NULL, + `scope` varchar(256) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `whitelisted_site_scope` +-- + +LOCK TABLES `whitelisted_site_scope` WRITE; +/*!40000 ALTER TABLE `whitelisted_site_scope` DISABLE KEYS */; +/*!40000 ALTER TABLE `whitelisted_site_scope` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2024-03-27 18:50:31 diff --git a/compose/voms-replica/assets/db-primary/replica-source.sql b/compose/voms-replica/assets/db-primary/replica-source.sql new file mode 100644 index 000000000..2bd114969 --- /dev/null +++ b/compose/voms-replica/assets/db-primary/replica-source.sql @@ -0,0 +1,2 @@ +CREATE USER 'replicator'@'%' IDENTIFIED BY 'pwd' REQUIRE SSL; +GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%'; \ No newline at end of file diff --git a/compose/voms-replica/assets/db-remote/replicate.sql b/compose/voms-replica/assets/db-remote/replicate.sql new file mode 100644 index 000000000..8154b5788 --- /dev/null +++ b/compose/voms-replica/assets/db-remote/replicate.sql @@ -0,0 +1,9 @@ +STOP REPLICA; +CHANGE REPLICATION SOURCE TO + SOURCE_HOST='db-replica.test.example', + SOURCE_USER='replicator', + SOURCE_PASSWORD='pwd', + SOURCE_SSL=1, + SOURCE_SSL_CA = '/etc/grid-security/certificates/igi-test-ca.pem', + SOURCE_SSL_VERIFY_SERVER_CERT=1; +START REPLICA; \ No newline at end of file diff --git a/compose/voms-replica/assets/db-replica/replica-source.sql b/compose/voms-replica/assets/db-replica/replica-source.sql new file mode 100644 index 000000000..2bd114969 --- /dev/null +++ b/compose/voms-replica/assets/db-replica/replica-source.sql @@ -0,0 +1,2 @@ +CREATE USER 'replicator'@'%' IDENTIFIED BY 'pwd' REQUIRE SSL; +GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%'; \ No newline at end of file diff --git a/compose/voms-replica/assets/db-replica/replicate.sql b/compose/voms-replica/assets/db-replica/replicate.sql new file mode 100644 index 000000000..ac312cdf8 --- /dev/null +++ b/compose/voms-replica/assets/db-replica/replicate.sql @@ -0,0 +1,9 @@ +STOP REPLICA; +CHANGE REPLICATION SOURCE TO + SOURCE_HOST='db-primary.test.example', + SOURCE_USER='replicator', + SOURCE_PASSWORD='pwd', + SOURCE_SSL=1, + SOURCE_SSL_CA = '/etc/grid-security/certificates/igi-test-ca.pem', + SOURCE_SSL_VERIFY_SERVER_CERT=1; +START REPLICA; \ No newline at end of file diff --git a/compose/voms-replica/assets/mysql-conf/primary.cnf b/compose/voms-replica/assets/mysql-conf/primary.cnf new file mode 100644 index 000000000..a4fd1991c --- /dev/null +++ b/compose/voms-replica/assets/mysql-conf/primary.cnf @@ -0,0 +1,11 @@ +[mysqld] +server-id = 1 +log_bin = mysql-bin +binlog_do_db = iam + +general_log = 1 +general_log_file = /var/log/mysql/primary.log + +ssl_ca=/etc/grid-security/certificates/igi-test-ca.pem +ssl_cert=/certs/voms.test.example.cert.pem +ssl_key=/certs/voms.test.example.key.pem \ No newline at end of file diff --git a/compose/voms-replica/assets/mysql-conf/remote.cnf b/compose/voms-replica/assets/mysql-conf/remote.cnf new file mode 100644 index 000000000..c3c6865ed --- /dev/null +++ b/compose/voms-replica/assets/mysql-conf/remote.cnf @@ -0,0 +1,8 @@ +[mysqld] +server-id = 3 +log_bin = mysql-bin +read_only = 1 +relay_log = f7467c4a9aac-relay-bin + +general_log = 1 +general_log_file = /var/log/mysql/remote.log \ No newline at end of file diff --git a/compose/voms-replica/assets/mysql-conf/replica.cnf b/compose/voms-replica/assets/mysql-conf/replica.cnf new file mode 100644 index 000000000..4583d3dd6 --- /dev/null +++ b/compose/voms-replica/assets/mysql-conf/replica.cnf @@ -0,0 +1,31 @@ +[mysqld] +server-id = 2 +log_bin = mysql-bin +binlog_do_db = iam +read_only = 1 +relay_log = 7309661fdc26-relay-bin + +general_log = 1 +general_log_file = /var/log/mysql/replica.log + +replicate-do-table=iam.iam_account +replicate-do-table=iam.iam_account_attrs +replicate-do-table=iam.iam_account_authority +replicate-do-table=iam.iam_account_group +replicate-do-table=iam.iam_address +replicate-do-table=iam.iam_authority +replicate-do-table=iam.iam_aup +replicate-do-table=iam.iam_aup_signature +replicate-do-table=iam.iam_group +replicate-do-table=iam.iam_group_labels +replicate-do-table=iam.iam_oidc_id +replicate-do-table=iam.iam_reg_request +replicate-do-table=iam.iam_saml_id +replicate-do-table=iam.iam_ssh_key +replicate-do-table=iam.iam_user_info +replicate-do-table=iam.iam_x509_cert +replicate-do-table=iam.iam_x509_proxy + +ssl_ca=/etc/grid-security/certificates/igi-test-ca.pem +ssl_cert=/certs/voms.test.example.cert.pem +ssl_key=/certs/voms.test.example.key.pem \ No newline at end of file diff --git a/compose/voms-replica/assets/nginx/conf.d/nginx.conf b/compose/voms-replica/assets/nginx/conf.d/nginx.conf new file mode 100644 index 000000000..7786f3794 --- /dev/null +++ b/compose/voms-replica/assets/nginx/conf.d/nginx.conf @@ -0,0 +1,33 @@ + +error_log /var/log/nginx/error.log debug; + +load_module modules/ngx_http_voms_module.so; + +events { + worker_connections 1024; +} + +http { + + include mime.types; + default_type application/octet-stream; + + resolver 127.0.0.11 ipv6=off; + + log_format storm '$time_iso8601 [$request_id] $remote_addr - $remote_user "$request" <$upstream_response_time> ' + '$ssl_protocol/$ssl_cipher ' + '"$ssl_client_s_dn" ' + '[$voms_fqans] ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log storm; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + include /etc/nginx/conf.d/*.conf; + +} \ No newline at end of file diff --git a/compose/voms-replica/assets/nginx/conf.d/voms-primary.test.example.conf b/compose/voms-replica/assets/nginx/conf.d/voms-primary.test.example.conf new file mode 100644 index 000000000..bd58cae6a --- /dev/null +++ b/compose/voms-replica/assets/nginx/conf.d/voms-primary.test.example.conf @@ -0,0 +1,69 @@ +server { + + listen 443 ssl; + server_name voms-primary.test.example; + + ssl_protocols TLSv1.2; + + ssl_certificate /certs/voms.test.example.cert.pem; + ssl_certificate_key /certs/voms.test.example.key.pem; + ssl_client_certificate /igtf/ca-trust/extracted/pem/tls-ca-bundle-all.pem; + + ssl_verify_client on; + ssl_verify_depth 100; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + location /generate-ac { + default_type application/xml; + + proxy_pass http://vomsaa-primary.test.example:8080; + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + + # Simple tracing via request_id + proxy_set_header X-Request-Id $request_id; + + # TLS headers + proxy_set_header X-SSL-Client-Cert $ssl_client_cert; + proxy_set_header X-SSL-Client-I-Dn $ssl_client_i_dn; + proxy_set_header X-SSL-Client-S-Dn $ssl_client_s_dn; + proxy_set_header X-SSL-Client-Serial $ssl_client_serial; + proxy_set_header X-SSL-Client-V-Start $ssl_client_v_start; + proxy_set_header X-SSL-Client-V-End $ssl_client_v_end; + proxy_set_header X-SSL-Client-Verify $ssl_client_verify; + proxy_set_header X-SSL-Protocol $ssl_protocol; + proxy_set_header X-SSL-Server-Name $ssl_server_name; + + # VOMS headers + proxy_set_header x-ssl_client_ee_cert $ssl_client_ee_cert; + proxy_set_header x-ssl_client_ee_s_dn $ssl_client_ee_s_dn; + proxy_set_header x-ssl_client_ee_i_dn $ssl_client_ee_i_dn; + proxy_set_header x-voms_fqans $voms_fqans; + proxy_set_header x-voms_user $voms_user; + proxy_set_header x-voms_user_ca $voms_user_ca; + proxy_set_header x-voms_vo $voms_vo; + proxy_set_header x-voms_not_before $voms_not_before; + proxy_set_header x-voms_not_after $voms_not_after; + proxy_set_header x-voms_generic_attributes $voms_generic_attributes; + proxy_set_header x-voms_serial $voms_serial; + + } + + location /actuator { + + proxy_pass http://vomsaa-primary.test.example:8080; + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + + # Simple tracing via request_id + proxy_set_header X-Request-Id $request_id; + + } +} diff --git a/compose/voms-replica/assets/nginx/conf.d/voms-remote.test.example.conf b/compose/voms-replica/assets/nginx/conf.d/voms-remote.test.example.conf new file mode 100644 index 000000000..c105db40d --- /dev/null +++ b/compose/voms-replica/assets/nginx/conf.d/voms-remote.test.example.conf @@ -0,0 +1,69 @@ +server { + + listen 443 ssl; + server_name voms-remote.test.example; + + ssl_protocols TLSv1.2; + + ssl_certificate /certs/voms.test.example.cert.pem; + ssl_certificate_key /certs/voms.test.example.key.pem; + ssl_client_certificate /igtf/ca-trust/extracted/pem/tls-ca-bundle-all.pem; + + ssl_verify_client on; + ssl_verify_depth 100; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + location /generate-ac { + default_type application/xml; + + proxy_pass http://vomsaa-remote.test.example:8080; + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + + # Simple tracing via request_id + proxy_set_header X-Request-Id $request_id; + + # TLS headers + proxy_set_header X-SSL-Client-Cert $ssl_client_cert; + proxy_set_header X-SSL-Client-I-Dn $ssl_client_i_dn; + proxy_set_header X-SSL-Client-S-Dn $ssl_client_s_dn; + proxy_set_header X-SSL-Client-Serial $ssl_client_serial; + proxy_set_header X-SSL-Client-V-Start $ssl_client_v_start; + proxy_set_header X-SSL-Client-V-End $ssl_client_v_end; + proxy_set_header X-SSL-Client-Verify $ssl_client_verify; + proxy_set_header X-SSL-Protocol $ssl_protocol; + proxy_set_header X-SSL-Server-Name $ssl_server_name; + + # VOMS headers + proxy_set_header x-ssl_client_ee_cert $ssl_client_ee_cert; + proxy_set_header x-ssl_client_ee_s_dn $ssl_client_ee_s_dn; + proxy_set_header x-ssl_client_ee_i_dn $ssl_client_ee_i_dn; + proxy_set_header x-voms_fqans $voms_fqans; + proxy_set_header x-voms_user $voms_user; + proxy_set_header x-voms_user_ca $voms_user_ca; + proxy_set_header x-voms_vo $voms_vo; + proxy_set_header x-voms_not_before $voms_not_before; + proxy_set_header x-voms_not_after $voms_not_after; + proxy_set_header x-voms_generic_attributes $voms_generic_attributes; + proxy_set_header x-voms_serial $voms_serial; + + } + + location /actuator { + + proxy_pass http://vomsaa-remote.test.example:8080; + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + + # Simple tracing via request_id + proxy_set_header X-Request-Id $request_id; + + } +} diff --git a/compose/voms-replica/assets/nginx/conf.d/voms-replica.test.example.conf b/compose/voms-replica/assets/nginx/conf.d/voms-replica.test.example.conf new file mode 100644 index 000000000..332f332ea --- /dev/null +++ b/compose/voms-replica/assets/nginx/conf.d/voms-replica.test.example.conf @@ -0,0 +1,69 @@ +server { + + listen 443 ssl; + server_name voms-replica.test.example; + + ssl_protocols TLSv1.2; + + ssl_certificate /certs/voms.test.example.cert.pem; + ssl_certificate_key /certs/voms.test.example.key.pem; + ssl_client_certificate /igtf/ca-trust/extracted/pem/tls-ca-bundle-all.pem; + + ssl_verify_client on; + ssl_verify_depth 100; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + location /generate-ac { + default_type application/xml; + + proxy_pass http://vomsaa-replica.test.example:8080; + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + + # Simple tracing via request_id + proxy_set_header X-Request-Id $request_id; + + # TLS headers + proxy_set_header X-SSL-Client-Cert $ssl_client_cert; + proxy_set_header X-SSL-Client-I-Dn $ssl_client_i_dn; + proxy_set_header X-SSL-Client-S-Dn $ssl_client_s_dn; + proxy_set_header X-SSL-Client-Serial $ssl_client_serial; + proxy_set_header X-SSL-Client-V-Start $ssl_client_v_start; + proxy_set_header X-SSL-Client-V-End $ssl_client_v_end; + proxy_set_header X-SSL-Client-Verify $ssl_client_verify; + proxy_set_header X-SSL-Protocol $ssl_protocol; + proxy_set_header X-SSL-Server-Name $ssl_server_name; + + # VOMS headers + proxy_set_header x-ssl_client_ee_cert $ssl_client_ee_cert; + proxy_set_header x-ssl_client_ee_s_dn $ssl_client_ee_s_dn; + proxy_set_header x-ssl_client_ee_i_dn $ssl_client_ee_i_dn; + proxy_set_header x-voms_fqans $voms_fqans; + proxy_set_header x-voms_user $voms_user; + proxy_set_header x-voms_user_ca $voms_user_ca; + proxy_set_header x-voms_vo $voms_vo; + proxy_set_header x-voms_not_before $voms_not_before; + proxy_set_header x-voms_not_after $voms_not_after; + proxy_set_header x-voms_generic_attributes $voms_generic_attributes; + proxy_set_header x-voms_serial $voms_serial; + + } + + location /actuator { + + proxy_pass http://vomsaa-replica.test.example:8080; + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + + # Simple tracing via request_id + proxy_set_header X-Request-Id $request_id; + + } +} diff --git a/compose/voms-replica/assets/nginx/error/voms-50x-error.xml b/compose/voms-replica/assets/nginx/error/voms-50x-error.xml new file mode 100644 index 000000000..69742553a --- /dev/null +++ b/compose/voms-replica/assets/nginx/error/voms-50x-error.xml @@ -0,0 +1,7 @@ + + + + 1006 + Internal server error: the VOMS server is not really working as it should... + + diff --git a/compose/voms-replica/assets/nginx/error/voms-cert-error.xml b/compose/voms-replica/assets/nginx/error/voms-cert-error.xml new file mode 100644 index 000000000..5df4532a8 --- /dev/null +++ b/compose/voms-replica/assets/nginx/error/voms-cert-error.xml @@ -0,0 +1,7 @@ + + + + 1005 + SSL certificate error: invalid or missing client certificate. + + diff --git a/compose/voms-replica/assets/vomsaa/application-mysql-test.yml b/compose/voms-replica/assets/vomsaa/application-mysql-test.yml new file mode 100644 index 000000000..d1e4931df --- /dev/null +++ b/compose/voms-replica/assets/vomsaa/application-mysql-test.yml @@ -0,0 +1,37 @@ +server: + address: 0.0.0.0 + port: 8080 + forward-headers-strategy: native + +spring: + main: + banner-mode: "off" + + jpa: + open-in-view: false + + datasource: + url: jdbc:mysql://${IAM_DB_HOST:db}:${IAM_DB_PORT:3306}/${IAM_DB_NAME:iam}?serverTimezone=UTC + username: ${IAM_DB_USERNAME:iam} + password: ${IAM_DB_PASSWORD:pwd} + max-active: ${IAM_DB_MAX_ACTIVE:100} + max-idle: ${IAM_DB_MAX_IDLE:5} + validation-query: ${IAM_DB_VALIDATION_QUERY:SELECT 1} + time-between-eviction-runs-millis: ${IAM_DB_TIME_BETWEEN_EVICTION_RUNS_MILLIS:5000} + min-evictable-idle-time-millis: ${IAM_DB_MIN_EVICTABLE_IDLE_TIME_MILLIS:60000} + + flyway: + enabled: false + +voms: + tls: + certificate-path: /etc/grid-security/voms/hostcert.pem + private-key-path: /etc/grid-security/voms/hostkey.pem + trust-anchors-dir: /etc/grid-security/certificates + trust-anchors-refresh-interval-secs: 14400 + aa: + host: ${VOMS_HOST:voms.test.example} + port: ${VOMS_PORT:server.port} + vo-name: indigo-dc + optional-group-label: voms.role + use-legacy-fqan-encoding: true diff --git a/compose/voms-replica/assets/vomsdir/indigo-dc/voms-primary.test.example.lsc b/compose/voms-replica/assets/vomsdir/indigo-dc/voms-primary.test.example.lsc new file mode 100644 index 000000000..ddd3bb92e --- /dev/null +++ b/compose/voms-replica/assets/vomsdir/indigo-dc/voms-primary.test.example.lsc @@ -0,0 +1,2 @@ +/C=IT/O=IGI/CN=*.test.example +/C=IT/O=IGI/CN=Test CA diff --git a/compose/voms-replica/assets/vomsdir/indigo-dc/voms-remote.test.example.lsc b/compose/voms-replica/assets/vomsdir/indigo-dc/voms-remote.test.example.lsc new file mode 100644 index 000000000..ddd3bb92e --- /dev/null +++ b/compose/voms-replica/assets/vomsdir/indigo-dc/voms-remote.test.example.lsc @@ -0,0 +1,2 @@ +/C=IT/O=IGI/CN=*.test.example +/C=IT/O=IGI/CN=Test CA diff --git a/compose/voms-replica/assets/vomsdir/indigo-dc/voms-replica.test.example.lsc b/compose/voms-replica/assets/vomsdir/indigo-dc/voms-replica.test.example.lsc new file mode 100644 index 000000000..ddd3bb92e --- /dev/null +++ b/compose/voms-replica/assets/vomsdir/indigo-dc/voms-replica.test.example.lsc @@ -0,0 +1,2 @@ +/C=IT/O=IGI/CN=*.test.example +/C=IT/O=IGI/CN=Test CA diff --git a/compose/voms-replica/assets/vomsdir/test.vo/vgrid02.cnaf.infn.it.lsc b/compose/voms-replica/assets/vomsdir/test.vo/vgrid02.cnaf.infn.it.lsc new file mode 100644 index 000000000..11316e3d6 --- /dev/null +++ b/compose/voms-replica/assets/vomsdir/test.vo/vgrid02.cnaf.infn.it.lsc @@ -0,0 +1,2 @@ +/C=IT/O=INFN/OU=Host/L=CNAF/CN=vgrid02.cnaf.infn.it +/C=IT/O=INFN/CN=INFN Certification Authority diff --git a/compose/voms-replica/assets/vomses/indigo-dc b/compose/voms-replica/assets/vomses/indigo-dc new file mode 100644 index 000000000..bff3197ee --- /dev/null +++ b/compose/voms-replica/assets/vomses/indigo-dc @@ -0,0 +1,6 @@ +"voms-primary" "voms-primary.test.example" "443" "/C=IT/O=IGI/CN=*.test.example" "indigo-dc" +"voms-replica" "voms-replica.test.example" "443" "/C=IT/O=IGI/CN=*.test.example" "indigo-dc" +"voms-remote" "voms-remote.test.example" "443" "/C=IT/O=IGI/CN=*.test.example" "indigo-dc" +"indigo-dc" "voms-primary.test.example" "443" "/C=IT/O=IGI/CN=*.test.example" "indigo-dc" +"indigo-dc" "voms-replica.test.example" "443" "/C=IT/O=IGI/CN=*.test.example" "indigo-dc" +"indigo-dc" "voms-remote.test.example" "443" "/C=IT/O=IGI/CN=*.test.example" "indigo-dc" \ No newline at end of file diff --git a/compose/voms-replica/assets/vomses/test.vo b/compose/voms-replica/assets/vomses/test.vo new file mode 100644 index 000000000..dc8876d8d --- /dev/null +++ b/compose/voms-replica/assets/vomses/test.vo @@ -0,0 +1 @@ +"test.vo" "vgrid02.cnaf.infn.it" "15000" "/C=IT/O=INFN/OU=Host/L=CNAF/CN=vgrid02.cnaf.infn.it" "test.vo" \ No newline at end of file diff --git a/compose/voms-replica/docker-compose.yml b/compose/voms-replica/docker-compose.yml new file mode 100644 index 000000000..7dab7ee79 --- /dev/null +++ b/compose/voms-replica/docker-compose.yml @@ -0,0 +1,310 @@ +version: "3" + +volumes: + data-primary: + data-replica: + data-remote: + trustanchors: + cabundle: + +networks: + site1-lan: + name: site1-lan + site2-lan: + name: site2-lan + site-to-site-tunnel: + name: tunnel + wan: + name: wan + +services: + trust: + container_name: trust + image: ${TRUST_IMAGE}:${TRUST_IMAGE_TAG} + environment: + - FORCE_TRUST_ANCHORS_UPDATE=1 + volumes: + - trustanchors:/etc/grid-security/certificates + - cabundle:/etc/pki + + db-primary: + container_name: db-primary + image: ${DB_IMAGE}:${DB_IMAGE_TAG} + volumes: + - data-primary:/var/lib/mysql + - ./assets/db-logs:/var/log/mysql + - ./assets/db-primary:/docker-entrypoint-initdb.d + - ./assets/mysql-conf/primary.cnf:/etc/mysql/conf.d/primary.cnf + - ./assets/certs:/certs + - trustanchors:/etc/grid-security/certificates + env_file: + - env-files/db.env + ports: + - "3306:3306" + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"] + interval: 5s + timeout: 3s + retries: 10 + start_period: 0s + networks: + site1-lan: + aliases: + - db-primary.test.example + + db-replica: + container_name: db-replica + image: ${DB_IMAGE}:${DB_IMAGE_TAG} + depends_on: + db-primary: + condition: service_healthy + volumes: + - data-replica:/var/lib/mysql + - ./assets/db-logs:/var/log/mysql + - ./assets/db-replica:/docker-entrypoint-initdb.d + - ./assets/mysql-conf/replica.cnf:/etc/mysql/conf.d/replica.cnf + - ./assets/certs:/certs + - trustanchors:/etc/grid-security/certificates + env_file: + - env-files/db.env + environment: + - REPORT_HOST=db-replica.test.example + ports: + - "3307:3306" + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"] + interval: 5s + timeout: 3s + retries: 10 + start_period: 0s + networks: + site1-lan: + aliases: + - db-replica.test.example + site-to-site-tunnel: + aliases: + - db-replica.test.example + + db-remote: + container_name: db-remote + image: ${DB_IMAGE}:${DB_IMAGE_TAG} + depends_on: + db-replica: + condition: service_healthy + volumes: + - data-remote:/var/lib/mysql + - ./assets/db-logs:/var/log/mysql + - ./assets/db-remote:/docker-entrypoint-initdb.d + - ./assets/mysql-conf/remote.cnf:/etc/mysql/conf.d/remote.cnf + - ./assets/certs:/certs + - trustanchors:/etc/grid-security/certificates + env_file: + - env-files/db.env + environment: + - REPORT_HOST=db-remote.test.example + ports: + - "3308:3306" + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"] + interval: 5s + timeout: 3s + retries: 10 + start_period: 0s + networks: + site2-lan: + aliases: + - db-remote.test.example + site-to-site-tunnel: + aliases: + - db-remote.test.example + + vomsaa-primary: + container_name: vomsaa-primary + image: ${VOMS_AA_IMAGE}:${VOMS_AA_IMAGE_TAG} + env_file: + - env-files/voms.env + environment: + - IAM_DB_HOST=db-primary.test.example + - VOMS_HOST=voms-primary.test.example + - VOMS_PORT=443 + ports: + - "1044:1044" + depends_on: + db-primary: + condition: service_healthy + volumes: + - ./assets/vomsaa:/workspace/config:ro + - ./assets/certs/voms.test.example.cert.pem:/etc/grid-security/voms/hostcert.pem:ro + - ./assets/certs/voms.test.example.key.pem:/etc/grid-security/voms/hostkey.pem:ro + - trustanchors:/etc/grid-security/certificates + networks: + site1-lan: + aliases: + - vomsaa-primary.test.example + + vomsaa-replica: + container_name: vomsaa-replica + image: ${VOMS_AA_IMAGE}:${VOMS_AA_IMAGE_TAG} + env_file: + - env-files/voms.env + environment: + - IAM_DB_HOST=db-replica.test.example + - VOMS_HOST=voms-replica.test.example + - VOMS_PORT=443 + ports: + - "1045:1044" + depends_on: + db-replica: + condition: service_healthy + volumes: + - ./assets/vomsaa:/workspace/config:ro + - ./assets/certs/voms.test.example.cert.pem:/etc/grid-security/voms/hostcert.pem:ro + - ./assets/certs/voms.test.example.key.pem:/etc/grid-security/voms/hostkey.pem:ro + - trustanchors:/etc/grid-security/certificates + networks: + site1-lan: + aliases: + - vomsaa-replica.test.example + + vomsaa-remote: + container_name: vomsaa-remote + image: ${VOMS_AA_IMAGE}:${VOMS_AA_IMAGE_TAG} + env_file: + - env-files/voms.env + environment: + - IAM_DB_HOST=db-remote.test.example + - VOMS_HOST=voms-remote.test.example + - VOMS_PORT=443 + ports: + - "1046:1044" + depends_on: + db-remote: + condition: service_healthy + volumes: + - ./assets/vomsaa:/workspace/config:ro + - ./assets/certs/voms.test.example.cert.pem:/etc/grid-security/voms/hostcert.pem:ro + - ./assets/certs/voms.test.example.key.pem:/etc/grid-security/voms/hostkey.pem:ro + - trustanchors:/etc/grid-security/certificates + networks: + site2-lan: + aliases: + - vomsaa-remote.test.example + + ngx-primary: + container_name: ngx-primary + image: ${NGINX_IMAGE}:${NGINX_IMAGE_TAG} + depends_on: + vomsaa-primary: + condition: service_started + trust: + condition: service_completed_successfully + environment: + TZ: Europe/Rome + X509_VOMS_DIR: /vomsdir + ports: + - "443:443" + volumes: + - cabundle:/igtf + - trustanchors:/etc/grid-security/certificates + - ./assets/certs:/certs + - ./assets/nginx/conf.d/nginx.conf:/etc/nginx/nginx.conf:ro + - ./assets/nginx/conf.d/voms-primary.test.example.conf:/etc/nginx/conf.d/voms-primary.test.example.conf:ro + networks: + site1-lan: + wan: + aliases: + - voms-primary.test.example + + ngx-replica: + container_name: ngx-replica + image: ${NGINX_IMAGE}:${NGINX_IMAGE_TAG} + depends_on: + vomsaa-replica: + condition: service_started + trust: + condition: service_completed_successfully + environment: + TZ: Europe/Rome + X509_VOMS_DIR: /vomsdir + ports: + - "444:443" + volumes: + - cabundle:/igtf + - trustanchors:/etc/grid-security/certificates + - ./assets/certs:/certs + - ./assets/vomsdir:/vomsdir + - ./assets/nginx/conf.d/nginx.conf:/etc/nginx/nginx.conf:ro + - ./assets/nginx/conf.d/voms-replica.test.example.conf:/etc/nginx/conf.d/voms-replica.test.example.conf:ro + networks: + site1-lan: + wan: + aliases: + - voms-replica.test.example + + ngx-remote: + container_name: ngx-remote + image: ${NGINX_IMAGE}:${NGINX_IMAGE_TAG} + depends_on: + vomsaa-remote: + condition: service_started + trust: + condition: service_completed_successfully + environment: + TZ: Europe/Rome + X509_VOMS_DIR: /vomsdir + ports: + - "445:443" + volumes: + - cabundle:/igtf + - trustanchors:/etc/grid-security/certificates + - ./assets/certs:/certs + - ./assets/vomsdir:/vomsdir + - ./assets/nginx/conf.d/nginx.conf:/etc/nginx/nginx.conf:ro + - ./assets/nginx/conf.d/voms-remote.test.example.conf:/etc/nginx/conf.d/voms-remote.test.example.conf:ro + networks: + site2-lan: + wan: + aliases: + - voms-remote.test.example + + client: + container_name: client + image: ${GRID_CLIENTS_IMAGE}:${GRID_CLIENTS_IMAGE_TAG} + environment: + TZ: Europe/Rome + depends_on: + trust: + condition: service_completed_successfully + volumes: + - cabundle:/etc/pki + - trustanchors:/etc/grid-security/certificates + - ./assets/vomsdir:/etc/grid-security/vomsdir + - ./assets/vomses:/etc/vomses + entrypoint: sleep infinity + networks: + wan: + + testsuite: + image: italiangrid/voms-testsuite:latest + init: true + depends_on: + trust: + condition: service_completed_successfully + environment: + - TZ=Europe/Rome + - "ROBOT_OPTIONS=--variable vo1:indigo-dc + --variable vo1_host:voms-primary.test.example + --variable vo1_issuer:'/C=IT/O=IGI/CN=*.test.example' + --variable vo1_legacy_fqan_enabled:True + --variable vo2:test.vo --variable vo1_host:voms-dev.cloud.cnaf.infn.it + --variable vo2_issuer:'/DC=org/DC=terena/DC=tcs/C=IT/ST=Roma/O=Istituto Nazionale di Fisica Nucleare/CN=voms-dev.cloud.cnaf.infn.it' + --variable vo2_legacy_fqan_enabled:True" + volumes: + - trustanchors:/etc/grid-security/certificates + - ./assets/vomses:/etc/vomses + - ./assets/vomsdir:/etc/grid-security/vomsdir + - ./voms-testsuite:/home/test/voms-testsuite + working_dir: /home/test/voms-testsuite + command: ["sleep", "infinity"] + networks: + wan: \ No newline at end of file diff --git a/compose/voms-replica/env-files/db.env b/compose/voms-replica/env-files/db.env new file mode 100644 index 000000000..9c8793b8d --- /dev/null +++ b/compose/voms-replica/env-files/db.env @@ -0,0 +1,6 @@ +TZ=Europe/Rome +MYSQL_ROOT_PASSWORD=pwd +MYSQL_USER=iam +MYSQL_PASSWORD=pwd +MYSQL_DATABASE=iam +IAM_DB_HOST=db \ No newline at end of file diff --git a/compose/voms-replica/env-files/voms.env b/compose/voms-replica/env-files/voms.env new file mode 100644 index 000000000..0b0cc13a2 --- /dev/null +++ b/compose/voms-replica/env-files/voms.env @@ -0,0 +1,3 @@ +TZ=Europe/Rome +JAVA_DEBUG_OPTS=-Djava.security.egd=file:/dev/./urandom -agentlib:jdwp=server=y,transport=dt_socket,suspend=n,address=1044 +JAVA_OPTS=-Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=mysql-test \ No newline at end of file diff --git a/compose/voms-replica/voms-testsuite b/compose/voms-replica/voms-testsuite new file mode 160000 index 000000000..6c0055e72 --- /dev/null +++ b/compose/voms-replica/voms-testsuite @@ -0,0 +1 @@ +Subproject commit 6c0055e725dc5027179a8e7dbed1d01b132cdfd8 diff --git a/iam-common/pom.xml b/iam-common/pom.xml index b7e664da1..0e8aeafdc 100644 --- a/iam-common/pom.xml +++ b/iam-common/pom.xml @@ -5,7 +5,7 @@ it.infn.mw.iam-parent iam-parent - 1.9.0 + 1.10.0 it.infn.mw.iam-common diff --git a/iam-login-service/pom.xml b/iam-login-service/pom.xml index 37f7043c2..4e45ea08c 100644 --- a/iam-login-service/pom.xml +++ b/iam-login-service/pom.xml @@ -22,7 +22,7 @@ it.infn.mw.iam-parent iam-parent - 1.9.0 + 1.10.0 it.infn.mw.iam-login-service diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/DefaultPasswordResetService.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/DefaultPasswordResetService.java index 161e66458..fb28b793a 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/DefaultPasswordResetService.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/DefaultPasswordResetService.java @@ -54,7 +54,7 @@ public DefaultPasswordResetService(IamAccountRepository accountRepository, PasswordEncoder passwordEncoder) { this.accountRepository = accountRepository; - this.notificationFactory= notificationFactory; + this.notificationFactory = notificationFactory; this.tokenGenerator = tokenGenerator; this.passwordEncoder = passwordEncoder; } @@ -67,8 +67,8 @@ public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { public void validateResetToken(String resetToken) { IamAccount account = accountRepository.findByResetKey(resetToken) - .orElseThrow(() -> new InvalidPasswordResetTokenError( - String.format("No account found for reset_key [%s]", resetToken))); + .orElseThrow(() -> new InvalidPasswordResetTokenError( + String.format("No account found for reset_key [%s]", resetToken))); if (!accountActiveAndEmailVerified(account)) { throw new InvalidPasswordResetTokenError( @@ -80,40 +80,38 @@ public void validateResetToken(String resetToken) { public void resetPassword(String resetToken, String password) { validateResetToken(resetToken); - // FIXME: we perform the lookup twice. if validateResetToken + // FIXME: we perform the lookup twice. if validateResetToken // was modified to return the IamAccount we save one call to the DB IamAccount account = accountRepository.findByResetKey(resetToken) - .orElseThrow(() -> new InvalidPasswordResetTokenError( - String.format("No account found for reset_key [%s]", resetToken))); - - eventPublisher.publishEvent(new PasswordResetEvent(this, account, - String.format("User %s reset its password", account.getUsername()))); + .orElseThrow(() -> new InvalidPasswordResetTokenError( + String.format("No account found for reset_key [%s]", resetToken))); account.setPassword(passwordEncoder.encode(password)); account.setResetKey(null); accountRepository.save(account); - } + eventPublisher.publishEvent(new PasswordResetEvent(this, account, + String.format("User %s reset its password", account.getUsername()))); + } @Override public void createPasswordResetToken(String email) { - Optional accountByMail = accountRepository.findByEmail(email); - - accountByMail.ifPresent(a -> { - if (accountActiveAndEmailVerified(a)) { - String resetKey = tokenGenerator.generateToken(); - a.setResetKey(resetKey); - accountRepository.save(a); - notificationFactory.createResetPasswordMessage(a); - } - }); - - if (!accountByMail.isPresent()){ - logger.warn("No account found linked to email: {}", email); + Optional accountByMail = accountRepository.findByEmail(email); + + accountByMail.ifPresent(a -> { + if (accountActiveAndEmailVerified(a)) { + String resetKey = tokenGenerator.generateToken(); + a.setResetKey(resetKey); + accountRepository.save(a); + notificationFactory.createResetPasswordMessage(a); } - } + }); + if (!accountByMail.isPresent()) { + logger.warn("No account found linked to email: {}", email); + } + } private boolean accountActiveAndEmailVerified(IamAccount account) { return account.isActive() && (account.getUserInfo().getEmailVerified() != null @@ -125,7 +123,7 @@ public void updatePassword(String username, String oldPassword, String newPasswo throws UserNotActiveOrNotVerified, BadUserPasswordError { IamAccount account = accountRepository.findByUsername(username) - .orElseThrow(() -> new UserNotFoundError("No user found linked to username " + username)); + .orElseThrow(() -> new UserNotFoundError("No user found linked to username " + username)); if (!accountActiveAndEmailVerified(account)) { throw new UserNotActiveOrNotVerified("Account is not active or email is not verified"); diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/PasswordDTO.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/PasswordDTO.java index 53944e479..3921c7cac 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/PasswordDTO.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/PasswordDTO.java @@ -15,17 +15,19 @@ */ package it.infn.mw.iam.api.account.password_reset; -import javax.validation.constraints.NotEmpty; +import static it.infn.mw.iam.util.RegexUtil.PASSWORD_REGEX; +import static it.infn.mw.iam.util.RegexUtil.PASSWORD_REGEX_MESSAGE_ERROR; -import org.hibernate.validator.constraints.Length; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; public class PasswordDTO { @NotEmpty private String currentPassword; - + @NotEmpty(message = "The password cannot be empty") - @Length(min = 5, message = "The password must be at least 5 characters") + @Pattern(regexp = PASSWORD_REGEX, message = PASSWORD_REGEX_MESSAGE_ERROR) private String updatedPassword; public String getCurrentPassword() { diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/PasswordResetController.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/PasswordResetController.java index 029e9d186..d73021f8d 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/PasswordResetController.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/PasswordResetController.java @@ -27,14 +27,17 @@ import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.util.HtmlUtils; import it.infn.mw.iam.api.account.password_reset.error.InvalidEmailAddressError; +import it.infn.mw.iam.api.account.password_reset.error.InvalidPasswordError; import it.infn.mw.iam.api.account.password_reset.error.InvalidPasswordResetTokenError; +import it.infn.mw.iam.api.scim.controller.utils.ValidationErrorMessageHelper; @Controller @RequestMapping(PasswordResetController.BASE_RESOURCE) @@ -50,7 +53,7 @@ public class PasswordResetController { private PasswordResetService service; private String nullSafeValidationErrorMessage(BindingResult validationResult) { - + FieldError result = validationResult.getFieldError(EMAIL_FIELD); if (result == null) { return EMAIL_VALIDATION_ERROR_MSG; @@ -59,7 +62,6 @@ private String nullSafeValidationErrorMessage(BindingResult validationResult) { } } - @RequestMapping(value = "/token", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE) @ResponseBody @@ -77,7 +79,7 @@ public void createPasswordResetToken(@Valid EmailDTO emailDTO, BindingResult val @RequestMapping(value = "/token/{token}", method = RequestMethod.HEAD) @ResponseBody public String validateResetToken(@PathVariable("token") String token) { - service.validateResetToken(token); + service.validateResetToken(sanitizeToken(token)); return "ok"; } @@ -85,26 +87,29 @@ public String validateResetToken(@PathVariable("token") String token) { public String resetPasswordPage(Model model, @PathVariable("token") String token) { String message = null; + String sanitizedToken = sanitizeToken(token); try { - service.validateResetToken(token); - + service.validateResetToken(sanitizedToken); + model.addAttribute("resetKey", sanitizedToken); } catch (InvalidPasswordResetTokenError e) { message = e.getMessage(); + model.addAttribute("errorMessage", message); } - model.addAttribute("statusMessage", message); - model.addAttribute("resetKey", token); - return "iam/resetPassword"; } @RequestMapping(value = {"", "/"}, method = RequestMethod.POST) - @ResponseBody - public void resetPassword(@RequestParam(required = true, name = "token") String token, - @RequestParam(required = true, name = "password") String password) { + @ResponseStatus(value = HttpStatus.CREATED) + public void resetPassword(@RequestBody @Valid ResetPasswordDTO password, + BindingResult validationResult) { - service.resetPassword(token, password); + if (validationResult.hasErrors()) { + throw new InvalidPasswordError(ValidationErrorMessageHelper + .buildValidationErrorMessage("Invalid reset password", validationResult)); + } + service.resetPassword(password.getToken(), password.getUpdatedPassword()); } @ResponseStatus(value = HttpStatus.BAD_REQUEST) @@ -114,6 +119,13 @@ public String emailValidationError(HttpServletRequest req, Exception ex) { return ex.getMessage(); } + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ExceptionHandler(InvalidPasswordError.class) + @ResponseBody + public String passwordResetValidationError(HttpServletRequest req, Exception ex) { + return ex.getMessage(); + } + @ResponseStatus(value = HttpStatus.NOT_FOUND) @ExceptionHandler(InvalidPasswordResetTokenError.class) @ResponseBody @@ -121,4 +133,7 @@ public String invalidPasswordRequestTokenError(HttpServletRequest req, Exception return ex.getMessage(); } + private String sanitizeToken(String token) { + return HtmlUtils.htmlEscape(token); + } } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/ResetPasswordDTO.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/ResetPasswordDTO.java new file mode 100644 index 000000000..c7996925f --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/account/password_reset/ResetPasswordDTO.java @@ -0,0 +1,51 @@ + +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.api.account.password_reset; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +import static it.infn.mw.iam.util.RegexUtil.PASSWORD_REGEX; +import static it.infn.mw.iam.util.RegexUtil.PASSWORD_REGEX_MESSAGE_ERROR; + +public class ResetPasswordDTO { + + @NotEmpty + @Pattern(regexp = PASSWORD_REGEX, message = PASSWORD_REGEX_MESSAGE_ERROR) + private String updatedPassword; + + @NotEmpty + @Size(max = 36, min = 36) + private String token; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getUpdatedPassword() { + return updatedPassword; + } + + public void setUpdatedPassword(String updatedPassword) { + this.updatedPassword = updatedPassword; + } +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/AupSignatureController.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/AupSignatureController.java index 5882335e1..170ae7874 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/AupSignatureController.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/AupSignatureController.java @@ -26,6 +26,8 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -46,18 +48,21 @@ import it.infn.mw.iam.audit.events.aup.AupSignedEvent; import it.infn.mw.iam.audit.events.aup.AupSignedOnBehalfEvent; import it.infn.mw.iam.core.time.TimeProvider; +import it.infn.mw.iam.notification.NotificationFactory; import it.infn.mw.iam.persistence.model.IamAccount; import it.infn.mw.iam.persistence.model.IamAup; import it.infn.mw.iam.persistence.model.IamAupSignature; import it.infn.mw.iam.persistence.repository.IamAupRepository; import it.infn.mw.iam.persistence.repository.IamAupSignatureRepository; +@SuppressWarnings("deprecation") @RestController @Transactional public class AupSignatureController { private static final String ACCOUNT_NOT_FOUND_FOR_ID_MESSAGE = "Account not found for id: %s"; - private static final String ACCOUNT_NOT_FOUND_FOR_AUTHENTICATED_USER_MESSAGE = "Account not found for authenticated user"; + private static final String ACCOUNT_NOT_FOUND_FOR_AUTHENTICATED_USER_MESSAGE = + "Account not found for authenticated user"; private final AupSignatureConverter signatureConverter; private final AccountUtils accountUtils; @@ -65,16 +70,17 @@ public class AupSignatureController { private final IamAupRepository aupRepo; private final TimeProvider timeProvider; private final ApplicationEventPublisher eventPublisher; - + private final NotificationFactory notificationFactory; public AupSignatureController(AupSignatureConverter conv, AccountUtils utils, IamAupSignatureRepository signatureRepo, IamAupRepository aupRepo, TimeProvider timeProvider, - ApplicationEventPublisher publisher) { + ApplicationEventPublisher publisher, NotificationFactory notificationFactory) { this.signatureConverter = conv; this.accountUtils = utils; this.signatureRepo = signatureRepo; this.aupRepo = aupRepo; this.timeProvider = timeProvider; this.eventPublisher = publisher; + this.notificationFactory = notificationFactory; } private Supplier aupNotFoundException() { @@ -108,7 +114,7 @@ public void signAup() throws AccountNotFoundException { public AupSignatureDTO getSignature() throws AccountNotFoundException { IamAccount account = accountUtils.getAuthenticatedUserAccount() - .orElseThrow(accountNotFoundException(ACCOUNT_NOT_FOUND_FOR_AUTHENTICATED_USER_MESSAGE)); + .orElseThrow(accountNotFoundException(ACCOUNT_NOT_FOUND_FOR_AUTHENTICATED_USER_MESSAGE)); IamAup aup = aupRepo.findDefaultAup().orElseThrow(aupNotFoundException()); IamAupSignature sig = @@ -118,7 +124,8 @@ public AupSignatureDTO getSignature() throws AccountNotFoundException { @GetMapping(value = "/iam/aup/signature/{accountId}") @PreAuthorize("#iam.hasScope('iam:admin.read') or #iam.hasAnyDashboardRole('ROLE_ADMIN', 'ROLE_GM') or #iam.isUser(#accountId)") - public AupSignatureDTO getSignatureForAccount(@PathVariable String accountId) throws AccountNotFoundException { + public AupSignatureDTO getSignatureForAccount(@PathVariable String accountId) + throws AccountNotFoundException { IamAccount account = accountUtils.getByAccountId(accountId) .orElseThrow(accountNotFoundException(format(ACCOUNT_NOT_FOUND_FOR_ID_MESSAGE, accountId))); @@ -133,10 +140,10 @@ public AupSignatureDTO getSignatureForAccount(@PathVariable String accountId) th @PatchMapping(value = "/iam/aup/signature/{accountId}") @ResponseStatus(value = HttpStatus.CREATED) @PreAuthorize("#iam.hasScope('iam:admin.write') or #iam.hasDashboardRole('ROLE_ADMIN')") - public AupSignatureDTO updateSignatureForAccount(@PathVariable String accountId) throws AccountNotFoundException { + public AupSignatureDTO updateSignatureForAccount(@PathVariable String accountId, + Authentication authentication) throws AccountNotFoundException { - IamAccount updaterAccount = accountUtils.getAuthenticatedUserAccount() - .orElseThrow(accountNotFoundException(ACCOUNT_NOT_FOUND_FOR_AUTHENTICATED_USER_MESSAGE)); + Optional updaterAccount = accountUtils.getAuthenticatedUserAccount(); IamAccount account = accountUtils.getByAccountId(accountId) .orElseThrow(accountNotFoundException(format(ACCOUNT_NOT_FOUND_FOR_ID_MESSAGE, accountId))); @@ -144,7 +151,18 @@ public AupSignatureDTO updateSignatureForAccount(@PathVariable String accountId) Date now = new Date(timeProvider.currentTimeMillis()); IamAupSignature signature = signatureRepo.createSignatureForAccount(aup, account, now); - eventPublisher.publishEvent(new AupSignedOnBehalfEvent(this, signature, updaterAccount.getUsername())); + + String principal = null; + + if (updaterAccount.isPresent()) { + principal = updaterAccount.get().getUsername(); + eventPublisher.publishEvent(AupSignedOnBehalfEvent.signedByUser(this, principal, signature)); + } else if (authentication instanceof OAuth2Authentication) { + OAuth2Authentication oauth2Auth = (OAuth2Authentication) authentication; + principal = oauth2Auth.getOAuth2Request().getClientId(); + eventPublisher + .publishEvent(AupSignedOnBehalfEvent.signedByClient(this, principal, signature)); + } return signatureConverter.dtoFromEntity(signature); } @@ -152,10 +170,10 @@ public AupSignatureDTO updateSignatureForAccount(@PathVariable String accountId) @DeleteMapping(value = "/iam/aup/signature/{accountId}") @ResponseStatus(value = HttpStatus.NO_CONTENT) @PreAuthorize("#iam.hasScope('iam:admin.write') or #iam.hasDashboardRole('ROLE_ADMIN')") - public void deleteSignatureForAccount(@PathVariable String accountId) throws AccountNotFoundException { + public void deleteSignatureForAccount(@PathVariable String accountId, + Authentication authentication) throws AccountNotFoundException { - IamAccount deleterAccount = accountUtils.getAuthenticatedUserAccount() - .orElseThrow(accountNotFoundException(ACCOUNT_NOT_FOUND_FOR_AUTHENTICATED_USER_MESSAGE)); + Optional deleterAccount = accountUtils.getAuthenticatedUserAccount(); IamAccount signatureAccount = accountUtils.getByAccountId(accountId) .orElseThrow(accountNotFoundException(format(ACCOUNT_NOT_FOUND_FOR_ID_MESSAGE, accountId))); @@ -166,7 +184,20 @@ public void deleteSignatureForAccount(@PathVariable String accountId) throws Acc if (signature.isPresent()) { signatureRepo.deleteSignatureForAccount(aup, signatureAccount); - eventPublisher.publishEvent(new AupSignatureDeletedEvent(this, deleterAccount.getUsername(), signature.get())); + + String principal = null; + + if (deleterAccount.isPresent()) { + principal = deleterAccount.get().getUsername(); + eventPublisher + .publishEvent(AupSignatureDeletedEvent.deletedByUser(this, principal, signature.get())); + } else if (authentication instanceof OAuth2Authentication) { + OAuth2Authentication oauth2Auth = (OAuth2Authentication) authentication; + principal = oauth2Auth.getOAuth2Request().getClientId(); + eventPublisher + .publishEvent(AupSignatureDeletedEvent.deletedByClient(this, principal, signature.get())); + } + notificationFactory.createAupSignatureRequestMessage(signatureAccount); } } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/DefaultAupService.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/DefaultAupService.java index d6f53975c..2675030a5 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/DefaultAupService.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/DefaultAupService.java @@ -90,6 +90,7 @@ public IamAup updateAup(AupDTO aupDto) { aup.setDescription(aupDto.getDescription()); aup.setUrl(aupDto.getUrl()); aup.setSignatureValidityInDays(aupDto.getSignatureValidityInDays()); + aup.setAupRemindersInDays(aupDto.getAupRemindersInDays()); /* * Due to transition from text to URL, when updating the AUP only URL is considered while text * is ignored and set to null diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupConverter.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupConverter.java index d23a2b025..0fec79bd3 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupConverter.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupConverter.java @@ -32,13 +32,15 @@ public IamAup entityFromDto(AupDTO dto) { aup.setSignatureValidityInDays(dto.getSignatureValidityInDays()); aup.setUrl(dto.getUrl()); aup.setText(dto.getText()); + aup.setAupRemindersInDays(dto.getAupRemindersInDays()); return aup; } @Override public AupDTO dtoFromEntity(IamAup entity) { return new AupDTO(entity.getUrl(), entity.getText(), entity.getDescription(), - entity.getSignatureValidityInDays(), entity.getCreationTime(), entity.getLastUpdateTime()); + entity.getSignatureValidityInDays(), entity.getCreationTime(), entity.getLastUpdateTime(), + entity.getAupRemindersInDays()); } } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupDTO.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupDTO.java index af404ab61..f0cbf4aee 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupDTO.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupDTO.java @@ -17,9 +17,7 @@ import java.util.Date; -import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.URL; @@ -30,6 +28,7 @@ import it.infn.mw.iam.api.scim.controller.utils.JsonDateSerializer; import it.infn.mw.iam.api.validators.NoQueryParamsUrl; +@AupRemindersAndSignature public class AupDTO { @NotBlank(message = "Invalid AUP: the AUP URL cannot be blank") @@ -43,10 +42,10 @@ public class AupDTO { message = "Invalid AUP: the description string must be at most 128 characters long") String description; - @NotNull(message = "Invalid AUP: signatureValidityInDays is required") - @Min(value = 0L, message = "Invalid AUP: signatureValidityInDays must be >= 0") Long signatureValidityInDays; + String aupRemindersInDays = "30,15,1"; + @JsonSerialize(using = JsonDateSerializer.class) Date creationTime; @@ -57,13 +56,15 @@ public AupDTO(@JsonProperty("url") String url, @JsonProperty("text") String text @JsonProperty("description") String description, @JsonProperty("signatureValidityInDays") Long signatureValidityInDays, @JsonProperty("creationTime") Date creationTime, - @JsonProperty("lastUpdateTime") Date lastUpdateTime) { + @JsonProperty("lastUpdateTime") Date lastUpdateTime, + @JsonProperty("aupRemindersInDays") String aupRemindersInDays) { this.url = url; this.description = description; this.signatureValidityInDays = signatureValidityInDays; this.creationTime = creationTime; this.lastUpdateTime = lastUpdateTime; this.text = text; + this.aupRemindersInDays = aupRemindersInDays; } public String getDescription() { @@ -101,6 +102,14 @@ public void setSignatureValidityInDays(Long signatureValidityInDays) { this.signatureValidityInDays = signatureValidityInDays; } + public String getAupRemindersInDays() { + return aupRemindersInDays; + } + + public void setAupRemindersInDays(String aupRemindersInDays) { + this.aupRemindersInDays = aupRemindersInDays; + } + public Date getCreationTime() { return creationTime; diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupRemindersAndSignature.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupRemindersAndSignature.java new file mode 100644 index 000000000..af121c57d --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupRemindersAndSignature.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.api.aup.model; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + +@Retention(RUNTIME) +@Target({TYPE}) +@Constraint(validatedBy = AupRemindersAndSignatureValidator.class) +public @interface AupRemindersAndSignature { + + String message() default "Invalid AUP"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupRemindersAndSignatureValidator.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupRemindersAndSignatureValidator.java new file mode 100644 index 000000000..2609699d9 --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/aup/model/AupRemindersAndSignatureValidator.java @@ -0,0 +1,104 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.api.aup.model; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class AupRemindersAndSignatureValidator implements ConstraintValidator { + + @Override + public boolean isValid(AupDTO value, ConstraintValidatorContext context) { + + Long signatureValidityInDays = value.getSignatureValidityInDays(); + String aupRemindersInDays = value.getAupRemindersInDays(); + + if (signatureValidityInDays == null) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate("Invalid AUP: signatureValidityInDays is required") + .addPropertyNode("signatureValidityInDays") + .addConstraintViolation(); + return false; + } + + if (signatureValidityInDays < 0) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate("Invalid AUP: signatureValidityInDays must be >= 0") + .addPropertyNode("signatureValidityInDays") + .addConstraintViolation(); + return false; + } + + if (aupRemindersInDays == null || aupRemindersInDays.isEmpty()) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate( + "Invalid AUP: aupRemindersInDays cannot be empty or null") + .addConstraintViolation(); + return false; + } + + try { + List numbers = Arrays.stream(aupRemindersInDays.split(",")) + .map(String::trim) + .map(Integer::parseInt) + .collect(Collectors.toList()); + + if (numbers.stream().anyMatch(i -> i <= 0)) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate( + "Invalid AUP: zero or negative values for reminders are not allowed") + .addConstraintViolation(); + return false; + } + + if (numbers.stream().anyMatch(i -> i >= signatureValidityInDays)) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate( + "Invalid AUP: aupRemindersInDays must be smaller than signatureValidityInDays") + .addConstraintViolation(); + return false; + } + + Set uniqueNumbers = new HashSet<>(numbers); + if (uniqueNumbers.size() != numbers.size()) { + context.disableDefaultConstraintViolation(); + context + .buildConstraintViolationWithTemplate("Invalid AUP: duplicate values for reminders are not allowed") + .addConstraintViolation(); + return false; + } + + return true; + } catch (NumberFormatException e) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate("Invalid AUP: non-integer value found") + .addConstraintViolation(); + return false; + } + } + +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/ClientManagementAPIController.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/ClientManagementAPIController.java index 406891a30..60231fb9a 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/ClientManagementAPIController.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/ClientManagementAPIController.java @@ -66,7 +66,8 @@ public class ClientManagementAPIController { private final ClientManagementService managementService; private final AccountUtils accountUtils; - public ClientManagementAPIController(ClientManagementService managementService, AccountUtils accountUtils) { + public ClientManagementAPIController(ClientManagementService managementService, + AccountUtils accountUtils) { this.managementService = managementService; this.accountUtils = accountUtils; } @@ -83,13 +84,11 @@ public RegisteredClientDTO saveNewClient(@RequestBody RegisteredClientDTO client @GetMapping @PreAuthorize("#iam.hasScope('iam:admin.read') or #iam.hasDashboardRole('ROLE_ADMIN')") public ListResponseDTO retrieveClients( - @RequestParam final Optional count, - @RequestParam final Optional startIndex, + @RequestParam final Optional count, @RequestParam final Optional startIndex, @RequestParam(defaultValue = "false") final boolean drOnly) { - Pageable pageable = - PagingUtils.buildPageRequest(count, startIndex, Sort.by("clientId")); - + Pageable pageable = PagingUtils.buildPageRequest(count, startIndex, Sort.by("clientId")); + if (drOnly) { return managementService.retrieveAllDynamicallyRegisteredClients(pageable); } else { @@ -110,7 +109,7 @@ public RegisteredClientDTO retrieveClient(@PathVariable String clientId) { public ListResponseDTO retrieveClientOwners(@PathVariable String clientId, @RequestParam final Optional count, @RequestParam final Optional startIndex) { - + return managementService.getClientOwners(clientId, buildPageRequest(count, startIndex)); } @@ -140,14 +139,13 @@ public void removeClientOwner(@PathVariable String clientId, @PutMapping("/{clientId}") @PreAuthorize("#iam.hasScope('iam:admin.write') or #iam.hasDashboardRole('ROLE_ADMIN')") public RegisteredClientDTO updateClient(@PathVariable String clientId, - @RequestBody RegisteredClientDTO client) - throws ParseException { + @RequestBody RegisteredClientDTO client) throws ParseException { return managementService.updateClient(clientId, client); } @PatchMapping("/{clientId}/enable") @PreAuthorize("#iam.hasScope('iam:admin.write') or #iam.hasDashboardRole('ROLE_ADMIN')") - public void enableClient(@PathVariable String clientId) { + public void enableClient(@PathVariable String clientId) { Optional account = accountUtils.getAuthenticatedUserAccount(); account.ifPresent(a -> managementService.updateClientStatus(clientId, true, a.getUuid())); } @@ -155,7 +153,7 @@ public void enableClient(@PathVariable String clientId) { @PatchMapping("/{clientId}/disable") @PreAuthorize("#iam.hasScope('iam:admin.write') or #iam.hasDashboardRole('ROLE_ADMIN')") public void disableClient(@PathVariable String clientId) { - Optional account = accountUtils.getAuthenticatedUserAccount(); + Optional account = accountUtils.getAuthenticatedUserAccount(); account.ifPresent(a -> managementService.updateClientStatus(clientId, false, a.getUuid())); } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/service/DefaultClientManagementService.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/service/DefaultClientManagementService.java index 25c12c870..1055aca9c 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/service/DefaultClientManagementService.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/service/DefaultClientManagementService.java @@ -23,6 +23,7 @@ import java.text.ParseException; import java.time.Clock; import java.util.Date; +import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -44,6 +45,7 @@ import it.infn.mw.iam.api.client.service.ClientService; import it.infn.mw.iam.api.client.util.ClientSuppliers; import it.infn.mw.iam.api.common.ListResponseDTO; +import it.infn.mw.iam.api.common.PagingUtils; import it.infn.mw.iam.api.common.client.RegisteredClientDTO; import it.infn.mw.iam.api.scim.converter.UserConverter; import it.infn.mw.iam.api.scim.model.ScimUser; @@ -55,6 +57,7 @@ import it.infn.mw.iam.audit.events.client.ClientStatusChangedEvent; import it.infn.mw.iam.audit.events.client.ClientUpdatedEvent; import it.infn.mw.iam.core.IamTokenService; +import it.infn.mw.iam.notification.NotificationFactory; import it.infn.mw.iam.persistence.model.IamAccount; import it.infn.mw.iam.persistence.model.IamAccountClient; import it.infn.mw.iam.persistence.repository.IamAccountRepository; @@ -72,11 +75,13 @@ public class DefaultClientManagementService implements ClientManagementService { private final OIDCTokenService oidcTokenService; private final IamTokenService tokenService; private final ApplicationEventPublisher eventPublisher; + private final NotificationFactory notificationFactory; public DefaultClientManagementService(Clock clock, ClientService clientService, ClientConverter converter, ClientDefaultsService defaultsService, UserConverter userConverter, IamAccountRepository accountRepo, OIDCTokenService oidcTokenService, - IamTokenService tokenService, ApplicationEventPublisher aep) { + IamTokenService tokenService, ApplicationEventPublisher aep, + NotificationFactory notificationFactory) { this.clock = clock; this.clientService = clientService; this.converter = converter; @@ -86,6 +91,7 @@ public DefaultClientManagementService(Clock clock, ClientService clientService, this.oidcTokenService = oidcTokenService; this.tokenService = tokenService; this.eventPublisher = aep; + this.notificationFactory = notificationFactory; } @Override @@ -139,10 +145,19 @@ public void deleteClientByClientId(String clientId) { public void updateClientStatus(String clientId, boolean status, String userId) { ClientDetailsEntity client = clientService.findClientByClientId(clientId) - .orElseThrow(ClientSuppliers.clientNotFound(clientId)); + .orElseThrow(ClientSuppliers.clientNotFound(clientId)); client = clientService.updateClientStatus(client, status, userId); - String message = "Client " + (status?"enabled":"disabled"); + String message = "Client " + (status ? "enabled" : "disabled"); eventPublisher.publishEvent(new ClientStatusChangedEvent(this, client, message)); + notificationFactory.createClientStatusChangedMessageFor(client, getClientOwners(clientId)); + } + + private List getClientOwners(String clientId) { + return clientService.findClientOwners(clientId, PagingUtils.buildUnpagedPageRequest()) + .getContent() + .stream() + .map(IamAccountClient::getAccount) + .collect(Collectors.toList()); } @Validated(OnClientUpdate.class) diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/validation/OnRegistrationCreation.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/validation/OnRegistrationCreation.java new file mode 100644 index 000000000..7408cad4c --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/client/management/validation/OnRegistrationCreation.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.api.client.management.validation; + +public interface OnRegistrationCreation { + +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/client/service/DefaultClientService.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/client/service/DefaultClientService.java index 1f6383cb0..b28e54efd 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/client/service/DefaultClientService.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/client/service/DefaultClientService.java @@ -23,12 +23,10 @@ import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.oauth2.service.OAuth2TokenEntityService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,7 +40,6 @@ @Service @Transactional -@SuppressWarnings("deprecation") public class DefaultClientService implements ClientService { private final Clock clock; @@ -55,10 +52,8 @@ public class DefaultClientService implements ClientService { private OAuth2TokenEntityService tokenService; - @Autowired public DefaultClientService(Clock clock, IamClientRepository clientRepo, - IamAccountClientRepository accountClientRepo, ApplicationEventPublisher eventPublisher, - OAuth2RequestValidator requestValidator, OAuth2TokenEntityService tokenService) { + IamAccountClientRepository accountClientRepo, ApplicationEventPublisher eventPublisher, OAuth2TokenEntityService tokenService) { this.clock = clock; this.clientRepo = clientRepo; this.accountClientRepo = accountClientRepo; diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/common/RegistrationViews.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/common/RegistrationViews.java new file mode 100644 index 000000000..a5ee49fa5 --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/common/RegistrationViews.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.api.common; + +public class RegistrationViews { + + private RegistrationViews() {} + + public static interface RegistrationDetail { + } + + public static interface RegistrationExtendDetail extends RegistrationDetail { + } + +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/api/scim/provisioning/ScimUserProvisioning.java b/iam-login-service/src/main/java/it/infn/mw/iam/api/scim/provisioning/ScimUserProvisioning.java index 8e1d7fdf4..ad3931674 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/api/scim/provisioning/ScimUserProvisioning.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/api/scim/provisioning/ScimUserProvisioning.java @@ -65,6 +65,7 @@ import it.infn.mw.iam.core.user.IamAccountService; import it.infn.mw.iam.core.user.exception.CredentialAlreadyBoundException; import it.infn.mw.iam.core.user.exception.UserAlreadyExistsException; +import it.infn.mw.iam.notification.NotificationFactory; import it.infn.mw.iam.persistence.model.IamAccount; import it.infn.mw.iam.persistence.repository.IamAccountRepository; import it.infn.mw.iam.registration.validation.UsernameValidator; @@ -84,6 +85,7 @@ public class ScimUserProvisioning private final IamAccountRepository accountRepository; private final UserConverter userConverter; private final DefaultAccountUpdaterFactory updatersFactory; + private final NotificationFactory notificationFactory; private ApplicationEventPublisher eventPublisher; @@ -91,12 +93,13 @@ public ScimUserProvisioning(IamAccountService accountService, OAuth2TokenEntityService tokenService, IamAccountRepository accountRepository, PasswordEncoder passwordEncoder, UserConverter userConverter, OidcIdConverter oidcIdConverter, SamlIdConverter samlIdConverter, SshKeyConverter sshKeyConverter, - X509CertificateConverter x509CertificateConverter, - UsernameValidator usernameValidator) { + X509CertificateConverter x509CertificateConverter, UsernameValidator usernameValidator, + NotificationFactory notificationFactory) { this.accountService = accountService; this.accountRepository = accountRepository; this.userConverter = userConverter; + this.notificationFactory = notificationFactory; this.updatersFactory = new DefaultAccountUpdaterFactory(passwordEncoder, accountRepository, accountService, tokenService, oidcIdConverter, samlIdConverter, sshKeyConverter, x509CertificateConverter, usernameValidator); @@ -266,11 +269,22 @@ private void executePatchOperation(IamAccount account, ScimPatchOperation> operations) { diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/IamAuditApplicationEvent.java b/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/IamAuditApplicationEvent.java index 253ed5327..4b601aa7a 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/IamAuditApplicationEvent.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/IamAuditApplicationEvent.java @@ -29,34 +29,32 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; @JsonPropertyOrder({"timestamp", "@type", "category", "principal", "message"}) -@JsonTypeInfo(use=Id.NAME, property="@type") +@JsonTypeInfo(use = Id.NAME, property = "@type") public abstract class IamAuditApplicationEvent extends ApplicationEvent { private static final long serialVersionUID = -6276169409979227109L; - + public static final String NULL_PRINCIPAL = ""; @JsonInclude private final IamEventCategory category; - + @JsonInclude private final String principal; - + @JsonInclude private final String message; - public IamAuditApplicationEvent(IamEventCategory category, Object source, String message) { + this(category, source, message, SecurityContextHolder.getContext().getAuthentication()); + } + + public IamAuditApplicationEvent(IamEventCategory category, Object source, String message, + Authentication auth) { super(source); - this.message = message; this.category = category; - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - - if (auth == null) { - this.principal = NULL_PRINCIPAL; - } else { - this.principal = auth.getName(); - } + this.message = message; + this.principal = (auth != null) ? auth.getName() : NULL_PRINCIPAL; } protected IamAuditApplicationEvent(IamEventCategory category, Object source) { @@ -80,9 +78,9 @@ public IamEventCategory getCategory() { public Object getSource() { return super.getSource(); } - + @JsonProperty("source") - public String getSourceClass(){ + public String getSourceClass() { return super.getSource().getClass().getSimpleName(); } } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/aup/AupSignatureDeletedEvent.java b/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/aup/AupSignatureDeletedEvent.java index 1adfbd004..40862a607 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/aup/AupSignatureDeletedEvent.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/aup/AupSignatureDeletedEvent.java @@ -15,8 +15,6 @@ */ package it.infn.mw.iam.audit.events.aup; -import static java.lang.String.format; - import com.fasterxml.jackson.databind.annotation.JsonSerialize; import it.infn.mw.iam.audit.events.IamAuditApplicationEvent; @@ -34,11 +32,23 @@ public class AupSignatureDeletedEvent extends IamAuditApplicationEvent { @JsonSerialize(using = IamAupSignatureSerializer.class) final IamAupSignature signature; - public AupSignatureDeletedEvent(Object source, String actor, IamAupSignature signature) { - super(IamEventCategory.AUP, source, - format("Administrator %s requested AUP signature to the user %s", actor, - signature.getAccount().getUsername())); + public AupSignatureDeletedEvent(Object source, String message, IamAupSignature signature) { + super(IamEventCategory.AUP, source, message); this.signature = signature; } + public static AupSignatureDeletedEvent deletedByClient(Object source, String clientId, + IamAupSignature signature) { + String message = String.format("Client %s deleted the AUP signature of %s user", clientId, + signature.getAccount().getUsername()); + return new AupSignatureDeletedEvent(source, message, signature); + } + + public static AupSignatureDeletedEvent deletedByUser(Object source, String userId, + IamAupSignature signature) { + String message = String.format("User %s deleted the AUP signature of %s user", userId, + signature.getAccount().getUsername()); + return new AupSignatureDeletedEvent(source, message, signature); + } + } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/aup/AupSignedOnBehalfEvent.java b/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/aup/AupSignedOnBehalfEvent.java index c4817a360..a410a4b93 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/aup/AupSignedOnBehalfEvent.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/audit/events/aup/AupSignedOnBehalfEvent.java @@ -15,8 +15,6 @@ */ package it.infn.mw.iam.audit.events.aup; -import static java.lang.String.format; - import com.fasterxml.jackson.databind.annotation.JsonSerialize; import it.infn.mw.iam.audit.events.IamAuditApplicationEvent; @@ -34,9 +32,23 @@ public class AupSignedOnBehalfEvent extends IamAuditApplicationEvent { @JsonSerialize(using = IamAupSignatureSerializer.class) final IamAupSignature signature; - public AupSignedOnBehalfEvent(Object source, IamAupSignature signature, String signedBy) { - super(IamEventCategory.AUP, source, format("Administrator %s signed the AUP on behalf of %s", - signedBy, signature.getAccount().getUsername())); + public AupSignedOnBehalfEvent(Object source, String message, IamAupSignature signature) { + super(IamEventCategory.AUP, source, message); this.signature = signature; } + + public static AupSignedOnBehalfEvent signedByClient(Object source, String clientId, + IamAupSignature signature) { + String message = String.format("Client %s signed the AUP on behalf of %s user", clientId, + signature.getAccount().getUsername()); + return new AupSignedOnBehalfEvent(source, message, signature); + } + + public static AupSignedOnBehalfEvent signedByUser(Object source, String userId, + IamAupSignature signature) { + String message = String.format("User %s signed the AUP on behalf of %s user", userId, + signature.getAccount().getUsername()); + return new AupSignedOnBehalfEvent(source, message, signature); + } + } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/authn/ExternalAuthenticationFailureHandler.java b/iam-login-service/src/main/java/it/infn/mw/iam/authn/ExternalAuthenticationFailureHandler.java index b7e399f84..acec18b04 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/authn/ExternalAuthenticationFailureHandler.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/authn/ExternalAuthenticationFailureHandler.java @@ -48,7 +48,6 @@ private String buildRedirectURL(AuthenticationException exception) { return UriComponentsBuilder.fromPath("/login") .queryParam("error", "true") - .queryParam("externalAuthenticationError", errorMessage) .build(true) .toString(); } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/config/CacheConfig.java b/iam-login-service/src/main/java/it/infn/mw/iam/config/CacheConfig.java index b50fad3a9..b212c1197 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/config/CacheConfig.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/config/CacheConfig.java @@ -16,9 +16,10 @@ package it.infn.mw.iam.config; import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.cache.CacheManager; import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.cache.support.NoOpCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; @@ -30,26 +31,31 @@ public class CacheConfig { @Bean - @ConditionalOnProperty(name = "redis-cache.enabled", havingValue = "false") - public CacheManager localCacheManager() { + @ConditionalOnExpression("${cache.enabled} == false") + CacheManager fakeCacheManager(CacheProperties props) { + return new NoOpCacheManager(); + } + + @Bean + @ConditionalOnExpression("${cache.enabled} == true and ${cache.redis.enabled} == false") + CacheManager localCacheManager(CacheProperties props) { return new ConcurrentMapCacheManager(IamWellKnownInfoProvider.CACHE_KEY, DefaultScopeMatcherRegistry.SCOPE_CACHE_KEY); } @Bean - @ConditionalOnProperty(name = "redis-cache.enabled", havingValue = "true") - public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() { + @ConditionalOnExpression("${cache.enabled} == true and ${cache.redis.enabled} == true") + RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() { return builder -> builder .withCacheConfiguration(IamWellKnownInfoProvider.CACHE_KEY, RedisCacheConfiguration.defaultCacheConfig()) .withCacheConfiguration(DefaultScopeMatcherRegistry.SCOPE_CACHE_KEY, RedisCacheConfiguration.defaultCacheConfig()); - } @Bean - @ConditionalOnProperty(name = "redis-cache.enabled", havingValue = "true") - public RedisCacheConfiguration redisCacheConfiguration() { + @ConditionalOnExpression("${cache.enabled} == true and ${cache.redis.enabled} == true") + RedisCacheConfiguration redisCacheConfiguration() { return RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues(); } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/config/RedisCacheProperties.java b/iam-login-service/src/main/java/it/infn/mw/iam/config/CacheProperties.java similarity index 65% rename from iam-login-service/src/main/java/it/infn/mw/iam/config/RedisCacheProperties.java rename to iam-login-service/src/main/java/it/infn/mw/iam/config/CacheProperties.java index 1751a2579..e8ffd455d 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/config/RedisCacheProperties.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/config/CacheProperties.java @@ -18,11 +18,27 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; -@ConfigurationProperties("redis-cache") +@ConfigurationProperties("cache") @Configuration -public class RedisCacheProperties { +public class CacheProperties { - private boolean enabled = false; + public class RedisProperties { + + private boolean enabled = false; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enable) { + this.enabled = enable; + } + + } + + private boolean enabled = true; + + private RedisProperties redis = new RedisProperties(); public boolean isEnabled() { return enabled; @@ -32,4 +48,13 @@ public void setEnabled(boolean enable) { this.enabled = enable; } + public RedisProperties getRedis() { + return redis; + } + + public void setRedis(RedisProperties redis) { + this.redis = redis; + } + + } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/config/IamProperties.java b/iam-login-service/src/main/java/it/infn/mw/iam/config/IamProperties.java index 95edad4b1..c6dd8f671 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/config/IamProperties.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/config/IamProperties.java @@ -232,6 +232,8 @@ public static class RegistrationProperties { Map fields; + List defaultGroups; + public boolean isShowRegistrationButtonInLoginPage() { return showRegistrationButtonInLoginPage; } @@ -287,6 +289,14 @@ public Map getFields() { public void setFields(Map fields) { this.fields = fields; } + + public List getDefaultGroups() { + return defaultGroups; + } + + public void setDefaultGroups(List defaultGroups) { + this.defaultGroups = defaultGroups; + } } public static class DeviceCodeProperties { @@ -548,7 +558,7 @@ public void setLocation(String location) { } public static class ClientProperties { - private boolean trackLastUsed; + private boolean trackLastUsed = false; public boolean isTrackLastUsed() { return trackLastUsed; @@ -559,6 +569,27 @@ public void setTrackLastUsed(boolean trackLastUsed) { } } + public static class DefaultGroup { + private String name; + private String enrollment = "INSERT"; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEnrollment() { + return enrollment; + } + + public void setEnrollment(String enrollment) { + this.enrollment = enrollment; + } + } + private String host; private String issuer; diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/config/TaskConfig.java b/iam-login-service/src/main/java/it/infn/mw/iam/config/TaskConfig.java index a9943bfc4..7a5442217 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/config/TaskConfig.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/config/TaskConfig.java @@ -37,6 +37,7 @@ import it.infn.mw.iam.config.lifecycle.LifecycleProperties; import it.infn.mw.iam.core.lifecycle.ExpiredAccountsHandler; import it.infn.mw.iam.core.user.IamAccountService; +import it.infn.mw.iam.core.web.aup.AupReminderTask; import it.infn.mw.iam.core.web.wellknown.IamWellKnownInfoProvider; import it.infn.mw.iam.notification.NotificationDelivery; import it.infn.mw.iam.notification.NotificationDeliveryTask; @@ -84,6 +85,9 @@ public class TaskConfig implements SchedulingConfigurer { @Autowired ExpiredAccountsHandler expiredAccountsHandler; + @Autowired + AupReminderTask aupReminderTask; + @Autowired CacheManager cacheManager; @@ -127,6 +131,12 @@ public void clearExpiredDeviceCodes() { deviceCodeService.clearExpiredDeviceCodes(); } + @Scheduled(fixedRateString = "${task.aupReminder:14400}", timeUnit = TimeUnit.SECONDS, + initialDelay = ONE_MINUTE_MSEC) + public void scheduledAupRemindersTask() { + aupReminderTask.sendAupReminders(); + } + public void schedulePendingNotificationsDelivery(final ScheduledTaskRegistrar taskRegistrar) { if (notificationTaskPeriodMsec < 0) { diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/IamStatisticalEndpoint.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/IamStatisticalEndpoint.java new file mode 100644 index 000000000..52802ce0e --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/IamStatisticalEndpoint.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.core; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import it.infn.mw.iam.persistence.repository.IamAccountRepository; + +@RestController +public class IamStatisticalEndpoint { + + @Autowired + IamAccountRepository accountRepo; + + @GetMapping("/stats") + public StatsEndpointResponse getStats() { + long count = accountRepo.count(); + return new StatsEndpointResponse(count); + } +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/StatsEndpointResponse.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/StatsEndpointResponse.java new file mode 100644 index 000000000..73c1317a8 --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/StatsEndpointResponse.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.core; + +public class StatsEndpointResponse { + + private long numberOfUsers; + + public StatsEndpointResponse(long numberOfUsers) { + this.numberOfUsers = numberOfUsers; + } + + public long getNumberOfUsers() { + return numberOfUsers; + } + + public void setNumberOfUsers(long numberOfUsers) { + this.numberOfUsers = numberOfUsers; + } +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/user/DefaultIamAccountService.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/user/DefaultIamAccountService.java index 061fc0351..81c3857a9 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/core/user/DefaultIamAccountService.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/user/DefaultIamAccountService.java @@ -28,6 +28,7 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.Objects; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.oauth2.model.OAuth2RefreshTokenEntity; @@ -51,9 +52,13 @@ import it.infn.mw.iam.audit.events.account.group.GroupMembershipRemovedEvent; import it.infn.mw.iam.audit.events.account.label.AccountLabelRemovedEvent; import it.infn.mw.iam.audit.events.account.label.AccountLabelSetEvent; +import it.infn.mw.iam.config.IamProperties; +import it.infn.mw.iam.config.IamProperties.DefaultGroup; +import it.infn.mw.iam.core.group.DefaultIamGroupService; import it.infn.mw.iam.core.user.exception.CredentialAlreadyBoundException; import it.infn.mw.iam.core.user.exception.InvalidCredentialException; import it.infn.mw.iam.core.user.exception.UserAlreadyExistsException; +import it.infn.mw.iam.notification.NotificationFactory; import it.infn.mw.iam.persistence.model.IamAccount; import it.infn.mw.iam.persistence.model.IamAccountGroupMembership; import it.infn.mw.iam.persistence.model.IamAttribute; @@ -81,11 +86,16 @@ public class DefaultIamAccountService implements IamAccountService, ApplicationE private ApplicationEventPublisher eventPublisher; private final OAuth2TokenEntityService tokenService; private final IamAccountClientRepository accountClientRepo; + private final NotificationFactory notificationFactory; + private final IamProperties iamProperties; + private final DefaultIamGroupService iamGroupService; public DefaultIamAccountService(Clock clock, IamAccountRepository accountRepo, IamGroupRepository groupRepo, IamAuthoritiesRepository authoritiesRepo, PasswordEncoder passwordEncoder, ApplicationEventPublisher eventPublisher, - OAuth2TokenEntityService tokenService, IamAccountClientRepository accountClientRepo) { + OAuth2TokenEntityService tokenService, IamAccountClientRepository accountClientRepo, + NotificationFactory notificationFactory, IamProperties iamProperties, + DefaultIamGroupService iamGroupService) { this.clock = clock; this.accountRepo = accountRepo; @@ -95,6 +105,9 @@ public DefaultIamAccountService(Clock clock, IamAccountRepository accountRepo, this.eventPublisher = eventPublisher; this.tokenService = tokenService; this.accountClientRepo = accountClientRepo; + this.notificationFactory = notificationFactory; + this.iamProperties = iamProperties; + this.iamGroupService = iamGroupService; } private void labelSetEvent(IamAccount account, IamLabel label) { @@ -177,10 +190,22 @@ public IamAccount createAccount(IamAccount account) { eventPublisher.publishEvent(new AccountCreatedEvent(this, account, "Account created for user " + account.getUsername())); - + + addToDefaultGroups(account); return account; } + private void addToDefaultGroups(IamAccount account) { + List defaultGroups = iamProperties.getRegistration().getDefaultGroups(); + if (Objects.nonNull(defaultGroups)) { + defaultGroups.forEach(group -> { + if ("INSERT".equalsIgnoreCase(group.getEnrollment())) { + iamGroupService.findByName(group.getName()).ifPresent(iamGroup -> addToGroup(account, iamGroup)); + } + }); + } + } + protected void removeClientLinks(IamAccount account) { accountClientRepo.deleteByAccount(account); @@ -403,6 +428,7 @@ public IamAccount disableAccount(IamAccount account) { account.touch(); accountRepo.save(account); eventPublisher.publishEvent(new AccountDisabledEvent(this, account)); + notificationFactory.createAccountSuspendedMessage(account); return account; } @@ -412,6 +438,7 @@ public IamAccount restoreAccount(IamAccount account) { account.touch(); accountRepo.save(account); eventPublisher.publishEvent(new AccountRestoredEvent(this, account)); + notificationFactory.createAccountRestoredMessage(account); return account; } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/web/aup/AupReminderTask.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/web/aup/AupReminderTask.java new file mode 100644 index 000000000..5bcff6068 --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/web/aup/AupReminderTask.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.core.web.aup; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import it.infn.mw.iam.notification.NotificationFactory; +import it.infn.mw.iam.persistence.model.IamAccount; +import it.infn.mw.iam.persistence.model.IamAup; +import it.infn.mw.iam.persistence.model.IamAupSignature; +import it.infn.mw.iam.persistence.repository.IamAccountRepository; +import it.infn.mw.iam.persistence.repository.IamAupRepository; +import it.infn.mw.iam.persistence.repository.IamAupSignatureRepository; +import it.infn.mw.iam.persistence.repository.IamEmailNotificationRepository; + +@Component +public class AupReminderTask { + + @Autowired + IamAccountRepository accounts; + + @Autowired + IamAupRepository aupRepo; + + @Autowired + NotificationFactory notification; + + @Autowired + IamAupSignatureRepository aupSignatureRepo; + + @Autowired + IamEmailNotificationRepository emailNotificationRepo; + + public void sendAupReminders() { + aupRepo.findDefaultAup().ifPresent(aup -> { + LocalDate currentDate = LocalDate.now(); + if (aup.getSignatureValidityInDays() > 0) { + LocalDate expirationDate = currentDate.minusDays(aup.getSignatureValidityInDays()); + Date expirationDateAsDate = toDate(expirationDate); + Date expirationDatePlusOneDayAsDate = toDate(expirationDate.plusDays(1)); + List reminderIntervals = parseReminderIntervals(aup.getAupRemindersInDays()); + + reminderIntervals.forEach( + interval -> processRemindersForInterval(aup, currentDate, interval, expirationDate)); + + List expiredSignatures = aupSignatureRepo.findByAupAndSignatureTime(aup, + expirationDateAsDate, expirationDatePlusOneDayAsDate); + + // check if an email of type AUP_EXPIRATION does not already exist, because it is never deleted + expiredSignatures.forEach(s -> { + if (isExpiredSignatureEmailNotAlreadySentFor(s.getAccount())) { + notification.createAupSignatureExpMessage(s.getAccount()); + } + }); + } + }); + } + + private void processRemindersForInterval(IamAup aup, LocalDate currentDate, Integer interval, + LocalDate expirationDate) { + LocalDate reminderDate = expirationDate.plusDays(interval); + Date reminderDateAsDate = toDate(reminderDate); + Date reminderDatePlusOneAsDate = toDate(reminderDate.plusDays(1)); + Date tomorrowAsDate = toDate(currentDate.plusDays(1)); + + List signatures = aupSignatureRepo.findByAupAndSignatureTime(aup, + reminderDateAsDate, reminderDatePlusOneAsDate); + + // check if an email of type AUP_REMINDER does not already exist, because it is never deleted + signatures.forEach(s -> { + if (isAupReminderEmailNotAlreadySentFor(s.getAccount(), tomorrowAsDate)) { + notification.createAupReminderMessage(s.getAccount(), aup); + } + }); + } + + public boolean isExpiredSignatureEmailNotAlreadySentFor(IamAccount account) { + return emailNotificationRepo + .countAupExpirationMessPerAccount(account.getUserInfo().getEmail()) == 0; + } + + public boolean isAupReminderEmailNotAlreadySentFor(IamAccount account, Date tomorrowAsDate) { + return emailNotificationRepo.countAupRemindersPerAccount(account.getUserInfo().getEmail(), + tomorrowAsDate) == 0; + } + + private Date toDate(LocalDate localDate) { + return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); + } + + private static List parseReminderIntervals(String aupRemindersInDays) { + List result = new ArrayList<>(); + String[] parts = aupRemindersInDays.split("\\s*,\\s*"); + for (String part : parts) { + result.add(Integer.parseInt(part.trim())); + } + return result; + } + +} diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/core/web/wellknown/IamWellKnownInfoProvider.java b/iam-login-service/src/main/java/it/infn/mw/iam/core/web/wellknown/IamWellKnownInfoProvider.java index 9254a1551..05c60d158 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/core/web/wellknown/IamWellKnownInfoProvider.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/core/web/wellknown/IamWellKnownInfoProvider.java @@ -164,7 +164,7 @@ private String getIssuerWithTrailingSlash() { } @Override - @Cacheable(CACHE_KEY) + @Cacheable(value = CACHE_KEY) public Map getWellKnownInfo() { Map result = newHashMap(); diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/notification/NotificationFactory.java b/iam-login-service/src/main/java/it/infn/mw/iam/notification/NotificationFactory.java index 035218299..a16359b05 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/notification/NotificationFactory.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/notification/NotificationFactory.java @@ -15,9 +15,13 @@ */ package it.infn.mw.iam.notification; +import java.util.List; import java.util.Optional; +import org.mitre.oauth2.model.ClientDetailsEntity; + import it.infn.mw.iam.persistence.model.IamAccount; +import it.infn.mw.iam.persistence.model.IamAup; import it.infn.mw.iam.persistence.model.IamEmailNotification; import it.infn.mw.iam.persistence.model.IamGroupRequest; import it.infn.mw.iam.persistence.model.IamRegistrationRequest; @@ -28,7 +32,8 @@ public interface NotificationFactory { IamEmailNotification createAccountActivatedMessage(IamRegistrationRequest request); - IamEmailNotification createRequestRejectedMessage(IamRegistrationRequest request, Optional motivation); + IamEmailNotification createRequestRejectedMessage(IamRegistrationRequest request, + Optional motivation); IamEmailNotification createAdminHandleRequestMessage(IamRegistrationRequest request); @@ -39,4 +44,17 @@ public interface NotificationFactory { IamEmailNotification createGroupMembershipApprovedMessage(IamGroupRequest groupRequest); IamEmailNotification createGroupMembershipRejectedMessage(IamGroupRequest groupRequest); + + IamEmailNotification createClientStatusChangedMessageFor(ClientDetailsEntity client, + List accounts); + + IamEmailNotification createAupReminderMessage(IamAccount account, IamAup aup); + + IamEmailNotification createAupSignatureExpMessage(IamAccount account); + + IamEmailNotification createAupSignatureRequestMessage(IamAccount account); + + IamEmailNotification createAccountSuspendedMessage(IamAccount account); + + IamEmailNotification createAccountRestoredMessage(IamAccount account); } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/notification/TransientNotificationFactory.java b/iam-login-service/src/main/java/it/infn/mw/iam/notification/TransientNotificationFactory.java index ea0b74e66..77ab7c021 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/notification/TransientNotificationFactory.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/notification/TransientNotificationFactory.java @@ -18,33 +18,41 @@ import static java.util.Arrays.asList; import java.io.IOException; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; -import freemarker.template.Configuration; -import freemarker.template.TemplateException; +import org.mitre.oauth2.model.ClientDetailsEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; +import com.google.common.collect.Lists; + +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; import it.infn.mw.iam.api.account.password_reset.PasswordResetController; import it.infn.mw.iam.core.IamDeliveryStatus; import it.infn.mw.iam.core.IamNotificationType; import it.infn.mw.iam.notification.service.resolver.AdminNotificationDeliveryStrategy; import it.infn.mw.iam.notification.service.resolver.GroupManagerNotificationDeliveryStrategy; import it.infn.mw.iam.persistence.model.IamAccount; +import it.infn.mw.iam.persistence.model.IamAup; import it.infn.mw.iam.persistence.model.IamEmailNotification; import it.infn.mw.iam.persistence.model.IamGroupRequest; import it.infn.mw.iam.persistence.model.IamNotificationReceiver; import it.infn.mw.iam.persistence.model.IamRegistrationRequest; -import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; -import freemarker.template.Template; public class TransientNotificationFactory implements NotificationFactory { @@ -54,6 +62,8 @@ public class TransientNotificationFactory implements NotificationFactory { private static final String USERNAME_FIELD = "username"; private static final String GROUPNAME_FIELD = "groupName"; private static final String MOTIVATION_FIELD = "motivation"; + private static final String AUP_PATH = "%s/iam/aup/sign"; + private static final String AUP_URL = "aupUrl"; @Value("${iam.baseUrl}") private String baseUrl; @@ -67,7 +77,8 @@ public class TransientNotificationFactory implements NotificationFactory { private final Configuration freeMarkerConfiguration; @Autowired - public TransientNotificationFactory(Configuration fm, NotificationProperties np, AdminNotificationDeliveryStrategy ands, GroupManagerNotificationDeliveryStrategy gmds) { + public TransientNotificationFactory(Configuration fm, NotificationProperties np, + AdminNotificationDeliveryStrategy ands, GroupManagerNotificationDeliveryStrategy gmds) { this.freeMarkerConfiguration = fm; this.properties = np; this.adminNotificationDeliveryStrategy = ands; @@ -199,7 +210,8 @@ public IamEmailNotification createAdminHandleGroupRequestMessage(IamGroupRequest LOG.debug("Create group membership admin notification for request {}", groupRequest.getUuid()); return createMessage("adminHandleGroupRequest.ftl", model, IamNotificationType.GROUP_MEMBERSHIP, - subject, groupManagerDeliveryStrategy.resolveGroupManagersEmailAddresses(groupRequest.getGroup())); + subject, + groupManagerDeliveryStrategy.resolveGroupManagersEmailAddresses(groupRequest.getGroup())); } @Override @@ -249,10 +261,156 @@ public IamEmailNotification createGroupMembershipRejectedMessage(IamGroupRequest return notification; } + @Override + public IamEmailNotification createClientStatusChangedMessageFor(ClientDetailsEntity client, + List accounts) { + Set recipients = client.getContacts(); + + Map model = new HashMap<>(); + model.put("clientId", client.getClientId()); + model.put("clientName", client.getClientName()); + model.put("isClientActive", client.isActive()); + model.put(ORGANISATION_NAME, organisationName); + + String subject = "Changed client status"; + + for (IamAccount a : accounts) { + recipients.add(a.getUserInfo().getEmail()); + } + + List emails = Lists.newArrayList(recipients); + + if (emails.isEmpty()) { + LOG.warn("No email to send notification to for client {}", client.getClientId()); + return null; + } + + IamEmailNotification notification = createMessage("clientStatusChanged.ftl", model, + IamNotificationType.CLIENT_STATUS, subject, emails); + + LOG.debug("Updated client status. Client id {}, active {}", client.getClientId(), + client.isActive()); + return notification; + } + + @Override + public IamEmailNotification createAupReminderMessage(IamAccount account, IamAup aup) { + String recipient = account.getUserInfo().getName(); + String aupUrl = String.format(AUP_PATH, baseUrl); + + LocalDate now = LocalDate.now(); + long signatureValidityInDays = aup.getSignatureValidityInDays(); + LocalDate signatureTime = account.getAupSignature() + .getSignatureTime() + .toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + LocalDate signatureValidTime = signatureTime.plusDays(signatureValidityInDays); + long missingDays = ChronoUnit.DAYS.between(now, signatureValidTime); + + Map model = new HashMap<>(); + model.put(RECIPIENT_FIELD, recipient); + model.put(AUP_URL, aupUrl); + model.put(ORGANISATION_NAME, organisationName); + model.put("missingDays", missingDays); + + String subject = "AUP signature reminder"; + + IamEmailNotification notification = createMessage("signAupReminder.ftl", model, + IamNotificationType.AUP_REMINDER, subject, asList(account.getUserInfo().getEmail())); + + LOG.debug("Created reminder message for signing the account {} AUP. Signing URL: {}", + account.getUuid(), aupUrl); + + return notification; + } + + @Override + public IamEmailNotification createAupSignatureExpMessage(IamAccount account) { + String recipient = account.getUserInfo().getName(); + String aupUrl = String.format(AUP_PATH, baseUrl); + + Map model = new HashMap<>(); + model.put(RECIPIENT_FIELD, recipient); + model.put(AUP_URL, aupUrl); + model.put(ORGANISATION_NAME, organisationName); + + String subject = "AUP signature expiration"; + + IamEmailNotification notification = createMessage("aupExpirationMessage.ftl", model, + IamNotificationType.AUP_EXPIRATION, subject, asList(account.getUserInfo().getEmail())); + + LOG.debug("Created AUP expiration message for the account {}. AUP signing URL: {}", + account.getUuid(), aupUrl); + + return notification; + + } + + @Override + public IamEmailNotification createAupSignatureRequestMessage(IamAccount account) { + String recipient = account.getUserInfo().getName(); + String aupUrl = String.format(AUP_PATH, baseUrl); + + Map model = new HashMap<>(); + model.put(RECIPIENT_FIELD, recipient); + model.put(AUP_URL, aupUrl); + model.put(ORGANISATION_NAME, organisationName); + + String subject = "AUP signature request"; + + IamEmailNotification notification = + createMessage("aupSignatureRequest.ftl", model, IamNotificationType.AUP_SIGNATURE_REQUEST, + subject, asList(account.getUserInfo().getEmail())); + + LOG.debug("Created AUP signature request message for the account {}. AUP signing URL: {}", + account.getUuid(), aupUrl); + + return notification; + } + + @Override + public IamEmailNotification createAccountSuspendedMessage(IamAccount account) { + String recipient = account.getUserInfo().getName(); + + Map model = new HashMap<>(); + model.put(RECIPIENT_FIELD, recipient); + model.put(ORGANISATION_NAME, organisationName); + + String subject = "Account suspended"; + + IamEmailNotification notification = createMessage("accountSuspended.ftl", model, + IamNotificationType.ACCOUNT_SUSPENDED, subject, asList(account.getUserInfo().getEmail())); + + LOG.debug("Created suspension message for the account {}", account.getUuid()); + + return notification; + } + + @Override + public IamEmailNotification createAccountRestoredMessage(IamAccount account) { + String recipient = account.getUserInfo().getName(); + + Map model = new HashMap<>(); + model.put(RECIPIENT_FIELD, recipient); + model.put(ORGANISATION_NAME, organisationName); + + String subject = "Account restored"; + + IamEmailNotification notification = createMessage("accountRestored.ftl", model, + IamNotificationType.ACCOUNT_RESTORED, subject, asList(account.getUserInfo().getEmail())); + + LOG.debug("Created restoration message for the account {}", account.getUuid()); + + return notification; + + } + protected IamEmailNotification createMessage(String templateName, Map model, IamNotificationType messageType, String subject, List receiverAddress) { try { + String formattedSubject = String.format("[%s IAM] %s", organisationName, subject); Template template = freeMarkerConfiguration.getTemplate(templateName); String body = FreeMarkerTemplateUtils.processTemplateIntoString(template, model); @@ -260,13 +418,13 @@ protected IamEmailNotification createMessage(String templateName, Map IamNotificationReceiver.forAddress(message, a)) - .collect(Collectors.toList())); + .map(a -> IamNotificationReceiver.forAddress(message, a)) + .collect(Collectors.toList())); return message; } catch (IOException | TemplateException e) { diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/registration/RegistrationApiController.java b/iam-login-service/src/main/java/it/infn/mw/iam/registration/RegistrationApiController.java index abe92b7f2..c6372506b 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/registration/RegistrationApiController.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/registration/RegistrationApiController.java @@ -19,6 +19,7 @@ import java.util.Optional; import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +34,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; -import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -45,7 +45,10 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; +import com.fasterxml.jackson.annotation.JsonView; + import it.infn.mw.iam.api.common.ErrorDTO; +import it.infn.mw.iam.api.common.RegistrationViews; import it.infn.mw.iam.api.scim.exception.ScimResourceNotFoundException; import it.infn.mw.iam.authn.AbstractExternalAuthenticationToken; import it.infn.mw.iam.authn.ExternalAuthenticationRegistrationInfo; @@ -93,8 +96,6 @@ private Optional getExternalAuthenticati return Optional.empty(); } - - @PreAuthorize("#iam.hasScope('registration:read') or hasRole('ADMIN')") @RequestMapping(value = "/registration/list", method = RequestMethod.GET) @ResponseBody @@ -115,10 +116,11 @@ public List listPendingRequests() { @RequestMapping(value = "/registration/create", method = RequestMethod.POST, consumes = "application/json") public RegistrationRequestDto createRegistrationRequest( - @RequestBody @Validated RegistrationRequestDto request, final BindingResult validationResult) { + @Valid @RequestBody @JsonView( + value = RegistrationViews.RegistrationDetail.class) RegistrationRequestDto request, + final BindingResult validationResult) { handleValidationError(validationResult); return service.createRequest(request, getExternalAuthenticationInfo()); - } @PreAuthorize("#iam.hasScope('registration:write') or hasRole('ADMIN')") @@ -135,7 +137,6 @@ public RegistrationRequestDto rejectRequest(@PathVariable("uuid") String uuid, return service.rejectRequest(uuid, Optional.ofNullable(motivation)); } - @RequestMapping(value = "/registration/confirm/{token}", method = RequestMethod.GET) public RegistrationRequestDto confirmRequest(@PathVariable("token") String token) { @@ -159,12 +160,13 @@ public ModelAndView verify(final Model model, @PathVariable("token") String toke } @RequestMapping(value = "/registration/insufficient-auth", method = RequestMethod.GET) - public ModelAndView insufficientAuth(final Model model, final HttpServletRequest request, final Authentication auth) { - + public ModelAndView insufficientAuth(final Model model, final HttpServletRequest request, + final Authentication auth) { + if (auth.isAuthenticated() && auth.getAuthorities().contains(USER_AUTHORITY)) { return new ModelAndView("redirect:/dashboard"); } - + model.addAttribute("authError", request.getAttribute("authError")); return new ModelAndView("iam/insufficient-auth"); } @@ -189,7 +191,7 @@ public ErrorDTO handleValidationError(RegistrationRequestValidatorError e) { private void handleValidationError(BindingResult result) { if (result.hasErrors()) { throw new RegistrationRequestValidatorError( - format(INVALID_REGISTRATION_TEMPLATE, stringifyValidationError(result))); + format(INVALID_REGISTRATION_TEMPLATE, stringifyValidationError(result))); } } } diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/registration/RegistrationRequestDto.java b/iam-login-service/src/main/java/it/infn/mw/iam/registration/RegistrationRequestDto.java index 489ea32f3..54519ca37 100644 --- a/iam-login-service/src/main/java/it/infn/mw/iam/registration/RegistrationRequestDto.java +++ b/iam-login-service/src/main/java/it/infn/mw/iam/registration/RegistrationRequestDto.java @@ -15,50 +15,105 @@ */ package it.infn.mw.iam.registration; +import static it.infn.mw.iam.util.RegexUtil.PASSWORD_REGEX; +import static it.infn.mw.iam.util.RegexUtil.PASSWORD_REGEX_MESSAGE_ERROR; + import java.util.Date; import java.util.List; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; +import javax.validation.constraints.NotEmpty; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; - +import com.fasterxml.jackson.annotation.JsonView; +import it.infn.mw.iam.api.client.management.validation.OnRegistrationCreation; import it.infn.mw.iam.api.common.LabelDTO; +import it.infn.mw.iam.api.common.RegistrationViews; import it.infn.mw.iam.registration.validation.UsernameRegExp; @JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonView({RegistrationViews.RegistrationExtendDetail.class, + RegistrationViews.RegistrationDetail.class}) public class RegistrationRequestDto { + @JsonView(RegistrationViews.RegistrationExtendDetail.class) private String uuid; + + @JsonView(RegistrationViews.RegistrationExtendDetail.class) private Date creationTime; + + @JsonView(RegistrationViews.RegistrationExtendDetail.class) private String status; + + @JsonView(RegistrationViews.RegistrationExtendDetail.class) private Date lastUpdateTime; - @Size(max = 32, message = "username cannot be longer than 32 chars") + + @JsonView({RegistrationViews.RegistrationExtendDetail.class, + RegistrationViews.RegistrationDetail.class}) + @Size(min = 2, max = 32, + message = "username cannot be longer than 32 chars and less than 2 chars") @UsernameRegExp private String username; + + @JsonView(RegistrationViews.RegistrationExtendDetail.class) + @Pattern(regexp = PASSWORD_REGEX, message = PASSWORD_REGEX_MESSAGE_ERROR, + groups = {OnRegistrationCreation.class}) + @Size(min = 8, message = "password should have at least 8 characters") private String password; + + @JsonView({RegistrationViews.RegistrationExtendDetail.class, + RegistrationViews.RegistrationDetail.class}) + @Size(min = 2, max = 128, groups = {OnRegistrationCreation.class}) + @NotBlank(message = "givenname cannot be blank") private String givenname; + + @JsonView({RegistrationViews.RegistrationExtendDetail.class, + RegistrationViews.RegistrationDetail.class}) + @Size(min = 2, max = 128, groups = {OnRegistrationCreation.class}) + @NotBlank(message = "familyname cannot be blank") private String familyname; + + @JsonView({RegistrationViews.RegistrationExtendDetail.class, + RegistrationViews.RegistrationDetail.class}) + @Email(message = "must be a valid email address") + @NotEmpty() private String email; + + @JsonView(RegistrationViews.RegistrationExtendDetail.class) private String birthdate; + + @JsonView(RegistrationViews.RegistrationExtendDetail.class) private String accountId; + + @JsonView({RegistrationViews.RegistrationExtendDetail.class, + RegistrationViews.RegistrationDetail.class}) + @NotEmpty(message = "notes cannot be empty") private String notes; + @JsonView({RegistrationViews.RegistrationExtendDetail.class, + RegistrationViews.RegistrationDetail.class}) private List labels; public RegistrationRequestDto() {} @JsonCreator - public RegistrationRequestDto(@JsonProperty("uuid") String uuid, - @JsonProperty("creationdate") Date creationTime, @JsonProperty("status") String status, - @JsonProperty("lastupdatetime") Date lastUpdateTime, - @JsonProperty("username") String username, @JsonProperty("password") String password, - @JsonProperty("givename") String givenname, @JsonProperty("familyname") String familyname, - @JsonProperty("email") String email, @JsonProperty("birthdate") String birthdate, - @JsonProperty("accountid") String accountId, @JsonProperty("notes") String notes, + public RegistrationRequestDto(@JsonProperty(value = "username", required = true) String username, + @JsonProperty(value = "givenname", required = true) String givenname, + @JsonProperty(value = "familyname", required = true) String familyname, + @JsonProperty(value = "email", required = true) String email, + @JsonProperty("notes") String notes, @JsonProperty("password") String password, + @JsonProperty("uuid") String uuid, @JsonProperty("birthdate") String birthdate, + @JsonProperty("accountId") String accountId, @JsonProperty("creationTime") Date creationTime, + @JsonProperty("status") String status, @JsonProperty("lastUpdateTime") Date lastUpdateTime, @JsonProperty("labels") List labels) { - + super(); this.username = username; this.password = password; this.givenname = givenname; diff --git a/iam-login-service/src/main/java/it/infn/mw/iam/util/RegexUtil.java b/iam-login-service/src/main/java/it/infn/mw/iam/util/RegexUtil.java new file mode 100644 index 000000000..9e09d040e --- /dev/null +++ b/iam-login-service/src/main/java/it/infn/mw/iam/util/RegexUtil.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.util; + +public final class RegexUtil { + + private RegexUtil() {} + + // Regex matches password with at least one lowercase letter, one uppercase + // letter, one number, one symbol and minimum length of 8 characters + public static final String PASSWORD_REGEX = + "^(?=.*[\\p{Lower}])(?=.*[\\p{Upper}])(?=.*[\\p{Digit}])(?=.*[\\p{Punct}]).{8,}([^\\r\\t\\v\\f\\n]+)$"; + public static final String PASSWORD_REGEX_MESSAGE_ERROR = + "The password must include at least one uppercase letter, one lowercase letter, one number, one symbol (e.g., @$!%*?&) and must contain at least 8 characters for greater security."; +} diff --git a/iam-login-service/src/main/resources/application-redis-test.yml b/iam-login-service/src/main/resources/application-redis-test.yml index 9a5b06f54..6fad69368 100644 --- a/iam-login-service/src/main/resources/application-redis-test.yml +++ b/iam-login-service/src/main/resources/application-redis-test.yml @@ -25,5 +25,6 @@ spring: flush-mode: immediate namespace: iam:session -redis-cache: - enabled: true \ No newline at end of file +cache: + redis: + enabled: true \ No newline at end of file diff --git a/iam-login-service/src/main/resources/application.yml b/iam-login-service/src/main/resources/application.yml index 67f4baa26..76083b81d 100644 --- a/iam-login-service/src/main/resources/application.yml +++ b/iam-login-service/src/main/resources/application.yml @@ -188,8 +188,13 @@ iam: section-to-be-displayed-first: ${IAM_LOGIN_PAGE_LAYOUT_SECTION_TO_DISPLAY_FIRST:LOGIN_FORM} external-authn-order: ${IAM_LOGIN_EXTERNAL_AUTHN_ORDER:x509,oidc,saml} -redis-cache: - enabled: ${IAM_REDIS_CACHE_ENABLED:false} + client: + track-last-used: ${IAM_CLIENT_TRACK_LAST_USED:false} + +cache: + enabled: ${IAM_CACHE_ENABLED:true} + redis: + enabled: ${IAM_CACHE_REDIS_ENABLED:false} x509: trustAnchorsDir: ${IAM_X509_TRUST_ANCHORS_DIR:/etc/grid-security/certificates} @@ -221,13 +226,10 @@ client-registration: allow-for: ${IAM_CLIENT_REGISTRATION_ALLOW_FOR:ANYONE} enable: ${IAM_CLIENT_REGISTRATION_ENABLE:true} client-defaults: - default-access-token-validity-seconds: ${DEFAULT_ACCESS_TOKEN_VALIDITY_SECONDS:3600} - default-device-code-validity-seconds: ${DEFAULT_DEVICE_CODE_VALIDITY_SECONDS:600} - default-id-token-validity-seconds: ${DEFAULT_ID_TOKEN_VALIDITY_SECONDS:600} - default-refresh-token-validity-seconds: ${DEFAULT_REFRESH_TOKEN_VALIDITY_SECONDS:2592000} - -client: - track-last-used: ${IAM_CLIENT_TRACK_LAST_USED:true} + default-access-token-validity-seconds: ${IAM_DEFAULT_ACCESS_TOKEN_VALIDITY_SECONDS:3600} + default-device-code-validity-seconds: ${IAM_DEFAULT_DEVICE_CODE_VALIDITY_SECONDS:600} + default-id-token-validity-seconds: ${IAM_DEFAULT_ID_TOKEN_VALIDITY_SECONDS:600} + default-refresh-token-validity-seconds: ${IAM_DEFAULT_REFRESH_TOKEN_VALIDITY_SECONDS:2592000} management: health: diff --git a/iam-login-service/src/main/resources/email-templates/accountRestored.ftl b/iam-login-service/src/main/resources/email-templates/accountRestored.ftl new file mode 100644 index 000000000..1656dc8a9 --- /dev/null +++ b/iam-login-service/src/main/resources/email-templates/accountRestored.ftl @@ -0,0 +1,7 @@ +Dear ${recipient}, + +this mail is to inform that your account in ${organisationName} has been restored. + +You will be able to obtain JWT tokens/VOMS credentials again. + +The ${organisationName} registration service diff --git a/iam-login-service/src/main/resources/email-templates/accountSuspended.ftl b/iam-login-service/src/main/resources/email-templates/accountSuspended.ftl new file mode 100644 index 000000000..117a9217b --- /dev/null +++ b/iam-login-service/src/main/resources/email-templates/accountSuspended.ftl @@ -0,0 +1,9 @@ +Dear ${recipient}, + +this mail is to inform that your account in ${organisationName} has been suspended. + +You will not be able to obtain JWT tokens/VOMS credentials anymore. + +Please contact administrators for any questions. + +The ${organisationName} registration service diff --git a/iam-login-service/src/main/resources/email-templates/aupExpirationMessage.ftl b/iam-login-service/src/main/resources/email-templates/aupExpirationMessage.ftl new file mode 100644 index 000000000..9670b6184 --- /dev/null +++ b/iam-login-service/src/main/resources/email-templates/aupExpirationMessage.ftl @@ -0,0 +1,12 @@ +Dear ${recipient}, + +you failed to sign the Acceptable Usage Policy (AUP) in time. + +You will NOT be able to obtain JWT tokens/VOMS credentials +for the ${organisationName} organization until you explicitly accept the AUP. + +To sign the AUP, point your browser to the following URL: + +${aupUrl} + +The ${organisationName} registration service diff --git a/iam-login-service/src/main/resources/email-templates/aupSignatureRequest.ftl b/iam-login-service/src/main/resources/email-templates/aupSignatureRequest.ftl new file mode 100644 index 000000000..d8840c63d --- /dev/null +++ b/iam-login-service/src/main/resources/email-templates/aupSignatureRequest.ftl @@ -0,0 +1,9 @@ +Dear ${recipient}, + +an administrator requested that you re-sign the Acceptable Usage Policy (AUP). + +To sign the AUP, point your browser to the following URL: + +${aupUrl} + +The ${organisationName} registration service diff --git a/iam-login-service/src/main/resources/email-templates/clientStatusChanged.ftl b/iam-login-service/src/main/resources/email-templates/clientStatusChanged.ftl new file mode 100644 index 000000000..995e42329 --- /dev/null +++ b/iam-login-service/src/main/resources/email-templates/clientStatusChanged.ftl @@ -0,0 +1,5 @@ +Dear user, + +this mail is to inform you that client ${clientName} with id ${clientId} has been <#if isClientActive>ACTIVATED<#else>SUSPENDED. + +The ${organisationName} registration service \ No newline at end of file diff --git a/iam-login-service/src/main/resources/email-templates/signAupReminder.ftl b/iam-login-service/src/main/resources/email-templates/signAupReminder.ftl new file mode 100644 index 000000000..f5c387743 --- /dev/null +++ b/iam-login-service/src/main/resources/email-templates/signAupReminder.ftl @@ -0,0 +1,15 @@ +Dear ${recipient}, + +we kindly remind you to sign the Acceptable Usage Policy (AUP). + +The AUP will expire in ${missingDays} days. + +After this date you will NOT be able to obtain JWT tokens/VOMS credentials +for the ${organisationName} organization. + +Note, however, that you can sign the AUP at *any* time +by simply pointing your browser to the following URL: + +${aupUrl} + +The ${organisationName} registration service diff --git a/iam-login-service/src/main/webapp/WEB-INF/views/iam/dashboard.jsp b/iam-login-service/src/main/webapp/WEB-INF/views/iam/dashboard.jsp index 4886e366f..03ca0827e 100644 --- a/iam-login-service/src/main/webapp/WEB-INF/views/iam/dashboard.jsp +++ b/iam-login-service/src/main/webapp/WEB-INF/views/iam/dashboard.jsp @@ -78,6 +78,7 @@ + diff --git a/iam-login-service/src/main/webapp/WEB-INF/views/iam/login.jsp b/iam-login-service/src/main/webapp/WEB-INF/views/iam/login.jsp index 282d80157..64934b085 100644 --- a/iam-login-service/src/main/webapp/WEB-INF/views/iam/login.jsp +++ b/iam-login-service/src/main/webapp/WEB-INF/views/iam/login.jsp @@ -48,7 +48,6 @@
External authentication error -
${param.externalAuthenticationError}
diff --git a/iam-login-service/src/main/webapp/WEB-INF/views/iam/resetPassword.jsp b/iam-login-service/src/main/webapp/WEB-INF/views/iam/resetPassword.jsp index 80c022c27..7e8c40f27 100644 --- a/iam-login-service/src/main/webapp/WEB-INF/views/iam/resetPassword.jsp +++ b/iam-login-service/src/main/webapp/WEB-INF/views/iam/resetPassword.jsp @@ -27,76 +27,88 @@ + - - -
-
Error: ${errorMessage}
-
-
- - -
-

- Set your password -

-

- Your password has been reset successfully! -

+ + +
+
Error: ${errorMessage}
+
+
+ +
+

+ Set your password +

+

+ Your password has been reset successfully! +

-
-
- {{ctrl.textAlert}} -
- - +
+
+ {{ctrl.textAlert}}
- -
- - + Back to Login Page +
+
+ + + + - -
-
+
- - Please provide a password - The password must be at least 6 characters long -
+ + Your password + must be strong and meet the following criteria: +
    +
  • At least 8 characters long
  • +
  • Include at least one uppercase letter
  • +
  • Include at least one lowercase letter
  • +
  • Include at least one number
  • +
  • Include at least one special character (e.g., @$!%*?&)
  • +
+
+ Please + provide a password
- -
-
+ +
+
- - Please confirm your password - Passwords do not match -
+ + Please + confirm your password + + Passwords do not match
- -
-
- + +
+
+ -
- -
- - - +
+ +
+ + + \ No newline at end of file diff --git a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.component.html b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.component.html index 0980bae8a..b6d4ee8b1 100644 --- a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.component.html +++ b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.component.html @@ -67,6 +67,15 @@

If set to zero, the AUP signature will be asked only at registration time.

+
+ +

+ {{$ctrl.aup.data.aupRemindersInDays}} +

+ + Indicate a sequence of three days representing how many days before the AUP expiration reminder messages must be sent. + +
diff --git a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.component.js b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.component.js index 22836b6a7..e55a0823d 100644 --- a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.component.js +++ b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.component.js @@ -73,7 +73,8 @@ self.reset = function() { self.aupVal = { url: self.aup.url, - signatureValidityInDays: self.aup.signatureValidityInDays + signatureValidityInDays: self.aup.signatureValidityInDays, + aupRemindersInDays: self.aup.aupRemindersInDays }; }; @@ -104,7 +105,8 @@ self.reset = function() { self.aupVal = { url: "", - signatureValidityInDays: 0 + signatureValidityInDays: 0, + aupRemindersInDays: "30,15,1" }; }; diff --git a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.create.dialog.html b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.create.dialog.html index c0cc0ac8e..a436247a0 100644 --- a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.create.dialog.html +++ b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/aup/aup.create.dialog.html @@ -45,10 +45,20 @@
+
+ + + + Indicate a sequence of comma-separated numbers representing how many days before the AUP expiration reminder messages must be sent. + + + Required input + +
+
+ + + + Indicate a sequence of comma-separated numbers representing how many days before the AUP expiration reminder messages must be sent. + + + Required input + +

Editing the AUP will not trigger an AUP signature diff --git a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/clients/clientslist/clientslist.component.html b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/clients/clientslist/clientslist.component.html index fb7426469..374f5efc2 100644 --- a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/clients/clientslist/clientslist.component.html +++ b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/components/clients/clientslist/clientslist.component.html @@ -77,7 +77,9 @@ Client name & id Created Dyn. registered - Last Used + Last Used + Information Actions diff --git a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/controllers/edit-password.controller.js b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/controllers/edit-password.controller.js index f5fb09fb3..e35a46eef 100644 --- a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/controllers/edit-password.controller.js +++ b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/controllers/edit-password.controller.js @@ -21,14 +21,14 @@ EditPasswordController.$inject = [ '$scope', '$state', '$uibModalInstance', 'Utils', 'ResetPasswordService', - 'user' + 'user','toaster' ]; function EditPasswordController( - $scope, $state, $uibModalInstance, Utils, ResetPasswordService, user) { + $scope, $state, $uibModalInstance, Utils, ResetPasswordService, user, toaster) { var editPasswordCtrl = this; - editPasswordCtrl.passwordMinlength = 6; + editPasswordCtrl.passwordMinlength = 8; editPasswordCtrl.userToEdit = user; editPasswordCtrl.dismiss = dismiss; @@ -63,7 +63,8 @@ editPasswordCtrl.user.password) .then(function() { return $uibModalInstance.close('Password updated'); }) .catch(function(error) { - console.error(error); + console.error(error.data); + toaster.pop({ type: 'error', body: error.data }); $scope.operationResult = Utils.buildErrorResult(error.data); }); }; diff --git a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/directives/password.directive.js b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/directives/password.directive.js new file mode 100644 index 000000000..efb613b00 --- /dev/null +++ b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/directives/password.directive.js @@ -0,0 +1,30 @@ +/* + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +angular.module('dashboardApp').directive('strongPassword', function () { + return { + require: 'ngModel', + link: function (scope, element, attrs, ngModel) { + ngModel.$parsers.unshift(function (viewValue) { + var passwordStrengthRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[(!"#$%&'()*+,-./:;<=>?@[\]\^ `{|}~)])([^\r\t\v\f\n]+).{8,}$/; + var isStrong = passwordStrengthRegex.test(viewValue); + + ngModel.$setValidity('strongPassword', isStrong); + + return viewValue; + }); + } + }; +}); \ No newline at end of file diff --git a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/services/passwordreset.service.js b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/services/passwordreset.service.js index bbe682a0b..4b937cbfb 100644 --- a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/services/passwordreset.service.js +++ b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/services/passwordreset.service.js @@ -19,66 +19,64 @@ angular.module('dashboardApp').factory('ResetPasswordService', ResetPasswordServ ResetPasswordService.$inject = ['$http', '$httpParamSerializerJQLike']; -function ResetPasswordService($http, $httpParamSerializerJQLike){ - +function ResetPasswordService($http, $httpParamSerializerJQLike) { + var service = { - forgotPassword : forgotPassword, - changePassword : changePassword, - updatePassword : updatePassword + forgotPassword: forgotPassword, + changePassword: changePassword, + updatePassword: updatePassword }; - + return service; - - function forgotPassword(email){ - + + function forgotPassword(email) { + var data = $httpParamSerializerJQLike({ - email: email + email: email }); - + var config = { - headers : { - 'Content-Type' : 'application/x-www-form-urlencoded' + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' } - } - + } + return $http.post('/iam/password-reset/token', data, config); - + }; - - function changePassword(resetKey, newPassword){ - var data = $httpParamSerializerJQLike({ - token : resetKey, - password : newPassword - }); - + + function changePassword(resetKey, newPassword) { + var body = JSON.stringify({ "updatedPassword": newPassword, "token": resetKey, }); + var config = { - headers : { - 'Content-Type': 'application/x-www-form-urlencoded' + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' } } - - return $http.post('/iam/password-reset', data, config); + + return $http.post('/iam/password-reset', body, config); } - function updatePassword(oldPassword, newPassword){ + function updatePassword(oldPassword, newPassword) { var config = { - headers : { - 'Accept' : 'text/plain', + headers: { + 'Accept': 'text/plain', 'Content-Type': 'application/x-www-form-urlencoded' }, - transformRequest: function(obj) { - var str = []; - for(var p in obj) - str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); - return str.join("&"); - } + transformRequest: function (obj) { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); + return str.join("&"); + } }; var data = { - 'currentPassword' : oldPassword, - 'updatedPassword' : newPassword - }; + 'currentPassword': oldPassword, + 'updatedPassword': newPassword + }; return $http.post('/iam/password-update', data, config); } } \ No newline at end of file diff --git a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/templates/home/editpassword.html b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/templates/home/editpassword.html index 6480ac737..262ca09bc 100644 --- a/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/templates/home/editpassword.html +++ b/iam-login-service/src/main/webapp/resources/iam/apps/dashboard-app/templates/home/editpassword.html @@ -27,40 +27,79 @@

-
- - - This is a required field +
+ + + This is + a required field
-
- - - This is a required field - Minimum length required is {{editPasswordCtrl.passwordMinlength}} +
+ + + This is a required + field + Your password must be strong and meet the following criteria: +
    +
  • At least 8 characters long
  • +
  • Include at least one uppercase letter
  • +
  • Include at least one lowercase letter
  • +
  • Include at least one number
  • +
  • Include at least one special character (e.g., @$!%*?&)
  • +
+
+ Minimum length + required is {{editPasswordCtrl.passwordMinlength}}
-
- - - This is a required field - Minimum length required is {{editPasswordCtrl.passwordMinlength}} - Must match the previous entry +
+ + + This is + a required field + Minimum + length required is {{editPasswordCtrl.passwordMinlength}} + Must + match the previous entry
- + \ No newline at end of file diff --git a/iam-login-service/src/main/webapp/resources/iam/js/directive/password.directive.js b/iam-login-service/src/main/webapp/resources/iam/js/directive/password.directive.js new file mode 100644 index 000000000..b949da8a8 --- /dev/null +++ b/iam-login-service/src/main/webapp/resources/iam/js/directive/password.directive.js @@ -0,0 +1,28 @@ +/* + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +angular.module('passwordResetApp').directive('strongPassword', function () { + return { + require: 'ngModel', + link: function (scope, element, attrs, ngModel) { + ngModel.$parsers.unshift(function (viewValue) { + var passwordStrengthRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!"#$%&'()*+,-./:;<=>?@[\]\^ `{|}~]).{8,}([^\r\t\v\f\n]+)$/; + var isStrong = passwordStrengthRegex.test(viewValue); + ngModel.$setValidity('strongPassword', isStrong); + return viewValue; + }); + } + }; +}); \ No newline at end of file diff --git a/iam-login-service/src/main/webapp/resources/iam/js/service/passwordreset.service.js b/iam-login-service/src/main/webapp/resources/iam/js/service/passwordreset.service.js index 81e539767..6c22b5d22 100644 --- a/iam-login-service/src/main/webapp/resources/iam/js/service/passwordreset.service.js +++ b/iam-login-service/src/main/webapp/resources/iam/js/service/passwordreset.service.js @@ -19,43 +19,42 @@ angular.module('passwordResetApp').factory('ResetPasswordService', ResetPassword ResetPasswordService.$inject = ['$http', '$httpParamSerializerJQLike']; -function ResetPasswordService($http, $httpParamSerializerJQLike){ - +function ResetPasswordService($http, $httpParamSerializerJQLike) { + var service = { - forgotPassword : forgotPassword, - changePassword : changePassword, + forgotPassword: forgotPassword, + changePassword: changePassword, }; - + return service; - - function forgotPassword(email){ - + + function forgotPassword(email) { + var data = $httpParamSerializerJQLike({ - email: email + email: email }); - + var config = { - headers : { - 'Content-Type' : 'application/x-www-form-urlencoded' + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' } - } - + } + return $http.post('/iam/password-reset/token', data, config); - + }; - - function changePassword(resetKey, newPassword){ - var data = $httpParamSerializerJQLike({ - token : resetKey, - password : newPassword - }); - + + function changePassword(resetKey, newPassword) { + + var data = JSON.stringify({ "updatedPassword": newPassword, "token": resetKey }); + var config = { - headers : { - 'Content-Type': 'application/x-www-form-urlencoded' + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' } } - + return $http.post('/iam/password-reset', data, config); } } \ No newline at end of file diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/client/AccountClientEndpointTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/client/AccountClientEndpointTests.java new file mode 100644 index 000000000..e8da780e0 --- /dev/null +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/client/AccountClientEndpointTests.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.test.api.account.client; + +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Date; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.oauth2.model.ClientDetailsEntity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import it.infn.mw.iam.persistence.model.IamAccount; +import it.infn.mw.iam.persistence.model.IamAccountClient; +import it.infn.mw.iam.persistence.repository.IamAccountRepository; +import it.infn.mw.iam.persistence.repository.client.IamAccountClientRepository; +import it.infn.mw.iam.persistence.repository.client.IamClientRepository; +import it.infn.mw.iam.test.util.WithMockOAuthUser; +import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; +import it.infn.mw.iam.test.util.oauth.MockOAuth2Filter; + +@RunWith(SpringRunner.class) +@IamMockMvcIntegrationTest +public class AccountClientEndpointTests { + + @Autowired + private IamAccountRepository accountRepo; + + @Autowired + private IamAccountClientRepository accountClientRepo; + + @Autowired + private IamClientRepository clientRepo; + + @Autowired + private MockMvc mvc; + + @Autowired + private MockOAuth2Filter mockOAuth2Filter; + + @Before + public void setup() { + mockOAuth2Filter.cleanupSecurityContext(); + } + + @After + public void cleanupOAuthUser() { + mockOAuth2Filter.cleanupSecurityContext(); + } + + private ClientDetailsEntity buildNewClient(String clientId) { + ClientDetailsEntity entity = new ClientDetailsEntity(); + entity.setClientId(clientId); + entity.setActive(true); + entity.setClientName(clientId); + return clientRepo.save(entity); + } + + private IamAccountClient addNewClientFor(IamAccount a, ClientDetailsEntity c) { + IamAccountClient accountClient = new IamAccountClient(); + accountClient.setAccount(a); + accountClient.setClient(c); + accountClient.setCreationTime(new Date()); + return accountClientRepo.save(accountClient); + } + + private void getMyClientsWorksForAdmins() throws Exception { + mvc.perform(get("/iam/account/me/clients")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.Resources", is(empty()))); + + IamAccount admin = accountRepo.findByUsername("admin").orElseThrow(); + ClientDetailsEntity clientAdmin = buildNewClient("client-admin"); + IamAccountClient accountClientAdmin = addNewClientFor(admin, clientAdmin); + + mvc.perform(get("/iam/account/me/clients")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.totalResults", is(1))) + .andExpect(jsonPath("$.Resources", not(empty()))) + .andExpect(jsonPath("$.Resources[0].client_id", is("client-admin"))); + + IamAccount test = accountRepo.findByUsername("test").orElseThrow(); + ClientDetailsEntity clientTest = buildNewClient("client-test"); + IamAccountClient accountClientTest = addNewClientFor(test, clientTest); + + mvc.perform(get("/iam/account/me/clients")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.totalResults", is(1))) + .andExpect(jsonPath("$.Resources", not(empty()))) + .andExpect(jsonPath("$.Resources[0].client_id", is("client-admin"))); + + accountClientRepo.delete(accountClientAdmin); + accountClientRepo.delete(accountClientTest); + clientRepo.delete(clientAdmin); + clientRepo.delete(clientTest); + } + + + @Test + public void anonymousAccessToMyClientsEndpointFailsTest() throws Exception { + mvc.perform(get("/iam/account/me/clients")) + .andDo(print()) + .andExpect(status().isUnauthorized()); + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void myClientsWorksForAdminsTest() throws Exception { + getMyClientsWorksForAdmins(); + } + + @Test + @WithMockOAuthUser(scopes = {"iam.admin:read"}, user = "admin", authorities = {"ROLE_ADMIN", "ROLE_USER"}) + public void myClientsWorksForAdminsWithTokenAndScopeAdminTest() throws Exception { + getMyClientsWorksForAdmins(); + } + + @Test + @WithMockOAuthUser(user = "admin", authorities = {"ROLE_ADMIN", "ROLE_USER"}) + public void myClientsWorksForAdminsWithTokenTest() throws Exception { + getMyClientsWorksForAdmins(); + } + +} diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordEncodingTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordEncodingTests.java index 068e2dc15..257a58ea9 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordEncodingTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordEncodingTests.java @@ -36,6 +36,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; +import it.infn.mw.iam.api.account.password_reset.ResetPasswordDTO; import it.infn.mw.iam.persistence.model.IamAccount; import it.infn.mw.iam.persistence.repository.IamAccountRepository; import it.infn.mw.iam.registration.PersistentUUIDTokenGenerator; @@ -76,11 +77,35 @@ public void cleanupOAuthUser() { mockOAuth2Filter.cleanupSecurityContext(); } + @Test + public void testNoValidResetToken() throws Exception { + String username = "password_encoded"; + + RegistrationRequestDto request = new RegistrationRequestDto(); + request.setGivenname("Password encoded"); + request.setFamilyname("Test"); + request.setEmail("password_encoded@example.org"); + request.setUsername(username); + request.setNotes("Some short notes..."); + + mvc + .perform(post("/registration/create").contentType(MediaType.APPLICATION_JSON) + .content(mapper.writeValueAsString(request))) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + String confirmationKey = "NoValidToken"; + mvc.perform(get("/registration/confirm/{token}", confirmationKey).contentType(APPLICATION_JSON)) + .andExpect(status().isNotFound()); + + } @Test public void testPasswordEncoded() throws Exception { String username = "password_encoded"; - String newPassword = "secure_password"; + String newPassword = "Secure_P@ssw0rd!"; RegistrationRequestDto request = new RegistrationRequestDto(); request.setGivenname("Password encoded"); @@ -100,9 +125,7 @@ public void testPasswordEncoded() throws Exception { request = mapper.readValue(rs, RegistrationRequestDto.class); String confirmationKey = tokenGenerator.getLastToken(); - mvc - .perform(get("/registration/confirm/{token}", confirmationKey) - .contentType(APPLICATION_JSON)) + mvc.perform(get("/registration/confirm/{token}", confirmationKey).contentType(APPLICATION_JSON)) .andExpect(status().isOk()); mvc.perform(post("/registration/approve/{uuid}", request.getUuid()) @@ -111,19 +134,20 @@ public void testPasswordEncoded() throws Exception { String resetKey = tokenGenerator.getLastToken(); + ResetPasswordDTO dto = new ResetPasswordDTO(); + dto.setUpdatedPassword(newPassword); + dto.setToken(resetKey); + mvc - .perform(post("/iam/password-reset").param("token", resetKey) - .param("password", newPassword) + .perform(post("/iam/password-reset").content(mapper.writeValueAsString(dto)) .with(authentication(adminAuthentication())) .contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()); + .andExpect(MockMvcResultMatchers.status().isCreated()); IamAccount account = iamAccountRepository.findByUuid(request.getAccountId()) .orElseThrow(() -> new AssertionError("Expected account not found")); Assert.assertTrue(passwordEncoder.matches(newPassword, account.getPassword())); - - } } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordResetTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordResetTests.java index 7c489a1a2..bf4440b31 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordResetTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordResetTests.java @@ -15,6 +15,10 @@ */ package it.infn.mw.iam.test.api.account.password; +import static it.infn.mw.iam.util.RegexUtil.PASSWORD_REGEX_MESSAGE_ERROR; +import static java.lang.String.format; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -30,7 +34,14 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.JsonObject; + import it.infn.mw.iam.IamLoginService; +import it.infn.mw.iam.api.account.password_reset.ResetPasswordDTO; +import it.infn.mw.iam.api.common.error.NoSuchAccountError; +import it.infn.mw.iam.persistence.model.IamAccount; +import it.infn.mw.iam.persistence.repository.IamAccountRepository; import it.infn.mw.iam.registration.PersistentUUIDTokenGenerator; import it.infn.mw.iam.test.core.CoreControllerTestSupport; import it.infn.mw.iam.test.notification.NotificationTestConfig; @@ -39,7 +50,6 @@ import it.infn.mw.iam.test.util.notification.MockNotificationDelivery; import it.infn.mw.iam.test.util.oauth.MockOAuth2Filter; - @RunWith(SpringRunner.class) @IamMockMvcIntegrationTest @SpringBootTest(classes = {IamLoginService.class, NotificationTestConfig.class, @@ -47,7 +57,6 @@ @WithAnonymousUser public class PasswordResetTests { - @Autowired private PersistentUUIDTokenGenerator tokenGenerator; @@ -60,6 +69,12 @@ public class PasswordResetTests { @Autowired private MockMvc mvc; + @Autowired + private ObjectMapper mapper; + + @Autowired + private IamAccountRepository accountRepo; + @Before public void setup() { mockOAuth2Filter.cleanupSecurityContext(); @@ -75,7 +90,7 @@ public void tearDown() { public void testChangePassword() throws Exception { String testEmail = "test@iam.test"; - String newPassword = "secure_password"; + String newPassword = "Secure_P@ssw0rd!"; mvc.perform(post("/iam/password-reset/token").param("email", testEmail)) .andExpect(status().isOk()); @@ -84,14 +99,90 @@ public void testChangePassword() throws Exception { mvc.perform(head("/iam/password-reset/token/{token}", resetToken)).andExpect(status().isOk()); + ResetPasswordDTO request = new ResetPasswordDTO(); + request.setUpdatedPassword(newPassword); + request.setToken(resetToken); + mvc - .perform( - post("/iam/password-reset").param("token", resetToken).param("password", newPassword)) - .andExpect(status().isOk()); + .perform(post("/iam/password-reset").contentType(APPLICATION_JSON) + .content(mapper.writeValueAsString(request))) + .andExpect(status().isCreated()); mvc.perform(head("/iam/password-reset/token/{token}", resetToken)) .andExpect(status().isNotFound()); + } + + @Test + public void testChangePasswordWeak() throws Exception { + String testEmail = "test@iam.test"; + + String newPassword = "weakpassword"; + + mvc.perform(post("/iam/password-reset/token").param("email", testEmail)) + .andExpect(status().isOk()); + + String resetToken = tokenGenerator.getLastToken(); + + mvc.perform(head("/iam/password-reset/token/{token}", resetToken)).andExpect(status().isOk()); + + JsonObject jsonBody = new JsonObject(); + jsonBody.addProperty("updatedPassword", newPassword); + jsonBody.addProperty("token", resetToken); + + mvc + .perform( + post("/iam/password-reset").contentType(APPLICATION_JSON).content(jsonBody.toString())) + .andExpect(status().isBadRequest()) + .andExpect(MockMvcResultMatchers.content() + .string("Invalid reset password: [resetPasswordDTO.updatedPassword : " + + PASSWORD_REGEX_MESSAGE_ERROR + "]")); + } + + @Test + public void testChangePasswordWithTokenJustUsed() throws Exception { + String testEmail = "test@iam.test"; + String newPassword = "Secure_P@ssw0rd!"; + + mvc.perform(post("/iam/password-reset/token").param("email", testEmail)) + .andExpect(status().isOk()); + + String resetToken = tokenGenerator.getLastToken(); + + mvc.perform(head("/iam/password-reset/token/{token}", resetToken)).andExpect(status().isOk()); + + JsonObject jsonBody = new JsonObject(); + jsonBody.addProperty("updatedPassword", newPassword); + jsonBody.addProperty("token", resetToken); + + mvc + .perform( + post("/iam/password-reset").contentType(APPLICATION_JSON).content(jsonBody.toString())) + .andExpect(status().isCreated()); + + mvc + .perform( + post("/iam/password-reset").contentType(APPLICATION_JSON).content(jsonBody.toString())) + .andExpect(status().is4xxClientError()); + } + + @Test + public void testRedirectToResetPasswordPage() throws Exception { + String resetToken = tokenGenerator.getLastToken() + "
"; + mvc.perform(get("/iam/password-reset/token/{token}", resetToken)).andExpect(status().isOk()); + } + + @Test + public void testRedirectToResetPasswordPageWithValidResetKey() throws Exception { + String resetToken = tokenGenerator.generateToken(); + String testEmail = "test@iam.test"; + IamAccount account = accountRepo.findByEmail(testEmail) + .orElseThrow( + () -> new NoSuchAccountError(format("No account found for email '%s'", testEmail))); + account.setResetKey(resetToken); + accountRepo.save(account); + + mvc.perform(get("/iam/password-reset/token/{token}", resetToken)).andExpect(status().isOk()); } @Test @@ -99,28 +190,30 @@ public void testResetPasswordWithInvalidResetToken() throws Exception { String resetToken = "abcdefghilmnopqrstuvz"; - mvc.perform(head("/iam/password-reset/token/{token}", resetToken)).andExpect(status().isNotFound()); - + mvc.perform(head("/iam/password-reset/token/{token}", resetToken)) + .andExpect(status().isNotFound()); + } @Test public void testCreatePasswordResetTokenReturnsOkForUnknownAddress() throws Exception { String testEmail = "test@foo.bar"; - + mvc.perform(post("/iam/password-reset/token").param("email", testEmail)) - .andExpect(status().isOk()); + .andExpect(status().isOk()); } @Test public void testEmailValidationForPasswordResetTokenCreation() throws Exception { String invalidEmailAddress = "this_is_not_an_email"; - + mvc.perform(post("/iam/password-reset/token").param("email", invalidEmailAddress)) - .andExpect(status().isBadRequest()) - .andExpect(MockMvcResultMatchers.content().string("validation error: please specify a valid email address")); - + .andExpect(status().isBadRequest()) + .andExpect(MockMvcResultMatchers.content() + .string("validation error: please specify a valid email address")); + } } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordUpdateTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordUpdateTests.java index 12d0db259..7a5227358 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordUpdateTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/account/password/PasswordUpdateTests.java @@ -52,10 +52,8 @@ public class PasswordUpdateTests { private final String USER_USERNAME = "password_tester_user"; private final String USER_PASSWORD = "password"; - private final ScimName USER_NAME = - ScimName.builder().givenName("TESTER").familyName("USER").build(); - private final ScimEmail USER_EMAIL = - ScimEmail.builder().email("password_tester_user@test.org").build(); + private final ScimName USER_NAME = ScimName.builder().givenName("TESTER").familyName("USER").build(); + private final ScimEmail USER_EMAIL = ScimEmail.builder().email("password_tester_user@test.org").build(); @Autowired private ScimUserProvisioning userService; @@ -71,13 +69,13 @@ public static void init() { public void testSetup() { testUser = userService.create(ScimUser.builder() - .active(true) - .addEmail(USER_EMAIL) - .name(USER_NAME) - .displayName(USER_USERNAME) - .userName(USER_USERNAME) - .password(USER_PASSWORD) - .build()); + .active(true) + .addEmail(USER_EMAIL) + .name(USER_NAME) + .displayName(USER_USERNAME) + .userName(USER_USERNAME) + .password(USER_PASSWORD) + .build()); } @After @@ -90,88 +88,86 @@ private ValidatableResponse doPost(String accessToken, String currentPassword, String newPassword) { return RestAssured.given() - .port(iamPort) - .auth() - .preemptive() - .oauth2(accessToken) - .formParam(PasswordUpdateController.CURRENT_PASSWORD, currentPassword) - .formParam(PasswordUpdateController.UPDATED_PASSWORD, newPassword) - .log() - .all(true) - .when() - .post(PasswordUpdateController.BASE_URL) - .then() - .log() - .all(true); + .port(iamPort) + .auth() + .preemptive() + .oauth2(accessToken) + .formParam(PasswordUpdateController.CURRENT_PASSWORD, currentPassword) + .formParam(PasswordUpdateController.UPDATED_PASSWORD, newPassword) + .log() + .all(true) + .when() + .post(PasswordUpdateController.BASE_URL) + .then() + .log() + .all(true); } private ValidatableResponse doPost(String currentPassword, String newPassword) { return RestAssured.given() - .port(iamPort) - .formParam(PasswordUpdateController.CURRENT_PASSWORD, currentPassword) - .formParam(PasswordUpdateController.UPDATED_PASSWORD, newPassword) - .log() - .all(true) - .when() - .post(PasswordUpdateController.BASE_URL) - .then() - .log() - .all(true); + .port(iamPort) + .formParam(PasswordUpdateController.CURRENT_PASSWORD, currentPassword) + .formParam(PasswordUpdateController.UPDATED_PASSWORD, newPassword) + .log() + .all(true) + .when() + .post(PasswordUpdateController.BASE_URL) + .then() + .log() + .all(true); } @Test public void testUpdatePassword() { String currentPassword = "password"; - String newPassword = "secure_password"; - + String newPassword = "Secure_p@ssw0rd"; String accessToken = passwordTokenGetter().port(iamPort) - .username(testUser.getUserName()) - .password(currentPassword) - .getAccessToken(); + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.OK.value()); passwordTokenGetter().port(iamPort) - .username(testUser.getUserName()) - .password(newPassword) - .getAccessToken(); + .username(testUser.getUserName()) + .password(newPassword) + .getAccessToken(); } @Test public void testUpdatePasswordFullAuthenticationRequired() { String currentPassword = "password"; - String newPassword = "secure_password"; + String newPassword = "Secure_P@ssw0rd!"; doPost(currentPassword, newPassword).statusCode(HttpStatus.UNAUTHORIZED.value()) - .body("error", equalTo("unauthorized")) - .body("error_description", - equalTo("Full authentication is required to access this resource")); + .body("error", equalTo("unauthorized")) + .body("error_description", + equalTo("Full authentication is required to access this resource")); } @Test public void testUpdateWrongPasswordProvided() { String currentPassword = "password"; - String newPassword = "secure_password"; + String newPassword = "Secure_P@ssw0rd!"; String accessToken = passwordTokenGetter().port(iamPort) - .username(testUser.getUserName()) - .password(currentPassword) - .getAccessToken(); + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); doPost(accessToken, "thisisnotthecurrentpassword", newPassword) - .statusCode(HttpStatus.BAD_REQUEST.value()) - .body(equalTo("Wrong password provided")); + .statusCode(HttpStatus.BAD_REQUEST.value()); } @Test public void testUpdatePasswordForbiddenAccess() { String currentPassword = "password"; - String newPassword = "secure_password"; + String newPassword = "Secure_P@ssw0rd!"; String accessToken = TestUtils.clientCredentialsTokenGetter().port(iamPort).getAccessToken(); doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.FORBIDDEN.value()); @@ -183,12 +179,11 @@ public void testUpdatePasswordNullPasswordAccess() { String currentPassword = "password"; String newPassword = null; String accessToken = passwordTokenGetter().port(iamPort) - .username(testUser.getUserName()) - .password(currentPassword) - .getAccessToken(); + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); - doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()) - .body(containsString("The password cannot be empty")); + doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()); } @Test @@ -197,12 +192,11 @@ public void testUpdatePasswordEmptyPasswordAccess() { String currentPassword = "password"; String newPassword = ""; String accessToken = passwordTokenGetter().port(iamPort) - .username(testUser.getUserName()) - .password(currentPassword) - .getAccessToken(); + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); - doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()) - .body(containsString("The password cannot be empty")); + doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()); } @Test @@ -211,30 +205,68 @@ public void testUpdatePasswordTooShortPasswordAccess() { String currentPassword = "password"; String newPassword = "pass"; String accessToken = passwordTokenGetter().port(iamPort) - .username(testUser.getUserName()) - .password(currentPassword) - .getAccessToken(); + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); + + doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()); + } + + @Test + public void testUpdatePasswordWithWeakPasswordAccess() { + + String currentPassword = "password"; + String newPassword = "newweakpassword"; + String accessToken = passwordTokenGetter().port(iamPort) + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); + + doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()); + } + + @Test + public void testUpdatePasswordWithWeakPasswordWithoutSpecialChars() { + + String currentPassword = "password"; + String newPassword = "Password1"; + String accessToken = passwordTokenGetter().port(iamPort) + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); + + doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()); + } + + @Test + public void testUpdatePasswordWithWeakPasswordWithoutNumbers() { + + String currentPassword = "password"; + String newPassword = "Sjfyt-hdddW!"; + String accessToken = passwordTokenGetter().port(iamPort) + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); - doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()) - .body(containsString("The password must be at least 5 characters")); + doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.BAD_REQUEST.value()); } @Test public void testUpdatePasswordUserNotActive() throws Exception { String currentPassword = "password"; - String newPassword = "newPassword"; + String newPassword = "newP@ssw0rd"; String accessToken = passwordTokenGetter().port(iamPort) - .username(testUser.getUserName()) - .password(currentPassword) - .getAccessToken(); + .username(testUser.getUserName()) + .password(currentPassword) + .getAccessToken(); IamAccount account = accountRepository.findByUsername(testUser.getUserName()) - .orElseThrow(() -> new Exception("Test user not found")); + .orElseThrow(() -> new Exception("Test user not found")); account.setActive(false); accountRepository.save(account); doPost(accessToken, currentPassword, newPassword).statusCode(HttpStatus.CONFLICT.value()) - .body(containsString("Account is not active or email is not verified")); + .body(containsString("Account is not active or email is not verified")); } } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupIntegrationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupIntegrationTests.java index 2033f7b87..b6d891540 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupIntegrationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupIntegrationTests.java @@ -15,8 +15,8 @@ */ package it.infn.mw.iam.test.api.aup; -import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -125,7 +125,9 @@ public void aupIsReturnedIfDefined() throws Exception { @Test public void aupCreationRequiresAuthenticatedUser() throws JsonProcessingException, Exception { Date now = new Date(); - AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, DEFAULT_AUP_DESC, -1L, now, now); + String reminders = "1,15,30"; + AupDTO aup = + new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, DEFAULT_AUP_DESC, -1L, now, now, reminders); mvc .perform( @@ -138,7 +140,9 @@ public void aupCreationRequiresAuthenticatedUser() throws JsonProcessingExceptio @WithMockUser(username = "test", roles = {"USER"}) public void aupCreationRequiresAdminPrivileges() throws JsonProcessingException, Exception { Date now = new Date(); - AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, DEFAULT_AUP_DESC, -1L, now, now); + String reminders = "1,15,30"; + AupDTO aup = + new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, DEFAULT_AUP_DESC, -1L, now, now, reminders); mvc .perform( @@ -224,11 +228,11 @@ public void aupDescriptionNoLongerThan128Chars() throws JsonProcessingException, } - @Test @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) public void aupCreationRequiresSignatureValidityDays() throws JsonProcessingException, Exception { - AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, null, null, null); + String reminders = "1,15,30"; + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, null, null, null, reminders); Date now = new Date(); mockTimeProvider.setTime(now.getTime()); @@ -244,7 +248,8 @@ public void aupCreationRequiresSignatureValidityDays() throws JsonProcessingExce @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) public void aupCreationRequiresPositiveSignatureValidityDays() throws JsonProcessingException, Exception { - AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, -1L, null, null); + String reminders = "1,15,30"; + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, -1L, null, null, reminders); Date now = new Date(); mockTimeProvider.setTime(now.getTime()); @@ -255,6 +260,109 @@ public void aupCreationRequiresPositiveSignatureValidityDays() .andExpect(jsonPath("$.error").value("Invalid AUP: signatureValidityInDays must be >= 0")); } + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupCreationRequiresAupRemindersInDays() throws Exception { + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, 3L, null, null, null); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + mvc + .perform( + post("/iam/aup").contentType(APPLICATION_JSON).content(mapper.writeValueAsString(aup))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("Invalid AUP: aupRemindersInDays cannot be empty or null")); + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupCreationRequiresAupRemindersInDaysNotEmpty() throws Exception { + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, 3L, null, null, ""); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + mvc + .perform( + post("/iam/aup").contentType(APPLICATION_JSON).content(mapper.writeValueAsString(aup))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("Invalid AUP: aupRemindersInDays cannot be empty or null")); + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupCreationRequiresNoZeroInAupRemindersInDays() throws Exception { + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, 3L, null, null, "0"); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + mvc + .perform( + post("/iam/aup").contentType(APPLICATION_JSON).content(mapper.writeValueAsString(aup))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value( + "Invalid AUP: zero or negative values for reminders are not allowed")); + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupCreationRequiresPositiveAupRemindersInDays() throws Exception { + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, 3L, null, null, "-22"); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + mvc + .perform( + post("/iam/aup").contentType(APPLICATION_JSON).content(mapper.writeValueAsString(aup))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value( + "Invalid AUP: zero or negative values for reminders are not allowed")); + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupCreationRequiresNoLettersInAupRemindersInDays() throws Exception { + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, 3L, null, null, "ciao"); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + mvc + .perform( + post("/iam/aup").contentType(APPLICATION_JSON).content(mapper.writeValueAsString(aup))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value( + "Invalid AUP: non-integer value found")); + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupCreationRequiresNoDuplicationInAupRemindersInDays() throws Exception { + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, 31L, null, null, "30,15,15"); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + mvc + .perform( + post("/iam/aup").contentType(APPLICATION_JSON).content(mapper.writeValueAsString(aup))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value( + "Invalid AUP: duplicate values for reminders are not allowed")); + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupCreationRequiresAupRemindersInDaysSmallerThanAupExpirationDays() throws Exception { + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, 3L, null, null, "4"); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + mvc + .perform( + post("/iam/aup").contentType(APPLICATION_JSON).content(mapper.writeValueAsString(aup))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value( + "Invalid AUP: aupRemindersInDays must be smaller than signatureValidityInDays")); + } + @Test @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) public void aupCreationWorks() throws JsonProcessingException, Exception { @@ -285,6 +393,36 @@ public void aupCreationWorks() throws JsonProcessingException, Exception { assertThat(createdAup.getLastUpdateTime(), creationAndLastUpdateTimeMatcher); } + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void whiteSpacesAllowedAmongAupRemindersDays() throws Exception { + AupDTO aup = new AupDTO(DEFAULT_AUP_URL, DEFAULT_AUP_TEXT, null, 31L, null, null, " 30, 15, 7 "); + + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + mvc + .perform( + post("/iam/aup").contentType(APPLICATION_JSON).content(mapper.writeValueAsString(aup))) + .andExpect(status().isCreated()); + + + String aupJson = mvc.perform(get("/iam/aup")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + AupDTO createdAup = mapper.readValue(aupJson, AupDTO.class); + + DateEqualModulo1Second creationAndLastUpdateTimeMatcher = new DateEqualModulo1Second(now); + assertThat(createdAup.getUrl(), equalTo(aup.getUrl())); + assertThat(createdAup.getDescription(), equalTo(aup.getDescription())); + assertThat(createdAup.getSignatureValidityInDays(), equalTo(aup.getSignatureValidityInDays())); + assertThat(createdAup.getCreationTime(), creationAndLastUpdateTimeMatcher); + assertThat(createdAup.getLastUpdateTime(), creationAndLastUpdateTimeMatcher); + } + @Test @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) public void aupCreationFailsIfAupAlreadyDefined() throws JsonProcessingException, Exception { @@ -396,7 +534,7 @@ public void aupUpdateWorks() throws JsonProcessingException, Exception { aup.setUrl(UPDATED_AUP_URL); aup.setDescription(UPDATED_AUP_DESC); - aup.setSignatureValidityInDays(18L); + aup.setSignatureValidityInDays(31L); // Time travel 1 minute in the future Date then = new Date(now.getTime() + TimeUnit.MINUTES.toMillis(1)); @@ -416,7 +554,7 @@ public void aupUpdateWorks() throws JsonProcessingException, Exception { assertThat(updatedAup.getDescription(), equalTo(UPDATED_AUP_DESC)); assertThat(updatedAup.getCreationTime(), new DateEqualModulo1Second(now)); assertThat(updatedAup.getLastUpdateTime(), new DateEqualModulo1Second(now)); - assertThat(updatedAup.getSignatureValidityInDays(), equalTo(18L)); + assertThat(updatedAup.getSignatureValidityInDays(), equalTo(31L)); } } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupReminderTaskTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupReminderTaskTests.java new file mode 100644 index 000000000..367caa594 --- /dev/null +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupReminderTaskTests.java @@ -0,0 +1,227 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.test.api.aup; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import it.infn.mw.iam.IamLoginService; +import it.infn.mw.iam.core.web.aup.AupReminderTask; +import it.infn.mw.iam.persistence.model.IamAccount; +import it.infn.mw.iam.persistence.model.IamAup; +import it.infn.mw.iam.persistence.repository.IamAccountRepository; +import it.infn.mw.iam.persistence.repository.IamAupRepository; +import it.infn.mw.iam.persistence.repository.IamAupSignatureRepository; +import it.infn.mw.iam.persistence.repository.IamEmailNotificationRepository; +import it.infn.mw.iam.service.aup.DefaultAupSignatureCheckService; +import it.infn.mw.iam.test.core.CoreControllerTestSupport; +import it.infn.mw.iam.test.notification.NotificationTestConfig; +import it.infn.mw.iam.test.util.MockTimeProvider; +import it.infn.mw.iam.test.util.WithAnonymousUser; +import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; +import it.infn.mw.iam.test.util.notification.MockNotificationDelivery; + +@RunWith(SpringRunner.class) +@IamMockMvcIntegrationTest +@SpringBootTest(classes = {IamLoginService.class, CoreControllerTestSupport.class, + NotificationTestConfig.class}, webEnvironment = WebEnvironment.MOCK) +@WithAnonymousUser +@TestPropertySource(properties = {"notification.disable=false"}) +public class AupReminderTaskTests extends AupTestSupport { + + @Autowired + private DefaultAupSignatureCheckService service; + + @Autowired + private IamAccountRepository accountRepo; + + @Autowired + private IamAupSignatureRepository signatureRepo; + + @Autowired + private IamEmailNotificationRepository notificationRepo; + + @Autowired + private AupReminderTask aupReminderTask; + + @Autowired + private MockNotificationDelivery notificationDelivery; + + @Autowired + private IamAupRepository aupRepo; + + @Autowired + private MockTimeProvider mockTimeProvider; + + @After + public void tearDown() { + notificationDelivery.clearDeliveredNotifications(); + aupRepo.deleteAll(); + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupReminderEmailWorks() { + IamAup aup = buildDefaultAup(); + aup.setSignatureValidityInDays(30L); + aupRepo.save(aup); + + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + LocalDate today = LocalDate.now(); + LocalDate tomorrow = today.plusDays(1); + Date tomorrowDate = Date.from(tomorrow.atStartOfDay(ZoneId.systemDefault()).toInstant()); + + IamAccount testAccount = accountRepo.findByUsername("test") + .orElseThrow(() -> new AssertionError("Expected test account not found")); + + mockTimeProvider.setTime(now.getTime() + TimeUnit.MINUTES.toMillis(5)); + + assertThat(service.needsAupSignature(testAccount), is(true)); + + signatureRepo.createSignatureForAccount(aup, testAccount, + new Date(mockTimeProvider.currentTimeMillis())); + + assertThat(service.needsAupSignature(testAccount), is(false)); + + mockTimeProvider.setTime(now.getTime() + TimeUnit.MINUTES.toMillis(10)); + + assertThat(notificationRepo.countAupRemindersPerAccount(testAccount.getUserInfo().getEmail(), + tomorrowDate), equalTo(0)); + + aupReminderTask.sendAupReminders(); + notificationDelivery.sendPendingNotifications(); + assertThat(notificationRepo.countAupRemindersPerAccount(testAccount.getUserInfo().getEmail(), + tomorrowDate), equalTo(1)); + + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupExpirationEmailWorks() { + IamAup aup = buildDefaultAup(); + aup.setSignatureValidityInDays(2L); + + LocalDate today = LocalDate.now(); + LocalDate twoDaysAgo = today.minusDays(2); + + Date date = Date.from(twoDaysAgo.atStartOfDay(ZoneId.systemDefault()).toInstant()); + aup.setCreationTime(date); + aup.setLastUpdateTime(date); + + aupRepo.save(aup); + + IamAccount testAccount = accountRepo.findByUsername("test") + .orElseThrow(() -> new AssertionError("Expected test account not found")); + + signatureRepo.createSignatureForAccount(aup, testAccount, date); + + assertThat( + notificationRepo.countAupExpirationMessPerAccount(testAccount.getUserInfo().getEmail()), + equalTo(0)); + + aupReminderTask.sendAupReminders(); + notificationDelivery.sendPendingNotifications(); + assertThat( + notificationRepo.countAupExpirationMessPerAccount(testAccount.getUserInfo().getEmail()), + equalTo(1)); + + aupReminderTask.sendAupReminders(); + notificationDelivery.sendPendingNotifications(); + assertThat( + notificationRepo.countAupExpirationMessPerAccount(testAccount.getUserInfo().getEmail()), + equalTo(1)); + + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupExpirationEmailNotSentIfUserIsDisabled() { + IamAup aup = buildDefaultAup(); + aup.setSignatureValidityInDays(2L); + + LocalDate today = LocalDate.now(); + LocalDate twoDaysAgo = today.minusDays(2); + + Date date = Date.from(twoDaysAgo.atStartOfDay(ZoneId.systemDefault()).toInstant()); + aup.setCreationTime(date); + aup.setLastUpdateTime(date); + + aupRepo.save(aup); + + IamAccount testAccount = accountRepo.findByUsername("test") + .orElseThrow(() -> new AssertionError("Expected test account not found")); + + signatureRepo.createSignatureForAccount(aup, testAccount, date); + + assertThat( + notificationRepo.countAupExpirationMessPerAccount(testAccount.getUserInfo().getEmail()), + equalTo(0)); + + testAccount.setActive(false); + accountRepo.save(testAccount); + + aupReminderTask.sendAupReminders(); + notificationDelivery.sendPendingNotifications(); + assertThat( + notificationRepo.countAupExpirationMessPerAccount(testAccount.getUserInfo().getEmail()), + equalTo(0)); + + } + + @Test + @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) + public void aupExpirationEmailNotSentIfAupSignatureValidityIsZero() { + IamAup aup = buildDefaultAup(); + aup.setSignatureValidityInDays(0L); + + LocalDate today = LocalDate.now(); + Date date = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant()); + + aup.setCreationTime(date); + aup.setLastUpdateTime(date); + + aupRepo.save(aup); + + IamAccount testAccount = accountRepo.findByUsername("test") + .orElseThrow(() -> new AssertionError("Expected test account not found")); + + signatureRepo.createSignatureForAccount(aup, testAccount, date); + + aupReminderTask.sendAupReminders(); + notificationDelivery.sendPendingNotifications(); + assertThat( + notificationRepo.countAupExpirationMessPerAccount(testAccount.getUserInfo().getEmail()), + equalTo(0)); + + } +} diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureIntegrationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureIntegrationTests.java index 95af83605..67167bc02 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureIntegrationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupSignatureIntegrationTests.java @@ -55,6 +55,7 @@ import it.infn.mw.iam.test.util.DateEqualModulo1Second; import it.infn.mw.iam.test.util.MockTimeProvider; import it.infn.mw.iam.test.util.WithAnonymousUser; +import it.infn.mw.iam.test.util.WithMockOAuthUser; import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; import it.infn.mw.iam.test.util.oauth.MockOAuth2Filter; @@ -214,6 +215,38 @@ public void signatureOnBehalfWorks() throws Exception, NoSuchElementException { } + @Test + @WithMockOAuthUser(scopes = "iam:admin.write", clientId = "client-cred") + public void signatureOnBehalfWithClientCredentialsWorks() throws Exception, NoSuchElementException { + + IamAup aup = buildDefaultAup(); + aupRepo.save(aup); + IamAccount testAccount = accountRepo.findByUsername("test").orElseThrow(); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + Optional signature = + aupSignatureRepo.findSignatureForAccount(aup, testAccount); + assertThat(signature.isEmpty(), equalTo(true)); + + AupSignatureDTO dto = new AupSignatureDTO(); + dto.setAup(aupConverter.dtoFromEntity(aup)); + AccountDTO accountDto = new AccountDTO(); + accountDto.setName(testAccount.getUserInfo().getName()); + accountDto.setUsername(testAccount.getUsername()); + accountDto.setUuid(testAccount.getUuid()); + dto.setAccount(accountDto); + dto.setSignatureTime(new Date()); + + mvc.perform(patch("/iam/aup/signature/{accountId}", testAccount.getUuid()) + .content(mapper.writeValueAsString(dto)) + .contentType(APPLICATION_JSON)).andExpect(status().isCreated()); + + assertThat(aupSignatureRepo.findSignatureForAccount(aup, testAccount).isEmpty(), + equalTo(false)); + + } + @Test @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) public void aupRemovalForSingleUser() throws Exception { @@ -240,6 +273,36 @@ public void aupRemovalForSingleUser() throws Exception { } + @Test + @WithMockOAuthUser(scopes = "iam:admin.write", clientId = "client-cred") + public void aupRemovalForSingleUserWithClientCredentialsWorks() throws Exception { + IamAup aup = buildDefaultAup(); + aupRepo.save(aup); + IamAccount testAccount = accountRepo.findByUsername("test").orElseThrow(); + Date now = new Date(); + mockTimeProvider.setTime(now.getTime()); + + Optional signature = + aupSignatureRepo.findSignatureForAccount(aup, testAccount); + assertThat(signature.isEmpty(), equalTo(true)); + + AupSignatureDTO dto = new AupSignatureDTO(); + dto.setAup(aupConverter.dtoFromEntity(aup)); + AccountDTO accountDto = new AccountDTO(); + accountDto.setName(testAccount.getUserInfo().getName()); + accountDto.setUsername(testAccount.getUsername()); + accountDto.setUuid(testAccount.getUuid()); + dto.setAccount(accountDto); + dto.setSignatureTime(new Date()); + + mvc.perform(patch("/iam/aup/signature/{accountId}", testAccount.getUuid()) + .content(mapper.writeValueAsString(dto)) + .contentType(APPLICATION_JSON)).andExpect(status().isCreated()); + mvc.perform(delete("/iam/aup/signature/" + testAccount.getUuid())) + .andExpect(status().isNoContent()); + + } + @Test @WithMockUser(username = "admin", roles = {"ADMIN", "USER"}) public void aupRemovalRemovesSignatureRecords() throws Exception { diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupTestSupport.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupTestSupport.java index 336433a4c..80b7bd72d 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupTestSupport.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/api/aup/AupTestSupport.java @@ -37,6 +37,7 @@ public IamAup buildDefaultAup() { aup.setCreationTime(now); aup.setLastUpdateTime(now); aup.setSignatureValidityInDays(365L); + aup.setAupRemindersInDays("30,15,1"); return aup; } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/core/IamStatisticalEndpointTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/core/IamStatisticalEndpointTests.java new file mode 100644 index 000000000..53fa80cb6 --- /dev/null +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/core/IamStatisticalEndpointTests.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.test.core; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import it.infn.mw.iam.core.StatsEndpointResponse; +import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; + +@RunWith(SpringRunner.class) +@IamMockMvcIntegrationTest +public class IamStatisticalEndpointTests { + + @Autowired + protected MockMvc mvc; + + @Test + public void anonymousisAcceptedAtStatEndpoint() throws Exception { + mvc.perform(get("/stats")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.numberOfUsers", equalTo(255))); + } + + @Test + public void testSetNumberOfUsers() { + StatsEndpointResponse userCount = new StatsEndpointResponse(0); + userCount.setNumberOfUsers(255); + assertEquals(255, userCount.getNumberOfUsers()); + } + +} diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/ext_authn/oidc/validator/OidcValidatorIntegrationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/ext_authn/oidc/validator/OidcValidatorIntegrationTests.java index 2f21cc15c..2ae7569ad 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/ext_authn/oidc/validator/OidcValidatorIntegrationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/ext_authn/oidc/validator/OidcValidatorIntegrationTests.java @@ -105,8 +105,8 @@ public void testValidatorError() throws JOSEException, UriComponentsBuilder.fromUri(response.getHeaders().getLocation()).build(); assertThat(locationUri.getPath(), equalTo("/login")); - assertThat(locationUri.getQueryParams().keySet(), hasItem("externalAuthenticationError")); - assertThat(locationUri.getQueryParams().getFirst("externalAuthenticationError"), is("always%20fails")); + assertThat(locationUri.getQueryParams().keySet(), hasItem("error")); + assertThat(locationUri.getQueryParams().getFirst("error"), is("true")); } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/login/LoginTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/login/LoginTests.java index 74efa1586..7fbb1f033 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/login/LoginTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/login/LoginTests.java @@ -115,6 +115,7 @@ public void loginRedirectsToSignAupPageWhenNeeded() throws Exception { aup.setUrl("http://default-aup.org/"); aup.setDescription("AUP description"); aup.setSignatureValidityInDays(0L); + aup.setAupRemindersInDays("30,15,1"); aupRepo.save(aup); diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/notification/RegistrationFlowNotificationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/notification/RegistrationFlowNotificationTests.java index 2ef619a99..02bda33ea 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/notification/RegistrationFlowNotificationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/notification/RegistrationFlowNotificationTests.java @@ -110,6 +110,10 @@ public void tearDown() throws InterruptedException { notificationDelivery.clearDeliveredNotifications(); } + public String formatSubject(String key) { + return String.format("[%s IAM] %s", organisationName, properties.getSubject().get(key)); + } + @Test public void testSendWithEmptyQueue() { @@ -145,7 +149,7 @@ public void testApproveFlowNotifications() throws Exception { IamEmailNotification message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("confirmation"))); + assertThat(message.getSubject(), equalTo(formatSubject("confirmation"))); notificationDelivery.clearDeliveredNotifications(); @@ -161,7 +165,7 @@ public void testApproveFlowNotifications() throws Exception { message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("adminHandleRequest"))); + assertThat(message.getSubject(), equalTo(formatSubject("adminHandleRequest"))); assertThat(message.getReceivers(), hasSize(1)); assertThat(message.getReceivers().get(0).getEmailAddress(), @@ -180,7 +184,7 @@ public void testApproveFlowNotifications() throws Exception { message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("activated"))); + assertThat(message.getSubject(), equalTo(formatSubject("activated"))); assertThat(message.getBody(), containsString(request.getUsername())); } @@ -212,7 +216,7 @@ public void testRejectFlowNoMotivationNotifications() throws Exception { IamEmailNotification message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("confirmation"))); + assertThat(message.getSubject(), equalTo(formatSubject("confirmation"))); notificationDelivery.clearDeliveredNotifications(); @@ -228,7 +232,7 @@ public void testRejectFlowNoMotivationNotifications() throws Exception { message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("adminHandleRequest"))); + assertThat(message.getSubject(), equalTo(formatSubject("adminHandleRequest"))); assertThat(message.getReceivers(), hasSize(1)); assertThat(message.getReceivers().get(0).getEmailAddress(), @@ -247,7 +251,7 @@ public void testRejectFlowNoMotivationNotifications() throws Exception { message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("rejected"))); + assertThat(message.getSubject(), equalTo(formatSubject("rejected"))); assertThat(message.getBody(), not(containsString("The administrator has provided the following motivation"))); @@ -280,7 +284,7 @@ public void testRejectFlowMotivationNotifications() throws Exception { IamEmailNotification message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("confirmation"))); + assertThat(message.getSubject(), equalTo(formatSubject("confirmation"))); notificationDelivery.clearDeliveredNotifications(); @@ -296,7 +300,7 @@ public void testRejectFlowMotivationNotifications() throws Exception { message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("adminHandleRequest"))); + assertThat(message.getSubject(), equalTo(formatSubject("adminHandleRequest"))); assertThat(message.getReceivers(), hasSize(1)); assertThat(message.getReceivers().get(0).getEmailAddress(), @@ -317,11 +321,10 @@ public void testRejectFlowMotivationNotifications() throws Exception { message = notificationDelivery.getDeliveredNotifications().get(0); - assertThat(message.getSubject(), equalTo(properties.getSubject().get("rejected"))); + assertThat(message.getSubject(), equalTo(formatSubject("rejected"))); assertThat(message.getBody(), containsString("The administrator has provided the following motivation")); - assertThat(message.getBody(), - containsString("We hate you")); + assertThat(message.getBody(), containsString("We hate you")); } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/EndpointsTestUtils.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/EndpointsTestUtils.java index 7f28b6620..81aaf7146 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/EndpointsTestUtils.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/EndpointsTestUtils.java @@ -22,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import com.fasterxml.jackson.databind.ObjectMapper; @@ -103,7 +104,14 @@ public AccessTokenGetter audience(String audience) { return this; } - public String performTokenRequest() throws Exception { + public String performSuccessfulTokenRequest() throws Exception { + + return performTokenRequest(200) + .getResponse() + .getContentAsString(); + } + + public MvcResult performTokenRequest(int statusCode) throws Exception { MockHttpServletRequestBuilder req = post("/token").param("grant_type", grantType) .param("client_id", clientId) .param("client_secret", clientSecret); @@ -120,18 +128,14 @@ public String performTokenRequest() throws Exception { req.param("aud", audience); } - String response = mvc.perform(req) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(); - - return response; + return mvc.perform(req) + .andExpect(status().is(statusCode)) + .andReturn(); } public DefaultOAuth2AccessToken getTokenResponseObject() throws Exception { - String response = performTokenRequest(); + String response = performSuccessfulTokenRequest(); // This is incorrectly named in spring security OAuth, what they call OAuth2AccessToken // is a TokenResponse object diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/RefreshTokenGranterTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/RefreshTokenGranterTests.java index c675a2203..057a46d7c 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/RefreshTokenGranterTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/RefreshTokenGranterTests.java @@ -24,6 +24,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.mitre.oauth2.model.ClientDetailsEntity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; @@ -34,6 +35,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import it.infn.mw.iam.IamLoginService; +import it.infn.mw.iam.api.client.service.ClientService; +import it.infn.mw.iam.api.client.util.ClientSuppliers; import it.infn.mw.iam.persistence.model.IamAup; import it.infn.mw.iam.persistence.repository.IamAccountRepository; import it.infn.mw.iam.persistence.repository.IamAupRepository; @@ -58,6 +61,9 @@ public class RefreshTokenGranterTests { @Autowired private IamAccountRepository accountRepo; + @Autowired + private ClientService clientService; + @Autowired private MockMvc mvc; @@ -93,6 +99,7 @@ public void testTokenRefreshFailsIfAupIsNotSigned() throws Exception { aup.setUrl("http://default-aup.org/"); aup.setDescription("AUP description"); aup.setSignatureValidityInDays(0L); + aup.setAupRemindersInDays("30,15,1"); aupRepo.save(aup); @@ -157,4 +164,48 @@ public void testRefreshFlowNotAllowedIfUserIsSuspended() throws Exception { accountRepo.findByUsername("test").get().setActive(true); } + @Test + public void testRefreshFlowNotAllowedIfClientIsSuspended() throws Exception { + + String clientId = "password-grant"; + String clientSecret = "secret"; + + // @formatter:off + String response = mvc.perform(post("/token") + .with(httpBasic(clientId, clientSecret)) + .param("grant_type", "password") + .param("username", USERNAME) + .param("password", PASSWORD) + .param("scope", SCOPE)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + // @formatter:on + + DefaultOAuth2AccessToken tokenResponse = + mapper.readValue(response, DefaultOAuth2AccessToken.class); + + String refreshToken = tokenResponse.getRefreshToken().toString(); + + ClientDetailsEntity client = clientService.findClientByClientId(clientId) + .orElseThrow(ClientSuppliers.clientNotFound(clientId)); + + client.setActive(false); + clientService.updateClient(client); + + // @formatter:off + mvc.perform(post("/token") + .with(httpBasic(clientId, clientSecret)) + .param("grant_type", "refresh_token") + .param("refresh_token", refreshToken)) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("$.error").value("invalid_client")) + .andExpect(jsonPath("$.error_description").value("Client is suspended: " + clientId)); + // @formatter:on + + client.setActive(true); + clientService.updateClient(client); + } + } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/ResourceOwnerPasswordCredentialsTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/ResourceOwnerPasswordCredentialsTests.java index 7775a224a..7f89daa3a 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/ResourceOwnerPasswordCredentialsTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/ResourceOwnerPasswordCredentialsTests.java @@ -123,6 +123,7 @@ public void testResourceOwnerPasswordCredentialsFailsIfAupIsNotSigned() throws E aup.setUrl("http://default-aup.org/"); aup.setDescription("AUP description"); aup.setSignatureValidityInDays(0L); + aup.setAupRemindersInDays("30,15,1"); aupRepo.save(aup); diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/TokenExchangeTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/TokenExchangeTests.java index 8ea60bc2c..c4f367ecd 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/TokenExchangeTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/TokenExchangeTests.java @@ -178,6 +178,7 @@ public void testImpersonationFlowFailsIfAUPNotSigned() throws Exception { aup.setUrl("http://default-aup.org/"); aup.setDescription("AUP description"); aup.setSignatureValidityInDays(0L); + aup.setAupRemindersInDays("30,15,1"); aupRepo.save(aup); diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/authzcode/AuthorizationCodeTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/authzcode/AuthorizationCodeTests.java index 7b90fa9c9..3d1fa7718 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/authzcode/AuthorizationCodeTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/authzcode/AuthorizationCodeTests.java @@ -137,6 +137,7 @@ public void testOidcAuthorizationCodeFlowWithAUPSignature() throws Exception { aup.setUrl("http://default-aup.org/"); aup.setDescription("AUP description"); aup.setSignatureValidityInDays(0L); + aup.setAupRemindersInDays("30,15,1"); aupRepo.save(aup); diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherCacheTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherCacheTests.java index 2ba38ac82..0d78278b0 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherCacheTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherCacheTests.java @@ -28,6 +28,7 @@ import org.mitre.oauth2.model.ClientDetailsEntity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; @@ -36,8 +37,8 @@ import com.nimbusds.jwt.JWTParser; import it.infn.mw.iam.api.client.service.ClientService; -import it.infn.mw.iam.config.CacheConfig; -import it.infn.mw.iam.config.RedisCacheProperties; +import it.infn.mw.iam.config.CacheProperties; +import it.infn.mw.iam.persistence.repository.client.IamClientRepository; import it.infn.mw.iam.test.oauth.EndpointsTestUtils; import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; @@ -53,10 +54,13 @@ public class ScopeMatcherCacheTests extends EndpointsTestUtils { private ClientService clientService; @Autowired - private CacheConfig cacheConfig; - + private IamClientRepository clientRepository; + + @Autowired + private CacheManager localCacheManager; + @Autowired - private RedisCacheProperties redisCacheProperties; + private CacheProperties cacheProperties; private String getAccessTokenForClient(String scopes) throws Exception { @@ -67,10 +71,19 @@ private String getAccessTokenForClient(String scopes) throws Exception { .getAccessTokenValue(); } + private void getAccessTokenForClientFailWithStatusCode(String scopes, int statusCode) throws Exception { + + new AccessTokenGetter().grantType("client_credentials") + .clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET) + .scope(scopes) + .performTokenRequest(statusCode); + } + @Test - public void ensureRedisCashIsDisabled() { - assertFalse(redisCacheProperties.isEnabled()); - assertThat(cacheConfig.localCacheManager(), instanceOf(CacheManager.class)); + public void ensureRedisCacheIsDisabled() { + assertFalse(cacheProperties.getRedis().isEnabled()); + assertThat(localCacheManager, instanceOf(ConcurrentMapCacheManager.class)); } @Test @@ -87,6 +100,8 @@ public void updatingClientScopesInvalidatesCache() throws ParseException, Except assertThat("scim:read", not(in(token.getJWTClaimsSet().getClaim("scope").toString().split(" ")))); client.setScope(Sets.newHashSet("openid", "profile", "email", "scim:read")); + clientRepository.save(client); + getAccessTokenForClientFailWithStatusCode("openid profile email scim:read", 400); clientService.updateClient(client); token = JWTParser.parse(getAccessTokenForClient("openid profile email scim:read")); assertThat("scim:read", in(token.getJWTClaimsSet().getClaim("scope").toString().split(" "))); @@ -94,4 +109,5 @@ public void updatingClientScopesInvalidatesCache() throws ParseException, Except clientService.deleteClient(client); } } + } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherExternalCacheTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherExternalCacheTests.java index efcedaa85..56af564ff 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherExternalCacheTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherExternalCacheTests.java @@ -27,11 +27,11 @@ import org.junit.jupiter.api.Test; import org.mitre.oauth2.model.ClientDetailsEntity; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.cache.CacheManager; +import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.junit.jupiter.Container; @@ -44,8 +44,7 @@ import io.restassured.RestAssured; import it.infn.mw.iam.api.client.service.ClientService; -import it.infn.mw.iam.config.CacheConfig; -import it.infn.mw.iam.config.RedisCacheProperties; +import it.infn.mw.iam.config.CacheProperties; import it.infn.mw.iam.test.TestUtils; import it.infn.mw.iam.test.oauth.EndpointsTestUtils; import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; @@ -54,7 +53,7 @@ @Testcontainers @IamMockMvcIntegrationTest @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, - properties = {"iam.access_token.include_scope=true", "redis-cache.enabled=true"}) + properties = {"iam.access_token.include_scope=true", "cache.redis.enabled=true"}) public class ScopeMatcherExternalCacheTests extends EndpointsTestUtils { private static final String CLIENT_ID = "cache-client"; @@ -68,10 +67,7 @@ public class ScopeMatcherExternalCacheTests extends EndpointsTestUtils { private ClientService clientService; @Autowired - private CacheConfig cacheConfig; - - @Autowired - private RedisCacheProperties redisCacheProperties; + private CacheProperties redisCacheProperties; @LocalServerPort private Integer iamPort; @@ -79,6 +75,9 @@ public class ScopeMatcherExternalCacheTests extends EndpointsTestUtils { @Autowired ObjectMapper mapper; + @Autowired + CacheManager cacheManager; + @Container private static final RedisContainer REDIS = new RedisContainer(); @@ -93,10 +92,7 @@ public void setup() { TestUtils.initRestAssured(); RestAssured.port = iamPort; assertTrue(redisCacheProperties.isEnabled()); - assertThat(cacheConfig.redisCacheConfiguration(), instanceOf(RedisCacheConfiguration.class)); - assertThat(cacheConfig.redisCacheManagerBuilderCustomizer(), - instanceOf(RedisCacheManagerBuilderCustomizer.class)); - + assertThat(cacheManager, instanceOf(RedisCacheManager.class)); } private String getAccessTokenForClient(String scopes) throws Exception { @@ -106,7 +102,6 @@ private String getAccessTokenForClient(String scopes) throws Exception { .clientSecret(CLIENT_SECRET) .scope(scopes) .getAccessTokenValue(); - } @Test diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherNoCacheTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherNoCacheTests.java new file mode 100644 index 000000000..85ad1a3a4 --- /dev/null +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/oauth/scope/matchers/ScopeMatcherNoCacheTests.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package it.infn.mw.iam.test.oauth.scope.matchers; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.in; +import static org.hamcrest.Matchers.not; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.oauth2.model.ClientDetailsEntity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.CacheManager; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.cache.support.NoOpCacheManager; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import com.google.common.collect.Sets; +import com.nimbusds.jwt.JWT; +import com.nimbusds.jwt.JWTParser; + +import it.infn.mw.iam.persistence.repository.client.IamClientRepository; +import it.infn.mw.iam.test.oauth.EndpointsTestUtils; +import it.infn.mw.iam.test.util.annotation.IamMockMvcIntegrationTest; + +@RunWith(SpringRunner.class) +@IamMockMvcIntegrationTest +@TestPropertySource(properties = {"cache.enabled=false", "iam.access_token.include_scope=true"}) +public class ScopeMatcherNoCacheTests extends EndpointsTestUtils { + + private static final String CLIENT_ID = "cache-client"; + private static final String CLIENT_SECRET = "secret"; + + @Autowired + private IamClientRepository clientRepo; + + @Autowired + private CacheManager cacheManager; + + private String getAccessTokenForClient(String scopes) throws Exception { + + return new AccessTokenGetter().grantType("client_credentials") + .clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET) + .scope(scopes) + .getAccessTokenValue(); + } + + @Test + public void ensureRedisCacheIsDisabled() { + assertThat(cacheManager, instanceOf(NoOpCacheManager.class)); + assertThat(cacheManager, not(instanceOf(ConcurrentMapCacheManager.class))); + assertThat(cacheManager, not(instanceOf(RedisCacheManager.class))); + } + + @Test + public void updatingClientScopesWithNoCache() throws Exception { + + ClientDetailsEntity client = new ClientDetailsEntity(); + client.setClientId(CLIENT_ID); + client.setClientSecret(CLIENT_SECRET); + client.setScope(Sets.newHashSet("openid", "profile", "email")); + clientRepo.save(client); + + try { + JWT token = JWTParser.parse(getAccessTokenForClient("openid profile email")); + assertThat("scim:read", + not(in(token.getJWTClaimsSet().getClaim("scope").toString().split(" ")))); + client.setScope(Sets.newHashSet("openid", "profile", "email", "scim:read")); + clientRepo.save(client); + token = JWTParser.parse(getAccessTokenForClient("openid profile email scim:read")); + assertThat("scim:read", in(token.getJWTClaimsSet().getClaim("scope").toString().split(" "))); + } finally { + clientRepo.delete(client); + } + } +} diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/RegistrationUsernameTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/RegistrationUsernameTests.java index af9c23eb8..dc61d61c1 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/RegistrationUsernameTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/RegistrationUsernameTests.java @@ -67,7 +67,7 @@ public void teardown() { private RegistrationRequestDto createRegistrationRequest(String username) { - String email = username + "@example.org"; + String email = username.split("@")[0] + "@example.org"; RegistrationRequestDto request = new RegistrationRequestDto(); request.setGivenname("Test"); request.setFamilyname("User"); @@ -81,8 +81,8 @@ private RegistrationRequestDto createRegistrationRequest(String username) { @Test public void validUsernames() throws Exception { - final String[] validUsernames = {"bob", "b", "test$", "root", "test1234", "test_", "_test", - "username@example.com", "username@domain"}; + final String[] validUsernames = {"bob","test$", "root", "test1234", "test_", "_test", + "username1@example.com", "username2@domain"}; for (String u : validUsernames) { RegistrationRequestDto r = createRegistrationRequest(u); @@ -102,7 +102,7 @@ public void validUsernames() throws Exception { @Test public void invalidUsernames() throws Exception { - final String[] invalidUsernames = {"£$%^&*(", ".,", "-test", "1test", "test$$", "@domain", + final String[] invalidUsernames = {"a","£$%^&*(", ".,", "-test", "1test", "test$$", "@domain", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}; for (String u : invalidUsernames) { diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/cern/CernRegistrationValidationServiceTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/cern/CernRegistrationValidationServiceTests.java index f54c34d02..b1b2d6bda 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/cern/CernRegistrationValidationServiceTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/registration/cern/CernRegistrationValidationServiceTests.java @@ -119,7 +119,6 @@ private RegistrationRequestDto createDto(String username) { request.setEmail(email); request.setUsername(username); request.setNotes("Some short notes..."); - request.setPassword("password"); return request; } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/repository/IamAupRepositoryTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/repository/IamAupRepositoryTests.java index 2c606f6cb..dd0e46a47 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/repository/IamAupRepositoryTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/repository/IamAupRepositoryTests.java @@ -64,6 +64,7 @@ public void aupCreationWorks() { assertThat(aup.getCreationTime(), new DateEqualModulo1Second(creationTime)); assertThat(aup.getLastUpdateTime(), new DateEqualModulo1Second(creationTime)); assertThat(aup.getSignatureValidityInDays(), equalTo(365L)); + assertThat(aup.getAupRemindersInDays(), equalTo("30,15,1")); } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserCreationTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserCreationTests.java index dce25dabd..d7fee48be 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserCreationTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/scim/user/ScimUserCreationTests.java @@ -21,6 +21,8 @@ import static it.infn.mw.iam.test.scim.ScimUtils.SCIM_WRITE_SCOPE; import static it.infn.mw.iam.test.scim.ScimUtils.buildUser; import static it.infn.mw.iam.test.scim.ScimUtils.buildUserWithPassword; +import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -36,7 +38,9 @@ import java.util.Date; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; +import org.hamcrest.collection.IsIterableContainingInAnyOrder; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -387,19 +391,28 @@ public void testUserCreationWithMultipleX509Certificate() throws Exception { .active(true) .build(); - List userCertList = user.getIndigoUser().getCertificates(); - ScimUser createdUser = scimUtils.postUser(user); List createdUserCertList = createdUser.getIndigoUser().getCertificates(); assertNotNull(createdUserCertList); - assertThat(createdUserCertList, hasSize(equalTo(2))); - assertThat(createdUserCertList.get(0).getDisplay(), equalTo(userCertList.get(0).getDisplay())); - assertThat(createdUserCertList.get(0).getPemEncodedCertificate(), - equalTo(userCertList.get(0).getPemEncodedCertificate())); - assertThat(createdUserCertList.get(0).getPrimary(), equalTo(userCertList.get(0).getPrimary())); - assertThat(createdUserCertList.get(1).getDisplay(), equalTo(userCertList.get(1).getDisplay())); - assertThat(createdUserCertList.get(1).getPrimary(), equalTo(userCertList.get(1).getPrimary())); + assertThat(createdUserCertList.stream().map(c -> c.getDisplay()).collect(Collectors.toList()), + IsIterableContainingInAnyOrder.containsInAnyOrder("Personal1", "Personal2")); + ScimX509Certificate createdCert1 = createdUserCertList.stream() + .filter(cert -> "Personal1".equals(cert.getDisplay())) + .findFirst() + .get(); + ScimX509Certificate createdCert2 = createdUserCertList.stream() + .filter(cert -> "Personal2".equals(cert.getDisplay())) + .findFirst() + .get(); + + assertThat(createdCert1.getPrimary(), equalTo(FALSE)); + assertThat(createdCert2.getPrimary(), equalTo(TRUE)); + assertThat(createdCert1.getPemEncodedCertificate(), + equalTo(X509Utils.x509Certs.get(0).certificate)); + assertThat(createdCert2.getPemEncodedCertificate(), + equalTo(X509Utils.x509Certs.get(1).certificate)); + } @Test @@ -426,19 +439,28 @@ public void testUserCreationWithMultipleX509CertificateAndNoPrimary() throws Exc .active(true) .build(); - List userCertList = user.getIndigoUser().getCertificates(); - ScimUser createdUser = scimUtils.postUser(user); List createdUserCertList = createdUser.getIndigoUser().getCertificates(); assertNotNull(createdUserCertList); - assertThat(createdUserCertList, hasSize(equalTo(2))); - assertThat(createdUserCertList.get(0).getDisplay(), equalTo(userCertList.get(0).getDisplay())); - assertThat(createdUserCertList.get(0).getPemEncodedCertificate(), - equalTo(userCertList.get(0).getPemEncodedCertificate())); - assertThat(createdUserCertList.get(0).getPrimary(), equalTo(true)); - assertThat(createdUserCertList.get(1).getDisplay(), equalTo(userCertList.get(1).getDisplay())); - assertThat(createdUserCertList.get(1).getPrimary(), equalTo(false)); + assertThat(createdUserCertList.stream().map(c -> c.getDisplay()).collect(Collectors.toList()), + IsIterableContainingInAnyOrder.containsInAnyOrder("Personal1", "Personal2")); + ScimX509Certificate createdCert1 = createdUserCertList.stream() + .filter(cert -> "Personal1".equals(cert.getDisplay())) + .findFirst() + .get(); + ScimX509Certificate createdCert2 = createdUserCertList.stream() + .filter(cert -> "Personal2".equals(cert.getDisplay())) + .findFirst() + .get(); + + assertThat(createdCert1.getPrimary(), equalTo(TRUE)); + assertThat(createdCert2.getPrimary(), equalTo(FALSE)); + assertThat(createdCert1.getPemEncodedCertificate(), + equalTo(X509Utils.x509Certs.get(0).certificate)); + assertThat(createdCert2.getPemEncodedCertificate(), + equalTo(X509Utils.x509Certs.get(1).certificate)); + } @Test @@ -472,7 +494,7 @@ public void testUserCreationWithAupSignatureIsIgnored() throws Exception { final String AUP_DESCRIPTION = "Test AUP"; final Date currentDate = new Date(); - AupDTO aup = new AupDTO(AUP_URL, "", AUP_DESCRIPTION, 0L, currentDate, currentDate); + AupDTO aup = new AupDTO(AUP_URL, "", AUP_DESCRIPTION, 0L, currentDate, currentDate, "30,15,1"); aupService.saveAup(aup); Calendar cal = Calendar.getInstance(); @@ -480,9 +502,10 @@ public void testUserCreationWithAupSignatureIsIgnored() throws Exception { cal.add(Calendar.HOUR_OF_DAY, 1); Date signatureTime = cal.getTime(); - ScimUser user = buildUser("user_with_aup_signature", "userwithaupsignature@email.test", "User", "Test") - .aupSignatureTime(signatureTime) - .build(); + ScimUser user = + buildUser("user_with_aup_signature", "userwithaupsignature@email.test", "User", "Test") + .aupSignatureTime(signatureTime) + .build(); ScimUser createdUser = scimUtils.postUser(user); assertThat(user.getUserName(), equalTo(createdUser.getUserName())); diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/service/IamAccountServiceTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/service/IamAccountServiceTests.java index fded5a4ad..67ccf07df 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/service/IamAccountServiceTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/service/IamAccountServiceTests.java @@ -39,6 +39,7 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Date; +import java.util.List; import java.util.Optional; import org.junit.Before; @@ -59,12 +60,18 @@ import com.google.common.collect.Sets; import it.infn.mw.iam.audit.events.account.AccountEndTimeUpdatedEvent; +import it.infn.mw.iam.config.IamProperties; +import it.infn.mw.iam.config.IamProperties.DefaultGroup; +import it.infn.mw.iam.core.group.DefaultIamGroupService; import it.infn.mw.iam.core.time.TimeProvider; import it.infn.mw.iam.core.user.DefaultIamAccountService; import it.infn.mw.iam.core.user.exception.CredentialAlreadyBoundException; import it.infn.mw.iam.core.user.exception.InvalidCredentialException; import it.infn.mw.iam.core.user.exception.UserAlreadyExistsException; +import it.infn.mw.iam.notification.NotificationFactory; import it.infn.mw.iam.persistence.model.IamAccount; +import it.infn.mw.iam.persistence.model.IamAccountGroupMembership; +import it.infn.mw.iam.persistence.model.IamGroup; import it.infn.mw.iam.persistence.model.IamOidcId; import it.infn.mw.iam.persistence.model.IamSamlId; import it.infn.mw.iam.persistence.model.IamSshKey; @@ -77,6 +84,8 @@ @RunWith(MockitoJUnitRunner.class) public class IamAccountServiceTests extends IamAccountServiceTestSupport { + private static final String TEST_GROUP_1 = "Test-group-1"; + public static final Instant NOW = Instant.parse("2021-01-01T00:00:00.00Z"); @Mock @@ -103,10 +112,21 @@ public class IamAccountServiceTests extends IamAccountServiceTestSupport { @Mock private OAuth2TokenEntityService tokenService; + @Mock + private NotificationFactory notificationFactory; + private Clock clock = Clock.fixed(NOW, ZoneId.systemDefault()); private DefaultIamAccountService accountService; + @Mock + private DefaultIamGroupService iamGroupService; + + @Mock + private IamProperties iamProperties; + + private IamProperties.RegistrationProperties registrationProperties = new IamProperties.RegistrationProperties(); + @Captor private ArgumentCaptor eventCaptor; @@ -126,9 +146,10 @@ public void setup() { when(authoritiesRepo.findByAuthority(anyString())).thenReturn(Optional.empty()); when(authoritiesRepo.findByAuthority("ROLE_USER")).thenReturn(Optional.of(ROLE_USER_AUTHORITY)); when(passwordEncoder.encode(any())).thenReturn(PASSWORD); + when(iamProperties.getRegistration()).thenReturn(registrationProperties); accountService = new DefaultIamAccountService(clock, accountRepo, groupRepo, authoritiesRepo, - passwordEncoder, eventPublisher, tokenService, accountClientRepo); + passwordEncoder, eventPublisher, tokenService, accountClientRepo, notificationFactory, iamProperties, iamGroupService); } @Test(expected = NullPointerException.class) @@ -843,4 +864,41 @@ public void testSetEndTimeWorksForNonNullDate() { assertThat(e.getAccount().getEndTime(), is(newEndTime)); } + @Test + public void testNewAccountAddedToDefaultGroups() { + IamAccount account = cloneAccount(CICCIO_ACCOUNT); + + IamGroup testGroup = new IamGroup(); + testGroup.setName(TEST_GROUP_1); + DefaultGroup defaultGroup = new DefaultGroup(); + defaultGroup.setName(TEST_GROUP_1); + defaultGroup.setEnrollment("INSERT"); + List defaultGroups = Arrays.asList(defaultGroup); + + registrationProperties.setDefaultGroups(defaultGroups); + when(iamGroupService.findByName(TEST_GROUP_1)).thenReturn(Optional.of(testGroup)); + + account = accountService.createAccount(account); + + assertTrue(getGroup(account).equals(testGroup)); + } + + private IamGroup getGroup(IamAccount account) { + Optional groupMembershipOptional = account.getGroups().stream().findFirst(); + if (groupMembershipOptional.isPresent()) { + return groupMembershipOptional.get().getGroup(); + } + return null; + } + + @Test + public void testNoDefaultGroupsAddedWhenDefaultGroupsNotGiven() { + IamAccount account = cloneAccount(CICCIO_ACCOUNT); + + account = accountService.createAccount(account); + + Optional groupMembershipOptional = account.getGroups().stream().findFirst(); + assertFalse(groupMembershipOptional.isPresent()); + } + } diff --git a/iam-login-service/src/test/java/it/infn/mw/iam/test/service/client/ClientManagementServiceTests.java b/iam-login-service/src/test/java/it/infn/mw/iam/test/service/client/ClientManagementServiceTests.java index 1711e80da..b9f8df669 100644 --- a/iam-login-service/src/test/java/it/infn/mw/iam/test/service/client/ClientManagementServiceTests.java +++ b/iam-login-service/src/test/java/it/infn/mw/iam/test/service/client/ClientManagementServiceTests.java @@ -105,7 +105,7 @@ public void testPagedClientLookup() { Sort sort = Sort.by(Direction.ASC, "clientId"); Pageable pageable = PagingUtils.buildPageRequest(10, 1, 100, sort); - + ListResponseDTO clients = managementService.retrieveAllClients(pageable); assertThat(clients.getTotalResults(), is(19L)); @@ -249,8 +249,7 @@ public void testBasicClientValidation() { } @Test - public void testDynamicallyRegisteredClientCanBeUpdated() - throws ParseException { + public void testDynamicallyRegisteredClientCanBeUpdated() throws ParseException { userAuth = Mockito.mock(UsernamePasswordAuthenticationToken.class); when(userAuth.getName()).thenReturn("test"); @@ -261,7 +260,7 @@ public void testDynamicallyRegisteredClientCanBeUpdated() request.setGrantTypes(Sets.newHashSet(AuthorizationGrantType.CLIENT_CREDENTIALS)); RegisteredClientDTO response = registrationService.registerClient(request, userAuth); - + String clientId = response.getClientId(); ClientDetailsEntity entity = clientService.findClientByClientId(clientId).orElseThrow(); assertThat(entity.isDynamicallyRegistered(), is(true)); @@ -296,8 +295,7 @@ public void testSecretRotation() throws ParseException { RegisteredClientDTO updatedClient = managementService.retrieveClientByClientId(client.getClientId()).orElseThrow(); - assertThat(updatedClient.getClientSecret(), - not(equalTo(savedClient.getClientSecret()))); + assertThat(updatedClient.getClientSecret(), not(equalTo(savedClient.getClientSecret()))); } @Test @@ -333,9 +331,8 @@ public void testClientOwnerAssignRemove() throws ParseException { RegisteredClientDTO savedClient = managementService.saveNewClient(client); assertThat(savedClient.getClientId(), is(client.getClientId())); assertThat(savedClient.getClientSecret(), notNullValue()); - - ListResponseDTO owners = - managementService.getClientOwners(savedClient.getClientId(), + + ListResponseDTO owners = managementService.getClientOwners(savedClient.getClientId(), PagingUtils.buildUnpagedPageRequest()); assertThat(owners.getTotalResults(), is(0L)); @@ -417,4 +414,24 @@ public void testClientStatusChange() { assertTrue(client.getStatusChangedOn().equals(Date.from(clock.instant()))); assertEquals("userUUID", client.getStatusChangedBy()); } + + @Test + public void testClientStatusChangeWithContacts() { + managementService.updateClientStatus("device-code-client", false, "userUUID"); + RegisteredClientDTO client = managementService.retrieveClientByClientId("device-code-client").get(); + + assertFalse(client.isActive()); + assertTrue(client.getStatusChangedOn().equals(Date.from(clock.instant()))); + assertEquals("userUUID", client.getStatusChangedBy()); + } + + @Test + public void testClientStatusChangeWithoutOwners() { + managementService.updateClientStatus("client-cred", false, "userUUID"); + RegisteredClientDTO client = managementService.retrieveClientByClientId("client-cred").get(); + + assertFalse(client.isActive()); + assertTrue(client.getStatusChangedOn().equals(Date.from(clock.instant()))); + assertEquals("userUUID", client.getStatusChangedBy()); + } } diff --git a/iam-persistence/pom.xml b/iam-persistence/pom.xml index 4d13a98e9..ae547b3de 100644 --- a/iam-persistence/pom.xml +++ b/iam-persistence/pom.xml @@ -22,7 +22,7 @@ it.infn.mw.iam-parent iam-parent - 1.9.0 + 1.10.0 it.infn.mw.iam-persistence diff --git a/iam-persistence/src/main/java/it/infn/mw/iam/core/IamNotificationType.java b/iam-persistence/src/main/java/it/infn/mw/iam/core/IamNotificationType.java index 971ae61be..ba3c26c74 100644 --- a/iam-persistence/src/main/java/it/infn/mw/iam/core/IamNotificationType.java +++ b/iam-persistence/src/main/java/it/infn/mw/iam/core/IamNotificationType.java @@ -16,5 +16,5 @@ package it.infn.mw.iam.core; public enum IamNotificationType { - CONFIRMATION, RESETPASSWD, ACTIVATED, REJECTED, GROUP_MEMBERSHIP + CONFIRMATION, RESETPASSWD, ACTIVATED, REJECTED, GROUP_MEMBERSHIP, AUP_REMINDER, AUP_EXPIRATION, AUP_SIGNATURE_REQUEST, ACCOUNT_SUSPENDED, ACCOUNT_RESTORED, CLIENT_STATUS } diff --git a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/model/IamAup.java b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/model/IamAup.java index c39a926e2..0039e0746 100644 --- a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/model/IamAup.java +++ b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/model/IamAup.java @@ -50,6 +50,9 @@ public class IamAup implements Serializable { @Column(name = "sig_validity_days", nullable = false) Long signatureValidityInDays; + @Column(name = "aup_reminders_days", nullable = false) + String aupRemindersInDays; + @Temporal(TemporalType.TIMESTAMP) @Column(name = "creation_time", nullable = false) Date creationTime; @@ -137,6 +140,14 @@ public void setSignatureValidityInDays(Long signatureValidityInDays) { this.signatureValidityInDays = signatureValidityInDays; } + public String getAupRemindersInDays() { + return aupRemindersInDays; + } + + public void setAupRemindersInDays(String aupRemindersInDays) { + this.aupRemindersInDays = aupRemindersInDays; + } + public Date getCreationTime() { return creationTime; diff --git a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamAccountRepository.java b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamAccountRepository.java index 225a9637e..38c196d60 100644 --- a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamAccountRepository.java +++ b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamAccountRepository.java @@ -141,7 +141,6 @@ Page findByLabelNameAndValue(@Param("name") String name, @Param("val @Query("select a from IamAccount a where a.active = TRUE") Page findActiveAccounts(Pageable op); - @Modifying @Query("delete from IamAccountGroupMembership") void deleteAllAccountGroupMemberships(); diff --git a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamAupSignatureRepository.java b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamAupSignatureRepository.java index cdbbeec4d..a2b775911 100644 --- a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamAupSignatureRepository.java +++ b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamAupSignatureRepository.java @@ -15,11 +15,13 @@ */ package it.infn.mw.iam.persistence.repository; - - +import java.util.Date; +import java.util.List; import java.util.Optional; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; import it.infn.mw.iam.persistence.model.IamAccount; import it.infn.mw.iam.persistence.model.IamAup; @@ -28,8 +30,12 @@ public interface IamAupSignatureRepository extends PagingAndSortingRepository, IamAupSignatureRepositoryCustom { + @Query("select ias from IamAupSignature ias join ias.account a where a.active = TRUE and ias.aup = :aup and :signatureTime <= ias.signatureTime and ias.signatureTime < :plusOne") + List findByAupAndSignatureTime(@Param("aup") IamAup aup, + @Param("signatureTime") Date signatureTime, @Param("plusOne") Date plusOne); + Optional findByAupAndAccount(IamAup aup, IamAccount account); - + Long deleteByAup(IamAup aup); - + } diff --git a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamEmailNotificationRepository.java b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamEmailNotificationRepository.java index fdb932798..16f970bdc 100644 --- a/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamEmailNotificationRepository.java +++ b/iam-persistence/src/main/java/it/infn/mw/iam/persistence/repository/IamEmailNotificationRepository.java @@ -46,4 +46,17 @@ List findByStatusWithUpdateTime( Integer countByDeliveryStatus(IamDeliveryStatus deliveryStatus); List findByNotificationType(IamNotificationType notificationType); + + @Query("select count(n) from IamEmailNotification n join n.receivers r where n.notificationType = it.infn.mw.iam.core.IamNotificationType.AUP_REMINDER" + + " and CURRENT_DATE <= n.lastUpdate and n.lastUpdate < :tomorrow" + + " and n.deliveryStatus <> it.infn.mw.iam.core.IamDeliveryStatus.DELIVERY_ERROR" + + " and r.emailAddress = :email_address") + Integer countAupRemindersPerAccount(@Param("email_address") String emailAddress, + @Param("tomorrow") Date tomorrow); + + @Query("select count(n) from IamEmailNotification n join n.receivers r where n.notificationType = it.infn.mw.iam.core.IamNotificationType.AUP_EXPIRATION" + + " and n.deliveryStatus <> it.infn.mw.iam.core.IamDeliveryStatus.DELIVERY_ERROR" + + " and r.emailAddress = :email_address") + Integer countAupExpirationMessPerAccount(@Param("email_address") String emailAddress); + } diff --git a/iam-persistence/src/main/resources/db/migration/h2/V105__add_aup_reminders.sql b/iam-persistence/src/main/resources/db/migration/h2/V105__add_aup_reminders.sql new file mode 100644 index 000000000..101cb09f8 --- /dev/null +++ b/iam-persistence/src/main/resources/db/migration/h2/V105__add_aup_reminders.sql @@ -0,0 +1 @@ +ALTER TABLE iam_aup ADD COLUMN aup_reminders_days VARCHAR(128) NOT NULL DEFAULT '30,15,1'; \ No newline at end of file diff --git a/iam-persistence/src/main/resources/db/migration/h2/V19__aup_tables.sql b/iam-persistence/src/main/resources/db/migration/h2/V19__aup_tables.sql index 18f449f46..8ad7b522c 100644 --- a/iam-persistence/src/main/resources/db/migration/h2/V19__aup_tables.sql +++ b/iam-persistence/src/main/resources/db/migration/h2/V19__aup_tables.sql @@ -3,7 +3,7 @@ CREATE TABLE iam_aup (ID BIGINT IDENTITY NOT NULL, description VARCHAR(128), last_update_time TIMESTAMP NOT NULL, name VARCHAR(36) NOT NULL UNIQUE, - sig_validity_days BIGINT NOT NULL, + sig_validity_days BIGINT NOT NULL, text LONGVARCHAR NOT NULL, PRIMARY KEY (ID)); diff --git a/iam-persistence/src/main/resources/db/migration/mysql/V105__add_aup_reminders.sql b/iam-persistence/src/main/resources/db/migration/mysql/V105__add_aup_reminders.sql new file mode 100644 index 000000000..101cb09f8 --- /dev/null +++ b/iam-persistence/src/main/resources/db/migration/mysql/V105__add_aup_reminders.sql @@ -0,0 +1 @@ +ALTER TABLE iam_aup ADD COLUMN aup_reminders_days VARCHAR(128) NOT NULL DEFAULT '30,15,1'; \ No newline at end of file diff --git a/iam-persistence/src/main/resources/db/migration/test/V100000___test_data.sql b/iam-persistence/src/main/resources/db/migration/test/V100000___test_data.sql index 468928784..0d2b46151 100644 --- a/iam-persistence/src/main/resources/db/migration/test/V100000___test_data.sql +++ b/iam-persistence/src/main/resources/db/migration/test/V100000___test_data.sql @@ -186,6 +186,9 @@ INSERT INTO client_grant_type (owner_id, grant_type) VALUES (18, 'urn:ietf:params:oauth:grant-type:device_code'), (18, 'authorization_code'), (19, 'client_credentials'); + +INSERT INTO client_contact (owner_id, contact) VALUES + (12, 'test@example.com'); INSERT INTO iam_user_info(ID, GIVENNAME, FAMILYNAME, EMAIL, EMAILVERIFIED, BIRTHDATE, GENDER, NICKNAME) VALUES (2, 'Test', 'User', 'test@iam.test', true, '1950-01-01','M','test'), diff --git a/iam-test-client/pom.xml b/iam-test-client/pom.xml index db660af74..aa2493565 100644 --- a/iam-test-client/pom.xml +++ b/iam-test-client/pom.xml @@ -5,7 +5,7 @@ it.infn.mw.iam-parent iam-parent - 1.9.0 + 1.10.0 it.infn.mw.iam-test-client diff --git a/iam-test-client/src/main/resources/templates/index.html b/iam-test-client/src/main/resources/templates/index.html index bef2168a7..b1c437fdd 100644 --- a/iam-test-client/src/main/resources/templates/index.html +++ b/iam-test-client/src/main/resources/templates/index.html @@ -106,7 +106,7 @@

INDIGO IAM Test Client Application

- +