diff --git a/.env.example b/.env.example index df326738..abf8fd72 100644 --- a/.env.example +++ b/.env.example @@ -26,4 +26,8 @@ EFILING_HUB_CLIENT_SECRET='' EFILING_HUB_API_BASE_URL='' # BCE ID test accounts for localdev -EFILING_BCEID= \ No newline at end of file +EFILING_BCEID= + +# Keycloak settings +KEYCLOAK_CLIENT_ID= +KEYCLOAK_CLIENT_SECRET= diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml new file mode 100644 index 00000000..328e945a --- /dev/null +++ b/.github/workflows/linkcheck.yml @@ -0,0 +1,28 @@ +name: eDivorce - Link Check + +on: + schedule: + - cron: "0 3 * * *" + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: [3.6] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Run Link Checker + run: | + python manage.py link_check diff --git a/.gitignore b/.gitignore index 38c3a5e0..df78405b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ var/ .installed.cfg *.egg .python-version +pyvenv.cfg # PyInstaller # Usually these files are written by a python script from a template diff --git a/README.md b/README.md index 2e9cd6ae..25e96dbf 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,9 @@ To run this project in your development machine, follow these steps: `docker-compose up -d` -9. Open your browser and go to http://127.0.0.1:8000, you will be greeted with the eDivorce homepage. In dev mode, you can log in with any username and the password 'divorce'. +9. Log in to the Keycloak administration console on http://127.0.0.1:8081 as user=admin/password=admin. Under Manage Users, create yourself a test account. Username, Email, First Name and Last Name fields are needed. + +10. Open your browser and go to http://127.0.0.1:8000, you will be greeted with the eDivorce homepage. You can log in with the account you created in step 9. ### SCSS Compilation diff --git a/conf/keycloak/realm-export.json b/conf/keycloak/realm-export.json new file mode 100644 index 00000000..2f9a8c8b --- /dev/null +++ b/conf/keycloak/realm-export.json @@ -0,0 +1,2120 @@ +{ + "id": "justice", + "realm": "justice", + "displayName": "Log in to justice.gov.bc.ca", + "displayNameHtml": "Log in to justice.gov.bc.ca", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": true, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "d42515a2-0ecb-45e0-8dbd-333fa154e026", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "justice", + "attributes": {} + }, + { + "id": "e8e82187-b866-423d-9f41-9d04d1bd7dcb", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "justice", + "attributes": {} + } + ], + "client": { + "edivorce-app": [], + "realm-management": [ + { + "id": "3297cef3-9d80-4fd4-841d-027b6b2902ec", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "7ba7a432-da70-4d14-b4e0-e2847b71a812", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "04130b80-22bc-4308-8b6b-f9ce9253401c", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "f811f862-343b-436b-afea-c35f99209799", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "2ebad1ad-504e-4fc9-9ff8-da7a08f69f84", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "930e6574-909a-476e-9614-38cdee10ef90", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "0cc89e52-25bc-44dd-bf9a-7264d3eb4b64", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "21820548-b725-4d61-aaa0-1d103403cd0c", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "1e4e1885-fff6-410b-b0e4-8036d8a8307e", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "a099906b-df3f-4df2-8dfe-e48033855bdd", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "d7819ce1-54bb-42e4-a4bb-123bcba05cb2", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "fdde9748-ea31-4c4a-878f-97e3e035d2d8", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "dc16c7ee-a93b-47d1-ae06-5de5785f267d", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "6dfd54a1-5f63-4726-92bc-c190f2d472b4", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "view-realm", + "manage-realm", + "query-users", + "create-client", + "manage-users", + "manage-identity-providers", + "view-authorization", + "view-events", + "query-clients", + "query-realms", + "view-users", + "manage-events", + "manage-authorization", + "manage-clients", + "query-groups", + "impersonation", + "view-identity-providers", + "view-clients" + ] + } + }, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "ffa0aff9-5e0f-4b82-9061-e6733f64c392", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "0839264e-dad5-4382-be03-83557a87c85b", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "bf0dbf76-4094-4f56-8d9b-187bd5b72131", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "802396e9-775d-47ab-9b9f-6aa754657b30", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + }, + { + "id": "c363e7d6-0cb2-4235-9a35-49a6dcdc04d7", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "9ad7fb23-6fa5-46db-afdd-fdec62867cad", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "7799f179-a24d-432c-a31b-664e9681bf62", + "attributes": {} + } + ], + "account": [ + { + "id": "f6f8c13c-cbaa-41af-8d10-77a46aaa77c0", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "ca4d1720-f1ed-409e-8285-236a0d71ebeb", + "attributes": {} + }, + { + "id": "802fdcb5-db78-4a0f-8ada-d56845f6cfec", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "ca4d1720-f1ed-409e-8285-236a0d71ebeb", + "attributes": {} + }, + { + "id": "f15e86d5-f731-4c3a-b479-457497526f30", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "ca4d1720-f1ed-409e-8285-236a0d71ebeb", + "attributes": {} + }, + { + "id": "24b428b5-54bf-48b1-a4d5-bdf36638467d", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "ca4d1720-f1ed-409e-8285-236a0d71ebeb", + "attributes": {} + }, + { + "id": "00b13494-54ea-47f4-be72-3b3f58b39131", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "ca4d1720-f1ed-409e-8285-236a0d71ebeb", + "attributes": {} + }, + { + "id": "939f0b50-d636-4adf-8352-dff9681a6235", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "ca4d1720-f1ed-409e-8285-236a0d71ebeb", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRoles": [ + "offline_access", + "uma_authorization" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account" + ] + } + ] + }, + "clients": [ + { + "id": "ca4d1720-f1ed-409e-8285-236a0d71ebeb", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/justice/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": [ + "view-profile", + "manage-account" + ], + "redirectUris": [ + "/realms/justice/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "760d9da4-98d0-4349-b833-542eb8c82f35", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/justice/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/realms/justice/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "f2cd1ffd-33b8-43e9-936e-caf3e2b2a66a", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "1a97d3a6-50ea-4733-a2a2-37e66862f488", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "7799f179-a24d-432c-a31b-664e9681bf62", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "d2c2bdf9-7388-4dad-8704-5fdfb5f91a0d", + "clientId": "edivorce-app", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://localhost:8000/*" + ], + "webOrigins": [ + "*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "08eaad5f-29c6-4630-853f-0b30fb775d4f", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "bcc12062-33ae-481c-895f-2af6da5463c7", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "ae882477-187f-4b4c-97f1-5750f2300221", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "ea9f0d16-2e3d-4afc-9be7-c4ef970609bb", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "4e3480d6-1cfa-4fe7-a059-58a60abf9743", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "17beebbb-40e0-47c1-8656-5a4bfd0ea4d1", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/justice/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/admin/justice/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "e983fe41-5700-47da-b24f-1125aebbd9b4", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "973f869c-af50-4d0e-9ab7-6d9168cf49da", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "c94238dd-6448-4b67-90e6-4107f89ee695", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "83dde3d4-cb98-4144-a059-dc5833506085", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "9bcd3d14-5fd6-48cd-98a8-85f9806e9ebb", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "52acda4c-0c2c-42aa-94d4-8e6bc59588db", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "0cad3a2d-36bd-4cf2-bbd7-39ce784916ad", + "name": "universal-id", + "protocol": "openid-connect", + "protocolMapper": "oidc-script-based-protocol-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "universal-id", + "jsonType.label": "String", + "script": "user.id.toUpperCase().replace(/-/g, '')" + } + } + ] + }, + { + "id": "a5b6580e-70b4-49fe-a42f-c40929aece45", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "4fd752f9-993b-4afb-b876-c2cf05ec3e96", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "f57876b6-240a-4f17-896e-079d3024de25", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "00042da0-4445-4e7c-8daa-310410df9939", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "8b8ed206-97a3-4021-9290-820f3a738dd6", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "96379604-d2d0-4b8c-8666-9a5094e53f59", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "fb5aa145-537e-4c4a-be86-8a18480515c5", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "0e85d328-e16e-4a22-bb18-c815af86861f", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "2da69c95-6fa4-4f6c-a2c1-a18f71a820cf", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "d839e688-29d3-4b60-b568-145b74a05b6c", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "c4a42be8-6e44-4067-8a05-c663f93dca2f", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "194a6ac6-696c-497e-9fe7-8d5ba81e240b", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "4e9311b0-7fc8-46dc-ba7e-c432a4b095a8", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "36314c76-7a68-4939-b94c-83c885b07892", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "b7af3b23-61c6-4816-b933-933121432086", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "7d20caf7-3182-46fc-afff-44f14bf676de", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "f851e830-d162-453f-99d0-186bc531e655", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "8c822393-6fd9-4c8e-83f1-cc4d01ac4719", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "id": "9a7d665c-1538-464f-b86f-2c93a14d4ee0", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "384eee71-6f43-48a7-8cf6-52dab7c5352a", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "26ed5e08-c21f-4909-8a1e-c7c9cedbb560", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "db483c73-f473-42af-a7d4-078f13435282", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "0d479f9f-1368-4ef0-8ca0-d51a175bda34", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "59166be6-e670-4c95-8960-42325e31ce8f", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "e302e0d6-e21f-426f-85d3-78ae60d1ea1e", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "a22297f7-9ca8-4341-9bdd-35f1d0c76513", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + }, + { + "id": "7dea2058-ff6a-4dc3-8b50-d9d583e05ddd", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "c4ddac07-917c-475e-a718-1dd09deae9a7", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "abf9d37c-0bd2-4623-b408-e583e4d83e8e", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "15fc038e-f5ce-4bd1-9787-c6cddb20e347", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "web-origins", + "roles" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "phone", + "address", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "adf3aa4f-9762-4800-81a9-de4ead1d3fe9", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "a361a445-97f8-4c72-a700-7fc7a4f4b281", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-full-name-mapper", + "oidc-usermodel-property-mapper", + "saml-role-list-mapper" + ] + } + }, + { + "id": "9acd9fac-cb13-4d02-aead-cfeae9affed9", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "5b870de7-4c52-43b5-adfc-eac2f04f1fcb", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "91076838-1cb9-4ec0-b0a5-de6e012d61c7", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "75f9efb3-b185-4cea-a2f3-f5a29703f9fb", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "d8964f85-801c-4552-87c4-2ff297cab81f", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "d1f17aef-165c-4c79-a91b-4b7e35942982", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-role-list-mapper", + "oidc-address-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper", + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-user-property-mapper" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "0dc26320-ea9c-42c9-85ad-076704072c5d", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "1ec111ef-f043-4077-811e-347b53bcc0fa", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + }, + { + "id": "b53bf6da-1381-4c41-b6e9-fd23b2cc5429", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "f9d1a1e8-d578-4493-8734-dde0e5f90d5d", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "f5a3d773-13ca-484a-a63b-351ca14f4e8c", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c24c4880-d92f-49a3-8450-32866cf868c0", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "9bb518fc-b8b5-49df-9890-c7eaa0f05e65", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "98a575f2-345f-4c41-8972-b51163f1fa90", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "0252c8d5-b220-40f4-a4f5-5a2daddc0b5f", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Account verification options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "ab03d5e1-fb16-420f-b042-c0427a6c1f9b", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "41e7e9d0-1fc8-4f3e-ab28-9118a3e3bce3", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "25a323b9-b233-4b1e-8462-ba37826a5b71", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "9bfcc2d3-1eab-42fa-a355-6ada66853baa", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "7310f2ed-90d2-4a3c-9106-53c310e7f5b5", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "e8f767f4-d660-4510-849a-e0e63e612e02", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "1793d092-a0c8-4772-82d7-bc6f71330e87", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c580e0b0-7b1c-4bd5-8fd2-c23a031260de", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "User creation or linking", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "b9d0331b-4151-48d6-ae60-13aae5a15654", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "a5fc09de-0457-4ae9-995f-1f39e84243c7", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Authentication Options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "195c4585-8e7d-4292-912f-1ebb4686c61f", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "a03407e8-4ad5-40e1-a422-41abc39ee9b9", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "df000770-fae0-406c-84da-055c3e4e6b12", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "7d9b9761-b638-4314-bf05-68f430b724f9", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "a0d11c9a-c13f-48d1-bd16-a888056db01f", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "5e30f6f6-90bb-46c0-82ab-43f0de780c0d", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": false, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": {}, + "keycloakVersion": "9.0.3", + "userManagedAccessAllowed": false +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index a300546d..22c1b403 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,5 +43,20 @@ services: - "5005:5001" restart: always + # Keycloak + keycloak: + container_name: edivorce-keycloak + image: jboss/keycloak:9.0.3 + environment: + DB_VENDOR: H2 + KEYCLOAK_USER: admin + KEYCLOAK_PASSWORD: admin + KEYCLOAK_IMPORT: /tmp/realm-export.json + volumes: + - ./conf/keycloak/realm-export.json:/tmp/realm-export.json + ports: + - 8081:8080 + command: ["-Dkeycloak.profile.feature.upload_scripts=enabled"] + volumes: data-redis: diff --git a/eDivorce.pyproj b/eDivorce.pyproj deleted file mode 100644 index 5f9e15a7..00000000 --- a/eDivorce.pyproj +++ /dev/null @@ -1,274 +0,0 @@ - - - - Debug - 2.0 - {49af6729-7075-48ab-903a-dd921e4282b5} - - manage.py - - . - . - {5F0BE9CA-D677-4A4D-8806-6076C0FAAD37};{349c5851-65df-11da-9384-00065b846f21};{888888a0-9f3d-457c-b088-3a5042f75d52} - Django launcher - MSBuild|env|$(MSBuildProjectFullPath) - http://localhost - edivorce.settings.local - - - - - 10.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - env - 3.6 - env (Python 3.6 (64-bit)) - Scripts\python.exe - Scripts\pythonw.exe - PYTHONPATH - X64 - - - - - - - - True - True - http://localhost - False - - - - - - - CurrentPage - True - False - False - False - - - - - - - - - False - False - - - - - \ No newline at end of file diff --git a/eDivorce.sln b/eDivorce.sln deleted file mode 100644 index 8d418f8e..00000000 --- a/eDivorce.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2018 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "eDivorce", "eDivorce.pyproj", "{49AF6729-7075-48AB-903A-DD921E4282B5}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {49AF6729-7075-48AB-903A-DD921E4282B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {49AF6729-7075-48AB-903A-DD921E4282B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {49AF6729-7075-48AB-903A-DD921E4282B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {49AF6729-7075-48AB-903A-DD921E4282B5}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {9E16EECB-E9F8-4631-BA0D-4BC734F9D5FA} - EndGlobalSection -EndGlobal diff --git a/edivorce/apps/core/authenticators.py b/edivorce/apps/core/authenticators.py deleted file mode 100644 index 00361cc0..00000000 --- a/edivorce/apps/core/authenticators.py +++ /dev/null @@ -1,22 +0,0 @@ -from rest_framework import authentication - -from edivorce.apps.core.models import BceidUser - - -class BCeIDAuthentication(authentication.BaseAuthentication): - """ - Make the DRF user the BCeID user populated in our middleware, to avoid DRF - overwriting our user for API calls. - - This relies on our middleware entirely for authentication. - """ - - def authenticate(self, request): - try: - request.user = request._user # pylint: disable=protected-access - except: - request.user = request._request.user # pylint: disable=protected-access - return (request.user, None) - - def get_user(self, pk): - return BceidUser.objects.get(pk=pk) \ No newline at end of file diff --git a/edivorce/apps/core/decorators.py b/edivorce/apps/core/decorators.py index 4f98f3ee..035280e2 100644 --- a/edivorce/apps/core/decorators.py +++ b/edivorce/apps/core/decorators.py @@ -9,28 +9,6 @@ from edivorce.apps.core.utils.user_response import get_data_for_user, get_step_r base_url = settings.PROXY_BASE_URL + settings.FORCE_SCRIPT_NAME[:-1] -def bceid_required(function=None): - """ - View decorator to check if the user is logged in to BCEID - - This decorator has a dependency on bceid_middleware.py - """ - - def _dec(view_func): - def _view(request, *args, **kwargs): - if not request.user.is_authenticated: - return redirect(base_url + '/login') - return view_func(request, *args, **kwargs) - - _view.__name__ = view_func.__name__ - _view.__dict__ = view_func.__dict__ - _view.__doc__ = view_func.__doc__ - - return _view - - return _dec if function is None else _dec(function) - - def intercept(function=None): """ Decorator to redirect to intercept page @@ -75,7 +53,7 @@ def prequal_completed(function=None): return redirect(reverse('prequalification', kwargs={'step': step})) return redirect(reverse('prequalification', kwargs={'step': '01'})) else: - return redirect(base_url + '/login') + return redirect('oidc_authentication_init') _view.__name__ = view_func.__name__ _view.__dict__ = view_func.__dict__ diff --git a/edivorce/apps/core/efilinghub.py b/edivorce/apps/core/efilinghub.py index 87f00198..69ce7318 100644 --- a/edivorce/apps/core/efilinghub.py +++ b/edivorce/apps/core/efilinghub.py @@ -159,12 +159,9 @@ class EFilingHub: # unavailable for a local eDivorce environment. Use an env specified mapping # to figure out what we should pass through to eFiling Hub. This BCEID username # needs to match with what you will be logging in with to the Test BCEID environment. - username = request.session.get('login_name', None) - if username: - if username in settings.EFILING_BCEID: - return settings.EFILING_BCEID[username] - return request.session.get('fake_bceid_guid', None) - return request.session.get('smgov_userguid', None) + # return 'ade9f711-d8c5-402e-8f70-5f0a1d4cc181' + return '53993f22-be67-43b9-94f2-222eca1b3bf7' + return request.session.get('bcgov_userguid', None) guid = _get_raw_bceid(request) if guid: diff --git a/edivorce/apps/core/management/commands/link_check.py b/edivorce/apps/core/management/commands/link_check.py new file mode 100644 index 00000000..6d8dcebe --- /dev/null +++ b/edivorce/apps/core/management/commands/link_check.py @@ -0,0 +1,54 @@ +import os +import sys +from urllib.request import urlopen + +from bs4 import BeautifulSoup + +from django.conf import settings +from django.core.management.base import BaseCommand + + +class Command(BaseCommand): + help = 'Checks links in the eDivorce application.' + + def _check_link(self, address): + try: + resp = urlopen(address) + if resp.status in [400, 404, 403, 408, 409, 501, 502, 503]: + return f"{resp.status} - {resp.reason}" + except Exception as e: + return f"{e}" + return None + + def handle(self, *args, **options): + errors = [] + + for root, directory, files in os.walk(settings.BASE_DIR + '/apps/core/templates/'): + for file in files: + if '.html' in file: + file_path = os.path.join(root, file) + + fs = open(file_path) + soup = BeautifulSoup(fs, 'html.parser') + links = soup.find_all('a', href=True) + for link in links: + if link is None: + continue + if link['href'].startswith('http'): + filename = str(file_path.name) + + status = self._check_link(link['href']) + if status: + errors.append({ + 'link': link['href'], + 'error': status, + 'file': filename + }) + + if len(errors) > 0: + for error in errors: + print('-------------------------------------------------------------') + print(f'File: {error["file"]}') + print(f'link: {error["link"]}') + print(f'Error: {error["error"]}\r\n') + sys.exit(1) diff --git a/edivorce/apps/core/middleware/bceid_middleware.py b/edivorce/apps/core/middleware/bceid_middleware.py deleted file mode 100644 index 4aae044c..00000000 --- a/edivorce/apps/core/middleware/bceid_middleware.py +++ /dev/null @@ -1,156 +0,0 @@ -import datetime -from ipaddress import ip_address, ip_network - -from django.conf import settings -from django.shortcuts import redirect -from django.utils import timezone -from django.utils.deprecation import MiddlewareMixin - -from ..models import BceidUser - -login_delta = datetime.timedelta(hours=2) - - -class AnonymousUser: - """ - Anonymous user, present mainly to provide authentication checks in templates - """ - - guid = None - display_name = '' - has_accepted_terms = False - - @property - def is_authenticated(self): - return False - - @property - def is_anonymous(self): - return True - - -anonymous_user = AnonymousUser() - - -class BceidMiddleware(MiddlewareMixin): # pylint: disable=too-few-public-methods - """ - Simple authentication middleware for operating in the BC Government - OpenShift environment, with SiteMinder integration. - - For our purposes, SiteMinder is configured to add the following headers: - - BCeID: - - SMGOV_USERGUID - - SMGOV_USERDISPLAYNAME - - SM_USER - - BC Services Card: - - SMGOV_USERGUID - - SMGOV_GIVENNAMES - - SMGOV_SURNAME - - SM_USER - - The first two are provided on pages configured to be protected by - SiteMinder, which is currently just /login. When a user goes to the login - page, if the user is logged in, SiteMinder adds those headers with their - BCeID values; if they're not logged in, it routes them through its - login/signup page and then back to the login page, with those headers in - place. For unprotected pages, those headers are stripped if present, - preventing spoofing. - - The third header is populated on every request that's proxied through - SiteMinder. For logged in users, it contains their ???; for anonymous - users, it's empty. - - When we detect authentication by the presence of the first two headers, we - store those values in the user's session. On all requests, we use them to - access a local proxy object for the user (available as request.user). For - users that are not logged in, an Anonymous User substitute is present. - - In a local development environment, we generate a guid based on the login - name and treat that guid/login name as guid/display name. - """ - - def process_request(self, request): # pylint: disable=too-many-branches - """ - Return None after populating request.user, or necessary redirects. - - If the request is not coming from inside the BC Government data centre, - redirect the request through the proxy server. - - If the SiteMinder headers are present, indicating the user has just - authenticated, save those headers to the session. - - Get the user's GUID and display name. If they're present, and the user - has authenticated (or we're in a local development environment), add - the local proxy user to the request; if not, store the anonymous user - instance. - """ - - # HTTP_SM_USER is available on both secure and unsecure pages. If it - # has a value then we know that the user is still logged into BCeID. - # This is an additional check to make sure we aren't letting users - # access the site via their session variables after logging out of bceid - # - # Note: It's still possible that a user has logged out of one BCeID and - # logged into another BCeID via www.bceid.ca without clicking the logout - # link on our app or closing the browser. This is an extreme edge case, - # and it's not pragmatic to code against it at this time. - siteminder_user = request.META.get('HTTP_SM_USER', '') - is_localdev = settings.DEPLOYMENT_TYPE in ['localdev', 'minishift'] - update_user = False - using_bc_services_card = False - - guid = request.META.get('HTTP_SMGOV_USERGUID', '') - given_names = request.META.get('HTTP_SMGOV_GIVENNAMES', '') - surname = request.META.get('HTTP_SMGOV_SURNAME', '') - displayname = request.META.get('HTTP_SMGOV_USERDISPLAYNAME', '') - - # HTTP_SMGOV_USERDISPLAYNAME is not included when BC Services Card authentication is used. - if not displayname and (surname or given_names): - displayname = "{0} {1}".format(given_names, surname) - using_bc_services_card = True - - # HTTP_SM_USER is typically '.' when BC Services Card authentication is used. - if (not siteminder_user or siteminder_user == '.') and given_names and surname: - siteminder_user = "{0}{1}".format(given_names.split(None, 1)[0], surname) - - if guid: - request.session['smgov_userguid'] = guid - else: - guid = request.session.get('smgov_userguid') - - if displayname: - request.session['smgov_userdisplayname'] = displayname - else: - displayname = request.session.get('smgov_userdisplayname') - - if is_localdev: - guid = request.session.get('fake_bceid_guid') - displayname = request.session.get('login_name') - - if guid and (siteminder_user or is_localdev): - request.user, created = BceidUser.objects.get_or_create(user_guid=guid) - if created: - request.session['first_login'] = True - if siteminder_user: - if created or not request.user.sm_user: - request.user.sm_user = siteminder_user - update_user = True - if request.user.is_bcsc != using_bc_services_card: - request.user.is_bcsc = using_bc_services_card - update_user = True - if request.user.display_name != displayname: - request.user.display_name = displayname - update_user = True - if (request.user.last_login is None or - timezone.now() - request.user.last_login > login_delta): - request.user.last_login = timezone.now() - update_user = True - - if update_user: - request.user.save() - else: - request.user = anonymous_user - - return None diff --git a/edivorce/apps/core/middleware/keycloak.py b/edivorce/apps/core/middleware/keycloak.py new file mode 100644 index 00000000..b25187ef --- /dev/null +++ b/edivorce/apps/core/middleware/keycloak.py @@ -0,0 +1,52 @@ +from django.conf import settings +from mozilla_django_oidc.auth import OIDCAuthenticationBackend +from mozilla_django_oidc.utils import absolutify + +from ..models import BceidUser + + +class EDivorceKeycloakBackend(OIDCAuthenticationBackend): + + def verify_claims(self, claims): + verified = super(EDivorceKeycloakBackend, self).verify_claims(claims) + print(claims) + + return verified + + def create_user(self, claims): + user = super(EDivorceKeycloakBackend, self).create_user(claims) + + user.first_name = claims.get('given_name', '') + user.last_name = claims.get('family_name', '') + user.display_name = "{} {}".format(user.first_name, user.last_name).strip() + user.sm_user = claims.get('preferred_username', '') + user.user_guid = claims.get('universal-id', '') + user.save() + + self.request.session['bcgov_userguid'] = user.user_guid + + return user + + def update_user(self, user, claims): + user.first_name = claims.get('given_name', '') + user.last_name = claims.get('family_name', '') + user.display_name = "{} {}".format(user.first_name, user.last_name).strip() + user.sm_user = claims.get('preferred_username', '') + user.user_guid = claims.get('universal-id', '') + user.save() + + self.request.session['bcgov_userguid'] = user.user_guid + + return user + + def filter_users_by_claims(self, claims): + user_guid = claims.get('universal-id') + if not user_guid: + return self.UserModel.objects.none() + return self.UserModel.objects.filter(user_guid=user_guid) + + +def keycloak_logout(request): + redirect_uri = absolutify(request, settings.FORCE_SCRIPT_NAME) + + return f'{settings.KEYCLOAK_LOGOUT}?redirect_uri={redirect_uri}' diff --git a/edivorce/apps/core/migrations/0001_initial.py b/edivorce/apps/core/migrations/0001_initial.py index 275da625..2fe26e4d 100644 --- a/edivorce/apps/core/migrations/0001_initial.py +++ b/edivorce/apps/core/migrations/0001_initial.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from django.db import migrations, models from django.conf import settings +import django.utils.timezone class Migration(migrations.Migration): @@ -12,6 +13,15 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='BceidUser', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('user_guid', models.CharField(unique=True, max_length=36, db_index=True)), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now)), + ('last_login', models.DateTimeField(default=django.utils.timezone.now)), + ], + ), migrations.CreateModel( name='FormQuestions', fields=[ diff --git a/edivorce/apps/core/migrations/0007_auto_20170210_1702.py b/edivorce/apps/core/migrations/0007_auto_20170210_1702.py index efb1d8bf..88046996 100644 --- a/edivorce/apps/core/migrations/0007_auto_20170210_1702.py +++ b/edivorce/apps/core/migrations/0007_auto_20170210_1702.py @@ -12,15 +12,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.CreateModel( - name='BceidUser', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('user_guid', models.CharField(unique=True, max_length=36, db_index=True)), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now)), - ('last_login', models.DateTimeField(default=django.utils.timezone.now)), - ], - ), migrations.RemoveField( model_name='profile', name='user', diff --git a/edivorce/apps/core/migrations/0020_bceiduser_is_bcsc.py b/edivorce/apps/core/migrations/0020_bceiduser_is_bcsc.py new file mode 100644 index 00000000..3c4f853b --- /dev/null +++ b/edivorce/apps/core/migrations/0020_bceiduser_is_bcsc.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2020-10-15 17:38 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0019_auto_20191008_2141'), + ] + + operations = [ + migrations.AddField( + model_name='bceiduser', + name='is_bcsc', + field=models.BooleanField(default=False), + ), + ] diff --git a/edivorce/apps/core/migrations/0024_auto_20201009_1235.py b/edivorce/apps/core/migrations/0024_auto_20201009_1235.py new file mode 100644 index 00000000..58042a77 --- /dev/null +++ b/edivorce/apps/core/migrations/0024_auto_20201009_1235.py @@ -0,0 +1,102 @@ +# Generated by Django 2.2.15 on 2020-10-09 21:12 + +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.utils.timezone + + +def set_username(apps, schema_editor): + Series = apps.get_model('core', 'bceiduser') + for series in Series.objects.all().iterator(): + series.username = 'user' + str(series.id) + series.save() + + +def reverse_func(apps, schema_editor): + pass # code for reverting migration, if any + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0023_auto_20201006_1314'), + ('auth', '0011_update_proxy_permissions'), + ] + + operations = [ + migrations.AlterModelOptions( + name='bceiduser', + options={'verbose_name': 'user', 'verbose_name_plural': 'users'}, + ), + migrations.AlterModelManagers( + name='bceiduser', + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.AddField( + model_name='bceiduser', + name='email', + field=models.EmailField(blank=True, max_length=254, verbose_name='email address'), + ), + migrations.AddField( + model_name='bceiduser', + name='first_name', + field=models.CharField(blank=True, max_length=30, verbose_name='first name'), + ), + migrations.AddField( + model_name='bceiduser', + name='groups', + field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'), + ), + migrations.AddField( + model_name='bceiduser', + name='is_superuser', + field=models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status'), + ), + migrations.AddField( + model_name='bceiduser', + name='last_name', + field=models.CharField(blank=True, max_length=150, verbose_name='last name'), + ), + migrations.AddField( + model_name='bceiduser', + name='password', + field=models.CharField(default='', max_length=128, verbose_name='password'), + preserve_default=False, + ), + migrations.AddField( + model_name='bceiduser', + name='user_permissions', + field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'), + ), + migrations.AddField( + model_name='bceiduser', + name='username', + field=models.CharField(blank=True, default='', max_length=150), + preserve_default=False, + ), + migrations.RunPython(set_username, reverse_func), + migrations.AlterField( + model_name='bceiduser', + name='username', + field=models.CharField(default='', error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'), + preserve_default=False, + ), + migrations.AlterField( + model_name='bceiduser', + name='date_joined', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined'), + ), + migrations.AlterField( + model_name='bceiduser', + name='last_login', + field=models.DateTimeField(blank=True, null=True, verbose_name='last login'), + ), + migrations.AddField( + model_name='bceiduser', + name='is_staff', + field=models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status'), + ), + ] diff --git a/edivorce/apps/core/migrations/0025_remove_bceiduser_is_bcsc.py b/edivorce/apps/core/migrations/0025_remove_bceiduser_is_bcsc.py new file mode 100644 index 00000000..ff2305b6 --- /dev/null +++ b/edivorce/apps/core/migrations/0025_remove_bceiduser_is_bcsc.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.15 on 2020-10-19 16:42 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0024_auto_20201009_1235'), + ('core', '0024_bceiduser_is_bcsc'), + ('core', '0020_bceiduser_is_bcsc'), + ] + + operations = [ + migrations.RemoveField( + model_name='bceiduser', + name='is_bcsc', + ), + ] diff --git a/edivorce/apps/core/models.py b/edivorce/apps/core/models.py index 469fe3dc..5d0d642f 100644 --- a/edivorce/apps/core/models.py +++ b/edivorce/apps/core/models.py @@ -6,12 +6,13 @@ from django.db.models import F from django.urls import reverse from django.utils import timezone from django.utils.encoding import python_2_unicode_compatible +from django.contrib.auth.models import AbstractUser from edivorce.apps.core import redis @python_2_unicode_compatible -class BceidUser(models.Model): +class BceidUser(AbstractUser): """ BCeID user table """ @@ -25,21 +26,12 @@ class BceidUser(models.Model): sm_user = models.TextField(blank=True) """ SiteMinder user value """ - date_joined = models.DateTimeField(default=timezone.now) - """ First login timestamp """ - - last_login = models.DateTimeField(default=timezone.now) - """ Most recent login timestamp """ - has_seen_orders_page = models.BooleanField(default=False) """ Flag for intercept page """ has_accepted_terms = models.BooleanField(default=False) """ Flag for accepting terms of service """ - is_bcsc = models.BooleanField(default=False) - """ Flag to identify BC Services Card users """ - @property def is_authenticated(self): return True @@ -48,9 +40,9 @@ class BceidUser(models.Model): def is_anonymous(self): return False - is_staff = True - - is_active = True + @property + def is_active(self): + return True def has_module_perms(self, *args): return True diff --git a/edivorce/apps/core/static/css/main.css b/edivorce/apps/core/static/css/main.css index e3b0ee23..e19fe5ac 100644 --- a/edivorce/apps/core/static/css/main.css +++ b/edivorce/apps/core/static/css/main.css @@ -1,3 +1,3 @@ -@font-face{font-family:'Myriad-Pro';src:url("../fonts/MyriadWebPro.ttf");font-weight:normal;font-style:normal}@font-face{font-family:'Myriad-Pro-Bold';src:url("../fonts/MyriadPro-Bold.otf");font-weight:bold;font-style:normal}body{font-family:Myriad-Pro,Calibri,Arial,Sans Serif;font-size:16px;line-height:24px;color:#313132;background:#036;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;min-width:768px}@media (min-width: 1920px){body{font-size:18px;line-height:1.5}}h1,h2,h3,h4{margin-top:0;margin-bottom:10px}h1 i.fa,h2 i.fa,h3 i.fa,h4 i.fa{font-size:24px;margin-right:6px}h1{font-weight:600;line-height:54px;color:#036;margin-bottom:20px}h1 small{font-size:14px;font-weight:700;text-transform:uppercase;color:#036;display:block;letter-spacing:0.1em}h2{font-weight:600;font-size:24px;line-height:36px;color:#313132;margin-bottom:20px}h3{font-weight:400;font-size:28px;line-height:42px;color:#036;margin-top:15px}h4{font-weight:600;font-size:18px;line-height:27px;color:#036;text-transform:uppercase}a{color:#365ebe;text-decoration:none;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}a:focus,a:hover{color:#2b4a96;text-decoration:underline;outline:none;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.intro{font-size:18px;line-height:28px}img{max-width:100%;height:auto}input.border-less-heading[type='text']{border:none;color:#036}input.border-less-heading[type='text']:focus{box-shadow:none;outline:none}input[type=number]{-moz-appearance:textfield}input.number-spinner[type=number]{-moz-appearance:spinner;text-align:right}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input.number-spinner[type=number]::-webkit-inner-spin-button,input.number-spinner[type=number]::-webkit-outer-spin-button{-moz-appearance:spinner}.table>tbody>tr>td,.list-builder>tbody>tr>td,.table>tbody>tr>th,.list-builder>tbody>tr>th,.table>tfoot>tr>td,.list-builder>tfoot>tr>td,.table>tfoot>tr>th,.list-builder>tfoot>tr>th,.table>thead>tr>td,.list-builder>thead>tr>td,.table>thead>tr>th,.list-builder>thead>tr>th{padding:12px 16px;vertical-align:top}.fact-sheet-question{width:50%}.fact-sheet-answer{width:25%}.fact-sheet-answer[readonly]{color:#8c8c8c;background:#f2f2f2}.fact-sheet-answer input,.fact-sheet-answer textarea{height:25px;width:100%;display:table-cell;border:none;resize:none;padding:2px 2px}.fact-sheet-answer input:focus,.fact-sheet-answer textarea:focus{box-shadow:none;outline:none}.fact-sheet-answer input[readonly],.fact-sheet-answer textarea[readonly]{color:#8c8c8c;background:#f2f2f2}.fact-sheet-answer input{text-align:left}.fact-sheet-control{border-bottom:1px solid #ddd;border-right:1px solid #ddd;border-left:1px solid #ddd;font-size:16px}.fact-sheet-control[readonly]{color:#8c8c8c;background:#f2f2f2}.fact-sheet-control a{color:#494949}.fact-sheet-control a i{color:#494949}.fact-sheet-control a:hover{text-decoration:none}.fact-sheet-control:hover{background:#d4dce5}.fact-sheet-button a{padding-right:6px;color:#494949}.fact-sheet-button a i{color:#494949}.fact-sheet-button a i:hover{color:#385dbc}.fact-sheet-input[readonly]{background:#f2f2f2}.table-cell-active{border:1px solid #66afe9;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.table>tbody>tr>td.list-builder-button,.list-builder>tbody>tr>td.list-builder-button{border:none}.table>thead>tr.list-builder-header>th:last-child,.list-builder>thead>tr.list-builder-header>th:last-child,.table>tbody>tr>td:last-child not:first-child,.list-builder>tbody>tr>td:last-child not:first-child{width:1px;white-space:nowrap}#claimant_children>thead>tr>th:nth-last-child(-n+2),#claimant_children>tbody>tr>td:nth-last-child(-n+2){width:1px;white-space:nowrap}.list-builder{border-collapse:initial;width:100%;table-layout:fixed;margin-bottom:48px}.list-builder-compact{margin-bottom:25px}.list-builder-hide-column{display:none;border:none}.child-item-row{height:50px}.child-item-row:hover td:not(:nth-last-child(-n+2)){background:#d4dce5}.child-support-amount[readonly]{background:#f2f2f2}div.dollar-prefix{position:relative}div.dollar-prefix:before{content:'$ ';top:0;height:100%;padding-left:5px;position:absolute;display:flex;flex-direction:row;align-items:center;justify-content:center}div.dollar-prefix input{text-align:right}div.percent-suffix{border:none;width:100%}div.percent-suffix input{border:none;padding:0px;outline:none;width:85%;text-align:right;display:inline}div.percent-suffix label{width:10%;display:inline;font-weight:normal}.money{text-align:right}.container-wrapper{padding:40px 0}.container-wrapper:nth-child(odd){background:#f2f2f2}.container-wrapper:nth-child(odd) input{background:#ffffff}.bg-danger{position:relative;padding:30px 30px 30px 75px;border-radius:8px;margin-bottom:20px;background-color:#fcf8e3}.bg-danger:after{content:"\f071";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;position:absolute;font-size:24px;color:#f0ad4e;top:30px;left:27px}.bg-danger.add-top-margin{margin-top:20px}.bg-danger.hard-stop{background-color:#faebe9}.bg-danger.hard-stop:after{content:"\f05e";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;position:absolute;font-size:24px;color:#d9534f;top:30px;left:27px}.bg-danger h2{line-height:initial;margin-bottom:10px}.bg-danger p+h2{margin-top:20px}.bg-danger #unselected_spouse_alert{margin-bottom:20px}.checkmark{background:#2e8540;position:relative;padding:22px 20px 20px 90px;color:#ffffff;border-radius:8px;font-size:32px}.checkmark:before{content:"\f00c";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;position:absolute;top:0;bottom:0;margin-top:auto;margin-bottom:auto;left:24px;font-size:42px;color:#ffffff;height:60px}@media (max-width: 991px){.container{width:100%;min-width:750px}}.tooltip.in{opacity:1}.tooltip-inner{text-align:left;background-color:#365ebe;padding:20px;font-size:16px;line-height:24px;max-width:300px;border-radius:10px;font-family:Myriad-Pro,Calibri,Arial,Sans Serif}.tooltip-innerb{font-size:18px}.tooltip-inner a{color:#ffffff;text-decoration:underline}.tooltip-inner a:focus,.tooltip-inner a:hover{color:#d5d5d5}.tooltip-arrow{pointer-events:none;border-color:rgba(255,255,255,0);border-width:12px !important}.tooltip.top .tooltip-arrow{border-top-color:#365ebe;margin-bottom:-16px}.tooltip.right{margin-left:10px}.tooltip.right .tooltip-arrow{border-right-color:#365ebe;margin-left:-12px;margin-top:-14px}.tooltip.bottom .tooltip-arrow{border-bottom-color:#365ebe;margin-top:-12px}.tooltip.left{margin-left:-10px}.tooltip.left .tooltip-arrow{border-left-color:#365ebe;margin-right:-12px;margin-top:-14px}.tooltip-link,.tooltip-no-link{color:#365ebe;border-bottom:dotted 1px #365ebe;cursor:pointer}.tooltip-link:hover,.tooltip-no-link:hover{color:#036;border-bottom-color:#365ebe}.tooltip-no-link{border-bottom:none}.collapse-trigger{margin-bottom:12px}.collapse-trigger>div{color:#365ebe;border-bottom:solid 1px #365ebe;display:inline;cursor:pointer}.collapse-trigger>div .tooltip-link,.collapse-trigger>div .tooltip-no-link{border:0}.collapse-trigger>div .tooltip-link:hover,.collapse-trigger>div .tooltip-no-link:hover{color:inherit}.collapse-trigger>div:after{font-family:FontAwesome;font-weight:normal;font-style:normal;display:inline-block;text-decoration:inherit;padding-left:10px;content:"\f077";-webkit-transform-origin:65% 50%;transform-origin:65% 50%;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.collapse-trigger>div:focus,.collapse-trigger>div:hover{color:#2b4a96;border-bottom:solid 1px #2b4a96;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.collapse-trigger.collapsed div:after{-webkit-transform:rotate(-180deg);transform:rotate(-180deg);-webkit-transform-style:preserve-3D;transform-style:preserve-3D;-webkit-transform-origin:65% 50%;transform-origin:65% 50%}.collapse>div,.collapsing>div{margin-bottom:25px}select.form-control{font-size:16px;height:42px}.form-group input.form-control,.input-group input.form-control:first-child{margin-top:12px;border-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;height:inherit;width:inherit;float:inherit;font-size:inherit;padding:12px 15px;line-height:1em;display:inline}.form-group input.form-control.input-wide,.input-group input.form-control.input-wide:first-child{width:70%}.alias-header{width:100%}@media (min-width: 992px){.form-group.name-group{display:flex !important;flex-direction:row;justify-content:space-between;margin-top:20px;margin-bottom:8px}}.form-group.name-group>div{width:80%}@media (min-width: 992px){.form-group.name-group>div{width:24%}}.form-group.name-group>div input{width:99%}.form-group.name-group p{margin-bottom:3px}@media (min-width: 992px){div#other_names_fields .form-inline .form-group{flex:inherit}}div#other_names_fields .form-inline label{width:calc(100% - 90px);text-align:left}.btn{line-height:initial;padding:12px 15px}.btn-primary{background:#365ebe}.btn-primary:hover{background-color:#1f376f}i.fa{color:#365ebe}i.fa.circle{border-radius:50%;padding:10px;border:solid 1px #365ebe}i.fa.fa-question-circle{margin-left:5px}.form-buttons{margin:30px 0}.form-buttons .btn{font-size:18px;border:none;border-radius:10px;padding:12px 15px;background-color:#365ebe;color:#ffffff;margin-bottom:12px;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.form-buttons .btn:hover{background-color:#1f376f;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.form-buttons .btn i.fa{color:#ffffff}.form-buttons .btn.btn-success{background-color:#57b26a;margin-left:12px;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.form-buttons .btn.btn-success:hover{background-color:#337040;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.form-buttons .btn[disabled]{pointer-events:none;cursor:default}.review-warning{background-color:#F7D4D5;border-radius:8px;position:relative;padding:30px 30px 30px 75px;margin-bottom:20px}.review-warning ul{padding-left:15px}.review-warning:after{content:"\f06a";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;position:absolute;font-size:24px;color:#AC2025;top:30px;left:27px}.review-warning .warning,.review-warning .progress-status i{color:#AC2025;font-weight:bolder;margin:0 3px}.error{border:2px solid #D8292F !important;-webkit-transition:0.1s ease-in-out all;transition:0.1s ease-in-out all}.error .warning,.error .help-block{color:#D8292F;font-size:16px;font-weight:bolder}.error-text{color:#D8292F}.table-error{border:2px solid #D8292F !important;-webkit-transition:0.1s ease-in-out all;transition:0.1s ease-in-out all;margin:-12px -16px;padding:12px 16px}.table-error .warning{color:#D8292F;font-size:14px;font-weight:bolder;display:inline-block;width:100%;text-align:center}.btn-radio{color:#036;background-color:#d7dff2;font-size:16px;text-transform:uppercase;letter-spacing:0.08em;font-weight:600;padding:20px 0;width:60px;height:60px;border-radius:30px;border:3px solid #d7dff2;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.btn-radio.active,.btn-radio:active,.btn-radio:focus,.btn-radio:hover,.open .dropdown-toggle.btn-radio{color:#FFFFFF;background-color:#365ebe;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.btn-radio.active,.btn-radio:active,.open .dropdown-toggle.btn-radio{background-image:none}.btn-radio.disabled,.btn-radio.disabled.active,.btn-radio.disabled:active,.btn-radio.disabled:focus,.btn-radio.disabled:hover,.btn-radio[disabled],.btn-radio.active[disabled],.btn-radio[disabled]:active,.btn-radio[disabled]:focus,.btn-radio[disabled]:hover,fieldset[disabled] .btn-radio,fieldset[disabled] .btn-radio.active,fieldset[disabled] .btn-radio:active,fieldset[disabled] .btn-radio:focus,fieldset[disabled] .btn-radio:hover{background-color:#365ebe;border-color:#365ebe;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.btn-radio+.btn-radio{margin-left:15px}.btn-radio-group{margin-bottom:20px}.btn-radio-group .btn.active.focus,.btn-radio-group .btn.active:focus,.btn-radio-group .btn.focus,.btn-radio-group .btn.focus:active,.btn-radio-group .btn:active:focus,.btn-radio-group .btn:focus{outline:none}.btn-radio-group .btn-radio-long{width:auto;white-space:normal;text-transform:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1em;max-width:500px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;text-align:left;padding:0 20px}input{border-radius:4px;color:#494949;padding:12px 15px;border:solid 1px #d5d5d5;line-height:1em}input:focus{outline:0;box-shadow:inset 0 1px 1px rgba(49,49,50,0.075),0 0 4px rgba(157,157,157,0.5)}input+i.fa{margin-left:10px}input.form-block{display:block;margin-bottom:16px}input.input-wide{width:70%}input.input-narrow{max-width:100px}input.input-inline{padding:5px 20px;border-radius:5px;margin-left:5px}input.radio-centered{margin-top:15px}.checkbox label,.radio label{margin-bottom:8px;font-weight:700}.checkbox label.tight-spacing,.radio label.tight-spacing{margin-bottom:2px}.radio p,.checkbox p{margin-bottom:8px;margin-left:21px}.radio .radio-with-textbox{display:flex;align-items:baseline;margin-bottom:16px}.radio .radio-with-textbox input.form-block{margin-bottom:0;margin-right:8px}textarea{width:100%;border-radius:10px;color:#494949;padding:12px 15px;border:solid 1px #d5d5d5;line-height:24px;resize:none}#top_banner{background-color:#036;border-bottom:2px solid #fcba19;padding:5px 20px 10px}#top_banner .top_banner-logo img{width:148px;height:auto;float:left}#top_banner p{color:#ffffff;font-size:16px;line-height:1em;margin-top:20px;margin-left:35px;float:left}#top_banner p .beta{border:solid 1px #ffffff;padding:4px 8px 3px;margin-left:10px;font-size:12px;text-transform:uppercase}#top_banner p .beta.environment-type{background-color:#B200FF}#top_banner .top_banner-user{color:#fff;font-size:14px;float:right;margin-top:16px}#top_banner .top_banner-user a{color:#ffffff}#top_banner .top_banner-user a:active,#top_banner .top_banner-user a:hover{color:#fcfcfc}#mid_banner{background-color:#38598A;font-size:14px;font-weight:600}#mid_banner .mid_banner-dash{float:left;margin-left:-20px}#mid_banner .mid_banner-dash a,#mid_banner .mid_banner-link a,#mid_banner .more_information-link a{padding:10px 16px;float:right;margin-left:6px}#mid_banner .mid_banner-dash a.active,#mid_banner .mid_banner-dash a:hover,#mid_banner .mid_banner-link a.active,#mid_banner .mid_banner-link a:hover,#mid_banner .more_information-link a.active,#mid_banner .more_information-link a:hover{color:#fff;background-color:#fcba19;text-decoration:none}#mid_banner .mid_banner-dash a.active i,#mid_banner .mid_banner-dash a:hover i,#mid_banner .mid_banner-link a.active i,#mid_banner .mid_banner-link a:hover i,#mid_banner .more_information-link a.active i,#mid_banner .more_information-link a:hover i{color:#fff}#mid_banner .mid_banner-dash a{margin-left:24px}#mid_banner i{color:#ffffff;padding:0 10px 0 0}#mid_banner a{color:#ffffff;text-decoration:none}#form_navigation{display:-webkit-box;display:-ms-flexbox;display:flex}#form_navigation form{margin-right:10px}.success-buttons{text-align:center;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-line-pack:justify;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.success-buttons .flex-row{width:45%;border-radius:8px;background-color:#d7dff2;border:1px solid #365ebe;display:flex;flex-direction:column;justify-content:space-between;padding:24px 30px}#other_names_fields .form-inline,#reconciliation_period_fields .form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:10px;padding:10px;background:#efefef;border-radius:5px}#other_names_fields .form-inline .form-group,#reconciliation_period_fields .form-inline .form-group{display:block;width:100%;margin-bottom:5px}@media (min-width: 992px){#other_names_fields .form-inline .form-group,#reconciliation_period_fields .form-inline .form-group{-webkit-box-flex:1;-ms-flex:1;flex:1}}#other_names_fields .form-inline .form-control,#reconciliation_period_fields .form-inline .form-control{display:inline-block;width:auto;vertical-align:middle;height:34px;margin-top:0;padding:8px 15px}#other_names_fields .form-inline label,#reconciliation_period_fields .form-inline label{min-width:45px;margin-right:10px;text-align:right}#other_names_fields .form-inline:before,#reconciliation_period_fields .form-inline:before{display:table;content:" "}#other_names_fields .form-inline select.response-dropdown,#reconciliation_period_fields .form-inline select.response-dropdown{margin-right:5px;-webkit-box-flex:0;-ms-flex:0 0 180px;flex:0 0 180px}@media (min-width: 1px) and (max-width: 1199px){#other_names_fields .form-inline select.response-dropdown,#reconciliation_period_fields .form-inline select.response-dropdown{margin-bottom:5px;-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%}}#other_names_fields .form-inline input.response-textbox,#reconciliation_period_fields .form-inline input.response-textbox{margin-right:5px;-webkit-box-flex:1;-ms-flex:1;flex:1;width:99%}#other_names_fields .form-inline input.btn,#reconciliation_period_fields .form-inline input.btn{padding:8px 15px}@media (min-width: 992px){#other_names_fields .form-inline input.btn,#reconciliation_period_fields .form-inline input.btn{-webkit-box-flex:0;-ms-flex:0 0 70px;flex:0 0 70px}}.footer{background-color:#036;border-top:3px solid #fcba19;padding:15px}.footer .footer-container ul{list-style-type:none}.footer .footer-container ul li{float:left;padding:2px 10px;position:relative}.footer .footer-container ul li a{display:block;text-align:center;color:#ffffff;font-size:13px;font-weight:600}.footer .footer-container ul li+li{border-left:1px solid #4b5e73}.question-well{min-height:20px;padding:25px;margin-top:25px;border:1px solid #d5d5d5;border-radius:10px;background:#ffffff}.question-well.hasFocus{border:1px solid #365ebe;-webkit-transition:0.1s ease-in-out all;transition:0.1s ease-in-out all}.question-well h3{margin-top:0}.question-well p{max-width:90%;margin-bottom:20px}.question-well .fact-sheet-table-inline-question{margin-bottom:48px}.question-well .required,.question-well .optional{font-size:14px;font-family:Myriad-Pro-Bold,Calibri,Arial,Sans Serif;font-weight:bold;text-transform:uppercase;padding:4px 6px;margin-left:16px;white-space:nowrap}.question-well .required.inline,.question-well .optional.inline{border:none;padding:0}.question-well .required{color:#D8292F;border:#D8292F 2px solid}.question-well .optional{color:#036;border:#036 1px solid}.question-well-border-less{min-height:20px;padding:25px 25px 0 0;margin-top:25px;background:#ffffff}.question-well-border-less h3{margin-top:20px}.question-well-border-less p{max-width:90%}.review-well{border-radius:10px;min-height:20px;margin-bottom:10px;border:1px solid #d5d5d5;background:#ffffff}.review-well .review-well{margin:0 40px 5px}.review-well .collapse-trigger{padding:20px 15px}.review-well .collapse,.review-well .collapsing{border-top:1px solid #d5d5d5;padding:24px 47px}.review-well .collapse>div,.review-well .collapsing>div{margin-bottom:0}.review-well .review-buttons{float:left;padding:0 15px 20px;margin:0 0 0 32px}@media (min-width: 991px){.review-well .review-buttons{float:right;padding:10px 15px;margin:0}}.review-well .review-buttons .fa{color:white;margin-right:6px}.review-well .collapse-trigger{margin-bottom:0;display:inline-block;width:100%}@media (min-width: 991px){.review-well .collapse-trigger{width:initial}}.review-well .collapse-trigger>div{border-bottom:none;font-size:18px;font-weight:600;padding-left:8px;position:relative}.review-well .collapse-trigger>div:before{font-family:FontAwesome;font-weight:normal;font-style:normal;position:absolute;text-decoration:inherit;left:0;content:"\f077";-webkit-transform-origin:50%;transform-origin:50%;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.review-well .collapse-trigger>div span{display:inline-block;margin-left:24px}.review-well .collapse-trigger>div:after{display:none}.review-well .collapse-trigger.empty{display:block;border-top:1px solid #d5d5d5}.review-well .collapse-trigger.empty div:before{display:none}.review-well .collapse-trigger.collapsed div:before{-webkit-transform:rotate(-180deg);transform:rotate(-180deg);-webkit-transform-style:preserve-3D;transform-style:preserve-3D;-webkit-transform-origin:50%;transform-origin:50%}.review-well .collapse.empty{display:inline-block;border-top:none}.review-well-no-icon{padding-left:47px}.review-well-child{display:inline-block;width:100%}.review-well-child .review-buttons{margin:0;padding-left:8px}@media (min-width: 991px){.review-well-child .review-buttons{margin:initial;padding-left:initial}}.review-well-child .collapse-trigger{padding-left:0}.review-well-child .collapse-trigger>div{color:#313132;font-weight:normal}.review-child-heading{background-color:#D4DCE5}.review-table-spacer::before{content:'';display:block;height:25px}.print-form-action{display:inline-block;float:right}.print-form-action a{text-decoration:none}.print-form-action:after{display:none}.step-review .collapse-trigger{font-size:24px;display:inline-block}.step-review .collapse-trigger.collapsed{margin-bottom:0;-webkit-transition:0.5s ease-out all;transition:0.5s ease-out all}.step-review table{margin-bottom:0}.step-review table thead tr{background-color:#036;color:#fff}.step-review table .value-column{width:30%;min-width:192px}.step-review .collapse>div,.step-review .collapsing>div{margin-bottom:0}.step-review .review-buttons{float:right}.signing-filing .question-well{margin-top:15px;margin-bottom:30px;padding-bottom:0}.signing-filing .question-well h3{font-size:24px}.signing-filing .form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;align-items:center;margin-bottom:10px;padding:10px;background:#efefef;border-radius:5px}.signing-filing .form-inline label{margin:0 15px 0 5px;text-align:right}.signing-filing .form-inline:before{display:table;content:" "}.signing-filing .form-inline input{margin-right:5px;-webkit-box-flex:1;-ms-flex:1;flex:1;width:99%;min-width:200px}.dashboard-content p{margin-bottom:15px}.dashboard-content ul{margin-bottom:30px}.dashboard-content .no-margin-bottom{margin-bottom:0 !important}.dashboard-content .add-top-margin{margin-top:30px}.dashboard-content .no-bullets{padding-left:0}.dashboard-content .no-bullets li{list-style:none}.dashboard-content .upload-area{padding:32px 20px 32px 20px;margin-bottom:50px;background-color:#f2f2f2;border:1px solid #9D9D9D;border-radius:8px}.row-flex{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;height:100%;overflow:hidden;background:#fdfdfd;position:relative}.row-flex .col{-webkit-box-flex:1;-ms-flex:1;flex:1;box-sizing:border-box;-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.row-flex .col.shroud:before{content:"";position:absolute;width:100%;display:block;height:100%;background:linear-gradient(to top, rgba(0,0,0,0.35) 0%, transparent 90%)}.row-flex .content-column{max-width:1280px;padding:36px 6% 50px;position:relative}.row-flex .progress-column{-webkit-box-flex:0;-ms-flex:0 0 280px;flex:0 0 280px;background-color:#efefef;-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.row-flex .dashnav-column{-webkit-box-flex:0;-ms-flex:0 0 290px;flex:0 0 289px;background-color:#036;-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.row-flex .more_information-column{background-color:#efefef;box-shadow:inset 0 0 10px 0 rgba(0,0,0,0.1);padding:20px 45px;font-size:14px;line-height:21px;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1;height:auto}@media (min-width: 1920px){.row-flex .more_information-column{font-size:16px;line-height:1.5}}.row-flex .more_information-column .more_information-close{float:right;font-size:24px;margin-top:3px}.row-flex .more_information-column .more_information-close i.fa{color:#036}.row-flex .more_information-column h2{color:#036;padding-right:25px}.row-flex .more_information-column h3{font-size:21px;line-height:28px}@media (min-width: 992px){.row-flex .more_information-column{padding:45px 20px;-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4;-webkit-box-flex:0;-ms-flex:0 0 306px;flex:0 0 306px}}.row-flex.intro-page{background:#38598A url("../img/bg-edivorce__landing.jpg") no-repeat top center fixed;background-size:cover}.row-flex.intro-page .content-column{margin:54px auto 100px;max-width:840px;padding:0 20px;text-align:center;color:#ffffff;position:relative}.row-flex.intro-page .content-column h1{color:#036;max-width:600px;margin:70px auto;font-size:48px}.row-flex.intro-page .content-column h2,.row-flex.intro-page .content-column h3{color:#ffffff}.row-flex.intro-page .content-column h2{font-size:30px;font-weight:600;margin:42px 0 0}.row-flex.intro-page .content-column h2.shaded-box{padding-top:28px;border-top-left-radius:8px;border-top-right-radius:8px}.row-flex.intro-page .content-column .intro{font-size:24px;line-height:36px;margin:0 100px}.row-flex.intro-page .content-column a{color:#ffffff;text-decoration:none}.row-flex.intro-page .content-column a:focus,.row-flex.intro-page .content-column a:hover{text-decoration:underline}.row-flex.intro-page .content-column a.btn:focus,.row-flex.intro-page .content-column a.btn:hover{text-decoration:none}.row-flex.intro-page .content-column .btn-group-lg>.btn,.row-flex.intro-page .content-column .btn-lg{padding:12px 40px;margin:10px}.row-flex.intro-page .content-column .flex-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;margin:20px 0;text-align:left;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:18px}.row-flex.intro-page .content-column .flex-wrapper .flex-column{width:45%}.row-flex.intro-page .content-column .flex-wrapper.shaded-box{padding-top:22px;padding-bottom:50px;margin-top:0;border-bottom-left-radius:8px;border-bottom-right-radius:8px}.row-flex.intro-page .content-column .flex-wrapper.shaded-box .flex-column.left{padding-left:30px}.row-flex.intro-page .content-column .flex-wrapper.shaded-box .flex-column.right{padding-right:30px}.row-flex.intro-page .content-column .flex-wrapper span.number-circle{border:solid 2px white;padding:0;border-radius:40px;width:40px;height:40px;display:inline-block;text-align:center;margin-right:10px;font-size:21px}.intro-footer{text-align:center;padding-bottom:92px;background:#ffffff}.intro-footer .column{max-width:640px;margin:0 auto}.intro-footer h3{color:#036;font-size:24px;line-height:36px;padding-top:60px;padding-bottom:35px;margin:0}.intro-footer .btn{width:260px;height:48px;font-weight:bold;line-height:24px;border-radius:8px}.dashnav-column h4,.overview-progress h4,.progress-column h4{color:#036;padding:0 18px;margin-top:36px;font-size:14px;letter-spacing:0.1em}.dashnav-column .progress-question,.overview-progress .progress-question,.progress-column .progress-question{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:70px;margin-bottom:12px;padding:0 24px;font-weight:bold}.dashnav-column .progress-question .progress-icon,.overview-progress .progress-question .progress-icon,.progress-column .progress-question .progress-icon{-webkit-box-flex:0;-ms-flex:0 0 46px;flex:0 0 50px}.dashnav-column .progress-question .progress-icon i,.overview-progress .progress-question .progress-icon i,.progress-column .progress-question .progress-icon i{font-size:20px;border:solid 1px #036;padding:8px;border-radius:36px}.dashnav-column .progress-question .progress-icon i.fa:before,.overview-progress .progress-question .progress-icon i.fa:before,.progress-column .progress-question .progress-icon i.fa:before{width:20px;text-align:center;display:block;height:20px}.dashnav-column .progress-question .progress-content,.overview-progress .progress-question .progress-content,.progress-column .progress-question .progress-content{width:190px;font-size:14px;line-height:1.3}@media (min-width: 1920px){.dashnav-column .progress-question .progress-content,.overview-progress .progress-question .progress-content,.progress-column .progress-question .progress-content{font-size:16px;width:190px}}.dashnav-column .progress-question .progress-content small,.overview-progress .progress-question .progress-content small,.progress-column .progress-question .progress-content small{font-size:11px;text-transform:uppercase;font-weight:bolder;letter-spacing:0.1em}.dashnav-column .progress-question i,.dashnav-column .progress-question span,.overview-progress .progress-question i,.overview-progress .progress-question span,.progress-column .progress-question i,.progress-column .progress-question span{color:#036;border-color:#036}.dashnav-column .progress-question.complete i,.dashnav-column .progress-question.complete span,.overview-progress .progress-question.complete i,.overview-progress .progress-question.complete span,.progress-column .progress-question.complete i,.progress-column .progress-question.complete span{color:#2e8540;border-color:#2e8540}.dashnav-column .progress-question:focus,.dashnav-column .progress-question:hover,.overview-progress .progress-question:focus,.overview-progress .progress-question:hover,.progress-column .progress-question:focus,.progress-column .progress-question:hover{background-color:#e6ca85;text-decoration:none}.dashnav-column .progress-question.active,.overview-progress .progress-question.active,.progress-column .progress-question.active{background-color:#fcba19;text-decoration:none}.dashnav-column .progress-status,.overview-progress .progress-status,.progress-column .progress-status{width:28px;text-align:right}.dashnav-column .progress-status i,.overview-progress .progress-status i,.progress-column .progress-status i{float:right}.dashnav-column .progress-status i.incomplete,.dashnav-column .progress-status i.skipped,.overview-progress .progress-status i.incomplete,.overview-progress .progress-status i.skipped,.progress-column .progress-status i.incomplete,.progress-column .progress-status i.skipped{color:#AC2025}.dashnav-column .progress-status i.complete,.overview-progress .progress-status i.complete,.progress-column .progress-status i.complete{color:#2e8540}.dashnav-column .progress-sub-menu,.overview-progress .progress-sub-menu,.progress-column .progress-sub-menu{list-style-type:none}.dashnav-column .progress-sub-menu li,.overview-progress .progress-sub-menu li,.progress-column .progress-sub-menu li{display:inline-block;padding:5px 24px 5px 22px;border-left:2px solid #fcba19;width:100%}.dashnav-column .progress-sub-menu .progress-sub-question,.overview-progress .progress-sub-menu .progress-sub-question,.progress-column .progress-sub-menu .progress-sub-question{width:190px;font-size:14px;line-height:1.3;color:#036}@media (min-width: 1920px){.dashnav-column .progress-sub-menu .progress-sub-question,.overview-progress .progress-sub-menu .progress-sub-question,.progress-column .progress-sub-menu .progress-sub-question{font-size:16px;width:190px}}.dashnav-column .progress-sub-menu .progress-sub-question .progress-content,.overview-progress .progress-sub-menu .progress-sub-question .progress-content,.progress-column .progress-sub-menu .progress-sub-question .progress-content{width:190px;font-size:14px;font-weight:bold;line-height:1.3}@media (min-width: 1920px){.dashnav-column .progress-sub-menu .progress-sub-question .progress-content,.overview-progress .progress-sub-menu .progress-sub-question .progress-content,.progress-column .progress-sub-menu .progress-sub-question .progress-content{font-size:16px;width:190px}}.dashnav-column .progress-sub-menu .progress-sub-question:focus,.dashnav-column .progress-sub-menu .progress-sub-question:hover,.overview-progress .progress-sub-menu .progress-sub-question:focus,.overview-progress .progress-sub-menu .progress-sub-question:hover,.progress-column .progress-sub-menu .progress-sub-question:focus,.progress-column .progress-sub-menu .progress-sub-question:hover{color:#fcba19;text-decoration:none;font-weight:700}.dashnav-column .progress-sub-menu .progress-sub-question.active:focus,.dashnav-column .progress-sub-menu .progress-sub-question.active:hover,.overview-progress .progress-sub-menu .progress-sub-question.active:focus,.overview-progress .progress-sub-menu .progress-sub-question.active:hover,.progress-column .progress-sub-menu .progress-sub-question.active:focus,.progress-column .progress-sub-menu .progress-sub-question.active:hover{border-bottom:1px solid #fcba19}.dashnav-column .progress-sub-menu .progress-sub-question.active,.overview-progress .progress-sub-menu .progress-sub-question.active,.progress-column .progress-sub-menu .progress-sub-question.active{text-decoration:none;padding-bottom:4px;border-bottom:1px solid #036;font-weight:700}.dashnav-column .progress-question{height:60px}.overview-progress{border:solid 1px #d5d5d5;border-radius:10px;background:#ffffff}.overview-progress .progress-question{margin-bottom:0;border-bottom:solid 1px #d5d5d5}.overview-progress .progress-question:last-of-type{border-bottom:none}.overview-progress .progress-question .progress-icon{-webkit-box-flex:0;-ms-flex:0 0 52px;flex:0 0 52px}.overview-progress .progress-question .progress-content{font-size:16px;font-weight:600;-webkit-box-flex:2;-ms-flex:2;flex:2}.overview-progress .progress-question .progress-status{font-size:14px;font-weight:600;-webkit-box-flex:1;-ms-flex:1;flex:1}.overview-progress .progress-question .progress-status i{font-size:20px;float:none;margin-left:16px;vertical-align:middle}.overview-progress .progress-question.complete{background-color:#d5e6d8}.overview-progress .progress-question:focus,.overview-progress .progress-question:hover{background-color:#d7dff2;text-decoration:none}.overview-progress .progress-question:first-child{border-top-left-radius:9px;border-top-right-radius:9px}.overview-progress .progress-question:last-child{border-bottom-left-radius:9px;border-bottom-right-radius:9px}.overview-progress .progress-question a{transition:0.1s background ease-in-out;-webkit-transition:0.1s background ease-in-out}.dashnav-column h4{color:#ffffff}.dashnav-column .progress-question .progress-icon{-webkit-box-flex:0;-ms-flex:0 0 36px;flex:0 0 36px}.dashnav-column .progress-question .progress-icon i{font-size:20px;border:none;padding:0}.dashnav-column .progress-question .progress-content{width:180px;color:#ffffff;font-weight:600}.dashnav-column .progress-question i{color:#ffffff}.dashnav-column .progress-question.active i,.dashnav-column .progress-question.active .progress-content{color:#036}.dashnav-column .progress-question:focus,.dashnav-column .progress-question:hover{background-color:#fcba19}.progress-column .progress-question.active:not(.complete) .progress-icon i{border:solid 1px #036;background-color:#036;color:#fcba19}.progress-column .progress-question.active.complete .progress-icon i{border:solid 1px #2e8540;background-color:#2e8540;color:#fcba19}.has-warning-box{border:3px solid #D8292F;padding-top:8px;padding-left:8px}.has-warning-box #terms_warning{color:#D8292F}.list-item-description{padding-left:20px;margin-bottom:25px;margin-top:-10px}.modal-dialog{width:780px}.modal-header{border:0;padding-bottom:0;padding-top:24px}.modal-title{font-size:32px;font-weight:normal}.modal-body{padding:0 64px 36px}.modal-body p{font-size:18px;margin-top:12px}.modal-footer{background:#f2f2f2;border-bottom-left-radius:10px;border-bottom-right-radius:10px}.footnote-marker{font-size:18px;top:-10px;position:relative;display:inline-block;left:1px;margin-right:1px}.footnote{margin-top:40px;margin-bottom:52px;font-size:16px}.footnote h5{font-size:30px;margin-bottom:20px}.footnote.shaded-box{border-radius:8px;padding:25px 80px 25px 80px}.shaded-box{background-color:rgba(0,0,0,0.7)}.light-shaded-box{background-color:#f2f2f2;border-radius:8px;padding:18px 30px;margin-bottom:28px}.light-shaded-box p{margin:0;max-width:100%}#delete_child_modal,#info_modal,#questions_modal,#terms_modal{margin-top:112px;font-size:18px}#delete_child_modal .modal-header,#info_modal .modal-header,#questions_modal .modal-header,#terms_modal .modal-header{text-align:center}#delete_child_modal .modal-header i,#info_modal .modal-header i,#questions_modal .modal-header i,#terms_modal .modal-header i{background-color:#365ebe;color:#ffffff;height:80px;width:80px;border-radius:40px;font-size:40px;padding:20px;margin-bottom:15px}#delete_child_modal .modal-body,#info_modal .modal-body,#questions_modal .modal-body,#terms_modal .modal-body{padding:36px 64px}#delete_child_modal .modal-body p,#info_modal .modal-body p,#questions_modal .modal-body p,#terms_modal .modal-body p{font-size:18px;margin-top:12px}#delete_child_modal .modal-footer,#info_modal .modal-footer,#questions_modal .modal-footer,#terms_modal .modal-footer{text-align:center;border:none;padding-bottom:18px}#delete_child_modal{text-align:center;vertical-align:middle;margin-top:112px;font-size:18px}#delete_child_modal .modal-footer{text-align:center;border:none;padding-bottom:18px}div#progress-overlay{position:fixed;top:0;bottom:0;left:0;right:0;z-index:10000;background:rgba(0,0,0,0.35)}div#progress-overlay-spinner{position:fixed;top:0;bottom:0;left:0;right:0;z-index:5000}span.hard-stop{font-size:2.8em;display:inline-block;float:left;margin:3px 10px 0 0}.date-picker-group .input-group-addon{display:inline-block;background-color:inherit;border:none}@media (min-width: 1px) and (max-width: 991px){.on-canvas{display:block}}@media (min-width: 992px){.on-canvas{-webkit-transition:0.2s ease-out all;transition:0.2s ease-out all;-webkit-transform:translateX(0);transform:translateX(0)}}@media (min-width: 1px) and (max-width: 991px){.off-canvas{display:none}}@media (min-width: 992px){.off-canvas{-webkit-transition:0.2s ease-out all;transition:0.2s ease-out all;-webkit-transform:translateX(306px);transform:translateX(306px)}}@media (min-width: 1px) and (max-width: 991px){.margin-right{margin-right:0}}@media (min-width: 992px){.margin-right{-webkit-transition:0.2s ease-out all;transition:0.2s ease-out all;margin-right:-306px}}@media (min-width: 1px) and (max-width: 991px){.no-margin-right{margin-right:0}}@media (min-width: 992px){.no-margin-right{-webkit-transition:0.2s ease-out all;transition:0.2s ease-out all;margin-right:0}} +@font-face{font-family:'Myriad-Pro';src:url("../fonts/MyriadWebPro.ttf");font-weight:normal;font-style:normal}@font-face{font-family:'Myriad-Pro-Bold';src:url("../fonts/MyriadPro-Bold.otf");font-weight:bold;font-style:normal}body{font-family:Myriad-Pro,Calibri,Arial,Sans Serif;font-size:16px;line-height:24px;color:#313132;background:#036;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;min-width:768px}@media (min-width: 1920px){body{font-size:18px;line-height:1.5}}h1,h2,h3,h4{margin-top:0;margin-bottom:10px}h1 i.fa,h2 i.fa,h3 i.fa,h4 i.fa{font-size:24px;margin-right:6px}h1{font-weight:600;line-height:54px;color:#036;margin-bottom:20px}h1 small{font-size:14px;font-weight:700;text-transform:uppercase;color:#036;display:block;letter-spacing:0.1em}h2{font-weight:600;font-size:24px;line-height:36px;color:#313132;margin-bottom:20px}h3{font-weight:400;font-size:28px;line-height:42px;color:#036;margin-top:15px}h4{font-weight:600;font-size:18px;line-height:27px;color:#036;text-transform:uppercase}a{color:#365ebe;text-decoration:none;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}a:focus,a:hover{color:#2b4a96;text-decoration:underline;outline:none;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.intro{font-size:18px;line-height:28px}img{max-width:100%;height:auto}input.border-less-heading[type='text']{border:none;color:#036}input.border-less-heading[type='text']:focus{box-shadow:none;outline:none}input[type=number]{-moz-appearance:textfield}input.number-spinner[type=number]{-moz-appearance:spinner;text-align:right}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input.number-spinner[type=number]::-webkit-inner-spin-button,input.number-spinner[type=number]::-webkit-outer-spin-button{-moz-appearance:spinner}.table>tbody>tr>td,.list-builder>tbody>tr>td,.table>tbody>tr>th,.list-builder>tbody>tr>th,.table>tfoot>tr>td,.list-builder>tfoot>tr>td,.table>tfoot>tr>th,.list-builder>tfoot>tr>th,.table>thead>tr>td,.list-builder>thead>tr>td,.table>thead>tr>th,.list-builder>thead>tr>th{padding:12px 16px;vertical-align:top}.fact-sheet-question{width:50%}.fact-sheet-answer{width:25%}.fact-sheet-answer[readonly]{color:#8c8c8c;background:#f2f2f2}.fact-sheet-answer input,.fact-sheet-answer textarea{height:25px;width:100%;display:table-cell;border:none;resize:none;padding:2px 2px}.fact-sheet-answer input:focus,.fact-sheet-answer textarea:focus{box-shadow:none;outline:none}.fact-sheet-answer input[readonly],.fact-sheet-answer textarea[readonly]{color:#8c8c8c;background:#f2f2f2}.fact-sheet-answer input{text-align:left}.fact-sheet-control{border-bottom:1px solid #ddd;border-right:1px solid #ddd;border-left:1px solid #ddd;font-size:16px}.fact-sheet-control[readonly]{color:#8c8c8c;background:#f2f2f2}.fact-sheet-control a{color:#494949}.fact-sheet-control a i{color:#494949}.fact-sheet-control a:hover{text-decoration:none}.fact-sheet-control:hover{background:#d4dce5}.fact-sheet-button a{padding-right:6px;color:#494949}.fact-sheet-button a i{color:#494949}.fact-sheet-button a i:hover{color:#385dbc}.fact-sheet-input[readonly]{background:#f2f2f2}.table-cell-active{border:1px solid #66afe9;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.table>tbody>tr>td.list-builder-button,.list-builder>tbody>tr>td.list-builder-button{border:none}.table>thead>tr.list-builder-header>th:last-child,.list-builder>thead>tr.list-builder-header>th:last-child,.table>tbody>tr>td:last-child not:first-child,.list-builder>tbody>tr>td:last-child not:first-child{width:1px;white-space:nowrap}#claimant_children>thead>tr>th:nth-last-child(-n+2),#claimant_children>tbody>tr>td:nth-last-child(-n+2){width:1px;white-space:nowrap}.list-builder{border-collapse:initial;width:100%;table-layout:fixed;margin-bottom:48px}.list-builder-compact{margin-bottom:25px}.list-builder-hide-column{display:none;border:none}.child-item-row{height:50px}.child-item-row:hover td:not(:nth-last-child(-n+2)){background:#d4dce5}.child-support-amount[readonly]{background:#f2f2f2}div.dollar-prefix{position:relative}div.dollar-prefix:before{content:'$ ';top:0;height:100%;padding-left:5px;position:absolute;display:flex;flex-direction:row;align-items:center;justify-content:center}div.dollar-prefix input{text-align:right}div.percent-suffix{border:none;width:100%}div.percent-suffix input{border:none;padding:0px;outline:none;width:85%;text-align:right;display:inline}div.percent-suffix label{width:10%;display:inline;font-weight:normal}.money{text-align:right}.container-wrapper{padding:40px 0}.container-wrapper:nth-child(odd){background:#f2f2f2}.container-wrapper:nth-child(odd) input{background:#ffffff}.bg-danger{position:relative;padding:30px 30px 30px 75px;border-radius:8px;margin-bottom:20px;background-color:#fcf8e3}.bg-danger:after{content:"\f071";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;position:absolute;font-size:24px;color:#f0ad4e;top:30px;left:27px}.bg-danger.add-top-margin{margin-top:20px}.bg-danger.hard-stop{background-color:#faebe9}.bg-danger.hard-stop:after{content:"\f05e";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;position:absolute;font-size:24px;color:#d9534f;top:30px;left:27px}.bg-danger h2{line-height:initial;margin-bottom:10px}.bg-danger p+h2{margin-top:20px}.bg-danger #unselected_spouse_alert{margin-bottom:20px}.checkmark{background:#2e8540;position:relative;padding:22px 20px 20px 90px;color:#ffffff;border-radius:8px;font-size:32px}.checkmark:before{content:"\f00c";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;position:absolute;top:0;bottom:0;margin-top:auto;margin-bottom:auto;left:24px;font-size:42px;color:#ffffff;height:60px}@media (max-width: 991px){.container{width:100%;min-width:750px}}.tooltip.in{opacity:1}.tooltip-inner{text-align:left;background-color:#365ebe;padding:20px;font-size:16px;line-height:24px;max-width:300px;border-radius:10px;font-family:Myriad-Pro,Calibri,Arial,Sans Serif}.tooltip-innerb{font-size:18px}.tooltip-inner a{color:#ffffff;text-decoration:underline}.tooltip-inner a:focus,.tooltip-inner a:hover{color:#d5d5d5}.tooltip-arrow{pointer-events:none;border-color:rgba(255,255,255,0);border-width:12px !important}.tooltip.top .tooltip-arrow{border-top-color:#365ebe;margin-bottom:-16px}.tooltip.right{margin-left:10px}.tooltip.right .tooltip-arrow{border-right-color:#365ebe;margin-left:-12px;margin-top:-14px}.tooltip.bottom .tooltip-arrow{border-bottom-color:#365ebe;margin-top:-12px}.tooltip.left{margin-left:-10px}.tooltip.left .tooltip-arrow{border-left-color:#365ebe;margin-right:-12px;margin-top:-14px}.tooltip-link,.tooltip-no-link{color:#365ebe;border-bottom:dotted 1px #365ebe;cursor:pointer}.tooltip-link:hover,.tooltip-no-link:hover{color:#036;border-bottom-color:#365ebe}.tooltip-no-link{border-bottom:none}.collapse-trigger{margin-bottom:12px}.collapse-trigger>div{color:#365ebe;border-bottom:solid 1px #365ebe;display:inline;cursor:pointer}.collapse-trigger>div .tooltip-link,.collapse-trigger>div .tooltip-no-link{border:0}.collapse-trigger>div .tooltip-link:hover,.collapse-trigger>div .tooltip-no-link:hover{color:inherit}.collapse-trigger>div:after{font-family:FontAwesome;font-weight:normal;font-style:normal;display:inline-block;text-decoration:inherit;padding-left:10px;content:"\f077";-webkit-transform-origin:65% 50%;transform-origin:65% 50%;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.collapse-trigger>div:focus,.collapse-trigger>div:hover{color:#2b4a96;border-bottom:solid 1px #2b4a96;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.collapse-trigger.collapsed div:after{-webkit-transform:rotate(-180deg);transform:rotate(-180deg);-webkit-transform-style:preserve-3D;transform-style:preserve-3D;-webkit-transform-origin:65% 50%;transform-origin:65% 50%}.collapse>div,.collapsing>div{margin-bottom:25px}select.form-control{font-size:16px;height:42px}.form-group input.form-control,.input-group input.form-control:first-child{margin-top:12px;border-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px;height:inherit;width:inherit;float:inherit;font-size:inherit;padding:12px 15px;line-height:1em;display:inline}.form-group input.form-control.input-wide,.input-group input.form-control.input-wide:first-child{width:70%}.alias-header{width:100%}@media (min-width: 992px){.form-group.name-group{display:flex !important;flex-direction:row;justify-content:space-between;margin-top:20px;margin-bottom:8px}}.form-group.name-group>div{width:80%}@media (min-width: 992px){.form-group.name-group>div{width:24%}}.form-group.name-group>div input{width:99%}.form-group.name-group p{margin-bottom:3px}@media (min-width: 992px){div#other_names_fields .form-inline .form-group{flex:inherit}}div#other_names_fields .form-inline label{width:calc(100% - 90px);text-align:left}.btn{line-height:initial;padding:12px 15px}.btn-primary{background:#365ebe}.btn-primary:hover{background-color:#1f376f}i.fa{color:#365ebe}i.fa.circle{border-radius:50%;padding:10px;border:solid 1px #365ebe}i.fa.fa-question-circle{margin-left:5px}.form-buttons{margin:30px 0}.form-buttons .btn{font-size:18px;border:none;border-radius:10px;padding:12px 15px;background-color:#365ebe;color:#ffffff;margin-bottom:12px;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.form-buttons .btn:hover{background-color:#1f376f;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.form-buttons .btn i.fa{color:#ffffff}.form-buttons .btn.btn-success{background-color:#57b26a;margin-left:12px;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.form-buttons .btn.btn-success:hover{background-color:#337040;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.form-buttons .btn[disabled]{pointer-events:none;cursor:default}.review-warning{background-color:#F7D4D5;border-radius:8px;position:relative;padding:30px 30px 30px 75px;margin-bottom:20px}.review-warning ul{padding-left:15px}.review-warning:after{content:"\f06a";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;position:absolute;font-size:24px;color:#AC2025;top:30px;left:27px}.review-warning .warning,.review-warning .progress-status i{color:#AC2025;font-weight:bolder;margin:0 3px}.error{border:2px solid #D8292F !important;-webkit-transition:0.1s ease-in-out all;transition:0.1s ease-in-out all}.error .warning,.error .help-block{color:#D8292F;font-size:16px;font-weight:bolder}.error-text{color:#D8292F}.table-error{border:2px solid #D8292F !important;-webkit-transition:0.1s ease-in-out all;transition:0.1s ease-in-out all;margin:-12px -16px;padding:12px 16px}.table-error .warning{color:#D8292F;font-size:14px;font-weight:bolder;display:inline-block;width:100%;text-align:center}.btn-radio{color:#036;background-color:#d7dff2;font-size:16px;text-transform:uppercase;letter-spacing:0.08em;font-weight:600;padding:20px 0;width:60px;height:60px;border-radius:30px;border:3px solid #d7dff2;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.btn-radio.active,.btn-radio:active,.btn-radio:focus,.btn-radio:hover,.open .dropdown-toggle.btn-radio{color:#FFFFFF;background-color:#365ebe;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.btn-radio.active,.btn-radio:active,.open .dropdown-toggle.btn-radio{background-image:none}.btn-radio.disabled,.btn-radio.disabled.active,.btn-radio.disabled:active,.btn-radio.disabled:focus,.btn-radio.disabled:hover,.btn-radio[disabled],.btn-radio.active[disabled],.btn-radio[disabled]:active,.btn-radio[disabled]:focus,.btn-radio[disabled]:hover,fieldset[disabled] .btn-radio,fieldset[disabled] .btn-radio.active,fieldset[disabled] .btn-radio:active,fieldset[disabled] .btn-radio:focus,fieldset[disabled] .btn-radio:hover{background-color:#365ebe;border-color:#365ebe;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.btn-radio+.btn-radio{margin-left:15px}.btn-radio-group{margin-bottom:20px}.btn-radio-group .btn.active.focus,.btn-radio-group .btn.active:focus,.btn-radio-group .btn.focus,.btn-radio-group .btn.focus:active,.btn-radio-group .btn:active:focus,.btn-radio-group .btn:focus{outline:none}.btn-radio-group .btn-radio-long{width:auto;white-space:normal;text-transform:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1em;max-width:500px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;text-align:left;padding:0 20px}input{border-radius:4px;color:#494949;padding:12px 15px;border:solid 1px #d5d5d5;line-height:1em}input:focus{outline:0;box-shadow:inset 0 1px 1px rgba(49,49,50,0.075),0 0 4px rgba(157,157,157,0.5)}input+i.fa{margin-left:10px}input.form-block{display:block;margin-bottom:16px}input.input-wide{width:70%}input.input-narrow{max-width:100px}input.input-inline{padding:5px 20px;border-radius:5px;margin-left:5px}input.radio-centered{margin-top:15px}.checkbox label,.radio label{margin-bottom:8px;font-weight:700}.checkbox label.tight-spacing,.radio label.tight-spacing{margin-bottom:2px}.radio p,.checkbox p{margin-bottom:8px;margin-left:21px}.radio .radio-with-textbox{display:flex;align-items:baseline;margin-bottom:16px}.radio .radio-with-textbox input.form-block{margin-bottom:0;margin-right:8px}textarea{width:100%;border-radius:10px;color:#494949;padding:12px 15px;border:solid 1px #d5d5d5;line-height:24px;resize:none}#top_banner{background-color:#036;border-bottom:2px solid #fcba19;padding:5px 20px 10px}#top_banner .top_banner-logo img{width:148px;height:auto;float:left}#top_banner p{color:#ffffff;font-size:16px;line-height:1em;margin-top:20px;margin-left:35px;float:left}#top_banner p .beta{border:solid 1px #ffffff;padding:4px 8px 3px;margin-left:10px;font-size:12px;text-transform:uppercase}#top_banner p .beta.environment-type{background-color:#B200FF}#top_banner .top_banner-user{color:#fff;font-size:14px;float:right;margin-top:16px}#top_banner .top_banner-user input[type=submit]{color:#ffffff;background-color:transparent;display:inline;padding:0;line-height:1.5;border:none}#top_banner .top_banner-user input[type=submit]:active,#top_banner .top_banner-user input[type=submit]:hover{color:#fcfcfc;text-decoration:underline}#mid_banner{background-color:#38598A;font-size:14px;font-weight:600}#mid_banner .mid_banner-dash{float:left;margin-left:-20px}#mid_banner .mid_banner-dash a,#mid_banner .mid_banner-link a,#mid_banner .more_information-link a{padding:10px 16px;float:right;margin-left:6px}#mid_banner .mid_banner-dash a.active,#mid_banner .mid_banner-dash a:hover,#mid_banner .mid_banner-link a.active,#mid_banner .mid_banner-link a:hover,#mid_banner .more_information-link a.active,#mid_banner .more_information-link a:hover{color:#fff;background-color:#fcba19;text-decoration:none}#mid_banner .mid_banner-dash a.active i,#mid_banner .mid_banner-dash a:hover i,#mid_banner .mid_banner-link a.active i,#mid_banner .mid_banner-link a:hover i,#mid_banner .more_information-link a.active i,#mid_banner .more_information-link a:hover i{color:#fff}#mid_banner .mid_banner-dash a{margin-left:24px}#mid_banner i{color:#ffffff;padding:0 10px 0 0}#mid_banner a{color:#ffffff;text-decoration:none}#form_navigation{display:-webkit-box;display:-ms-flexbox;display:flex}#form_navigation form{margin-right:10px}.success-buttons{text-align:center;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-line-pack:justify;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.success-buttons .flex-row{width:45%;border-radius:8px;background-color:#d7dff2;border:1px solid #365ebe;display:flex;flex-direction:column;justify-content:space-between;padding:24px 30px}#other_names_fields .form-inline,#reconciliation_period_fields .form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:10px;padding:10px;background:#efefef;border-radius:5px}#other_names_fields .form-inline .form-group,#reconciliation_period_fields .form-inline .form-group{display:block;width:100%;margin-bottom:5px}@media (min-width: 992px){#other_names_fields .form-inline .form-group,#reconciliation_period_fields .form-inline .form-group{-webkit-box-flex:1;-ms-flex:1;flex:1}}#other_names_fields .form-inline .form-control,#reconciliation_period_fields .form-inline .form-control{display:inline-block;width:auto;vertical-align:middle;height:34px;margin-top:0;padding:8px 15px}#other_names_fields .form-inline label,#reconciliation_period_fields .form-inline label{min-width:45px;margin-right:10px;text-align:right}#other_names_fields .form-inline:before,#reconciliation_period_fields .form-inline:before{display:table;content:" "}#other_names_fields .form-inline select.response-dropdown,#reconciliation_period_fields .form-inline select.response-dropdown{margin-right:5px;-webkit-box-flex:0;-ms-flex:0 0 180px;flex:0 0 180px}@media (min-width: 1px) and (max-width: 1199px){#other_names_fields .form-inline select.response-dropdown,#reconciliation_period_fields .form-inline select.response-dropdown{margin-bottom:5px;-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%}}#other_names_fields .form-inline input.response-textbox,#reconciliation_period_fields .form-inline input.response-textbox{margin-right:5px;-webkit-box-flex:1;-ms-flex:1;flex:1;width:99%}#other_names_fields .form-inline input.btn,#reconciliation_period_fields .form-inline input.btn{padding:8px 15px}@media (min-width: 992px){#other_names_fields .form-inline input.btn,#reconciliation_period_fields .form-inline input.btn{-webkit-box-flex:0;-ms-flex:0 0 70px;flex:0 0 70px}}.footer{background-color:#036;border-top:3px solid #fcba19;padding:15px}.footer .footer-container ul{list-style-type:none}.footer .footer-container ul li{float:left;padding:2px 10px;position:relative}.footer .footer-container ul li a{display:block;text-align:center;color:#ffffff;font-size:13px;font-weight:600}.footer .footer-container ul li+li{border-left:1px solid #4b5e73}.question-well{min-height:20px;padding:25px;margin-top:25px;border:1px solid #d5d5d5;border-radius:10px;background:#ffffff}.question-well.hasFocus{border:1px solid #365ebe;-webkit-transition:0.1s ease-in-out all;transition:0.1s ease-in-out all}.question-well h3{margin-top:0}.question-well p{max-width:90%;margin-bottom:20px}.question-well .fact-sheet-table-inline-question{margin-bottom:48px}.question-well .required,.question-well .optional{font-size:14px;font-family:Myriad-Pro-Bold,Calibri,Arial,Sans Serif;font-weight:bold;text-transform:uppercase;padding:4px 6px;margin-left:16px;white-space:nowrap}.question-well .required.inline,.question-well .optional.inline{border:none;padding:0}.question-well .required{color:#D8292F;border:#D8292F 2px solid}.question-well .optional{color:#036;border:#036 1px solid}.question-well-border-less{min-height:20px;padding:25px 25px 0 0;margin-top:25px;background:#ffffff}.question-well-border-less h3{margin-top:20px}.question-well-border-less p{max-width:90%}.review-well{border-radius:10px;min-height:20px;margin-bottom:10px;border:1px solid #d5d5d5;background:#ffffff}.review-well .review-well{margin:0 40px 5px}.review-well .collapse-trigger{padding:20px 15px}.review-well .collapse,.review-well .collapsing{border-top:1px solid #d5d5d5;padding:24px 47px}.review-well .collapse>div,.review-well .collapsing>div{margin-bottom:0}.review-well .review-buttons{float:left;padding:0 15px 20px;margin:0 0 0 32px}@media (min-width: 991px){.review-well .review-buttons{float:right;padding:10px 15px;margin:0}}.review-well .review-buttons .fa{color:white;margin-right:6px}.review-well .collapse-trigger{margin-bottom:0;display:inline-block;width:100%}@media (min-width: 991px){.review-well .collapse-trigger{width:initial}}.review-well .collapse-trigger>div{border-bottom:none;font-size:18px;font-weight:600;padding-left:8px;position:relative}.review-well .collapse-trigger>div:before{font-family:FontAwesome;font-weight:normal;font-style:normal;position:absolute;text-decoration:inherit;left:0;content:"\f077";-webkit-transform-origin:50%;transform-origin:50%;-webkit-transition:all 0.1s ease-in-out;transition:all 0.1s ease-in-out}.review-well .collapse-trigger>div span{display:inline-block;margin-left:24px}.review-well .collapse-trigger>div:after{display:none}.review-well .collapse-trigger.empty{display:block;border-top:1px solid #d5d5d5}.review-well .collapse-trigger.empty div:before{display:none}.review-well .collapse-trigger.collapsed div:before{-webkit-transform:rotate(-180deg);transform:rotate(-180deg);-webkit-transform-style:preserve-3D;transform-style:preserve-3D;-webkit-transform-origin:50%;transform-origin:50%}.review-well .collapse.empty{display:inline-block;border-top:none}.review-well-no-icon{padding-left:47px}.review-well-child{display:inline-block;width:100%}.review-well-child .review-buttons{margin:0;padding-left:8px}@media (min-width: 991px){.review-well-child .review-buttons{margin:initial;padding-left:initial}}.review-well-child .collapse-trigger{padding-left:0}.review-well-child .collapse-trigger>div{color:#313132;font-weight:normal}.review-child-heading{background-color:#D4DCE5}.review-table-spacer::before{content:'';display:block;height:25px}.print-form-action{display:inline-block;float:right}.print-form-action a{text-decoration:none}.print-form-action:after{display:none}.step-review .collapse-trigger{font-size:24px;display:inline-block}.step-review .collapse-trigger.collapsed{margin-bottom:0;-webkit-transition:0.5s ease-out all;transition:0.5s ease-out all}.step-review table{margin-bottom:0}.step-review table thead tr{background-color:#036;color:#fff}.step-review table .value-column{width:30%;min-width:192px}.step-review .collapse>div,.step-review .collapsing>div{margin-bottom:0}.step-review .review-buttons{float:right}.signing-filing .question-well{margin-top:15px;margin-bottom:30px;padding-bottom:0}.signing-filing .question-well h3{font-size:24px}.signing-filing .form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;align-items:center;margin-bottom:10px;padding:10px;background:#efefef;border-radius:5px}.signing-filing .form-inline label{margin:0 15px 0 5px;text-align:right}.signing-filing .form-inline:before{display:table;content:" "}.signing-filing .form-inline input{margin-right:5px;-webkit-box-flex:1;-ms-flex:1;flex:1;width:99%;min-width:200px}.dashboard-content p{margin-bottom:15px}.dashboard-content ul{margin-bottom:30px}.dashboard-content .no-margin-bottom{margin-bottom:0 !important}.dashboard-content .add-top-margin{margin-top:30px}.dashboard-content .no-bullets{padding-left:0}.dashboard-content .no-bullets li{list-style:none}.dashboard-content .upload-area{padding:32px 20px 32px 20px;margin-bottom:50px;background-color:#f2f2f2;border:1px solid #9D9D9D;border-radius:8px}.row-flex{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;height:100%;overflow:hidden;background:#fdfdfd;position:relative}.row-flex .col{-webkit-box-flex:1;-ms-flex:1;flex:1;box-sizing:border-box;-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.row-flex .col.shroud:before{content:"";position:absolute;width:100%;display:block;height:100%;background:linear-gradient(to top, rgba(0,0,0,0.35) 0%, transparent 90%)}.row-flex .content-column{max-width:1280px;padding:36px 6% 50px;position:relative}.row-flex .progress-column{-webkit-box-flex:0;-ms-flex:0 0 280px;flex:0 0 280px;background-color:#efefef;-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.row-flex .dashnav-column{-webkit-box-flex:0;-ms-flex:0 0 290px;flex:0 0 289px;background-color:#036;-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.row-flex .more_information-column{background-color:#efefef;box-shadow:inset 0 0 10px 0 rgba(0,0,0,0.1);padding:20px 45px;font-size:14px;line-height:21px;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1;height:auto}@media (min-width: 1920px){.row-flex .more_information-column{font-size:16px;line-height:1.5}}.row-flex .more_information-column .more_information-close{float:right;font-size:24px;margin-top:3px}.row-flex .more_information-column .more_information-close i.fa{color:#036}.row-flex .more_information-column h2{color:#036;padding-right:25px}.row-flex .more_information-column h3{font-size:21px;line-height:28px}@media (min-width: 992px){.row-flex .more_information-column{padding:45px 20px;-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4;-webkit-box-flex:0;-ms-flex:0 0 306px;flex:0 0 306px}}.row-flex.intro-page{background:#38598A url("../img/bg-edivorce__landing.jpg") no-repeat top center fixed;background-size:cover}.row-flex.intro-page .content-column{margin:54px auto 100px;max-width:840px;padding:0 20px;text-align:center;color:#ffffff;position:relative}.row-flex.intro-page .content-column h1{color:#036;max-width:600px;margin:70px auto;font-size:48px}.row-flex.intro-page .content-column h2,.row-flex.intro-page .content-column h3{color:#ffffff}.row-flex.intro-page .content-column h2{font-size:30px;font-weight:600;margin:42px 0 0}.row-flex.intro-page .content-column h2.shaded-box{padding-top:28px;border-top-left-radius:8px;border-top-right-radius:8px}.row-flex.intro-page .content-column .intro{font-size:24px;line-height:36px;margin:0 100px}.row-flex.intro-page .content-column a{color:#ffffff;text-decoration:none}.row-flex.intro-page .content-column a:focus,.row-flex.intro-page .content-column a:hover{text-decoration:underline}.row-flex.intro-page .content-column a.btn:focus,.row-flex.intro-page .content-column a.btn:hover{text-decoration:none}.row-flex.intro-page .content-column .btn-group-lg>.btn,.row-flex.intro-page .content-column .btn-lg{padding:12px 40px;margin:10px}.row-flex.intro-page .content-column .flex-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;margin:20px 0;text-align:left;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:18px}.row-flex.intro-page .content-column .flex-wrapper .flex-column{width:45%}.row-flex.intro-page .content-column .flex-wrapper.shaded-box{padding-top:22px;padding-bottom:50px;margin-top:0;border-bottom-left-radius:8px;border-bottom-right-radius:8px}.row-flex.intro-page .content-column .flex-wrapper.shaded-box .flex-column.left{padding-left:30px}.row-flex.intro-page .content-column .flex-wrapper.shaded-box .flex-column.right{padding-right:30px}.row-flex.intro-page .content-column .flex-wrapper span.number-circle{border:solid 2px white;padding:0;border-radius:40px;width:40px;height:40px;display:inline-block;text-align:center;margin-right:10px;font-size:21px}.intro-footer{text-align:center;padding-bottom:92px;background:#ffffff}.intro-footer .column{max-width:640px;margin:0 auto}.intro-footer h3{color:#036;font-size:24px;line-height:36px;padding-top:60px;padding-bottom:35px;margin:0}.intro-footer .btn{width:260px;height:48px;font-weight:bold;line-height:24px;border-radius:8px}.dashnav-column h4,.overview-progress h4,.progress-column h4{color:#036;padding:0 18px;margin-top:36px;font-size:14px;letter-spacing:0.1em}.dashnav-column .progress-question,.overview-progress .progress-question,.progress-column .progress-question{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:70px;margin-bottom:12px;padding:0 24px;font-weight:bold}.dashnav-column .progress-question .progress-icon,.overview-progress .progress-question .progress-icon,.progress-column .progress-question .progress-icon{-webkit-box-flex:0;-ms-flex:0 0 46px;flex:0 0 50px}.dashnav-column .progress-question .progress-icon i,.overview-progress .progress-question .progress-icon i,.progress-column .progress-question .progress-icon i{font-size:20px;border:solid 1px #036;padding:8px;border-radius:36px}.dashnav-column .progress-question .progress-icon i.fa:before,.overview-progress .progress-question .progress-icon i.fa:before,.progress-column .progress-question .progress-icon i.fa:before{width:20px;text-align:center;display:block;height:20px}.dashnav-column .progress-question .progress-content,.overview-progress .progress-question .progress-content,.progress-column .progress-question .progress-content{width:190px;font-size:14px;line-height:1.3}@media (min-width: 1920px){.dashnav-column .progress-question .progress-content,.overview-progress .progress-question .progress-content,.progress-column .progress-question .progress-content{font-size:16px;width:190px}}.dashnav-column .progress-question .progress-content small,.overview-progress .progress-question .progress-content small,.progress-column .progress-question .progress-content small{font-size:11px;text-transform:uppercase;font-weight:bolder;letter-spacing:0.1em}.dashnav-column .progress-question i,.dashnav-column .progress-question span,.overview-progress .progress-question i,.overview-progress .progress-question span,.progress-column .progress-question i,.progress-column .progress-question span{color:#036;border-color:#036}.dashnav-column .progress-question.complete i,.dashnav-column .progress-question.complete span,.overview-progress .progress-question.complete i,.overview-progress .progress-question.complete span,.progress-column .progress-question.complete i,.progress-column .progress-question.complete span{color:#2e8540;border-color:#2e8540}.dashnav-column .progress-question:focus,.dashnav-column .progress-question:hover,.overview-progress .progress-question:focus,.overview-progress .progress-question:hover,.progress-column .progress-question:focus,.progress-column .progress-question:hover{background-color:#e6ca85;text-decoration:none}.dashnav-column .progress-question.active,.overview-progress .progress-question.active,.progress-column .progress-question.active{background-color:#fcba19;text-decoration:none}.dashnav-column .progress-status,.overview-progress .progress-status,.progress-column .progress-status{width:28px;text-align:right}.dashnav-column .progress-status i,.overview-progress .progress-status i,.progress-column .progress-status i{float:right}.dashnav-column .progress-status i.incomplete,.dashnav-column .progress-status i.skipped,.overview-progress .progress-status i.incomplete,.overview-progress .progress-status i.skipped,.progress-column .progress-status i.incomplete,.progress-column .progress-status i.skipped{color:#AC2025}.dashnav-column .progress-status i.complete,.overview-progress .progress-status i.complete,.progress-column .progress-status i.complete{color:#2e8540}.dashnav-column .progress-sub-menu,.overview-progress .progress-sub-menu,.progress-column .progress-sub-menu{list-style-type:none}.dashnav-column .progress-sub-menu li,.overview-progress .progress-sub-menu li,.progress-column .progress-sub-menu li{display:inline-block;padding:5px 24px 5px 22px;border-left:2px solid #fcba19;width:100%}.dashnav-column .progress-sub-menu .progress-sub-question,.overview-progress .progress-sub-menu .progress-sub-question,.progress-column .progress-sub-menu .progress-sub-question{width:190px;font-size:14px;line-height:1.3;color:#036}@media (min-width: 1920px){.dashnav-column .progress-sub-menu .progress-sub-question,.overview-progress .progress-sub-menu .progress-sub-question,.progress-column .progress-sub-menu .progress-sub-question{font-size:16px;width:190px}}.dashnav-column .progress-sub-menu .progress-sub-question .progress-content,.overview-progress .progress-sub-menu .progress-sub-question .progress-content,.progress-column .progress-sub-menu .progress-sub-question .progress-content{width:190px;font-size:14px;font-weight:bold;line-height:1.3}@media (min-width: 1920px){.dashnav-column .progress-sub-menu .progress-sub-question .progress-content,.overview-progress .progress-sub-menu .progress-sub-question .progress-content,.progress-column .progress-sub-menu .progress-sub-question .progress-content{font-size:16px;width:190px}}.dashnav-column .progress-sub-menu .progress-sub-question:focus,.dashnav-column .progress-sub-menu .progress-sub-question:hover,.overview-progress .progress-sub-menu .progress-sub-question:focus,.overview-progress .progress-sub-menu .progress-sub-question:hover,.progress-column .progress-sub-menu .progress-sub-question:focus,.progress-column .progress-sub-menu .progress-sub-question:hover{color:#fcba19;text-decoration:none;font-weight:700}.dashnav-column .progress-sub-menu .progress-sub-question.active:focus,.dashnav-column .progress-sub-menu .progress-sub-question.active:hover,.overview-progress .progress-sub-menu .progress-sub-question.active:focus,.overview-progress .progress-sub-menu .progress-sub-question.active:hover,.progress-column .progress-sub-menu .progress-sub-question.active:focus,.progress-column .progress-sub-menu .progress-sub-question.active:hover{border-bottom:1px solid #fcba19}.dashnav-column .progress-sub-menu .progress-sub-question.active,.overview-progress .progress-sub-menu .progress-sub-question.active,.progress-column .progress-sub-menu .progress-sub-question.active{text-decoration:none;padding-bottom:4px;border-bottom:1px solid #036;font-weight:700}.dashnav-column .progress-question{height:60px}.overview-progress{border:solid 1px #d5d5d5;border-radius:10px;background:#ffffff}.overview-progress .progress-question{margin-bottom:0;border-bottom:solid 1px #d5d5d5}.overview-progress .progress-question:last-of-type{border-bottom:none}.overview-progress .progress-question .progress-icon{-webkit-box-flex:0;-ms-flex:0 0 52px;flex:0 0 52px}.overview-progress .progress-question .progress-content{font-size:16px;font-weight:600;-webkit-box-flex:2;-ms-flex:2;flex:2}.overview-progress .progress-question .progress-status{font-size:14px;font-weight:600;-webkit-box-flex:1;-ms-flex:1;flex:1}.overview-progress .progress-question .progress-status i{font-size:20px;float:none;margin-left:16px;vertical-align:middle}.overview-progress .progress-question.complete{background-color:#d5e6d8}.overview-progress .progress-question:focus,.overview-progress .progress-question:hover{background-color:#d7dff2;text-decoration:none}.overview-progress .progress-question:first-child{border-top-left-radius:9px;border-top-right-radius:9px}.overview-progress .progress-question:last-child{border-bottom-left-radius:9px;border-bottom-right-radius:9px}.overview-progress .progress-question a{transition:0.1s background ease-in-out;-webkit-transition:0.1s background ease-in-out}.dashnav-column h4{color:#ffffff}.dashnav-column .progress-question .progress-icon{-webkit-box-flex:0;-ms-flex:0 0 36px;flex:0 0 36px}.dashnav-column .progress-question .progress-icon i{font-size:20px;border:none;padding:0}.dashnav-column .progress-question .progress-content{width:180px;color:#ffffff;font-weight:600}.dashnav-column .progress-question i{color:#ffffff}.dashnav-column .progress-question.active i,.dashnav-column .progress-question.active .progress-content{color:#036}.dashnav-column .progress-question:focus,.dashnav-column .progress-question:hover{background-color:#fcba19}.progress-column .progress-question.active:not(.complete) .progress-icon i{border:solid 1px #036;background-color:#036;color:#fcba19}.progress-column .progress-question.active.complete .progress-icon i{border:solid 1px #2e8540;background-color:#2e8540;color:#fcba19}.has-warning-box{border:3px solid #D8292F;padding-top:8px;padding-left:8px}.has-warning-box #terms_warning{color:#D8292F}.list-item-description{padding-left:20px;margin-bottom:25px;margin-top:-10px}.modal-dialog{width:780px}.modal-header{border:0;padding-bottom:0;padding-top:24px}.modal-title{font-size:32px;font-weight:normal}.modal-body{padding:0 64px 36px}.modal-body p{font-size:18px;margin-top:12px}.modal-footer{background:#f2f2f2;border-bottom-left-radius:10px;border-bottom-right-radius:10px}.footnote-marker{font-size:18px;top:-10px;position:relative;display:inline-block;left:1px;margin-right:1px}.footnote{margin-top:40px;margin-bottom:52px;font-size:16px}.footnote h5{font-size:30px;margin-bottom:20px}.footnote.shaded-box{border-radius:8px;padding:25px 80px 25px 80px}.shaded-box{background-color:rgba(0,0,0,0.7)}#delete_child_modal,#info_modal,#questions_modal,#terms_modal{margin-top:112px;font-size:18px}#delete_child_modal .modal-header,#info_modal .modal-header,#questions_modal .modal-header,#terms_modal .modal-header{text-align:center}#delete_child_modal .modal-header i,#info_modal .modal-header i,#questions_modal .modal-header i,#terms_modal .modal-header i{background-color:#365ebe;color:#ffffff;height:80px;width:80px;border-radius:40px;font-size:40px;padding:20px;margin-bottom:15px}#delete_child_modal .modal-body,#info_modal .modal-body,#questions_modal .modal-body,#terms_modal .modal-body{padding:36px 64px}#delete_child_modal .modal-body p,#info_modal .modal-body p,#questions_modal .modal-body p,#terms_modal .modal-body p{font-size:18px;margin-top:12px}#delete_child_modal .modal-footer,#info_modal .modal-footer,#questions_modal .modal-footer,#terms_modal .modal-footer{text-align:center;border:none;padding-bottom:18px}#delete_child_modal{text-align:center;vertical-align:middle;margin-top:112px;font-size:18px}#delete_child_modal .modal-footer{text-align:center;border:none;padding-bottom:18px}div#progress-overlay{position:fixed;top:0;bottom:0;left:0;right:0;z-index:10000;background:rgba(0,0,0,0.35)}div#progress-overlay-spinner{position:fixed;top:0;bottom:0;left:0;right:0;z-index:5000}span.hard-stop{font-size:2.8em;display:inline-block;float:left;margin:3px 10px 0 0}.date-picker-group .input-group-addon{display:inline-block;background-color:inherit;border:none}@media (min-width: 1px) and (max-width: 991px){.on-canvas{display:block}}@media (min-width: 992px){.on-canvas{-webkit-transition:0.2s ease-out all;transition:0.2s ease-out all;-webkit-transform:translateX(0);transform:translateX(0)}}@media (min-width: 1px) and (max-width: 991px){.off-canvas{display:none}}@media (min-width: 992px){.off-canvas{-webkit-transition:0.2s ease-out all;transition:0.2s ease-out all;-webkit-transform:translateX(306px);transform:translateX(306px)}}@media (min-width: 1px) and (max-width: 991px){.margin-right{margin-right:0}}@media (min-width: 992px){.margin-right{-webkit-transition:0.2s ease-out all;transition:0.2s ease-out all;margin-right:-306px}}@media (min-width: 1px) and (max-width: 991px){.no-margin-right{margin-right:0}}@media (min-width: 992px){.no-margin-right{-webkit-transition:0.2s ease-out all;transition:0.2s ease-out all;margin-right:0}} /*# sourceMappingURL=main.css.map */ \ No newline at end of file diff --git a/edivorce/apps/core/static/css/main.scss b/edivorce/apps/core/static/css/main.scss index 8afd0f4d..b07d4839 100644 --- a/edivorce/apps/core/static/css/main.scss +++ b/edivorce/apps/core/static/css/main.scss @@ -994,12 +994,18 @@ textarea { float: right; margin-top: 16px; - a { + input[type=submit] { color: #ffffff; + background-color: transparent; + display: inline; + padding: 0; + line-height: 1.5; + border: none; &:active, &:hover { color: #fcfcfc; + text-decoration: underline; } } } @@ -2136,18 +2142,6 @@ textarea { background-color: rgba(0,0,0,0.7); } -.light-shaded-box { - background-color: $color-grey-lightest; - border-radius: 8px; - padding: 18px 30px; - margin-bottom: 28px; - - p { - margin: 0; - max-width: 100%; - } -} - #delete_child_modal, #info_modal, #questions_modal, diff --git a/edivorce/apps/core/templates/base.html b/edivorce/apps/core/templates/base.html index ea9a987e..089ee643 100644 --- a/edivorce/apps/core/templates/base.html +++ b/edivorce/apps/core/templates/base.html @@ -13,10 +13,10 @@ {% compress css %} - - - - + + + + {% endcompress %} {% block extra_css %} {% endblock %} @@ -54,8 +54,12 @@
{% if request.user.is_authenticated %} - {{ request.user.display_name}} -   |   Log out +
+ {{ request.user.display_name}} +   |   + {% csrf_token %} + +
{% endif %}
diff --git a/edivorce/apps/core/templates/dashboard/file_documents.html b/edivorce/apps/core/templates/dashboard/file_documents.html index 67d0708c..f86a54c8 100644 --- a/edivorce/apps/core/templates/dashboard/file_documents.html +++ b/edivorce/apps/core/templates/dashboard/file_documents.html @@ -11,10 +11,10 @@

