From 10f9305b524fbcfb2a7a7be96e6f4a0a0030268c Mon Sep 17 00:00:00 2001 From: Julius van Dis Date: Sat, 17 Jun 2023 10:09:49 +0200 Subject: [PATCH] Make use of jwt token for authentication --- .env.template | 12 ++ .gitignore | 1 + docker-compose.yml | 64 +++++----- docker/keto/namespaces/permissions.ts | 2 +- docker/kratos/identities/import_identities.sh | 12 +- .../oathkeeper/accounts-management-rules.yaml | 17 +++ docker/oathkeeper/config.yaml | 8 ++ docker/oathkeeper/jwks.json | 18 +++ docker/oathkeeper/rules.yaml | 106 +--------------- docs/Workday App permissions model.drawio.png | Bin 0 -> 32828 bytes docs/identity-access-management.md | 117 ++++++++++++++++++ docs/oathkeeper-decision-engine.png | Bin 0 -> 111621 bytes package-lock.json | 32 ++--- package.json | 4 +- pom.xml | 6 +- readme.md | 98 +++++++++++---- .../eco/workday}/mocks/LoadAssignmentData.kt | 0 .../eco/workday}/mocks/LoadClientData.kt | 0 .../eco/workday}/mocks/LoadContractData.kt | 0 .../flock/eco/workday}/mocks/LoadData.kt | 0 .../flock/eco/workday}/mocks/LoadEventData.kt | 0 .../eco/workday}/mocks/LoadEventRatingData.kt | 0 .../eco/workday}/mocks/LoadExpensesData.kt | 0 .../eco/workday}/mocks/LoadHolidayData.kt | 0 .../eco/workday}/mocks/LoadPersonData.kt | 3 +- .../eco/workday}/mocks/LoadProjectData.kt | 0 .../eco/workday}/mocks/LoadSickdaysData.kt | 0 .../flock/eco/workday/mocks/LoadUserData.kt | 116 +++++++++++++++++ .../eco/workday}/mocks/LoadWorkDayData.kt | 0 .../flock/eco/workday/mocks/Users.kt | 44 +++++++ src/develop/kotlin/mocks/LoadUserData.kt | 64 ---------- src/develop/kotlin/mocks/Users.kt | 38 ------ .../kotlin/authentication/KratosIdentity.kt | 12 +- .../kotlin/authentication/OathkeeperProxy.kt | 50 ++++---- src/main/kotlin/config/WebSecurityConfig.kt | 102 ++++++++++----- .../application-develop-kratos.properties | 47 +++++++ .../resources/application-develop.properties | 1 - 37 files changed, 628 insertions(+), 346 deletions(-) create mode 100644 .env.template create mode 100644 docker/oathkeeper/jwks.json create mode 100644 docs/Workday App permissions model.drawio.png create mode 100644 docs/identity-access-management.md create mode 100644 docs/oathkeeper-decision-engine.png rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadAssignmentData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadClientData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadContractData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadEventData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadEventRatingData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadExpensesData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadHolidayData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadPersonData.kt (98%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadProjectData.kt (100%) rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadSickdaysData.kt (100%) create mode 100644 src/develop/kotlin/community/flock/eco/workday/mocks/LoadUserData.kt rename src/develop/kotlin/{ => community/flock/eco/workday}/mocks/LoadWorkDayData.kt (100%) create mode 100644 src/develop/kotlin/community/flock/eco/workday/mocks/Users.kt delete mode 100644 src/develop/kotlin/mocks/LoadUserData.kt delete mode 100644 src/develop/kotlin/mocks/Users.kt create mode 100644 src/main/resources/application-develop-kratos.properties diff --git a/.env.template b/.env.template new file mode 100644 index 000000000..1af83a01f --- /dev/null +++ b/.env.template @@ -0,0 +1,12 @@ + +PUBLIC_APP_HOST=workday.flock.local:8081 +PUBLIC_APP_URL=http://$PUBLIC_APP_HOST + +PUBLIC_ACCOUNTS_HOST=accounts.flock.local:8081 +PUBLIC_ACCOUNTS_URL=http://$PUBLIC_ACCOUNTS_HOST +ACCOUNTS_SELFSERVICE_URL=$PUBLIC_ACCOUNTS_URL/ui/ + +PUBLIC_KRATOS_URL=http://$PUBLIC_ACCOUNTS_HOST/api + +INTERNAL_KRATOS_URL=http://kratos:4433 +INTERNAL_ADMIN_KRATOS_URL=http://kratos:4434 diff --git a/.gitignore b/.gitignore index 46418dc65..11d084932 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ secrets.yml node_modules coverage .env +/docker/kratos/identities/existing_identities.json diff --git a/docker-compose.yml b/docker-compose.yml index 1a262d6fa..7e3512299 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,24 +1,25 @@ version: "3.9" services: - workday: - image: gcr.io/flock-eco/flock-eco-workday-develop:snapshot - environment: - - GOOGLE_APPLICATION_CREDENTIALS=/tmp/keys/application_default_credentials.json - volumes: - - type: bind - source: $HOME/.config/gcloud/application_default_credentials.json - target: /tmp/keys/application_default_credentials.json - read_only: true - ports: - - "8080:8080" - networks: - - intranet +# workday: +# image: gcr.io/flock-eco/flock-eco-workday-develop:snapshot +# environment: +# - GOOGLE_APPLICATION_CREDENTIALS=/tmp/keys/application_default_credentials.json +# volumes: +# - type: bind +# source: $HOME/.config/gcloud/application_default_credentials.json +# target: /tmp/keys/application_default_credentials.json +# read_only: true +# ports: +# - "8080:8080" +# networks: +# - intranet oathkeeper: image: oryd/oathkeeper:v0.40.2 depends_on: - kratos - kratos-selfservice-ui-node + - kratos-setup-users # - workday ports: - "8081:4455" @@ -26,9 +27,10 @@ services: command: serve proxy -c "/etc/config/oathkeeper/config.yaml" environment: - LOG_LEVEL=debug - - ERRORS_HANDLERS_REDIRECT_CONFIG_TO=$SELFSERVICE_URL/login - - SERVE_PROXY_CORS_ALLOWED_ORIGINS_0=$PUBLIC_INGRESS_URL - - SERVE_PROXY_CORS_ALLOWED_ORIGINS_1=$SELFSERVICE_URL + - ERRORS_HANDLERS_REDIRECT_CONFIG_TO=$ACCOUNTS_SELFSERVICE_URL/login + - MUTATORS_ID_TOKEN_CONFIG_ISSUER_URL=$PUBLIC_ACCOUNTS_URL + - SERVE_PROXY_CORS_ALLOWED_ORIGINS_0=$PUBLIC_APP_URL + - SERVE_PROXY_CORS_ALLOWED_ORIGINS_1=$ACCOUNTS_SELFSERVICE_URL - SERVE_PROXY_CORS_ALLOWED_ORIGINS_2=$PUBLIC_KRATOS_URL restart: on-failure networks: @@ -63,19 +65,19 @@ services: - DSN=postgres://kratos:secret@postgres-kratos:5432/kratos?sslmode=disable&max_conns=20&max_idle_conns=4 # - SERVE_PUBLIC_BASE_URL=$PUBLIC_KRATOS_URL - - SERVE_ADMIN_BASE_URL=$ADMIN_KRATOS_URL_INTERNAL - - SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=$PUBLIC_INGRESS_URL - - SELFSERVICE_ALLOWED_RETURN_URLS_0=$PUBLIC_INGRESS_URL - - SELFSERVICE_ALLOWED_RETURN_URLS_1=$SELFSERVICE_URL + - SERVE_ADMIN_BASE_URL=$INTERNAL_ADMIN_KRATOS_URL + - SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=$PUBLIC_APP_URL + - SELFSERVICE_ALLOWED_RETURN_URLS_0=$PUBLIC_APP_URL + - SELFSERVICE_ALLOWED_RETURN_URLS_1=$ACCOUNTS_SELFSERVICE_URL # - BASE_PATH=/kratos - - SELFSERVICE_FLOWS_ERROR_UI_URL=$SELFSERVICE_URL/error - - SELFSERVICE_FLOWS_SETTINGS_UI_URL=$SELFSERVICE_URL/settings - - SELFSERVICE_FLOWS_RECOVERY_UI_URL=$SELFSERVICE_URL/recovery - - SELFSERVICE_FLOWS_VERIFICATION_UI_URL=$SELFSERVICE_URL/verification - - SELFSERVICE_FLOWS_LOGOUT_UI_URL=$SELFSERVICE_URL/logout - - SELFSERVICE_FLOWS_LOGOUT_AFTER_DEFAULT_BROWSER_RETURN_URL=$PUBLIC_INGRESS_URL - - SELFSERVICE_FLOWS_LOGIN_UI_URL=$SELFSERVICE_URL/login - - SELFSERVICE_FLOWS_REGISTRATION_UI_URL=$SELFSERVICE_URL/registration + - SELFSERVICE_FLOWS_ERROR_UI_URL=$ACCOUNTS_SELFSERVICE_URL/error + - SELFSERVICE_FLOWS_SETTINGS_UI_URL=$ACCOUNTS_SELFSERVICE_URL/settings + - SELFSERVICE_FLOWS_RECOVERY_UI_URL=$ACCOUNTS_SELFSERVICE_URL/recovery + - SELFSERVICE_FLOWS_VERIFICATION_UI_URL=$ACCOUNTS_SELFSERVICE_URL/verification + - SELFSERVICE_FLOWS_LOGOUT_UI_URL=$ACCOUNTS_SELFSERVICE_URL/logout + - SELFSERVICE_FLOWS_LOGOUT_AFTER_DEFAULT_BROWSER_RETURN_URL=$PUBLIC_APP_URL + - SELFSERVICE_FLOWS_LOGIN_UI_URL=$ACCOUNTS_SELFSERVICE_URL/login + - SELFSERVICE_FLOWS_REGISTRATION_UI_URL=$ACCOUNTS_SELFSERVICE_URL/registration ports: - '4433:4433' - '4434:4434' @@ -92,7 +94,7 @@ services: kratos-selfservice-ui-node: image: oryd/kratos-selfservice-ui-node:latest environment: - - KRATOS_PUBLIC_URL=$PUBLIC_KRATOS_URL_INTERNAL + - KRATOS_PUBLIC_URL=$INTERNAL_KRATOS_URL - KRATOS_BROWSER_URL=$PUBLIC_KRATOS_URL - BASE_PATH=/ui networks: @@ -135,7 +137,7 @@ services: command: migrate sql -e --yes -c /etc/config/kratos/kratos.yml kratos-setup-users: - image: curlimages/curl + image: atlassian/default-image:4 # TODO let's go leaner depends_on: - kratos networks: @@ -144,7 +146,7 @@ services: - type: bind source: ./docker/kratos/identities target: /tmp - command: sh /tmp/import_identities.sh + command: /tmp/import_identities.sh keto-migrate: image: oryd/keto:v0.11.1-alpha.0 diff --git a/docker/keto/namespaces/permissions.ts b/docker/keto/namespaces/permissions.ts index 8f1457dbb..5e875a45f 100644 --- a/docker/keto/namespaces/permissions.ts +++ b/docker/keto/namespaces/permissions.ts @@ -1,4 +1,4 @@ -import {Namespace, SubjectSet, Context} from "@ory/keto-namespace-types" +import {Namespace, Context} from "@ory/keto-namespace-types" class User implements Namespace { diff --git a/docker/kratos/identities/import_identities.sh b/docker/kratos/identities/import_identities.sh index b8da9937f..9ac79a03d 100644 --- a/docker/kratos/identities/import_identities.sh +++ b/docker/kratos/identities/import_identities.sh @@ -1,10 +1,14 @@ -#!/bin/bash +#!/bin/sh + sleep 3 while read line; do curl --request POST -vvv -sL \ + --fail \ --header "Content-Type: application/json" \ --data-binary "@$line" http://kratos:4434/admin/identities -done < <(find . -type f -name "*.json") - - +done < <(find /tmp -type f -name "*.json") +echo $PWD +curl -vvv \ + --header "Accept: application/json" \ + http://kratos:4434/admin/identities | jq '[.[] | {"id": .id, "email": .traits.email} ] ' > /tmp/existing_identities.json diff --git a/docker/oathkeeper/accounts-management-rules.yaml b/docker/oathkeeper/accounts-management-rules.yaml index 5e5924373..b63ded6c4 100644 --- a/docker/oathkeeper/accounts-management-rules.yaml +++ b/docker/oathkeeper/accounts-management-rules.yaml @@ -1,3 +1,20 @@ +- id: oathkeeper-jwks + version: v0.40.2 + upstream: + url: http://oathkeeper:4456 + match: + url: http://accounts.flock.local:8081/.well-known/jwks.json + methods: + - GET + authenticators: + - handler: noop + authorizer: + handler: allow + mutators: + - handler: noop + errors: + - handler: redirect + - id: kratos-public-api version: v0.40.2 upstream: diff --git a/docker/oathkeeper/config.yaml b/docker/oathkeeper/config.yaml index 66983d7d2..c1d0c6b34 100644 --- a/docker/oathkeeper/config.yaml +++ b/docker/oathkeeper/config.yaml @@ -57,6 +57,14 @@ errors: verbose: true mutators: + id_token: + # Set enabled to true if the authenticator should be enabled and false to disable the authenticator. Defaults to false. + enabled: true + config: + issuer_url: --set-me-through-env-variable-- + jwks_url: file:///etc/config/oathkeeper/jwks.json + ttl: 60s + claims: '{"aud": ["https://my-backend-service/some/endpoint"],"email": "{{ print .Extra.identity.traits.email }}"}' header: enabled: true config: diff --git a/docker/oathkeeper/jwks.json b/docker/oathkeeper/jwks.json new file mode 100644 index 000000000..949be6087 --- /dev/null +++ b/docker/oathkeeper/jwks.json @@ -0,0 +1,18 @@ +{ + "keys": [ + { + "use": "sig", + "kty": "RSA", + "kid": "75ab2a62-5eeb-4362-8a23-6aa8e0622f4d", + "alg": "RS256", + "n": "u6cx6cF08Jqavfl5Mrh8_KBDXkBu-g6aY1SZsxy31ac_9iZgI3YgEkqkFqO4AvDG8fIydU8BINbbxtvDe6bgTXdagKAshsgqTHLRIrv0gPX7ZEeAU-dahP1dsWtmmgmNCzduPn8N8LBkQuj9DifGKihGr8E7LjcuGx6rvaxpsrl-bQZ5TxKZRq3CkB-vXJM8nXn48hlWwRZ8AcAUcazJFbao5xD0ejzgL1WDndXPix2u_Twl6zDZ8BlMmUKmPQUr9voWLA0CZbmpF3Temp6ENW20ngucrv1MsWE65MQnFqnt5bnlL30OJWdV3u280Dqchhr1b5CtNOdB0lzzGdmVuw", + "e": "AQAB", + "d": "qPy1_DXVI192_qGMvVpaY_3G7TfFOLax3cWv7BZujp7hAMAqT4Tu-Mny3thsu2ktH3Dmc7HD6FjU7k21ysLKt7hF7hNQRcg4H0Q-hbMRSpk53GJvdB-h6qVoHIAFk64KMBGo2-r7GMcgYwkB6h9zWz-N-HRg4QucH5wNOO_s9556GHe5tRVuz4YsaF0XdLXS5bPLgkAtVZhE_4KCaAaZJL4aV35zBc2HMKZ059L3H2RnPQtloEDUDbeDPPZKwUBCBhGNQvz6GkaYn-sdgIQnHv374RfXDHga2_qDKBbNIKno9F59tt5ytijrtqnJGovAMnmT4bAn7ExpUw0tMfC7gQ", + "p": "wVwk9tRW5w4PTyRuo5eYvmgRmfDUFWYreQCweHkKNT92EPUlJQevKcfvKc8DM2CH3T6o3KVvuNVq4JUsPAFh7MWW_V_H_HDZQ6Q0iAyb6mTrSdAjHrnTY9MHc-aDSKfuneXY_e3-ag-0gmMBng7Bu0PxomWZZHhWZ7aclAEitBs", + "q": "-HHEhBkjuycQg6ZdbOP4SFHQ_X6CQNXrHP8RWnYpnwFCV1vnccUxOHsaXZkJSVU1ibLD9eU_iTtR3F4zPFEEmIM5JVuBvLJcHqqBbEDYPabPoefAz3yqzUEw-yWG2O9JaD7u4zl-zr9R6ieMYV0IyGuGvRkPk6MnhJSsr6RcfuE", + "dp": "NT7pkurwL1pIzvNqYDQ7xJsl1a1iya3D5ONStSonrHgYTB0lqGfQTYIYEvxFll1LrJo3p-MKu-xRLR0G_FMpIylaJdW9XX-55I2QRbKrMMWvoTjmouxrEL8o-zqMBnLwG50SvwJNn-lJPOqEpIDNyoKwRJcTwX391TuNLJiPdOc", + "dq": "F_8VFhU_iEIbrDuTZoMWZhXQ88sWVaDT1rckO_KRzpPWjo2H60s6l9P8FfJEHVsnkqc7mjKMUnrySzCmDjtdEEYMbPlLrKglkaiyW3xf5oSIJYE29FN8Q9r6GifjwGxMUM9TT4ssHlgIV29-daEAyirolrcm9AGcPYgGrehYLsE", + "qi": "fjD-SuFpHe3xgk-1SDtjV19QtbFmchjoGuWA5A9SPiA-L3471uv9mI5zil-GS54URtuVBd6QZ404zBR7cuc9VnUHE5k_avKfQh0O4uIkOF7o7TMPf8xc3d4Uee2uKvJsASQw9rNcwtpqKSismxTNE86SoTa8zEYjYDdgYr81zTE" + } + ] +} diff --git a/docker/oathkeeper/rules.yaml b/docker/oathkeeper/rules.yaml index d5c7f84c9..0c89de1c9 100644 --- a/docker/oathkeeper/rules.yaml +++ b/docker/oathkeeper/rules.yaml @@ -17,106 +17,12 @@ handler: allow mutators: - handler: header - errors: - - handler: redirect - -- id: echo-public - version: v0.40.2 - match: - url: http://localhost:8085/<.*> - methods: - - GET - authenticators: - - handler: anonymous - authorizer: - handler: allow - mutators: - - handler: header - errors: - - handler: redirect -- id: echo-public - version: v0.40.2 - match: - url: https://<.*>.gitpod.io/echo/public/<.*> - methods: - - GET - authenticators: - - handler: anonymous - authorizer: - handler: allow - mutators: - - handler: header - errors: - - handler: redirect -- id: echo-protected - version: v0.40.2 - match: - url: https://<.*>.gitpod.io/echo/protected/<.*> - methods: - - GET - authenticators: - - handler: cookie_session - authorizer: - handler: allow - mutators: - - handler: header - errors: - - handler: redirect -- id: echo-elevated-authentication - version: v0.40.2 - match: - url: https://<.*>.gitpod.io/echo/elevated/<.*> - methods: - - GET - authenticators: - - handler: cookie_session + - handler: id_token config: - check_session_url: http://kratos-whoami-aal-aware:8080/sessions/whoami?aal=aal2 - authorizer: - handler: remote_json - config: - remote: http://keto:4466/relation-tuples/check - payload: '{ "namespace": "access", "object": "{{printIndex .MatchContext.RegexpCaptureGroups - 1}}", "relation": "read", "subject_id": "{{print .Subject}}" }' - mutators: - - handler: header - errors: - - handler: redirect - config: - to: https://8085-flockcommun-identityacc-995ctfvg8og.ws-eu96b.gitpod.io/kratos/self-service/login/browser?refresh=true&aal=aal2 -- id: echo-keto-get-vehicles - version: v0.40.2 - match: - url: https://<.*>.gitpod.io/echo/vehicles/<.*> - methods: - - GET - authenticators: - - handler: cookie_session - authorizer: - handler: remote_json - config: - remote: http://keto:4466/relation-tuples/check - payload: '{ "namespace": "access", "object": "{{printIndex .MatchContext.RegexpCaptureGroups - 1}}", "relation": "read", "subject_id": "{{print .Subject}}" }' - mutators: - - handler: header - errors: - - handler: redirect -- id: echo-keto-get-finances - version: v0.40.2 - match: - url: https://<.*>.gitpod.io/echo/finances/<.*> - methods: - - GET - authenticators: - - handler: cookie_session - authorizer: - handler: remote_json - config: - remote: http://keto:4466/relation-tuples/check - payload: '{ "namespace": "access", "object": "{{printIndex .MatchContext.RegexpCaptureGroups - 1}}", "relation": "read", "subject_id": "{{print .Subject}}" }' - mutators: - - handler: header + claims: | + { + "aud": ["http://workday.flock.local:8081"], + "email": "{{ print .Extra.identity.traits.email }}" + } errors: - handler: redirect diff --git a/docs/Workday App permissions model.drawio.png b/docs/Workday App permissions model.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..a7bad596f7124876fe61dda12747210c28be71b0 GIT binary patch literal 32828 zcmeEu1zc6zwmz|mO(>;+bf>@uDWySLx|-I5^}Q>M8~}IC#`J zIJmcn3E@iDS=2QA!u2&!Q^Kiu#P|^hhv%c;Q8PdHpp(vSSR5`f<(*Glq9RV7zJ6R{ zDqNzXwq9OB4$iiYKDO?@LLOK@xCGz3dpbCubjCXDv=J2%6+0**aS$VEBqGTrrg&)k z9|<9h z%kZzRA^c+o|6@d~G2+&eeDG1x%gYUGinY^nhPP1_7n2kclYq;-TIxo}w7Eo;;j^2w zD;9pKVeMT#kz16Vd_3LZiYf+kNJs?v4=x(op0xFG{!JIi$gqC4jyt3B#OfJq9aJ&b zIjCmhs-^8?rfBQ3GnxRbkFT?*$L`=ULeS;T7kC4Az5ei`y{Cr<)_!+=cYCz;@$n4&!)7Nv-F8Q}+r|q9{s+Ay7Yyxf zVdAzY<~PkuogMr@KoE(UIuBdj&*i)`uS)H@k2Y`xZD10y*m_NCtC;4z?}}Z zFa35|b|&)YbozLDLVv$mwcmdIvypp{GS&?d)1MQ$`y7y_|Nnb`8K=)LyX3#p-9b$g zF%dUwU2S*ClV;+9KK5FH$_HVGAfgap>*l{ZyPkm_Sf8D%zJ9?!=N#(*OR)Q=r;neL zr=zEbt=rLGuPXU?`g=HRZ+#GGrC-}A0+d^Sfu3yF&F{;7h<@6Yd45YgTK!^6)f7`Y4SAEwDC__wzqfB$;l_Fq45 z{3$BG&h74W`+EBO*zeB8pPaJYc7C=#j-dCpW$#b6+udcz%n{t+j?n%px_X{qxIq|yim2zwlfFMa zgugDJKl|Ah(_ePMUw#8IFz)|Yp%#_=y<+rnwDoWffvt$BJ{X_B2jXcU+wPyFD20AX z^|sFY@6nT34+llWW`hc|ceC~Nb++GDv<|A^t?jB^Ur>d9KO1>?dVr!*+P=2i2GP_1 z{p$9oQ2*!a+uup19yp%hcmA;`{%VmC;~41V?1we2L8s4L-s$ir<{J{!Ab01`>9d>`9=@k5P8Yp*gRw3 zKVk6x<(2^Rb9(>%m*7um=zqHF`uAvLk)4}<`mVn?vj1?$b=Ob(tB&iggZm$^NPq9Q zntJ-UI@oSU)PG>q|K+yvA8XP>V!Imh-%pcb{^di^zcqLe5&AV=_{Agp?+G4u9r(Yx zm3Ph5e|;mEYqhe`JMz z!B&2~?H>i7{Ey4--z=zzZ}iu3x_@}6`FlI`m+%v9TRXsW|G;;*b#rz^U}t*(z`zL= zQ$l=pX8=qUcfW9Vc5pzDJS88jFGR3*+o&G0#9m0KzKtY_D{+adz?B`r^|JjH7yFA6 zzKikhb_qA{+M$17)Nl~=s))qyj@orwcU_dfd1e1He1N?4&mRQ!`cD8beul%piBMGC zJndbDey5rK<(wN)$z37(x!C`{VIoHAchim7;{Pcm{qG4!eu+P}U6@~ElYhJ+*bU(R zsuT0SB_6@-=C6LUW&eCK=3m1M{FLwi88aXv3VGyh$LgnM*!k=K%)p=ZL@~cdNz^^v zoc}F?T=Abl?e1#-8wa_N#r$Um1iOLh&!j52c}RTlt49Ab5y4LG^(Qd(FAx&^bZY+V z@$7%I%J>O*i~Jc+<|mN7WBYdfO(bIc>jB6wo+^A0Q--t)f>-^LYuk0`LD>Fwmv^Vf z-#WfOU;iiWzPkZ`{`vp+l7GJYKboDtulw!X-_A7rEkoW-75?)Qi+=*{`kNDr{~AXB zr!xB=F#3?K7XP{F{}fq>BWnZJcZ*r;1=>(3W>L2NRRN@+#-lpfp8C`lX8YGrhoS5u6 znxlQ}v`=>S=&3%BymYo4X?n4|t@jO&e#~yArZ_eZg?tIUIkpxSR<-PF?RxX8|7+Kc zi>^0+Smm9U_I;OJm5zhn{ZYt92^HrjWHJhK;8L+}|LCE3x#@^G74UX`FqB3431}8! z?w{Wm<=c?`(m|(6lpQ;FSd&x_YQLZvtKk*xjO90>!k0W4rMwj01Wl2De0954#dS() zpO8hJ`o-XP^sD2sd)ZxvMp(YQxOvVp_-)R@+`YYyb&}k%P5CJGDAXh6D7%>A3Bl-% zAItq;Uf(SZTV0^U4A(hl8C^3tx`*j7=aW$pHtt*QFS$o*9rG@$rJbykyp+0d4|!b* zZrn48B8v0&YiLH9AiX;QpZPtT7jvIqH`cln_*IDfz@hXs`Asvch*hjOUoNk{(%Ryu zt8xutt3J2CJvu^A5L0d6t=S$!@OHkNC9f-qw*2wp%%GMrNraHh$vm66elsu&m;JpcNobt@ux?c>$bkj0sr zkVO~g7dHyVU&_15{Ftq+iP#8f_jett$jLo;Tr-VXc6#koWuE?J)!vryAJbX7av2AY z-zw9_on@2@lj>i(C@l7*&e@P&!Y$wEx{=16k8_`0)h*vV zGs?>4lG13;Xgh_Rm%1y~Y(*zuf)$ymM{!ePRFeYld91vL{4V z?WiJ`Uk7sW@oBsXe$RA!Y1Fk8Ufm@|)_*2j`=X3_uF#3=+`%-&dj+j;nAfUqFxyRE zPLs=wi$n35R-AVkVu@U5^PhR1VI8r0G+fRBpE{^O6r0_qVEy9e@vCv**KNy$QAC8gv3u3cXdo|m=$w-JM6Ive!Fk+v-~0HO3T{@ zC&nsH9Jyw4^XyqCWhET>t%-P+5|_d2qTy?PT){L28odQ#S7%?{HdIZfVnkiJbvrO_z6EY4DJ(3i`@B?+7Sxax8*QEv$v0I0tvGO zYe@4y=+C^kS)Pl_$}Or}u@aE-FtPaY#8!{GjZ);|py{9}9(R}niIN@O*k}g5f?~kb zm2)1Mc3o$%3Fz7I#<#i0OZ-2*;C~h!gQXF~+DPN}6H^?X>P~xXpw0R$T7z*U*=?i- zn{fWb-GJV?iF>6%^OJo#>e@E93FxzKj54I=6Jzz13ebX6toG4lq%|}&)a@;_!y#0} z2Vip+1wWWvV*laQ%avCqOV}f1RAFfz{!C4ktv0`LD)mS<9i6mKNgs_38dZRHU_2Z! zTeit+A61&-)rnFebYs076;9-Yuer6kL2!-^Ghu(5K#Q~Z0V)oEiKl5}=_P#(s^D~c zEKzxgXbciNYES;d&Qp8z)zLVPJW0795 z693DnV;3lB&6L{j_mx-N(R8OGm$f?cfH+s}3=Q9<(X63pP$yIsoU$` zPNiw``RMT)i+B0bzE@;c#$)^Ba_y^Tsi~;Vo<S(EP1*ut$BfIvQmT4=R5NM&)-{uLL8$|s0EV*bttKVjy-lK9}%3BGI zGu(0UjF|)z`;Vyby%adSWqW_HR2Aas=1uozy%#BN&YCOw4{mk3%*eegSXcXo7o#v;-^^~6#N zDn=VDThAN&myg-Tw=dH#K*yV$piFgJtBm!jyxe{KZ?@{6CO}N*0JK&TvpFlN)mGm- zSigBTh5Lmn*drkjc`uE5-)PpIPVgz?+&Ixv>aaeFS6{xu4sn|ft-1Qn)_8JKIKccU zE-}B1*n_)$xj!9dWsV2;3_5b{)Xg)QQLb6#t{W+$fW~GJ|t63gi@+IDx zrqeReu{`v!@=VyxID2=JvTfV@Ve$?^>jAR-cMo?*e)4i+J?xt}Etn@ugLO;RoleFS zP;3kuczdXd^1TK=N(7E<&&Md^-B||M)3Cnj&E2;Om3O8|bXp?{wXOlPQ5a!ceu;Bu zk}i{xTEXNMLF>4aZHGK_cSbJGaO_43N}bgb#xjvP`5sSkrxQYU;t_Q!uXJb~tJ841 ze_IlU-VI~N)LDBFv6+> zJ;jcIkOf1>kR4zh;dtgSgUywI=VLF3R z+NTHcn4F$m@&Usl4V!lMWrOa*yN3)PZcTYZtRj0HVVJW@x3I)J^#TD*Zy+W}@L$9gU^gkwH21%UUWLYD_#i zIij7wXYAleKSXVfS5Qk`;lRbqJ;~sE;{r;3d<$gE=8%~(Yh7T+sb(s+tKJ3o&dy=g z)L92$vhhC4Nyv%eI`E7(cnXU-KB|kTM0KI;5k;U2U$0M-_rI*My+^2_p^<^@&+UbI zoE|7v&Rv#je66LeolUZjUwvb3vGmwE34;pD+v5SJ55f)`(1ERc#Lff<@Ach4Q~Fq) z3x_qbxQ~_iyzR@BkBsP;=ZnTC+M{k^aaPc>QSXX&!6i{SYHsa0XV(!y*le6O1JhM@$knd%hS+&E8 zIQ>RwG}>~Z>fVJ}0(6in%%@oPq3i-2iQ^`fRwuwWzF$h7q=c`<%%z!~Zd`8SZFuEq z1lClY)dae$rkY+fr=k>q1Z8wz_6jz_d#ZDB*;1 zsirdW)w>S8uq#xZQnTqgv+rqxr}dW$35BF)V(67r*mYkm?bKoy-u8EM?Kxr@tRt+X z#YD81xvnmLc0WjJ2`mje*Zs%wN24l(_mCRe$g6A-zVLUGLOZd6^b-iA_|#M%A^c!{ zcccGJ#&4Tv9W%?v`%z4~O6yoM?rp<}{}^6v9Fcs{j znvw~A$+f`k@TO4_=7e0H;VV~HocFYf~AaNfOmT} zS37TIpiQUdQKz&*d$om~nv#kV*3!_O*Q}~&9o%x&m-qTW0Zt;Cu4Vn^%?oxN7DLxl z+grh}YZWxBQqZ|5Q}AR&OSstxas56Ww!W&vWZn{X+ke9@UcF5KS;CBx3$0)vtB$Z* z_G^n={G95zBou%whFHldL1M4D`Xhouw;b_!lI6fzc%fh;b9_oOK!qB{dd%j8WPkh6 z7vjc&XN<#Y-XqvN^Tk6%QzKu3PJXrH0d;dk*}~>z$89>V&$84s)Q?U{9bsgHJxd%t zKQ%!)KF+{=wJ4%beCy7Ov7-B2FPY@wvGewx{tp?$ZU$6_oSk}5AQliPYWNk5tyn5n zO_l>}9KGg&KJBR3%GdMbXCqI1s(k&V|IJ4bisD#)_ruE%2gUPtEXmMh!A8mjQ0uc~ z&TOQ3jA5VmkPfYXvWWbgYPF<81nStQO+B z|M=RP2ZE)KAGRNLU8Cr;EB`uZEPm{1Wb&&U8jo5*_2QBfNt52_V^61s8?DwPcIHx=OK|V z{$3f@JlQB^dDdD>Rt?AGUt#RFxNmHM*7Rc-gm0JzT^KEV!1QtuBw4zkl*;8 zRZ?2o`=&XxR4t7;rfzj+uzXNO%zIL$KA3VW$k4#R=*T=do%1{>WHfgzgc1D^v|W8V zE!?_ZWAUk5f585Jvi?|HMo6KA``NYCm!7Q$Vf?0B6~^VcXL&IrpNFfJnIqS|7gG+5 zwdf0TAFV4kDAg48eW#5T$fYXDJ8+PBA<om~$lD1bNVc zKx#9FJjUU9nf{Dp;8=LWLf}Bswj)Iz5>~VE4lTvQJt@oU_vyv4laDVR)XEjqkIc-< zG7f11)$Bqw2Dk$ieSSJ?$Xp!mMb@^GRtPsWG&K#fp41On38Wkl&!n{u(?1~LRwhBL z8Gmk0^CS&2&llm^_0wu7lkBWdBxf-J&xQoTqTlIjc&V(Lb#2Xo3W$#uki| zcxf~(Tbn<8rh6zCQ|Qj2^hfJmuX1mxv4k7B6Ixc=o$BM(zHr!h^p<;h3*Xczgx=R5 zr_o`Qs&FYr$Yo|$Kx+GPOs%fH_*Sh?F~n}1_VCookzA^}c1cT2^y9&6hH3{-us*{# z84F*&Kt)Vp)5HC+P~JLXYa?*=$Jmw-gQSPi$QjURHgbVqEJvzrW2sVLdtH%P=;6>L zBfN%s*jil!{&n@j?eLB;8v9ow)5`fRI0TOuwnHgh#!v z6O}70l2PpUVL;L2&PVPXZ(jXNacc~^>O+0>8Xk0664&@&LF= zMz=ncSGE|m##Uyew22Z)cqk1kN_Ci0?6V=mB$A&m*r1>eQl=$>f!KNfb|Bv%mhHsL zWvu!>2YT;1SBlWOwk(yEjx4JnobxuqLms>*HtV+MmNnhMs(Z;3#UyEay z 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 literal 0 HcmV?d00001 diff --git a/docs/identity-access-management.md b/docs/identity-access-management.md new file mode 100644 index 000000000..460988e29 --- /dev/null +++ b/docs/identity-access-management.md @@ -0,0 +1,117 @@ +# Authentication and Authorization + +The intended target state for Workday is to extract all forms of Authentication and Authorization from the spring boot +and or react application, but rather make use of an identity aware proxy (Ory's Oathkeeper) to make such decisions. + +This means that all incoming requests to the Spring Boot application are expected to be authenticated, and authorised, +such that the application can focus on the functional logic solely. + +## Roadmap + +(🟡 being worked on, 🟢 done ) + +1. 🟡 Setup authentication model in `flock-iam` project (external to Workday) +2. 🟡 Introduce Oathkeeper proxy for Workday, to route all traffic through it before reaching the app itself +3. 🟡 Authentication via Ory's Kratos +4. 'Simpler' `GET` and `PUT` endpoints authorization +5. `POST` / create endpoint +6. List endpoints +7. Removal of authorities from workday app itself + +## Understanding the Ory stack + +(probably best to move me to flock-iam related repo?) + +There are multiple components to the Ory stack + +- Kratos, ... +- Oathkeeper, ... +- Keto, ... + +Every http request to the Workday app is called via the Oathkeeper proxy (running on port `8081`) + +![Oathkeeper decision engine](./oathkeeper-decision-engine.png) + +Oathkeeper performs various checks: + +1. Is there a matching access rule? If no, handle error +2. Is the user's request authenticated through a `cookie_sesion`? If no, handle error +3. Is the user's request authorized? If no, handle error +4. Mutate the request (e.g. to amend user information to the request) + +## Workday's permission model + +[Ory's keto](https://www.ory.sh/docs/keto/) make use of a permission model, to determine whether a given subject (a +User) can access an object (e.g. a Workday, a Holiday, etc.). A permission model consists of two parts: a relation +model, and the derived permissions from said these relations. + +Below you'll find the initial _relations model_ for Workday. +![x](Workday%20App%20permissions%20model.drawio.png) + +Which can be read as + +- A _Person_ is the **owner** of a _Workday_ +- A _User_ is the **owner** of a _Person_ +- A _Flock_ is the **organisational unit** of a _Person_ +- A _Flock_ is the **organisational unit** of a _Flock_ +- A _User_ is the **manager** of a _Flock_ +- etc. + +> ℹ️ +> This model allows manager of (a) Flock. to have a relation with a specific Workday coupled to a person. +> +> E.g. _Workday-X_ is **owned** by _Person-Y_, which is part of **organisational unit** _Flock-Z_, which in turn is \* +> \*managed\*\* by _User-manager-A_ + +Besides the relations model, Workday also need permissions assigned. Ory's keto, provided an intuitive concept for +permissions in the following form: + +> _subject_ can **permission** _object_? yes/no + +These are derived from the relations, and are essentially a graph traversal. + +In the permission model the following rules apply (amongst others): + +- An owner of a Person can view and edit all owned Workdays by that Person. +- A manager of a Person can view and edit all owned Workdays by that Person. +- A manager of a Flock is the manager of all Persons that have said Flock as their organizational unit. +- A manager of a Flock is the manager of all Flocks that have said Flock as their organizational unit. + +for the implementation details see [permissions.ts](../docker/keto/namespaces/permissions.ts) + +## Developing Workday with Ory + +> ℹ️ Prerequisites: +> +> 1. In your `etc/hosts`, the domains `accounts.flock.local` and `workday.flock.local` should both resolve to 127.0.0.1 +> +> ``` +> 127.0.0.1 accounts.flock.local +> 127.0.0.1 workday.flock.local +> ``` +> +> 2. Run `docker compose up -d` to start all Ory related containers for identity and access management. +> 3. Also, make sure that you're The workday application tries to connect to is expected to run on port `8080`, with + + profile [`🔗develop`](src/main/resources/application-develop.properties) + and [`🔗develop-kratos`](src/main/resources/application-develop-kratos.properties) active (in that order!) + +By default, the `kratos-setup-users` container will try to create identities (= users) found in +the [docker/kratos/identities](../docker/kratos/identities) folder. Workday can use the resulting kratosIds to bind them +to the mocked users created on startup. + +> ⚠️ `kratosId`s +> +> Note that the `kratosId`s defined in [🔗`Users.kt`](src/develop/kotlin/community/flock/eco/workday/mocks/Users.kt) will +> have different ids from the generated ones. These are substituted with the actual Kratos identities when Workday +> creates +> the users. + +### Generate a jwks.json + +(flock-iam material) +To generate a `jwks.json` file: + +```bash +docker run oryd/oathkeeper:v0.40.3 credentials generate --alg RS256 > jwks.json +``` diff --git a/docs/oathkeeper-decision-engine.png b/docs/oathkeeper-decision-engine.png new file mode 100644 index 0000000000000000000000000000000000000000..8462e52ddbb7bacbc96629df493d581e4d64d4f4 GIT binary patch literal 111621 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 z zu-wsy;mJFVZ5RlT$g!WlKWr-*>k()VTk2JNN5;gDkFTtGN06nhp~b~@smt7;>E-*r zbTO?LeW|&9X~HT&l9YT#T#{ZJZ~y)!oa6)MR2<#iDeQuRZR(r>lgcX!O}N>EeM_!S zEb669b>B7CN5x365mNHJov5_w4Z%Ds2^31av)$BouGc1d%ya#OM81rv0cnf`opEod zMf*A>X%nzFt!l?i^a&e51vP#%9u&Uw)XFOGhZ=poig8Ab-h+$pIy!Ms%REoY_VbMD z-MfX?DDDUfYO6hb_z-t$abe-kA4!?Qu~??2KQ@iCeP8)I8s~*SrggyKpL&H05tIJT ze!frUFt>c>Y0M2z7c0oW56n`EUl|Ms$C?D7Z*%y?i-cEA-m^MR8&^(0nKgfNS0dJh8^e_ zK*HOx*UqS77n0)&&ALs8oiS1=QVlVe%r|o`E8*d_NmWuLOs!~TO1yVG>%Fl_ox9_* zcK22W{Df>8Rj?z49-@eNV#y%UhqHd$(!?rGzjK;9Ok;lJ5-CS8GaJ=qaNU3Tbj&4U zu`~YrZE8>?clARc%3DD9H%lL@b%IX7EI6>2m6bJXa=iauM&iH^T+~T|`4!-}@Bmp& zwfYO?uVHQg9=JOB;~UAGH!V5Ft{DJf4*`Vl1o(T2r4qHsNJT*=zhCRXXuA!Lx1L)M zI3*vPWdfPggVkY`pM#uDf$<43G4BBCO&P#)5BeM?(ADV>^Mcvt5Ll65%aR|$wT{`}~FC5d`sUvvkCN0kvgpJ8hgen$MDhPPIFL~zUL>gX{% zV)Ce5Dsn?PX<3&ylB%zpFZ+)-&%3m_ zg~F|>vRmqAfz476z_N{Yk$T8XIaljHKmZ&rX`1fN@#C|w7U4<8wdpu#xOBfb4a4Fb zxcRMOl2i+d=%c8*_OZU;%z zcV*YJDa$t^PUFzal`t=JsdDEW1S%^4S0;7Xm-Dmf=bI&`Sth@i%}hE)CAH-eKVaJu z*XJvoow>+`gntEP5;WXCSj3$ME}hv03}$(`VskwVhw#I0Q0_~ z2sCHua;1CxfvKyBRa1|$YO16q%yiwuP9UO5F-yjpoEvNuX6BC0&$I!22ZsO*__Dmg zfjZRQ4KW+IIQZJBK{eQnt44U?0*O_Vh`ah0cS;TBG-AbT(gsw5{D3WnXX5O!CYq#hH;+WQ(KP*fNqyp?~}F z;Z1_E(sLwM=IyJ){i!()Bic*9o*$<*+M?CFHQd91S;5pbW!wu0F-su&*dZIL|4s_S zpWwE6{_W?S0pRmBPd%9{x5YA@pb6v2jP0$(*qdbM0~J?3USqevPH#2W*1MyY?XtY| z#Ll+|!VbDqs{d+bpXoIDdf0&yv%Y%X8I=#j#-Eg#NZ%%?1KYgHCE-_%^>gP==u0U(fiM|$`5zbMZ({J+AKpqC{igf1l3MDIcU|ry zkdteIb~@YPNsiy-?u7S4ndSu6hm?!sZB2kH{uY`1!dx)*H}Vz$yT6Fqj44+Z2j1R* zvx59_j!D+DQs~bM);IvWeEzb+ICI^p!ldb??8OHAebM>|Fwn)kciV*a%LTTafzf9S zB&#;_%?($;MPs8Pv33rM>5oY(vbWhChf7T_PIf*o%dlZystG`1LoJ;18n{;#OwsM@ z7SIs+^)*;HV99QI^h0xiu2eV43iuLy9@V@Z8WWaKjm%jDE+fUt@Me5ZhtY!YUjwMz zzzWne?vBfLF&`BhN~H**Bp?=310_t+tH70>I2%+V&}Y5lHkPwVpcm&KI)76ZWE(Tf zy}LH`)#BS1VbSmdwk#)s&97Yc(}_)|v*Hzw;FDZrUw#L{+?F90SmEi^e=tV!)p1zTASbWqFPz(z&s{sQc1Q~l07*er8@Uo(UH{LP|kmd$K4 z|6sg!?GJr3|KfA@&e0N5Ch4-Z!nv^$9&zOASg|H^y}$%5lKeDorHpwi%^Gff1N;lA zKR@ele}zSgXv!qU`{L<{PXMf-DKS51+pr>Z=F$L%H^xoeU#N&|2%Yo}6_~_eftKHGU$lVpVQc(hB#??;dHt;i; z)m|TH>2XUB0FG%2362wzX74jVUfTrRoInGl>%cgUStmA@+Us)Ha_*A5cYSO6E(Ork z_O7!cV{hs)_GG5{CzXv>GxHuLodRWdiB*AY12l(s8n9pN4hQQT7feC*vIN8@XHN}h zo8m6=cE+LQn)4m2eaDB*BPZSgv#wo-@T`O{ov&$B?nFFNR)LKj7m$Jyglv*!dslQ*2rZfs0(m}Hdf<$oX1mM2mJhyux{QFu{SneE@R}32{~j_WQq45*_p8hU?@dif$88k%;F5d*gqs!! z^A;wUp<=_h@%N7tx}4Vf@4KJ$-sMiW<$f6I8zmA&so3%pl<3BnedOF+}NuF zZ@Wk@q;Ye{wN_e#7N@aKKU|cyjGKBve?u8ZdcN*?agp6=5P-DQl1?+N{3*A%c}u?& za(#P_41AuqEbH9XPzo9w>0xXD~{L{?MZEV5gx&N2?iB;B0a zqVXdXi!=tqU8nia+O=*ivWVS4b=c7@W5R^Ukk+|v9SrbXzspY`CAN`4;BUxZYUcKL#*w9%w`Gq@tkk}CL@W>VXc&HGL~36#mb z8uagQ-`{la(J6(|%+Rbtj8ZA_g6F0BwOjKGSYbi!k5}HYNGCFp2r1rmSN-ioBsjJC zrIarUYeH(_)fOoR4hqv^ey&ny5(-ZyMT~80m>Sq-*3dL>eszhabz zopgV5(ROZho_4B#Abv@9zsz=Q(d%H5PCebNJ}@LP$cZqI4LFfE(u5fUNbt!JWpmPrmGJ3OnhPinoRx&b5#zGA^p6P$P8G zYt81dCIs9ykj<28?*_yjW_6Z6c#81RdxI;8RNnHXB8mIxP@W^P`2 zfHgVjn`qxm>4iKbmM2>Fi)WRLwU;i{YR#!&l*K|<5l9qv=aRq$)aF1YHK9OrS?@R( z8_hH>x)f&`xZ?h}f`oZCcaxbC6rh>7S;#`RxbAfuAj-H_X%OVr@z?kSR|&xhg$j<0 z!!kW$Di0#0dN?BvfcoZWaG7O%CJIBVvSI*BHMrSXZR153Mt)t+yy-zluP5~JaNL00 zyTugd$uI@2y^L-0ZZ$-77i+gykHi||n&OB=d^J1W2)$aAEcDKKgA1F>$T%@1=t#Md z={-ZAPDq3tCI+e_9AD&lh$JU=W^L4e?F7!`M5)xy!Hu2o5acYxTMud07Qv=N61DvV zZ%kFEJ=*m&>mZrxG)u>(B2>_hfx?H^dDfY)FUA)d1v#aRg!?EcFEyI9EHW$wH8>xT zv;{48KkRRJUe&x&j&Ty$h;w%zy8YAD^Sb`-PKc;eky>c&gM^sDJbM=th(Rr>PZqp4 z>@X}v^Gue6f`oq)u&@KbCwVF$6GDkf64MoDP?aDzoW1VuD;|3G)@R0M9HJcsIRB8X zq>JK~C9;)X@D~*7p*{*k<$B*fr7skt#2*~{V+4C>T{z5Oj{A#jm))HvwAr6`*@5@sa@X(YOp+9Ajz6|PY1%gX>gQcD z$Ntv= zJO#7$f+i>(NLRY4ice8c+opLZ^=$NYn{$WFL}Sg8`Y@OC z`ouX?oJZ+q<&;SzS@5GhSa&--RIkT&jp?H9C}0HJc1RS>&Kmh#n}~K7 zVq=dL43lARyeMI!dD|g2jB0$qj$o&8MoJ(ASXg=zWs~TDkXAL$SIbvf{`Cg&>Ga1K zCx3=-^_tYVO+h0CPX=mD1N1$m$BhL#UsTO+cBsfNdONk8?Mmmwu1j5+9SshOPfElk4OYNvQmy zgnJSNWW8uWD##^SPS+qG8+)1xLFV7#8{-=zxVV0?81OfK$>fR2zI6Q#_;tU2m6l6x z=heAkSLES3HnzAO4$ZIdpsHEkQnYSD`krzat;o$tx*&7n`}w=a?Kl2hY|X2F6Rq%w z{^PCRO1p0lBD)1+t=ZWzFqG1AOk@3Fc%2ULj;&4up(7!FXCFv{t5d2|H!LXVPEdZd z$d;n3bK0i5DodUxeOH>PYNzkD_kNv-f%B0Qi(tG^p0n~)e9&U2r-@teLOX&Ck;tVH zG_N|Dtu8T_@rKAk(Oal!t~;rH;fUjzN36w7k6@4UTe(Rk3Ao4)$FX8O_&k)_Vb60P zK=Kyb7ym3KF8--XumE8AP;fb_x4^KX*df8?g?0fLV`GxwA1hf#(PsrOhA5%1v0)C1 zyUw2oY`BRls8tg#5k+CNKVz8Nf`VMv;@P!fOg?Y|3&heJKN%&Gke&FI=uRga%aR~@ zx>Z%vqp@X%YSPF!i(pamk7pH2_nOSf@$qZD`?aq}OVkql)KgAWWn5)P1(rBibY!EHN#|g<~?hPCv&cm_-}q3Qjn=3TQt2r|Jsr5$miIhymC~h*-q1J@kz|{ zD$aJsRv6e=>t!PXoCDEXx|MQp$^Amvp!!{YDvznL+%9k>r-Ccltf+kom(vqsiNKTC zQ~`Y`aS$L-&0OIDVFBnD55c114$YA#3MBH1_2F9T9O>5SUiy*uW4~vr$J~k@6LT0F zu_Q`<0NoJV9IyEyF&Hc_dnCOA6Sl-;&+sG1@4Z_{Yw=MHhsd^o-f8xXc_r=d2+a@3 z1^u&cDszavE=#ESlQpG@LItX5A^7T>g*IbwJ?I_nlSq9?H0|JQ>)r7`&-R|E7 zr?Bmw%qPRLsG!mxpOdyJDaDQ0h<{*fY%!$YO zKS+dcFhnuC{p%_Xj0(mN6B}E-$Y{vDl%Gdx%D0y<=jf?a(36MTmdK3ZlKX z7jCb}MlG9Q{fO%@-mt~GQ>-nFJ&be=@c@z36CP`If~-XCJ|rJUG5KQP?P=i8uLY_Z7KRdcbU#>ZB&x?$ z;5J+249SBaQZrFO7bvf-2=hCu(a(ltbC~t{sR<6)u)})dvfrJ9_uSjX;pALaRQfAE}a2xJ(z0;J|zP;WHeEbS0GF41#&RMRntL0fn zY6|Md7lWmjEbR?H$~gnKGOaU&SziejaZIfTpA4S^2hBn))-LtweE3n57;*vnT;A9X zB(t55u?wS(vsX-A_|}|1zuYIP=Xo%^WLTUt1xh@;#@uWeYsGQS6(BEht=or5Vgy@X z1>T?n-FT9KcMRV<2MmdKy`wY=axi=MG=4G5TXk&x0XM=~;9V0w?rLzEyhQXJHvh3F ze~Or3XI+=HUlSTFWwCb!_Q<(e_IGarZ})C(ZZhpp(Rxq`8W`d@uwp!&l9`U^^N$#+ zq7V4U?XGuW_dOjKl1*iNH9+6`BKOZ}7Zr8Bjx_-P8xLwydLi#e=cu|_`eUV*2X|Dp)s^<9v?iM7?5`==L7pC-T0t?DRmbS-0 zk&df~-BMZ9@pvSqS9S}lG>yrrU(x?{JKlieD~LKoc6Dt`wVqXmK}Vk(EOs+|L1Q_R zSXV(vq%^tCR6=NoE1jFu##|99Cr2~z28L>rB?{07D|riM>+Gs?XPBRLphEV_UDHd< zl}Se+l{RubF!t7&^t{3NqTj=`?tyo&>_Z-U$&`NReEDp)oaH|IheWc&67z<8%=cj9&+&lyy&4;XY7QfJnNBqpeLCZF7M zYW8)2xVz%^EE6q7O!WbiJvN69{C7{- zOBVTD%%UDTr9>YXA2g4rk^4;Tr4g+*6vkhYKa=-8GPgoY8yUI+^ zx~sw)tbcxcIxT~|mx4IBVb!k7wNBl3nOqLk-iI{`KO>pPNljWP8t{$vS*JUXlUKTc zA*G^fy?c7oZMpoX8QnX4T>^f(_A0D2KXwzo~rFkm;AleHEl#L?(Iqx z_MtWXEgrFVxwFNV1py6zTgBcH^hrC&3YeUzaqS+y^#l^v? zt&8!n>gw8EO|spwEwpce_UB&L7N-|18wiem!}Q2*K1l$P=VY3U6z*48y&cKUlPm@EXt6| z?m_b0s3go2Y+Wupem<>g74B!xXlt9lvX}KDy$WlTO)t3|lG!g^aXjoeuu3JpoMpg= z{5H1U_qjT^N_|^)(0HWu%{LH^jdVZX_uQY`u2``5Tyvh>Il(z3{^eVx)p5DquP!rN zpVQEamJk1>XoulPlKdGbo4m?lSI^MDy}4cmN;Z`CJk+x}NkomYwdy(HeZHc6AG{W^ z#NXz2Kz>Vtk1r%dN>`zMw`VOw$YQ*+L5X%u8#98pr%Ys@83%#OsLSq`Co@vhmx$r> zCloWD{8AA+>~)UzU8K~ZKAH2qhuv~bEAzaxEzjz2z`ciD6^HeHMmp^l+IS?GL#P~9 zA0u?|q%8gry%*&^1VW= zgJE|mF`sUTAOsQeZbvu`UJF5wJMpHwz80!lomH7v`_G7}YiPlrE}W%v?9mc}MM)51 zE{H4*NBJLrdLjINLV$vnHXrGWsYTvXs#r zb93;LD{G7Eakdw-+?{{S3-amvdz=U3LNojxpI3JqL%5qfcN0NF=z;cNtRf&V();%Q zJ|jg(w~5x(iz*$~2L@G%P(_4>TvRGhhNnu@SoaO@%%DXx*372*A?I|4q^G94B>|_7 z5mSzq%wF?zt_-v3@Q$}}5O+mxA;0TmaW}<{*ovgJa*=6kOIff;do&~HKF-H@EM0j^ zcG=GRox82inFZXaR~SQ&hzNZ#P}pu~oz=yXzK?6{_GW5kWGf>6CWqAYHZg}XB(?i0 zY%HWxuB_QTFS486uhYtu*1ZV$t@^6=-4gAeHMdrVf}aNE!E57Wuorw~2D;XtZawx{ zGG%N_&=Qs5+!(!Va_$IE(mguLBH}JDDzC_Hv&J&bVhVK$hrxF-8N`%m6-qkUj`zN4 z=gfDzw4OM+a`UMCsS0}|iK@WLFJp;AOY;gS0ZDJ>x#qEEZ;^(#=pinaFC>H+EJ_?k z;n-vMWEW3#D)O}Q2IgjfdB z9NEMLW=^O!CAN#Wq^Ho9P=N(u|WX-6ni;tGkajh(uC%b74 zu5bGi9q}|HNtg$GAKShcrBEV0SReYVh%t(zOjqUM1MU!ufIw0hv|lj<@DA9ql65J+MGS$*EyBEr*d`BAz7xs36+`#QM_?O7DO&+X zHv+yvSc!im?i15bOq!|`XzKALcMDb%lPcfeAPc+q4G~2p1vIBXDQ6IH@z-~A_WZ8R z)QBAR($88}d}XGuEkKeq25^6H`@s2GiE4|>m(i_G&>b;&rFX1Pz}bvP z>kxBh`04orBvfY6Uc^`QGkU;cMZI*#3x7N${*POWRBY)BAC4FQ!?6PLYK&98-QI=m z$xZ)4JU#uXf9^JtTe7f;vXF^$?2N&aPN4U4MTlhzU6ay67U^vkTH(X0?GN$)^V@GH z16m|Ed_}nAH?$aB`0Wu7{L9tijel|~8MO<3=T7$KfCWtixkFJ!x0BvHFh+dv@)-Jb zf1pJ_^S7vB+`oh*sA6of1txBHra2$j77fUbwsdhiEw3IMes@!UMPt7&%`V+eyE*qc z9ST7^R!qK+D>HZXzH)n`wDq-cMR)7kv ztiUG_*yuikz?(~yqnF<|j}=~9<<3t_y&c70!ef55{)I=s0!Ap;2L0AYNxbr8IpN{H zwq2AfGrhklw-`*^^E(l}q_XVw5oI~pkzJpo=%L zG_qRj$ZTGzI>(d@ya<-rpGW_DIP&>YWxdA^vuf;>D%S@!pchaOdbBLn-aG!XfBY&l zBW7N(=QkQ%p2lZdglui;?ZRV-?xW;>*R6JbAm&|QF0FlYpYSH`p;M0o5TyOyKlRC! zwka4^8vA6WSq^liD)(7P$XLS++HZkErz8UP>$ARgqvtjk5Q&Zo&MD!YZYNeJDv>Fs zB7okqwBwT0s74bdaO8i!v#9XaGXewb4-tRWybNpHhQkO}irj#Z`B_hqNp8SJ`Jef3 zN^!5~e}MR+(k<=+rNapM&vUeTQu6u*DA0_R(08-zhY15 zzU-C9{_Fc>87Q2#@%cEzn18d1YPibkO@+3k+eo4j!%wu%6aFHNf*qE&5`v;bGRs!E zq6UA>Ki%yE4F!Jo5dh1m$~!P#ekpW5$e+MY=pwWpQlVGlM!?H*#RCvHKfUp1jd5$bXFgel}ku*$_)ie7KlXimt?NS6Xf2Z z?kmwo9S9qV*#29I+?b`Qr$3T`y4PW@k&a(mfPNrcsNt#Jo93Z}{gC{MN-ndsw_pYX z#bEIYDtExX6Sl)dqoT%?Q7RwFTvYamGVsAmC>+8C^7u4@6@+@OY>WFDl`a<1W3}wh zES?VV+5LsG5Dgy&Uar9m*{5O-XPRu#+~KWp%dQNG|BEu#;L=5!mbz0!tWOEoSzjYOhBxPu_BmR;@K$f zjK0LjS7u;=d2EguswA{Bzo_y|AS7M2*2Mt>mU(yYSz7InVaq3iFRiN1;nn|pp!b4< zLOlr#vOFeDZb{;%flBGWJI)+{YTfR4tnWflx(*;t{Cx0Y!^Q~+bY5!RS^Xf;?0c=As4BY%{L{o4UX{_~+ zUECPsh*)c-gZNC%vau{AkXwu>tq(1u_wYjS8&w-fsb|EdoeC-qp?3?kJsP+wVDeQC zJ9KD0EZt(*IpF?jHF|>n8z(zIE$j+@l&UhO`EH^z@=WXOfAawt;qg{WBA;o!e8Sxv zM;Zwn?t5q4k5?UE@q{?+$8e3y#_pzv7w0{s*rUzy^D4m!c z3wo1twm_7PIK5tAQm<+t1O|s{hWQR(kDU=t$AQ!bj}Qq=V!pyL|0bN4LgZsF+>@WH z9GT*t@c=d{Wgmd;bBIfHrUK2C&UqV#hZGl%I48>Jw(kHA89xbKMy|O4k)N4cz#^f- zJW;8yO=0iC${tDf{w#R5g;Y8Sv=2 zV85WRCg_DMR3zOF_$k z8QH&$(%7lRyA;Zlt`Le_rkfBY|6CEcLoK&b`x;@t$MFe@E{jl>`m>1r!i4GV5wdpm zt?{Nh1}Ptd$SATjlR_2u=r~!&QAU-i<=j&FU8#Mit{ORhlh`CmM0{`7PhP95dZFpo zxh*^`B8?{Gz!qME%Y#89dB=N~M&IADqRpNam^A@&uXf;Xl9dl?mhix0`yJ^!-*i!< zE%%evnn>obtL_d>HSH`y-26J%_6y}24qBQ{gS=1V1%LN<1Y>gsxS~*S&xxgC1nl>q z^-xxR&&>)UL34VBR^;DdPqPpqCy2E84d~Kx4|PTE&IJ6I} za%CG~lUpBoS3y`|^O?C`P=66_feZ$Ne-i2lvM$Esxdi_er{&^ zLN5@_asV0j7}@h_VRH3B-5{OzCKh+au7h$)I*&ar3q)+%nr3?M{9Kb857u`T9iFQ1 z4q#rp%HJ_)v~-sAMVXWNkAQ<59txNb|2)0s%{oq^UL7k2RYxo&f|_y%U)$A9tG$xq zpOJ8K6nUWnM#~FNT9tt7RrCw&s$+55OK#=4%%4yVf1UIcZfGKJU;59ayT5YHrHM%i zaq7mxFax+bySL9K7-zn3=|w8FGV+0AIvQXIwLee`RCL*IsB6GS1k;E0gS-qXW}E1O zkAUxB6_p#13WC>Okb;eAzvIz*_pSi=^m+#F>|NOEr?^+pQ@fuF8sA$#u+p?U>%7~I z&WBAQ5Do~Qc!gPtyY0(?Nc-uHi&h9VgnWh7*VFwK+N;EZZjsUDBe|Qzsf>4fey&NOr`dPz1l>_rR(ReVi(oH|!VEBj zYU!YI)TK~JI6Hd;X$llBsR8^+ZUK}z3xWEeu`uwljf(a4<9(a=)kf3?h`WSUj8wZ1 zyp8@4yFYz=KUe29B^@1D0+YuxfR!*7>5&Dg^3D=>tnf(omojDex9wO#Sc6ZIz(5JA zi7&S}*g5X~y>XoTRQ%to2F26E%4em>pX$!cBrqy2y_r^b&G`G|W$bLi882>hF+)O` z7T!FG>0f`E-MrNT=YP7g#-)_sKBJ-(Uh-I&iY95Ty%9x+ilzr5k9n8t_3H ze^LvVUwkRMD1nw%J+Cx1k$t~lsxO-{)Q?Ah^Xr_%*r43#yq!x_6m0gwA$ydVt}*LF z%yi+4lF4NBE}w{LD$ohLO4>>ocIU5`6$V_7jJ}`gtL?)mU$W4M_@u@skw8nj5aCRo zzrwAx+yr<2khphoq`Y{jAHavv;ctf;RyWxa%EEDu?iDUE152RRrOC~!+foKO4-We^ ztaT}&{C4!w`RdH{kzw&XBR-33X;QJzc!1ns^HRTuM*4YBm>O24P0;%U} z`?C09vI0hp9IJ%bqycIh-U1xYxU>hInJHuozK){YJ$zs-i{G%^pVd3DZeCh3H{7F7 zS=nk=;{*>%r<+I?s2(2jv~jD$QP@d->l0`d@=I6fj?&%W=qOBOba;tl%FFU2rj7mM z!}ByXn4oDSG2>L-WSScKyH^vnN&sd8@dFkXH_9&`Zr?8yQU6Oi!yZX?WSu5#V9HW; zkVY}XY=6Zp0QctUXrILPot0)Gu4@2D1b?=8?W{VVAQ$r@+8cZ zE$Jtf-5M6!2lx3*oG||{7F$S+tiiWVFk*!NM$Bjz=cOsWBvRq5y=vI+=o}`(j0rVa z-As|pZZVTzbgW2M-v-faN&ad{r?r6aJwi9(E{FvEM@iLSBc`N}L?9ht7A^?7J&%ie z38=^>CpAWs{KCK?-&k@2Z2ZlrWxG#0L4wwr9Oxx&PO|Xh$=!8178Zjegptyw7u1<+gbhKHHeN<%c&u2z==^x#>ERu+(z3FogCMN=Nhz@K#| z!}<%uLR@u|s%=5~E8<%MeS3C}$}PXs9u^*u-#(-p#QLJZ%enk{d2;h@0OjV-&!w@< zQYvWzCTzYQ*Sz=MVQasR?tc9nd^RF>}mWo_6$Kj?BL zdr%O#wMo9BbNM))v#T2IVgNvB#4doo-3SZ0{LCa+heOHuvRu!Q``!+)<)LvE#HH81 zr_zw4_ApHF9xL81De>^_iy>`mJZaUl?~e>6%}jX{wGUddRPFPm>MHwNsBLavqh^Jq z5KEL~V=;LDHq#e^e&)bUvZXe9*Qj2N)%*IGO|Qc8k&SV2WUbGhkqsQ)n-aZ8_5H*C12nI6QbMMnFV}sze9o$BzjX3 zQ955kD27FxF{C^Pwdf0-l`-yNI5 zMBe=a`IF;utWsuw>YrO&{i7yMY%m7u`N!4VG}g|9f|vW0qxai@z8RquO84K6Y~TVY zAJs1B!Zu??(aoo(?&XHX!G6D9CtuB;mkrX+%SQu```h34 z&h9@?83LcD1KgY&du|9T)|xgs0ZN}Iz03KLLB=|L8F)2C zj`k00flUJl^LYWR>3I76Q+O4bZcyLd%w8RRnO-=mRYyl7JOs^V09d4v;`_I++MpoH z;Q(dM7qF2lzt2n=I%sr_<$cdx@m}* zyY;Rfu^3LEw$xitJ3s!6FHtK2-JQKrWfu-{Kdw&XV!;l_Lhk~-@161-78?119qV9w zl6)SI7Yb!+Zb37q2u)msn8k>-;K2k?W*QArM1|uj17KuE_2u?R-wL z@;^jG@-(pF`DPqe3ZZCG!_^K2Y_gQ@SsA04rWUaQCjE z1FYS-Ml@Byy+Cn&L7t}z*Z-Moc?MV-yy!AAV2&7O1?&d{YmaF-=3DRKbkcm5$64rBaFQLY ziVA?_Q~cs{+QHDIS)b#eZk0zIy1GlTBCz?1mFpguU?B0et6FKIuvFZ`m!S66Z`<2! zy%b_PHb{y*NccL(kaL>GW z5oWC3oaNB7Jn@3i!F%}heYs&xNyP0+{dkj{OZPs4icFY-aCR&TZ)Q+f5F>A??m?&PzWZCzoXhGX{Yez&77*DY+Ub)0;OOUhK{dQb2uC<-$S z^FZu>!@pT|(BA(bhgfWLS(DM544ZXrV#!FjTsy2gM?Ju@)(ZN+Z9Pk3;Yr`Rl{x@x zQquI3c`v8M?%ii~Mx`)EDYlQcd8}0vF^h@X8^~`Rz{&%Gf>w>6n^Sr*F_MZ<&rOQt zx}i)BO}rX}37M#nF!SdI-emH}8GN@hjAP)@$qV`bu9@XUd0zgPK}Z0o&dEsG>*vU9 z^xXph*ubO%o+t06v+~@V{l5^5wmuWE%}q~+G*h(X_d9eV?pp8lr&bR4Zej_b1abeJ z)wXZrqLRPx^3Nc6vx9=1)+g+Vy_>znUdTI9a^^@n8&7|`)G_7V&r-pF{JnEFw1xAZ z!y?Qh46{`LoL?N^Y_Xd@t3zwaiI^pyqd8xqWoBmmsSntn>LwA1`PlcRt#hL8v^gzOlWE)&;0Hy3 zyaQjbWo@(x2%D z6O{B~whArBnpu8O6fPyY!a~F@13o37t^L~+fRi?{1!x@AzlyJp{kS{U7AWU_!^*>O zhPHwf1Du5qL#KR>^erI{KB)s+7wLSU8EAjU4MN3a(Acy;*xz^cjaF?y3>mJTzJc0k zFJ@Ti>ufY7gNWTiOTHHv{FvBSuyI0E$+f1yzljK9u=*}xhxPd*d#ld_HRc+>J$}yu zv0O42u`FzZlK6TPvvwsR>Vp=;;NaQaTc)>E5v`(@+J-!<9KD~t_6 zGt4q_+$aKCVrwT}A>~{-TXfa{4ky4e{QqAJ;Y-0$dv!M4TEMdhzJb4JO*JeNoJi8k>-r++QTVuVyxEkiN!Xe?`BHAj%mK z0YgE*5l-g7SzX!l)w`P``4)6`GxdL8_a;ooEMM*+`X|juKLSFk4YOFkNZ<`!Wixzr zV|1$YqF(mHXZ84H(UP7ZtGFy?X#(q9mF?nVT%w=}#{!oI_}e3jM*lyl$k+gMyyc_?@d{3Yz<5 zwS0VUF`JUauG$Ac&`dKVE7I|C(G4FR77E*${IU*n01x2baWUx4fUz|FI7#ltfTObc zzzhVqA3#ThURNmnL&%`*jyk&M*`m{|UqT5#WJZ}qo+E)OnJn*B};(-Sc} zS5~t}g=`QJWMo&T;{sg9Poc^7Ms;4tg2q{*Hf*4wODaG}^=;_3^#U)~*f$*XI|}B= zX+LCn9eKPXrS?$2;vqHvRiOu_N6%=X(6o@CRlnUgU)WRfTJ~A7dbiCABHDvOBDy1! zUY?=YKO6`2GCm*Nwok0o=3@p&JVzv;6l#*PU^I;5JPSG|IC2T}}Lu3OgaV zzTWpj*ZlVU@b>KamhVN<8)j&L-5>k8-3WOnzF~1@xm#7vl_RDi_w9t$meZ{wO0s}6 z^X7Ye2J#+zvhcKcUaV0<2Fh5i*K#w3g^u3mb5QQs`fF z9WRa0;}OfZtd5Os7hP23J61BJst25Gari$>+tXOagdOLl$0`>ViR?w>rs%AZraz(S z39=Vg!DToHtWP5>-*A5&D&FjlREe8U2h@1E*Ihw1U#rYuaLU@sGx&S6Ilp?i1#mzq z`us%`3*;pkmtAGt-6ZBLOebmBl;$!P0 zcPss16^{ZVSoDp>-aEqwGeg-02%uI!q~bGJDLyY}GO9FXrxkpi0h5InG0Vzk$oK|u zw%y8_MG#-Av-5(Exbj?3*sjTn%uwXEv$F(8!Rhi){wv9h#zJ5zAiEP1$A}=3m@kf)+jc&GUeZ z>EFIUb-;m%c_MFVS#7N}ks|HwGBA=a_v!i$X!|y4KgB-vaEd`G@}|f`!`S%4H0zWc z(ea&t7JU*_Y33_C|eZe8{d6docFC#6$1%%N@(z*^j0-r=kJ{ zQ~)4o57&%71Rm;&H8%eUXJNk@DEtCIFD+;xPGQQ*9Gk6_+{>cEuFKuD^CwAqHE-=7 zF~c?U*~qoz>-lfn@|^y`Nte1;2=PU%`9JEL4G93RZYbcytE>+ivhwOX{AJjax-eHT zcpd8xJnb@(^(mlZ)t%q9Hf^A%iIxj$c+J0T{sn7LLeG2)`9lZ*f9QRB`Gr;PTGX`l ztRQj~nX4@)Nkq(I-?Nj##HN%hyU^R{E~Oa%S1Avy@(``uR)ck<8Ry~pm*gigztj-% zbH!>&oex=bR1PX$eu*H&i=qVprg3|oOMLtnpI@F<!YfB;|`>gNy z^PGf@jlyjT7oo!x7L?4XsSa3riiG&7?zcBQjz*jSLc{#cG-IU7u;wKNy|2=CFzLCG zV@vU5a8#AkQe&cGbbvvw9teuj$E>s$&>tINN=4)oR<@Zc+ow!T8Ex&a#9H{is4#vK z&)8IS@+yYPej>-b409NAau?1G{CB^4G1<5^KR(=n8)-(6-fjk{s(-@QDc5@;Kq;YVCxR0Rl6!CMtIwLLc5A&S zJ^LTe_ZI)#q`ihym<0=sE@(jiDtvXF);y+S(J=xPvvd;aob>McikvW3^AypVPS;(@yDL$7S zO@uDl>I?ai2Sj`mps@@29? z#l(#B+~B2REK*Nd*8^gabn0RDJ2Vid3|qI*Q>uUY3sF~;{Q)}*85S{(V0R0RVXNO~ zdd~fEZ6%-u!)r>ywPTNGkuAgu1p6_y+#hR>lE8cN@A|D^Zd(&`KO`NSbq89MH>bX4 z$Kb2#SRY2Ki6VjtjmeyY1bz-*b8!fXZ+4G$NxlP($G3v%!v>8Xupe8 zqS$|P>=A!U`7`RbrPKr_SivMxh-9u$7f87Tr)Ojap)4}jpPHBoaT+~#I8(TW+@3wE z$7N>%-F=cc6Y~9XJmQ!zF}?qLb?hxZ-67yJ0*Rm`dnZrMqS%FP+Xt$rE{7Dsfg)L; zWajUHja$eOL7JOb7x5E)7J{*|L66m>ARXmbmdD2*jBN8%;%?toa<+$rRkoZ&7?H99 zN_uxlUQnJ8&E(=OHD$lS1{CSRmNI zR{;mRHTJ%Z&-x?hcmjMJPL@@4K2XR~PmiH6`hdu-$Iyuz7F6}-$9KE0LC3i7>@xWC z%wFY4qQD9Tt1Sl%LY zFqyi1-l&B+%fV1O#aY}KvOpe~v?8*$Yh=5(D<@Mu=WSMZlUxe_bBkg|I91}~cSXdB z|8H4q-0{9o7WE`b!eFYw`|uaPM~0MVaf}p=d0+b1C>w+Q#K&1tPif}*LI%58=zOax zI=)~kJ`#^hsSmY?ngpKlonIEywVQd_F6zxHc5BpR2J9cUo#Jy4sn5f3;Wv5SmKR&y z(IU+>ygz^F@r}I0RGjA_!&m~W?g;aH6zBKJXxQp3@Sf3-EU*l3` z;-$N042)PGY{KlOsurHwmKh#Ct)r5!CnrwojR|TuR-iL}NeiJn&HNmFjV#^7*27N#DeNVYEgA%m~ zRpjwg(7CcgqCSRsXV~V!Uf}IOG``!_^?$FvjmOcvKDuLO0&-bDs=so#=XHEW-#Lxs z<-f(pNUgoxC_Wt0Xa^@>GAg%{>n_!Q9*!HRA)~diY*CwCdz>&3F1i!j=*XWfMVhVM zT;8&0i!&#$uEy;8XeG(py)L>#%rm(+;~8XIRWFM;!@*v^A8=wwUAoUK>(@_AT$B%< zAd8aWU8;JDfaXXQDXs9Yj|9&|4Qhp0mtfCO%syrRHSc$7^5@3-$cN>PTIaAVxZfO4 zj{aX#M!-^uiOJ~D>T(P^{@u>rrC!F~nEKk}cVS~)m+KXY^LejnPtE~jD~|rOfhLTa z!%sbUllUXAzO&hT7U;5H2{&1KRXywF*#)K9aKSioT02(fbr$xx5;;5Q__w#5XERRK zB*5oHRM0+>ztWts`{8I~bn?eDts41W7O@M^7~Ghl7xgK+_)Pg50lxPNKX#Za0INMF z>f+%6lW=4SB_d79J?w(1Kz46mDH7^^o3q_2mIpr@@kY#T;QYb@U5QKks+vKn(VM5h z4j*a%Dhl|zI*_sX8q`~#q}R2be|`_lP2jiSq6CQ&kR*T0*}LyPzx;nReRW)v&HJ^$ z(zSqecPQOU*AkL~qS7D&(%s$CA&7JcSd>ahEg-41G}6*Yv%muH?DPA+fARtLp1o)0 z%5$9~Y{NCUglHdZ@#i_tUig6c)Y>7vX4{{xBS36fs|r`F35g_`k_kb5k_kCjGSHp3 zJY+la-<^Kyt5Yrvw8G%ww9~9 zpp$%%_}1!}V?$P=7QXAj!k3m1V&}O}!b#)`!~ZTi$$0TB@WXV7Vv0HvDBu$0opsD4%TjEq^V|@o4i&x(qltH(YhZTYI&kE#}c;^@D@Dy?j zVPdb*67PLmygAz9q8)Qag^)i#9x?=e_Z#{Foa)+Ls0RV|GCtRH;8bbW)D-XJ?@*Bh z+YGly=34^s)>0+*aB^LnisJ(>i?Wl>;tkw}alf<}3nTs00?+9o3r1SRSrLqBp6aLQ z6>4fk?7EZ-HHVs-4EAr;^KC&}5m4hD2NyQX%{{YiVq_8VMsuoSZ2Hv`P8#luRq|W^ z8)rJni|Ws%Ow(0|89mYgItx`-5py1(ABirT#d#d@vCxc$|L>FL*3=bw9R9y212(%h z`v3ptO&FB+e_8ebi1g~gmCNa;R;#ke0_^equOCo*$eR3@)|LQjYc?QKK!U+qp%0C> zR0eB|1`nvk#_SyJGG1#)#$DTBhW8CnKH$7LP?FAH{?_R6%l&%WwkhDEgt{oR1wMri zxJnrR?{gFt@m@ii$h7;=o}<`PliTy*tqsu1fby}RE-ymfpR7GNI$$Sl8Wupa7lJH< zrz@8D^)GtKzFKy7kDFauvZnoO-$zvzP0vgIE5N7%{GTdd1O4y&lN$*g+zfm3&G=00 zJWt;LrZ@Skq37P?gA~Qe(`PF0^=n&XPexRZmLf?9ut;TD0A$yD(LUsC#_ruk;6Kgt z{e`uZ_*L89`p@Q(K|keux%o`LuawK1wt68{|I6}ul(iM({#SQ1(0)#cW3HY?vWh)i zeegKoVvO^s>wHmj=Q02K#l}aiY%WpT@fFWWzaMxv;?OgfgzV2I5(5^YH>|CJ!TkRu z9Jv4mPzjoq99@?rl|>d&P(f*!LQ(GT&96Dp{h*V}OUE4H;J0WR+K1`n%BS7jeA590 z=u=|g_kTO+LI(Bt|L>DsG9m(_YbvFuw_hQFy1(K2Qge`sf30bwAVZzWUlqW1*Z({| zZg9+aihkcA7_6tNSthCmRk5&}uZ(f3J5!(24p+elid^%9(iq}3&|%ExE)068l`XJW za1}|Kl^)v~pbvmg7r0Q zr-(-YX<&bo3f9aF0V*3V1UMUYx`U(0E^}_Twv(&!Y9OWj-GwGlU#RloyI21azyqSM z9BG@kiTht3Wa$m3{uGtYZzK!O8-PkTUZqn&bvg6X2HS?E{;;tv(CCDv-u2xK`(*y@ zAv}qJ)ePpF1q7F2!uS}=FBW+Awzbe22fBN+M~A(P&kqD6fzCiEhc2~4i>}!hH9A14 zNVMwG0{A{KGVq$OFLE{JMxR2$hyWn zYmS0za?p4~3J?o6D)9eHTWEPu6u6pbc>svQHP2lZp8q{@Kx3mfGEASD!#-AU4;EtS z!eaBY3dYmuN7ep1q=_Gk*mg=Dda&*|otY$RL{U&eb4hj=@7>E1d<{Sj0~>|Ge}AVn zfrm49c6P9Yo64(9ictbf# z^QTZ^de`R&gm^zJfB6r`aDlkt<;gxjkXXv9C=7YV6oOn%wOsPPd~-fj55RPT*>VAW zpJ>NzHAeXJ5Iac2cEIz``G86=eG%uDjd8Xi8<6V1m=cCy7bUZb2=SL_W^lQr^#E*X z|6d*YdA6jD;TH?Yqpl=1IvpeQIZI@SvaT5y`8v)zQ#)xbq^O~((uNd#eXBmGF-? z&ehj;x8_ph`$%U>fJUXRQPJw~*XRWq-@b?oPtah))%x!9Z*Zr&eSe$PBG9d*Gm`X0 z=tVI&tYa+~fmLlc*XI`dgQS}A+-8?9Wf87va0*KF7fc_btd4AX@ghAptI_oe`~0j` zwa2ns+8mXW=VkUHMLTP;JuxG3P1L+4^~+B!%-f8@QFN;t-oIRK>Gs-){Uu zJ9oSL4psZdhfPQP>_nTD!aq^@0jFiY)#f60XWBF012_01FhV1z1}Lj30uJY;pI#bA zP>}sidEl!98FUIvd@14gF0b&OYQOG@lJ}VPGS&!u|@ax=L9VA^m zyW#>rn#s&(Ggsbn@u6KkCv7lUjkO04POglEnvW}A0ZpP`eB)MM_&tGSf_*`4lD#I5 z9jX@t)AGH~y@sWv{dvaY?;(!(cu{)#ERBo^2vJv~WTUNC#1yMd6aut3Y%eExj~=Bk zjTMCi1C5dN9lu&F`3Q{Ls%NLt@Bi&xmAhKx$k^5IE`IO5AZXBP%hqkfjuaXRD?X~5 z-TR8@eg3?mOQbF^FY(o*mgF%0`knl- zc-&jpmSwmo(dKRB&*SYAuxJi`acL9CaRLEi2b5rFdRigEG{-1XR|U@T&{ON0{aDX# zjA&x_#UeeQ=0=B2>MJt_O4)KD)*;#{8S}}X+L_}HPt}gnIo_hH9$GvNRaS0~hVtY& zgV<7Z9}iczc_oY;PD*gl)YvaX9vyV0G&ZdR0=pBK_2K}k$rBB9#1^1Yjc9ryW-axv zthB-=>m=&HQ&X605z^@K{y8q?f8RU4$1=y9C@bi`-F^KhWemgVk>7Q-x?rEnRwx7qkOt$X z;CojIY0CJ+1@h!_&2SKPyy&=xh79A`{mnMR$>33@DE-=@Kn==+*J5l!)6 zrz8+te-S=SAegW!=jO(JeeV8NtVqq>?MMG5SpRaZ1uB z0s$KO^A$8(clwits2EF@z9pg%q8EEph$@xYMt64ZzfZWoAl-ME=HGNukoOD?)UqGe z1^m{cRS5ZnmSF%3-kH%5Z{V>x7$gPNPw)EiRukj%^;mw%HdKf855#-YvzGt-=Gn-L zat_XcT-QktcC1^JO^KskWG}6ndI5ISQhbb+Ds@B9wxF5+{W(K4Sh*O$i?z{_QwYaRQzSGg?~hxx9`sUVoU0eFZObl`!7uE1CmxHDYBtG z!hR)IG(QISup{Bpz(JM7K3W)YniN_(_RUiXfaT4BhxUSpMsKXaZl_cVGrDnVTdxCs zzkeh1t6~mD7PkPQR@l`&!}3q_fO>1jBE&60Z1NK?bI^z`4hib8=W7v`)s$fk3`93p znO-0^l+O!Gr6yxVKUVF5PwzUMd)0JuOO_Cam`*J9U)vrxz{~;Q$l3Rkx{c6WOZ~Ms zVQ#L=w|N}HR5HJ0Uvqu;aq>O87!SKa56AeQ{x*K6d_kbAZCR%L{$WE^#mM3Duv)gy|NlrS$z!Z@#o9_=IwOklqZ9vyqfrR4qae0XG^d_gWUq=zZ^~7Syj;i zBLt!9-{f4>IR`gR3n93(<{4A>EWCFErCHw{UG||ZvL|(Rj)sY?lx-)uh zFY4Zj98@sBvrYKx(u&!Zm})3=kRmj_F(!&&2@u98eop?Z?6BNytfx+6i(t4%J&8e} zFc<)VKRhx-M^g7<%8sN5F&!GW3k! zvjMPUntW?u|NP7sZJ{_N&~MBf2_P`8Q@^WEeYQKx3lyi^EtDN*N}^i;n*U)N%1~OK zvmcKGF6^~8_OvI7mY-hoQ#RoDAGr8p=MtoK^y++(^Zz{dn;(#MFv zJMe1O*^a|$MK66XkgFsv%ijQrqIB^RM)em(^K# zSP|Q@g`QG{JO^i9Ch^WxbJ2VCbC-R?bQqmxh5V*5vw6T4r^C&kz_E{0Qz94t+MjQn zeNNBw8++$y$c&C0o`Czb$sQZ#W~eG zJD7KQE@V*yge>b@6(52A2&pY0j$YNY=^HmKfG2);OLv_Ad7efa7$^AP7&L<2~Y32^H%e3!mI1BoODp8~h?yoeAO@$<}7h6j9bT5Ns_ zTKo4~+xB@+ccy$Dd6%laGBJ0mYwA0JZRG}>gWjdIFMhod0MkO=hVM-Skn$9F(FcjG z1AUNM!YmB|fp_lG*C>z!Eqsk?=f395Z$~P>ocy%)XGxeJqc_H_LkxRT5?QBCica7d zmWs>G2kMCgDWr97QE`P zo5cqiTsmtx6@@;8nah1)l78TDX8_XZ{t;G{=c||BTy#Bno{$pX5}SANpoOzkv1V2( zT{AH)oGcl$6u1(zhw|IqcIsuXcE22rbV*iNv1ZlzJOI$lg(({#Jk3Qv`T2DeMX%Z0 zVh2(#9`sK60>JaAItd0se$_tH2<1q7kkcI;=sUK*nb4W2ZwF-y}ib8mbZnueik0zHhNOmhNApj;?P zf$`Y4MY%3k1t#5?#!oWY<1W*GDWVH&BqUFsb1sc&E9(}Z69jv z&UL9xWkwO@oHQ4ptP>XXHHcuxvFdtvBV&cvsS7?ZqOqxU1+9AwX) zs)wIa{&AlC8UM-i#V{C^KkMI0JlXaB-vx6)ALU;D|DZOkh{mZ7{3gpMRZWZPDm~UHn=?e@>s_oFf6-1MWqfG1&{0p(}D?ss|nhKRA748tS7fb_d#tZ@d=ld7ON<` zS-tDRO4M&AP@~9)dCz~vg*@4o!eBOR<1_xiak|sKisJ9xUuYe_FbaM4f14D7J~MTo zbdj=v_0h>=DCCZSI&q8Q4wq>ApIlKdt7`C_~hxtoi-=q5L5C89lyMRZeb;h_s&F` z060k)%TcXw^_pjuY6?EU#T;6QKNf3??U5e;)&_-vj9;^I38T&ppRp)jiD;;vu2maXDnIEgP59BvITSx`wctLr8ROP2EKTR};c4mu(=M5tm{F^sHzmv76ibAZ2 zI2_Z8+a8T@w43xf)uJ7_#eIJ}BqPu`@g5(N`=~Hb7jQ1Hs)SrUl5ly#ol`O9^fH2s z5}j-`q_;l)MSPo=>83pCcM}Z4w6Xo``XfN0zd=*1|IWkK0SMEaY%Q4l9V%Fte>ZqZ zn5epH*j#4gV++c@bLb_Y&61oX*5F`zRvyn_Hh)@M@MR+zHkdmeym^UvTV+rhaQlTa2q|U>Jl)Or-2JQZ<)g#`u&(S>XvYjNM{!z4VxV@x7Kc^|t!}$~ z__FP=hku7wsGBmj)3=9=D!s*KVZ}@`<_pfac%uD(8Y0Zb!4a7Co!ovK!@2B>XFJ@) z+f&(g1^)1Xtl++HgmD9(ypOj(R`;nh2lJGMGOx>v=3Mvp(eFjh03lHL3EFUhDL*pt zO?qzC$jmZG!($9jGulUrLYwm6ke0j+4}JG$T?c&^PeE_%apQX;y1TRVTNR*o_`{WQD z4i**K?!A4K{xt?8>XWd*+tq3A7>smg`6F#wvUT-#--@yhoRMA)kdgP>I~UxkhJzQ*wdLkLt$_ z4OOfDAU!&xkEO@HQ$%==;_21QCw7K6%LPsAa~FKGADzdyeSD*)Uh{{Z6Zh5&_onU- z2^*p)Tme)Qlk)xa&x%ddxm&ir>7hYd3Dg2^h1p&k7VUJ83gcV+z*EibxvhJ<3i&z9X}ntw4(V^xMe}8%cMN+Yy~i5yhc28Zb1?aR*+nJ} zudmJr0gd`|z}cUkp0~U0a3EE>RJ{AIj97GE2eoqmt=L^`P%qcMFo6lfmcP-t7%?QA zi@?H%;Ud<{34*ZxpS0ua$WgzhpsgUIPq|Q0;jF2iyrI6nw9qad%@LfYCzAHe@F#I8 z=^5#!3f5rc*JE>p^!=kg9xAo; za5f6gvM%zPw^4NM-jj97%r^vEeM|L6KogKOa~ z7|^d8NDiE73l2>C^Purke+1<2fq;b7=Vhb>9X0jFHY_yKmf@Erg_>D)6Nx-AKy{u} zUbWf{GtGQ+G)}fT?gGj?wm_u91IVwieb0_ynHR+~9ws2X6$eJ(=vAl}=J&U!6vk(LIjuzD~Z5{CC&c5--T05&2lNHzh~+Kxo|q zzzkM%rslQRZK%7B(UHlcoh5!rZ3C?E*-=hzG zXpa91y~3=ae3`*H*Y-Wg8%wuTYN=Se&Q{=Lbwor&JQxf|mOkMS(XfC(ZD9X7b_y?^ z#uOxK-rbO9C@(8>?d}D@X0Im*wz;uU+Qug7z7^91$)~qnsa)Wh*IdLpLy~@VZG5&x z$Wy>zAdr)jBc04kbbt-yLVR8CQ{R8G40i_YD z_#`UG{JoO#2ZF5}79kh!?$KjLn70NrEkbyGA2Rued+|!55?n+v5RDWEX_vORkZ@#I z?DNT=TVvlGsnKI zrZvxmZ%^rmw0!E{IZKboqIQ=JB{Wm)ONoPOZ~CyXK&8mL+kr6ozO!_@L!-I>I^}zy z2dSM8djxb#XlqOEV6a|wVdpjT`)QZ$rPVJ8$VEH1JStn>8+(_qlNTj36dKfcjUq9> z=U1gbOtb?kknR|R$ivljz&Z?CVa(rI;L$lt(#usl?eaZ6O@b{45ka60+T^1vmV(%U zoU1n%bc)LWo+eNydEFIDYFCjxchN9My-#!VHY`v<1De$IR%Z%Zm^k#x0WlF2`f7h`sOJlxt;$V4lJ`lO|8K) zxb=J_UMXtn|M}`*Xj}#63g+JRAC@7$ps5v3cBTZ4g*hJj^8~bNTwQM=hw+&Tvx6wY zSXj`olK5yO6^slhq!!$xh~N&r__O~Ev3KKmaekb=!xG1Kux*c<+>{~lQwX)0&G@FO zqw^Kv-(Ro6oKv$8a#Wr9mw6OfptF8^8_|tzs?%b<+K{M7F|=G7f*s{nA5TgPq;0;) zs6ymo(v;S|`2PE|{{}Vv)Xk#N2GtJ0*@>xPiY8KyllQ4jM(eMB$b{z7d|fXJUjKm; z*$X*$cQ$7@yf^_0B>gS^$1d@YI`d2Cx)@g#1pLg)zM}Lcx=UJ6tRY41&=b3_TP@nl z@4hO?1xxpzE%Efa`4gMV#NCEO40pEkKYWI8yts{#;hwLbuOibf3kJ zI=fnE6XJ<6@Mu<=&Q~VOFHwZFd@g0ro6FVVliE0hr@hiC-i+jMzAH7J=-)E6^Kzek;cwXJ_ueWKd8IO#f6VKQ-y%s@lVkzcUdqh_=Ns+ihpVG=E{hEonc!pM0+Re_SqU~;3^U{)tjpCSB7Q&gl#bGrnjxoOmoU7hFy*PeuU%1itjG`l44z70t35$`5n zp0yYo@oLPv#Q7C_iTNv5L11M1*FT%PM+eKX%rK=aRD{C*Sl!CHCy?V_XcyN#cAb)a z*-YnndG+k(3O}}oYt6z&yee&KT6I;pzSiQn)c?%l!FA%wq*6LkUi z#!;^0{ik)^-(=9*NQ2Z<@lOG4Zc53jlG!!apHR*Ajg)(dVfH4TsO;P1k3I|$q^X!o zd)x!klpjE46ihUQo-b9}SK6ZMR*c&~iKjXF0N6BM&;l5!%_kv?k+B`P>oDI~`yeGq zxK&w3&hzije)(!Za5J-U!OTDkfcwE^pY#33lut)vGKWHd6JC(>;Exd*ryVZ}1S(lB zPmrmsDrJv9KO2gp9SsY2Cnk=%I@{Yh6a5v|GAbRkEj!`0( zZZYHxGCI%amsvtcB8_aj$udm}U*@&w6ZhwIMQ)_p>Q+YhwlaZdy9_;=utY^A##MRH z-d_J}YOs%|2^wu4rxA8PMMrgi9IX$64(X&oHDI=u72;t`LtG2LQ`y1$AaFh?Dhe(I z6zV1by9|@8&%6Q$^e;rj>8>5>x3NW&9nDvR&w3N2RP?JC86+DYr(@+Fa!bXu%i8Qx z$&~3{G?We;&-WxV?!Xqx)SIVSrj~PTN+&4mtxC~_%+XSHJ72DERaO+}M$ak0Y$r=Q zW!h+b1iH^dy3=~8zh1V#yhqev=O_45@(j1-vtg(jY#M|8Q;nokq+?Bl%z0lc1RF92 zhgx=%wuOt)rhN&yzTDkeNdf(iwQ}w>NvBLbnqc4>tgs<;smool-|ISYr2gf)wz=O# zUaie4pbjDfvvzxN4)v7i*Fz*+|LmUGj3ZwRWP20^`I{VVRTRG1$R*RKmvr&ka4@5h z_9**^Wr~~2v4|8uTNdOcjNrcgR^vN>RrtYG<A$tPKG#Bp?*gkIw3!WVgy zKk{zFvaSUfg@3yWQ+*ZFIp`C)q&(glWF$)h+jgjX$=P5_&~AhBL%77V4U2NZw^&-%JWQGWqNr$ znNE3H$`8&mH<1R9kfw~{TDv9rG?Z9YwVTK6}j1mZK*M46gC;8)^sS$Yie-MZ4_$p z4$1fA9Nd_9H*7KXM9!7u8>#Z2*1H#$skKK35^%FYSA$PR)rV3>6xhtHiC1X5iOzsB zja?AkP26-?vV^;qn@oO45ZO7Lp+uPSy!5)nlId%TdJYMb?DS5TkN3JR1LAPEt36#1 z#UGMla6;F9$gpK|NW|m1!gQ$(%g;h)IiG|Y(Xa^oNFlc|Xu~7TR1l`O?K#v=_>GJu zv(2pN=|ei9qW_Dj!s8rQEVU ztn?Du?ABKli;z|POGnP~Fl{rasD6a!SaECf;EqtT+Z-9YpJ+!UC(t>#9~UJol5RQQ z=x)u6A)f7NKuG{Ym#{)9wNtdiz>+9VT=oH$Z?OdgX01sn~b@|V1wShhXFyQ?|`O62~C8Pn!Sm`OTbl474%{-bR? zAEnk@pmw=4Vc5PU^e{W}RM|NbC(2H_rcbm4V>RdCer0J{lFng}f7LYRa9;DuVsicg zJW(+drWXJy@eQzgw_&I8$C|jg>jm$xCWK-A$h*53GLPNG!27^b>7`NVp!e9t58PN>qYO{- ztTE%q8o&tiNrc8_ZcUoBOd~L^zi6g)xNA@Y)AiFLkgK&M|_m%$~&LG)lEzfLRzfwXD zyCF#J-RvE*1~SR#d0GHy#xuG^A7>m#UqiaWv`eCt;)f~oqo9Tv_RFiqVch;pe6(Nq zt2-Kjy4tgSV)epyc=7L_U=jBkx;-C)U#5y$>DMG2QN zwEU1rQ2ao%TlD1frlec-$$DHh6gESW$vbx#+VY0&1xIz6I?;gK&Nb3TeMvHyVugN% zav)(kYKP6};Qqn4mY);TQQ42mqV?A3kp3&eD=e2EGch&{d@>1#3#fTa2@zo;J*4A$ zrGna~k)*xD4!Y$MA|iiF0EV?`43Jl?paw2oZ-D_5Q9b4fE{oYo3Bo;N7}spZZl{ijXbM>;=x zG04g?aNv6D#s*yTUy7V~6exLxcwpx9>;qH4>1`zb1!ra7@78V4@|kIdRtm<_r!Z6+ z*Ljg`uiQ?q>V({oO(7kg?i4^nM9-a9c!@op}!DMUKR`FUh|* zfoxBcp7*x0`B;w6v!8d1AIO!Fxe!G1oj%WvF{%s&HNI}j5EGma4{(|RbsG0vrlM`s(t!L-@a{QxUkTy zAd`$(;5^~_X!qcY*hJjDGNqe7>h%v(Y&!6Gx8Q-;EB1Ee!vg9lOnz!Q=c5kq!_e6~ z$Jru(1uuFO#`o>>OHKDdWi0W#(v)`5Dw=u_-CK8<{2Fh>WAW#Lgr(7Sy!kb{7W^=s zLWQ07sPS*G!_MY_Khi=nghXs!? zjcu?FDe>6JIJ5e^7hIHz38g5kG_!X7n$%6&-8L=Z^Fh$szH|#~$<99Z^cmgxrt*iA z*VDZhc*)%%U%!&Z(ua4s|He*>y zmgpm{Ayw+L&v43gnnpr7%#L*1E+k!-#Bn$nZ+)E4`>C&4j}*=Ov92~P+*3}frFsf+ z2l5;xSt4pS3n`vp6&etvGY?Tj8e%DHk4jca$=18yC!psmfYBYrF0T^3 zSMd@OqKbleQ%QXodp9Vh((JLdzwzeJAXwp3!*e6W5nTq`2OHwZaylNz0!r6C2O<=> ziOc@ho|QcaFDYa7&P|`t*mOyIzJo(k1FKr>ZN5^IuU15`5Vf6eRpDWu^(*ZCY7Jm3 zK&?k)ARHExG{)npP}yRd9aut9#ZF!s3(HGfoTgvNO}|6tvXrJC#NA1l#LUL%$_&M^_tFr|OS&w?7?8JB zEogE*(x_lHZPTP!j0o+DO;@L6!cPbL*3w@{fS0JKsExqgIW9LnbiAB2yrvmpE&0-w zi(U22?{LLrKhhBs6Xzz!M?E+mzzf{F;vjI^ykQu7uEZzbQd0A_!x&w4&WV%R77VPA zR5O|S@1uBe_-Rp)dQnUzWBuMgmA4cAE3{5=eo>0)26vDusBjDW?rIj257oswj}21a z;Dp988{7_Apa|tjEW!&{{mlPXy0S4wJw%D!P!wv!t|T@n_>smKq!$sFeC`r(pclVE zFrB{R_4(^MHLXXlEAv5RHl8)^d#%YgZ)=I!r$g^ZBlQphwZ7(MP~(F-^$J1jie?sB z!RKNzTrWz8i-hs~yIi3u6x?I@JsTsgBU|HdLzAtDvG%?|b2CU`hik;lh&k_-G&c*Y zRT?uar3%Y*J#%|~iP;{Ck8Jfdi=fqozH*TScyajw3P`PiG#YlA#g{*S9FK10zNIQ< zh=1BgT8lrjSke-w1Eumqs41vgyoH`0d_oU~=~z5Bn54Ts$lgiEIV8R)Z?#mVanB^U z*IgxRx1uq|pI$Abnj6-UWa!VU3gdvhX<5dB6?(~UHhyT1RaT!*?Pc*JnHRK$A1K8VhGVN3Y;@E@?tiFx zA6DeK(XXJgKn4}!1MPtg7YJm4E^wKKj-oy3$d!(Do21L!-An4Z_qMFM)0;i9#Aoef zeQxQyL(P&hRN zNv3eUO{rJW#pipu8Ft-GKyXb_Dfn*?-IHD7+afT1F_5@ZmoK}d*Z1YGOnO*{cWtOq zFdYjWH!5l9Y0pMF=|JHfNO)Qr?OTP=XM8NFB*S|2iUp+v_mPspLu>RVFT}8wiH6mF z7!R$^Hc&thXz7q{B8D8Gk^n$eT=5$&$!W>1jqVk-9QE4|L*rVrbx+EP|Mr!8pzh z$OnntecH3mG0hY<2V*hycXJIf!XWVT9#lpIEWcz+39fE-VUFvv~srVhP(kZsB&Y!BlD+tEnUm4UmFq#YbcB@fe2Yh*p>4G)ge)(n;?UME#s*ys5ha`!~cCTKOMpEK9y^S%hxFbCE#({bI)1}CE+bl0J zzP!dY#32=2MR|BdSNRzZWdY5r)BLDtcJjOh5NKY%Ed&a%oGes|8L6omI zm-I`74NBiJ-Vp)o1_ElT`NUPmMShP!}gE0r03ni+uoXyQYm&y{&kidpbmWBRN-ZX&>APrcS8)Ndz2ei zG?2s=+tuPjs{Ggo%jltdEhW1M+^$oH>B@Pr5idL`0VxmGH-ddBVT!Sd$wY81yU1k0 zp8m*T9Yw{~DRD|Ds|LM|a_~gMzq0Vr%weHF68a?sWrP!=2sR~Cr!KDJDniYmRv(rreKXnu>6?`!EObLb6St1%d2O#20 z<`c#Aj%b{mqoIVbFz2n-hXrLSZB5*dPI(pnq>j81)(Q&}4I=ZFRlvlYT9F-q)@EOl z4W%6Ryk?0CTxZfGq%3ee$g{8MCp^tYtz<-=E((=IFI7eXdUB1{0PlQ8Xhvi7D>(}> zpP%-cQvUNg&Wf@{Nh(g=uEM_wO**J(PsjnO{D7>ot-U zb%zb^j*s_@t4xV@#JE%e&Ll0_Xm;hFiM_7zw)^fHbD`=y-R_PWu*4q?#r@%#6vN4W z(ej+<+VVVDC_V>IIk?vL6uDT;JMBJFTg4XD7Wn)FixisF8?svQ;Vd!#f^JK?xg%NW zEISQtwa|>!O-ZtL_fT2KbB~W<)YbeR7~u^rEv*kR!nLl^!f^sTMDnuHu}bUj$d5aC zSR&w~Z2~at4$9b$&o)uQ6Oki!Z zOT2p0{gxAEns8hh+q@unKb5II?v9$=m|(so^|Zj20m#B6n0YO>fgm9s@N=oSW1N;R z=)?I}Xol!zen|Ao3}rX#m8zM8#~8*`-d^So3H#_StldZ#iaC6(F`%Q`B@0BTr;=9b z<^O#$w7fXs$&a;*d$siEbO&o%>V}1fC6$zp07W>(5}K#N)K6_q;@{EZFM-4!z*c~s zxX-@tEw~=nFq*d_pzwcZ^*e~2r>5{LG_a9-$at|cj+=2obwOF9+_Z^GLaVh{_~eRd zfM>IphZL160FVEbA%FfeB#K}=A%rXzQ+_3|1e}q6S$sb!B;tt4%%5V)YO>aTzt9vo_`}mUb_vkYvdSu1z5*YQ=`e zswf{9Q$L8&l>)5sRRkdZpX>G`&1rDFlv-~%4K2&6djX1gMYPke>C&V|W z)uByoSpr77fv>JTn4G11NBhfzpTjEJOFvyh&Xx@iD3C1Kx<= zTZYTbzyZ9gOy(g5GV-28N1=wBO-+BTzfu})CTCV z9~vESzH0w@*u+q}UUJ_5z`6iCB-KudAZ}vn+oQaEz{g0=hSIf!y-oonSBL3tLnRgo4 z5Q01_%9b?tu(f4uj2Eop^~ySJsZ&GP25~5r%7B${HT2JT-X1S9HfaMnviT zyIn5~sWXEVznDv%rz6##OF>U8`JQkm^>U%u-6nUa^_TPa@>mPY!da5uRPJvE-{v$ftYv)ER-?bHo7Sh1ct2Jn zOJ-d}QaPnH$F#EQKdgQ~h{uY`J?5p~jkh_GpH{yv+g~l5fIp&vzy_w@y09xCRh?oa z$ue8BL~9DYrehgBN!LuU7X?gWqD zj5BkP2FOL*NLh?e*5~bHxQ6DW;_k=FrW@-lw&zbre1%Gr(fT!M=Qz?{4L&tcs1(j_ zHx-j8p4SAhp)be1{YdSq2ZixLsU)S`P-3G>&K^#mS(zZ=kaRDNNXOMd>6jz7 zkO`0S#Dmq7gvK@k*0t9ys})TWr)<)^N>z6)cPSn#Hc|i>n;R4Y`J4!A(Yc4Om3WI# zjZj`T{jtac*Ww=YS=i7U4kaR$81oMi)4OS@N%9o$ApL7{FZ#n%lu3gl9m3kbO%MG}*LeQ&u$Cy=i(*Y%Ei>jGz(ko;%DY^4j~B!9@& zAZwo7(VT@YLTmzleKGFUIn!KDeIK`7C+f=;OPW)rXXm=GUt5Xo-K}RA{gPML>%`4+ zf&g<6y(Bu-+|lN?Wp6&y+kQOuf)@TYyb!Lj#6Py5FH^Q*Y@zv@@AU$n0Hb($+dWBo zW7MH}Gp=w*ado)<8_Wm;BnMZ_&BLuqeS+7T z=ake&LGT12B0`lH8YHDmeU4V^Nmpn%2nrzlP>B(^ubhm!?cNGuE8aXWKY4P%bE--mTFY_FZy@=AAJ0Re*oSEP~q5+)idOk_-s5^G654c zeh{ncSq@w{`0_JhD;4&M3eDCJqbKFw3%ZRw_T=dV%lC*rA?fdu5~wIj{d<>Fpc^~M z<0O(d>pej1Y&A{L6@&a9y4c3hOC?^R`);tGqStm{tzX1$$SGbXX!_Cik~?-kFBnhq zz^&-C>ln-5e12DAdLxTJci})J=2rCN|B-gqeNlbi+gBK15RjCR8X5#irMr<5R6@E% zx`qa6kZzPx(g0}?iJ@a?kdC2;9vX%i?&IhCdj|J^yk>xN_Bm(ov)0<{dS9YGaXO+o zFB(X}JuTSsSZBW3NNu1O;mNB~EjR986PrSCR9~`B|8aoCzWFHSM}oPVSz)-2C6b?dqd>>)JP;V|Q_o60On<}PbXn)nfsN3a*Q?QfJJ zt+LvOtC3Z^JIn>FST5`;#Y>#!iQ@!++>8Qj!BzYujVebgea;2;wD?6Pl%QtvyNQt= zkJ*l8m_w$MfJG<2CGph*F148B9@;yvSi3s`H~CiBdVxbfg&j-*R!P3V5DWB863Z29 zXlrI@(aU&;V8=%MGYULM&9mf98sK&F7XW1(MSvGS3dmLeVLg63o%<_8A`TJK!24G5#HJgdbXA3CzP2B+h!6Tr9hOn@5`6RLS+F`mZg*~2D9gumceX6!uw1ZBUnQpJ* zoQOnPbUpZ=ta1UHgm7=MMt!O5%|MIOGHnH5Pv#~E0wszN7W(|tSI2eW%A_Xe?F0}Z z+&H9{QCSF;##>58ptYai{}dNF(IgaLXBB>n!gp;S&i7~cTd{}I06xW&KES@n5guxx zC;+r^M(R*(H6!9_ry9>lqRF#XX8;IpKYXx~^dq3D1-QTeG@f1j&u##f7E!$9VQ47O z9|i9~dnm2@C0G&t*HsP-jMJiMHO5NiKjA$9YE}UpIySnF3fY-~^O^jg)PSV0vcSC~ z#tHzunsAx?iTj7S1q?wpLc^D<{>gX$JD0yCBG$S6X&9LRzJGmRRMDAG1S{aFF{}u{ z#tHyitb)X7Ecu{_aPto36*(2`Kc1M5A$#lf5OU(dEJ7Cc{~)HTA7tsO%mI&~gKlhQ ztXH%eih$nWKOrE%62|?S%qSL+bv@p}k|@dC8TpX3F{oP{5=jb3o&gsTw-xCN&S`5* zbK?OHh*|#DduISBsV#CwEFS@ZVK-2R9s^WH0+GfoJb;x!(#P~>WtgWudT&Cz`Is07 zSh9diqV?as{%rwYJN^D@Av4>+_^8D@TkVBqsPS`B;LdS&{HNFqr^dn-&rRk9_!{1? zsQ6hU>E~#%JENce`)iiRZB&}nB3gMqtN0wup4$tv-JY9?KodXZ|C;!tnS6{6FN$Oq zYa;-0XFs4PU*zvvb_1@X$iM4IO0?_^6ghaXukIkkQm09=e1ICpjzEw$lJxoi-3=CV z$?fm`x=rWv&aIZ$=ZuZ}Q`^9#`zIvjFTh!i9gOn?`M)tZ9Tr#us+I$#?o@4Q zF2KdC2C~Q>XZcS*0Z2`$@3G8QI+r_)4rKE20U92`PJuXT0L%lNef-Z%z85dt3jlfV z#M8eEC0-6xh)*tpgoUF2)0{AUTy}Us$U@k07esSfGd=6`@}I6MkHF=DCoC|coxgzU zajUDal;ai&2jrRk_ze2xV}&~b&`EnOAmDiLI3OM&5)TNS0741rcfhY{Z?>+}iQtOA ztpR5O;8_1Q3cY1Q-LbMrX#(_8O%BM7)OJN>(DuieT%|~SunyLPJ4}ne^?b%qb>MDB zw&VP2{badO?^EZ~S-X6A-eObrh0x=b!}eSE*~jjk(c+Z@>s_hUUMD3+d!N5FPftrN z8nyo8p_CBq0_dRZ>#AKAx2U0CM4g+st%nGIP|Mh?a&vM$d>Ccrbd70bG!q`IRBekU?9$^=j zl8*o(y#VyL9`|flqSI%us@Hi1Xl6|Z%%2tlOKEPdU#`xz+_eS{kMS3fB<~8kb@(*i zVXi%9>gJy1TN54l18vD00}N6*9Sj;1z(VomchK$U0JIG;(!;oU_}8oaYCN=u z^r15Q-+(nDHBGhZ#^^}W2>!GK<0<=pD1FJ}J{B=YQMza00YALvr-t13e+2%R1XgHl z#v13LC%!x1OOJWnk5@x+C}T*Segi-{9DD~Fpb*Iuh3F^hicFNg8O;qA)A+314oH(I z+Brc>ptPq(!clJFVafqHwDRvJ01xH27M`PV+Y`q;kWmt#OR>8PFrRrq&vDOK5?La@ zxdH6HDKxq#4ty+DcYNdtd_@;Pb_>@7dKZJVM)7dm3W@Xlbf?Np?WMnifobs3oI-x# zE4FU=+(`p{MB5g&bX{7;XU9TfLY9wT1=fY)iD;kwE|30FNDOsGY`(rUe+w*sI7A9T z`sD@(k@pbJ6j=8G)8%tt72r_BjX_EoH#J)sX9mn6hqHia!q}`YKz9t#?Wcu|-5lO} z1IPH#9!D$Dqs&OHOxVU5ZYWeDvBKAIZ!unaYkU^?G*ZW!#8aUOy6;XOv8>D}sWVK( zS1%F>kPazl3rXH?NI$rr-*x&EaM$ve?q4k_=mLdvcE-z#2D}7>ER=2(^6yUNo*G@Z z@mq%P>41r7mFXh>o&0{~7-0HF@ib1}pys{OuR;rnm;)z^nt z%rNbp(bkrDX--^VX_EIbnuXn6kg70!=>Znu;s4HgMVV^1Ix~J20lDrVC%S0Rm=O6{cF}$tQc9pc@@@XK*tON84Ns)BpEIgU0qc{! zH?kELOXc|Ap|LFi?UuSchI2X9XZzRNgeSa*SqGwi^1|$2TZkq9K9(d@jPw+kv{Oh(L_GL24qmfE2)5bk#Bc;b}MWZ zcu{di=zvw$hzAJx7U&|9q^=-C|IV04-pc1(qvVufH=ldCvmJnux zj)p4*R{Uib{@UXCzlfjY{ zLZq9?rx{T7Srio5WD7e<=ATBNs6Be}Iw}6YAy~4SVRaP8+HJr$JlxM-X#Fyga-ra7 z&SYJ&Zf?HReZ%$UD#-UIR8!1@eP}*NptnkS#r5ogi?RD-Ew#|=Qo2wZs|A|r3bUkG zDlNbS45hkVP5dI_qc$9KDKHoBn^`6O}o3VU=dFVB9T-g$oa{3fLJ z=UF!ME8HG`8-Jc&H)YHxiJjk$hB?foDZ^<7O)c(Xo`|C+t^R5lxpj|=UPD~7&~2ub z;OvQ7?qkhk%S5+hhfFVC%6|s3jRJOEfEKh^J=Tt#Vn7xbfP*Zi=?cp}NH-S^{b zeK)~BrBq+ywUUcdCtNIIbl#PHc2k}j6zAq{fwc!JuL#(^u8!MrQ|viQ$P6=@P&c*< zzm{_2S6~mKR4V>Y-wg#lwghO#w<|R;Vsez(e63a)nn%|~6JqDI zzEMGvx9BlbSkTB^?Ox_X^h!NYilwaQRZljPkznPv%S%}=a!5($iqv6NmGsrbd`e@7 z`JM%%B5TQ5n3pxQ=myi0O^63_#`@ilx6&a?ito}r@NzB4?Wjj6|UUw4MMw*(X{P_>jxha9@>8dh|ZJl(w5fF10v*l z!w9k3!tkqup@32EMTgNPp2xwu?57gET${1+oL${&c~0Z7()@h)JGUiv_ET^v$9;@bqQ*;h}B-F z5TeMCC5(#$a@;J1!2C_Jhq2AM8UhD?5O9>NkZJS!LR2koU~u~7wgI+Tv!8N-22Gkd zi)j3}D2&wY&6rsaP-h-^BP*JoV-JL0MG=IKyKq`8`OOwShz7mqYdsC16*bxk05@~6 zLJkdkn}y@5qRB}xT1ndqfXs=I<s@dMI-Kc4^llCbbU`g#F5@JS)bzc2s4em&;F zeI}_6@6y|O^u;2X28T~eGnr&20+d6tKqbjOj!|7WxLlT6+Hax30i3v#V_s|D&WD{{ zX@N7f4nMDqTA{j}S>)b+`qWUO|I(fo2S_55@#l1d9O0aFf`am(hRkOl3+cXHUwQ`M z!X|s800Kby7x3oSFPwvtNI?6|On%y4b&z;s2}?d0f=L-rddvR?YF&g;3`R+AR<*i& zSn|%q?3afJl;awjExc-KnNq(*qq5W4+{KA=bItQk8^rfnQ~(lYp`mj=BIe|JkOmWI zvbrj`c-Ck;I%f3@<9Q44V{tB2n0?B0PJvM3ld9Jbun3k0Zp*|PEW3Gn$s(Q&r9;@%U!&(S&n{m19VUH09~C*dcwH9bTc2e zL6Xo+*DJuqHEmoL8E=Jmy4VpD79`5Sv{FDP6Eu9Aopl67Dw1QaVf5WkAS7)7cUf<) z77dhxw1=Rt9nEUr0X|97FQ>}qSqhbJ*#MbLCN9xu)y_!GV#6BB@!v;H2i{@0@f$4{ zZ+-0pmN7&1fP05;Z|$J;X0G?+{%ce)&-FQ*`ZSPz*Y5oF?cGPs)s_C^N^8F-O*g+h zlqs?qfbu?lGV%F&6HqN7UI%0~sne$ZodfE$6-S~ui{?c|#u1}c`Z?*KaS?kCw^)&8hSUWf18v4 z?ai)}@Adv4)7CjSfGf|@R1xP88P0oz1}M=R{T%se%6+(-3L&5-R0>426~diTBy@QXvEMsJMIYgdmm_TLax_+dsnlvP9a&al<%=T^hVK~`Dy3jE8ptO2a^I{ZxQs6fnMlou`&<`Ff> z2Ge{`mzkT0Jp3aEqiKezGIWOeZmM>xYt`PqvYsOL+mdL;_P`ZRpjYO>Sn+_qZk44{ zsigh=n%fH4W*@MH3=<5-JOOZeKXye&t00%b0FQj5o9d_kqp$H)gSF=j?m&;z*TQR& zd7l{@cv=QvP~CYObg`JRq_D>WaMJq$pkDIv2DeXoWthI<=RXcI=QD+Xe@)uFxY{`& z)SP}!DdC-$q!6XMk*@z86PhG`F5(W)y>8-@yDjo#j27?%UVpZ#DCRt_;2Nhq9x- zd<8Cc9*SH<8EwJL?$^Hi;{*9Zo>88A6O@17 z^|}K{Ftxz0V9x^pb}krrmEzd+YAj9`?EkjLwzTH@WsCE^Q?NWBAYTV5)B{%4TK|~) zk97jD>(6Ga68mdLq>(|pz94=JwYld$7OBJdeWezi2?9Vvri#%z%&JRmj^(NnHt1D zPdlJ@`8HxzV<13YdoZ8Se28SqiN~EFJ|M`n126|Zi>}iXff%cfV$y>-Uo{CjIyWmb+=ujcE!n?87-?`;exx)Wky1tolWE{1-QcdOvqBx9DGfX~3V z{T35&J@LoHcSA(#E(ip&WVBQSg{#`zKW^W35N{U*GpuQ2oBavA))^_y^y2IMW%`J3 zc$eiLL!O0H6gPXBZDxQE22_p^r!YXnJwd!leoc@`RbK&+^&LiD_*Na)(qYN}u6}5$ zfO=K&wV>-{1h%|4#~55K(;!Lp?7vwSmZfg?&F@S<;7E&><4eTq=j>h;Khu>Ri{Ijm z2Msb(!MR}XGG_vPs=C&rjQm#GT(m2_=Z;slFk_>rhEweR-yxksOd1|zK%3WJ05GtY z-tPY^&<~k=hgb>>zJ8O5#=6r!aCh8tSLXZn?OWlutq^rYh*h#R&_Qr(c?B-tm;tr@|BnavX4i7iRJNCH$JcM5d%PDmOagEBK-uturtE%8~ zTzwzOj&p;s6IpQ8Zg!~S&%Zy|GO5U;?`+X}HWkH;e>a}lIxdM`{}J*ctoUzhQJfCH&ggQ+a zdkpQbd|*{k4Rf3y5|NqNs~+GTGPE-hOp+aqT=c%vIJrgLiNgDXzph+Ad$A8a_BzTFwr&Yz(yzA*bV={I5G%dPMp@Hb<=nnXxSPin^*^t+ zz!^X_ml7=v2+YvoaAR4#as^QtyV{TditI&dk4+D&L^cQYas7d~y+d zH#zFD@g$$HxY;JK^8^-9C@FI?xMMqBL=c&SF~bX~bez2!CDmvUltk><`WtuLm0Ql{ zefBGSYBgD>Gm_bDhY{9G8YP@kbIE>RX_|{H8|hdnZ@brmwFJ6vr}iMl?EZ2 zUV4*)vpcemwWEKpC1n3CGiuQ3b#HagR3A1O7Vu49uoY{~m&kN1f4pL)3rkOjN+aLW z_}*|N=YMxt>3FVi)p+p|a=V{o1#LBQ=7#+&IQVt*P<}_Gk*xB`&+C9)?YA<^h+i`H zXYZVD=K1uS+V?fFo(wkyY&Gd6PBMj<|7;#99UuGqoo61=(eWcRu(h>D61Ry7y$wn?4>z-c2fkb1>)nGT zHt6g>EVTJY;-P)wSz>t~##YRF$Zj)j@CWzqkX`M-#hi37<`_b<1neXdv+>&DgqSDy z7wEE!!2@=_KR@!$kjrp)u6wn-n(@;Qp6h&R( zkV&@w_LvWMU{OliWi6YalXuCrbFmX$AW)UXeIT}x##Oi(o64TcIO#=OdGDUkH#J4M z*K2(Z8$zp6y3$MN2vJA@_A{Sk7gUCQS{I~S3_iu&{Ip3 zCMw)*a2=Zq_4h)p!WSaPFxGgkZWn@3nXGfn*#`9qSFMYTL9PUxN~TZ!{H#C7L;x$EZ-IgpJR_ArXd?x*QxMAfDrb03)9 ztY${do$As}U$)^%lMJT60cpilH#1<#@gqO|O7gM2yA5WTZ>IUwa(<=j*gwUf!pOe? zESdsC4E_O3S%BqoRc{7i`bDbwUh82*%V(G1YuM+e1HXWo!<)k>8QPAK?81aOgFL7w zQKYar))~$ThVkwwe{6UyF`w>ZbW9BqrN^IXQ#0qF!!T@l!xj;{;qgrsnX8SL)xYfm z5_JL(+i^$_)v%n*1cUwej?mw(iGzRpe1ny{P2hT1+Qmo*Zg88$Kh*{x)0WgAxXbfT z?Uihcyp$pAy^cYgr|o!m(pPo848hYkyD$tY3mY+8pODTX13#B8e6|EVXC_fDP=^@% zZj^tO*vxZO-At9;`c=fAWMH!AiTHHC#gcQDte5=H)v95280$K#)W8&k3CE-Xf$5WN zp^8osz@56V21{sW;229cU9LJVC6KPa3VrZSczZbAW`BVZWDIrf4Aiz-U@64*{X^JSG5c8(FkKRjfof5 z4Y>q)tm7`C<@a#io@q29(8G7J^pH^hTe$@~|2=z!`U*DXxKz8Lr@7t~gTrLv74bbu z^dxiyyt;S1O?y{97qfO|_6cH}e<9InF2f~SPTuufexL-Oh6PV4J54^6`}rknY5ql-q!U{r5MJw-RnK~f zs@{Q?mq=*?Fem~aRgE< z0AcJ!Au6v*O5dnXfy_SP@+|*my=}85e~|_1^@8`xs<4c^qUhBfrFb#@X6)@7N?OZZ z-r)YofUAk7-sWU_zjr@j=T|rDsUr_1WSr*WD)r%398!D?VFQZHscYe3us z&^YHI2&xN6&TJt|f+*KbZMAdL{s@yyPgMCR@@Iu}Vj|5NfKn8)%puplQK(g*t3voeA65@igS&pLDZAe1eN*I0D)#TpK&hfO4n;I4Mmp4ugOI<8D^yM)= ziV5-Sir$kD8`YBFmOlHwXjS~&s{bJ16d$x!W!*n#PzKNHe!qo7WlVaMB0i%ZYqT>> ze4csNyz|3|IkMg;6UG$0`P_-CMUBR4zJJo7{&c7S9G=XNRD&D_(kRI7C|wWkRVu97 zpL9>XHRMo;W)7D4p_V^`6O^r)`U-NB*8K}}gM>LV_!dpx_lkbiCFNei{p&ZEW#m*| zY7B~K-eV+X7y9P9Y?KT7ftf4dMpiw2*`q0~CgA{C-z!z}r!@p2x?GdmzGD~Gm3 z(bX<6nP_Hz>Ig9&qYgR-bRvf5Hz-g_$i_pZRIvXG_jYALOKhVIoFhuz zA13T7pYZ0}E8jTzJG#cI+cicP$EB0J+>T^+9XC{q_OpuxA#UkZ)m*=wS<-cgAqcE3 z(;`k5n+x^RXMMtv`%H}RF_v6D@Ca%5HbpT8ExeS$ki@5X9J)@jPMT7_SUWD@nQsn?N4>1Al6xF!j%iX{0yzAhLeQ3;i5*3SW%pj#=FuQq7QQ=_aSk(M@4?BMrAC>@3I1J`ZRRlV!vz*Ee) zdIh5e%c)%Gwpgp7e5~j6h)d9kMEskdO$VPJ$$bl|mRNlZVq#7sdVhAgTwNnmg^YVe zM^aZ?smw0{19cWe4KXU{qKVl@SgXg#cXOOh{D5897v=B$K&J4nCug5l5%LaZ^?Q}J zy63=wkEX%tG5&z=ro3kBczypCg4J$kX}z!bB;RAWSb%-c zTK(6r#0X~Th`l_|@lRvYYaw(1KS@mC_FAX*{;Xrj14C!i?fbVDuw;%x(nFU=A7!ay zGU&3%{p6s6ktyI5fuqFB&d~e*4nf^hn_0kxt$ji{*tKFwU6mlYyx>t98DD@%v8Y#& zR;uU0O?e81pLkktkLxq*zf72kcnV>O)>bRK=!UOH$8!j&zOYeEnS82K^3z?qckR?J zN%DL4Z7E(t@_5T2)!i;Eh#KXLkF`Pt6Mg20-J;kRuu7gEomGKQ4(13s+%>yvt(pMv z3B?NMJ6+M<>$X4_$J^6au;eJm<|;A~xXfRcR&sK9Ro8pR5EJ5Poil0?Um}^J#5oNW z1m?V<+Znn~p;Gg8C#3=so8GTnrA|4B#$G!}z-=AK$?;iTedJo6?oJ=9bQA7D4Rt1>U<>V{6qk1utOOAm-}4` z$?rJ91~L3rP8d>5>&1Zt)?f^&c_@$SpPOTvF)dJx9reSI$S+HX+tv^_0T(zh!Hllu zmbqdCrQyh|zv}&ft9eG2{)HS^Sk!96uzOq!KdeS=X~GtF9PL(wXVuL`kQAqWo^E0B z%*l7vcv3<7G*ONWZzdBPto8J-s8aW9?|Kf$oVcuORKq;Cmt%X&*nx1H@uM|}#6cBk znw$}{K1(~g;Pu7Yr({jlSN_CHFw;k5*ifCWLft1IMG6ALTU?%pEV)jt#~lFfv*J+f zDz>X_57}zq6DfM!uzZQeYR0^}<1V%LO)$KEZj+3`-O{#FrB_C$h}{(o>KOrgH_M-`f`mUV!`Okas{jHZI|(_UUJ{FS#6olksk_z`z~_4 zCRG!|Grl7;26YN>h>oNk6`oP_yO$YlrX(LJ`rTkhJ=dKLC;mNJ##VNT(he@L_#S9~ zidPlqs#q-RRe70Jf|%6Y_mLYL^>HSOx3mS4+;)zb`*=6+eM~Q*^~y$1$=)@g%BDWi za^Ll7*|4b1up)@x)56+hqMi20US^gzV2SL}AuObZsf8vM3Zs)b5T4$I(ysqoS((zyN z)hA@lB?ZrQC3>}X$agT8&R|gP^c~`h@0R6H za&Sc$ZBZ3Bctf%;DA--z{_&#LdtQN-__bR(kLHCfX%7Sdf_4G_~p^>vM zzg}US5O$V_otL5s1#%^dO8HA0$tOk)UN-qn*QK<#P5b6Yd@Rb8?hg9Fbe4H~6d|K3 z>X2F$>MeMVSoz*?-mRnPJ;6IYlq`gbuwi*A$IVnPdykh|6E#$ITqZBj9IA*9Mg|~r z6QdSX3(EGA@Dn0$TwAY_8zxE*wzb(;!JtSJ*C`GX(WvIkkenA~IAMG04ZI1FEmePz zCoLBkKhcvt?Sy2%{viKhmx*4bz&pd4XQSs`wE%QOaMl&Po zyp6)pD2Q-6he4I*tVhagkEeahlCNBFkWTzdb0rv2Yv4{(b20jcwytyZtz}rrnAm$1W|iqN?Su+Q-P=R{civLE$>R|9H^O%QJV03a9M1Vdr9-(8lyCKpqukH|vtS1P zFK^apUyd9}h}V*bYG4x%Pm)*<8!mIKWfG0h0fGGMILKxRqbK3_ovqJ>{HvZ-q@P&z z17M;tzeu%B@ZIf*>Sw>J*GYK5jQotJKdT$3Fmv#IhUw zN-j%CbIzUX1>+gb^K{I!a@ADyCSWcewbf{B7qNiXEarRA(GZps8q~B=C1>szqAD3wC9N$veDT|0w-T!X=RYrJ66DuT-(0zE>qbs^i7yaqW&|+$Mz}qGJYHyy+b?0{8$(Ctc{>6L ziJ?u8)}^!Cy6GjFGh?5X$*-t{#95`1_)uC2;~8?4+h_uxXRl^x=rcMej6xm|05UPs z^65yjtk>-_lCKY41n?ISd^%VJUK|2@Ff_ZwD10m}iA9Ylw2f{vqG{26a?Kz5MIB;r zv_lTQN%tN{iv83yO`@RPb#l4{mXhZMyc^@1;=D{Pm#aTl`%(l!dnQ0N8tHpm0$bOH zsKJs~PYv7lW|BXoji9EHCauwf1b*?Eb|m*h-&ciW*h4;u?vjI{rdu#1XpQn=T$lvp z#%vtbXA!)xuccVDIcpNQU0*JNaV)*UsqOhy@d}Dl?L@W%K(vEFA?QzZ$cf#O421kJK_SPIKsUyH0BP*^64$4t9gctWiKoN zgmI<5WkV7P7OWxW4{@%eKcoeQ_d~Fl`1~d|l4qi;<)J~Kx3%iHn8)VA=uelx-Mh$K`+h#P)1O0tqd5(jcj5Z%R#)-aDCjkQm%hH0|i=}HH*6ACq z`UW#SU?|@Vx)RtivN=D4ti~9!gM#;7@6TyNFB5}vNI~)E@EE}n8UQYtyE)gX&lZy8 z`%vQVhc>A+3tcAc220wQ=Kdodwo?9r1U~S6Td^4g*+661^`s81#Te;IOfs z(faU@EQKp5kKHAxeCk%8eX z{1k&iX_k_}9nl$t`b=HS)d0(xcY?&hDGB?qs##!^J@T|%x0w{H9X7Xa*iMw8`N3`h z$6}|w@_O3t3j+lEici*>p9Ck0&Rwy&RKvq1}NjH83!= zPOEG@sdeRz%m^{Qpu15L^a5F&_`m9Z+!;5a3ovMJ2)HCrByR~@qTSFhN<*kRRFI0U z8Xrqd1!Byu!mgW9XOyeAYXaT0eCBoKJYIBOzkCD^Z>}Yv_WD_^r-L_H%;$)I+vm|> zpB-mU2Hx3V6`I+)n63dbuxH~T=mqVyDix@P4Q(w|Km`$+hJ#a;v<>`V(8v_BZn%Fe zBJr!G4}WBxkCjtlRSEg4_3GTBRPu4ivQVHP1C+|`iaO{#S*Z3wws5hG%B_HExa6Y{ zetGGuOwN)KHM1Qv3EMJV^#!{7S3rPHg<@{lN=w)KX=ZYr@3EFey=p*%VJ|go6-?Uj zlnjpOl)Tb#pJF31PRQQ3ACP)>`jLky1>r2yAK}f0s0SH|t(om7CA;Edgrj5+X(Z(M z`oFYI569Jdn~dVmTe21CZN*28H1mBu6Z*R@$!A>uv2~0%K?^ctV!@#}pQ)`(l8>3X zrpc_#^&A|7%k5)tJdWK<#GHG*$lkYnj~{-rDuH?;gb(7j&Kof38vfoqGiS_s@+ItH ztlhSUy6TNrQjAIdXnsu<7$ia07kAltu|&Fz)aHL7+rvWAY-N{GzYYjyjK+Y4CE-$a zd;-(TfYolm##Ocel#^1cLPh5e1oGKJzA#?dJUkuHs>rcAR%hqY`u+;*y^VpOrB=D1 zH=nIKmc?8xO{ceY<@~n(ct$DTnM<$$8?v}bh&TT^BU%HdZSrpl_ekS|1RTxm`i&0; znLQlwOceWUwB#AqpI9#ZGUkfS^``GfmeL^T9+PO~vQn`?i}%_G`_ z`nji94kFL8)UTQCI9eJ`d=bBg)Gryx1=J+kLonVnU+=k0jNaBPdi z@;q_|wGWS|BK7YDBLZt8L&F>_)nkj=6|)17ADck(=Z^^9odxhO%PUL< z=2M!dHnLe4=0`TNNu(?q)?^TFFQg{>c+AWNb>Q3eOgUbBxCFK=DRBz5OGGkd-_0Mt zH-4u|Z1Sg&*UR`y zyQ#IS@J=}LCjGI-?rB7};eShNyj!~XxbKl&wv!Q6l#zuPl8q@(slNd0klyxmZ=ausnr04Rdjmf>o5B+(Ul$KM}FW^ZoYQ>G4 z7xXm#H%Dwt3IPx?%6pA3wcWjX>4|%V-w21^QGlz^WNdc2$RU5>B^y3g+5H#U)>rc@ zrTwI0K;Na!rOUCUN;th!!kZa-yMYE1!Ns6zDr<%10TEF$A(y2SH#GzQiV;4A(z299 zB}h@C+=tzo@EL=%u)vr3;S-_vOx$7?_hv^FO%B2_D~o)@IxlpKG`Y>HLewd*I22mR#C?P(PO(?Q)E$Oy(urz zy|03$sfW}MIrC}c3~~ElG1o;6GQ-f~cXkD-8YD-UFD3Ucy=gdRErr+Qnn(=cr?ef3 zwAMB`bS?@*u~`1%I^iL#oq@bARgX-$_3i905L?T}BLzGCsui{j zyxPg^+p6<_(`8OJ$jY`ytwfe;B%DHAk8RX)%x~?KFZ&^aKwrs}O)KfOL;j4J*4lHBbBbtSV(h5RyWaI)S#x&DCy)P(>B$d7I*dLH#b+v3U@DOrq+GX#B`~ z@AZnu7^OIwJ9IxJ`l`sB$|zTM88ZLWf~-&1OL!zP@)rxi|(2UG<@| z${1k{S$6!?K1+ucau56x2cMz?gdb-+_?rU@9LH~G>EC2`tkKVsSldhcw$#^31I#SD zoNi<6Irip=kj>f$ag+difStGRlnejCUrpx*t9Tkx$y#5xUpt{Cm-P)Bvs1A|dH?f= z_(B$qKrFc=P1ipUXD?qwf;7X4Ik9_x2l)EOq@Q2nC(EfB%jXYfOQS{7`G`{M-Jtbo zH`ktFXCf;&dc8t~n$Jo}4iwNc=3lReHchhRw!}nMgGTfw15ja%3v8iL5~zS@Jy;Gu zG*gNQ4|2|qn$1NLpYT`C6(!hD*eW(To)opkQD7_E##;!U-wIIYl|E8}oXTyo-rHQQ z9+=CYKk*e;ig_~CpbY{4!eI`x=EDc|gE%H8sYaM*b4L87Kv?6^7Q_4Fa8_bZ&0}?2 z%q`+hXg!H;f~vjrk)k-{Yn3>h*8m?PV*SyhvRe5U>m@4CMZGpzr~Mv!#7c1vsHKVb zj!)J3i@K@lE(wHMyT(8omF|IkX3MZ2it>9>k!vC9lxSyUxiO1XFGuLTCF@sK8~Qsz z@4CpLSX!wM|w?ZkAt*HwW1-{9|KoMTY(0h?fKWGhyTGi;Th3jI0V5-A- z_M=PQW!0|{H#E<+-`3aOF60gSt=Feq#iV?SN{D;1_+~6mvW?sm%eJha3i8T&0a^?s zcBj*PrIM$kp)>Z%Q2|llJ7B+<$}bebKPHs^rp6$(MmjCT_lIikJe^;fEFRTGkLEF947MuW zs@K}t(t3KSRo}(S7!I4y{a9S`N7dkmw3*=p8#$&j0Wu2y^B6lztt8sHe(3u(poQWx ztG&7!a2}eyv{yKf(5mw9q4}g>hSu-;zINXP>#J1ubt^=($t~gd(#eg!W!f%=vqhu? zbGEBik4{j5thWf6V1+arfOSfh!X@+G?Mb3Ch4()Cp3izQW%m?cr+Q%pSO4JgV6B`s z^MhanwRu0KYSgR*nc&&OVNA|R59)cjMS>%~wy494J!$blYDx_4igeU?9!dsRzp;EkzPCU^E8p9$1h8AhjF z^(EzmSL=P^gfZ0>8{l2h&}2GCJ&6??9y2u3Bo+7FJMNQDibi4y`54Rwc(g4rT_k#+ zyDI}fz1!&E-Fjt-=}$si>TiD+>+=`6JPaaKA0hDvPd8hC)?k_;soks};xLV0#Ip{S z-fz7|$}4x>4-(8ZPQvp`0jk1v-dCqhmICRH?-*xU60P=SD}VPd4SufU3W2CtvKV`2 z*DKK{=v;bXRdqswQ9@`UF}vOqn%kOhPc!7(2p=P)1%vkIb@F3fmW~n{dJBe6x4m({ z$}^tm-^{!hFjH@nrfe;t&s-F_?91)^Ro6>ArF6r!B_Z?c~MU6L6fqIabjA?iTR_gmu4d#$3~pT#IGZ1Isev-fnv6 zs=u6=GT#3y@5;Z~+`4ex4>i+)a0%*a=~XqB8cI>p-fC&JsG+%Lu7ncvSVP*XDN3m+ zs%~k`QKAu&)~&H(DiKoB8e@o*5S1X`>;CZl6W{y8^R9EwyY}8^ul=62&fd>iCw)dd z0q^5d$F7&=tm{$a`B2Z(Fk+5G)3wZpCr)TQxca?&k2-623Nz=}ep+7cXG#)i&ufyu zWy&X9N6p(SHdt6~1|BS;YBjm!pT))bKR%@=+rwKmLw`OQvJ8|@wppsjl!~A zEF;G6I%ZYcDAkJ0M{z;vJyKCLiAScZ^)S}U8_{RPYVC8>VCS%IsMP{}bz__Q;!mf3 z&kOKN*BQG0jI+-?%)$F_Q$@a2ZhnVetAiSxBF0ZkKXk^?8)O&pi)c*?UG~xfo2n$f zh~?#0dnIM)qP_K2{iz{#u+wZFcF@G?jN7w(J{A9zhcm3TqlK8;Oz8f=hiTfperZ0j z&$G3ZP{CZe3o;rQuZ0!+(T{JAKdpnRUu9Dw=XYME*9%X37;?NuR-l1UMk76|oJl!n z9P%CMBsl2{Gi4evwp$aLMN zO-y(ZBpaD1PmLf@c!8dTwt~H)$Qae#(7tNU=FAb@l=mz!@AA#ORXJ8kxJz{C*ptLQ z#N565o!$oLhl*Lgk}mNvp3XsZbsUROOwXC(py3Wj_s8>9m-sufhOP+;uu_sK=bLke z^v(;3%;n9^#`>uEG(+$%v=)Okc^d5NC5&c+ zHqKMw$3LbXU#u@a8T^N9Z%Dq z8j3&SuOwUC8U~wVN1+U|?}OR+QX>238*KWmDHHV6bY;r?-44zxyS<#DvB278bkq}` z{vi79qZh7mLcMO7vz8z7!1qh`6bUt^nS0P@o;J6{+6gh zoJWGqI?5--lWKNYwRF@Xr`|_pTj=IA{jsD;K|wgB3C{;c1X7{Ac!VW-Ia7C2&lsL_ z%ABQ0J(cfO)7SVjL!wC(?I7q{P6z@Q%5Utz+%=ezpNRWx@BRMJWmBU8zqmmI)Oh-{^io3E$yfy-+48ED5 zmiCr_a+OMuLLJZb`Q_e^vv;`SW4Hb@T^2SJZ6**UWfKb$Tl0tY`}Z11RJU@cUnV?^ zY#ZA8EL+ooW|)`tVq{ar1|h3V|1zsqyL*F+?Gs(j@qh3s-GT7%Yl#OUDR|kEnoaj# zJ2Cz1D`cG_ShnNA%LLB3MC8Z*g1efC8AfpH z3}GgFyz=0EIE}GW2W7tuS+&9e+0-jgLA1GY$XCr}q6Om>>yJpEGa5pX{cni?cu`ajkpb(|$gKZx<4g$3~ok*tb zb8J?5%3yg>ujMg+pY3og^nR<|w4aSeu#|zHLL0*|BCC}tI7zeE90&L8CAP-98_C{T zcV_UbHm09sptnQ~0S5gOuuzt#*stcjAuH^bVAi_?{OFqO16#7nxL5Wi>AsBdUK;Np zH7a5_ZhI-f-hDs1e`7go`6V{%k&2X{7h?OBR?Re%(>8+KT`Rame^+n&cSiU^Eb2hD z4LgWP*?N_3(KM!6)gX^v<)Y0vZIkhl!!I(CBa2t?&A)wKVaM9z@i7`S40mj#Ml}xa zRX=c!=z6miAnUd1j};Qcs}YhFUVg<&Bzsi5{!TdnkEV z6j&I4z`;M(Vlm9QHmI5x5lR;&fFlKrwJg3H%|EM!QaiK6upc(W2&&m%Zk{}uWKTJx zJw<+*mZc&kVq)Aqb;jrxpzk}$({=kEGA(J{zzg8YjXAp(s);7eUqm$vhEcTG}CMJ~>3Vo}Qw|gf!9tDQK-<%IzsKn2KXUhAL7we+OFXw&$+? z4LVeAdofHnReGpyYVBeGu$3iMmtR>%E=m%Ms9z($R09G{^m}=5r*pxBCa?okQ1i72 zXdxEVuIp`DZyN7`7*|5WfnujU3ZK9u+_&oYV!;T&|X={>up+`S0V+-3?#gcI0ZOTI7M1ZpR^@f zU;t7uOH5@<&HNeJ<$!S1SK~$9)LY64-#*cZ6c*p@Fy&R3#{uUO4a|vh#h0D&ZTGZK zqDr>@F$&2@;-fpcsl%AgMyfkIw5B$rXx=30nSe%-6B$lOhNm~`HqPQeMc0Tgs9#Ot z(e(HnAtYQpi#8DB&p^!#!WD^;%d4RoR8=y8QVXzj7H2DD^d0O1vUSGTla}R;Egxlu z5@#0{^OQ(%MFL}&L6Zso@EVwzTTJKdld^sp&>59aJJ}KoJDYm~+2^y7PY4Rxk934n zRgVP`!a@)$e5@jK+P)`DxXTfUtxJwr8{UDdqxJF7p_ZXF?JPTUKk?JZo6Na zG`cj=6O|!bVd;^a>|n}xh$CI_JO9`HnZawsPa0Z8iYa_y6@nlHnNOAiPViWb1 z7EjV+yf!y^ICow7m?Dm~ySP<07%;fY=v>VITwthoG{d1>+v5RsWpQxTsoNU3R_(z} z#6LK@3xSUCgF*s>Z;O0Oa0hh5%s)YI?$zrMzFLf&&V3{>gVWmH!Ru`vK6;F?)5omb zBgulUd&aqWa5>n<7lf0(gG3?Cma~w&_(-%Yc%ADoIonBoYF*xHHty!i z7$B5fWFn#e zs_Mk2WWxKldmWt(`mj&w8crY)s&wa1Vw*4i09Q^*g5T&)I@sxXWB;xh| zIF>&i&X`CKc^8@p*k|c+y|eV3M|vcxqO8Iq)K`q+iPz@L-BI6r{ayW*MsBd1ArzD} zjC2=v=f^v%!yt5x>mKv6(jq6sO-6MpNY;rN{|c#qZCu>~6j6Sqe_oLPD1SzZLkGDX yu6UNf>U8+>-~!C2|FsS~y8#C6|8qwd@93)yyTz}9Yhg!#=bH7+EA^ItCjS?t;qt@) literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json index 769b82538..465785c8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "dependencies": { "@babel/runtime": "^7.7.7", "@date-io/dayjs": "^1.3.13", - "@flock-community/flock-eco-core": "^2.7.8", - "@flock-community/flock-eco-feature-user": "^2.7.8", + "@flock-community/flock-eco-core": "^2.7.9", + "@flock-community/flock-eco-feature-user": "^2.7.9", "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", @@ -1893,19 +1893,19 @@ } }, "node_modules/@flock-community/flock-eco-core": { - "version": "2.7.8", - "resolved": "https://flock.jfrog.io/artifactory/api/npm/flock-npm/@flock-community/flock-eco-core/-/@flock-community/flock-eco-core-2.7.8.tgz", - "integrity": "sha512-K/VS2vwG7kQnFd9O+1hk/a50tqil+0C2Qu4LqEVhyEB4OFAs1ugQnhM8L/Fl1/XdjM1QPw6gSyeDWRbFodjebg==", + "version": "2.7.9", + "resolved": "https://flock.jfrog.io/artifactory/api/npm/flock-npm/@flock-community/flock-eco-core/-/@flock-community/flock-eco-core-2.7.9.tgz", + "integrity": "sha512-5XNqKPE5zNOwCSlWoKAN9AiIwF1OfjDVnG3uQXCEY/rWRLPOpWCI0nFvvMmCGKHna71cr+Hy25j8gZ5308tgNQ==", "dependencies": { "typescript": "4.5.5" } }, "node_modules/@flock-community/flock-eco-feature-user": { - "version": "2.7.8", - "resolved": "https://flock.jfrog.io/artifactory/api/npm/flock-npm/@flock-community/flock-eco-feature-user/-/@flock-community/flock-eco-feature-user-2.7.8.tgz", - "integrity": "sha512-LpeA7aqNle7YT+eVCKK2ZWF3pu6G2DmPbJxMN4TyOCmQ4A0yidKx2iCjHQ1LNTO0WP55GZ5/U0Ny7ik6DTsbjg==", + "version": "2.7.9", + "resolved": "https://flock.jfrog.io/artifactory/api/npm/flock-npm/@flock-community/flock-eco-feature-user/-/@flock-community/flock-eco-feature-user-2.7.9.tgz", + "integrity": "sha512-vbHb2AXag50oc3Ra7n2wi1ygN8nkpRe4bpmNBn+a2kxyarrtlltcE4yZjfAWAAuHRnf9+VU22eT/uwMyeKfOZA==", "dependencies": { - "@flock-community/flock-eco-core": "^2.7.8" + "@flock-community/flock-eco-core": "^2.7.9" } }, "node_modules/@flock-community/flock-eco-webpack": { @@ -32131,19 +32131,19 @@ } }, "@flock-community/flock-eco-core": { - "version": "2.7.8", - "resolved": "https://flock.jfrog.io/artifactory/api/npm/flock-npm/@flock-community/flock-eco-core/-/@flock-community/flock-eco-core-2.7.8.tgz", - "integrity": "sha512-K/VS2vwG7kQnFd9O+1hk/a50tqil+0C2Qu4LqEVhyEB4OFAs1ugQnhM8L/Fl1/XdjM1QPw6gSyeDWRbFodjebg==", + "version": "2.7.9", + "resolved": "https://flock.jfrog.io/artifactory/api/npm/flock-npm/@flock-community/flock-eco-core/-/@flock-community/flock-eco-core-2.7.9.tgz", + "integrity": "sha512-5XNqKPE5zNOwCSlWoKAN9AiIwF1OfjDVnG3uQXCEY/rWRLPOpWCI0nFvvMmCGKHna71cr+Hy25j8gZ5308tgNQ==", "requires": { "typescript": "4.5.5" } }, "@flock-community/flock-eco-feature-user": { - "version": "2.7.8", - "resolved": "https://flock.jfrog.io/artifactory/api/npm/flock-npm/@flock-community/flock-eco-feature-user/-/@flock-community/flock-eco-feature-user-2.7.8.tgz", - "integrity": "sha512-LpeA7aqNle7YT+eVCKK2ZWF3pu6G2DmPbJxMN4TyOCmQ4A0yidKx2iCjHQ1LNTO0WP55GZ5/U0Ny7ik6DTsbjg==", + "version": "2.7.9", + "resolved": "https://flock.jfrog.io/artifactory/api/npm/flock-npm/@flock-community/flock-eco-feature-user/-/@flock-community/flock-eco-feature-user-2.7.9.tgz", + "integrity": "sha512-vbHb2AXag50oc3Ra7n2wi1ygN8nkpRe4bpmNBn+a2kxyarrtlltcE4yZjfAWAAuHRnf9+VU22eT/uwMyeKfOZA==", "requires": { - "@flock-community/flock-eco-core": "^2.7.8" + "@flock-community/flock-eco-core": "^2.7.9" } }, "@flock-community/flock-eco-webpack": { diff --git a/package.json b/package.json index 410ed0ce4..b2e3d5855 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ "dependencies": { "@babel/runtime": "^7.7.7", "@date-io/dayjs": "^1.3.13", - "@flock-community/flock-eco-core": "^2.7.8", - "@flock-community/flock-eco-feature-user": "^2.7.8", + "@flock-community/flock-eco-core": "^2.7.9", + "@flock-community/flock-eco-feature-user": "^2.7.9", "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", diff --git a/pom.xml b/pom.xml index 3a6048567..fa7e9fc30 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ flock-eco-application-parent com.github.flock-community.flock-eco - 2.7.8 + 2.7.9 flock.community.eco.workday @@ -45,6 +45,10 @@ org.springframework.boot spring-boot-starter-actuator + + org.springframework.security + spring-security-oauth2-resource-server + org.springframework.cloud spring-cloud-gcp-starter-sql-postgresql diff --git a/readme.md b/readme.md index 98ce4ed8d..fef700fca 100644 --- a/readme.md +++ b/readme.md @@ -1,22 +1,44 @@ # Flock Workday -## Run +about + +## Get started + +Run the Workday app, with the backend and frontend bundled together: ```bash -./mvnw clean compile spring-boot:run -Dspring-boot.run.profiles=develop -Pdevelop +./mvnw clean compile spring-boot:run \ + -Dspring-boot.run.profiles=develop \ + -P develop \ + -P frontend ``` -Mark `src/develop/kotlin` as source directory. - -Add `develop` to the springboot `application` run configuration active profiles. +Run a full build of backend and frontend, and build a Docker 🐳 image ```bash -./mvnw clean install -npm install +./mvnw clean install jib:dockerBuild\ + -P develop \ + -P frontend \ + -Djib.container.environment=SPRING_PROFILES_ACTIVE=develop \ + --file pom.xml ``` -Run `application` and `npm start`. Make sure you're using the correct node version. If you have nvm installed, -run `nvm use` to set node to the version defined in .nvmrc +### Backend tips + +- ℹ️ Mark `src/develop/kotlin` as source directory, if not done automatically by your IDE. +- ℹ️ Add `develop` to the springboot `application` run configuration active profiles. ( + Find [`🔗Application.kt`](src/main/kotlin/Application.kt), run the app one time, and adjust the config) +- ℹ️ The `com.github.eirslett` dependency is used to package the frontend together with the backend, but this only + happens if the `frontend` profile is active (`-P` flag). + - Example: `./mvnw clean install -P frontend`) + +### Frontend tips + +- ℹ️ Workday makes use of [nvm](https://github.com/nvm-sh/nvm) and an [`🔗.nvmrc`](./.nvmrc) to define the Node version. + By running `nvm use`, you activate the configured Node version. +- ℹ️ To run the frontend independently, run `npm install` and then `npm start`. + - A webpack devServer is used to proxy api calls towards the backend, which is expected to run on port 8080. See + the [`🔗webpack.config.js`](./webpack.config.js) for more details. ## Users @@ -30,12 +52,31 @@ run `nvm use` to set node to the version defined in .nvmrc ## Linting -Use `ktlint` to lint kotlin files or `eslint` for javascript files +Use `ktlint` to lint kotlin files + +```bash +# check code style (it's also bound to "mvn verify") +./mvnw antrun:run@ktlint +``` + +```bash +# fix code style deviations (runs built-in formatter) +./mvnw antrun:run@ktlint-format +``` + +Use `prettier` for javascript/typescript files + +```bash +# fix code styles for js files with eslint +npm run lint format +``` + +[Install the prettier plugin in your IDE](https://prettier.io/docs/en/editors.html) to get the most out of prettier. ## Database - Generate diff file with liquibase - ``` + ```bash ./mvnw clean compile liquibase:update liquibase:diff ``` - Rename `db.changelog-diff.yaml` to `db.changelog-#.yaml` @@ -49,23 +90,38 @@ Use `ktlint` to lint kotlin files or `eslint` for javascript files relativeToChangelogFile: true ``` -```bash -# check code style (it's also bound to "mvn verify") -$ ./mvnw antrun:run@ktlint - src/main/kotlin/Main.kt:10:10: Unused import +## Integration with Ory (authentication and authorization) -# fix code style deviations (runs built-in formatter) -$ ./mvnw antrun:run@ktlint-format +See also [Identity access management](./docs/identity-access-management.md) for the prerequisites and more detailed +information -# fix code styles for js files with eslint -$ npm run lint +It is possible to run workday locally, integrating with the Ory stack (Kratos, Oathkeeper, Keto) for identity access and +permission management using the docker compose file. + +```bash +# Yolo, TL;DR +# Start everything authentication/authorization related +docker compose up -d + +# Alternatively, start the spring app through IDE, with profile develop-kratos active +./mvnw clean compile spring-boot:run \ + -Dspring-boot.run.profiles=develop,develop-kratos \ + -P develop \ + -P frontend + +# Go +open http://workday.flock.local:8081 ``` -## Generate secrets +### Development info regarding the Ory stack + +See [Authentication and Authorization](./docs/authentication-and-authorization.md) + +## Generate secrets (deprecated?) Generate secrets to deploy via travis-ci -``` +```bash tar cvf secrets.tar ./service-account.json src/main/resources/application-cloud.properties travis encrypt-file secrets.tar --add ``` diff --git a/src/develop/kotlin/mocks/LoadAssignmentData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadAssignmentData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadAssignmentData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadAssignmentData.kt diff --git a/src/develop/kotlin/mocks/LoadClientData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadClientData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadClientData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadClientData.kt diff --git a/src/develop/kotlin/mocks/LoadContractData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadContractData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadContractData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadContractData.kt diff --git a/src/develop/kotlin/mocks/LoadData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadData.kt diff --git a/src/develop/kotlin/mocks/LoadEventData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadEventData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadEventData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadEventData.kt diff --git a/src/develop/kotlin/mocks/LoadEventRatingData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadEventRatingData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadEventRatingData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadEventRatingData.kt diff --git a/src/develop/kotlin/mocks/LoadExpensesData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadExpensesData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadExpensesData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadExpensesData.kt diff --git a/src/develop/kotlin/mocks/LoadHolidayData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadHolidayData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadHolidayData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadHolidayData.kt diff --git a/src/develop/kotlin/mocks/LoadPersonData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadPersonData.kt similarity index 98% rename from src/develop/kotlin/mocks/LoadPersonData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadPersonData.kt index f0bff2d73..327191f90 100644 --- a/src/develop/kotlin/mocks/LoadPersonData.kt +++ b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadPersonData.kt @@ -3,7 +3,6 @@ package community.flock.eco.workday.mocks import community.flock.eco.feature.user.model.User import community.flock.eco.workday.model.Person import community.flock.eco.workday.repository.PersonRepository -import mocks.users import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.stereotype.Component import java.time.Instant @@ -73,7 +72,7 @@ class LoadPersonData( init { val userMap = userData.data.associateBy { it.name } - users.forEach { + mockUsers.forEach { createPerson( firstname = it.firstName, lastname = it.lastName, diff --git a/src/develop/kotlin/mocks/LoadProjectData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadProjectData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadProjectData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadProjectData.kt diff --git a/src/develop/kotlin/mocks/LoadSickdaysData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadSickdaysData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadSickdaysData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadSickdaysData.kt diff --git a/src/develop/kotlin/community/flock/eco/workday/mocks/LoadUserData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadUserData.kt new file mode 100644 index 000000000..144820c6f --- /dev/null +++ b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadUserData.kt @@ -0,0 +1,116 @@ +package community.flock.eco.workday.mocks + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import community.flock.eco.core.authorities.Authority +import community.flock.eco.feature.user.forms.UserAccountOauthForm +import community.flock.eco.feature.user.forms.UserAccountPasswordForm +import community.flock.eco.feature.user.model.User +import community.flock.eco.feature.user.model.UserAccountOauthProvider +import community.flock.eco.feature.user.services.UserAccountService +import community.flock.eco.feature.user.services.UserAuthorityService +import community.flock.eco.workday.authorities.ExpenseAuthority +import community.flock.eco.workday.authorities.HolidayAuthority +import community.flock.eco.workday.authorities.SickdayAuthority +import community.flock.eco.workday.authorities.WorkDayAuthority +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.stereotype.Component +import java.io.File +import java.io.IOException +import java.util.* + + +@Component +@ConditionalOnProperty(prefix = "flock.eco.workday", name = ["develop"]) +class LoadUserData( + @Value("\${flock.eco.workday.login}") + private val loginType: String, + private val userAccountService: UserAccountService, + userAuthorityService: UserAuthorityService, + private val objectMapper: ObjectMapper +) { + + val data: MutableSet = mutableSetOf() + + val workerRoles = setOf( + HolidayAuthority.READ, + HolidayAuthority.WRITE, + SickdayAuthority.READ, + SickdayAuthority.WRITE, + WorkDayAuthority.READ, + WorkDayAuthority.WRITE, + WorkDayAuthority.TOTAL_HOURS, + ExpenseAuthority.READ, + ExpenseAuthority.WRITE + ) + private val allAuthorities = userAuthorityService.allAuthorities() + + private val workerAuthorities = userAuthorityService.allAuthorities().filter { workerRoles.contains(it) } + + init { + if (loginType == "KRATOS") { + mockUsers.forEach { createUserAccountOAuth(it, getKratosIdentities()) } + } else { + mockUsers.forEach { createUserAccountPassword(it) } + } + + } + + private fun getKratosIdentities() = try { + objectMapper.readValue>(File(KRATOS_IDENTITIES_FILE_LOCATION)) + } catch (e: IOException) { + LOG.warn("Could not find existing Kratos identities. Will create users without Kratos link") + throw IllegalStateException( + "Kratos identities could not be found and linked to users known in Workday. " + + "Be sure to run `docker compose up -d` to generate the kratos identity file" + ) + } + + private final fun createUserAccountPassword(mockUser: MockUser) = UserAccountPasswordForm( + name = mockUser.firstName, + email = "${mockUser.firstName.lowercase()}@sesam.straat", + password = mockUser.firstName.lowercase(), + authorities = mockUser.authorities.map { it.toName() }.toSet() + ) + .save() + + + private final fun createUserAccountOAuth(mockUser: MockUser, kratosIdentities: List): User { + val email = "${mockUser.firstName.lowercase()}@sesam.straat" + return UserAccountOauthForm( + name = mockUser.firstName, + email = email, + provider = UserAccountOauthProvider.KRATOS, + reference = kratosIdentities.find { it.email == email }?.id ?: mockUser.kratosId, + authorities = mockUser.authorities.map { it.toName() }.toSet() + ) + .save() + } + + val MockUser.authorities: List + get() { + return when (role) { + Role.ADMIN -> allAuthorities + Role.USER -> workerAuthorities + } + } + + + private fun UserAccountPasswordForm.save(): User = + userAccountService.createUserAccountPassword(this) + .user + .also { data.add(it) } + + private fun UserAccountOauthForm.save(): User = + userAccountService.createUserAccountOauth(this) + .user + .also { data.add(it) } + + companion object { + private const val KRATOS_IDENTITIES_FILE_LOCATION = "./docker/kratos/identities/existing_identities.json" + private val LOG: Logger = LoggerFactory.getLogger(LoadUserData::class.java) + } +} diff --git a/src/develop/kotlin/mocks/LoadWorkDayData.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/LoadWorkDayData.kt similarity index 100% rename from src/develop/kotlin/mocks/LoadWorkDayData.kt rename to src/develop/kotlin/community/flock/eco/workday/mocks/LoadWorkDayData.kt diff --git a/src/develop/kotlin/community/flock/eco/workday/mocks/Users.kt b/src/develop/kotlin/community/flock/eco/workday/mocks/Users.kt new file mode 100644 index 000000000..70e532bcf --- /dev/null +++ b/src/develop/kotlin/community/flock/eco/workday/mocks/Users.kt @@ -0,0 +1,44 @@ +package community.flock.eco.workday.mocks + +import java.time.LocalDate + +enum class Role { + USER, ADMIN +} + +data class MockUser( + val firstName: String, + val lastName: String, + val kratosId: String, + val role: Role = Role.USER, + val active: Boolean = true, + val birthdate: LocalDate? = null, + val joinDate: LocalDate? = null +) + +data class KratosIdentity(val id: String, val email: String) + +val mockUsers = listOf( + MockUser( + "Tommy", + "Dog", + kratosId = "00000000-0000-0000-0000-000000000001", + birthdate = LocalDate.of(1980, 5, 8), + joinDate = LocalDate.of(2000, 5, 8) + ), + MockUser( + "Ieniemienie", + "Mouse", + kratosId = "00000000-0000-0000-0000-000000000002", + birthdate = LocalDate.now() + ), + MockUser( + "Pino", + "Woodpecker", + kratosId = "00000000-0000-0000-0000-000000000003", + joinDate = LocalDate.of(1983, 6, 7) + ), + MockUser("Bert", "Muppets", kratosId = "00000000-0000-0000-0000-000000000004", role = Role.ADMIN), + MockUser("Ernie", "Muppets", kratosId = "00000000-0000-0000-0000-000000000005"), + MockUser("Aart", "Staartjes", kratosId = "00000000-0000-0000-0000-000000000006", active = false) +) diff --git a/src/develop/kotlin/mocks/LoadUserData.kt b/src/develop/kotlin/mocks/LoadUserData.kt deleted file mode 100644 index aecea41fc..000000000 --- a/src/develop/kotlin/mocks/LoadUserData.kt +++ /dev/null @@ -1,64 +0,0 @@ -package community.flock.eco.workday.mocks - -import community.flock.eco.core.authorities.Authority -import community.flock.eco.feature.user.forms.UserAccountPasswordForm -import community.flock.eco.feature.user.model.User -import community.flock.eco.feature.user.services.UserAccountService -import community.flock.eco.feature.user.services.UserAuthorityService -import community.flock.eco.workday.authorities.ExpenseAuthority -import community.flock.eco.workday.authorities.HolidayAuthority -import community.flock.eco.workday.authorities.SickdayAuthority -import community.flock.eco.workday.authorities.WorkDayAuthority -import mocks.Role -import mocks.users -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.stereotype.Component - -@Component -@ConditionalOnProperty(prefix = "flock.eco.workday", name = ["develop"]) -class LoadUserData( - private val userAccountService: UserAccountService, - userAuthorityService: UserAuthorityService -) { - val data: MutableSet = mutableSetOf() - - val workerRoles = setOf( - HolidayAuthority.READ, - HolidayAuthority.WRITE, - SickdayAuthority.READ, - SickdayAuthority.WRITE, - WorkDayAuthority.READ, - WorkDayAuthority.WRITE, - WorkDayAuthority.TOTAL_HOURS, - ExpenseAuthority.READ, - ExpenseAuthority.WRITE - ) - - private val allAuthorities = userAuthorityService.allAuthorities() - private val workerAuthorities = userAuthorityService.allAuthorities().filter { workerRoles.contains(it) } - - init { - users.forEach { create(it) } - } - - private final fun create(user: mocks.User) = UserAccountPasswordForm( - name = user.firstName, - email = "${user.firstName.toLowerCase()}@sesam.straat", - password = user.firstName.toLowerCase(), - authorities = user.authorities.map { it.toName() }.toSet() - ) - .save() - - val mocks.User.authorities: List - get() { - return when (role) { - Role.ADMIN -> allAuthorities - Role.USER -> workerAuthorities - } - } - - private fun UserAccountPasswordForm.save(): User = - userAccountService.createUserAccountPassword(this) - .user - .also { data.add(it) } -} diff --git a/src/develop/kotlin/mocks/Users.kt b/src/develop/kotlin/mocks/Users.kt deleted file mode 100644 index bba080647..000000000 --- a/src/develop/kotlin/mocks/Users.kt +++ /dev/null @@ -1,38 +0,0 @@ -package mocks - -import java.time.LocalDate - -enum class Role { - USER, ADMIN -} - -data class User( - val firstName: String, - val lastName: String, - val role: Role = Role.USER, - val active: Boolean = true, - val birthdate: LocalDate? = null, - val joinDate: LocalDate? = null -) - -val users = listOf( - User( - "Tommy", - "Dog", - birthdate = LocalDate.of(1980, 5, 8), - joinDate = LocalDate.of(2000, 5, 8) - ), - User( - "Ieniemienie", - "Mouse", - birthdate = LocalDate.now() - ), - User( - "Pino", - "Woodpecker", - joinDate = LocalDate.of(1983, 6, 7) - ), - User("Bert", "Muppets", role = Role.ADMIN), - User("Ernie", "Muppets"), - User("Aart", "Staartjes", active = false) -) diff --git a/src/main/kotlin/authentication/KratosIdentity.kt b/src/main/kotlin/authentication/KratosIdentity.kt index c52b72ce7..030671590 100644 --- a/src/main/kotlin/authentication/KratosIdentity.kt +++ b/src/main/kotlin/authentication/KratosIdentity.kt @@ -1,13 +1,5 @@ package community.flock.eco.workday.authentication -data class KratosIdentity( - val userId: UserId, - val emailAddress: EmailAddress -) { - @JvmInline - value class UserId(val value: String) - - @JvmInline - value class EmailAddress(val value: String) -} +@JvmInline +value class KratosUserId(val value: String) diff --git a/src/main/kotlin/authentication/OathkeeperProxy.kt b/src/main/kotlin/authentication/OathkeeperProxy.kt index e58f60dff..aa370ecca 100644 --- a/src/main/kotlin/authentication/OathkeeperProxy.kt +++ b/src/main/kotlin/authentication/OathkeeperProxy.kt @@ -2,18 +2,19 @@ package community.flock.eco.workday.authentication import community.flock.eco.feature.user.services.UserAccountService import community.flock.eco.feature.user.services.UserSecurityService -import community.flock.eco.workday.authentication.KratosIdentity.* import org.springframework.beans.factory.annotation.Autowired import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.AuthenticationProvider import org.springframework.security.core.Authentication import org.springframework.security.core.AuthenticationException import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.oauth2.core.oidc.OidcIdToken import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken import org.springframework.security.web.util.matcher.RequestMatcher import org.springframework.stereotype.Component import java.io.IOException +import java.time.Instant import javax.servlet.FilterChain import javax.servlet.ServletException import javax.servlet.http.HttpServletRequest @@ -21,29 +22,34 @@ import javax.servlet.http.HttpServletResponse @Component class OathkeeperProxyAuthenticationProvider( + private val userAccountService: UserAccountService ) : AuthenticationProvider { - @Autowired - lateinit var userAccountService: UserAccountService - @Throws(AuthenticationException::class) override fun authenticate(authentication: Authentication): Authentication { - val kratosIdentity = authentication.credentials as KratosIdentity? - - val account = - kratosIdentity?.let { - userAccountService.findUserAccountPasswordByUserEmail(it.emailAddress.value) - } + val kratosIdentity = authentication.credentials as KratosUserId? + val account = kratosIdentity?.let { userAccountService.findUserAccountOauthByReference(it.value) } return if (account != null) { - val userSecurityPassword = UserSecurityService.UserSecurityPassword(account) + val userSecurityOauth2 = UserSecurityService.UserSecurityOauth2( + account, OidcIdToken( + "token-value", + Instant.EPOCH, Instant.MAX, + mapOf( + Pair("sub", account.reference), + Pair("name", account.user.name ?: "anon"), + Pair("email", account.user.email), + Pair("kratos_user_id", kratosIdentity.value) + ) + ) + ) PreAuthenticatedAuthenticationToken( - userSecurityPassword.username, - userSecurityPassword, - userSecurityPassword.authorities + userSecurityOauth2.account.user.code, + userSecurityOauth2, + userSecurityOauth2.authorities ) } else { PreAuthenticatedAuthenticationToken( - kratosIdentity?.emailAddress ?: "anonymous", + kratosIdentity?.value ?: "anonymous", null ) } @@ -67,19 +73,11 @@ class OathkeeperProxyAuthenticationProcessingFilter( @Throws(AuthenticationException::class, IOException::class, ServletException::class) override fun attemptAuthentication(request: HttpServletRequest, response: HttpServletResponse): Authentication { // Extract from request - val email = request.getHeader("X-Email") - val userId = request.getHeader("X-User"); - - if ((email == null || userId == null)) { - throw InvalidOathkeeperProxyHeadersException("Invalid authentication headers (X-User: $userId, X-Email: $email") - } - val auth = KratosIdentity( - UserId(userId), - EmailAddress(email) - ) + val userId = request.getHeader("X-User") + ?: throw InvalidOathkeeperProxyHeadersException("Invalid authentication headers (X-User)") // Create a token object ot pass to Authentication Provider - val token = PreAuthenticatedAuthenticationToken(email, auth) + val token = PreAuthenticatedAuthenticationToken(userId, KratosUserId(userId)) return authenticationManager.authenticate(token) } diff --git a/src/main/kotlin/config/WebSecurityConfig.kt b/src/main/kotlin/config/WebSecurityConfig.kt index 800d74e68..38c5a69ef 100644 --- a/src/main/kotlin/config/WebSecurityConfig.kt +++ b/src/main/kotlin/config/WebSecurityConfig.kt @@ -10,6 +10,8 @@ import community.flock.eco.workday.authorities.HolidayAuthority import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Configuration +import org.springframework.core.convert.converter.Converter +import org.springframework.security.authentication.AbstractAuthenticationToken import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity import org.springframework.security.config.annotation.web.builders.HttpSecurity @@ -18,17 +20,50 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer import org.springframework.security.config.http.SessionCreationPolicy +import org.springframework.security.oauth2.core.oidc.OidcIdToken +import org.springframework.security.oauth2.jwt.Jwt import org.springframework.security.web.authentication.AnonymousAuthenticationFilter +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken import org.springframework.security.web.util.matcher.AntPathRequestMatcher import org.springframework.security.web.util.matcher.NegatedRequestMatcher import org.springframework.stereotype.Component - +import java.util.* + +internal class CustomAuthenticationConverter( + private val userAccountService: UserAccountService, +) : Converter { + override fun convert(jwt: Jwt): AbstractAuthenticationToken { + + val account = userAccountService.findUserAccountOauthByReference(jwt.subject) + return if (account != null) { + val userSecurityOauth2 = UserSecurityService.UserSecurityOauth2( + account, OidcIdToken( + jwt.tokenValue, + jwt.issuedAt, jwt.expiresAt, + jwt.claims + ) + ) + PreAuthenticatedAuthenticationToken( + userSecurityOauth2.account.user.code, + userSecurityOauth2, + userSecurityOauth2.authorities + ) + } else { + PreAuthenticatedAuthenticationToken( + jwt.subject ?: "anonymous", + null + ) + } + } +} @Component class MyUserSecurityService( private val userSecurityService: UserSecurityService, - private val oathkeeperProxyAuthenticationProvider:OathkeeperProxyAuthenticationProvider + private val userAccountService: UserAccountService, + private val oathkeeperProxyAuthenticationProvider: OathkeeperProxyAuthenticationProvider ) { + fun googleLogin(http: HttpSecurity): OAuth2LoginConfigurer.UserInfoEndpointConfig { return userSecurityService.googleLogin(http) } @@ -37,12 +72,29 @@ class MyUserSecurityService( return userSecurityService.databaseLogin(http) } - fun kratosLogin(http: HttpSecurity, authenticationManager: AuthenticationManager): Unit { + fun kratosLoginJWT(http: HttpSecurity, authenticationManager: AuthenticationManager): Unit { http - .httpBasic().disable() //No Http Basic Login - .formLogin().disable() //No Form Login - .logout() - .addLogoutHandler(RedirectLogoutHandler()) //No Logout + .httpBasic().disable() //No Http Basic Login + .formLogin().disable() //No Form Login + .logout().addLogoutHandler(RedirectLogoutHandler()) //No Logout + + // No Session pls + http + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .oauth2ResourceServer { + it.jwt { jwt -> + jwt.jwtAuthenticationConverter(CustomAuthenticationConverter(userAccountService)) + } + } + } + + fun kratosLoginHeader(http: HttpSecurity, authenticationManager: AuthenticationManager): Unit { + http + .httpBasic().disable() //No Http Basic Login + .formLogin().disable() //No Form Login + .logout().addLogoutHandler(RedirectLogoutHandler()) //No Logout + // No Session pls http .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) @@ -54,7 +106,6 @@ class MyUserSecurityService( authenticationManager ), AnonymousAuthenticationFilter::class.java ) - } fun testLogin(http: HttpSecurity): FormLoginConfigurer { @@ -75,11 +126,6 @@ class WebSecurityConfig : WebSecurityConfigurerAdapter() { @Autowired lateinit var userSecurityService: MyUserSecurityService - @Autowired - lateinit var userAccountService: UserAccountService - - @Autowired - lateinit var oathkeeperProxyAuthenticationProvider: OathkeeperProxyAuthenticationProvider @Value("\${flock.eco.workday.login:TEST}") lateinit var loginType: String @@ -95,11 +141,6 @@ class WebSecurityConfig : WebSecurityConfigurerAdapter() { userAuthorityService.addAuthority(HolidayAuthority::class.java) http - .httpBasic().disable() //No Http Basic Login - .formLogin().disable() //No Form Login - .logout() - .addLogoutHandler(RedirectLogoutHandler()) //No Logout - .and() .headers() .frameOptions() .sameOrigin() @@ -119,19 +160,22 @@ class WebSecurityConfig : WebSecurityConfigurerAdapter() { .antMatchers("/h2/**").permitAll() .antMatchers("/api/events/**").permitAll() .antMatchers(*SWAGGER_WHITELIST).permitAll() + .anyRequest().authenticated() http .cors() - http - // No Session pls - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .authenticationProvider(oathkeeperProxyAuthenticationProvider) - .addFilterBefore( - OathkeeperProxyAuthenticationProcessingFilter( - NegatedRequestMatcher(AntPathRequestMatcher("/error")), - authenticationManager() - ), AnonymousAuthenticationFilter::class.java - ) + + when (loginType.uppercase(Locale.getDefault())) { + "GOOGLE" -> + userSecurityService.googleLogin(http) + .and() + .defaultSuccessUrl("/", true) + + "DATABASE" -> userSecurityService.databaseLogin(http).loginPage("/").loginProcessingUrl("/login") + "KRATOS" -> userSecurityService.kratosLoginJWT(http, authenticationManager()) + else -> userSecurityService.testLogin(http).loginPage("/").loginProcessingUrl("/login") + } + + } } diff --git a/src/main/resources/application-develop-kratos.properties b/src/main/resources/application-develop-kratos.properties new file mode 100644 index 000000000..eb0c57f69 --- /dev/null +++ b/src/main/resources/application-develop-kratos.properties @@ -0,0 +1,47 @@ +# trim me down to only the kratos related properties. I should only be used in combination with the `develop` profile / properties +flock.eco.cloud.stub.enabled=true + +flock.eco.workday.develop=true +flock.eco.workday.login=KRATOS +flock.eco.workday.bucket.documents=flock-eco-workday-documents + + +spring.security.oauth2.resourceserver.jwt.issuer-uri= http://accounts.flock.local:8081 +spring.security.oauth2.resourceserver.jwt.jws-algorithm=RS256 +spring.security.oauth2.resourceserver.jwt.jwk-set-uri= http://accounts.flock.local:8081/.well-known/jwks.json + +spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE +spring.datasource.username=sa +spring.datasource.password= +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.platform=h2 + +spring.h2.console.enabled=true +spring.h2.console.path=/h2 +spring.h2.console.settings.web-allow-others=true + +spring.jpa.database=h2 +spring.cloud.gcp.sql.enabled=false + +logging.level.org.hibernate.SQL=DEBUG +logging.level.org.springframework.security=DEBUG +logging.level.org.springframework.security.web.authentication=TRACE + +server.port=${PORT:8080} +server.forward-headers-strategy=NATIVE +server.compression.enabled=true +server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css,image/jpeg + +flock.eco.feature.exactonline.clientId=745c6eae-3f5c-4ccd-ae78-4217ff32d621 +flock.eco.feature.exactonline.clientSecret=eEVRgN8GU8wJ +flock.eco.feature.exactonline.redirectUri=http://localhost:3000/api/exactonline/redirect +flock.eco.feature.exactonline.requestUri=https://start.exactonline.nl + +workday.average_sick_days = 5 +workday.average_training_days = 5 +workday.average_public_days = 9 +workday.average_holi_days = 25 + +spring.cloud.gcp.storage.enabled = false +#spring.cloud.gcp.credentials.location=file:token.json +google.drive.sheets.workday.templateId=16dSJHdp-LphqhpodNPrpDCOJLSJmDEe-NNGiZR0lbqM diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 7114c84db..45cea5d73 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -19,7 +19,6 @@ spring.cloud.gcp.sql.enabled=false logging.level.org.hibernate.SQL=DEBUG logging.level.org.springframework.security=DEBUG -logging.level.org.springframework.security.web.authentication=TRACE server.port=${PORT:8080} server.forward-headers-strategy=NATIVE