At the counter, the registry staff will check your documents to make sure they've been completed properly.

If you're not sure whether you've filled out the documents correctly, get some - legal advice before you file your documents — from - family duty counsel + legal advice before you file your documents — from + family duty counsel or (in Vancouver) from the Vancouver - Justice Access Centre Self-Help and Information Services. + Justice Access Centre Self-Help and Information Services.

If the registry is satisfied that your documents are in order, they will stamp the documents with the date, the court seal, and a file number.

You now have a divorce file open in the Supreme Court.

diff --git a/edivorce/apps/core/templates/dashboard/help_saving_pdf.html b/edivorce/apps/core/templates/dashboard/help_saving_pdf.html index 4bd6ea27..e446e66b 100644 --- a/edivorce/apps/core/templates/dashboard/help_saving_pdf.html +++ b/edivorce/apps/core/templates/dashboard/help_saving_pdf.html @@ -55,7 +55,7 @@

It's a great idea to save the PDFs of your forms to your computer so you have a backup, and can print it later. You must have Adobe Reader installed (or Preview on Mac), otherwise, you can - download it + download it here.

@@ -87,7 +87,7 @@ “Documents”). You may want to make a note of where you saved it.
  • Open Adobe Reader (or Preview on Mac). If you need to, you can download it + href="https://get2.adobe.com/reader/" target="_blank">download it here.
  • When Adobe Reader is open, go to File, then to Open, then go to your “Downloads” folder (or to where you saved the diff --git a/edivorce/apps/core/templates/dashboard/next_steps.html b/edivorce/apps/core/templates/dashboard/next_steps.html index 95203396..c60393b2 100644 --- a/edivorce/apps/core/templates/dashboard/next_steps.html +++ b/edivorce/apps/core/templates/dashboard/next_steps.html @@ -65,10 +65,10 @@

    If you're not sure whether you've filled out the documents correctly, get some - legal advice before you file your documents — from - family duty counsel + legal advice before you file your documents — from + family duty counsel or (in Vancouver) from the Vancouver - Justice Access Centre Self-Help and + Justice Access Centre Self-Help and Information Services.

    diff --git a/edivorce/apps/core/templates/dashboard/order_certificate.html b/edivorce/apps/core/templates/dashboard/order_certificate.html index 670bc43a..7de4ec21 100644 --- a/edivorce/apps/core/templates/dashboard/order_certificate.html +++ b/edivorce/apps/core/templates/dashboard/order_certificate.html @@ -18,7 +18,7 @@

    For details on - how to apply for a Certificate of Divorce + how to apply for a Certificate of Divorce refer to the Legal Services Society website.

    Out of Country Certificate of Divorce Requirements

    diff --git a/edivorce/apps/core/templates/dashboard/print_form.html b/edivorce/apps/core/templates/dashboard/print_form.html index 8d991974..219204f4 100644 --- a/edivorce/apps/core/templates/dashboard/print_form.html +++ b/edivorce/apps/core/templates/dashboard/print_form.html @@ -139,7 +139,7 @@

    -{% if where_were_you_married_country == 'Canada' and not request.user.is_bcsc %} +{% if where_were_you_married_country == 'Canada' %}

    Select how you would like to file (?) your documents:

    {% endblock %} diff --git a/edivorce/apps/core/templates/legal.html b/edivorce/apps/core/templates/legal.html index 854125d7..7baa5702 100644 --- a/edivorce/apps/core/templates/legal.html +++ b/edivorce/apps/core/templates/legal.html @@ -23,7 +23,7 @@

    Online resources

    - You may want to look at the Divorce self-help kit + You may want to look at the Divorce self-help kit on the Family Law in British Columbia website for a step-by-step guide. You can also visit ClickLaw and the Justice Education Society for online legal information. diff --git a/edivorce/apps/core/templates/localdev/bceid.html b/edivorce/apps/core/templates/localdev/bceid.html deleted file mode 100644 index 77bb2222..00000000 --- a/edivorce/apps/core/templates/localdev/bceid.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - Government of British Columbia - - - - - - - CLP - - - - - - - - - - - - - - - - - - - - - -

    -
    -
    -
    -
    FAKE BCeID LOGIN – FOR SOFTWARE DEVELOPMENT PURPOSES ONLY
    -
    -
    - -
    -
    -
    - -
    -
    -
    - - -
    - - - - - - - - - - - - - - - - - - diff --git a/edivorce/apps/core/templates/localdev/debug.html b/edivorce/apps/core/templates/localdev/debug.html deleted file mode 100644 index 46d4fb59..00000000 --- a/edivorce/apps/core/templates/localdev/debug.html +++ /dev/null @@ -1,16 +0,0 @@ - - - Debug - - - - -{% for k, v in request.META.items %} - {% if k.isupper %} - {{ k }} = {{ v }}
    - {% endif %} -{% endfor %} - - - - \ No newline at end of file diff --git a/edivorce/apps/core/templates/localdev/register.html b/edivorce/apps/core/templates/localdev/register.html deleted file mode 100644 index 2f5d2e2a..00000000 --- a/edivorce/apps/core/templates/localdev/register.html +++ /dev/null @@ -1,17 +0,0 @@ - - - Register - - - - -

    localdev registration is not implemented

    - -

    Enter any user id with the password divorce to - simulate a login in your localdev envirommnent.

    - -Goto Login - - - - \ No newline at end of file diff --git a/edivorce/apps/core/templates/partials/fact_sheets/fact_sheet_b.html b/edivorce/apps/core/templates/partials/fact_sheets/fact_sheet_b.html index 5361a40d..3e8575d1 100644 --- a/edivorce/apps/core/templates/partials/fact_sheets/fact_sheet_b.html +++ b/edivorce/apps/core/templates/partials/fact_sheets/fact_sheet_b.html @@ -53,7 +53,7 @@ target="_blank">Federal Child Support Guidelines: Step-by-Step Guide
  • - The child support page on the Family Law in B.C. website.
  • diff --git a/edivorce/apps/core/templates/pdf/images_to_pdf.html b/edivorce/apps/core/templates/pdf/images_to_pdf.html index 8a6da5e5..bc0c6c0c 100644 --- a/edivorce/apps/core/templates/pdf/images_to_pdf.html +++ b/edivorce/apps/core/templates/pdf/images_to_pdf.html @@ -29,7 +29,7 @@ diff --git a/edivorce/apps/core/templates/question/01_orders.html b/edivorce/apps/core/templates/question/01_orders.html index 7a16522a..1351d088 100644 --- a/edivorce/apps/core/templates/question/01_orders.html +++ b/edivorce/apps/core/templates/question/01_orders.html @@ -81,7 +81,7 @@ asked to provide details for each request.

    For more information, please refer to the - Spousal Support fact sheet on the Family Law in B.C. website.

    @@ -136,7 +136,7 @@ asked to provide details for each request.

    Anything you own including real estate, bank accounts, cars and RRSPs. For more information, please refer to the - Dealing with Debts After Separation fact sheet on the Family Law in B.C. website.

    @@ -271,14 +271,14 @@ asked to provide details for each request.

    More information on which court you may need to go to can be found on the - Family Law in B.C. website + Family Law in B.C. website and the Government of B.C. website.

    Asking for Orders Pertaining to Children in Provincial or Supreme Court.

    If you will be asking for parenting and support issues, you can choose between the - Divorce Act + Divorce Act or the Family Law Act. @@ -452,7 +452,7 @@ asked to provide details for each request.

    More information on - Court Orders can be found on the Family Law in B.C. website.

    diff --git a/edivorce/apps/core/templates/question/06_children_income_expenses.html b/edivorce/apps/core/templates/question/06_children_income_expenses.html index 76378128..bdd80b4e 100644 --- a/edivorce/apps/core/templates/question/06_children_income_expenses.html +++ b/edivorce/apps/core/templates/question/06_children_income_expenses.html @@ -581,7 +581,7 @@

    For more information on - undue hardship + undue hardship refer to the Family Law of B.C. website.

    @@ -606,7 +606,7 @@

    More details on what are - + generally considered special or extraordinary expenses can be found on the Family Law of B.C. website. diff --git a/edivorce/apps/core/templates/question/06_children_what_for.html b/edivorce/apps/core/templates/question/06_children_what_for.html index c97ff8c8..88d9e1ed 100644 --- a/edivorce/apps/core/templates/question/06_children_what_for.html +++ b/edivorce/apps/core/templates/question/06_children_what_for.html @@ -151,7 +151,7 @@

    If you wish to file your separation agreement the parts of the agreement that deal with parenting and support can be enforced as if they were in a court order. More information on - + how to file your agreement can be found on the Family Law website. @@ -191,7 +191,7 @@

    If you - + wish to file your separation agreement , the parts of the agreement that deal with parenting and support can be @@ -260,7 +260,7 @@

    If you wish to file your separation agreement, the parts of the agreement that deal with parenting and support can be enforced as if they were in a court order. More information on - + how to file your agreement can be found on the Family Law website. @@ -391,7 +391,7 @@ The Supreme Court Family Order Pick List which sets out standard terms for most of the usual orders made in family cases. Refer to the fact sheet - + Child Support by the Legal Services Society for more information.

    @@ -457,7 +457,7 @@

    There are big differences in how the Divorce Act and the Family Law Act deal with some issues, especially parenting. For more information, see the fact sheet - + Parenting apart and the other fact sheets it links to.

    @@ -499,7 +499,7 @@ you must only consider the child’s best interests. And if you go to court, the judge can only consider the child’s best interests in making parenting orders. For more information on the - + best interests of the child please refer to the Family Law in B.C. website. diff --git a/edivorce/apps/core/templates/question/06_children_your_children.html b/edivorce/apps/core/templates/question/06_children_your_children.html index 307ef941..2491984e 100644 --- a/edivorce/apps/core/templates/question/06_children_your_children.html +++ b/edivorce/apps/core/templates/question/06_children_your_children.html @@ -231,7 +231,7 @@

    For more information on - step-parents' rights and responsibilities please refer to the Family Law of B.C. website.

    diff --git a/edivorce/apps/core/templates/question/07_support.html b/edivorce/apps/core/templates/question/07_support.html index ec44c73d..28a9fc03 100644 --- a/edivorce/apps/core/templates/question/07_support.html +++ b/edivorce/apps/core/templates/question/07_support.html @@ -63,7 +63,7 @@ or a family justice counsellor for help. For more information, please see the fact sheet - Spousal Support on the Family Law in B.C. website.

    @@ -83,7 +83,7 @@ detailed in a separation agreement.

    Many couples come to an agreement about spousal support outside of court and capture the details in a - separation agreement. "Agreements that are filed with the court can be enforced — they have the same force as a court order. They can also be set aside (cancelled) if the situation @@ -107,7 +107,7 @@

    For help on what factors to consider, and details to include in your spousal support agreement, refer to the online tool, - How to Write Your Own Separation Agreement, on the Family Law in B.C. website.

    @@ -206,7 +206,7 @@

    There are big differences in how the Divorce Act and the Family Law Act deal with some issues, especially parenting. For more information on - which laws apply to your situation please refer to the Family Law of B.C. website.

    @@ -284,7 +284,7 @@ into account the income of both spouses, how long you were married, and whether you have children.

    For more information, see the Department of Justice website on - spousal support.

    @@ -321,7 +321,7 @@ target="_blank">Financial Statement Form (F8) and file it with the court for orders related to support. For help, refer to the guide - How to deal with a Supreme Court Financial Statement, produced by the Legal Services Society.

    diff --git a/edivorce/apps/core/templates/question/08_property.html b/edivorce/apps/core/templates/question/08_property.html index c057142a..38d09daa 100644 --- a/edivorce/apps/core/templates/question/08_property.html +++ b/edivorce/apps/core/templates/question/08_property.html @@ -132,8 +132,8 @@

    The Family Law web site has an online separation agreement tool that details some of the items to consider when - dividing property and - debt.

    + dividing property and + debt.

    {% input_field type="textarea" name="how_to_divide_property_debt" rows="8" cols="65" class="response-textarea" %} @@ -223,11 +223,11 @@ target="_blank">Family Justice section of the BC Government web site.
  • Dividing family property and debts on the Family Law in British Columbia website
  • Living Together or Living Apart, a booklet about the family law basics in B.C.
  • You have met the conditions for using the Online Divorce Assistant
    -

    1. Gather your documents

    -

    You will need the following documents to move forward with the divorce request:

    -
      -
    • Marriage certificate
    • -
    • Separation agreement (if applicable)
    • -
    • Court order (if applicable)
    • -
    -
    - -
    -

    2. Register or Login

    +

    Register or Login

    You will need a Basic BCeID or BC Services Card account to access the Online Divorce Assistant. This will also enable you to securely access multiple other online government services.

    -
    -

    NOTE about logging in with your BC Services Card

    -

    - You can log in and use the Online Divorce Assistant with your BC Services Card. - However, you are limited to filing in-person at a BC Court Registry as online - filing with a BC Services Card is currently not available. -

    -
    -

    Register for a
    Basic BCeID

    diff --git a/edivorce/apps/core/templatetags/format_utils.py b/edivorce/apps/core/templatetags/format_utils.py index 140718a2..907687de 100644 --- a/edivorce/apps/core/templatetags/format_utils.py +++ b/edivorce/apps/core/templatetags/format_utils.py @@ -193,22 +193,6 @@ def agreed_child_support_amount(context, claimant_id, line_breaks=True): return linebreaksli(context.get('amount_income_over_high_income_limit_{}'.format(claimant_id), '')) -@register.filter -def css_rotate(image): - """ Gets extra CSS needed for image rotation when generating PDFs """ - if image.rotation == 90 or image.rotation == 270: - height = image.width - width = image.height - else: - height = image.height - width = image.width - - if width == 0 or height/width < 1.3: - return 'width: 100%' - else: - return 'height: 26.7cm' - - @register.filter def name_you(responses): """ Gets and formats given_name_1_you, given_name_2_you, given_name_3_you, last_name_you from responses """ diff --git a/edivorce/apps/core/tests/test_api.py b/edivorce/apps/core/tests/test_api.py index 82eca245..bddb9951 100644 --- a/edivorce/apps/core/tests/test_api.py +++ b/edivorce/apps/core/tests/test_api.py @@ -44,8 +44,8 @@ class MockRedis: @override_settings(CLAMAV_ENABLED=False) class APITest(APITestCase): def setUp(self): - self.user = BceidUser.objects.create(user_guid='1234') - self.another_user = BceidUser.objects.create(user_guid='5678') + self.user = _get_or_create_user(user_guid='1234') + self.another_user = _get_or_create_user(user_guid='5678') self.client = APIClient() self.default_doc_type = 'MC' self.default_party_code = 0 @@ -53,10 +53,10 @@ class APITest(APITestCase): def test_get_documents(self): url = reverse('documents') response = self.client.get(url) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) response = self.client.post(url, {}) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.client.force_authenticate(self.user) response = self.client.get(url) @@ -195,7 +195,7 @@ class APITest(APITestCase): url = document.get_file_url() response = self.client.get(url) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.client.force_authenticate(self.another_user) response = self.client.get(url) @@ -246,7 +246,7 @@ class APITest(APITestCase): url = document.get_file_url() response = self.client.delete(url) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(Document.objects.count(), 1) self.client.force_authenticate(self.another_user) @@ -267,7 +267,7 @@ class APITest(APITestCase): 'rotation': 90 } response = self.client.put(url, data) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.client.force_authenticate(self.another_user) response = self.client.put(url, data) @@ -307,14 +307,12 @@ class APITest(APITestCase): @mock.patch.object(Redis, 'get', MockRedis.get) @mock.patch.object(Redis, 'delete', MockRedis.delete) @mock.patch.object(Redis, 'exists', MockRedis.exists) -@override_settings(AUTHENTICATION_BACKENDS=('edivorce.apps.core.authenticators.BCeIDAuthentication',)) -@modify_settings(MIDDLEWARE={'remove': 'edivorce.apps.core.middleware.bceid_middleware.BceidMiddleware', }) class GraphQLAPITest(GraphQLTestCase): GRAPHQL_URL = reverse('graphql') def setUp(self): - self.user = BceidUser.objects.create(user_guid='1234') - self.another_user = BceidUser.objects.create(user_guid='5678') + self.user = _get_or_create_user(user_guid='1234') + self.another_user = _get_or_create_user(user_guid='5678') self.default_doc_type = 'MC' self.default_party_code = 0 @@ -512,3 +510,10 @@ def _create_file(extension='jpg'): num_documents = Document.objects.count() new_file = SimpleUploadedFile(f'test_file_{num_documents + 1}.{extension}', b'test content') return new_file + + +def _get_or_create_user(user_guid): + try: + return BceidUser.objects.get(user_guid=user_guid) + except BceidUser.DoesNotExist: + return BceidUser.objects.create(user_guid=user_guid, username=user_guid) diff --git a/edivorce/apps/core/tests/test_efiling_hub.py b/edivorce/apps/core/tests/test_efiling_hub.py index d3c4f074..b289fe91 100644 --- a/edivorce/apps/core/tests/test_efiling_hub.py +++ b/edivorce/apps/core/tests/test_efiling_hub.py @@ -152,17 +152,11 @@ class EFilingHubTests(TransactionTestCase): self.assertTrue('transaction_id' in self.request.session) def test_bceid_get_current(self): - self.request.session['smgov_userguid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' + self.request.session['bcgov_userguid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' with self.settings(DEPLOYMENT_TYPE='prod'): bceid = self.hub._get_bceid(self.request) self.assertEqual(bceid, '70fc9ce1-0cd6-4170-b842-bbabb88452a9') - def test_bceid_get_local_fake(self): - self.request.session['fake_bceid_guid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' - with self.settings(DEPLOYMENT_TYPE='localdev'): - bceid = self.hub._get_bceid(self.request) - self.assertEqual(bceid, '70fc9ce1-0cd6-4170-b842-bbabb88452a9') - def test_bceid_anonymous_user(self): with self.settings(DEPLOYMENT_TYPE='prod'): bceid = self.hub._get_bceid(self.request) @@ -194,7 +188,7 @@ class EFilingHubTests(TransactionTestCase): @mock.patch('edivorce.apps.core.efilinghub.EFilingHub._get_api') def test_upload_success(self, mock_get_api): - self.request.session['smgov_userguid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' + self.request.session['bcgov_userguid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' with self.settings(DEPLOYMENT_TYPE='prod'): mock_get_api.side_effect = [ self._mock_response(text=json.dumps(INITIAL_DOC_UPLOAD_RESPONSE)), @@ -208,7 +202,7 @@ class EFilingHubTests(TransactionTestCase): @mock.patch('edivorce.apps.core.efilinghub.EFilingHub._get_api') def test_upload_failed_initial_upload(self, mock_get_api): - self.request.session['smgov_userguid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' + self.request.session['bcgov_userguid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' with self.settings(DEPLOYMENT_TYPE='prod'): mock_get_api.side_effect = [ self._mock_response(text=json.dumps(INITIAL_DOC_UPLOAD_RESPONSE), status=401), @@ -220,7 +214,7 @@ class EFilingHubTests(TransactionTestCase): @mock.patch('edivorce.apps.core.efilinghub.EFilingHub._get_api') def test_upload_failed_generate_url(self, mock_get_api): - self.request.session['smgov_userguid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' + self.request.session['bcgov_userguid'] = '70fc9ce1-0cd6-4170-b842-bbabb88452a9' with self.settings(DEPLOYMENT_TYPE='prod'): mock_get_api.side_effect = [ self._mock_response(text=json.dumps(INITIAL_DOC_UPLOAD_RESPONSE)), diff --git a/edivorce/apps/core/urls.py b/edivorce/apps/core/urls.py index 8a3845c5..66ec0d6d 100644 --- a/edivorce/apps/core/urls.py +++ b/edivorce/apps/core/urls.py @@ -1,7 +1,7 @@ from django.conf.urls import url from django.urls import path -from .views import main, system, pdf, api, localdev +from .views import main, system, pdf, api urlpatterns = [ # url(r'^guide$', styleguide.guide), @@ -13,10 +13,7 @@ urlpatterns = [ # we add an extra 'x' to the file extension so the siteminder proxy doesn't treat it as an image path('api/documents///x//', api.DocumentView.as_view(), name='document'), - # url(r'^login/headers$', system.headers), - - url(r'^login$', main.login, name="login"), - url(r'^bceid$', localdev.bceid, name="bceid"), + url(r'^signin$', main.signin, name="signin"), url(r'^register$', main.register, name="register"), url(r'^register_sc$', main.register_sc, name="register_sc"), url(r'^logout$', main.logout, name="logout"), diff --git a/edivorce/apps/core/views/localdev.py b/edivorce/apps/core/views/localdev.py deleted file mode 100644 index 86cd7193..00000000 --- a/edivorce/apps/core/views/localdev.py +++ /dev/null @@ -1,32 +0,0 @@ -import uuid -import binascii -from encodings.utf_8 import decode -from django.conf import settings -from django.shortcuts import render, redirect -from django.views.decorators.csrf import csrf_exempt - - -@csrf_exempt -def bceid(request): - """ fake bceid login for developer workstation environment """ - if request.method == "POST": - login_name = request.POST.get('user', '') - password = request.POST.get('password', '') - - # just in case anyone from the general public discovers the dev server - # make sure they don't accidentally login and think this is production - if password.lower() != 'divorce': - return redirect(settings.PROXY_BASE_URL + settings.FORCE_SCRIPT_NAME[:-1] + '/bceid') - - # convert the login name to a guid - hex_name = decode(binascii.hexlify(str.encode(login_name)))[0] - fake_guid = hex_name.rjust(32, '0') - - # save the guid in a session variable - request.session['login_name'] = login_name - request.session['fake_bceid_guid'] = fake_guid - - return redirect(settings.PROXY_BASE_URL + settings.FORCE_SCRIPT_NAME[:-1] + '/login') - - else: - return render(request, 'localdev/bceid.html') diff --git a/edivorce/apps/core/views/main.py b/edivorce/apps/core/views/main.py index a2a3b388..04ce4532 100644 --- a/edivorce/apps/core/views/main.py +++ b/edivorce/apps/core/views/main.py @@ -5,9 +5,10 @@ from django.contrib import messages from django.shortcuts import render, redirect from django.urls import reverse from django.utils import timezone +from django.contrib.auth.decorators import login_required from edivorce.apps.core.utils.derived import get_derived_data -from ..decorators import bceid_required, intercept, prequal_completed +from ..decorators import intercept, prequal_completed from ..utils.cso_filing import file_documents, forms_to_file from ..utils.question_step_mapping import list_of_registries from ..utils.step_completeness import get_error_dict, get_missed_question_keys, get_step_completeness, is_complete, get_formatted_incomplete_list @@ -25,14 +26,10 @@ def home(request): """ This is the homepage """ - # HTTP_SM_USER is available on both unsecure and secure pages. - # If it has a value then we know the user is logged into BCeID/siteminder - siteminder_is_authenticated = request.META.get('HTTP_SM_USER', '') != '' - # if the user is returning from BCeID registration, then log them in to the site - if siteminder_is_authenticated and request.session.get('went_to_register', False): + if request.user.is_authenticated and request.session.get('went_to_register', False): request.session['went_to_register'] = False - return redirect(settings.PROXY_BASE_URL + settings.FORCE_SCRIPT_NAME[:-1] + '/login') + return redirect('oidc_authentication_init') return render(request, 'intro.html', context={'hide_nav': True}) @@ -72,7 +69,7 @@ def success(request): if request.user.is_authenticated: return redirect(reverse('overview')) else: - return render(request, 'success.html', context={'register_url': settings.REGISTER_URL,'register_sc_url': settings.REGISTER_SC_URL}) + return render(request, 'success.html', context={'register_url': settings.REGISTER_BCEID_URL,'register_sc_url': settings.REGISTER_BCSC_URL}) return redirect(reverse('incomplete')) @@ -103,7 +100,7 @@ def register(request): return render(request, 'localdev/register.html') request.session['went_to_register'] = True - return redirect(settings.REGISTER_URL) + return redirect(settings.REGISTER_BCEID_URL) def register_sc(request): """ @@ -113,38 +110,16 @@ def register_sc(request): return render(request, 'localdev/register.html') request.session['went_to_register'] = True - return redirect(settings.REGISTER_SC_URL) - -def login(request): - """ - This page is proxy-protected by Siteminder. Users who are not - logged into BCeID will get a login page. Users who are logged into - BCeID will be redirected to the dashboard - """ - if settings.DEPLOYMENT_TYPE in ['localdev', 'minishift'] and not request.session.get('fake_bceid_guid'): - return redirect(settings.PROXY_BASE_URL + settings.FORCE_SCRIPT_NAME[:-1] + '/bceid') + return redirect(settings.REGISTER_BCSC_URL) +def signin(request): if not request.user.is_authenticated: - # Fix for weird siteminder behaviour...... - # If a user is logged into an IDIR then they can see the login page but - # the SMGOV headers are missing. If this is the case, then log them out - # of their IDIR, and redirect them back to here again.... - - # FUTURE DEV NOTE: The DC elements of HTTP_SM_USERDN header will tell us - # exactly how the user is logged in. But it doesn't seem like a very - # good idea at this time to rely on this magic string. e.g. CN=Smith\, - # John,OU=Users,OU=Attorney General,OU=BCGOV,DC=idir,DC=BCGOV - - if request.GET.get('noretry', '') != 'true': - return redirect(settings.LOGOUT_URL_TEMPLATE % ( - settings.PROXY_BASE_URL, - settings.FORCE_SCRIPT_NAME[:-1] + '/login%3Fnoretry=true')) - return render(request, '407.html') - if timezone.now() - request.user.last_login > datetime.timedelta(minutes=1): - request.user.last_login = timezone.now() - request.user.save() + ## I think Django might be doing this automatically now that we have switched to mozilla-django-oidc? + #if timezone.now() - request.user.last_login > datetime.timedelta(minutes=1): + # request.user.last_login = timezone.now() + # request.user.save() copy_session_to_db(request, request.user) @@ -165,7 +140,7 @@ def logout(request): return response -@bceid_required +@login_required @prequal_completed @intercept def overview(request): @@ -193,7 +168,7 @@ def overview(request): return response -@bceid_required +@login_required @prequal_completed def dashboard_nav(request, nav_step): """ @@ -225,13 +200,13 @@ def dashboard_nav(request, nav_step): return render(request, template_name=template_name, context=responses_dict) -@bceid_required +@login_required @prequal_completed def submit_initial_files(request): return _submit_files(request, initial=True) -@bceid_required +@login_required @prequal_completed def submit_final_files(request): return _submit_files(request, initial=False) @@ -254,7 +229,7 @@ def _submit_files(request, initial=False): return redirect(reverse('dashboard_nav', kwargs={'nav_step': next_page}), context=responses_dict) -@bceid_required +@login_required @prequal_completed def question(request, step, sub_step=None): """ @@ -326,7 +301,7 @@ def contact(request): return render(request, 'contact-us.html', context={'active_page': 'contact'}) -@bceid_required +@login_required def intercept_page(request): """ On intercept, show the Orders page to get the requested orders before the diff --git a/edivorce/apps/core/views/pdf.py b/edivorce/apps/core/views/pdf.py index 463f3ec4..0fc3bb07 100644 --- a/edivorce/apps/core/views/pdf.py +++ b/edivorce/apps/core/views/pdf.py @@ -5,10 +5,10 @@ import json from django.conf import settings from django.http import HttpResponse from django.template.loader import render_to_string +from django.contrib.auth.decorators import login_required import requests -from ..decorators import bceid_required from ..models import Document from ..utils.derived import get_derived_data from ..utils.user_response import get_data_for_user @@ -16,7 +16,7 @@ from ..utils.user_response import get_data_for_user EXHIBITS = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'[::-1]) -@bceid_required +@login_required def form(request, form_number): """ View for rendering PDF's and previews """ @@ -111,7 +111,7 @@ def __add_claimant_info(responses, claimant): return responses -@bceid_required +@login_required def images_to_pdf(request, doc_type, party_code): documents = Document.objects.filter( bceid_user=request.user, doc_type=doc_type, party_code=party_code) diff --git a/edivorce/apps/core/views/system.py b/edivorce/apps/core/views/system.py index c6bf7a95..768f1400 100644 --- a/edivorce/apps/core/views/system.py +++ b/edivorce/apps/core/views/system.py @@ -13,10 +13,6 @@ def health(request): # pylint: disable=unused-argument return HttpResponse(Question.objects.count()) -def headers(request): - return render(request, 'localdev/debug.html') - - def current(request): """ Debug tool usable in dev and test environments, available at /current diff --git a/edivorce/apps/poc/urls.py b/edivorce/apps/poc/urls.py index 0567ac76..ae508eac 100644 --- a/edivorce/apps/poc/urls.py +++ b/edivorce/apps/poc/urls.py @@ -1,12 +1,12 @@ from django.conf.urls import url +from django.contrib.auth.decorators import login_required from edivorce.apps.poc import views -from ..core.decorators import bceid_required urlpatterns = [ - url(r'scan', bceid_required(views.UploadScan.as_view()), name="poc-scan"), - url(r'hub', bceid_required(views.EfilingHubUpload.as_view()), name="poc-hub"), - url(r'storage/doc/(?P\d+)', bceid_required(views.view_document_file), name="poc-storage-download"), - url(r'storage/delete/(?P\d+)', bceid_required(views.UploadStorageDelete.as_view()), name="poc-storage-delete"), - url(r'storage', bceid_required(views.UploadStorage.as_view()), name="poc-storage"), + url(r'scan', login_required(views.UploadScan.as_view()), name="poc-scan"), + url(r'hub', login_required(views.EfilingHubUpload.as_view()), name="poc-hub"), + url(r'storage/doc/(?P\d+)', login_required(views.view_document_file), name="poc-storage-download"), + url(r'storage/delete/(?P\d+)', login_required(views.UploadStorageDelete.as_view()), name="poc-storage-delete"), + url(r'storage', login_required(views.UploadStorage.as_view()), name="poc-storage"), ] \ No newline at end of file diff --git a/edivorce/settings/base.py b/edivorce/settings/base.py index b1b5e6e3..d622e194 100644 --- a/edivorce/settings/base.py +++ b/edivorce/settings/base.py @@ -11,6 +11,8 @@ https://docs.djangoproject.com/en/1.8/ref/settings/ """ import os + +from django.urls import reverse_lazy from environs import Env from unipath import Path @@ -45,6 +47,7 @@ INSTALLED_APPS = ( 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', + 'mozilla_django_oidc', # Load after auth 'rest_framework', 'debug_toolbar', 'corsheaders', @@ -71,11 +74,16 @@ MIDDLEWARE = ( 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'edivorce.apps.core.middleware.bceid_middleware.BceidMiddleware', 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', ) +AUTH_USER_MODEL = 'core.BceidUser' + +AUTHENTICATION_BACKENDS = ( + 'edivorce.apps.core.middleware.keycloak.EDivorceKeycloakBackend', +) + ROOT_URLCONF = 'edivorce.urls' TEMPLATES = [ @@ -101,7 +109,8 @@ WSGI_APPLICATION = 'wsgi.application' # by presence of Basic Auth headers REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ - 'edivorce.apps.core.authenticators.BCeIDAuthentication', + 'mozilla_django_oidc.contrib.drf.OIDCAuthentication', + 'rest_framework.authentication.SessionAuthentication' ] } @@ -117,7 +126,7 @@ LOGGING = { 'loggers': { '': { 'handlers': ['console'], - 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), + 'level': env('DJANGO_LOG_LEVEL', 'INFO'), }, }, } @@ -175,10 +184,6 @@ DEBUG_TOOLBAR_CONFIG = { SECURE_BROWSER_XSS_FILTER = True -LOGOUT_URL = '/accounts/logout/' - -# CLAMAV settings - # eFiling Hub settings EFILING_HUB_TOKEN_BASE_URL = env('EFILING_HUB_TOKEN_BASE_URL', 'https://efiling.gov.bc.ca') EFILING_HUB_REALM = env('EFILING_HUB_REALM', 'abc') @@ -187,3 +192,13 @@ EFILING_HUB_CLIENT_SECRET = env('EFILING_HUB_CLIENT_SECRET', 'abc') EFILING_HUB_API_BASE_URL = env('EFILING_HUB_API_BASE_URL', 'https://efiling.gov.bc.ca') EFILING_BCEID = env.dict('EFILING_BCEID', '', subcast=str) + +# Keycloak OpenID Connect settings +# Provided by mozilla-django-oidc +LOGIN_URL = reverse_lazy('oidc_authentication_init') +OIDC_RP_SIGN_ALGO = 'RS256' +OIDC_RP_SCOPES = 'openid email profile' +# this is needed to bypass the Keycloak login screen +OIDC_AUTH_REQUEST_EXTRA_PARAMS = {'kc_idp_hint': 'bceid'} +OIDC_RP_CLIENT_SECRET = env('KEYCLOAK_CLIENT_SECRET', '') +OIDC_OP_LOGOUT_URL_METHOD = 'edivorce.apps.core.middleware.keycloak.keycloak_logout' diff --git a/edivorce/settings/local.py b/edivorce/settings/local.py index 7eb8b98d..99c38713 100644 --- a/edivorce/settings/local.py +++ b/edivorce/settings/local.py @@ -21,16 +21,14 @@ WEASYPRINT_IMAGE_LOOPBACK = 'http://host.docker.internal:8000' WEASYPRINT_CSS_LOOPBACK = WEASYPRINT_IMAGE_LOOPBACK DEPLOYMENT_TYPE = 'localdev' -REGISTER_URL = '#' -REGISTER_SC_URL ='#' +REGISTER_BCEID_URL = '#' +REGISTER_BCSC_URL = '#' PROXY_BASE_URL = '' SASS_PROCESSOR_ENABLED = True SASS_PROCESSOR_ROOT = PROJECT_ROOT + '/edivorce/apps/core/static' SASS_OUTPUT_STYLE = 'compressed' CORS_ORIGIN_ALLOW_ALL = True -LOGOUT_URL = '/accounts/logout/' - # CLAMAV settings CLAMAV_ENABLED = env.bool('CLAMAV_ENABLED', True) CLAMAV_TCP_PORT = env.int('CLAMAV_TCP_PORT', 3310) @@ -41,3 +39,13 @@ REDIS_HOST = env('REDIS_HOST', 'localhost') REDIS_PORT = env.int('REDIS_PORT', 6379) REDIS_DB = env('REDIS_DB', '') REDIS_PASSWORD = env('REDIS_PASSWORD', '') + +# Keycloak OpenID Connect settings +# Provided by mozilla-django-oidc +OIDC_OP_JWKS_ENDPOINT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/certs' +OIDC_OP_AUTHORIZATION_ENDPOINT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/auth' +OIDC_OP_TOKEN_ENDPOINT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/token' +OIDC_OP_USER_ENDPOINT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/userinfo' +KEYCLOAK_LOGOUT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/logout' +OIDC_RP_CLIENT_ID = 'edivorce-app' +LOGIN_REDIRECT_URL = '/signin' diff --git a/edivorce/settings/openshift.py b/edivorce/settings/openshift.py index 84e9db7d..8c8e8045 100644 --- a/edivorce/settings/openshift.py +++ b/edivorce/settings/openshift.py @@ -1,5 +1,7 @@ +from mozilla_django_oidc import utils from .base import * + def openshift_db_config(): ''' Database config based on the django-ex openshift sample application @@ -45,42 +47,66 @@ COMPRESS_OFFLINE = True # # See nginx-proxy/conf.d/server.conf for related settings # -DEPLOYMENT_TYPE = os.getenv('ENVIRONMENT_TYPE') +DEPLOYMENT_TYPE = env('ENVIRONMENT_TYPE', 'unittest') PROXY_URL_PREFIX = '' PROXY_BASE_URL = os.getenv('PROXY_BASE_URL', 'https://justice.gov.bc.ca') +if DEPLOYMENT_TYPE in ['dev', 'unittest']: + DEBUG = True + # Keycloak OpenID Connect settings + OIDC_OP_JWKS_ENDPOINT = 'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/tz0e228w/protocol/openid-connect/certs' + OIDC_OP_AUTHORIZATION_ENDPOINT = 'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/tz0e228w/protocol/openid-connect/auth' + OIDC_OP_TOKEN_ENDPOINT = 'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/tz0e228w/protocol/openid-connect/token' + OIDC_OP_USER_ENDPOINT = 'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/tz0e228w/protocol/openid-connect/userinfo' + KEYCLOAK_LOGOUT = 'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/tz0e228w/protocol/openid-connect/logout' + OIDC_RP_CLIENT_ID = 'e-divorce-app' + if DEPLOYMENT_TYPE == 'dev': PROXY_URL_PREFIX = os.getenv('PROXY_URL_PREFIX', '/divorce') - DEBUG = True CSRF_COOKIE_AGE = None SESSION_COOKIE_AGE = 3600 - REGISTER_URL = 'https://www.test.bceid.ca/directories/bluepages/details.aspx?serviceID=5522' - REGISTER_SC_URL = 'https://logontest7.gov.bc.ca/clp-cgi/fed/fedLaunch.cgi?partner=fed38&partnerList=fed38&flags=0001:0,7&TARGET=http://dev.justice.gov.bc.ca/divorce/login' - LOGOUT_URL_TEMPLATE = 'https://logontest7.gov.bc.ca/clp-cgi/logoff.cgi?returl=%s%s&retnow=1' - LOGOUT_URL = LOGOUT_URL_TEMPLATE % (PROXY_BASE_URL, PROXY_URL_PREFIX) + REGISTER_BCEID_URL = 'https://www.test.bceid.ca/directories/bluepages/details.aspx?serviceID=5522' + REGISTER_BCSC_URL = 'https://logontest7.gov.bc.ca/clp-cgi/fed/fedLaunch.cgi?partner=fed38&partnerList=fed38&flags=0001:0,7&TARGET=http://dev.justice.gov.bc.ca/divorce/oidc/authenticate' if DEPLOYMENT_TYPE == 'test': PROXY_URL_PREFIX = os.getenv('PROXY_URL_PREFIX', '/divorce') - REGISTER_URL = 'https://www.test.bceid.ca/directories/bluepages/details.aspx?serviceID=5521' - REGISTER_SC_URL = 'https://logontest7.gov.bc.ca/clp-cgi/fed/fedLaunch.cgi?partner=fed38&partnerList=fed38&flags=0001:0,7&TARGET=http://test.justice.gov.bc.ca/divorce/login' - LOGOUT_URL_TEMPLATE = 'https://logontest7.gov.bc.ca/clp-cgi/logoff.cgi?returl=%s%s&retnow=1' - LOGOUT_URL = LOGOUT_URL_TEMPLATE % (PROXY_BASE_URL, PROXY_URL_PREFIX) + REGISTER_BCEID_URL = 'https://www.test.bceid.ca/directories/bluepages/details.aspx?serviceID=5521' + REGISTER_BCSC_URL = 'https://logontest7.gov.bc.ca/clp-cgi/fed/fedLaunch.cgi?partner=fed38&partnerList=fed38&flags=0001:0,7&TARGET=http://test.justice.gov.bc.ca/divorce/oidc/authenticate' + # Keycloak OpenID Connect settings + OIDC_OP_JWKS_ENDPOINT = 'https://sso-test.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/certs' + OIDC_OP_AUTHORIZATION_ENDPOINT = 'https://sso-test.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/auth' + OIDC_OP_TOKEN_ENDPOINT = 'https://sso-test.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/token' + OIDC_OP_USER_ENDPOINT = 'https://sso-test.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/userinfo' + KEYCLOAK_LOGOUT = 'https://sso-test.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/logout' + OIDC_RP_CLIENT_ID = 'XXXXXXXX' if DEPLOYMENT_TYPE == 'prod': PROXY_URL_PREFIX = os.getenv('PROXY_URL_PREFIX', '/divorce') - REGISTER_URL = 'https://www.bceid.ca/directories/bluepages/details.aspx?serviceID=5203' - REGISTER_SC_URL = 'https://logon7.gov.bc.ca/clp-cgi/fed/fedLaunch.cgi?partner=fed49&partnerList=fed49&flags=0001:0,8&TARGET=http://justice.gov.bc.ca/divorce/login' - LOGOUT_URL_TEMPLATE = 'https://logon7.gov.bc.ca/clp-cgi/logoff.cgi?returl=%s%s&retnow=1' - LOGOUT_URL = LOGOUT_URL_TEMPLATE % (PROXY_BASE_URL, PROXY_URL_PREFIX) + REGISTER_BCEID_URL = 'https://www.bceid.ca/directories/bluepages/details.aspx?serviceID=5203' + REGISTER_BCSC_URL = 'https://logon7.gov.bc.ca/clp-cgi/fed/fedLaunch.cgi?partner=fed49&partnerList=fed49&flags=0001:0,8&TARGET=http://justice.gov.bc.ca/divorce/oidc/authenticate' + # Keycloak OpenID Connect settings + OIDC_OP_JWKS_ENDPOINT = 'https://sso.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/certs' + OIDC_OP_AUTHORIZATION_ENDPOINT = 'https://sso.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/auth' + OIDC_OP_TOKEN_ENDPOINT = 'https://sso.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/token' + OIDC_OP_USER_ENDPOINT = 'https://sso.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/userinfo' + KEYCLOAK_LOGOUT = 'https://sso.pathfinder.gov.bc.ca/auth/realms/XXXXXXXX/protocol/openid-connect/logout' + OIDC_RP_CLIENT_ID = 'XXXXXXXX' # Google Tag Manager (Production) GTM_ID = 'GTM-W4Z2SPS' if DEPLOYMENT_TYPE == 'minishift': DEBUG = True - REGISTER_URL = '#' - REGISTER_SC_URL ='#' + REGISTER_BCEID_URL = '#' + REGISTER_BCSC_URL = '#' PROXY_BASE_URL = '' + # Keycloak OpenID Connect settings + OIDC_OP_JWKS_ENDPOINT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/certs' + OIDC_OP_AUTHORIZATION_ENDPOINT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/auth' + OIDC_OP_TOKEN_ENDPOINT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/token' + OIDC_OP_USER_ENDPOINT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/userinfo' + KEYCLOAK_LOGOUT = 'http://localhost:8081/auth/realms/justice/protocol/openid-connect/logout' + OIDC_RP_CLIENT_ID = 'edivorce-app' # Internal Relative Urls FORCE_SCRIPT_NAME = PROXY_URL_PREFIX + '/' @@ -101,8 +127,8 @@ SESSION_EXPIRE_AT_BROWSER_CLOSE = True if DEPLOYMENT_TYPE != 'minishift': SESSION_COOKIE_PATH = PROXY_URL_PREFIX - SESSION_COOKIE_SECURE=True - CSRF_COOKIE_SECURE=True + SESSION_COOKIE_SECURE = True + CSRF_COOKIE_SECURE = True # CLAMAV settings CLAMAV_ENABLED = True @@ -113,4 +139,16 @@ CLAMAV_TCP_ADDR = os.getenv('CLAMAV_TCP_ADDR', 'clamav') REDIS_HOST = os.getenv('REDIS_HOST', 'redis') REDIS_PORT = 6379 REDIS_DB = '' -REDIS_PASSWORD = os.getenv('REDIS_PASSWORD', '') \ No newline at end of file +REDIS_PASSWORD = os.getenv('REDIS_PASSWORD', '') + +# Keycloak OpenID Connect settings +LOGIN_REDIRECT_URL = PROXY_URL_PREFIX + '/signin' + + +def monkey_absolutify(request, path): + return PROXY_BASE_URL + path + + +# monkey-patching mozilla_django_oidc.utils.absolutify so it doesn't +# return urls prefixed with 'http://edivorce-django:8080' on OpenShift +utils.absolutify = monkey_absolutify diff --git a/edivorce/urls.py b/edivorce/urls.py index ada0d674..b0e8ee6a 100644 --- a/edivorce/urls.py +++ b/edivorce/urls.py @@ -22,6 +22,8 @@ if settings.ENVIRONMENT in ['localdev', 'minishift']: urlpatterns.append(url(r'^404/$', main.page_not_found, {'exception': Exception()})) urlpatterns.append(url(r'^500/$', main.server_error)) +urlpatterns.append(url(r'^oidc/', include('mozilla_django_oidc.urls'))) + urlpatterns.append(url(r'^', include('edivorce.apps.core.urls'))) handler404 = main.page_not_found diff --git a/requirements.txt b/requirements.txt index 31d972b5..5fe43068 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,14 +1,18 @@ +-i https://pypi.org/simple aniso8601==7.0.0 +beautifulsoup4==4.9.3 certifi==2020.6.20 +cffi==1.14.2 chardet==3.0.4 clamd==1.0.2 -Django==2.2.15 +cryptography==3.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' django-appconf==1.0.4 django-compressor==2.4 django-cors-headers==3.5.0 django-crispy-forms==1.9.2 django-debug-toolbar==2.2 django-sass-processor==0.8 +django==2.2.15 djangorestframework==3.11.1 environs==8.0.0 graphene==2.1.8 @@ -17,22 +21,27 @@ graphql-core==2.3.2 graphql-relay==2.0.1 gunicorn==20.0.4 idna==2.10 +josepy==1.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' libsass==0.20.0 marshmallow==3.7.1 -Pillow==7.2.0 +mozilla-django-oidc==1.2.4 +pillow==7.2.0 promise==2.3 psycopg2==2.8.5 +pycparser==2.20; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +pyopenssl==19.1.0 python-dotenv==0.14.0 pytz==2020.1 rcssmin==1.0.6 redis==3.5.3 requests==2.24.0 rjsmin==1.1.0 -Rx==1.6.1 +rx==1.6.1 singledispatch==3.4.0.3 six==1.15.0 +soupsieve==2.0.1 sqlparse==0.3.1 -Unidecode==1.1.1 -Unipath==1.1 +unidecode==1.1.1 +unipath==1.1 urllib3==1.25.10 whitenoise==3.3.1 diff --git a/vue/src/components/Uploader/Uploader.vue b/vue/src/components/Uploader/Uploader.vue index 679761af..33bf10c6 100644 --- a/vue/src/components/Uploader/Uploader.vue +++ b/vue/src/components/Uploader/Uploader.vue @@ -32,6 +32,7 @@ :post-action="postAction" :input-id="inputId" name="file" + :headers="{ 'X-CSRFToken': getCSRFToken() }" :class="['drop-zone', dragging ? 'dragging' : '']" :data="inputKeys" @input-file="inputFile" @@ -186,7 +187,7 @@ }, pdfURL() { return `${this.$parent.proxyRootPath}pdf-images/${this.docType}/${this.party}/`; - }, + } }, methods: { inputFile(newFile, oldFile) { @@ -257,7 +258,7 @@ file: result, size: result.size, type: result.type, - compressed: true + compressed: true, }); }, error(err) { @@ -347,11 +348,12 @@ remove(file) { const urlbase = `${this.$parent.proxyRootPath}api/documents`; const encFilename = encodeURIComponent(file.name); + const token = this.getCSRFToken(); if (!file.error) { // we add an extra 'x' to the file extension so the siteminder proxy doesn't treat it as an image const url = `${urlbase}/${this.docType}/${this.party}/${encFilename}x/${file.size}/`; axios - .delete(url) + .delete(url, { headers: { "X-CSRFToken": token } }) .then((response) => { const pos = this.files.findIndex( (f) => f.docType === file.docType && f.size === file.size @@ -411,13 +413,15 @@ saveMetaData() { let allFiles = []; this.files.forEach((file) => { - allFiles.push({ - filename: file.name, - size: file.size, - width: file.width, - height: file.height, - rotation: rotateFix(file.rotation), - }); + if (!file.error) { + allFiles.push({ + filename: file.name, + size: file.size, + width: file.width, + height: file.height, + rotation: rotateFix(file.rotation), + }); + } }); const data = { docType: this.docType, @@ -447,14 +451,28 @@ console.log("error", error.message || error); // if there was an error it's probably because the upload isn't finished yet // mark the metadata as dirty so it will save metadata again + this.retries++; + this.isDirty = true; }); } }) .catch((error) => { this.showError("Error saving metadata"); console.log("error", error); - this.retries++; }); + }, + getCSRFToken() { + const name = "csrftoken"; + if (document.cookie && document.cookie !== "") { + const cookies = document.cookie.split(";"); + for (let i = 0; i < cookies.length; i++) { + const cookie = cookies[i].trim(); + if (cookie.substring(0, name.length + 1) === name + "=") { + return decodeURIComponent(cookie.substring(name.length + 1)); + } + } + } + return null; } }, created() {