Showing preview only (1,813K chars total). Download the full file or copy to clipboard to get everything.
Repository: malach-it/boruta-server
Branch: master
Commit: 0b879b9d49cc
Files: 669
Total size: 1.6 MB
Directory structure:
gitextract_c41fuwm_/
├── .credo.exs
├── .formatter.exs
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── deploy.yml
│ └── elixir.yml
├── .gitignore
├── .gitlab-ci.yml
├── .tool-versions
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Dockerfile.admin
├── Dockerfile.auth
├── Dockerfile.full
├── Dockerfile.gateway
├── GENERAL_TERMS_AND_CONDITIONS.md
├── LICENSE.md
├── README.md
├── ansible/
│ ├── .kube/
│ │ └── kubeconfig-k8s-boruta.yaml
│ ├── deploy.yml
│ ├── hosts
│ └── inventories/
│ ├── gke
│ ├── local
│ └── scaleway
├── apps/
│ ├── boruta_admin/
│ │ ├── .formatter.exs
│ │ ├── .gitignore
│ │ ├── assets/
│ │ │ ├── .browserslistrc
│ │ │ ├── .editorconfig
│ │ │ ├── .eslintrc.js
│ │ │ ├── .gitignore
│ │ │ ├── index.html
│ │ │ ├── jsconfig.json
│ │ │ ├── package.json
│ │ │ ├── postcss.config.js
│ │ │ ├── src/
│ │ │ │ ├── App.vue
│ │ │ │ ├── components/
│ │ │ │ │ ├── Breadcrumb.vue
│ │ │ │ │ ├── Feedback.vue
│ │ │ │ │ ├── Forms/
│ │ │ │ │ │ ├── BackendForm.vue
│ │ │ │ │ │ ├── ClientForm.vue
│ │ │ │ │ │ ├── FormErrors.vue
│ │ │ │ │ │ ├── GatewayScopesField.vue
│ │ │ │ │ │ ├── IdentityProviderField.vue
│ │ │ │ │ │ ├── IdentityProviderForm.vue
│ │ │ │ │ │ ├── OrganizationForm.vue
│ │ │ │ │ │ ├── OrganizationsField.vue
│ │ │ │ │ │ ├── RoleForm.vue
│ │ │ │ │ │ ├── RolesField.vue
│ │ │ │ │ │ ├── ScopesField.vue
│ │ │ │ │ │ ├── ScopesFieldByName.vue
│ │ │ │ │ │ ├── TextEditor.vue
│ │ │ │ │ │ ├── UpstreamForm.vue
│ │ │ │ │ │ └── UserForm.vue
│ │ │ │ │ ├── Header.vue
│ │ │ │ │ ├── Toaster.vue
│ │ │ │ │ └── VerifiableCredentialClaim.vue
│ │ │ │ ├── main.js
│ │ │ │ ├── models/
│ │ │ │ │ ├── backend.model.js
│ │ │ │ │ ├── business-log-stats.model.js
│ │ │ │ │ ├── client.model.js
│ │ │ │ │ ├── email-template.model.js
│ │ │ │ │ ├── error-template.model.js
│ │ │ │ │ ├── identity-provider.model.js
│ │ │ │ │ ├── key-pair.model.js
│ │ │ │ │ ├── organization.model.js
│ │ │ │ │ ├── request-log-stats.model.js
│ │ │ │ │ ├── role.model.js
│ │ │ │ │ ├── scope.model.js
│ │ │ │ │ ├── template.model.js
│ │ │ │ │ ├── upstream.model.js
│ │ │ │ │ ├── user.model.js
│ │ │ │ │ └── utils.js
│ │ │ │ ├── router.js
│ │ │ │ ├── services/
│ │ │ │ │ ├── configuration-file.service.js
│ │ │ │ │ └── oauth.service.js
│ │ │ │ ├── store.js
│ │ │ │ └── views/
│ │ │ │ ├── BadRequest.vue
│ │ │ │ ├── Clients/
│ │ │ │ │ ├── Client.vue
│ │ │ │ │ ├── ClientList.vue
│ │ │ │ │ ├── EditClient.vue
│ │ │ │ │ ├── KeyPairList.vue
│ │ │ │ │ └── NewClient.vue
│ │ │ │ ├── Clients.vue
│ │ │ │ ├── Configuration/
│ │ │ │ │ ├── ConfigurationFileUpload.vue
│ │ │ │ │ ├── EditBadRequestTemplate.vue
│ │ │ │ │ ├── EditForbiddenTemplate.vue
│ │ │ │ │ ├── EditInternalServerErrorTemplate.vue
│ │ │ │ │ ├── EditNotFoundTemplate.vue
│ │ │ │ │ └── ErrorTemplateList.vue
│ │ │ │ ├── Configuration.vue
│ │ │ │ ├── Dashboard/
│ │ │ │ │ ├── BusinessEvents.vue
│ │ │ │ │ └── Requests.vue
│ │ │ │ ├── Dashboard.vue
│ │ │ │ ├── Home.vue
│ │ │ │ ├── IdentityProviders/
│ │ │ │ │ ├── BackendList.vue
│ │ │ │ │ ├── Backends/
│ │ │ │ │ │ ├── Backend.vue
│ │ │ │ │ │ ├── EditConfirmationInstructionsEmailTemplate.vue
│ │ │ │ │ │ ├── EditResetPasswordInstructionsEmailTemplate.vue
│ │ │ │ │ │ └── EditTxCodeEmailTemplate.vue
│ │ │ │ │ ├── Backends.vue
│ │ │ │ │ ├── EditBackend.vue
│ │ │ │ │ ├── EditCredentialOfferTemplate.vue
│ │ │ │ │ ├── EditCrossDevicePresentationTemplate.vue
│ │ │ │ │ ├── EditEditResetPasswordTemplate.vue
│ │ │ │ │ ├── EditEditUserTemplate.vue
│ │ │ │ │ ├── EditIdentityProvider.vue
│ │ │ │ │ ├── EditLayoutTemplate.vue
│ │ │ │ │ ├── EditNewChooseSessionTemplate.vue
│ │ │ │ │ ├── EditNewConfirmationTemplate.vue
│ │ │ │ │ ├── EditNewConsentTemplate.vue
│ │ │ │ │ ├── EditNewResetPasswordTemplate.vue
│ │ │ │ │ ├── EditOrganization.vue
│ │ │ │ │ ├── EditRegistrationTemplate.vue
│ │ │ │ │ ├── EditSessionTemplate.vue
│ │ │ │ │ ├── EditTotpAuthenticationTemplate.vue
│ │ │ │ │ ├── EditTotpRegistrationTemplate.vue
│ │ │ │ │ ├── EditUser.vue
│ │ │ │ │ ├── EditWebauthnAuthenticationTemplate.vue
│ │ │ │ │ ├── EditWebauthnRegistrationTemplate.vue
│ │ │ │ │ ├── IdentityProvider.vue
│ │ │ │ │ ├── IdentityProviderList.vue
│ │ │ │ │ ├── NewBackend.vue
│ │ │ │ │ ├── NewIdentityProvider.vue
│ │ │ │ │ ├── NewOrganization.vue
│ │ │ │ │ ├── NewUser.vue
│ │ │ │ │ ├── OrganizationList.vue
│ │ │ │ │ ├── Organizations.vue
│ │ │ │ │ ├── UserImport.vue
│ │ │ │ │ ├── UserList.vue
│ │ │ │ │ └── Users.vue
│ │ │ │ ├── IdentityProviders.vue
│ │ │ │ ├── Layouts/
│ │ │ │ │ └── Main.vue
│ │ │ │ ├── NotFound.vue
│ │ │ │ ├── OauthCallback.vue
│ │ │ │ ├── Roles/
│ │ │ │ │ ├── EditRole.vue
│ │ │ │ │ ├── NewRole.vue
│ │ │ │ │ ├── Role.vue
│ │ │ │ │ └── RoleList.vue
│ │ │ │ ├── Roles.vue
│ │ │ │ ├── Scopes/
│ │ │ │ │ └── ScopeList.vue
│ │ │ │ ├── Scopes.vue
│ │ │ │ ├── Upstreams/
│ │ │ │ │ ├── EditUpstream.vue
│ │ │ │ │ ├── NewUpstream.vue
│ │ │ │ │ ├── Upstream.vue
│ │ │ │ │ └── UpstreamList.vue
│ │ │ │ └── Upstreams.vue
│ │ │ ├── tests/
│ │ │ │ └── unit/
│ │ │ │ └── .eslintrc.js
│ │ │ └── vite.config.js
│ │ ├── config/
│ │ │ ├── config.exs
│ │ │ ├── dev.exs
│ │ │ ├── prod.exs
│ │ │ └── test.exs
│ │ ├── lib/
│ │ │ ├── boruta_admin/
│ │ │ │ ├── application.ex
│ │ │ │ ├── configuration_loader/
│ │ │ │ │ └── schema.ex
│ │ │ │ ├── configuration_loader.ex
│ │ │ │ ├── configurations/
│ │ │ │ │ └── configuration.ex
│ │ │ │ ├── configurations.ex
│ │ │ │ ├── logs.ex
│ │ │ │ ├── release.ex
│ │ │ │ └── repo.ex
│ │ │ ├── boruta_admin.ex
│ │ │ ├── boruta_admin_web/
│ │ │ │ ├── controllers/
│ │ │ │ │ ├── backend_controller.ex
│ │ │ │ │ ├── boruta/
│ │ │ │ │ │ ├── client_controller.ex
│ │ │ │ │ │ └── scope_controller.ex
│ │ │ │ │ ├── configuration_controller.ex
│ │ │ │ │ ├── fallback_controller.ex
│ │ │ │ │ ├── identity_provider_controller.ex
│ │ │ │ │ ├── key_pair_controller.ex
│ │ │ │ │ ├── logs_controller.ex
│ │ │ │ │ ├── organization_controller.ex
│ │ │ │ │ ├── page_controller.ex
│ │ │ │ │ ├── role_controller.ex
│ │ │ │ │ ├── upstream_controller.ex
│ │ │ │ │ └── user_controller.ex
│ │ │ │ ├── endpoint.ex
│ │ │ │ ├── gettext.ex
│ │ │ │ ├── plugs/
│ │ │ │ │ ├── authorization.ex
│ │ │ │ │ └── logger.ex
│ │ │ │ ├── router.ex
│ │ │ │ ├── telemetry.ex
│ │ │ │ ├── templates/
│ │ │ │ │ ├── error/
│ │ │ │ │ │ ├── 404.html.eex
│ │ │ │ │ │ └── 500.html.eex
│ │ │ │ │ └── page/
│ │ │ │ │ └── admin.html.eex
│ │ │ │ └── views/
│ │ │ │ ├── backend_view.ex
│ │ │ │ ├── changeset_view.ex
│ │ │ │ ├── client_view.ex
│ │ │ │ ├── configuration_view.ex
│ │ │ │ ├── error_helpers.ex
│ │ │ │ ├── error_view.ex
│ │ │ │ ├── identity_provider_view.ex
│ │ │ │ ├── key_pair_view.ex
│ │ │ │ ├── logs_view.ex
│ │ │ │ ├── organization_view.ex
│ │ │ │ ├── page_view.ex
│ │ │ │ ├── role_view.ex
│ │ │ │ ├── scope_view.ex
│ │ │ │ ├── upstream_view.ex
│ │ │ │ └── user_view.ex
│ │ │ └── boruta_admin_web.ex
│ │ ├── mix.exs
│ │ ├── priv/
│ │ │ ├── examples/
│ │ │ │ └── configuration.yml
│ │ │ ├── gettext/
│ │ │ │ ├── en/
│ │ │ │ │ └── LC_MESSAGES/
│ │ │ │ │ └── errors.po
│ │ │ │ └── errors.pot
│ │ │ ├── repo/
│ │ │ │ ├── migrations/
│ │ │ │ │ ├── .formatter.exs
│ │ │ │ │ └── 20240508054424_create_configurations.exs
│ │ │ │ └── seeds.exs
│ │ │ └── test/
│ │ │ └── configuration_files/
│ │ │ ├── bad_backend_configuration.yml
│ │ │ ├── bad_client_configuration.yml
│ │ │ ├── bad_error_template_configuration.yml
│ │ │ ├── bad_identity_provider_configuration.yml
│ │ │ ├── bad_organization_configuration.yml
│ │ │ ├── bad_role_configuration.yml
│ │ │ ├── bad_scope_configuration.yml
│ │ │ └── full_configuration.yml
│ │ └── test/
│ │ ├── boruta_admin/
│ │ │ └── configuration_loader_test.exs
│ │ ├── boruta_admin_web/
│ │ │ ├── controllers/
│ │ │ │ ├── backend_controller_test.exs
│ │ │ │ ├── client_controller_test.exs
│ │ │ │ ├── configuration_controller_test.exs
│ │ │ │ ├── identity_provider_controller_test.exs
│ │ │ │ ├── key_pair_controller_test.exs
│ │ │ │ ├── logs_controller_test.exs
│ │ │ │ ├── organization_controller_test.exs
│ │ │ │ ├── page_controller_test.exs
│ │ │ │ ├── role_controller_test.exs
│ │ │ │ ├── scope_controller_test.exs
│ │ │ │ ├── upstream_controller_test.exs
│ │ │ │ └── user_controller_test.exs
│ │ │ └── views/
│ │ │ ├── error_view_test.exs
│ │ │ └── page_view_test.exs
│ │ ├── data/
│ │ │ ├── import_users_hashed_password_valid.csv
│ │ │ ├── import_users_password_custom_headers_valid.csv
│ │ │ ├── import_users_password_invalid.csv
│ │ │ └── import_users_password_valid.csv
│ │ ├── support/
│ │ │ ├── boruta_factory.ex
│ │ │ ├── boruta_identity_factory.ex
│ │ │ ├── conn_case.ex
│ │ │ └── data_case.ex
│ │ └── test_helper.exs
│ ├── boruta_auth/
│ │ ├── .formatter.exs
│ │ ├── .gitignore
│ │ ├── config/
│ │ │ ├── config.exs
│ │ │ ├── dev.exs
│ │ │ ├── prod.exs
│ │ │ └── test.exs
│ │ ├── lib/
│ │ │ ├── boruta_auth/
│ │ │ │ ├── application.ex
│ │ │ │ ├── key_pairs/
│ │ │ │ │ └── schemas/
│ │ │ │ │ └── key_pair.ex
│ │ │ │ ├── key_pairs.ex
│ │ │ │ ├── log_rotate.ex
│ │ │ │ ├── repo.ex
│ │ │ │ └── scheduler.ex
│ │ │ └── boruta_auth.ex
│ │ ├── mix.exs
│ │ ├── priv/
│ │ │ └── repo/
│ │ │ ├── boruta.seeds.exs
│ │ │ └── migrations/
│ │ │ ├── 20201129024828_create_boruta.exs
│ │ │ ├── 20210114202055_usec_timestamps.exs
│ │ │ ├── 20210202095024_add_key_pair_to_clients.exs
│ │ │ ├── 20210301123331_add_label_to_scopes.exs
│ │ │ ├── 20210514211510_add_default_redirect_uris_to_clients.exs
│ │ │ ├── 20210919174149_openid_connect.exs
│ │ │ ├── 20210919174150_clients_refresh_tokens.exs
│ │ │ ├── 20211013161324_clients_public_revoke.exs
│ │ │ ├── 20220113221532_store_previous_token.exs
│ │ │ ├── 20220603211852_id_token_signature_alg_configuration.exs
│ │ │ ├── 20220625203958_confidential_clients.exs
│ │ │ ├── 20220824105115_refresh_token_rotation.exs
│ │ │ ├── 20221025084535_authorization_code_chains.exs
│ │ │ ├── 20221122131429_client_authentication_methods.exs
│ │ │ ├── 20221129120152_signed_userinfo_response.exs
│ │ │ ├── 20230506151359_optional_public_key_for_oauth_clients.exs
│ │ │ ├── 20230514134306_clients_jwks_uri.exs
│ │ │ ├── 20230515093131_create_key_pairs.exs
│ │ │ ├── 20230515152140_client_id_token_kid.exs
│ │ │ ├── 20231217091349_add_metadata_to_clients.exs
│ │ │ ├── 20231217144905_oid4vci_implementation.exs
│ │ │ ├── 20240127081327_siopv2_implementation.exs
│ │ │ ├── 20240321101558_dpop_implementation.exs
│ │ │ ├── 20240417052138_par_implementation.exs
│ │ │ ├── 20240506083712_c_nonce_implementation.exs
│ │ │ ├── 20240812111902_defered_credentials.exs
│ │ │ ├── 20240824191208_clients_did.exs
│ │ │ ├── 20240908082918_verifiable_presentation_definitions.exs
│ │ │ ├── 20240914084657_clients_response_mode.exs
│ │ │ ├── 20241021132955_clients_key_pair_types.exs
│ │ │ ├── 20241209110846_tokens_tx_code.exs
│ │ │ ├── 20241220104923_clients_signatures_adapters.exs
│ │ │ ├── 20250315084213_fix_oauth_clients_did.exs
│ │ │ ├── 20250413070457_agent_credentials.exs
│ │ │ ├── 20250524160749_public_client_id.exs
│ │ │ ├── 20260324152715_codes_response_type.exs
│ │ │ ├── 20260324152716_code_metadata_policy.exs
│ │ │ ├── 20260330112657_siopv2_encryption.exs
│ │ │ └── 20260428121802_requested_scope.exs
│ │ └── test/
│ │ ├── boruta_auth/
│ │ │ └── key_pairs_test.exs
│ │ └── test_helper.exs
│ ├── boruta_gateway/
│ │ ├── .formatter.exs
│ │ ├── .gitignore
│ │ ├── config/
│ │ │ ├── config.exs
│ │ │ ├── dev.exs
│ │ │ ├── prod.exs
│ │ │ └── test.exs
│ │ ├── lib/
│ │ │ ├── boruta_gateway/
│ │ │ │ ├── application.ex
│ │ │ │ ├── configuration_loader.ex
│ │ │ │ ├── configuration_schemas/
│ │ │ │ │ └── gateway.ex
│ │ │ │ ├── gateway_pipeline.ex
│ │ │ │ ├── logger.ex
│ │ │ │ ├── microgateway_pipeline.ex
│ │ │ │ ├── plugs/
│ │ │ │ │ ├── assign_sidecar_upstream.ex
│ │ │ │ │ ├── assign_upstream.ex
│ │ │ │ │ ├── authorize.ex
│ │ │ │ │ ├── handler.ex
│ │ │ │ │ └── metrics.ex
│ │ │ │ ├── release.ex
│ │ │ │ ├── repo.ex
│ │ │ │ ├── router.ex
│ │ │ │ ├── server.ex
│ │ │ │ ├── sidecar_router.ex
│ │ │ │ ├── upstreams/
│ │ │ │ │ ├── client/
│ │ │ │ │ │ └── supervisor.ex
│ │ │ │ │ ├── client.ex
│ │ │ │ │ ├── store.ex
│ │ │ │ │ └── upstream.ex
│ │ │ │ └── upstreams.ex
│ │ │ ├── boruta_gateway.ex
│ │ │ └── mix/
│ │ │ └── tasks/
│ │ │ └── server.ex
│ │ ├── mix.exs
│ │ ├── priv/
│ │ │ ├── repo/
│ │ │ │ ├── migrations/
│ │ │ │ │ ├── 20200219201345_create_upstreams.exs
│ │ │ │ │ ├── 20200326185929_upstreams_notify.exs
│ │ │ │ │ ├── 20210111144958_change_upstreams_required_scopes_type.exs
│ │ │ │ │ ├── 20220319220305_add_pool_size_to_upstreams.exs
│ │ │ │ │ ├── 20220728122802_add_max_idle_time_to_upstreams.exs
│ │ │ │ │ ├── 20220729040405_add_pool_count_to_upstreams.exs
│ │ │ │ │ ├── 20220810082956_add_forbidden_response_to_upstreams.exs
│ │ │ │ │ ├── 20220810084238_add_error_content_type_to_upstreams.exs
│ │ │ │ │ ├── 20220810084450_add_unauthorized_response_to_upstreams.exs
│ │ │ │ │ ├── 20221024100810_add_forwarded_token_signature_algorithm_to_upstreams.exs
│ │ │ │ │ ├── 20221024122642_add_forwarded_token_secret_to_upstreams.exs
│ │ │ │ │ ├── 20221024132312_add_forwarded_token_key_pair_to_upstreams.exs
│ │ │ │ │ ├── 20230413190522_upstreams_unique_indices.exs
│ │ │ │ │ ├── 20230421135202_add_node_name_to_upstreams.exs
│ │ │ │ │ └── 20230422083455_update_upstreams_unique_constraint.exs
│ │ │ │ └── seeds.exs
│ │ │ └── test/
│ │ │ └── configuration_files/
│ │ │ ├── authorized.yml
│ │ │ ├── authorized_introspect.yml
│ │ │ ├── bad_configuration.yml
│ │ │ ├── bad_gateway_configuration.yml
│ │ │ ├── bad_microgateway_configuration.yml
│ │ │ ├── forbidden.yml
│ │ │ ├── full_configuration.yml
│ │ │ ├── not_found.yml
│ │ │ └── unauthorized.yml
│ │ └── test/
│ │ ├── boruta_gateway/
│ │ │ ├── configuration_loader_test.exs
│ │ │ ├── integration/
│ │ │ │ └── requests_test.exs
│ │ │ ├── upstreams/
│ │ │ │ ├── client_test.exs
│ │ │ │ └── store_test.exs
│ │ │ └── upstreams_test.exs
│ │ ├── support/
│ │ │ └── data_case.ex
│ │ └── test_helper.exs
│ ├── boruta_identity/
│ │ ├── .formatter.exs
│ │ ├── .gitignore
│ │ ├── assets/
│ │ │ └── wallet/
│ │ │ ├── .browserslistrc
│ │ │ ├── .gitignore
│ │ │ ├── Dockerfile
│ │ │ ├── README.md
│ │ │ ├── package.json
│ │ │ ├── public/
│ │ │ │ ├── index.html
│ │ │ │ └── robots.txt
│ │ │ ├── src/
│ │ │ │ ├── App.vue
│ │ │ │ ├── components/
│ │ │ │ │ ├── Consent.vue
│ │ │ │ │ ├── Credentials.vue
│ │ │ │ │ ├── HelloWorld.vue
│ │ │ │ │ └── KeySelect.vue
│ │ │ │ ├── main.ts
│ │ │ │ ├── registerServiceWorker.ts
│ │ │ │ ├── router/
│ │ │ │ │ └── index.ts
│ │ │ │ ├── shims-vue.d.ts
│ │ │ │ ├── store/
│ │ │ │ │ └── index.ts
│ │ │ │ └── views/
│ │ │ │ ├── HomeView.vue
│ │ │ │ ├── Oid4vcCallbackView.vue
│ │ │ │ └── VerifiableCredentialsIssuanceView.vue
│ │ │ ├── tsconfig.json
│ │ │ └── vite.config.js
│ │ ├── config/
│ │ │ ├── config.exs
│ │ │ ├── dev.exs
│ │ │ ├── prod.exs
│ │ │ └── test.exs
│ │ ├── lib/
│ │ │ ├── boruta_identity/
│ │ │ │ ├── accounts/
│ │ │ │ │ ├── backends/
│ │ │ │ │ │ ├── federated.ex
│ │ │ │ │ │ ├── internal/
│ │ │ │ │ │ │ └── user.ex
│ │ │ │ │ │ ├── internal.ex
│ │ │ │ │ │ ├── ldap/
│ │ │ │ │ │ │ └── user.ex
│ │ │ │ │ │ └── ldap.ex
│ │ │ │ │ ├── choose_sessions.ex
│ │ │ │ │ ├── confirmations.ex
│ │ │ │ │ ├── consents.ex
│ │ │ │ │ ├── deliveries/
│ │ │ │ │ │ ├── email_template.ex
│ │ │ │ │ │ └── user_notifier.ex
│ │ │ │ │ ├── deliveries.ex
│ │ │ │ │ ├── registrations.ex
│ │ │ │ │ ├── reset_passwords.ex
│ │ │ │ │ ├── schemas/
│ │ │ │ │ │ ├── consent.ex
│ │ │ │ │ │ ├── role.ex
│ │ │ │ │ │ ├── role_scope.ex
│ │ │ │ │ │ ├── user.ex
│ │ │ │ │ │ ├── user_authorized_scope.ex
│ │ │ │ │ │ ├── user_role.ex
│ │ │ │ │ │ └── user_token.ex
│ │ │ │ │ ├── sessions.ex
│ │ │ │ │ ├── settings.ex
│ │ │ │ │ ├── users.ex
│ │ │ │ │ ├── verifiable_credentials.ex
│ │ │ │ │ └── verifiable_presentations.ex
│ │ │ │ ├── accounts.ex
│ │ │ │ ├── admin.ex
│ │ │ │ ├── application.ex
│ │ │ │ ├── clients.ex
│ │ │ │ ├── configuration/
│ │ │ │ │ └── error_template.ex
│ │ │ │ ├── configuration.ex
│ │ │ │ ├── federated_accounts.ex
│ │ │ │ ├── hooks/
│ │ │ │ │ └── post_user_creation_hook.ex
│ │ │ │ ├── identity_providers/
│ │ │ │ │ ├── backend.ex
│ │ │ │ │ ├── backend_role.ex
│ │ │ │ │ ├── client_identity_provider.ex
│ │ │ │ │ ├── identity_provider.ex
│ │ │ │ │ └── template.ex
│ │ │ │ ├── identity_providers.ex
│ │ │ │ ├── ldap_repo.ex
│ │ │ │ ├── logger.ex
│ │ │ │ ├── organizations/
│ │ │ │ │ ├── organization.ex
│ │ │ │ │ └── organization_user.ex
│ │ │ │ ├── organizations.ex
│ │ │ │ ├── repo.ex
│ │ │ │ ├── resource_owners.ex
│ │ │ │ ├── totp.ex
│ │ │ │ └── webauthn.ex
│ │ │ ├── boruta_identity.ex
│ │ │ ├── boruta_identity_web/
│ │ │ │ ├── concerns/
│ │ │ │ │ └── authenticable.ex
│ │ │ │ ├── controllers/
│ │ │ │ │ ├── backends_controller.ex
│ │ │ │ │ ├── choose_session_controller.ex
│ │ │ │ │ ├── fallback_controller.ex
│ │ │ │ │ ├── totp_controller.ex
│ │ │ │ │ ├── user_confirmation_controller.ex
│ │ │ │ │ ├── user_consent_controller.ex
│ │ │ │ │ ├── user_registration_controller.ex
│ │ │ │ │ ├── user_reset_password_controller.ex
│ │ │ │ │ ├── user_session_controller.ex
│ │ │ │ │ ├── user_settings_controller.ex
│ │ │ │ │ ├── wallet_controller.ex
│ │ │ │ │ └── webauthn_controller.ex
│ │ │ │ ├── endpoint.ex
│ │ │ │ ├── gettext.ex
│ │ │ │ ├── plugs/
│ │ │ │ │ └── sessions.ex
│ │ │ │ ├── router.ex
│ │ │ │ ├── telemetry.ex
│ │ │ │ ├── templates/
│ │ │ │ │ ├── error/
│ │ │ │ │ │ ├── 400.html.eex
│ │ │ │ │ │ ├── 403.html.eex
│ │ │ │ │ │ ├── 404.html.eex
│ │ │ │ │ │ └── 500.html.eex
│ │ │ │ │ ├── layout/
│ │ │ │ │ │ └── app.html.eex
│ │ │ │ │ └── wallet/
│ │ │ │ │ └── index.html.eex
│ │ │ │ ├── token.ex
│ │ │ │ └── views/
│ │ │ │ ├── error_helpers.ex
│ │ │ │ ├── error_view.ex
│ │ │ │ ├── template_view.ex
│ │ │ │ └── wallet_view.ex
│ │ │ └── boruta_identity_web.ex
│ │ ├── mix.exs
│ │ ├── priv/
│ │ │ ├── gettext/
│ │ │ │ ├── en/
│ │ │ │ │ └── LC_MESSAGES/
│ │ │ │ │ └── errors.po
│ │ │ │ └── errors.pot
│ │ │ ├── repo/
│ │ │ │ ├── migrations/
│ │ │ │ │ ├── .formatter.exs
│ │ │ │ │ ├── 20210127190501_create_users_auth_tables.exs
│ │ │ │ │ ├── 20210128080043_create_users_authorized_scopes.exs
│ │ │ │ │ ├── 20210208110903_user_authorized_scopes_unique_index.exs
│ │ │ │ │ ├── 20210302213536_create_consents.exs
│ │ │ │ │ ├── 20210806194842_add_last_login_at_to_users.exs
│ │ │ │ │ ├── 20211002132445_modify_users_confirmed_at.exs
│ │ │ │ │ ├── 20211129225646_create_relying_parties.exs
│ │ │ │ │ ├── 20211130230927_create_clients_relying_parties.exs
│ │ │ │ │ ├── 20220117220007_add_registrable_to_relying_parties.exs
│ │ │ │ │ ├── 20220118122834_add_unique_name_to_relying_parties.exs
│ │ │ │ │ ├── 20220120214356_create_relying_party_templates.exs
│ │ │ │ │ ├── 20220131133951_add_confirmable_to_relying_parties.exs
│ │ │ │ │ ├── 20220218144931_add_consentable_to_relying_parties.exs
│ │ │ │ │ ├── 20220221123627_add_choose_session_to_relying_parties.exs
│ │ │ │ │ ├── 20220520212652_add_user_editable_to_relying_parties.exs
│ │ │ │ │ ├── 20220528155902_create_internal_users.exs
│ │ │ │ │ ├── 20220607201657_add_user_authorized_scopes_scope_id.exs
│ │ │ │ │ ├── 20220617195827_rename_relying_parties.exs
│ │ │ │ │ ├── 20220628073937_create_error_templates.exs
│ │ │ │ │ ├── 20220812123254_create_backends.exs
│ │ │ │ │ ├── 20220815073225_add_backend_id_to_identity_providers.exs
│ │ │ │ │ ├── 20220815091033_remove_type_from_identity_providers.exs
│ │ │ │ │ ├── 20220815115719_add_default_to_backends.exs
│ │ │ │ │ ├── 20220816074610_add_password_hashing_opts_to_backends.exs
│ │ │ │ │ ├── 20220817134821_change_users_provider_to_backend_id.exs
│ │ │ │ │ ├── 20220817150643_add_backend_id_to_internal_users.exs
│ │ │ │ │ ├── 20220826055043_add_mail_configuration_to_backends.exs
│ │ │ │ │ ├── 20220904073628_create_pg_trgm_extension.exs
│ │ │ │ │ ├── 20220904183116_create_trgm_index.exs
│ │ │ │ │ ├── 20220911195248_add_ldap_configuration_to_backends.exs
│ │ │ │ │ ├── 20220915191039_add_ldap_ser_rdn_attribute_to_backends.exs
│ │ │ │ │ ├── 20221008202236_add_ldap_master_credentials_to_backends.exs
│ │ │ │ │ ├── 20221026092004_create_email_templates.exs
│ │ │ │ │ ├── 20221026211130_add_smtp_ssl_to_backends.exs
│ │ │ │ │ ├── 20221028083326_add_revoked_at_to_users_tokens.exs
│ │ │ │ │ ├── 20221108140432_add_metadata_fields_to_backends.exs
│ │ │ │ │ ├── 20221108144651_add_metadata_to_users.exs
│ │ │ │ │ ├── 20230303151220_add_group_to_users.exs
│ │ │ │ │ ├── 20230502111802_add_identity_federation_to_backends.exs
│ │ │ │ │ ├── 20230605073651_create_roles.exs
│ │ │ │ │ ├── 20230605074117_create_roles_scopes.exs
│ │ │ │ │ ├── 20230615082520_create_roles_users.exs
│ │ │ │ │ ├── 20230626064411_create_backends_roles.exs
│ │ │ │ │ ├── 20230805134343_add_totpable_to_identity_providers.exs
│ │ │ │ │ ├── 20230805160200_add_totp_to_users.exs
│ │ │ │ │ ├── 20230810130509_add_enforce_totp_to_identity_providers.exs
│ │ │ │ │ ├── 20230903150227_create_organizations.exs
│ │ │ │ │ ├── 20230908094746_add_label_to_organizations.exs
│ │ │ │ │ ├── 20230908113944_create_organizations_users.exs
│ │ │ │ │ ├── 20230909103013_add_create_default_organization_to_backends.exs
│ │ │ │ │ ├── 20240109125818_add_verifiable_credentails_to_backends.exs
│ │ │ │ │ ├── 20240110094020_add_federated_metadata_to_users.exs
│ │ │ │ │ ├── 20240426110841_organizations_users_reference.exs
│ │ │ │ │ ├── 20240505104631_organizations_users_reference2.exs
│ │ │ │ │ ├── 20240808195715_add_webauthn_challenge_to_users.exs
│ │ │ │ │ ├── 20240820140733_add_webauthn_public_key_to_users.exs
│ │ │ │ │ ├── 20240820233604_add_webauthn_to_identity_providers.exs
│ │ │ │ │ ├── 20240907103609_add_verifiable_presentations_to_backends.exs
│ │ │ │ │ ├── 20241017153124_add_account_type_to_users.exs
│ │ │ │ │ ├── 20241130000259_add_check_password_to_identity_providers.exs
│ │ │ │ │ └── 20250302193825_remove_global_email_unique_constraint.exs
│ │ │ │ └── seeds.exs
│ │ │ └── templates/
│ │ │ ├── choose_session/
│ │ │ │ └── index.mustache
│ │ │ ├── confirmations/
│ │ │ │ └── new.mustache
│ │ │ ├── consents/
│ │ │ │ └── new.mustache
│ │ │ ├── emails/
│ │ │ │ ├── confirmation_instructions.html.mustache
│ │ │ │ ├── confirmation_instructions.txt.mustache
│ │ │ │ ├── reset_password_instructions.html.mustache
│ │ │ │ ├── reset_password_instructions.txt.mustache
│ │ │ │ ├── tx_code.html.mustache
│ │ │ │ └── tx_code.txt.mustache
│ │ │ ├── errors/
│ │ │ │ ├── 400.mustache
│ │ │ │ ├── 401.mustache
│ │ │ │ ├── 403.mustache
│ │ │ │ ├── 404.mustache
│ │ │ │ └── 500.mustache
│ │ │ ├── layouts/
│ │ │ │ └── app.mustache
│ │ │ ├── mfa/
│ │ │ │ ├── totp/
│ │ │ │ │ ├── authentication.mustache
│ │ │ │ │ └── registration.mustache
│ │ │ │ └── webauthn/
│ │ │ │ ├── authentication.mustache
│ │ │ │ └── registration.mustache
│ │ │ ├── registrations/
│ │ │ │ └── new.mustache
│ │ │ ├── reset_passwords/
│ │ │ │ ├── edit.mustache
│ │ │ │ └── new.mustache
│ │ │ ├── sessions/
│ │ │ │ └── new.mustache
│ │ │ └── settings/
│ │ │ ├── credential_offer.mustache
│ │ │ ├── edit_user.mustache
│ │ │ └── verifiable_presentation.mustache
│ │ └── test/
│ │ ├── boruta_identity/
│ │ │ ├── accounts/
│ │ │ │ └── deliveries_test.exs
│ │ │ ├── accounts_test.exs
│ │ │ ├── admin_test.exs
│ │ │ ├── configuration_test.exs
│ │ │ ├── federated_accounts_test.exs
│ │ │ ├── identity_providers/
│ │ │ │ ├── backend_test.exs
│ │ │ │ └── identity_provider_test.exs
│ │ │ ├── identity_providers_test.exs
│ │ │ ├── resource_owners_test.exs
│ │ │ ├── totp_test.exs
│ │ │ └── webauthn_test.exs
│ │ ├── boruta_identity_web/
│ │ │ ├── concerns/
│ │ │ │ └── authenticable_test.exs
│ │ │ ├── controllers/
│ │ │ │ ├── choose_session_controller_test.exs
│ │ │ │ ├── page_controller_test.exs
│ │ │ │ ├── totp_controller_test.exs
│ │ │ │ ├── user_confirmation_controller_test.exs
│ │ │ │ ├── user_consent_controller_test.exs
│ │ │ │ ├── user_registration_controller_test.exs
│ │ │ │ ├── user_reset_password_controller_test.exs
│ │ │ │ ├── user_session_controller_test.exs
│ │ │ │ └── user_settings_controller_test.exs
│ │ │ ├── plugs/
│ │ │ │ └── sessions_test.exs
│ │ │ └── views/
│ │ │ ├── error_view_test.exs
│ │ │ ├── layout_view_test.exs
│ │ │ └── page_view_test.exs
│ │ ├── support/
│ │ │ ├── boruta_factory.ex
│ │ │ ├── boruta_identity_factory.ex
│ │ │ ├── conn_case.ex
│ │ │ ├── data_case.ex
│ │ │ └── fixtures/
│ │ │ ├── accounts_fixtures.ex
│ │ │ ├── admin_fixtures.ex
│ │ │ └── identity_providers_fixtures.ex
│ │ └── test_helper.exs
│ └── boruta_web/
│ ├── .formatter.exs
│ ├── .gitignore
│ ├── config/
│ │ ├── config.exs
│ │ ├── dev.exs
│ │ ├── prod.exs
│ │ └── test.exs
│ ├── lib/
│ │ ├── boruta/
│ │ │ └── status_resolver.ex
│ │ ├── boruta_web/
│ │ │ ├── application.ex
│ │ │ ├── controllers/
│ │ │ │ ├── did_controller.ex
│ │ │ │ ├── fallback_controller.ex
│ │ │ │ ├── monitoring_controller.ex
│ │ │ │ ├── oauth/
│ │ │ │ │ ├── authorize_controller.ex
│ │ │ │ │ ├── introspect_controller.ex
│ │ │ │ │ ├── pushed_authorization_request_controller.ex
│ │ │ │ │ ├── revoke_controller.ex
│ │ │ │ │ └── token_controller.ex
│ │ │ │ ├── openid/
│ │ │ │ │ ├── credential_controller.ex
│ │ │ │ │ ├── dynamic_registration_controller.ex
│ │ │ │ │ ├── jwks_controller.ex
│ │ │ │ │ └── userinfo_controller.ex
│ │ │ │ └── openid_controller.ex
│ │ │ ├── endpoint.ex
│ │ │ ├── gettext.ex
│ │ │ ├── logger.ex
│ │ │ ├── plugs/
│ │ │ │ └── rate_limit.ex
│ │ │ ├── presentation_server.ex
│ │ │ ├── release.ex
│ │ │ ├── repo.ex
│ │ │ ├── router.ex
│ │ │ ├── templates/
│ │ │ │ └── error/
│ │ │ │ ├── 404.html.eex
│ │ │ │ └── 500.html.eex
│ │ │ ├── token.ex
│ │ │ └── views/
│ │ │ ├── error_helpers.ex
│ │ │ ├── error_view.ex
│ │ │ ├── oauth_view.ex
│ │ │ └── openid_view.ex
│ │ ├── boruta_web.ex
│ │ └── mix/
│ │ └── tasks/
│ │ └── server.ex
│ ├── mix.exs
│ ├── priv/
│ │ ├── gettext/
│ │ │ ├── en/
│ │ │ │ └── LC_MESSAGES/
│ │ │ │ └── errors.po
│ │ │ └── errors.pot
│ │ └── repo/
│ │ └── migrations/
│ │ └── .keep
│ └── test/
│ ├── boruta_web/
│ │ ├── controllers/
│ │ │ ├── credential_controller_test.exs
│ │ │ ├── oauth/
│ │ │ │ ├── authorization_code_test.exs
│ │ │ │ ├── authorize_controller_test.exs
│ │ │ │ ├── client_credentials_test.exs
│ │ │ │ ├── direct_post_test.exs
│ │ │ │ ├── implicit_test.exs
│ │ │ │ ├── introspect_test.exs
│ │ │ │ ├── openid_connect_test.exs
│ │ │ │ ├── password_test.exs
│ │ │ │ └── revoke_test.exs
│ │ │ └── pushed_authorization_request_controller_test.exs
│ │ ├── plugs/
│ │ │ └── rate_limit_test.exs
│ │ └── views/
│ │ ├── error_view_test.exs
│ │ ├── layout_view_test.exs
│ │ └── page_view_test.exs
│ ├── support/
│ │ ├── boruta_factory.ex
│ │ ├── boruta_identity_factory.ex
│ │ └── conn_case.ex
│ └── test_helper.exs
├── boruta-admin.openapi.json
├── config/
│ ├── config.exs
│ ├── dev.exs
│ ├── prod.exs
│ ├── releases.exs
│ └── test.exs
├── docker-compose.yml
├── examples/
│ ├── README.md
│ └── sidecar-authorization-gateways/
│ ├── config/
│ │ ├── example-gateway-configuration.yml
│ │ ├── example-httpbin-configuration.yml
│ │ └── example-protected-httpbin-configuration.yml
│ └── docker-compose.yml
├── mix.exs
├── rel/
│ ├── env.bat.eex
│ ├── env.sh.eex
│ └── vm.args.eex
├── scripts/
│ ├── prepare_assets.sh
│ └── setup.debian.sh
├── static_config/
│ ├── example-gateway-configuration.yml
│ ├── example-httpbin-configuration.yml
│ └── example-protected-httpbin-configuration.yml
└── vetur.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .credo.exs
================================================
# This file contains the configuration for Credo and you are probably reading
# this after creating it with `mix credo.gen.config`.
#
# If you find anything wrong or unclear in this file, please report an
# issue on GitHub: https://github.com/rrrene/credo/issues
#
%{
#
# You can have as many configs as you like in the `configs:` field.
configs: [
%{
#
# Run any exec using `mix credo -C <name>`. If no exec name is given
# "default" is used.
#
name: "default",
#
# These are the files included in the analysis:
files: %{
#
# You can give explicit globs or simply directories.
# In the latter case `**/*.{ex,exs}` will be used.
#
included: ["lib/", "src/", "test/", "web/", "apps/"],
excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"]
},
#
# Load and configure plugins here:
#
plugins: [],
#
# If you create your own checks, you must specify the source files for
# them here, so they can be loaded by Credo before running the analysis.
#
requires: [],
#
# If you want to enforce a style guide and need a more traditional linting
# experience, you can change `strict` to `true` below:
#
strict: true,
#
# If you want to use uncolored output by default, you can change `color`
# to `false` below:
#
color: true,
#
# You can customize the parameters of any check by adding a second element
# to the tuple.
#
# To disable a check put `false` as second element:
#
# {Credo.Check.Design.DuplicatedCode, false}
#
checks: [
#
## Consistency Checks
#
{Credo.Check.Consistency.ExceptionNames, []},
{Credo.Check.Consistency.LineEndings, []},
{Credo.Check.Consistency.ParameterPatternMatching, []},
{Credo.Check.Consistency.SpaceAroundOperators, []},
{Credo.Check.Consistency.SpaceInParentheses, []},
{Credo.Check.Consistency.TabsOrSpaces, []},
#
## Design Checks
#
# You can customize the priority of any check
# Priority values are: `low, normal, high, higher`
#
{Credo.Check.Design.AliasUsage,
[priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 1]},
# You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just
# set this value to 0 (zero).
#
{Credo.Check.Design.TagTODO, [exit_status: 0]},
{Credo.Check.Design.TagFIXME, []},
#
## Readability Checks
#
{Credo.Check.Readability.AliasOrder, []},
{Credo.Check.Readability.FunctionNames, []},
{Credo.Check.Readability.LargeNumbers, []},
{Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]},
{Credo.Check.Readability.ModuleAttributeNames, []},
{Credo.Check.Readability.ModuleDoc, []},
{Credo.Check.Readability.ModuleNames, []},
{Credo.Check.Readability.ParenthesesInCondition, []},
{Credo.Check.Readability.ParenthesesOnZeroArityDefs, []},
{Credo.Check.Readability.PredicateFunctionNames, []},
{Credo.Check.Readability.PreferImplicitTry, []},
{Credo.Check.Readability.RedundantBlankLines, []},
{Credo.Check.Readability.Semicolons, []},
{Credo.Check.Readability.SpaceAfterCommas, []},
{Credo.Check.Readability.StringSigils, []},
{Credo.Check.Readability.TrailingBlankLine, []},
{Credo.Check.Readability.TrailingWhiteSpace, []},
# TODO: enable by default in Credo 1.1
{Credo.Check.Readability.UnnecessaryAliasExpansion, false},
{Credo.Check.Readability.VariableNames, []},
#
## Refactoring Opportunities
#
{Credo.Check.Refactor.CondStatements, []},
{Credo.Check.Refactor.CyclomaticComplexity, []},
{Credo.Check.Refactor.FunctionArity, []},
{Credo.Check.Refactor.LongQuoteBlocks, []},
{Credo.Check.Refactor.MapInto, []},
{Credo.Check.Refactor.MatchInCondition, []},
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
{Credo.Check.Refactor.Nesting, [max_nesting: 3]},
{Credo.Check.Refactor.UnlessWithElse, []},
{Credo.Check.Refactor.WithClauses, []},
{Credo.Check.Refactor.RedundantWithClauseResult, false},
#
## Warnings
#
{Credo.Check.Warning.BoolOperationOnSameValues, []},
{Credo.Check.Warning.ExpensiveEmptyEnumCheck, []},
{Credo.Check.Warning.IExPry, []},
{Credo.Check.Warning.IoInspect, []},
{Credo.Check.Warning.LazyLogging, []},
{Credo.Check.Warning.OperationOnSameValues, []},
{Credo.Check.Warning.OperationWithConstantResult, []},
{Credo.Check.Warning.RaiseInsideRescue, []},
{Credo.Check.Warning.UnusedEnumOperation, []},
{Credo.Check.Warning.UnusedFileOperation, []},
{Credo.Check.Warning.UnusedKeywordOperation, []},
{Credo.Check.Warning.UnusedListOperation, []},
{Credo.Check.Warning.UnusedPathOperation, []},
{Credo.Check.Warning.UnusedRegexOperation, []},
{Credo.Check.Warning.UnusedStringOperation, []},
{Credo.Check.Warning.UnusedTupleOperation, []},
{Credo.Check.Warning.SpecWithStruct, false},
{Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, false},
#
# Controversial and experimental checks (opt-in, just replace `false` with `[]`)
#
{Credo.Check.Consistency.MultiAliasImportRequireUse, false},
{Credo.Check.Consistency.UnusedVariableNames, false},
{Credo.Check.Design.DuplicatedCode, false},
{Credo.Check.Readability.AliasAs, false},
{Credo.Check.Readability.MultiAlias, false},
{Credo.Check.Readability.Specs, false},
{Credo.Check.Readability.SinglePipe, false},
{Credo.Check.Refactor.ABCSize, false},
{Credo.Check.Refactor.AppendSingleItem, false},
{Credo.Check.Refactor.DoubleBooleanNegation, false},
{Credo.Check.Refactor.ModuleDependencies, false},
{Credo.Check.Refactor.PipeChainStart, false},
{Credo.Check.Refactor.VariableRebinding, false},
{Credo.Check.Refactor.Apply, false},
{Credo.Check.Warning.MapGetUnsafePass, false},
{Credo.Check.Warning.UnsafeToAtom, false}
#
# Custom checks can be created using `mix credo.gen.check`.
#
]
}
]
}
================================================
FILE: .formatter.exs
================================================
[
inputs: ["mix.exs", "config/*.exs"],
subdirectories: ["apps/*"]
]
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: boruta-server
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/workflows/deploy.yml
================================================
name: Deployment
on:
push:
branches:
- provider-policies-registration
workflow_run:
workflows:
- Continuous Integration
branches:
- master
- signatures-adapter
types:
- completed
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-server-image:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: benjlevesque/short-sha@v1.2
id: short-sha
with:
length: 8
- name: Build and push server Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
file: Dockerfile.full
context: .
build-args: |
BORUTA_OAUTH_BASE_URL=https://oauth.boruta.patatoid.fr
push: true
tags: |
${{ env.REGISTRY }}/malach-it/boruta-server:${{ steps.short-sha.outputs.sha }},
${{ env.REGISTRY }}/malach-it/boruta-server:${{ github.head_ref || github.ref_name }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-gateway-image:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: benjlevesque/short-sha@v1.2
id: short-sha
with:
length: 8
- name: Build and push gateway Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
file: Dockerfile.gateway
context: .
push: true
tags: |
${{ env.REGISTRY }}/malach-it/boruta-gateway:${{ steps.short-sha.outputs.sha }},
${{ env.REGISTRY }}/malach-it/boruta-gateway:${{ github.head_ref || github.ref_name }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-auth-image:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: benjlevesque/short-sha@v1.2
id: short-sha
with:
length: 8
- name: Build and push auth Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
file: Dockerfile.auth
context: .
push: true
tags: |
${{ env.REGISTRY }}/malach-it/boruta-auth:${{ steps.short-sha.outputs.sha }},
${{ env.REGISTRY }}/malach-it/boruta-auth:${{ github.head_ref || github.ref_name }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-admin-image:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: benjlevesque/short-sha@v1.2
id: short-sha
with:
length: 8
- name: Build and push admin Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
file: Dockerfile.admin
context: .
push: true
tags: |
${{ env.REGISTRY }}/malach-it/boruta-admin:${{ steps.short-sha.outputs.sha }},
${{ env.REGISTRY }}/malach-it/boruta-admin:${{ github.head_ref || github.ref_name }}
labels: ${{ steps.meta.outputs.labels }}
================================================
FILE: .github/workflows/elixir.yml
================================================
name: Continuous Integration
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
static_code_analysis:
name: Static Code Analysis
runs-on: ubuntu-22.04
container: elixir:1.14.5-otp-25
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Retrieve Cached Dependencies
uses: actions/cache@v3
id: mix-cache
with:
path: |
deps
_build
key: ${{ runner.os }}-${{ hashFiles('mix.lock') }}
# - name: Check Code Format
# run: mix format --check-formatted
- name: Elixir prerequisites
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- name: Compilation warnings
run: mix compile --force --warnings-as-errors
- name: Run Credo
run: mix credo --strict
# - name: Run Dialyzer
# run: mix dialyzer
unit_tests:
name: Unit Tests
runs-on: ubuntu-22.04
container: elixir:1.14.5-otp-25
strategy:
fail-fast: false
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.6.0
with:
access_token: ${{ github.token }}
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Retrieve Cached Dependencies
uses: actions/cache@v3
id: mix-cache
with:
path: |
deps
_build
key: ${{ runner.os }}-${{ hashFiles('mix.lock') }}
- name: Elixir prerequisites
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- name: Run test
run: mix test --trace
env:
MIX_ENV: test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DATABASE: boruta_test
POSTGRES_HOST: postgres
================================================
FILE: .gitignore
================================================
/_build/
/cover/
/deps/
/doc/
/tmp/
/log/
/.fetch
erl_crash.dump
*.ez
.env.sh
.env
*.swp
*.swo
*.orig
tags*
apps/*/priv/static/**
apps/*/priv/ssl/**
apps/*/log/**
.vscode
/ansible/group_vars
================================================
FILE: .gitlab-ci.yml
================================================
stages:
- test
- build
- deploy
services:
- postgres:latest
.elixir-task:
image: elixir:1.12.1
before_script:
- apt-get install -y libcurl4-openssl-dev libssl-dev libevent-dev
- mix local.hex --force
- mix local.rebar --force
- mix deps.get
# dialyzer:
# stage: test
# extends: .elixir-task
# cache:
# paths:
# - _build/
# script:
# - mix dialyzer
credo:
stage: test
extends: .elixir-task
script:
- mix credo --strict
test:
stage: test
extends: .elixir-task
script:
- mix test --trace
variables:
POSTGRES_DATABASE: boruta_test
POSTGRES_HOST: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
MIX_ENV: test
build:
image: docker:19.03.12
stage: build
services:
- docker:19.03.12-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker pull $CI_REGISTRY/patatoid/boruta/app:latest
script:
- docker build --cache-from $CI_REGISTRY/patatoid/boruta/app:latest -t $CI_REGISTRY/patatoid/boruta/app:$CI_COMMIT_SHORT_SHA .
- docker tag $CI_REGISTRY/patatoid/boruta/app:$CI_COMMIT_SHORT_SHA $CI_REGISTRY/patatoid/boruta/app:latest
- docker push $CI_REGISTRY/patatoid/boruta/app:$CI_COMMIT_SHORT_SHA
- docker push $CI_REGISTRY/patatoid/boruta/app:latest
only:
- master
deploy:
stage: deploy
image: debian:latest
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
cache:
paths:
- .cache/pip
before_script:
- apt-get update
- apt-get install -y curl python3-pip apt-transport-https
- curl https://baltocdn.com/helm/signing.asc | apt-key add -
- echo "deb https://baltocdn.com/helm/stable/debian/ all main" | tee /etc/apt/sources.list.d/helm-stable-debian.list
- apt-get update
- apt-get install -y helm
- pip3 install --upgrade setuptools pip
- pip3 install ansible pyhelm grpcio requests openshift kubernetes
- ansible-galaxy collection install kubernetes.core
- curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
- curl -LO "https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
- echo "$(<kubectl.sha256) kubectl" | sha256sum --check
- mv ./kubectl /usr/bin/kubectl
- chmod 755 /usr/bin/kubectl
script:
- cd ansible
- echo $VAULT_PASSWORD > vault_pass.txt
- ansible-vault decrypt ./.kube/kubeconfig-k8s-boruta.yaml --vault-password-file vault_pass.txt
- KUBECONFIG=./.kube/kubeconfig-k8s-boruta.yaml ansible-playbook -i ./inventories/scaleway deploy.yml -e release_tag=$CI_COMMIT_SHORT_SHA --vault-password-file vault_pass.txt
only:
- master
================================================
FILE: .tool-versions
================================================
nodejs 25.2.1
erlang 25.3.2.21
elixir 1.14.5-otp-25
================================================
FILE: CHANGELOG.md
================================================
# Changelog
> Note that 0.X.X releases are reverved for the beta version of the server and may include breaking changes.
## [unreleased]
### Added
- [ssi] code chains
- verify verifiable presentation from code chains
- issuance code chains
- next flow redirection in case of presentation success
- agent token management
- [ssi] code metadata policies
- restrict issuance / presentation key usage for enabled check public client id clients
- [ssi] server sent events verifiable presentation page navigation
- [identity] add resource owner in credentials templates
- [ssi] credential issuance scope restriction
- [wallet] display credential presentation purposes
### Changed
- [ssi] remove resource owner constraint for openid4vc flows
- [ssi] default backend authorization details for anonymous users
- [ssi] issuance / presentation default templates open integrated wallet in a popup
- [ssi] add client_id to credential offers
- [identity] improve identity providers querying and cache
- [admin] group direct post requests in dashboard
### Fixed
- [admin] add credential offer and presentation in breadcrumb
- [admin] update identity provider title in breadcrumb
- [admin] feedback stars display
- [wallet] qr code scan redirection
- [ssi] public and unknown users presentation
### Security
- [admin] only expose client name in templates
- [auth] remove default client secret from seeds
- [admin] set minimum oauth client private key modulus size
## [0.8.0] - 2025-07-12
### Added
- [auth] agent credentials / code flows
- [wallet] key selection
- [ssi] verify public client id oauth client option
### Changed
- [auth] max authorization code ttl to 600 seconds
- [ssi] remove authentication on siopv2 flow
### Fixed
- [admin] file upload text editor update
- [ssi] expose public credential configuration for authenticated users
- [wallet] fix presentation duplicates
### Security
- [auth] experimental request rate limiting
- [auth] remove dynamic client registration
## [0.7.2] - 2025-04-13
### Fixed
- [auth] fix boruta core migration
## [0.7.1] - 2025-04-05
### Fixed
- [ssi] do not use ES256 alg to verify EdDSA JWTs
- [identity] expose default templates static assets
## [0.7.0] - 2025-03-26
### Added
- [admin] signatures adapter
- [wallet] display an error when no credential match presentation
- [identity] add reload button in credentials temapltes
- [wallet] close qr code scanner on click
### Security
- [wallet] fix npm vulnerabilities
- [admin] fix npm vulnerabilities
## [0.6.1] - 2025-03-15
### Security
- [admin] update verifiable presentations default template
## [0.6.0] - 2025-03-15
### Added
- [identity] passwordless user creation (WIP)
- [identity] destroy user
- [ssi] transaction code in OID4VCI preauthorized code flow
- [ssi] vct configuration in verifiable credentials
- [admin] feedback form
- [wallet] web identity wallet bootstrap (PWA)
- [identity] scope user emails per backend
- [admin] decentralized identity example flows
- [ssi] verifiable credentials nested claims
### Changed
- [identity] remove user metadata value constraints
- [admin] verifiable credentials claim format
### Fixed
- [admin] defered configuration
- [admin] example credential issuance link
- [ssi] oauth clients did persistence
- [admin] verifiable presentation definition text edition
### Security
- [admin] remove cdnjs dependency
- [identity] remove picsum dependency
## [0.5.1] - 2024-11-21
### Added
- [admin] user csv import metadata
- [infra] organization creation in static configuration
- [admin] client key pair configuration + support for EC keys
### Fixed
- [ssi] several verifiable credentials issuance and presentation fixes
- [auth] configurable status display in id_token claims
- [admin] user with empty metadata save
- [admin] federated users deletion
## [0.5.0] - 2024-10-17
### Added
- [ssi] OpenID for Verifiable Credentials Presentation implementation
## [0.4.2] - 2024-09-20
### Fixed
- [auth] fix authorize entrypoint
## [0.4.1] - 2024-09-18
### Fixed
- [admin] ipv6 log display
### Security
- [infra] remove .env.example.sig as suspicious file
## [0.4.0] 2024-09-01
### Added
- [ssi] Configurable verifiable credentials issuance with oid4vci implementation
- [ssi] Siopv2 same device implementation
- [auth] Demonstration proof of possession implementation
- [auth] Pushed Authorization Request implementation
- [infra] Server ip address bindings configuration via environment variables
- [infra]Infrastructure as Code with static file configuration
- [admin] Admin ui improvements
- [auth] Better identity federation
- [identity] Webauthn integration
- [infra] Remote IP logging
### Security
- [admin] instance authenticated admins are sub or organization restricted
### Fixed
- [infra] Fix organization and sub admin access restriction
## [0.3.0] 2024-01-18
### Added
- [identity] user organisation management
- [identity] TOTP second factor support
- [identity] user roles management
- [infra] split auth/admin/gateway/all docker images
- [infra] split gateway, admin, auth releases
- [infra] system wide installation script
- [infra] gather statistical info on installation
## [0.2.0] - 2023-05-17
### Added
- [gateway] introspected token forwarding to updatreams
- [identity] email templates edition
- [identity] configure, expose and edit user metadata
- [identity] user metadata configuration
- [gateway] static configuration
- [gateway] microgateways
- [identity] identity federation (login with button)
- [auth] better well-known openid configuration
- [auth] dynamic client registration
- [auth] client authentication methods configuration
- [auth] global signing key pairs
### Security
- [identity] invalidate user reset password token at use
## [0.1.0] - 2022-10-25
Initial beta release
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of Conduct
## 1. Why share this code of conduct?
A code of conduct aims to set the frame of community interactions around the corresponding open-source product. As collective work is at stake here, getting into it requires fitting the rules that make a safe and well-being place to work. This document aims the community wellness to give us the best opportunities to produce the relative facts and deliverables. From this perspective, the need for us to navigate with psychological safety is a must-have to deliver the best we can to improve and make evolve the code at the heart of the community.
## 2. What is a violation?
The purpose of this document is to set the limits and how to mitigate when violations occur. First of all, any violation of applicable law is to be reported for the healthiness of our interactions. We would make focus on harassment and all kind of discrimination against ancestry, age, color, religion, caste, origin, race, personal appearance, nationality, socio-economic status, level of experience, gender identity and expression, sex characteristics, ethnicity, sexual identity and orientation, visible or invisible disability, body size, and other private or personal information that can be used for harming purposes.
## 3. What is a contribution?
Are considered contributions, the produced code and all derived material propagated under the copyright provided by this repository of code. Other material out of this scope is not considered contributions to this project and we do have not any responsibility for them. Also, any official representation of the product may be considered as a contribution. Those need a written validation from the owners of the project.
## 4. In accordance with the product vision
The contributions to this project may fit its vision, all contributions that may diverge from it would be considered as violations if not consented by the owner. The vision of the project is stated as :
ENABLING ORGANIZATIONS THEN USERS TO MANAGE DIGITAL IDENTITIES WHERE DATA PROTECTION IMPROVE SYSTEMS SECURITY
## 5. The roles and responsibilities of contributors
Within this frame arise three main responsibilities. From those can be derived roles that have to fulfill all of them within the community. The objective of them is to help community wellness.
The first responsibility is to report violations that are described above (section 2). It is an overall member's duty to report such violations to the right person following an escalation process. That person will be named here as a facilitator of escalation, described next.
In order to facilitate escalation, the facilitator starts from report and assess the situation to find the right way to mitigate the issue. By owning the report, he keeps the process alive until its resolution by facilitating interactions with the mediating people. The best is to have a written trace of the way the situation was solved step by step to reproduce if it occurs again. He is also responsible for the escalation process improvement.
Within the community, mediation of the situations of violation is made by resolving the conflicts. The responsible person for this should be trained to conflict resolution using methods like Non-Violent Communication from Rosenberg or other peaceful ways of resolution. The responsibility includes finding external resources to solve the conflict, up to contact authorities in case of grave violation or violation of applicable law.
Once again, it is an overall responsibility to report the issues as it is the basis for a healthy community. Starting by navigating within the frame, ensuring psychological safety is also needed for us to evolve as a community.
For example, the minimal roles within a community around an open-source project start with an owner. The project owner can take both mediator and facilitator of escalation responsibilities. Those can be split then and spread across the community knowing that the responsibilities do not have to be unique within the community. Finding suitable roles according to the needed responsibilities of this framework is a work that may include community members to find a collective track toward them.
## 6. Escalation of violations
Based on IT incident report patterns, escalation of violations aims to find the root cause, fix the issue, and prevent its reappearance. Also, one of the objectives is to avoid conflict between parties and find equitable solutions to solve the issue. For that, the mediation may be made using methodology such as Non-Violent Communication to enforce communication over violence being factual as a basis.
The escalation process may suit the community integrating it, then as finding the roles, one may find a collective track to find the best way to mitigate issues. As a minimal process, the project owner must leave an explicit way to report abuse. As a reminder, it is an overall community member's responsibility to report violations of the present code of conduct. That report is to be done in an anonymous way to prevent retaliation. The people responsible for facilitation can keep track of the report, find the best people to mitigate it within the community (it can be himself), and the mediation can begin.
Then comes the mediation, for a low-importance violation, the mediator can facilitate communication and take action against the abuse. In case of public violation, the impactful content is to be removed. Actions may be temporary or permanent bans from the community for example. The issue of the mediation may be tracked by the facilitator for audit purposes but also to mediate if the violation comes up again. That record may be public or private. He can also find ways to improve the escalation process or trigger a role redefinition within the community.
In case of grave violation like any against applicable law, the authorities are to be warned and the overall community has the duty to facilitate their work.
## 7. Ethical goals
This frame of contributions may help to promote ethical goals. Before this, contributions may not imply in any manner a step against those goals, knowing that going toward them aims for us to live in a better place which is the purpose of the current document. This community aims to:
- fight against slavery and forced labor, empower labor law
- empower human rights
- empower diversity, equity, and inclusion
The frame helps to have the tools to get mutual aid to go toward those goals.
> Exemplarity is not required, goodwill is.
OWNER CONTACT:
pascal@malach.it
<p xmlns:cc="http://creativecommons.org/ns#" >This code of conduct is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">Attribution-NonCommercial-ShareAlike 4.0 International</a></p>
================================================
FILE: Dockerfile.admin
================================================
FROM node:25.2.1 AS assets
# For packages not compatible with OpenSSL 3.0 https://nodejs.org/en/blog/release/v17.0.0/
ENV NODE_OPTIONS=--openssl-legacy-provider
WORKDIR /app
COPY ./apps/boruta_admin/assets /app
RUN npm ci
RUN npm run build
FROM elixir:1.14-otp-25-alpine AS builder
RUN apk --no-cache --update add build-base git
ENV MIX_ENV=prod
RUN mix local.hex --force
RUN mix local.rebar --force
WORKDIR /app
COPY . .
COPY --from=assets /priv/static/assets ./apps/boruta_admin/priv/static/assets
RUN rm -rf deps
RUN mix do clean, deps.get
RUN mix compile
WORKDIR /app/apps/boruta_admin
RUN mix phx.digest
WORKDIR /app
RUN mix release boruta_admin --force --overwrite
FROM elixir:1.14-otp-25-alpine
WORKDIR /app
COPY --from=builder /app/_build/prod/rel/boruta_admin ./
CMD ["/bin/sh", "-c", "/app/bin/boruta_admin start"]
================================================
FILE: Dockerfile.auth
================================================
FROM node:25.2.1 AS identity_assets
ARG BORUTA_OAUTH_BASE_URL
# For packages not compatible with OpenSSL 3.0 https://nodejs.org/en/blog/release/v17.0.0/
ENV NODE_OPTIONS=--openssl-legacy-provider
WORKDIR /app/wallet
COPY ./apps/boruta_identity/assets /app
RUN npm ci
RUN npm run build
FROM elixir:1.14-otp-25-alpine AS builder
RUN apk --no-cache --update add build-base git
ENV MIX_ENV=prod
RUN mix local.hex --force
RUN mix local.rebar --force
WORKDIR /app
COPY . .
RUN rm -rf deps
RUN mix do clean, deps.get
RUN mix compile
COPY --from=identity_assets /priv ./apps/boruta_identity/priv/
WORKDIR /app/apps/boruta_identity
RUN mix phx.digest
WORKDIR /app/apps/boruta_web
RUN mix phx.digest
WORKDIR /app
RUN mix release boruta_auth --force --overwrite
FROM elixir:1.14-otp-25-alpine
WORKDIR /app
COPY --from=builder /app/_build/prod/rel/boruta_auth ./
CMD ["/bin/sh", "-c", "/app/bin/boruta_auth start"]
================================================
FILE: Dockerfile.full
================================================
FROM node:25.2.1 AS admin_assets
# For packages not compatible with OpenSSL 3.0 https://nodejs.org/en/blog/release/v17.0.0/
ENV NODE_OPTIONS=--openssl-legacy-provider
WORKDIR /app
COPY ./apps/boruta_admin/assets /app
RUN npm ci
RUN npm run build
FROM node:25.2.1 AS identity_assets
ARG BORUTA_OAUTH_BASE_URL
# For packages not compatible with OpenSSL 3.0 https://nodejs.org/en/blog/release/v17.0.0/
ENV NODE_OPTIONS=--openssl-legacy-provider
WORKDIR /app/wallet
COPY ./apps/boruta_identity/assets /app
RUN npm ci
RUN npm run build
FROM elixir:1.14-otp-25-alpine AS builder
RUN apk --no-cache --update add build-base git
ENV MIX_ENV=prod
RUN mix local.hex --force
RUN mix local.rebar --force
WORKDIR /app
COPY . .
RUN rm -rf deps
RUN mix do clean, deps.get
RUN mix compile
COPY --from=admin_assets /priv/static/assets ./apps/boruta_admin/priv/static/assets
COPY --from=identity_assets /priv/static/wallet ./apps/boruta_identity/priv/static/wallet
WORKDIR /app/apps/boruta_admin
RUN mix phx.digest
WORKDIR /app/apps/boruta_identity
RUN mix phx.digest
WORKDIR /app/apps/boruta_web
RUN mix phx.digest
WORKDIR /app
RUN mix release boruta --force --overwrite
FROM elixir:1.14-otp-25-alpine
WORKDIR /app
COPY --from=builder /app/_build/prod/rel/boruta ./
# File used for gateway static configuration, used in combination with `BORUTA_GATEWAY_CONFIGURATION_PATH` environment variable
COPY /static_config/example-gateway-configuration.yml config/example-gateway-configuration.yml
COPY /static_config/example-httpbin-configuration.yml config/example-httpbin-configuration.yml
COPY /static_config/example-protected-httpbin-configuration.yml config/example-protected-httpbin-configuration.yml
CMD ["/bin/sh", "-c", "/app/bin/boruta start"]
================================================
FILE: Dockerfile.gateway
================================================
FROM elixir:1.14-otp-25-alpine AS builder
RUN apk --no-cache --update add build-base git
ENV MIX_ENV=prod
RUN mix local.hex --force
RUN mix local.rebar --force
WORKDIR /app
COPY . .
RUN rm -rf deps
RUN mix do clean, deps.get
RUN mix compile
WORKDIR /app
RUN mix release boruta_gateway --force --overwrite
FROM elixir:1.14-otp-25-alpine
WORKDIR /app
COPY --from=builder /app/_build/prod/rel/boruta_gateway ./
# File used for gateway static configuration, used in combination with `BORUTA_GATEWAY_CONFIGURATION_PATH` environment variable
COPY /static_config/example-gateway-configuration.yml config/example-gateway-configuration.yml
COPY /static_config/example-httpbin-configuration.yml config/example-httpbin-configuration.yml
COPY /static_config/example-protected-httpbin-configuration.yml config/example-protected-httpbin-configuration.yml
CMD ["/bin/sh", "-c", "/app/bin/boruta_gateway start"]
================================================
FILE: GENERAL_TERMS_AND_CONDITIONS.md
================================================
### General Terms and Conditions for Boruta (Open Beta)
#### **1. Introduction**
Welcome to the open beta of Boruta, an identity and access management solution developed and maintained by Malachit EI. By participating in the beta, you agree to these General Terms and Conditions ("Terms"). Boruta is provided as-is for testing purposes and may not be fully optimized for all production use cases.
These Terms are supplementary to the Apache 2.0 License under which Boruta is licensed. In the event of a conflict, the Apache 2.0 License governs the open-source aspects of Boruta.
---
#### **2. Eligibility**
Participation in the Boruta beta is open to all individuals and organizations, provided they comply with applicable laws and these Terms. By using Boruta, you affirm that you are at least 18 years old or have obtained consent from a legal guardian.
---
#### **3. Scope of Use**
The beta software is made available for testing and feedback purposes. Users are encouraged to explore Boruta's features, report issues, and share suggestions. Malachit recommends against using the beta version in production environments for critical applications.
---
#### **4. User Responsibilities**
Users agree to:
- Use Boruta solely for lawful purposes and in compliance with all applicable laws and regulations.
- Avoid using Boruta in ways that could harm, disable, overburden, or impair the software, its infrastructure, or third-party services connected to it.
- Refrain from introducing malicious code (e.g., viruses, worms) or attempting to exploit vulnerabilities in Boruta or its associated systems.
- Use Boruta in compliance with its documentation and avoid reverse engineering, decompiling, or disassembling the software unless expressly permitted under the Apache 2.0 License.
- Ensure that any identity information collected through Boruta is handled in compliance with applicable data protection and privacy laws. Users acknowledge that they are solely responsible for the proper handling, storage, and use of such information.
---
#### **5. Prohibited Activities**
Users may not:
- Use Boruta for unlawful, unethical, or harmful activities, including but not limited to unauthorized access to systems, identity theft, fraud, or spamming.
- Attempt to circumvent security measures or protections implemented within Boruta.
- Misrepresent the software or its capabilities to others, especially in production environments.
- Share or distribute Boruta in a manner inconsistent with its open-source license (Apache 2.0).
---
#### **6. Feedback and Contributions**
Feedback is critical to improving Boruta. Users may report bugs, suggest features, and provide other feedback through GitHub issues. By submitting feedback:
- You grant Malachit a non-exclusive, royalty-free, perpetual, and irrevocable license to use, modify, and distribute your contributions.
- Significant contributors may be acknowledged publicly in the project documentation or release notes.
For security-related or sensitive issues, please report directly via email at pascal@malach.it.
Additionally, Boruta provides a feedback form under the io.malach.it [Privacy Policy](https://io.malach.it/privacy-policy.html), ensuring compliance with data protection standards.
---
#### **7. Stability and Updates**
While Boruta is stable for general testing, it may not fully support all production environments. Users should exercise caution when deploying Boruta in critical systems.
- **Updates**: Monthly releases are planned during the beta phase. Updates may include new features, bug fixes, or breaking changes.
- **Changelog**: Each release will be accompanied by a detailed changelog on GitHub, outlining updates, known issues, and any migration steps for breaking changes.
- **Data Recovery**: While Malachit will make best efforts to preserve user data during updates, some updates may cause data loss. Such instances will be noted in the changelog.
---
#### **8. Communication and Notifications**
- **Updates**: All updates and announcements will be shared on the project’s GitHub repository.
- **Future Notifications**: To receive notifications about future releases and updates, users can sign up via the contact form at [https://io.malach.it](https://io.malach.it). The contact form complies with the io.malach.it [Privacy Policy](https://io.malach.it/privacy-policy.html).
- **Support**: For inquiries, users may contact pascal@malach.it. Malachit aims to respond within three business days but does not guarantee response times during the beta.
---
#### **9. Privacy and Data Use**
- The contact form on [https://io.malach.it](https://io.malach.it) collects personal data, such as email addresses, to facilitate notifications about Boruta updates.
- Data collected through the contact form will be handled in accordance with the io.malach.it [Privacy Policy](https://io.malach.it/privacy-policy.html).
- Malachit does not collect or retain sensitive user data through the beta software unless explicitly stated.
---
#### **10. Indemnity**
Users agree to indemnify and hold harmless Malachit, its affiliates, and contributors from any claims, damages, liabilities, or expenses arising from:
- Misuse of Boruta.
- Violation of these Terms.
- Unauthorized deployment or alteration of Boruta.
- Improper handling, collection, or storage of identity information collected by users through Boruta.
---
#### **11. Liability Disclaimer**
- Boruta is provided "as-is" during the beta phase without warranties of any kind, express or implied, including but not limited to fitness for a particular purpose or non-infringement.
- Malachit disclaims liability for any damages arising from:
- Improper use of Boruta or failure to adhere to its documentation.
- Unauthorized modifications or alterations made by users.
- Use of Boruta in high-risk environments where failure could lead to severe damages, such as critical infrastructure or life-support systems, without explicit prior approval from Malachit.
- Malachit reserves the right to restrict access to the beta for users engaged in misuse or harmful activities.
---
#### **12. Termination**
Malachit reserves the right to terminate or modify the beta program at any time. Upon termination, Boruta will remain accessible as software under the Apache 2.0 license.
---
#### **13. Transition to Full Release**
At the end of the beta phase, Boruta will transition to its full release while remaining open source under the Apache 2.0 License. Malachit reserves the right to release additional features, tools, or related services under separate terms. Users will be notified of the transition and encouraged to update to the latest version.
---
#### **14. Governing Law**
These Terms are governed by the laws of France. Malachit is registered as an Entreprise Individuelle (EI) under French law. Any disputes arising from these Terms will be resolved under the exclusive jurisdiction of the courts in France.
---
#### **15. Contact Information**
For any questions or concerns regarding Boruta or these Terms, please contact:
Pascal Knoth, Malachit
Email: pascal@malach.it
Website: [https://io.malach.it](https://io.malach.it)
================================================
FILE: LICENSE.md
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2022-2026 - Pascal Knoth (patatoid - malachit)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================

boruta is a standalone authorization server that aims to implement OAuth 2.0 and Openid Connect up to decentralized identity specifications. It provides administration tools and a customizable identity provider out of the box to manage authorization, but also an experimental gateway to apply access rules to incoming traffic.
## Status
boruta is currently in an __open beta phase__, if you are interested in the project and the tools it provides, you are encourage to test the product within your context. Production readyness will depend on your feedback, helping to fix the possible bugs and improve the solution usability. While being mostly stable and security asessed for some of its parts, boruta is a work in progress, please read the [General Terms and Conditions](GENERAL_TERMS_AND_CONDITIONS.md).
## Implemented specifications and certification
As it, boruta server aim to follow the RFCs from IETF:
- [RFC 6749 - The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749)
- [RFC 7662 - OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662)
- [RFC 7009 - OAuth 2.0 Token Revocation](https://tools.ietf.org/html/rfc7009)
- [RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636)
- [RFC 7521 - Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants](https://www.rfc-editor.org/rfc/rfc7521)
- [RFC 7523 - JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants](https://tools.ietf.org/html/rfc7523)
- [RFC 9449 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop)
- [RFC 9126 - OAuth 2.0 Pushed Authorization Requests](https://datatracker.ietf.org/doc/html/rfc9126)
And the specifications from the OpenID Foundation:
- [OpenID Connect core 1.0](https://openid.net/specs/openid-connect-core-1_0.html)
- [OpenID Connect Dynamic Client Registration 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-registration-1_0.html)
- [OpenID for Verifiable Credential Issuance](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html)
- [Self-Issued OpenID Provider v2](https://openid.net/specs/openid-connect-self-issued-v2-1_0.html)
- [OpenID for Verifiable Presentations - draft 21](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html)
This server has been certified for the Basic, Implicit, and Hybrid OpenID Provider profiles by the OpenID Foundation on October, 18th 2022 for the tagged versions 0.1.0 and 0.5.0
This server has been certified for the Config and Dynamic OpenID Provider profiles by the OpenID Foundation on May, 16th 2023 for the tagged version 0.2.0
This server has also been certified against the [European Blockchain Service Infrastructure (EBSI)](https://ec.europa.eu/digital-building-blocks/sites/display/EBSI) issuance test suite for the tagged version 0.4.0 and for verifiable credential verification for the tagged version 0.5.0.



## Documentation
Server documentation is available on github pages [here](https://malach-it.github.io/developers.boruta/docs/intro). It highlights how the server works, describing its architecture, parameters and the associated authentication / authorization flows. It is a Work In Progress, all feedback or contributions would be welcomed.
## DID creation and resolution
boruta may use [Universal resolver](https://github.com/decentralized-identity/universal-resolver) for DID resolution and [Universal registrar](https://github.com/decentralized-identity/universal-registrar) for DID creation. Those are to be configured as environment variables, respectively `DID_RESOLVER_BASE_URL` and `DID_REGISTRAR_BASE_URL`. DIDs are used in the decentralized identity flows and are present as key identifier header of the other generated JWTs.
## Integrated wallet
This project includes a demo wallet implemented for testing purposes. It is compliant with the decentralized identity flows but does not have neither secure storage nor portability features which makes it not production ready. Note that even if those features come in further releases, this wallet does not target to be an EUDI wallet as the European framework states.
## Installation
A [loom presentation](https://www.loom.com/share/77006360fdac44bc9113fab9cf30aba5) about how to get a server up and running.
Note that the easiest way to try the server is by using docker compose.
### Run an instance from docker
> Note this image is built for x86_64 architecture, for other architectures build yourself the image or use docker compose install that will build the image for your architecture.
A docker image is available at `malachit/boruta-server` on [DockerHub](https://hub.docker.com/r/malachit/boruta-server), you will need a postgres instance installed on your system with credentials provided as environment variables in `.env.*`.
1. Get environment file
```bash
wget https://raw.githubusercontent.com/malach-it/boruta-server/master/.env.dev
```
Once done you will be able to launch the server.
```bash
docker run -it --env-file .env.dev --network=host malachit/boruta-server:0.4.0
```
The applications will be available on different ports (depending on the values provided in `.env.dev`):
- http://localhost:4000 for the authorization server
- http://localhost:4001 for the admin interface
- http://localhost:4002 for the gateway
- http://localhost:4003 for the microgateway
Admin credentials are the one seeded and available in environment file.
### Run an instance from docker-compose
You can build and run the docker images as follow:
```bash
docker-compose up
```
The applications will be available on different ports (depending on the docker compose environment configuration):
- http://localhost:8080 for the authorization server
- http://localhost:8081 for the admin interface
- http://localhost:8082 for the gateway
- http://localhost:8083 for the microgateway
Admin credentials are the one seeded and available in environment file.
### Requirements
- Elixir >= 1.13
- postgreSQL >= 13
- node >= 16.5 (if you need to prepare assets)
### Run a release from scratch
1. first you need to get project dependencies
```bash
mix deps.get
```
2. you need to prepare assets in order for them to be included in the release
```bash
./scripts/prepare_assets.sh
```
3. then you can craft the release
```bash
MIX_ENV=prod mix release boruta
```
Once done, you can run the release as follow:
```bash
env $(cat .env.example | xargs) _build/prod/rel/boruta/bin/boruta start
```
The applications will be available on different ports (depending on the values provided in `.env.example`):
- http://localhost:8080 for the authorization server
- http://localhost:8081 for the admin interface
- http://localhost:8082 for the gateway
- http://localhost:8083 for the microgateway
Admin credentials are the one seeded and available in environment file.
### Run a development server
1. first you need to get project dependencies
```bash
mix deps.get
```
2. you need to prepare assets in order to fetch javascript dependencies
```bash
./scripts/prepare_assets.sh
```
3. because of the forwarding of requests between web and identity modules, you need to add the `/accounts` path prefix in configuration
```diff
--- a/apps/boruta_identity/config/config.exs
+++ b/apps/boruta_identity/config/config.exs
@@ -4,8 +4,8 @@ config :boruta_identity,
ecto_repos: [BorutaAuth.Repo, BorutaIdentity.Repo]
config :boruta_identity, BorutaIdentityWeb.Endpoint,
- url: [host: "localhost"],
- # url: [host: "localhost", path: "/accounts"],
+ # url: [host: "localhost"],
+ url: [host: "localhost", path: "/accounts"],
```
You now should be able to start the development server
```bash
env $(cat .env.dev | xargs) MIX_ENV=dev mix boruta.server
```
The applications will be available on different ports (depending on the values provided in `.env.dev`):
- http://localhost:4000 for the authorization server
- http://localhost:4001 for the admin interface
- http://localhost:4002 for the gateway
- http://localhost:4003 for the microgateway
Admin credentials are the one seeded and available in environment file.
### Default admin credentials
In order to authenticate to the administration interface you will be asked for credentials that are by default (seeded from environment variables) `admin@test.test` / `imaynotknowthat`.
## Environment variables
| Variable name | description |
| ---------------------------------- | ------------------- |
| `SECRET_KEY_BASE` | The Phoenix secret key base. It must be at least 64 cheracters long. |
| `POSTGRES_USER` | The database user provided as credentials in postgreSQL connections. |
| `POSTGRES_PASSWORD` | The database password provided as credentials in postgreSQL connections. |
| `POSTGRES_DATABASE` | The database name provided in postgreSQL connections. |
| `POSTGRES_HOST` | The database host provided in postgreSQL connections. |
| `POOL_SIZE` | The postgreSQL pool size of each application, the real connection count will be twice that value. |
| `MAX_LOG_RETENTION_DAYS` | The number of days the logs are kept to the server. This value defaults to 60. |
| `K8S_NAMESPACE` | If set along with K8S_SELECTOR, it setups libcluster in order to connect boruta erlang nodes in kubernetes together. |
| `K8S_SELECTOR` | If set along with K8S_NAMESPACE, it setups libcluster in order to connect boruta erlang nodes in kubernetes together. |
| `BORUTA_ADMIN_OAUTH_CLIENT_ID` | An uuidv4 string representing the admin oauth client id. It will be part of the client seeded in the setup task. |
| `BORUTA_ADMIN_OAUTH_CLIENT_SECRET` | The admin oauth client secret. It will be part of the client seeded in the setup task. |
| `BORUTA_ADMIN_OAUTH_BASE_URL` | The URL base URL of the authorization server admin will use (linked to above client_id and secret, without trailing slash). |
| `BORUTA_ADMIN_EMAIL` | The first admin email. It will be part of the user seeded in the setup task. |
| `BORUTA_ADMIN_PASSWORD` | The first admin password. It will be part of the user seeded in the setup task. |
| `BORUTA_ADMIN_HOST` | The host that represent the host where boruta admin server will be deployed to. |
| `BORUTA_ADMIN_BIND` | The IP address the boruta admin server will be bound to. |
| `BORUTA_ADMIN_PORT` | The port where boruta admin server will be exposed on. |
| `BORUTA_ADMIN_BASE_URL` | The base URL where boruta admin server http endpoint will be deployed to (without trailing slash). |
| `BORUTA_OAUTH_SCHEME` | The scheme that will be used for URL building, default to https. |
| `BORUTA_OAUTH_HOST` | The host where boruta oauth server will be deployed to. |
| `BORUTA_OAUTH_BIND` | The IP address the boruta oauth server will be bound to. |
| `BORUTA_OAUTH_PORT` | The port where boruta oauth server will be exposed on. |
| `BORUTA_OAUTH_BASE_URL` | The base URL where boruta oauth server http endpoint will be deployed to (without trailing slash). |
| `BORUTA_GATEWAY_PORT` | The port where boruta gateway will be exposed on. |
| `BORUTA_GATEWAY_SIDECAR_PORT` | The port where boruta microgateway will be exposed on. |
| `BORUTA_GATEWAY_CONFIGURATION_PATH`| The path containing the gateway static configuration. |
| `BORUTA_CONFIGURATION_PATH` | The path containing the boruta static configuration. |
| `BORUTA_SUB_RESTRICTED` | If set, the uid of the only user to have access to the administration interface. |
| `BORUTA_ORGANIZATION_RESTRICTED` | If set, the uid of the only organization to have access to the administration interface. |
| `DID_RESOLVER_BASE_URL` | Did resolver API endpoint, accroding to the [W3C DID resolution specification](https://w3c.github.io/did-resolution/) |
| `DID_REGISTRAR_BASE_URL` | Did registrar API endpoint, accroding to the [W3C DID registration specification](https://identity.foundation/did-registration/) |
| `DID_SERVICES_API_KEY` | API key granting access to DID revolver and registrar services. |
## Code of Conduct
This product community follows the code of conduct available [here](CODE_OF_CONDUCT.md)
## License
This code is released under the [Apache 2.0](LICENSE.md) license.
## General Terms and Conditions
By using Boruta, you agree to the [General Terms and Conditions](GENERAL_TERMS_AND_CONDITIONS.md), which complement the software's Apache 2.0 License.
## About boruta
The name boruta comes from a polish legend where he is a gentle devil (an angel, maybe) that is such evil that having him at home makes you safe. He was living during the middle ages in the castle of the little town of Leczyca, since then the people from there have a little figurine of him at home helping the house to be protected from bad fate.
================================================
FILE: ansible/.kube/kubeconfig-k8s-boruta.yaml
================================================
$ANSIBLE_VAULT;1.1;AES256
61666431343966366336333965363036373037353566316363333465633762663931623438373666
6238346264616633303238616462393462373662343139360a613866366365613266373236383066
34663165333365633762623961333565396361353439303538363466376463383133653333663130
6236346365633562390a646266363130666465393530653864363832613533393862353931366238
31383135303361633766643963633436356331316333343164346563623532393235373432356261
31313035313235666337383030643766626236366263313537666163653436633332396531626430
34643964393564343732356262303962633764323330363738633634373436303434313239303833
66373835623834363165303062626236323034386464373236303233653263633661663465323237
37636463636363313132663434386134363433643464373131363765633562316366313537346130
36373065383430643731356362613166613432616336353538336137326331646564376334316430
37353761633665653937623138333931613564633366346331343438613665346638323762353266
32363834643236323937393364666531666432393666346634643861613134393137633338666431
62336361663731356139373433303130643334333831343537326238323863653465323265623963
64383766656436393336343838313634353731313133363335393235616664346564393862653334
61323961613132633036326138363166376534616331303433633435313237626133646665656230
35653264353137643530336365623937653662306535343863336230333732366333343166643930
62666561383331613335356331393738626163613432393630343431623738656439633536393364
33636634363663313763613535336264303465386539636530633463623931313730646439353939
38613434663137643530383165633666323963626262366162333831626363613965313631346163
35333930633435646239376134356138623431663530323330363335326237626365383436323836
65646363346137303032363666326134316332313962326438353336643233316239313535396435
37333937326334653432333931376630363339346435666632386138373230626562366666313163
31323931383066383762313266393535383165363464386439666461393538353138366265656331
30323362383634336334376466336565643430613436666265313939646534386563376336646562
38356562383464326162336639626265393133323533383338613036636237353264393665333862
34666434323133623030396263653230303534376239363866336366626364323632373663303437
36363466326533633361373465313635623432363864613866633739656232663038623730353736
35653338633561376235653761663433353034633630666564303238386437633137373034373836
39373537323539653832383635353231663162356139373065336430376330373532346164336536
61343165353365666535393534613366396439653338616333373836376234666335313866386636
64616636333635303230313632316162353033626364613865333934313764643839353963336561
38353238396138333066386530643762303064326363396638343731646465643731653335373330
34643035326533383633333465353132303235663532636239633935386339613037393437356434
37383538613065356133343038376534346665353136633530343763363935616437616632393438
32396562626165386633646436626262646132326161636163313231396533633866333564653066
37326236323335366638633234343763383665616265373064353033396234333937316661326637
38653434386463363637636566353563626539366637636635366362386561356461303961303830
64623334303564663931633431616439313939633562343561386665353264663631346634316234
62643762636531306163656436353664663231316339326663643064376464306433363332333864
32356161336635626566316362623332356636623062326333383936333130336163663965373134
34386136303962316131373165656562623766633339373039313931376463626463343366303061
31373734303034613565373431313736376463316435666136323536633661363433633237333739
37366638633066643930656133363137396662353765633132623766386339636639393465383133
61353938373736393439303461373133656537313361383839343038323232363130643333663564
35353963373136646332323436626337353962343766356235373633353936376333366164333934
39366366353966656237356438353432666534383039353931376435393761363634323166326336
66373738356331356132646435333964363230393361366335363633666132386339373138623133
33363431636333646638636162643434643039346239653930326636303132303535323866666264
33623834343230353232313832623437303065306637653733383364323332306361383232303831
39663361386333313238316364396162626161346333343934333565323833383162353734343962
38373731663034396563613130363861366664323961373437343739386436656432653765313437
61613966626536653766363162356132643263646235656263343538643035623938353064643431
34336431346165646339656633336130643336343134633633663638393964326666383231633835
39313966663064386234643464623966386436666464383636633837373433313663323165383739
64653963356565363433643338633039316566366630393764343165343134366264393933306339
34313536343632386565326235613664633261626263623931353938623265323237353338383535
38363633343838393163636361383835653334303162336632313038316235323565653166646131
32333462663964306436306461313330353932313034656334303839643135623135323832363232
34613234316530363439346165373539393231616534303639346163303135313462616231363034
38366266396238333366363936373763303537353737656330363333616239653430363861386538
35353232316435663130316134333363366564396639313166396439303065613637356434383666
34323230636235366262656238646263303936643434363337323561633063303134636134353137
33306633636135396361373364383533393761633533396361643131346564623562653762303235
32386262663936333436333634386338333739613665373439333533306362346264343431633339
34663864313231323565386131653537343037353261616561656635353363626133323362646136
61353961336136323363646132336266336637616436663535393963366362316634393430383731
61663065383461643636333938323533616630306332353831663933653062653365646666383030
39336534373831613834626664363132346530326431323866323163633630373061666436656230
31633735613130343961323061356461303464643839393565303837303639303864393433663436
30663834316538353934363439396632306564313631663431353638323633653434343936353936
62363939316464326366396464313039353266306533306365663963386666643633306238643436
64323337336130366564303766383137633562373837383963326539383733363139356135663766
39653631393839363530313034313866383033333861313239346236623935623264313333376330
62326233393863323365323537653336303661643131316665373538343332396165306463653064
61393463386331313336613164613630393031633865316139663932323465623263316234623563
66356363326562336133343163363661373062323531616333376363653362316630616631616335
66306266623730383935396134666639666266306636353338366332386164656135373166643838
64386235666265613463343631343164363133613063643466303435313934343965383337303137
36323133633330303539346539313164313863323363353462303635396233666638353164303834
63396539356439636432666562333339663666396139373661383836373439356332663337643539
33366631396662323936636238626266653333393362383963376336386530326664396538316334
63323263666161666461343334323966376639623439366231643137373733343436623564326332
32386461613238636664656635613530626239303862316566303530326233363666663162323334
64643161656166613963633733363636373736656166653062643765373731306533333964333264
36343063326466613230323638373635636538323932316231346230373963633238646239643134
32323635383035323638316231653736626666643939363839333461636332386338313532323065
63363663333764323734663665313036326438313330316338666665326261316132653362303037
65656138383961373664396463373562663438323864363739373464643632353632366266666465
30353733643264333837633161653932316135326665643434333230376366643039363165313530
36356636653965623761303833303533346630656561663531666132396633633861376637333939
61316536666335653563613032653839343437333664313364373836363263376465383963363139
34386561326634323062333265333736356232623630356666623061656261373136336566323961
35303764626462346361396438356634353430333661666138366362303039353066363637346164
64663232316333393334376335326163333861303536636163353364363362303566383063646465
30306538623231343137316362656632343032616432323636653638363463626437356538663033
37643666343166636638636639316331376463636362336531306461323935346236343163356330
30666662393938653766613336353134656636373366373538363463303861636164
================================================
FILE: ansible/deploy.yml
================================================
- hosts: localhost
tasks:
- name: Add stable bitnami repo
kubernetes.core.helm_repository:
name: bitnami
repo_url: https://charts.bitnami.com/bitnami
- name: Add stable jetstack repo
kubernetes.core.helm_repository:
name: jetstack
repo_url: https://charts.jetstack.io
- name: Create a k8s namespace
kubernetes.core.k8s:
api_version: v1
name: boruta-staging
kind: Namespace
state: present
# - name: Install cert-manager helm package
# kubernetes.core.helm:
# name: cert-manager
# chart_ref: jetstack/cert-manager
# chart_version: 1.11.1
# release_namespace: cert-manager
# create_namespace: true
# values:
# installCRDs: true
# upgrade looks to be complicated, variable names contain breaking changes
# the master configuration file - https://github.com/bitnami/charts/blob/main/bitnami/postgresql/values.yaml
#
# - name: Install postgres helm package
# kubernetes.core.helm:
# name: postgres
# chart_ref: bitnami/postgresql
# chart_version: "12.2.7"
# release_namespace: boruta-staging
# values:
# global.postgresql.auth.postgresPassword: "{{ postgresql_password }}"
# primary.extendedConfiguration: |
# max_connections = 1024
- name: Create libcluster role
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: libcluster-role
namespace: boruta-staging
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- name: Create libcluster binding
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: libcluster-bindings
namespace: boruta-staging
subjects:
- kind: ServiceAccount
name: default
namespace: boruta-staging
roleRef:
kind: Role
name: libcluster-role
apiGroup: rbac.authorization.k8s.io
- name: Create SSL let's encrypt certificate
kubernetes.core.k8s:
state: present
definition:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-production
spec:
acme:
email: io.pascal.knoth@gmail.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: boruta-staging-ssl-account-key
solvers:
- http01:
ingress:
class: nginx
selector:
dnsZones:
- 'boruta.patatoid.fr'
- name: Create Boruta Ingress
kubernetes.core.k8s:
state: present
definition:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
namespace: boruta-staging
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: letsencrypt-production
# nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: "{{ gateway_host }}"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: boruta-gateway
port:
number: 5000
- host: "{{ httpbin_sidecar_host }}"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: boruta-httpbin-sidecar
port:
number: 5001
- host: "{{ protected_httpbin_sidecar_host }}"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: boruta-protected-httpbin-sidecar
port:
number: 5001
- host: "{{ oauth_host }}"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: boruta-oauth
port:
number: 4001
- host: "{{ admin_host }}"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: boruta-admin
port:
number: 4002
tls:
- hosts:
- "{{ oauth_host }}"
- "{{ admin_host }}"
- "{{ gateway_host }}"
- "{{ httpbin_sidecar_host }}"
- "{{ protected_httpbin_sidecar_host }}"
secretName: boruta-staging-cert
- name: create boruta app ConfigMap
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: ConfigMap
metadata:
name: boruta-env
namespace: boruta-staging
data:
SECRET_KEY_BASE: "{{ secret_key_base }}"
POSTGRES_USER: postgres
POSTGRES_PASSWORD: "{{ postgresql_password }}"
POSTGRES_DATABASE: boruta
POSTGRES_HOST: postgres-postgresql
MAX_LOG_RETENTION_DAYS: "180"
K8S_NAMESPACE: boruta-staging
K8S_SELECTOR: app=boruta
BORUTA_ADMIN_OAUTH_CLIENT_ID: "{{ admin_client_id }}"
BORUTA_ADMIN_OAUTH_CLIENT_SECRET: "{{ admin_client_secret }}"
BORUTA_ADMIN_OAUTH_BASE_URL: "{{ oauth_base_url }}"
BORUTA_ADMIN_EMAIL: "{{ admin_email }}"
BORUTA_ADMIN_PASSWORD: "{{ admin_password }}"
BORUTA_ADMIN_HOST: "{{ admin_host }}"
BORUTA_ADMIN_PORT: "4002"
BORUTA_ADMIN_BASE_URL: "{{ boruta_base_url }}"
BORUTA_OAUTH_HOST: "{{ oauth_host }}"
BORUTA_OAUTH_PORT: "4001"
BORUTA_OAUTH_BASE_URL: "{{ oauth_base_url }}"
BORUTA_GATEWAY_PORT: "5000"
BORUTA_GATEWAY_SIDECAR_PORT: "5001"
BORUTA_ORGANIZATION_RESTRICTED: "{{ boruta_organization_restricted }}"
DID_SERVICES_API_KEY: "{{ did_services_api_key }}"
POOL_SIZE: "5"
- name: Setup boruta auth database
register: database_setup
kubernetes.core.k8s:
state: present
definition:
apiVersion: batch/v1
kind: Job
metadata:
name: boruta-auth-setup
namespace: boruta-staging
backoffLimit: 3
spec:
template:
spec:
containers:
- image: "ghcr.io/malach-it/boruta-server:master"
command: ["/app/bin/boruta"]
args: ["eval", "BorutaWeb.Release.setup"]
envFrom:
- configMapRef:
name: boruta-env
imagePullPolicy: Always
name: boruta
restartPolicy: OnFailure
imagePullSecrets:
- name: dockerconfigjson-github-com
- name: Create Boruta logs persistent volume claim
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: logs-pvc
namespace: boruta-staging
spec:
storageClassName: standard-rwo
accessModes:
- ReadWriteOnce # TODO will cause issues when running on multiple nodes
resources:
requests:
storage: 5Gi
- name: Get blue/green deployment status
kubernetes.core.k8s_info:
kind: Service
namespace: boruta-staging
label_selectors:
- "app=boruta"
register: boruta_services
- name: Create Boruta blue/green deployment
kubernetes.core.k8s:
state: present
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ 'boruta-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-blue' else 'boruta-blue' }}"
namespace: boruta-staging
spec:
replicas: 1
strategy:
type: Recreate
rollingUpdate: null
selector:
matchLabels:
deployment: "{{ 'boruta-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-blue' else 'boruta-blue' }}"
template:
metadata:
name: boruta
labels:
deployment: "{{ 'boruta-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-blue' else 'boruta-blue' }}"
app: boruta
spec:
volumes:
- name: logs
persistentVolumeClaim:
claimName: logs-pvc
containers:
- image: "ghcr.io/malach-it/boruta-server:{{ release_tag }}"
readinessProbe:
httpGet:
path: /healthcheck
port: 4001
env:
- name: BORUTA_GATEWAY_CONFIGURATION_PATH
value: "./config/example-gateway-configuration.yml"
envFrom:
- configMapRef:
name: boruta-env
imagePullPolicy: Always
name: boruta
volumeMounts:
- mountPath: "/app/log"
name: logs
imagePullSecrets:
- name: dockerconfigjson-github-com
- name: Wait for deployment readyness
shell: "kubectl -n boruta-staging wait --for=condition=Ready po --all -l deployment={{ 'boruta-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-blue' else 'boruta-blue' }}"
retries: 6
delay: 5
register: result
until: result.rc == 0
- name: Create OAuth Service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: boruta-oauth
namespace: boruta-staging
labels:
app: boruta
spec:
selector:
deployment: "{{ 'boruta-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-blue' else 'boruta-blue' }}"
ports:
- protocol: TCP
targetPort: 4001
name: oauth-tcp
port: 4001
- name: Create Admin Service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: boruta-admin
namespace: boruta-staging
labels:
app: boruta
spec:
selector:
deployment: "{{ 'boruta-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-blue' else 'boruta-blue' }}"
ports:
- protocol: TCP
targetPort: 4002
name: admin-tcp
port: 4002
- name: Create Gateway Service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: boruta-gateway
namespace: boruta-staging
labels:
app: boruta
spec:
selector:
deployment: "{{ 'boruta-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-blue' else 'boruta-blue' }}"
ports:
- protocol: TCP
targetPort: 5000
name: gateway-tcp
port: 5000
- name: Create httpbin sidecar Service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: boruta-httpbin-sidecar
namespace: boruta-staging
labels:
app: boruta-httpbin
spec:
selector:
deployment: "{{ 'boruta-httpbin-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-httpbin-blue' else 'boruta-httpbin-blue' }}"
ports:
- protocol: TCP
targetPort: 5001
name: httpbin-tcp
port: 5001
- name: Create protected httpbin sidecar Service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: boruta-protected-httpbin-sidecar
namespace: boruta-staging
labels:
app: boruta-protected-httpbin
spec:
selector:
deployment: "{{ 'boruta-protected-httpbin-green' if boruta_services.resources[0].spec.selector.deployment == 'boruta-protected-httpbin-blue' else 'boruta-protected-httpbin-blue' }}"
ports:
- protocol: TCP
targetPort: 5001
name: gateway-tcp
port: 5001
- name: Delete Boruta blue/green deployment
kubernetes.core.k8s:
state: absent
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ 'boruta-blue' if boruta_services.resources[0].spec.selector.deployment == 'boruta-blue' else 'boruta-green' }}"
namespace: boruta-staging
================================================
FILE: ansible/hosts
================================================
[local]
localhost
================================================
FILE: ansible/inventories/gke
================================================
[gke]
localhost
[gke:vars]
ansible_connection=local
================================================
FILE: ansible/inventories/local
================================================
[local]
localhost
[local:vars]
ansible_connection=local
================================================
FILE: ansible/inventories/scaleway
================================================
[scaleway]
localhost
[scaleway:vars]
ansible_connection=local
================================================
FILE: apps/boruta_admin/.formatter.exs
================================================
[
import_deps: [:ecto, :phoenix],
inputs: ["*.{ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{ex,exs}"],
subdirectories: ["priv/*/migrations"]
]
================================================
FILE: apps/boruta_admin/.gitignore
================================================
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
boruta_admin-*.tar
# If NPM crashes, it generates a log, let's ignore it too.
npm-debug.log
# The directory NPM downloads your dependencies sources to.
/assets/node_modules/
# Since we are building assets from assets/,
# we ignore priv/static. You may want to comment
# this depending on your deployment strategy.
/priv/static/
================================================
FILE: apps/boruta_admin/assets/.browserslistrc
================================================
> 1%
last 2 versions
================================================
FILE: apps/boruta_admin/assets/.editorconfig
================================================
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
================================================
FILE: apps/boruta_admin/assets/.eslintrc.js
================================================
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'@vue/standard'
],
plugins: ['prettier'],
rules: {
'prettier/prettier': 'error',
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'camelcase': 'off',
'prefer-promise-reject-errors': 'off'
},
parserOptions: {
parser: '@babel/eslint-parser'
},
requireConfigFile: false
}
================================================
FILE: apps/boruta_admin/assets/.gitignore
================================================
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: apps/boruta_admin/assets/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Boruta · Phoenix Framework</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" integrity="sha512-8bHTC73gkZ7rZ7vpqUQThUDhqcNFyYi2xgDgPDHc+GXVGHXq+xPjynxIopALmOPqzo9JZj0k6OqqewdGO3EsrQ==" crossorigin="anonymous" />
<script>
window.env = {
BORUTA_ADMIN_OAUTH_CLIENT_ID: '6a2f41a3-c54c-fce8-32d2-0324e1c32e20',
BORUTA_ADMIN_OAUTH_BASE_URL: 'http://localhost:4000',
BORUTA_ADMIN_BASE_URL: 'http://localhost:4001',
BORUTA_ADMIN_BASE_SOCKET_URL: 'ws://localhost:4001'
}
</script>
</head>
<body>
<noscript>
<strong>We're sorry but boruta-admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script type="module" src="/src/main.js"></script>
</body>
</html>
================================================
FILE: apps/boruta_admin/assets/jsconfig.json
================================================
{
"include": [
"./src/**/*"
]
}
================================================
FILE: apps/boruta_admin/assets/package.json
================================================
{
"name": "boruta-admin",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vite",
"build": "vite build --emptyOutDir",
"build:watch": "vite build --watch --emptyOutDir",
"deploy": "vite build"
},
"dependencies": {
"axios": "^1.15.2",
"boruta-client": "github:malach-it/boruta-client",
"chartjs-adapter-moment": "^1.0.0",
"codejar": "^3.5.0",
"core-js": "^2.6.5",
"google-palette": "^1.1.0",
"jwt-decode": "^3.1.2",
"lodash": "^4.18.1",
"moment": "^2.29.4",
"phoenix": "^1.5.7",
"phoenix-socket": "^1.2.3",
"prismjs": "^1.26.0",
"semantic-ui-css": "^2.4.1",
"socket.io-client": "^4.2.0",
"vue": "^3.2.13",
"vue-chart-3": "^3.1.8",
"vue-router": "^4.0.12",
"vuex": "^4.0.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.18.9",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@vitejs/plugin-vue": "^5.2.3",
"@vue/eslint-config-standard": "^4.0.0",
"autoprefixer": "^10.4.2",
"chai": "^4.1.2",
"eslint": "^8.7.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^8.3.0",
"prettier": "2.7.1",
"sass": "^1.48.0",
"vite": "^6.3.4",
"vite-plugin-node-polyfills": "^0.23.0",
"vite-plugin-singlefile": "^2.2.0"
}
}
================================================
FILE: apps/boruta_admin/assets/postcss.config.js
================================================
module.exports = {
plugins: {
autoprefixer: {}
}
}
================================================
FILE: apps/boruta_admin/assets/src/App.vue
================================================
<template>
<router-view></router-view>
</template>
<script>
export default {
name: 'App'
}
</script>
<style lang="scss">
body {
min-height: 100%;
height: auto;
width: 100%;
overflow-x: hidden;
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Breadcrumb.vue
================================================
<template>
<div class="ui breadcrumb">
<span v-for="(item, index) in items" :key="item.path">
<span v-if="index + 1 < items.length">
<router-link :to="item.path" class="section">{{ item.label }}</router-link>
<i class="right angle icon divider"></i>
</span>
<span class="section" v-else>
{{ item.label }}
</span>
</span>
</div>
<hr />
</template>
<script>
const labels = {
'root': 'Home',
'not-found': 'Not found',
'bad-request': 'Bad request',
'dashboard': 'Dashboard',
'request-logs': 'Requests',
'business-event-logs': 'Business Events',
'identity-providers': "Identity providers",
'new-identity-provider': 'Create',
'identity-provider': ({ params }) => params.identityProviderId,
'edit-layout-template': 'Edit layout template',
'edit-session-template': 'Edit login template',
'edit-totp-registration-template': 'Edit TOTP registration template',
'edit-totp-authentication-template': 'Edit TOTP authentication template',
'edit-webauthn-registration-template': 'Edit Webauthn registration template',
'edit-webauthn-authentication-template': 'Edit Webauthn authentication template',
'edit-choose-session-template': 'Edit choose session template',
'edit-registration-template': 'Edit registration template',
'edit-edit-user-template': 'Edit user edition template',
'edit-new-reset-password-template': 'Edit send reset password instructions template',
'edit-edit-reset-password-template': 'Edit reset password template',
'edit-new-confirmation-template': 'Edit send confirmation instructions template',
'edit-new-consent-template': 'Edit consent template',
'edit-credential-offer-template': 'Edit credential offer template',
'edit-cross-device-presentation-template': 'Edit verifiable presentation template',
'backends': 'Backends',
'backend': ({ params }) => params.backendId,
'new-backend': 'Create',
'edit-confirmation-instructions-email-template': 'Edit confirmation instructions email template',
'edit-reset-password-instructions-email-template': 'Edit reset password instructions email template',
'edit-tx-code-email-template': 'Edit transaction code email template',
'users': 'Users',
'new-user': 'Create',
'user-import': 'Import',
'edit-user': ({ params }) => params.userId,
'organizations': 'Organizations',
'new-organization': 'Create',
'edit-organization': ({ params }) => params.organizationId,
'clients': 'Clients',
'key-pair-list': 'Key pairs',
'new-client': 'Create',
'client': ({ params }) => params.clientId,
'upstreams': 'Upstreams',
'new-upstream': 'Create',
'upstream': ({ params }) => params.upstreamId,
'scopes': 'Scopes',
'scope': ({ params }) => params.scopeId,
'roles': 'Roles',
'new-role': 'Create',
'role': ({ params }) => params.roleId,
'configuration': 'Configuration',
'configuration-file-upload': 'Configuration file upload',
'error-template-list': 'Error templates',
'edit-bad-request-template': 'Edit bad request template',
'edit-forbidden-template': 'Edit forbidden template',
'edit-not-found-template': 'Edit not found template',
'edit-internal-server-error-template': 'Edit internal server error template'
}
export default {
name: 'breadcrumb',
computed: {
items () {
const items = this.$route.matched
.filter(({ name }) => name)
.filter(({ name }) => labels[name])
.map((route) => {
const { name } = route
const label = labels[name]
return {
label: (label instanceof Function) ? label(this.$route) : label,
path: { name, params: this.$route.params }
}
})
return items
}
}
}
</script>
<style scoped lang="scss">
.ui.breadcrumb {
font-size: 1em;
line-height: 1em;
padding: 1rem 1rem 0 1rem;
.section {
display: inline;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Feedback.vue
================================================
<template>
<div class="feedback">
<div @click="toggle()" class="ui yellow feedback button">Feedback</div>
<div class="feedback overlay" v-if="show">
<div class="ui feedback wrapper massive center aligned segment">
<i class="ui white close icon" @click="toggle()"></i>
<h2>Your feedback has value</h2>
<div class="rating">
<a v-for="rating in ratings" @click="setRating(rating)">
<span class="star" v-if="isRatingActive(rating)">★</span>
<span class="star" v-if="!isRatingActive(rating)">☆</span>
</a>
</div>
<form target="_blank" class="ui large form" action="https://gateway.boruta.patatoid.fr/store" method="POST">
<input type="hidden" name="rating" :value="rating" />
<div class="field">
<textarea name="feedback" v-model="feedback" placeholder="Say something (optional)" />
</div>
<div class="field">
<div class="ui checkbox">
<input name="_privacy_policy" type="checkbox" v-model="privacy">
<label>I have read the <a href="https://io.malach.it/privacy-policy.html" target="_blank"> Privacy policy</a></label>
</div>
</div>
<button :disabled="!privacy" class="ui fluid violet button" type="submit">Submit</button>
</form>
</div>
</div>
</div>
</template>
<script>
import oauth from '../services/oauth.service'
export default {
data () {
const ratings = ['horrible', 'poor', 'neutral', 'good', 'excellent']
return {
show: false,
ratings,
rating: null,
feedback: null,
privacy: false
}
},
computed: {
isRatingActive () {
return (rating) => {
return this.ratings.indexOf(rating) <= this.ratings.indexOf(this.rating)
}
}
},
methods: {
toggle () {
this.show = !this.show
},
setRating (rating) {
this.rating = rating
}
}
}
</script>
<style scoped lang="scss">
.feedback.button {
position: absolute;
right: 9em;
top: .5em;
}
.feedback.overlay {
position: fixed;
right: 1rem;
bottom: calc(40px + 1rem);
z-index: 1000;
}
.feedback.wrapper {
position: relative;
.close {
position: absolute;
top: -1.2em;
right: 0;
cursor: pointer;
}
.rating {
margin-bottom: 1em;
font-size: 2rem;
height: 2.4rem;
display: flex;
align-items: center;
justify-content: center;
.star {
display: block;
width: 2.4rem;
cursor: pointer;
font-weight: bold;
font-size: 1em;
color: #fbbd08!important;
&:hover {
font-size: 1.4em;
transition: all .2s ease-in-out;
}
}
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/BackendForm.vue
================================================
<template>
<div class="ui backend-form segment">
<FormErrors :errors="backend.errors" v-if="backend.errors" />
<form class="ui form" @submit.prevent="submit">
<div ref="tabularMenu" class="ui top attached stackable tabular menu">
<a id="general-configuration" @click="openTab" class="active item">General configuration</a>
<a id="type" @click="openTab" class="item">Type</a>
<a id="email-configuration" @click="openTab" class="item">Email configuration</a>
<a id="identity-federation" @click="openTab" class="item">Identity federation</a>
<a id="verifiable-credentials" @click="openTab" class="item">Verifiable credentials</a>
<a id="user-metadata" @click="openTab" class="item">User metadata</a>
</div>
<div ref="form">
<div ref="general-configuration" data-tab="general-configuration" class="ui bottom attached active tab segment">
<h2>General configuration</h2>
<div class="field" :class="{ 'error': backend.errors?.name }">
<label>Name</label>
<input type="text" v-model="backend.name" placeholder="Shiny new backend">
</div>
<div class="ui info message">
Default backend will be used in case of resource owner password credentials requests.
</div>
<div class="field" :class="{ 'error': backend.errors?.is_default }">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="backend.is_default">
<label>Default</label>
</div>
</div>
<div class="ui info message">
Newly created users will have a default organization along with them.
</div>
<div class="field" :class="{ 'error': backend.errors?.create_default_organization }">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="backend.create_default_organization">
<label>Create default organization</label>
</div>
</div>
<h2>Roles</h2>
<RolesField :currentRoles="backend.roles" @delete-role="deleteRole" @add-role="addRole" />
</div>
<div ref="type" data-tab="type" class="ui bottom attached tab segment">
<h2>Backend type</h2>
<div class="field" :class="{ 'error': backend.errors?.type }">
<label>Type</label>
<select v-model="backend.type">
<option value="Elixir.BorutaIdentity.Accounts.Internal">Internal</option>
<option value="Elixir.BorutaIdentity.Accounts.Ldap">LDAP</option>
</select>
</div>
<section v-if="backend.type == 'Elixir.BorutaIdentity.Accounts.Internal'">
<h3>Internal configuration</h3>
<div class="field" :class="{ 'error': backend.errors?.password_hashing_alg }">
<label>Password hashing algorithm</label>
<select v-model="backend.password_hashing_alg" @change="onAlgorithmChange">
<option :value="alg.name" v-for="alg in passwordHashingAlgorithms" :key="alg">{{ alg.label }}</option>
</select>
</div>
<h4>Password hashing algorithm options</h4>
<div class="field" v-for="opt in passwordHashingOpts" :key="opt.name" :class="{ 'error': backend.errors?.password_hashing_opts }">
<label>{{ opt.label }}</label>
<input :type="opt.type" v-model="backend.password_hashing_opts[opt.name]" :placeholder="opt.default">
</div>
</section>
<section v-if="backend.type == 'Elixir.BorutaIdentity.Accounts.Ldap'">
<h3>LDAP configuration</h3>
<div class="field" :class="{ 'error': backend.errors?.ldap_host }">
<label>Host</label>
<input type="text" v-model="backend.ldap_host" placeholder="example.com">
</div>
<div class="field" :class="{ 'error': backend.errors?.ldap_user_rdn_attribute }">
<label>User RDN attribute</label>
<input :type="text" v-model="backend.ldap_user_rdn_attribute" placeholder="sn" />
</div>
<div class="field" :class="{ 'error': backend.errors?.ldap_base_dn }">
<label>Base distinguished name (dn)</label>
<input type="text" v-model="backend.ldap_base_dn" placeholder="dc=example,dc=com">
</div>
<div class="field" :class="{ 'error': backend.errors?.ldap_ou }">
<label>Users organization unit (ou)</label>
<input type="text" v-model="backend.ldap_ou" placeholder="ou=People">
</div>
<div class="field" :class="{ 'error': backend.errors?.ldap_master_dn }">
<label>Master distinguished name <i>(needed only for user edition)</i></label>
<input type="text" v-model="backend.ldap_master_dn" placeholder="cn=admin,dc=ldap,dc=test">
</div>
<div class="field" :class="{ 'error': backend.errors?.ldap_master_password }">
<label>Master password <i>(needed only for user edition)</i></label>
<div class="ui left icon input">
<input :type="ldapMasterPasswordVisible ? 'text' : 'password'" autocomplete="new-password" v-model="backend.ldap_master_password" />
<i class="eye icon" :class="{ 'slash': ldapMasterPasswordVisible }" @click="ldapMasterPasswordVisibilityToggle()"></i>
</div>
</div>
<div class="field" :class="{ 'error': backend.errors?.ldap_pool_size }">
<label>Pool size</label>
<input type="number" v-model="backend.ldap_pool_size" placeholder="5">
</div>
</section>
</div>
<div ref="email-configuration" data-tab="email-configuration" class="ui bottom attached tab segment">
<h2>Email configuration</h2>
<h3>SMTP configuration</h3>
<div class="field" :class="{ 'error': backend.errors?.smtp_from }">
<label>From</label>
<input type="text" v-model="backend.smtp_from" placeholder="from@mail.example">
</div>
<div class="field" :class="{ 'error': backend.errors?.smtp_relay }">
<label>Relay</label>
<input type="text" v-model="backend.smtp_relay" placeholder="smtp.example.com">
</div>
<div class="field" :class="{ 'error': backend.errors?.smtp_username }">
<label>Username</label>
<input type="text" v-model="backend.smtp_username" placeholder="username">
</div>
<div class="field" :class="{ 'error': backend.errors?.smtp_password }">
<label>Password</label>
<div class="ui left icon input">
<input :type="smtpPasswordVisible ? 'text' : 'password'" autocomplete="new-password" v-model="backend.smtp_password" />
<i class="eye icon" :class="{ 'slash': smtpPasswordVisible }" @click="smtpPasswordVisibilityToggle()"></i>
</div>
</div>
<div class="field" :class="{ 'error': backend.errors?.smtp_ssl }">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="backend.smtp_ssl">
<label>SSL</label>
</div>
</div>
<div class="field" :class="{ 'error': backend.errors?.smtp_tls }">
<label>TLS</label>
<select v-model="backend.smtp_tls">
<option value="always">Always</option>
<option value="never">Never</option>
<option value="if_available">If available</option>
</select>
</div>
<div class="field" :class="{ 'error': backend.errors?.smtp_port }">
<label>Port</label>
<input type="number" v-model="backend.smtp_port" placeholder="25">
</div>
<h3>Email templates</h3>
<div v-if="backend.isPersisted" class="ui segment">
<router-link
:to="{ name: 'edit-confirmation-instructions-email-template', params: { backendId: backend.id } }"
class="ui fluid blue button">Edit confirmation template</router-link>
</div>
<div v-if="backend.isPersisted" class="ui segment">
<router-link
:to="{ name: 'edit-reset-password-instructions-email-template', params: { backendId: backend.id } }"
class="ui fluid blue button">Edit reset password template</router-link>
</div>
<div v-if="backend.isPersisted" class="ui segment">
<router-link
:to="{ name: 'edit-tx-code-email-template', params: { backendId: backend.id } }"
class="ui fluid blue button">Edit transaction code template</router-link>
</div>
</div>
<div ref="identity-federation" data-tab="identity-federation" class="ui bottom attached tab segment">
<h2>Identity federation (login with)</h2>
<div v-for="federatedServer in backend.federated_servers" class="ui federated-server-field segment">
<i class="ui large close icon" @click="deleteFederatedServer(federatedServer)"></i>
<h3>Federated server</h3>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Server name</label>
<input type="text" v-model="federatedServer.name" placeholder="boruta">
</div>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Client ID</label>
<input type="text" v-model="federatedServer.client_id">
</div>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Client secret</label>
<div class="ui left icon input">
<input :type="federatedServer.clientSecretVisible ? 'text' : 'password'" autocomplete="new-password" v-model="federatedServer.client_secret" />
<i class="eye icon" :class="{ 'slash': federatedServer.clientSecretVisible }" @click="federatedServerVisibilityToggle(federatedServer)"></i>
</div>
</div>
<div class="ui info message">
You'll need to fill the redirect uri on the remote server `${BORUTA_OAUTH_HOST}/accounts/backends/:backend_id/:federated_server_name/callback`
</div>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Base URL</label>
<input type="text" v-model="federatedServer.base_url">
</div>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>scope <i>(separated with a whitespace)</i></label>
<input type="text" v-model="federatedServer.scope">
</div>
<h4>Federated metadata</h4>
<div class="ui federated-metadata-fields segment" v-for="metadataEndpoint in federatedServer.metadata_endpoints || []">
<h5>Metadata endpoint configuration</h5>
<i class="ui large close icon" @click="deleteMetadataEndpoint(federatedServer, metadataEndpoint)"></i>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Metadata endpoint URL</label>
<input type="text" v-model="metadataEndpoint.endpoint">
</div>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Metadata endpoint claims <i>(separated with a whitespace)</i></label>
<input type="text" v-model="metadataEndpoint.claims">
</div>
</div>
<div class="field">
<a class="ui blue fluid button" @click="addMetadataEndpoint(federatedServer)">Add a federated metadata endpoint</a>
</div>
<h4>Federated server endpoints</h4>
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="federatedServer.isDiscovery">
<label>Use OpenID discovery</label>
</div>
</div>
<div v-if="federatedServer.isDiscovery">
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Discovery path</label>
<input type="text" v-model="federatedServer.discovery_path">
</div>
</div>
<div v-else>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Userinfo path</label>
<input type="text" v-model="federatedServer.userinfo_path">
</div>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Authorize path</label>
<input type="text" v-model="federatedServer.authorize_path">
</div>
<div class="field" :class="{ 'error': backend.errors?.federated_servers }">
<label>Token path</label>
<input type="text" v-model="federatedServer.token_path">
</div>
</div>
</div>
<div class="field">
<a class="ui blue fluid button" @click="addFederatedServer()">Add a federated server</a>
</div>
</div>
<div ref="verifiable-credentials" data-tab="verifiable-credentials" class="ui bottom attached tab segment">
<h2>Verifiable credentials</h2>
<div v-for="credential in backend.verifiable_credentials" class="ui credential-field segment">
<i class="ui large close icon" @click="deleteVerifiableCredential(credential)"></i>
<h3>Verifiable credential</h3>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Credential identifier</label>
<input type="text" v-model="credential.credential_identifier" placeholder="BorutaCredential">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Verifiable credential type</label>
<input type="text" v-model="credential.vct" placeholder="urn:boruta:verifiable-credential-type">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Version</label>
<select v-model="credential.version">
<option value="11">11</option>
<option value="13">13</option>
</select>
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Format</label>
<select v-model="credential.format">
<option value="jwt_vc_json">jwt_vc_json</option>
<option value="jwt_vc">jwt_vc</option>
<option value="vc+sd-jwt">vc+sd-jwt</option>
</select>
</div>
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="credential.defered">
<label>Defered</label>
</div>
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Types <i>(separated with a whitespace)</i></label>
<input type="text" v-model="credential.types" placeholder="VerifiableCredential BorutaCredential">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Time to live <i>(in seconds)</i></label>
<input type="number" v-model="credential.time_to_live" placeholder="31536000">
</div>
<h4>Claims</h4>
<div class="claim" v-for="claim in credential.claims">
<VerifiableCredentialClaim :format="credential.format" :credential="credential" :claim="claim" :errors="backend.errors"></VerifiableCredentialClaim>
</div>
<div class="field">
<a class="ui blue fluid button" @click="addVerifiableCredentialClaim(credential)">Add a claim</a>
</div>
<h4>Display</h4>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Name</label>
<input type="text" v-model="credential.display.name" placeholder="Boruta Credential">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Background color</label>
<input type="text" v-model="credential.display.background_color" placeholder="#53b29f">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Text color</label>
<input type="text" v-model="credential.display.text_color" placeholder="#ffffff">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Logo URL</label>
<input type="text" v-model="credential.display.logo.url" placeholder="https://io.malach.it/assets/images/logo.png">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Logo alt text</label>
<input type="text" v-model="credential.display.logo.alt_text" placeholder="Boruta credential logo">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_credentials }">
<label>Scope restriction <i>(leave blank for no restriction)</i></label>
<ScopesFieldByName :currentScopes="credential.scopes" :scopes="scopes" @add-scope="addCredentialScope(credential)" @delete-scope="scope => deleteCredentialScope(credential, scope)" />
</div>
</div>
<div class="field">
<a class="ui blue fluid button" @click="addVerifiableCredential()">Add a verifiable credential</a>
</div>
<h2>Verifiable presentations</h2>
<div v-for="presentation in backend.verifiable_presentations" class="ui presentation-field segment">
<i class="ui large close icon" @click="deleteVerifiablePresentation(presentation)"></i>
<h3>Verifiable presentation</h3>
<div class="field" :class="{ 'error': backend.errors?.verifiable_presentations }">
<label>Presentation identifier</label>
<input type="text" v-model="presentation.presentation_identifier" placeholder="BorutaPresentation">
</div>
<div class="field" :class="{ 'error': backend.errors?.verifiable_presentations }">
<label>Presentation definition</label>
<TextEditor :content="presentation.presentation_definition" @codeUpdate="setPresentationDefitiion($event, presentation)" />
</div>
</div>
<div class="field">
<a class="ui blue fluid button" @click="addVerifiablePresentation()">Add a verifiable presentation</a>
</div>
</div>
<div ref="user-metadata" data-tab="user-metadata" class="ui bottom attached tab segment">
<h2>User metadata configuration</h2>
<div v-for="field in backend.metadata_fields" class="ui metadata-field segment">
<i class="ui large close icon" @click="deleteMetadataField(field)"></i>
<h3>Metadata field</h3>
<div class="field" :class="{ 'error': backend.errors?.metadata_fields }">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="field.user_editable">
<label>User editable</label>
</div>
</div>
<div class="field" :class="{ 'error': backend.errors?.metadata_fields }">
<label>Scope restriction <i>(leave blank for no restriction)</i></label>
<ScopesFieldByName :currentScopes="field.scopes" :scopes="scopes" @add-scope="addMetadataFieldScope(field)" @delete-scope="scope => deleteMetadataFieldScope(field, scope)" />
</div>
<div class="field" :class="{ 'error': backend.errors?.metadata_fields }">
<label>Attribute name</label>
<input type="text" v-model="field.attribute_name" placeholder="family_name">
</div>
</div>
<div class="field">
<a class="ui blue fluid button" @click="addMetadataField()">Add a metadata field</a>
</div>
</div>
</div>
<div class="actions">
<button class="ui right floated violet button" type="submit">{{ action }}</button>
</div>
</form>
</div>
</template>
<script>
import Backend, { Claim } from '../../models/backend.model'
import RolesField from './RolesField.vue'
import Role from '../../models/role.model'
import Scope from '../../models/scope.model'
import FormErrors from './FormErrors.vue'
import ScopesFieldByName from './ScopesFieldByName.vue'
import TextEditor from '../../components/Forms/TextEditor.vue'
import VerifiableCredentialClaim from '../../components/VerifiableCredentialClaim.vue'
export default {
name: 'backend-form',
props: ['backend', 'action'],
components: {
FormErrors,
RolesField,
ScopesFieldByName,
TextEditor,
VerifiableCredentialClaim
},
data () {
return {
passwordHashingAlgorithms: Backend.passwordHashingAlgorithms,
ldapMasterPasswordVisible: false,
smtpPasswordVisible: false,
scopes: []
}
},
computed: {
passwordHashingOpts () {
return Backend.passwordHashingOpts[this.backend.password_hashing_alg]
}
},
mounted () {
Scope.all().then(scopes => {
this.scopes = scopes
})
},
methods: {
onAlgorithmChange () {
this.backend.resetPasswordAlgorithmOpts()
if (this.backend.isPersisted) {
alert('Changing the password hashing algorithm may invalidate already saved passwords. Use this feature with care.')
}
},
ldapMasterPasswordVisibilityToggle () {
this.ldapMasterPasswordVisible = !this.ldapMasterPasswordVisible
},
smtpPasswordVisibilityToggle () {
this.smtpPasswordVisible = !this.smtpPasswordVisible
},
federatedServerVisibilityToggle (federatedServer) {
federatedServer.clientSecretVisible = !federatedServer.clientSecretVisible
},
addFederatedServer () {
this.backend.federated_servers.push({})
},
addMetadataEndpoint (federatedServer) {
federatedServer.metadata_endpoints ||= []
federatedServer.metadata_endpoints.push({})
},
deleteMetadataEndpoint (federatedServer, endpoint) {
federatedServer.metadata_endpoints.splice(
federatedServer.metadata_endpoints.indexOf(endpoint),
1
)
},
addVerifiableCredentialClaim (credential) {
credential.claims.push(Claim.build('attribute'))
},
addVerifiableCredential () {
this.backend.verifiable_credentials.push({defered: false, display: {logo: {}}, claims: [], scopes: []})
},
addVerifiablePresentation () {
this.backend.verifiable_presentations.push({})
},
addMetadataField () {
this.backend.metadata_fields.push({ scopes: [] })
},
deleteMetadataField (field) {
this.backend.metadata_fields.splice(
this.backend.metadata_fields.indexOf(field),
1
)
},
deleteFederatedServer (federatedServer) {
this.backend.federated_servers.splice(
this.backend.federated_servers.indexOf(federatedServer),
1
)
},
deleteVerifiableCredential (credential) {
this.backend.verifiable_credentials.splice(
this.backend.verifiable_credentials.indexOf(credential),
1
)
},
deleteVerifiablePresentation (presentation) {
this.backend.verifiable_presentations.splice(
this.backend.verifiable_presentations.indexOf(presentation),
1
)
},
setPresentationDefitiion (content, presentation) {
presentation.presentation_definition = content
},
addMetadataFieldScope (field) {
field.scopes ||= []
field.scopes.push({})
},
deleteMetadataFieldScope (field, scope) {
field.scopes.splice(field.scopes.indexOf(scope), 1)
},
addCredentialScope (credential) {
credential.scopes ||= []
credential.scopes.push({})
},
deleteCredentialScope (credential, scope) {
credential.scopes.splice(credential.scopes.indexOf(scope), 1)
},
back () {
this.$emit('back')
},
addRole () {
this.backend.roles.push({ model: new Role() })
},
deleteRole (role) {
this.backend.roles.splice(
this.backend.roles.indexOf(role),
1
)
},
openTab (e) {
const tab = e.target.id
Array.from(this.$refs.tabularMenu.getElementsByClassName('item')).forEach(e => {
if (e.id == tab) {
e.classList.add('active')
this.$refs[e.id].classList.add('active')
} else {
e.classList.remove('active')
this.$refs[e.id].classList.remove('active')
}
})
}
},
watch: {
'backend.errors': {
deep: true,
handler (errors) {
setTimeout(() => {
Array.from(this.$refs.tabularMenu.getElementsByClassName('error')).forEach(e => {
e.classList.remove('error')
})
Array.from(this.$refs.form.getElementsByClassName('error')).forEach(elt => {
const tab = elt.closest('.tab').getAttribute('data-tab')
this.$refs.tabularMenu.querySelector('#' + tab).classList.add('error')
})
}, 100)
}
}
}
}
</script>
<style scoped lang="scss">
.metadata-field.segment, .federated-server-field.segment, .credential-field.segment, .presentation-field.segment {
.field {
margin-bottom: 1em!important;
}
.close.icon {
position: absolute;
cursor: pointer;
top: 1.17em;
right: .5em;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/ClientForm.vue
================================================
<template>
<div class="ui client-form segment">
<FormErrors v-if="client.errors" :errors="client.errors" />
<form ref="form" class="ui form" @submit.prevent="submit">
<div ref="tabularMenu" class="ui top attached stackable tabular menu">
<a id="general-configuration" @click="openTab" class="active item">General configuration</a>
<a id="authentication" @click="openTab" class="item">Authentication</a>
<a id="security" @click="openTab" class="item">Security</a>
<a id="grant-types" @click="openTab" class="item">Grant types</a>
</div>
<div ref="general-configuration" data-tab="general-configuration" class="ui bottom attached active tab segment">
<div class="field" :class="{ 'error': client.errors?.name }">
<label>Name</label>
<input v-model="client.name" placeholder="Super client" autocomplete="new-password" />
</div>
<div class="field" :class="{ 'error': client.errors?.id }" v-if="!client.isPersisted">
<label>Client ID</label>
<input v-model="client.id" autocomplete="new-password" placeholder="Must be an UUIDv4 - Leave blank to autogenerate" />
</div>
<div class="field" :class="{ 'error': client.errors?.id }">
<label>Public client ID</label>
<input v-model="client.public_client_id" placeholder="https://boruta.host" />
</div>
<div class="field" :class="{ 'error': client.errors?.secret }">
<label>Client secret</label>
<div class="ui left icon input">
<input :type="passwordVisible ? 'text' : 'password'" autocomplete="new-password" v-model="client.secret" placeholder="Leave blank to autogenerate" />
<i class="eye icon" :class="{ 'slash': passwordVisible }" @click="passwordVisibilityToggle()"></i>
</div>
</div>
<div class="field" :class="{ 'error': client.errors?.access_token_ttl }">
<label>Access token TTL (seconds)</label>
<input type="number" v-model="client.access_token_ttl" placeholder="3600" />
</div>
<div class="field" :class="{ 'error': client.errors?.authorization_code_ttl }">
<label>Authorization code TTL (seconds)</label>
<input type="number" v-model="client.authorization_code_ttl" placeholder="60" />
</div>
<div class="field" :class="{ 'error': client.errors?.refresh_token_ttl }">
<label>Refresh token TTL (seconds)</label>
<input type="number" v-model="client.refresh_token_ttl" placeholder="2592000" />
</div>
<div class="field" :class="{ 'error': client.errors?.id_token_ttl }">
<label>ID token TTL (seconds)</label>
<input type="number" v-model="client.id_token_ttl" placeholder="3600" />
</div>
<div class="field" :class="{ 'error': client.errors?.authorization_request_ttl }">
<label>Authorization request TTL (seconds)</label>
<input type="number" v-model="client.authorization_request_ttl" placeholder="60" />
</div>
<div class="field" :class="{ 'error': client.errors?.redirect_uris }">
<label>Redirect URIs</label>
<div v-for="(redirectUri, index) in client.redirect_uris" class="field" :key="index">
<div class="ui right icon input">
<input type="text" v-model="redirectUri.uri" placeholder="http://redirect.uri" />
<i v-on:click="deleteRedirectUri(redirectUri)" class="close icon"></i>
</div>
</div>
<a v-on:click.prevent="addRedirectUri()" class="ui blue fluid button">Add a redirect uri</a>
</div>
<div class="field" :class="{ 'error': client.errors?.response_mode }">
<label>Response mode</label>
<select v-model="client.response_mode">
<option value="post">post</option>
<option value="direct_post">direct_post</option>
</select>
</div>
</div>
<div ref="authentication" data-tab="authentication" class="ui bottom attached tab segment">
<h3>Client authentication</h3>
<div class="ui segment">
<div class="inline fields" :class="{ 'error': client.errors?.token_endpoint_auth_methods }">
<label>Client authentication methods</label>
<div class="field" v-for="method in tokenEndpointAuthMethods" :key="method">
<div class="ui checkbox">
<input type="checkbox" v-model="client.token_endpoint_auth_methods" :value="method" />
<label>{{ method }}</label>
</div>
</div>
</div>
</div>
<div class="ui segment">
<div class="inline fields" :class="{ 'error': client.errors?.token_endpoint_jwt_auth_alg }">
<label>Client JWT authentication signature algorithm</label>
<div class="field" v-for="alg in clientJwtAuthenticationSignatureAlgorithms" :key="alg">
<div class="ui radio checkbox">
<label>{{ alg }}</label>
<input type="radio" v-model="client.token_endpoint_jwt_auth_alg" :value="alg" />
</div>
</div>
</div>
</div>
<div class="field" v-if="client.token_endpoint_jwt_auth_alg.match(/RS/)">
<label>Client JWT authentication public key (pem)</label>
<textarea v-model="client.jwt_public_key" placeholder="Your public key here"></textarea>
</div>
<div class="ui segment">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="client.confidential">
<label>Confidential</label>
</div>
</div>
<h3>User authentication</h3>
<div class="field" :class="{ 'error': client.errors?.identity_provider_id }">
<IdentityProviderField :identityProvider="client.identity_provider.model" @identityProviderChange="setIdentityProvider"/>
</div>
</div>
<div ref="security" data-tab="security" class="ui bottom attached tab segment">
<h3>Signatures adapter</h3>
<div class="field" :class="{ 'error': client.errors?.signatures_adapter }">
<select v-model="client.signatures_adapter">
<option v-for="adapter in signaturesAdapters" :value="adapter">{{ adapter }}</option>
</select>
</div>
<div class="ui segment" v-if="client.signatures_adapter == 'Elixir.Boruta.Universal.Signatures'">
<div class="ui info message">
The usage of the Universal adapter requires an account, please contact Godiddy services <a href="https://godiddy.com/contact" target="_blank">https://godiddy.com/contact</a> and set the API key as an environment variable.
</div>
<h4>Key management</h4>
<h4>Key type</h4>
<div class="field" :class="{ 'error': client.errors?.key_pair_type }">
<select v-model="client.key_pair_type.type" @change="keyPairTypeChanged = true">
<option value="universal">
universal
</option>
</select>
</div>
<div class="field">
<label>method</label>
<select>
<option value="key">key</option>
</select>
</div>
<hr />
<div class="field" v-if="client.did">
<label>Client did</label>
<pre>{{ client.did }}</pre>
</div>
<div class="field" v-if="clientPublicKey">
<label>Client public key</label>
<pre>{{ clientPublicKey }}</pre>
</div>
<button type="button" class="ui fluid orange button" :disabled="keyPairTypeChanged" @click="regenerateKeyPair()" v-if="client.isPersisted">Regenerate client key pair</button>
</div>
<div class="ui segment" v-if="client.signatures_adapter == 'Elixir.Boruta.Internal.Signatures'">
<h4>Key type</h4>
<div class="field" :class="{ 'error': client.errors?.key_pair_type }">
<select v-model="client.key_pair_type.type" @change="keyPairTypeChanged = true">
<option v-for="keyPairType in Object.keys(keyPairTypes)" :value="keyPairType" :key="keyPairType">
{{ keyPairType }}
</option>
</select>
</div>
<div v-for="(value, param) in keyPairTypes[client.key_pair_type.type]" class="field" :class="{ 'error': client.errors?.key_pair_type }">
<label>{{ param }}</label>
<select v-if="value instanceof Array" v-model="client.key_pair_type[param]">
<option v-for="option in value" :value="option" :key="option">
{{ option }}
</option>
</select>
<input v-else type="text" v-model="client.key_pair_type[param]" />
</div>
<h4>Key management</h4>
<div class="field">
<select v-model="client.key_pair_id">
<option :value="null">Custom key pair</option>
<option v-for="keyPair in keyPairs" :value="keyPair.id" :key="keyPair.id">
{{ keyPair.id }}
</option>
</select>
</div>
<hr />
<div class="field" v-if="client.did">
<label>Client did</label>
<pre>{{ client.did }}</pre>
</div>
<div class="field" v-if="clientPublicKey">
<label>Client public key</label>
<pre>{{ clientPublicKey }}</pre>
</div>
<button type="button" class="ui fluid orange button" :disabled="keyPairTypeChanged" @click="regenerateKeyPair()" v-if="client.isPersisted">Regenerate client key pair</button>
<hr />
<a class="ui fluid orange button" @click="regenerateDid()" v-if="client.isPersisted">Regenerate client did</a>
</div>
<h3>Token signatures</h3>
<div class="ui segment">
<div class="inline fields" :class="{ 'error': client.errors?.id_token_signature_alg }">
<label>ID token signature algorithm</label>
<div class="field" v-for="alg in idTokenSignatureAlgorithms" :key="alg">
<div class="ui radio checkbox">
<label>{{ alg }}</label>
<input type="radio" v-model="client.id_token_signature_alg" :value="alg" />
</div>
</div>
</div>
</div>
<div class="ui segment">
<div class="inline fields" :class="{ 'error': client.errors?.userinfo_signed_response_alg }">
<label>Userinfo response signature algorithm</label>
<div class="field" v-for="alg in UserinfoResponseSignatureAlgorithms" :key="alg">
<div class="ui radio checkbox">
<label>{{ alg || 'none' }}</label>
<input type="radio" v-model="client.userinfo_signed_response_alg" :value="alg" />
</div>
</div>
</div>
</div>
<h3>Authorization</h3>
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="client.enforce_dpop">
<label>Enforce Demonstration Proof-of-Possession (DPoP)</label>
</div>
</div>
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="client.enforce_tx_code">
<label>Enforce pre-authorized code transaction code</label>
</div>
</div>
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="client.authorize_scope">
<label>Authorize scopes</label>
</div>
</div>
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="client.check_public_client_id">
<label>Check public client id</label>
</div>
</div>
<div class="field" :class="{ 'error': client.errors?.authorized_scopes }">
<ScopesField v-if="client.authorize_scope" :currentScopes="client.authorized_scopes" @delete-scope="deleteScope" @add-scope="addScope" />
</div>
<h3>PKCE configuration</h3>
<div class="ui segment">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="client.pkce">
<label>PKCE enabled</label>
</div>
</div>
<div class="ui segment">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="client.public_refresh_token">
<label>Public refresh token</label>
</div>
</div>
<div class="ui segment">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="client.public_revoke">
<label>Public revoke</label>
</div>
</div>
</div>
<div ref="grant-types" data-tab="grant-types" class="ui bottom attached tab segment">
<h3>Supported grant types</h3>
<div class="ui segment" v-for="grantType in client.grantTypes" :key="grantType.label">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="grantType.value">
<label>{{ grantType.label }}</label>
</div>
</div>
</div>
<div class="actions">
<button class="ui violet button" type="submit">{{ action }}</button>
</div>
</form>
</div>
</template>
<script>
import Scope from '../../models/scope.model'
import KeyPair from '../../models/key-pair.model'
import Client from '../../models/client.model'
import ScopesField from './ScopesField.vue'
import IdentityProviderField from './IdentityProviderField.vue'
import FormErrors from './FormErrors.vue'
export default {
name: 'client-form',
props: ['client', 'action'],
components: {
ScopesField,
IdentityProviderField,
FormErrors
},
data() {
return {
keyPairTypes: Client.keyPairTypes,
signaturesAdapters: Client.signaturesAdapters,
keyPairs: [],
keyPairTypeChanged: false,
idTokenSignatureAlgorithms: Client.idTokenSignatureAlgorithms,
UserinfoResponseSignatureAlgorithms: Client.UserinfoResponseSignatureAlgorithms,
clientJwtAuthenticationSignatureAlgorithms: Client.clientJwtAuthenticationSignatureAlgorithms,
tokenEndpointAuthMethods: Client.tokenEndpointAuthMethods,
passwordVisible: false
}
},
mounted () {
KeyPair.all().then(keyPairs => {
this.keyPairs = keyPairs
})
},
methods: {
regenerateKeyPair () {
if (confirm("Are you sure you want to regenerate this client key pair?")) {
this.client.regenerateKeyPair().then(() => {
this.$emit('submit')
})
}
},
regenerateDid () {
if (confirm("Are you sure you want to regenerate this client did?")) {
this.client.regenerateDid().then(() => {
this.$emit('submit')
})
}
},
submit () {
this.keyPairTypeChanged = false
this.$emit('submit')
},
addRedirectUri () {
this.client.redirect_uris.push({})
},
deleteRedirectUri (redirectUri) {
this.client.redirect_uris.splice(
this.client.redirect_uris.indexOf(redirectUri),
1
)
},
setIdentityProvider (identityProvider) {
this.client.identity_provider = { model: identityProvider }
},
addScope () {
this.client.authorized_scopes.push({ model: new Scope() })
},
deleteScope (scope) {
this.client.authorized_scopes.splice(
this.client.authorized_scopes.indexOf(scope),
1
)
},
passwordVisibilityToggle () {
this.passwordVisible = !this.passwordVisible
},
openTab (e) {
const tab = e.target.id
Array.from(this.$refs.tabularMenu.getElementsByClassName('item')).forEach(e => {
if (e.id == tab) {
e.classList.add('active')
this.$refs[e.id].classList.add('active')
} else {
e.classList.remove('active')
this.$refs[e.id].classList.remove('active')
}
})
}
},
watch: {
'$route.hash': {
handler (hash) {
console.log(this.$refs.tabularMenu)
Array.from(this.$refs.tabularMenu.getElementsByClassName('item')).forEach(e => {
console.log(e.classList)
if (Array.from(e.classList).includes(hash.slice(1))) {
e.classList.add('active')
} else {
e.classList.remove('active')
}
})
}
},
'client.errors': {
deep: true,
handler (errors) {
setTimeout(() => {
Array.from(this.$refs.tabularMenu.getElementsByClassName('error')).forEach(e => {
e.classList.remove('error')
})
Array.from(this.$refs.form.getElementsByClassName('error')).forEach(elt => {
const tab = elt.closest('.tab').getAttribute('data-tab')
this.$refs.tabularMenu.querySelector('#' + tab).classList.add('error')
})
}, 100)
}
},
'client.public_key': {
deep: true,
handler (newPublicKey) {
this.clientPublicKey = newPublicKey
}
},
'client.key_pair_id': {
deep: true,
handler (newKeyPairId) {
if (newKeyPairId) {
this.clientPublicKey = this.keyPairs.find(({ id }) => {
return id === newKeyPairId
}).public_key
} else {
const keyPair = this.keyPairs.find(({ public_key }) => {
return public_key === this.client.public_key
})
this.client.key_pair_id = keyPair ? keyPair.id : null
this.clientPublicKey = this.client.public_key
}
}
}
}
}
</script>
<style scoped lang="scss">
.client-form {
.field {
position: relative;
pre {
overflow: hidden;
text-overflow: ellipsis;
}
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/FormErrors.vue
================================================
<template>
<div @click="hide()" class="form-errors ui error message" v-if="show" :class="{ 'inline': inline }">
<div class="header">
Could not save current record
</div>
<ul class="list">
<li v-for="key in Object.keys(errors)" :key="key">
<strong>{{ label(key) }} </strong> {{ errors[key][0] }}
</li>
</ul>
</div>
</template>
<script>
const labels = {
'access_token_ttl': 'Access token TTL',
'authorization_code_ttl': 'Authorization code TTL',
'authorized_scopes': 'Authorized scopes',
'backend_id': 'Backend',
'client_identity_providers': 'Client',
'file': 'File',
'forwarded_token_signature_alg': 'Forwarded token signature algorithm',
'forwarded_token_signature_private_key': 'ID token signature private key',
'forwarded_token_signature_public_key': 'ID token signature public key',
'forwarded_token_signature_secret': 'ID token signature secret',
'id_token_signature_alg': 'ID token signature algorithm',
'id_token_ttl': 'ID token TTL',
'identity_provider_id': 'identity provider',
'is_default': 'Default',
'name': 'Name',
'password_hashing_opts': 'Password hashing options',
'redirect_uris': 'Redirect URIs',
'refresh_token_ttl': 'Refresh token TTL',
'resource': 'Resource'
}
export default {
name: 'FormErrors',
props: ['errors', 'inline'],
data () {
return {
show: true
}
},
methods: {
label(key) {
return labels[key] === undefined ? key : labels[key]
},
hide () {
this.show = false
}
}
}
</script>
<style scoped lang="scss">
.ui.error.message:not(.inline) {
cursor: pointer;
position: fixed;
z-index: 1000;
top: 4em;
right: 1em;
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/GatewayScopesField.vue
================================================
<template>
<div class="field edit-scopes">
<div v-for="(authorizedScope, index) in currentScopes" class="field" :key="index">
<div class="fields">
<div class="four wide field">
<label>Method</label>
<select type="text" v-model="authorizedScope.method">
<option :value="method" v-for="method in methods" :key="method">{{ method }}</option>
</select>
</div>
<div class="twelve wide field">
<label>Scope</label>
<div class="ui scope right icon input">
<select type="text" v-model="authorizedScope.model" class="authorized-scopes-select">
<option :value="scope" v-for="scope in scopeOptions(authorizedScope.model)" :key="scope.id">{{ scope.name }}</option>
</select>
<i v-on:click="deleteScope(authorizedScope)" class="close icon"></i>
</div>
</div>
</div>
</div>
<div class="ui info message" v-if="currentScopes.length"><i>You can use "*" as method wildcard</i></div>
<button v-on:click.prevent="addScope()" class="ui blue fluid button">Add a scope</button>
</div>
</template>
<script>
import Scope from '../../models/scope.model'
export default {
name: 'ScopesField',
props: {
currentScopes: {
type: Array,
default: () => ([])
}
},
data () {
return {
scopes: [],
methods: ['*', 'GET', 'POST', 'PUT', 'HEAD', 'OPTIONS', 'PATCH', 'DELETE']
}
},
computed: {
scopeOptions () {
const vm = this
return function (authorizedScope) {
return vm.scopes.map((scope) => {
if (authorizedScope.name === scope.name) {
return authorizedScope
}
return scope
})
}
}
},
mounted () {
Scope.all().then((scopes) => {
this.scopes = scopes
})
},
methods: {
deleteScope (scope) {
this.$emit('delete-scope', scope)
},
addScope () {
this.$emit('add-scope')
}
}
}
</script>
<style scoped lang="scss">
.edit-scopes {
.scope.input {
select {
margin-right: 3em;
}
}
.ui.icon.input>i.icon.close {
cursor: pointer;
pointer-events: all;
position: absolute;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/IdentityProviderField.vue
================================================
<template>
<div class="field">
<label>identity provider</label>
<select v-model="currentIdentityProviderId">
<option v-for="identityProviderOption in identityProviders" :value="identityProviderOption.id" :key="identityProviderOption.id" :selected="identityProviderOption.id == currentIdentityProviderId">
{{ identityProviderOption.name }}
</option>
</select>
</div>
</template>
<script>
import IdentityProvider from '../../models/identity-provider.model'
export default {
name: 'IdentityProviderField',
props: ['identityProvider'],
mounted () {
IdentityProvider.all().then((identityProviders) => {
this.identityProviders = identityProviders
})
},
data () {
return {
identityProviders: []
}
},
computed: {
currentIdentityProviderId: {
get () {
return this.identityProvider.id
},
set (identityProviderId) {
return this.$emit('identityProviderChange', this.identityProviders.find(({ id }) => id === identityProviderId))
}
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/IdentityProviderForm.vue
================================================
<template>
<div class="ui identity-provider-form segment">
<FormErrors v-if="identityProvider.errors" :errors="identityProvider.errors" />
<form ref="form" class="ui form" @submit.prevent="submit">
<div ref="tabularMenu" class="ui top attached stackable tabular menu">
<a id="general-configuration" @click="openTab" class="active item">General configuration</a>
<a id="features" @click="openTab" class="item">Features</a>
</div>
<div ref="general-configuration" data-tab="general-configuration" class="ui bottom attached active tab segment">
<div class="field" :class="{ 'error': identityProvider.errors?.name }">
<label>Name</label>
<input type="text" v-model="identityProvider.name" placeholder="Super identity provider">
</div>
<div class="field" :class="{ 'error': identityProvider.errors?.backend_id }">
<label>Backend</label>
<select v-model="identityProvider.backend_id">
<option :value="backend.id" v-for="backend in backends">{{ backend.name }}</option>
</select>
</div>
<div v-if="identityProvider.isPersisted" class="ui segment">
<router-link
:to="{ name: 'edit-layout-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit layout template</router-link>
</div>
<section v-if="identityProvider.isPersisted">
<h3>Sessions</h3>
<div class="ui segment">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.check_password">
<label>check password</label>
</div>
<hr />
<router-link
:to="{ name: 'edit-session-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit login template</router-link>
</div>
<div v-show="displayResetPassword">
<div class="ui segment">
<router-link
:to="{ name: 'edit-new-reset-password-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit send reset password instructions template</router-link>
</div>
<div class="ui segment">
<router-link
:to="{ name: 'edit-edit-reset-password-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit reset password template</router-link>
</div>
</div>
</section>
</div>
<div ref="features" data-tab="features" class="ui bottom attached tab segment">
<section v-if="identityProvider.isPersisted">
<h3>Choose session</h3>
<div class="ui segment">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.choose_session">
<label>choose session</label>
</div>
<p class="ui info message">
Give the ability for the user to choose to keep current session or to create a new one on authorization
</p>
<div v-if="identityProvider.choose_session">
<router-link
:to="{ name: 'edit-choose-session-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit choose session template</router-link>
</div>
</div>
</section>
<section v-show="displayWebauthnable">
<h3>Webauthn</h3>
<div class="ui segment">
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.webauthnable">
<label>enable Webauthn</label>
</div>
</div>
<hr />
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.enforce_webauthn">
<label>enforce Webauthn</label>
</div>
</div>
<p class="ui info message">
Give the ability for end users to register an authentication second factor with Passkeys.
</p>
<div v-if="identityProvider.webauthnable">
<router-link
:to="{ name: 'edit-webauthn-registration-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit Webauthn registration template</router-link>
<hr />
<router-link
:to="{ name: 'edit-webauthn-authentication-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit Webauthn authentication template</router-link>
</div>
</div>
</section>
<section v-show="displayTotpable">
<h3>Time based One Time Password</h3>
<div class="ui segment">
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.totpable">
<label>enable TOTP</label>
</div>
</div>
<hr />
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.enforce_totp">
<label>enforce TOTP</label>
</div>
</div>
<p class="ui info message">
Give the ability for end users to register an authentication second factor with TOTP.
</p>
<div v-if="identityProvider.totpable">
<router-link
:to="{ name: 'edit-totp-registration-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit TOTP registration template</router-link>
<hr />
<router-link
:to="{ name: 'edit-totp-authentication-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit TOTP authentication template</router-link>
</div>
</div>
</section>
<section v-show="displayRegistrable">
<h3>Registration</h3>
<div class="ui segment">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.registrable">
<label>registrable</label>
</div>
<p class="ui info message">
Give the ability for end users to register within the given identity provider. If activated the user have access to registration page and can provide its own credentials.
</p>
<div v-if="identityProvider.registrable">
<router-link
:to="{ name: 'edit-registration-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit registration template</router-link>
</div>
</div>
</section>
<section v-show="displayUserEditable">
<h3>User information edition</h3>
<div class="ui segment">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.user_editable">
<label>user editable</label>
</div>
<p class="ui info message">
Give the ability for end users to update their account information.
</p>
<div v-if="identityProvider.user_editable">
<router-link
:to="{ name: 'edit-edit-user-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit user edition template</router-link>
</div>
</div>
</section>
<section v-show="displayConfirmable">
<h3>Email confirmation</h3>
<div class="ui segment">
<div class=" field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.confirmable">
<label>confirmable</label>
</div>
<p class="ui info message">
Confirm new registred accounts. sends an email in order to confirm user's email.
</p>
<div v-if="identityProvider.confirmable">
<router-link
:to="{ name: 'edit-new-confirmation-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit send confirmation template</router-link>
</div>
</div>
</div>
</section>
<section v-show="displayConsentable">
<h3>User consent</h3>
<div class="ui segment">
<div class=" field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="identityProvider.consentable">
<label>user consent</label>
</div>
<p class="ui info message">
Users have to consent requested scopes to be authorized.
</p>
<div v-if="identityProvider.consentable">
<router-link
:to="{ name: 'edit-new-consent-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit consent template</router-link>
</div>
</div>
</div>
</section>
<section v-show="identityProvider.isPersisted">
<h3>Credential offer</h3>
<div class="ui segment">
<div class=" field">
<p class="ui info message">
SSI credential offer page
</p>
<div>
<router-link
:to="{ name: 'edit-credential-offer-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit credential offer template</router-link>
</div>
</div>
</div>
<h3>Credential presentation</h3>
<div class="ui segment">
<div class=" field">
<p class="ui info message">
SSI credential presentation page
</p>
<div>
<router-link
:to="{ name: 'edit-cross-device-presentation-template', params: { identityProviderId: identityProvider.id } }"
class="ui fluid blue button">Edit cross device presentation template</router-link>
</div>
</div>
</div>
</section>
</div>
<div class="actions">
<button class="ui violet button" type="submit">{{ action }}</button>
</div>
</form>
</div>
</template>
<script>
import Backend from '../../models/backend.model'
import FormErrors from './FormErrors.vue'
export default {
name: 'identity-provider-form',
props: ['identityProvider', 'action'],
components: {
FormErrors
},
data() {
return {
backends: []
}
},
computed: {
displayConfirmable () {
return this.identityProvider.isPersisted && this.identityProvider.backend.features?.includes('confirmable')
},
displayResetPassword () {
return this.identityProvider.backend.features?.includes('reset_password')
},
displayRegistrable () {
return this.identityProvider.isPersisted && this.identityProvider.backend.features?.includes('registrable')
},
displayWebauthnable () {
return this.identityProvider.isPersisted && this.identityProvider.backend.features?.includes('webauthnable')
},
displayTotpable () {
return this.identityProvider.isPersisted && this.identityProvider.backend.features?.includes('totpable')
},
displayUserEditable () {
return this.identityProvider.isPersisted && this.identityProvider.backend.features?.includes('user_editable')
},
displayConsentable () {
return this.identityProvider.isPersisted && this.identityProvider.backend.features?.includes('consentable')
}
},
mounted () {
Backend.all().then(backends => this.backends = backends)
},
methods: {
openTab (e) {
const tab = e.target.id
Array.from(this.$refs.tabularMenu.getElementsByClassName('item')).forEach(e => {
if (e.id == tab) {
e.classList.add('active')
this.$refs[e.id].classList.add('active')
} else {
e.classList.remove('active')
this.$refs[e.id].classList.remove('active')
}
})
}
},
watch: {
identityProvider: {
handler ({ backend_id }) {
this.identityProvider.backend = this.backends.find(({ id }) => id === backend_id) || this.identityProvider.backend
},
deep: true
},
'identityProvider.errors': {
deep: true,
handler (errors) {
setTimeout(() => {
Array.from(this.$refs.tabularMenu.getElementsByClassName('error')).forEach(e => {
e.classList.remove('error')
})
Array.from(this.$refs.form.getElementsByClassName('error')).forEach(elt => {
const tab = elt.closest('.tab').getAttribute('data-tab')
this.$refs.tabularMenu.querySelector('#' + tab).classList.add('error')
})
}, 100)
}
}
}
}
</script>
<style scoped lang="scss">
.identity-provider-form {
section {
margin-bottom: 1rem;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/OrganizationForm.vue
================================================
<template>
<div class="ui organization-form segment">
<FormErrors :errors="organization.errors" v-if="organization.errors" />
<form class="ui form" @submit.prevent="submit">
<h2>General configuration</h2>
<div class="field">
<label>Name</label>
<input type="text" v-model="organization.name" placeholder="wonder-organization" />
</div>
<div class="field">
<label>Label</label>
<input type="text" v-model="organization.label" placeholder="Wonder organization" />
</div>
<div class="actions">
<button class="ui violet button" type="submit">{{ action }}</button>
</div>
</form>
</div>
</template>
<script>
import FormErrors from './FormErrors.vue'
export default {
name: 'organization-form',
props: ['organization', 'action'],
components: {
FormErrors
}
}
</script>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/OrganizationsField.vue
================================================
<template>
<div class="field edit-organizations">
<div v-for="(organization, index) in currentOrganizations" class="field" :key="index">
<div class="ui right icon input">
<select type="text" v-model="organization.model" class="organizations-select">
<option :value="organization" v-for="organization in organizationOptions(organization.model)" :key="organization.id">{{ organization.name }}</option>
</select>
<i v-on:click="deleteOrganization(organization)" class="close icon"></i>
</div>
</div>
<a v-on:click.prevent="addOrganization()" class="ui blue fluid button">Add an organization</a>
</div>
</template>
<script>
import Organization from '../../models/organization.model'
export default {
name: 'OrganizationsField',
props: ['currentOrganizations'],
data () {
return {
organizations: []
}
},
computed: {
organizationOptions () {
const vm = this
return function (organization) {
return vm.organizations.map((organization) => {
if (organization.id === organization.id) {
return organization
}
return organization
})
}
}
},
mounted () {
Organization.all().then(({ data: organizations }) => {
this.organizations = organizations
})
},
methods: {
deleteOrganization (organization) {
this.$emit('delete-organization', organization)
},
addOrganization () {
this.$emit('add-organization')
}
}
}
</script>
<!-- Add "organizationd" attribute to limit CSS to this component only -->
<style organizationd lang="scss">
.edit-organizations {
.ui.icon.input>i.icon.close {
cursor: pointer;
pointer-events: all;
}
.organizations-select {
margin-right: 3em;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/RoleForm.vue
================================================
<template>
<div class="role-form">
<div class="ui segment">
<FormErrors v-if="role.errors" :errors="role.errors" />
<form class="ui form" @submit.prevent="submit">
<div class="field" :class="{ 'error': role.errors?.name }">
<label>Name</label>
<input type="text" v-model="role.name" placeholder="administrator">
</div>
<hr />
<ScopesField :currentScopes="role.scopes" @addScope="addScope" @deleteScope="deleteScope" />
<button class="ui right floated violet button" type="submit">{{ action }}</button>
<a class="ui button" v-on:click="back()">Back</a>
</form>
</div>
</div>
</template>
<script>
import Scope from '../../models/scope.model'
import Role from '../../models/role.model'
import FormErrors from '../../components/Forms/FormErrors.vue'
import ScopesField from '../../components/Forms/ScopesField.vue'
export default {
name: 'role-form',
props: ['role', 'action'],
components: {
FormErrors,
ScopesField
},
mounted () {
},
methods: {
back () {
this.$emit('back')
},
addScope () {
this.role.scopes.push({ model: new Scope(), method: 'GET' })
},
deleteScope (scope) {
this.role.scopes.splice(
this.role.scopes.indexOf(scope),
1
)
}
}
}
</script>
<style scoped lang="scss">
.role-form {
.field {
position: relative;
&.roles input {
margin-right: 3em;
}
}
.ui.icon.input>i.icon.close {
cursor: pointer;
pointer-events: all;
position: absolute;
}
.authorized-scopes-select {
margin-right: 3em;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/RolesField.vue
================================================
<template>
<div class="field edit-roles">
<div v-for="(role, index) in currentRoles" class="field" :key="index">
<div class="ui right icon input">
<select type="text" v-model="role.model" class="roles-select">
<option :value="role" v-for="role in roleOptions(role.model)" :key="role.id">{{ role.name }}</option>
</select>
<i v-on:click="deleteRole(role)" class="close icon"></i>
</div>
</div>
<a v-on:click.prevent="addRole()" class="ui blue fluid button">Add a role</a>
</div>
</template>
<script>
import Role from '../../models/role.model'
export default {
name: 'RolesField',
props: ['currentRoles'],
data () {
return {
roles: []
}
},
computed: {
roleOptions () {
const vm = this
return function (role) {
return vm.roles.map((currentRole) => {
if (role.id === currentRole.id) {
return role
}
return currentRole
})
}
}
},
mounted () {
Role.all().then((roles) => {
this.roles = roles
})
},
methods: {
deleteRole (role) {
this.$emit('delete-role', role)
},
addRole () {
this.$emit('add-role')
}
}
}
</script>
<!-- Add "roled" attribute to limit CSS to this component only -->
<style roled lang="scss">
.edit-roles {
.ui.icon.input>i.icon.close {
cursor: pointer;
pointer-events: all;
}
.roles-select {
margin-right: 3em;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/ScopesField.vue
================================================
<template>
<div class="field edit-scopes">
<div v-for="(authorizedScope, index) in currentScopes" class="field" :key="index">
<div class="ui right icon input">
<select type="text" v-model="authorizedScope.model" class="authorized-scopes-select">
<option :value="scope" v-for="scope in scopeOptions(authorizedScope.model)" :key="scope.id">{{ scope.name }}</option>
</select>
<i v-on:click="deleteScope(authorizedScope)" class="close icon"></i>
</div>
</div>
<a v-on:click.prevent="addScope()" class="ui blue fluid button">Add a scope</a>
</div>
</template>
<script>
import Scope from '../../models/scope.model'
export default {
name: 'ScopesField',
props: ['currentScopes'],
data () {
return {
scopes: []
}
},
computed: {
scopeOptions () {
const vm = this
return function (authorizedScope) {
return vm.scopes.map((scope) => {
if (authorizedScope.name === scope.name) {
return authorizedScope
}
return scope
})
}
}
},
mounted () {
Scope.all().then((scopes) => {
this.scopes = scopes
})
},
methods: {
deleteScope (scope) {
this.$emit('delete-scope', scope)
},
addScope () {
this.$emit('add-scope')
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.edit-scopes {
.ui.icon.input>i.icon.close {
cursor: pointer;
pointer-events: all;
}
.authorized-scopes-select {
margin-right: 3em;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/ScopesFieldByName.vue
================================================
<template>
<div class="field edit-scopes">
<div v-for="(scope, index) in currentScopes" class="field" :key="index">
<div class="ui right icon input">
<select type="text" v-model="scope.name" class="scopes-select">
<option :value="scope.name" v-for="scope in scopes" :key="scope.id">{{ scope.name }}</option>
</select>
<i v-on:click="deleteScope(scope)" class="close icon"></i>
</div>
</div>
<a v-on:click.prevent="addScope()" class="ui blue fluid button">Add a scope</a>
</div>
</template>
<script>
export default {
name: 'ScopesFieldByName',
props: ['currentScopes', 'scopes'],
methods: {
deleteScope (scope) {
this.$emit('delete-scope', scope)
},
addScope () {
this.$emit('add-scope')
}
}
}
</script>
<style scoped lang="scss">
.edit-scopes {
.ui.icon.input>i.icon.close {
cursor: pointer;
pointer-events: all;
}
.scopes-select {
margin-right: 3em;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/TextEditor.vue
================================================
<template>
<div class="text-editor">
<div class="editor lang-markup" ref="editor"></div>
</div>
</template>
<script>
import { CodeJar } from 'codejar'
import { withLineNumbers } from 'codejar/linenumbers'
import { highlight, languages } from 'prismjs'
export default {
name: 'TextEditor',
props: ['content'],
mounted () {
const highlightFunc = (editor) => {
const code = editor.textContent
editor.innerHTML = highlight(code, languages.markup, 'markup')
}
const editor = CodeJar(this.$refs.editor, withLineNumbers(highlightFunc), {
tab: ' '.repeat(2),
spellcheck: false
})
editor.onUpdate(code => {
this.$emit('codeUpdate', code)
})
this.editor = editor
this.editor.updateCode(this.content)
},
watch: {
content(newContent, content) {
if (!content) this.editor.updateCode(this.content)
}
}
}
</script>
<style lang="scss">
.text-editor {
height: 100%;
width: 100%;
overflow: hidden;
.codejar-wrap {
height: 100%;
.codejar-linenumbers {
color: orange !important;
height: 100%;
padding-left: .5em !important;
}
.editor {
background: #f5f2f0;
cursor: text;
height: 100%;
border-radius: 6px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
font-family: 'Source Code Pro', monospace;
font-weight: 400;
letter-spacing: normal;
line-height: 20px;
tab-size: 4;
.token.attr-name {
color: #690;
}
.token.selector {
color: #c90;
}
}
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/UpstreamForm.vue
================================================
<template>
<div class="ui upstream-form segment">
<FormErrors v-if="upstream.errors" :errors="upstream.errors" />
<form class="ui form" @submit.prevent="submit">
<div ref="tabularMenu" class="ui top attached stackable tabular menu">
<a id="general-configuration" @click="openTab" class="active item">General configuration</a>
<a id="uris" @click="openTab" class="item">URIs</a>
<a id="authorization" @click="openTab" class="item">Authorization</a>
</div>
<div ref="form">
<div ref="general-configuration" data-tab="general-configuration" class="ui bottom attached active tab segment">
<h2>General configuration</h2>
<div class="field" :class="{ 'error': upstream.errors?.node_name }">
<label>Node</label>
<select v-model="upstream.node_name" placeholder="global">
<option value="global">global</option>
<option v-for="name in nodeNames" :value="name">{{ name }}</option>
</select>
</div>
<div class="field" :class="{ 'error': upstream.errors?.scheme }">
<label>Scheme</label>
<select v-model="upstream.scheme" placeholder="https">
<option value="https">https</option>
<option value="http">http</option>
</select>
</div>
<div class="field" :class="{ 'error': upstream.errors?.host }">
<label>Host</label>
<input type="text" v-model="upstream.host" placeholder="host.test">
</div>
<div class="field" :class="{ 'error': upstream.errors?.port }">
<label>Port</label>
<input type="text" v-model="upstream.port" placeholder="443">
</div>
<div class="field" :class="{ 'error': upstream.errors?.pool_count }">
<label>Pool count</label>
<input type="number" v-model="upstream.pool_count" placeholder="10">
</div>
<div class="field" :class="{ 'error': upstream.errors?.pool_size }">
<label>Pool size</label>
<input type="number" v-model="upstream.pool_size" placeholder="10">
</div>
<div class="field" :class="{ 'error': upstream.errors?.max_idle_time }">
<label>Max idle time</label>
<input type="number" v-model="upstream.max_idle_time" placeholder="10">
</div>
</div>
<div ref="uris" data-tab="uris" class="ui bottom attached tab segment">
<h2>URIs</h2>
<div class="upstreams field" :class="{ 'error': upstream.errors?.uris }">
<div v-for="(upstreamUri, index) in upstream.uris" class="field" :key="index">
<div class="ui right icon input">
<input type="text" v-model="upstreamUri.uri" placeholder="/matching (without trailing slash)" />
<i v-on:click="deleteUpstreamUri(upstreamUri)" class="close icon"></i>
</div>
</div>
<a v-on:click.prevent="addUpstreamUri()" class="ui blue fluid button">Add an upstream uri</a>
</div>
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="upstream.strip_uri">
<label>Strip URI</label>
</div>
</div>
</div>
<div ref="authorization" data-tab="authorization" class="ui bottom attached tab segment">
<h3>Authorization</h3>
<div class="field">
<div class="ui toggle checkbox">
<input type="checkbox" v-model="upstream.authorize">
<label>Authorize</label>
</div>
</div>
<div class="field" v-if="upstream.authorize" :class="{ 'error': upstream.errors?.required_scopes }">
<label>Required scopes <i>(leave empty to not filter)</i></label>
<GatewayScopesField :currentScopes="upstream.required_scopes" @delete-scope="deleteScope" @add-scope="addScope" />
</div>
<div v-if="upstream.authorize">
<h4>Error templates</h4>
<div class="field" :class="{ 'error': upstream.errors?.error_content_type }">
<label>Error content type</label>
<input type="text" v-model="upstream.error_content_type" placeholder="text">
</div>
<div class="field" :class="{ 'error': upstream.errors?.forbidden_response }">
<label>Forbidden response</label>
<textarea v-model="upstream.forbidden_response" placeholder="You are forbidden to access this resource."></textarea>
</div>
<div class="field" :class="{ 'error': upstream.errors?.unauthorized_response }">
<label>Unauthorized response</label>
<textarea v-model="upstream.unauthorized_response" placeholder="You are unauthorized to access this resource."></textarea>
</div>
</div>
<h3>Forwarded authorization</h3>
<div class="ui segment">
<div class="inline fields" :class="{ 'error': upstream.errors?.forwarded_token_signature_alg }">
<label>Forwarded token signature algorithm</label>
<div class="field" v-for="alg in forwardedTokenSignatureAlgorithms" :key="alg">
<div class="ui radio checkbox">
<label>{{ alg }}</label>
<input type="radio" v-model="upstream.forwarded_token_signature_alg" :value="alg" />
</div>
</div>
</div>
</div>
<div v-if="isHsAlgorithm" class="field" :class="{ 'error': upstream.errors?.forwarded_token_secret }">
<label>Forwarded token secret <em>(leave blank to autogenerate)</em></label>
<input type="text" v-model="upstream.forwarded_token_secret" placeholder="text">
</div>
<div v-if="isRsAlgorithm">
<div class="field" :class="{ 'error': upstream.errors?.forwarded_token_private_key }">
<label>Forwarded token private key <em>(leave blank to autogenerate)</em></label>
<textarea v-model="upstream.forwarded_token_private_key"></textarea>
</div>
<div class="field" :class="{ 'error': upstream.errors?.forwarded_token_public_key }">
<label>Forwarded token public key</label>
<textarea v-model="upstream.forwarded_token_public_key"></textarea>
</div>
</div>
</div>
</div>
<div class="actions">
<button class="ui right floated violet button" type="submit">{{ action }}</button>
</div>
</form>
</div>
</template>
<script>
import Scope from '../../models/scope.model'
import Upstream from '../../models/upstream.model'
import GatewayScopesField from '../../components/Forms/GatewayScopesField.vue'
import FormErrors from '../../components/Forms/FormErrors.vue'
export default {
name: 'upstream-form',
props: ['upstream', 'action'],
components: {
FormErrors,
GatewayScopesField
},
data () {
return {
nodeNames: [],
forwardedTokenSignatureAlgorithms: Upstream.forwardedTokenSignatureAlgorithms
}
},
mounted () {
Upstream.nodeList().then(nodes => this.nodeNames = nodes)
},
computed: {
isHsAlgorithm () {
return this.upstream.forwarded_token_signature_alg?.match(/HS/)
},
isRsAlgorithm () {
return this.upstream.forwarded_token_signature_alg?.match(/RS/)
}
},
methods: {
back () {
this.$emit('back')
},
addUpstreamUri () {
this.upstream.uris.push({})
},
deleteUpstreamUri (uri) {
this.upstream.uris.splice(
this.upstream.uris.indexOf(uri),
1
)
},
addScope () {
this.upstream.required_scopes.push({ model: new Scope(), method: 'GET' })
},
deleteScope (scope) {
this.upstream.required_scopes.splice(
this.upstream.required_scopes.indexOf(scope),
1
)
},
openTab (e) {
const tab = e.target.id
Array.from(this.$refs.tabularMenu.getElementsByClassName('item')).forEach(e => {
if (e.id == tab) {
e.classList.add('active')
this.$refs[e.id].classList.add('active')
} else {
e.classList.remove('active')
this.$refs[e.id].classList.remove('active')
}
})
}
},
watch: {
'upstream.errors': {
deep: true,
handler (errors) {
setTimeout(() => {
Array.from(this.$refs.tabularMenu.getElementsByClassName('error')).forEach(e => {
e.classList.remove('error')
})
Array.from(this.$refs.form.getElementsByClassName('error')).forEach(elt => {
const tab = elt.closest('.tab').getAttribute('data-tab')
this.$refs.tabularMenu.querySelector('#' + tab).classList.add('error')
})
}, 100)
}
}
}
}
</script>
<style scoped lang="scss">
.upstream-form {
.field {
position: relative;
&.upstreams input {
margin-right: 3em;
}
}
.ui.icon.input>i.icon.close {
cursor: pointer;
pointer-events: all;
position: absolute;
}
.authorized-scopes-select {
margin-right: 3em;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Forms/UserForm.vue
================================================
<template>
<div class="ui user-form segment">
<FormErrors :errors="user.errors" v-if="user.errors" />
<form class="ui form" @submit.prevent="submit">
<div ref="tabularMenu" class="ui top attached stackable tabular menu">
<a id="general-configuration" @click="openTab" class="active item">General configuration</a>
<a id="authorization" @click="openTab" class="item">Authorization</a>
</div>
<div ref="general-configuration" data-tab="general-configuration" class="ui bottom attached active tab segment">
<h2>General configuration</h2>
<div class="field" v-if="!user.isPersisted" :class="{ 'error': user.errors?.backend }">
<label>Backend</label>
<select v-model="user.backend_id">
<option :value="backend.id" v-for="backend in backends" :key="backend.id">{{ backend.name }}</option>
</select>
</div>
<div class="field" v-if="!user.isPersisted" :class="{ 'error': user.errors?.email }">
<label>Email</label>
<input type="text" v-model="user.email" placeholder="email@example.com" />
</div>
<div class="field" v-if="!user.isPersisted" :class="{ 'error': user.errors?.password }">
<label>Password</label>
<input type="password" v-model="user.password" />
</div>
<div class="field" :class="{ 'error': user.errors?.group }">
<label>Group</label>
<input type="text" v-model="user.group" />
</div>
<section v-if="user.backend.metadata_fields.length">
<h3>Metadata</h3>
<div class="ui metadata segment" v-for="field in user.backend.metadata_fields">
<h4>{{ field.attribute_name }}</h4>
<div class="ui three column stackable grid">
<div class="column">
<div class="field" :class="{ 'error': user.errors?.metadata }">
<label>Value</label>
<input type="text" v-model="user.metadata[field.attribute_name].value" placeholder="metadata" />
</div>
</div>
<div class="column">
<div class="field" :class="{ 'error': user.errors?.metadata }">
<label>Verifiable credential status</label>
<select v-model="user.metadata[field.attribute_name].status">
<option value="valid">valid</option>
<option value="suspended">suspended</option>
<option value="revoked">revoked</option>
</select>
</div>
</div>
<div class="column">
<div class="field">
<label>Claim format</label>
<div class="ui toggle checkbox">
<input type="checkbox" v-model="user.metadata[field.attribute_name].displayStatus">
<label>display status</label>
</div>
</div>
</div>
</div>
</div>
</section>
<h3>Organizations</h3>
<OrganizationsField :currentOrganizations="user.organizations" @delete-organization="deleteOrganization" @add-organization="addOrganization" />
</div>
<div ref="authorization" data-tab="authorization" class="ui bottom attached tab segment">
<h2>Authorization</h2>
<h3>Roles</h3>
<RolesField :currentRoles="user.roles" @delete-role="deleteRole" @add-role="addRole" />
<h3>Authorized scopes</h3>
<ScopesField :currentScopes="user.authorized_scopes" @delete-scope="deleteScope" @add-scope="addScope" />
</div>
<div class="actions">
<button class="ui right floated violet button" type="submit">{{ action }}</button>
</div>
</form>
</div>
</template>
<script>
import Scope from '../../models/scope.model'
import Role from '../../models/role.model'
import Organization from '../../models/organization.model'
import Backend from '../../models/backend.model'
import ScopesField from './ScopesField.vue'
import RolesField from './RolesField.vue'
import OrganizationsField from './OrganizationsField.vue'
import FormErrors from './FormErrors.vue'
export default {
name: 'user-form',
props: ['user', 'action'],
components: {
ScopesField,
RolesField,
OrganizationsField,
FormErrors
},
data () {
return {
scopes: [],
backends: []
}
},
mounted () {
Scope.all().then((scopes) => {
this.scopes = scopes
})
Backend.all().then((backends) => {
this.backends = backends
})
},
methods: {
addScope () {
this.user.authorized_scopes.push({ model: new Scope() })
},
deleteScope (scope) {
this.user.authorized_scopes.splice(
this.user.authorized_scopes.indexOf(scope),
1
)
},
addRole () {
this.user.roles.push({ model: new Role() })
},
deleteRole (role) {
this.user.roles.splice(
this.user.roles.indexOf(role),
1
)
},
addOrganization () {
this.user.organizations.push({ model: new Organization() })
},
deleteOrganization (organization) {
this.user.organizations.splice(
this.user.organizations.indexOf(organization),
1
)
},
openTab (e) {
const tab = e.target.id
Array.from(this.$refs.tabularMenu.getElementsByClassName('item')).forEach(e => {
if (e.id == tab) {
e.classList.add('active')
this.$refs[e.id].classList.add('active')
} else {
e.classList.remove('active')
this.$refs[e.id].classList.remove('active')
}
})
}
},
watch: {
user: {
handler ({ backend_id }) {
this.user.backend = this.backends.find(({ id }) => id === backend_id) || this.user.backend
},
deep: true
},
'user.backend': {
handler() {
this.user.backend.metadata_fields.forEach((field) => {
this.user.metadata[field.attribute_name] ||= { status: 'valid' }
})
}
},
'user.errors': {
deep: true,
handler (errors) {
setTimeout(() => {
Array.from(this.$refs.tabularMenu.getElementsByClassName('error')).forEach(e => {
e.classList.remove('error')
})
Array.from(this.$refs.form.getElementsByClassName('error')).forEach(elt => {
const tab = elt.closest('.tab').getAttribute('data-tab')
this.$refs.tabularMenu.querySelector('#' + tab).classList.add('error')
})
}, 100)
}
},
}
}
</script>
<style lang="scss">
.metadata .toggle {
padding: 8px;
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Header.vue
================================================
<template>
<div class="header" :class="{ 'dark': darkMode }">
<div class="ui main menu" :class="{ 'inverted': darkMode }">
<router-link :to="{ name: 'home' }" class="logo item">
<img src="../assets/images/logo-inverted.png" v-if="darkMode" />
<img src="../assets/images/logo.png" v-else />
</router-link>
<div class="right menu">
<span class="ui email item">
{{ currentUser.email }}
</span>
<a v-on:click.prevent="logout()" class="ui item">
<i class="ui power off icon"></i>
</a>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import oauth from '../services/oauth.service'
export default {
name: 'Header',
props: ['darkMode'],
computed: {
currentUser() {
return oauth.currentUser
},
...mapGetters(['isAuthenticated'])
},
methods: {
logout () {
this.$store.dispatch('logout')
}
}
}
</script>
<style scoped lang="scss">
.header.dark {
background: #1b1c1d;
.main.menu {
border: 1px solid rgba(255,255,255,.08);
}
}
.header {
background: white;
max-width: 100%;
overflow: hidden;
.item.logo {
min-width: 199px;
background: inherit!important;
padding: 0 1rem 0 .7rem;
&:before {
display: none;
}
img {
max-width: calc(199px - 1.7rem);
max-height: 22px;
width: auto;
}
}
.power.off.icon {
margin: 0!important;
}
.main.menu {
border-radius: 0;
}
@media screen and (max-width: 768px) {
.item.email {
display: none;
}
}
@media screen and (max-width: 1127px) {
position: fixed;
z-index: 100;
width: 100%;
padding-left: 3.2em;
}
}
</style>
================================================
FILE: apps/boruta_admin/assets/src/components/Toaster.vue
======================
gitextract_c41fuwm_/ ├── .credo.exs ├── .formatter.exs ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ ├── deploy.yml │ └── elixir.yml ├── .gitignore ├── .gitlab-ci.yml ├── .tool-versions ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Dockerfile.admin ├── Dockerfile.auth ├── Dockerfile.full ├── Dockerfile.gateway ├── GENERAL_TERMS_AND_CONDITIONS.md ├── LICENSE.md ├── README.md ├── ansible/ │ ├── .kube/ │ │ └── kubeconfig-k8s-boruta.yaml │ ├── deploy.yml │ ├── hosts │ └── inventories/ │ ├── gke │ ├── local │ └── scaleway ├── apps/ │ ├── boruta_admin/ │ │ ├── .formatter.exs │ │ ├── .gitignore │ │ ├── assets/ │ │ │ ├── .browserslistrc │ │ │ ├── .editorconfig │ │ │ ├── .eslintrc.js │ │ │ ├── .gitignore │ │ │ ├── index.html │ │ │ ├── jsconfig.json │ │ │ ├── package.json │ │ │ ├── postcss.config.js │ │ │ ├── src/ │ │ │ │ ├── App.vue │ │ │ │ ├── components/ │ │ │ │ │ ├── Breadcrumb.vue │ │ │ │ │ ├── Feedback.vue │ │ │ │ │ ├── Forms/ │ │ │ │ │ │ ├── BackendForm.vue │ │ │ │ │ │ ├── ClientForm.vue │ │ │ │ │ │ ├── FormErrors.vue │ │ │ │ │ │ ├── GatewayScopesField.vue │ │ │ │ │ │ ├── IdentityProviderField.vue │ │ │ │ │ │ ├── IdentityProviderForm.vue │ │ │ │ │ │ ├── OrganizationForm.vue │ │ │ │ │ │ ├── OrganizationsField.vue │ │ │ │ │ │ ├── RoleForm.vue │ │ │ │ │ │ ├── RolesField.vue │ │ │ │ │ │ ├── ScopesField.vue │ │ │ │ │ │ ├── ScopesFieldByName.vue │ │ │ │ │ │ ├── TextEditor.vue │ │ │ │ │ │ ├── UpstreamForm.vue │ │ │ │ │ │ └── UserForm.vue │ │ │ │ │ ├── Header.vue │ │ │ │ │ ├── Toaster.vue │ │ │ │ │ └── VerifiableCredentialClaim.vue │ │ │ │ ├── main.js │ │ │ │ ├── models/ │ │ │ │ │ ├── backend.model.js │ │ │ │ │ ├── business-log-stats.model.js │ │ │ │ │ ├── client.model.js │ │ │ │ │ ├── email-template.model.js │ │ │ │ │ ├── error-template.model.js │ │ │ │ │ ├── identity-provider.model.js │ │ │ │ │ ├── key-pair.model.js │ │ │ │ │ ├── organization.model.js │ │ │ │ │ ├── request-log-stats.model.js │ │ │ │ │ ├── role.model.js │ │ │ │ │ ├── scope.model.js │ │ │ │ │ ├── template.model.js │ │ │ │ │ ├── upstream.model.js │ │ │ │ │ ├── user.model.js │ │ │ │ │ └── utils.js │ │ │ │ ├── router.js │ │ │ │ ├── services/ │ │ │ │ │ ├── configuration-file.service.js │ │ │ │ │ └── oauth.service.js │ │ │ │ ├── store.js │ │ │ │ └── views/ │ │ │ │ ├── BadRequest.vue │ │ │ │ ├── Clients/ │ │ │ │ │ ├── Client.vue │ │ │ │ │ ├── ClientList.vue │ │ │ │ │ ├── EditClient.vue │ │ │ │ │ ├── KeyPairList.vue │ │ │ │ │ └── NewClient.vue │ │ │ │ ├── Clients.vue │ │ │ │ ├── Configuration/ │ │ │ │ │ ├── ConfigurationFileUpload.vue │ │ │ │ │ ├── EditBadRequestTemplate.vue │ │ │ │ │ ├── EditForbiddenTemplate.vue │ │ │ │ │ ├── EditInternalServerErrorTemplate.vue │ │ │ │ │ ├── EditNotFoundTemplate.vue │ │ │ │ │ └── ErrorTemplateList.vue │ │ │ │ ├── Configuration.vue │ │ │ │ ├── Dashboard/ │ │ │ │ │ ├── BusinessEvents.vue │ │ │ │ │ └── Requests.vue │ │ │ │ ├── Dashboard.vue │ │ │ │ ├── Home.vue │ │ │ │ ├── IdentityProviders/ │ │ │ │ │ ├── BackendList.vue │ │ │ │ │ ├── Backends/ │ │ │ │ │ │ ├── Backend.vue │ │ │ │ │ │ ├── EditConfirmationInstructionsEmailTemplate.vue │ │ │ │ │ │ ├── EditResetPasswordInstructionsEmailTemplate.vue │ │ │ │ │ │ └── EditTxCodeEmailTemplate.vue │ │ │ │ │ ├── Backends.vue │ │ │ │ │ ├── EditBackend.vue │ │ │ │ │ ├── EditCredentialOfferTemplate.vue │ │ │ │ │ ├── EditCrossDevicePresentationTemplate.vue │ │ │ │ │ ├── EditEditResetPasswordTemplate.vue │ │ │ │ │ ├── EditEditUserTemplate.vue │ │ │ │ │ ├── EditIdentityProvider.vue │ │ │ │ │ ├── EditLayoutTemplate.vue │ │ │ │ │ ├── EditNewChooseSessionTemplate.vue │ │ │ │ │ ├── EditNewConfirmationTemplate.vue │ │ │ │ │ ├── EditNewConsentTemplate.vue │ │ │ │ │ ├── EditNewResetPasswordTemplate.vue │ │ │ │ │ ├── EditOrganization.vue │ │ │ │ │ ├── EditRegistrationTemplate.vue │ │ │ │ │ ├── EditSessionTemplate.vue │ │ │ │ │ ├── EditTotpAuthenticationTemplate.vue │ │ │ │ │ ├── EditTotpRegistrationTemplate.vue │ │ │ │ │ ├── EditUser.vue │ │ │ │ │ ├── EditWebauthnAuthenticationTemplate.vue │ │ │ │ │ ├── EditWebauthnRegistrationTemplate.vue │ │ │ │ │ ├── IdentityProvider.vue │ │ │ │ │ ├── IdentityProviderList.vue │ │ │ │ │ ├── NewBackend.vue │ │ │ │ │ ├── NewIdentityProvider.vue │ │ │ │ │ ├── NewOrganization.vue │ │ │ │ │ ├── NewUser.vue │ │ │ │ │ ├── OrganizationList.vue │ │ │ │ │ ├── Organizations.vue │ │ │ │ │ ├── UserImport.vue │ │ │ │ │ ├── UserList.vue │ │ │ │ │ └── Users.vue │ │ │ │ ├── IdentityProviders.vue │ │ │ │ ├── Layouts/ │ │ │ │ │ └── Main.vue │ │ │ │ ├── NotFound.vue │ │ │ │ ├── OauthCallback.vue │ │ │ │ ├── Roles/ │ │ │ │ │ ├── EditRole.vue │ │ │ │ │ ├── NewRole.vue │ │ │ │ │ ├── Role.vue │ │ │ │ │ └── RoleList.vue │ │ │ │ ├── Roles.vue │ │ │ │ ├── Scopes/ │ │ │ │ │ └── ScopeList.vue │ │ │ │ ├── Scopes.vue │ │ │ │ ├── Upstreams/ │ │ │ │ │ ├── EditUpstream.vue │ │ │ │ │ ├── NewUpstream.vue │ │ │ │ │ ├── Upstream.vue │ │ │ │ │ └── UpstreamList.vue │ │ │ │ └── Upstreams.vue │ │ │ ├── tests/ │ │ │ │ └── unit/ │ │ │ │ └── .eslintrc.js │ │ │ └── vite.config.js │ │ ├── config/ │ │ │ ├── config.exs │ │ │ ├── dev.exs │ │ │ ├── prod.exs │ │ │ └── test.exs │ │ ├── lib/ │ │ │ ├── boruta_admin/ │ │ │ │ ├── application.ex │ │ │ │ ├── configuration_loader/ │ │ │ │ │ └── schema.ex │ │ │ │ ├── configuration_loader.ex │ │ │ │ ├── configurations/ │ │ │ │ │ └── configuration.ex │ │ │ │ ├── configurations.ex │ │ │ │ ├── logs.ex │ │ │ │ ├── release.ex │ │ │ │ └── repo.ex │ │ │ ├── boruta_admin.ex │ │ │ ├── boruta_admin_web/ │ │ │ │ ├── controllers/ │ │ │ │ │ ├── backend_controller.ex │ │ │ │ │ ├── boruta/ │ │ │ │ │ │ ├── client_controller.ex │ │ │ │ │ │ └── scope_controller.ex │ │ │ │ │ ├── configuration_controller.ex │ │ │ │ │ ├── fallback_controller.ex │ │ │ │ │ ├── identity_provider_controller.ex │ │ │ │ │ ├── key_pair_controller.ex │ │ │ │ │ ├── logs_controller.ex │ │ │ │ │ ├── organization_controller.ex │ │ │ │ │ ├── page_controller.ex │ │ │ │ │ ├── role_controller.ex │ │ │ │ │ ├── upstream_controller.ex │ │ │ │ │ └── user_controller.ex │ │ │ │ ├── endpoint.ex │ │ │ │ ├── gettext.ex │ │ │ │ ├── plugs/ │ │ │ │ │ ├── authorization.ex │ │ │ │ │ └── logger.ex │ │ │ │ ├── router.ex │ │ │ │ ├── telemetry.ex │ │ │ │ ├── templates/ │ │ │ │ │ ├── error/ │ │ │ │ │ │ ├── 404.html.eex │ │ │ │ │ │ └── 500.html.eex │ │ │ │ │ └── page/ │ │ │ │ │ └── admin.html.eex │ │ │ │ └── views/ │ │ │ │ ├── backend_view.ex │ │ │ │ ├── changeset_view.ex │ │ │ │ ├── client_view.ex │ │ │ │ ├── configuration_view.ex │ │ │ │ ├── error_helpers.ex │ │ │ │ ├── error_view.ex │ │ │ │ ├── identity_provider_view.ex │ │ │ │ ├── key_pair_view.ex │ │ │ │ ├── logs_view.ex │ │ │ │ ├── organization_view.ex │ │ │ │ ├── page_view.ex │ │ │ │ ├── role_view.ex │ │ │ │ ├── scope_view.ex │ │ │ │ ├── upstream_view.ex │ │ │ │ └── user_view.ex │ │ │ └── boruta_admin_web.ex │ │ ├── mix.exs │ │ ├── priv/ │ │ │ ├── examples/ │ │ │ │ └── configuration.yml │ │ │ ├── gettext/ │ │ │ │ ├── en/ │ │ │ │ │ └── LC_MESSAGES/ │ │ │ │ │ └── errors.po │ │ │ │ └── errors.pot │ │ │ ├── repo/ │ │ │ │ ├── migrations/ │ │ │ │ │ ├── .formatter.exs │ │ │ │ │ └── 20240508054424_create_configurations.exs │ │ │ │ └── seeds.exs │ │ │ └── test/ │ │ │ └── configuration_files/ │ │ │ ├── bad_backend_configuration.yml │ │ │ ├── bad_client_configuration.yml │ │ │ ├── bad_error_template_configuration.yml │ │ │ ├── bad_identity_provider_configuration.yml │ │ │ ├── bad_organization_configuration.yml │ │ │ ├── bad_role_configuration.yml │ │ │ ├── bad_scope_configuration.yml │ │ │ └── full_configuration.yml │ │ └── test/ │ │ ├── boruta_admin/ │ │ │ └── configuration_loader_test.exs │ │ ├── boruta_admin_web/ │ │ │ ├── controllers/ │ │ │ │ ├── backend_controller_test.exs │ │ │ │ ├── client_controller_test.exs │ │ │ │ ├── configuration_controller_test.exs │ │ │ │ ├── identity_provider_controller_test.exs │ │ │ │ ├── key_pair_controller_test.exs │ │ │ │ ├── logs_controller_test.exs │ │ │ │ ├── organization_controller_test.exs │ │ │ │ ├── page_controller_test.exs │ │ │ │ ├── role_controller_test.exs │ │ │ │ ├── scope_controller_test.exs │ │ │ │ ├── upstream_controller_test.exs │ │ │ │ └── user_controller_test.exs │ │ │ └── views/ │ │ │ ├── error_view_test.exs │ │ │ └── page_view_test.exs │ │ ├── data/ │ │ │ ├── import_users_hashed_password_valid.csv │ │ │ ├── import_users_password_custom_headers_valid.csv │ │ │ ├── import_users_password_invalid.csv │ │ │ └── import_users_password_valid.csv │ │ ├── support/ │ │ │ ├── boruta_factory.ex │ │ │ ├── boruta_identity_factory.ex │ │ │ ├── conn_case.ex │ │ │ └── data_case.ex │ │ └── test_helper.exs │ ├── boruta_auth/ │ │ ├── .formatter.exs │ │ ├── .gitignore │ │ ├── config/ │ │ │ ├── config.exs │ │ │ ├── dev.exs │ │ │ ├── prod.exs │ │ │ └── test.exs │ │ ├── lib/ │ │ │ ├── boruta_auth/ │ │ │ │ ├── application.ex │ │ │ │ ├── key_pairs/ │ │ │ │ │ └── schemas/ │ │ │ │ │ └── key_pair.ex │ │ │ │ ├── key_pairs.ex │ │ │ │ ├── log_rotate.ex │ │ │ │ ├── repo.ex │ │ │ │ └── scheduler.ex │ │ │ └── boruta_auth.ex │ │ ├── mix.exs │ │ ├── priv/ │ │ │ └── repo/ │ │ │ ├── boruta.seeds.exs │ │ │ └── migrations/ │ │ │ ├── 20201129024828_create_boruta.exs │ │ │ ├── 20210114202055_usec_timestamps.exs │ │ │ ├── 20210202095024_add_key_pair_to_clients.exs │ │ │ ├── 20210301123331_add_label_to_scopes.exs │ │ │ ├── 20210514211510_add_default_redirect_uris_to_clients.exs │ │ │ ├── 20210919174149_openid_connect.exs │ │ │ ├── 20210919174150_clients_refresh_tokens.exs │ │ │ ├── 20211013161324_clients_public_revoke.exs │ │ │ ├── 20220113221532_store_previous_token.exs │ │ │ ├── 20220603211852_id_token_signature_alg_configuration.exs │ │ │ ├── 20220625203958_confidential_clients.exs │ │ │ ├── 20220824105115_refresh_token_rotation.exs │ │ │ ├── 20221025084535_authorization_code_chains.exs │ │ │ ├── 20221122131429_client_authentication_methods.exs │ │ │ ├── 20221129120152_signed_userinfo_response.exs │ │ │ ├── 20230506151359_optional_public_key_for_oauth_clients.exs │ │ │ ├── 20230514134306_clients_jwks_uri.exs │ │ │ ├── 20230515093131_create_key_pairs.exs │ │ │ ├── 20230515152140_client_id_token_kid.exs │ │ │ ├── 20231217091349_add_metadata_to_clients.exs │ │ │ ├── 20231217144905_oid4vci_implementation.exs │ │ │ ├── 20240127081327_siopv2_implementation.exs │ │ │ ├── 20240321101558_dpop_implementation.exs │ │ │ ├── 20240417052138_par_implementation.exs │ │ │ ├── 20240506083712_c_nonce_implementation.exs │ │ │ ├── 20240812111902_defered_credentials.exs │ │ │ ├── 20240824191208_clients_did.exs │ │ │ ├── 20240908082918_verifiable_presentation_definitions.exs │ │ │ ├── 20240914084657_clients_response_mode.exs │ │ │ ├── 20241021132955_clients_key_pair_types.exs │ │ │ ├── 20241209110846_tokens_tx_code.exs │ │ │ ├── 20241220104923_clients_signatures_adapters.exs │ │ │ ├── 20250315084213_fix_oauth_clients_did.exs │ │ │ ├── 20250413070457_agent_credentials.exs │ │ │ ├── 20250524160749_public_client_id.exs │ │ │ ├── 20260324152715_codes_response_type.exs │ │ │ ├── 20260324152716_code_metadata_policy.exs │ │ │ ├── 20260330112657_siopv2_encryption.exs │ │ │ └── 20260428121802_requested_scope.exs │ │ └── test/ │ │ ├── boruta_auth/ │ │ │ └── key_pairs_test.exs │ │ └── test_helper.exs │ ├── boruta_gateway/ │ │ ├── .formatter.exs │ │ ├── .gitignore │ │ ├── config/ │ │ │ ├── config.exs │ │ │ ├── dev.exs │ │ │ ├── prod.exs │ │ │ └── test.exs │ │ ├── lib/ │ │ │ ├── boruta_gateway/ │ │ │ │ ├── application.ex │ │ │ │ ├── configuration_loader.ex │ │ │ │ ├── configuration_schemas/ │ │ │ │ │ └── gateway.ex │ │ │ │ ├── gateway_pipeline.ex │ │ │ │ ├── logger.ex │ │ │ │ ├── microgateway_pipeline.ex │ │ │ │ ├── plugs/ │ │ │ │ │ ├── assign_sidecar_upstream.ex │ │ │ │ │ ├── assign_upstream.ex │ │ │ │ │ ├── authorize.ex │ │ │ │ │ ├── handler.ex │ │ │ │ │ └── metrics.ex │ │ │ │ ├── release.ex │ │ │ │ ├── repo.ex │ │ │ │ ├── router.ex │ │ │ │ ├── server.ex │ │ │ │ ├── sidecar_router.ex │ │ │ │ ├── upstreams/ │ │ │ │ │ ├── client/ │ │ │ │ │ │ └── supervisor.ex │ │ │ │ │ ├── client.ex │ │ │ │ │ ├── store.ex │ │ │ │ │ └── upstream.ex │ │ │ │ └── upstreams.ex │ │ │ ├── boruta_gateway.ex │ │ │ └── mix/ │ │ │ └── tasks/ │ │ │ └── server.ex │ │ ├── mix.exs │ │ ├── priv/ │ │ │ ├── repo/ │ │ │ │ ├── migrations/ │ │ │ │ │ ├── 20200219201345_create_upstreams.exs │ │ │ │ │ ├── 20200326185929_upstreams_notify.exs │ │ │ │ │ ├── 20210111144958_change_upstreams_required_scopes_type.exs │ │ │ │ │ ├── 20220319220305_add_pool_size_to_upstreams.exs │ │ │ │ │ ├── 20220728122802_add_max_idle_time_to_upstreams.exs │ │ │ │ │ ├── 20220729040405_add_pool_count_to_upstreams.exs │ │ │ │ │ ├── 20220810082956_add_forbidden_response_to_upstreams.exs │ │ │ │ │ ├── 20220810084238_add_error_content_type_to_upstreams.exs │ │ │ │ │ ├── 20220810084450_add_unauthorized_response_to_upstreams.exs │ │ │ │ │ ├── 20221024100810_add_forwarded_token_signature_algorithm_to_upstreams.exs │ │ │ │ │ ├── 20221024122642_add_forwarded_token_secret_to_upstreams.exs │ │ │ │ │ ├── 20221024132312_add_forwarded_token_key_pair_to_upstreams.exs │ │ │ │ │ ├── 20230413190522_upstreams_unique_indices.exs │ │ │ │ │ ├── 20230421135202_add_node_name_to_upstreams.exs │ │ │ │ │ └── 20230422083455_update_upstreams_unique_constraint.exs │ │ │ │ └── seeds.exs │ │ │ └── test/ │ │ │ └── configuration_files/ │ │ │ ├── authorized.yml │ │ │ ├── authorized_introspect.yml │ │ │ ├── bad_configuration.yml │ │ │ ├── bad_gateway_configuration.yml │ │ │ ├── bad_microgateway_configuration.yml │ │ │ ├── forbidden.yml │ │ │ ├── full_configuration.yml │ │ │ ├── not_found.yml │ │ │ └── unauthorized.yml │ │ └── test/ │ │ ├── boruta_gateway/ │ │ │ ├── configuration_loader_test.exs │ │ │ ├── integration/ │ │ │ │ └── requests_test.exs │ │ │ ├── upstreams/ │ │ │ │ ├── client_test.exs │ │ │ │ └── store_test.exs │ │ │ └── upstreams_test.exs │ │ ├── support/ │ │ │ └── data_case.ex │ │ └── test_helper.exs │ ├── boruta_identity/ │ │ ├── .formatter.exs │ │ ├── .gitignore │ │ ├── assets/ │ │ │ └── wallet/ │ │ │ ├── .browserslistrc │ │ │ ├── .gitignore │ │ │ ├── Dockerfile │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── public/ │ │ │ │ ├── index.html │ │ │ │ └── robots.txt │ │ │ ├── src/ │ │ │ │ ├── App.vue │ │ │ │ ├── components/ │ │ │ │ │ ├── Consent.vue │ │ │ │ │ ├── Credentials.vue │ │ │ │ │ ├── HelloWorld.vue │ │ │ │ │ └── KeySelect.vue │ │ │ │ ├── main.ts │ │ │ │ ├── registerServiceWorker.ts │ │ │ │ ├── router/ │ │ │ │ │ └── index.ts │ │ │ │ ├── shims-vue.d.ts │ │ │ │ ├── store/ │ │ │ │ │ └── index.ts │ │ │ │ └── views/ │ │ │ │ ├── HomeView.vue │ │ │ │ ├── Oid4vcCallbackView.vue │ │ │ │ └── VerifiableCredentialsIssuanceView.vue │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── config/ │ │ │ ├── config.exs │ │ │ ├── dev.exs │ │ │ ├── prod.exs │ │ │ └── test.exs │ │ ├── lib/ │ │ │ ├── boruta_identity/ │ │ │ │ ├── accounts/ │ │ │ │ │ ├── backends/ │ │ │ │ │ │ ├── federated.ex │ │ │ │ │ │ ├── internal/ │ │ │ │ │ │ │ └── user.ex │ │ │ │ │ │ ├── internal.ex │ │ │ │ │ │ ├── ldap/ │ │ │ │ │ │ │ └── user.ex │ │ │ │ │ │ └── ldap.ex │ │ │ │ │ ├── choose_sessions.ex │ │ │ │ │ ├── confirmations.ex │ │ │ │ │ ├── consents.ex │ │ │ │ │ ├── deliveries/ │ │ │ │ │ │ ├── email_template.ex │ │ │ │ │ │ └── user_notifier.ex │ │ │ │ │ ├── deliveries.ex │ │ │ │ │ ├── registrations.ex │ │ │ │ │ ├── reset_passwords.ex │ │ │ │ │ ├── schemas/ │ │ │ │ │ │ ├── consent.ex │ │ │ │ │ │ ├── role.ex │ │ │ │ │ │ ├── role_scope.ex │ │ │ │ │ │ ├── user.ex │ │ │ │ │ │ ├── user_authorized_scope.ex │ │ │ │ │ │ ├── user_role.ex │ │ │ │ │ │ └── user_token.ex │ │ │ │ │ ├── sessions.ex │ │ │ │ │ ├── settings.ex │ │ │ │ │ ├── users.ex │ │ │ │ │ ├── verifiable_credentials.ex │ │ │ │ │ └── verifiable_presentations.ex │ │ │ │ ├── accounts.ex │ │ │ │ ├── admin.ex │ │ │ │ ├── application.ex │ │ │ │ ├── clients.ex │ │ │ │ ├── configuration/ │ │ │ │ │ └── error_template.ex │ │ │ │ ├── configuration.ex │ │ │ │ ├── federated_accounts.ex │ │ │ │ ├── hooks/ │ │ │ │ │ └── post_user_creation_hook.ex │ │ │ │ ├── identity_providers/ │ │ │ │ │ ├── backend.ex │ │ │ │ │ ├── backend_role.ex │ │ │ │ │ ├── client_identity_provider.ex │ │ │ │ │ ├── identity_provider.ex │ │ │ │ │ └── template.ex │ │ │ │ ├── identity_providers.ex │ │ │ │ ├── ldap_repo.ex │ │ │ │ ├── logger.ex │ │ │ │ ├── organizations/ │ │ │ │ │ ├── organization.ex │ │ │ │ │ └── organization_user.ex │ │ │ │ ├── organizations.ex │ │ │ │ ├── repo.ex │ │ │ │ ├── resource_owners.ex │ │ │ │ ├── totp.ex │ │ │ │ └── webauthn.ex │ │ │ ├── boruta_identity.ex │ │ │ ├── boruta_identity_web/ │ │ │ │ ├── concerns/ │ │ │ │ │ └── authenticable.ex │ │ │ │ ├── controllers/ │ │ │ │ │ ├── backends_controller.ex │ │ │ │ │ ├── choose_session_controller.ex │ │ │ │ │ ├── fallback_controller.ex │ │ │ │ │ ├── totp_controller.ex │ │ │ │ │ ├── user_confirmation_controller.ex │ │ │ │ │ ├── user_consent_controller.ex │ │ │ │ │ ├── user_registration_controller.ex │ │ │ │ │ ├── user_reset_password_controller.ex │ │ │ │ │ ├── user_session_controller.ex │ │ │ │ │ ├── user_settings_controller.ex │ │ │ │ │ ├── wallet_controller.ex │ │ │ │ │ └── webauthn_controller.ex │ │ │ │ ├── endpoint.ex │ │ │ │ ├── gettext.ex │ │ │ │ ├── plugs/ │ │ │ │ │ └── sessions.ex │ │ │ │ ├── router.ex │ │ │ │ ├── telemetry.ex │ │ │ │ ├── templates/ │ │ │ │ │ ├── error/ │ │ │ │ │ │ ├── 400.html.eex │ │ │ │ │ │ ├── 403.html.eex │ │ │ │ │ │ ├── 404.html.eex │ │ │ │ │ │ └── 500.html.eex │ │ │ │ │ ├── layout/ │ │ │ │ │ │ └── app.html.eex │ │ │ │ │ └── wallet/ │ │ │ │ │ └── index.html.eex │ │ │ │ ├── token.ex │ │ │ │ └── views/ │ │ │ │ ├── error_helpers.ex │ │ │ │ ├── error_view.ex │ │ │ │ ├── template_view.ex │ │ │ │ └── wallet_view.ex │ │ │ └── boruta_identity_web.ex │ │ ├── mix.exs │ │ ├── priv/ │ │ │ ├── gettext/ │ │ │ │ ├── en/ │ │ │ │ │ └── LC_MESSAGES/ │ │ │ │ │ └── errors.po │ │ │ │ └── errors.pot │ │ │ ├── repo/ │ │ │ │ ├── migrations/ │ │ │ │ │ ├── .formatter.exs │ │ │ │ │ ├── 20210127190501_create_users_auth_tables.exs │ │ │ │ │ ├── 20210128080043_create_users_authorized_scopes.exs │ │ │ │ │ ├── 20210208110903_user_authorized_scopes_unique_index.exs │ │ │ │ │ ├── 20210302213536_create_consents.exs │ │ │ │ │ ├── 20210806194842_add_last_login_at_to_users.exs │ │ │ │ │ ├── 20211002132445_modify_users_confirmed_at.exs │ │ │ │ │ ├── 20211129225646_create_relying_parties.exs │ │ │ │ │ ├── 20211130230927_create_clients_relying_parties.exs │ │ │ │ │ ├── 20220117220007_add_registrable_to_relying_parties.exs │ │ │ │ │ ├── 20220118122834_add_unique_name_to_relying_parties.exs │ │ │ │ │ ├── 20220120214356_create_relying_party_templates.exs │ │ │ │ │ ├── 20220131133951_add_confirmable_to_relying_parties.exs │ │ │ │ │ ├── 20220218144931_add_consentable_to_relying_parties.exs │ │ │ │ │ ├── 20220221123627_add_choose_session_to_relying_parties.exs │ │ │ │ │ ├── 20220520212652_add_user_editable_to_relying_parties.exs │ │ │ │ │ ├── 20220528155902_create_internal_users.exs │ │ │ │ │ ├── 20220607201657_add_user_authorized_scopes_scope_id.exs │ │ │ │ │ ├── 20220617195827_rename_relying_parties.exs │ │ │ │ │ ├── 20220628073937_create_error_templates.exs │ │ │ │ │ ├── 20220812123254_create_backends.exs │ │ │ │ │ ├── 20220815073225_add_backend_id_to_identity_providers.exs │ │ │ │ │ ├── 20220815091033_remove_type_from_identity_providers.exs │ │ │ │ │ ├── 20220815115719_add_default_to_backends.exs │ │ │ │ │ ├── 20220816074610_add_password_hashing_opts_to_backends.exs │ │ │ │ │ ├── 20220817134821_change_users_provider_to_backend_id.exs │ │ │ │ │ ├── 20220817150643_add_backend_id_to_internal_users.exs │ │ │ │ │ ├── 20220826055043_add_mail_configuration_to_backends.exs │ │ │ │ │ ├── 20220904073628_create_pg_trgm_extension.exs │ │ │ │ │ ├── 20220904183116_create_trgm_index.exs │ │ │ │ │ ├── 20220911195248_add_ldap_configuration_to_backends.exs │ │ │ │ │ ├── 20220915191039_add_ldap_ser_rdn_attribute_to_backends.exs │ │ │ │ │ ├── 20221008202236_add_ldap_master_credentials_to_backends.exs │ │ │ │ │ ├── 20221026092004_create_email_templates.exs │ │ │ │ │ ├── 20221026211130_add_smtp_ssl_to_backends.exs │ │ │ │ │ ├── 20221028083326_add_revoked_at_to_users_tokens.exs │ │ │ │ │ ├── 20221108140432_add_metadata_fields_to_backends.exs │ │ │ │ │ ├── 20221108144651_add_metadata_to_users.exs │ │ │ │ │ ├── 20230303151220_add_group_to_users.exs │ │ │ │ │ ├── 20230502111802_add_identity_federation_to_backends.exs │ │ │ │ │ ├── 20230605073651_create_roles.exs │ │ │ │ │ ├── 20230605074117_create_roles_scopes.exs │ │ │ │ │ ├── 20230615082520_create_roles_users.exs │ │ │ │ │ ├── 20230626064411_create_backends_roles.exs │ │ │ │ │ ├── 20230805134343_add_totpable_to_identity_providers.exs │ │ │ │ │ ├── 20230805160200_add_totp_to_users.exs │ │ │ │ │ ├── 20230810130509_add_enforce_totp_to_identity_providers.exs │ │ │ │ │ ├── 20230903150227_create_organizations.exs │ │ │ │ │ ├── 20230908094746_add_label_to_organizations.exs │ │ │ │ │ ├── 20230908113944_create_organizations_users.exs │ │ │ │ │ ├── 20230909103013_add_create_default_organization_to_backends.exs │ │ │ │ │ ├── 20240109125818_add_verifiable_credentails_to_backends.exs │ │ │ │ │ ├── 20240110094020_add_federated_metadata_to_users.exs │ │ │ │ │ ├── 20240426110841_organizations_users_reference.exs │ │ │ │ │ ├── 20240505104631_organizations_users_reference2.exs │ │ │ │ │ ├── 20240808195715_add_webauthn_challenge_to_users.exs │ │ │ │ │ ├── 20240820140733_add_webauthn_public_key_to_users.exs │ │ │ │ │ ├── 20240820233604_add_webauthn_to_identity_providers.exs │ │ │ │ │ ├── 20240907103609_add_verifiable_presentations_to_backends.exs │ │ │ │ │ ├── 20241017153124_add_account_type_to_users.exs │ │ │ │ │ ├── 20241130000259_add_check_password_to_identity_providers.exs │ │ │ │ │ └── 20250302193825_remove_global_email_unique_constraint.exs │ │ │ │ └── seeds.exs │ │ │ └── templates/ │ │ │ ├── choose_session/ │ │ │ │ └── index.mustache │ │ │ ├── confirmations/ │ │ │ │ └── new.mustache │ │ │ ├── consents/ │ │ │ │ └── new.mustache │ │ │ ├── emails/ │ │ │ │ ├── confirmation_instructions.html.mustache │ │ │ │ ├── confirmation_instructions.txt.mustache │ │ │ │ ├── reset_password_instructions.html.mustache │ │ │ │ ├── reset_password_instructions.txt.mustache │ │ │ │ ├── tx_code.html.mustache │ │ │ │ └── tx_code.txt.mustache │ │ │ ├── errors/ │ │ │ │ ├── 400.mustache │ │ │ │ ├── 401.mustache │ │ │ │ ├── 403.mustache │ │ │ │ ├── 404.mustache │ │ │ │ └── 500.mustache │ │ │ ├── layouts/ │ │ │ │ └── app.mustache │ │ │ ├── mfa/ │ │ │ │ ├── totp/ │ │ │ │ │ ├── authentication.mustache │ │ │ │ │ └── registration.mustache │ │ │ │ └── webauthn/ │ │ │ │ ├── authentication.mustache │ │ │ │ └── registration.mustache │ │ │ ├── registrations/ │ │ │ │ └── new.mustache │ │ │ ├── reset_passwords/ │ │ │ │ ├── edit.mustache │ │ │ │ └── new.mustache │ │ │ ├── sessions/ │ │ │ │ └── new.mustache │ │ │ └── settings/ │ │ │ ├── credential_offer.mustache │ │ │ ├── edit_user.mustache │ │ │ └── verifiable_presentation.mustache │ │ └── test/ │ │ ├── boruta_identity/ │ │ │ ├── accounts/ │ │ │ │ └── deliveries_test.exs │ │ │ ├── accounts_test.exs │ │ │ ├── admin_test.exs │ │ │ ├── configuration_test.exs │ │ │ ├── federated_accounts_test.exs │ │ │ ├── identity_providers/ │ │ │ │ ├── backend_test.exs │ │ │ │ └── identity_provider_test.exs │ │ │ ├── identity_providers_test.exs │ │ │ ├── resource_owners_test.exs │ │ │ ├── totp_test.exs │ │ │ └── webauthn_test.exs │ │ ├── boruta_identity_web/ │ │ │ ├── concerns/ │ │ │ │ └── authenticable_test.exs │ │ │ ├── controllers/ │ │ │ │ ├── choose_session_controller_test.exs │ │ │ │ ├── page_controller_test.exs │ │ │ │ ├── totp_controller_test.exs │ │ │ │ ├── user_confirmation_controller_test.exs │ │ │ │ ├── user_consent_controller_test.exs │ │ │ │ ├── user_registration_controller_test.exs │ │ │ │ ├── user_reset_password_controller_test.exs │ │ │ │ ├── user_session_controller_test.exs │ │ │ │ └── user_settings_controller_test.exs │ │ │ ├── plugs/ │ │ │ │ └── sessions_test.exs │ │ │ └── views/ │ │ │ ├── error_view_test.exs │ │ │ ├── layout_view_test.exs │ │ │ └── page_view_test.exs │ │ ├── support/ │ │ │ ├── boruta_factory.ex │ │ │ ├── boruta_identity_factory.ex │ │ │ ├── conn_case.ex │ │ │ ├── data_case.ex │ │ │ └── fixtures/ │ │ │ ├── accounts_fixtures.ex │ │ │ ├── admin_fixtures.ex │ │ │ └── identity_providers_fixtures.ex │ │ └── test_helper.exs │ └── boruta_web/ │ ├── .formatter.exs │ ├── .gitignore │ ├── config/ │ │ ├── config.exs │ │ ├── dev.exs │ │ ├── prod.exs │ │ └── test.exs │ ├── lib/ │ │ ├── boruta/ │ │ │ └── status_resolver.ex │ │ ├── boruta_web/ │ │ │ ├── application.ex │ │ │ ├── controllers/ │ │ │ │ ├── did_controller.ex │ │ │ │ ├── fallback_controller.ex │ │ │ │ ├── monitoring_controller.ex │ │ │ │ ├── oauth/ │ │ │ │ │ ├── authorize_controller.ex │ │ │ │ │ ├── introspect_controller.ex │ │ │ │ │ ├── pushed_authorization_request_controller.ex │ │ │ │ │ ├── revoke_controller.ex │ │ │ │ │ └── token_controller.ex │ │ │ │ ├── openid/ │ │ │ │ │ ├── credential_controller.ex │ │ │ │ │ ├── dynamic_registration_controller.ex │ │ │ │ │ ├── jwks_controller.ex │ │ │ │ │ └── userinfo_controller.ex │ │ │ │ └── openid_controller.ex │ │ │ ├── endpoint.ex │ │ │ ├── gettext.ex │ │ │ ├── logger.ex │ │ │ ├── plugs/ │ │ │ │ └── rate_limit.ex │ │ │ ├── presentation_server.ex │ │ │ ├── release.ex │ │ │ ├── repo.ex │ │ │ ├── router.ex │ │ │ ├── templates/ │ │ │ │ └── error/ │ │ │ │ ├── 404.html.eex │ │ │ │ └── 500.html.eex │ │ │ ├── token.ex │ │ │ └── views/ │ │ │ ├── error_helpers.ex │ │ │ ├── error_view.ex │ │ │ ├── oauth_view.ex │ │ │ └── openid_view.ex │ │ ├── boruta_web.ex │ │ └── mix/ │ │ └── tasks/ │ │ └── server.ex │ ├── mix.exs │ ├── priv/ │ │ ├── gettext/ │ │ │ ├── en/ │ │ │ │ └── LC_MESSAGES/ │ │ │ │ └── errors.po │ │ │ └── errors.pot │ │ └── repo/ │ │ └── migrations/ │ │ └── .keep │ └── test/ │ ├── boruta_web/ │ │ ├── controllers/ │ │ │ ├── credential_controller_test.exs │ │ │ ├── oauth/ │ │ │ │ ├── authorization_code_test.exs │ │ │ │ ├── authorize_controller_test.exs │ │ │ │ ├── client_credentials_test.exs │ │ │ │ ├── direct_post_test.exs │ │ │ │ ├── implicit_test.exs │ │ │ │ ├── introspect_test.exs │ │ │ │ ├── openid_connect_test.exs │ │ │ │ ├── password_test.exs │ │ │ │ └── revoke_test.exs │ │ │ └── pushed_authorization_request_controller_test.exs │ │ ├── plugs/ │ │ │ └── rate_limit_test.exs │ │ └── views/ │ │ ├── error_view_test.exs │ │ ├── layout_view_test.exs │ │ └── page_view_test.exs │ ├── support/ │ │ ├── boruta_factory.ex │ │ ├── boruta_identity_factory.ex │ │ └── conn_case.ex │ └── test_helper.exs ├── boruta-admin.openapi.json ├── config/ │ ├── config.exs │ ├── dev.exs │ ├── prod.exs │ ├── releases.exs │ └── test.exs ├── docker-compose.yml ├── examples/ │ ├── README.md │ └── sidecar-authorization-gateways/ │ ├── config/ │ │ ├── example-gateway-configuration.yml │ │ ├── example-httpbin-configuration.yml │ │ └── example-protected-httpbin-configuration.yml │ └── docker-compose.yml ├── mix.exs ├── rel/ │ ├── env.bat.eex │ ├── env.sh.eex │ └── vm.args.eex ├── scripts/ │ ├── prepare_assets.sh │ └── setup.debian.sh ├── static_config/ │ ├── example-gateway-configuration.yml │ ├── example-httpbin-configuration.yml │ └── example-protected-httpbin-configuration.yml └── vetur.config.js
SYMBOL INDEX (1748 symbols across 395 files)
FILE: apps/boruta_admin/assets/src/models/backend.model.js
class Backend (line 125) | class Backend {
method constructor (line 126) | constructor(params = {}) {
method isPersisted (line 135) | get isPersisted() {
method save (line 139) | save() {
method destroy (line 169) | destroy() {
method serialized (line 180) | get serialized() {
method resetPasswordAlgorithmOpts (line 277) | resetPasswordAlgorithmOpts() {
method passwordHashingAlgorithms (line 281) | static get passwordHashingAlgorithms() {
method passwordHashingOpts (line 289) | static get passwordHashingOpts() {
method api (line 368) | static api() {
method all (line 379) | static all() {
method get (line 389) | static get(id) {
class Claim (line 398) | class Claim {
method constructor (line 399) | constructor (attrs = {}) {
method build (line 424) | static build (claimType) {
method assignType (line 428) | assignType (claimType) {
method attributeTypes (line 432) | static get attributeTypes () {
method objectTypes (line 436) | static get objectTypes () {
method arrayTypes (line 440) | static get arrayTypes () {
method isAttribute (line 444) | get isAttribute () {
method isObject (line 448) | get isObject () {
method isArray (line 452) | get isArray () {
method baseClaim (line 456) | static baseClaim(claimType) {
FILE: apps/boruta_admin/assets/src/models/business-log-stats.model.js
class LogStats (line 21) | class LogStats {
method constructor (line 22) | constructor (params = {}) {
FILE: apps/boruta_admin/assets/src/models/client.model.js
class Client (line 101) | class Client {
method constructor (line 102) | constructor (params = {}) {
method validate (line 112) | validate () {
method save (line 130) | async save () {
method regenerateDid (line 161) | async regenerateDid () {
method regenerateKeyPair (line 182) | async regenerateKeyPair () {
method destroy (line 204) | destroy () {
method serialized (line 213) | get serialized () {
FILE: apps/boruta_admin/assets/src/models/email-template.model.js
class EmailTemplate (line 20) | class EmailTemplate {
method constructor (line 21) | constructor (params = {}) {
method save (line 30) | save () {
method destroy (line 52) | destroy () {
method serialized (line 72) | get serialized () {
method api (line 81) | static api () {
method get (line 92) | static get (backendId, type) {
FILE: apps/boruta_admin/assets/src/models/error-template.model.js
class ErrorTemplate (line 27) | class ErrorTemplate {
method constructor (line 28) | constructor (params = {}) {
method save (line 37) | save () {
method destroy (line 59) | destroy () {
method serialized (line 79) | get serialized () {
method api (line 87) | static api () {
method get (line 98) | static get (type) {
method all (line 104) | static all () {
FILE: apps/boruta_admin/assets/src/models/identity-provider.model.js
class IdentityProvider (line 30) | class IdentityProvider {
method constructor (line 31) | constructor (params = {}) {
method isPersisted (line 40) | get isPersisted () {
method save (line 44) | save () {
method destroy (line 72) | destroy () {
method serialized (line 81) | get serialized () {
method api (line 115) | static api () {
method all (line 126) | static all () {
method get (line 132) | static get (id) {
FILE: apps/boruta_admin/assets/src/models/key-pair.model.js
class KeyPair (line 12) | class KeyPair {
method constructor (line 13) | constructor (params = {}) {
method persisted (line 22) | get persisted () {
method rotate (line 26) | rotate () {
method save (line 36) | save () {
method destroy (line 56) | destroy () {
method serialized (line 65) | get serialized () {
FILE: apps/boruta_admin/assets/src/models/organization.model.js
class Organization (line 17) | class Organization {
method constructor (line 18) | constructor (params = {}) {
method isPersisted (line 27) | get isPersisted() {
method save (line 31) | async save () {
method destroy (line 58) | destroy () {
method serialized (line 62) | get serialized () {
FILE: apps/boruta_admin/assets/src/models/request-log-stats.model.js
class LogStats (line 20) | class LogStats {
method constructor (line 21) | constructor (params = {}) {
FILE: apps/boruta_admin/assets/src/models/role.model.js
class Role (line 15) | class Role {
method constructor (line 16) | constructor (params = {}) {
method save (line 25) | save () {
method destroy (line 53) | destroy () {
method serialized (line 62) | get serialized () {
FILE: apps/boruta_admin/assets/src/models/scope.model.js
class Scope (line 17) | class Scope {
method constructor (line 18) | constructor (params = {}) {
method persisted (line 27) | get persisted () {
method reset (line 31) | reset () {
method save (line 38) | save () {
method destroy (line 58) | destroy () {
method serialized (line 67) | get serialized () {
FILE: apps/boruta_admin/assets/src/models/template.model.js
class Template (line 18) | class Template {
method constructor (line 19) | constructor (params = {}) {
method save (line 28) | save () {
method destroy (line 50) | destroy () {
method serialized (line 70) | get serialized () {
method api (line 79) | static api () {
method get (line 90) | static get (identityProviderId, type) {
FILE: apps/boruta_admin/assets/src/models/upstream.model.js
class Upstream (line 43) | class Upstream {
method constructor (line 44) | constructor (params = {}) {
method baseUrl (line 53) | get baseUrl () {
method save (line 59) | save () {
method destroy (line 87) | destroy () {
method serialized (line 96) | get serialized () {
FILE: apps/boruta_admin/assets/src/models/user.model.js
class User (line 56) | class User {
method constructor (line 57) | constructor (params = {}) {
method isPersisted (line 66) | get isPersisted() {
method validate (line 71) | validate () {
method save (line 89) | async save () {
method destroy (line 117) | destroy () {
method serialized (line 121) | get serialized () {
FILE: apps/boruta_admin/assets/src/models/utils.js
function addClientErrorInterceptor (line 5) | function addClientErrorInterceptor(instance) {
FILE: apps/boruta_admin/assets/src/services/configuration-file.service.js
class ConfigurationFile (line 4) | class ConfigurationFile {
method api (line 5) | static get api () {
method upload (line 15) | static upload (file) {
method get (line 30) | static get (type = '') {
method baseConfiguration (line 37) | static get baseConfiguration () {
FILE: apps/boruta_admin/assets/src/services/oauth.service.js
class Oauth (line 4) | class Oauth {
method constructor (line 5) | constructor () {
method idToken (line 27) | get idToken() {
method currentUser (line 31) | get currentUser() {
method authenticate (line 40) | authenticate (response) {
method login (line 60) | login () {
method silentRefresh (line 64) | silentRefresh () {
method callback (line 68) | async callback () {
method logout (line 78) | logout () {
method storeLocationName (line 85) | storeLocationName ({ name, params, query }) {
method storedLocation (line 91) | get storedLocation () {
method accessToken (line 98) | get accessToken () {
method isAuthenticated (line 102) | get isAuthenticated () {
method expiresIn (line 108) | get expiresIn () {
FILE: apps/boruta_admin/assets/src/store.js
method isAuthenticated (line 10) | isAuthenticated (state) {
method SET_AUTHENTICATED (line 15) | SET_AUTHENTICATED (state, isAuthenticated) {
method logout (line 20) | logout ({ commit }) {
FILE: apps/boruta_admin/lib/boruta_admin.ex
class BorutaAdmin (line 1) | defmodule BorutaAdmin
FILE: apps/boruta_admin/lib/boruta_admin/application.ex
class BorutaAdmin.Application (line 1) | defmodule BorutaAdmin.Application
method start (line 8) | def start(_type, _args) do
method setup_database (line 28) | def setup_database do
method config_change (line 40) | def config_change(changed, _new, removed) do
method boruta_admin_request_handler (line 45) | def boruta_admin_request_handler(_, %{duration: duration}, %{conn: con...
method log_level (line 77) | defp log_level(nil, _conn), do: :info
method connection_type (line 84) | defp connection_type(:set_chunked), do: "chunked"
method connection_type (line 85) | defp connection_type(_), do: "sent"
method duration (line 87) | defp duration(duration) do
FILE: apps/boruta_admin/lib/boruta_admin/configuration_loader.ex
class BorutaAdmin.ConfigurationLoader (line 1) | defmodule BorutaAdmin.ConfigurationLoader
method node_name (line 14) | def node_name do
method from_file! (line 40) | def from_file!(path) do
method load_configuration (line 50) | def load_configuration(configuration) do
method load_configuration (line 366) | def load_configuration(%{}, result), do: result
FILE: apps/boruta_admin/lib/boruta_admin/configuration_loader/schema.ex
class BorutaAdmin.ConfigurationLoader.Schema (line 1) | defmodule BorutaAdmin.ConfigurationLoader.Schema
method gateway (line 6) | def gateway do
method microgateway (line 52) | def microgateway do
method organization (line 99) | def organization do
method backend (line 112) | def backend do
method identity_provider (line 269) | def identity_provider do
method client (line 299) | def client do
method scope (line 356) | def scope do
method role (line 370) | def role do
method error_template (line 391) | def error_template do
FILE: apps/boruta_admin/lib/boruta_admin/configurations.ex
class BorutaAdmin.Configurations (line 1) | defmodule BorutaAdmin.Configurations
method upsert_configuration (line 9) | def upsert_configuration(name, value) do
method list_configurations (line 18) | def list_configurations do
method get_configuration (line 22) | def get_configuration(name) do
FILE: apps/boruta_admin/lib/boruta_admin/configurations/configuration.ex
class BorutaAdmin.Configurations.Configuration (line 1) | defmodule BorutaAdmin.Configurations.Configuration
method changeset (line 25) | def changeset(upstream, attrs) do
FILE: apps/boruta_admin/lib/boruta_admin/logs.ex
class BorutaAdmin.Logs (line 18) | defmodule BorutaAdmin.Logs
class BorutaAdmin.Logs.FileTooLargeError (line 1) | defmodule BorutaAdmin.Logs.FileTooLargeError
method message (line 13) | def message(exception) do
method read (line 36) | def read(start_at, end_at, application, :request = type, query) do
method read (line 124) | def read(start_at, end_at, application, :business = type, query) do
method read (line 202) | def read(_start_at, _end_at, _application, _type), do: %{}
method log_stream (line 204) | defp log_stream(start_at, end_at, application, type) do
method parse_request_log (line 238) | defp parse_request_log(log_line) do
method normalize_request_label_path (line 279) | defp normalize_request_label_path(path), do: path
method apply_request_filters (line 281) | def apply_request_filters(request_stream, query) do
method apply_business_filters (line 300) | def apply_business_filters(request_stream, query) do
method parse_business_log (line 319) | defp parse_business_log(log_line) do
method log_dates (line 348) | defp log_dates(start_date, end_date) do
method time_scale_unit (line 356) | defp time_scale_unit(start_at, end_at) do
FILE: apps/boruta_admin/lib/boruta_admin/release.ex
class BorutaAdmin.Release (line 1) | defmodule BorutaAdmin.Release
method load_configuration (line 4) | def load_configuration do
FILE: apps/boruta_admin/lib/boruta_admin/repo.ex
class BorutaAdmin.Repo (line 1) | defmodule BorutaAdmin.Repo
FILE: apps/boruta_admin/lib/boruta_admin_web.ex
class BorutaAdminWeb (line 1) | defmodule BorutaAdminWeb
method controller (line 20) | def controller do
method view (line 30) | def view do
method router (line 45) | def router do
method channel (line 54) | def channel do
method view_helpers (line 61) | defp view_helpers do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/backend_controller.ex
class BorutaAdminWeb.BackendController (line 1) | defmodule BorutaAdminWeb.BackendController
method index (line 17) | def index(conn, _params) do
method create (line 22) | def create(conn, %{"backend" => backend_params}) do
method create (line 32) | def create(_conn, _params), do: {:error, :bad_request}
method show (line 34) | def show(conn, %{"id" => id}) do
method update (line 39) | def update(conn, %{"id" => id, "backend" => backend_params}) do
method update (line 48) | def update(_conn, _params), do: {:error, :bad_request}
method delete (line 50) | def delete(conn, %{"id" => id}) do
method email_template (line 59) | def email_template(conn, %{"backend_id" => id, "template_type" => temp...
method update_email_template (line 64) | def update_email_template(conn, %{
method delete_email_template (line 77) | def delete_email_template(conn, %{"backend_id" => id, "template_type" ...
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/boruta/client_controller.ex
class BorutaAdminWeb.ClientController (line 1) | defmodule BorutaAdminWeb.ClientController
method index (line 18) | def index(conn, _params) do
method create (line 24) | def create(conn, %{"client" => client_params}) do
method show (line 33) | def show(conn, %{"id" => client_id}) do
method update (line 39) | def update(conn, %{"id" => client_id, "client" => client_params}) do
method update_client (line 49) | defp update_client(
method update_client (line 68) | defp update_client(client, client_params) do
method regenerate_did (line 72) | def regenerate_did(conn, %{"id" => client_id}) do
method regenerate_key_pair (line 80) | def regenerate_key_pair(conn, %{"id" => client_id}) do
method delete (line 89) | def delete(conn, %{"id" => client_id}) do
method get_client (line 102) | defp get_client(client_id) do
method ensure_open_for_edition (line 107) | defp ensure_open_for_edition(client_id) do
method delete_client_multi (line 117) | defp delete_client_multi(client_id) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/boruta/scope_controller.ex
class BorutaAdminWeb.ScopeController (line 1) | defmodule BorutaAdminWeb.ScopeController
method index (line 25) | def index(conn, _params) do
method create (line 30) | def create(conn, %{"scope" => scope_params}) do
method show (line 39) | def show(conn, %{"id" => id}) do
method update (line 44) | def update(conn, %{"id" => id, "scope" => scope_params}) do
method delete (line 53) | def delete(conn, %{"id" => id}) do
method ensure_open_for_edition (line 62) | def ensure_open_for_edition(scope) do
method delete_scope_multi (line 69) | defp delete_scope_multi(scope) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/configuration_controller.ex
class BorutaAdminWeb.ConfigurationController (line 1) | defmodule BorutaAdminWeb.ConfigurationController
method error_template (line 31) | def error_template(conn, %{"template_type" => template_type}) do
method update_error_template (line 36) | def update_error_template(conn, %{
method delete_error_template (line 48) | def delete_error_template(conn, %{"template_type" => template_type}) do
method example_configuration_file (line 53) | def example_configuration_file(conn, _params) do
method configuration (line 87) | def configuration(conn, _params) do
method upload_configuration_file (line 93) | def upload_configuration_file(conn, %{"file" => %Plug.Upload{path: pat...
method filter_configuration (line 109) | defp filter_configuration(configuration, %{"scope" => scope}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/fallback_controller.ex
class BorutaAdminWeb.FallbackController (line 1) | defmodule BorutaAdminWeb.FallbackController
method call (line 9) | def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
method call (line 16) | def call(conn, {:error, :bad_request}) do
method call (line 23) | def call(conn, {:error, :not_found}) do
method call (line 30) | def call(conn, {:error, :unauthorized}) do
method call (line 37) | def call(conn, {:error, :forbidden}) do
method call (line 44) | def call(conn, {:error, :protected_resource}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/identity_provider_controller.ex
class BorutaAdminWeb.IdentityProviderController (line 1) | defmodule BorutaAdminWeb.IdentityProviderController
method index (line 17) | def index(conn, _params) do
method create (line 22) | def create(conn, %{"identity_provider" => identity_provider_params}) do
method show (line 32) | def show(conn, %{"id" => id}) do
method update (line 37) | def update(conn, %{"id" => id, "identity_provider" => identity_provide...
method delete (line 46) | def delete(conn, %{"id" => id}) do
method template (line 55) | def template(conn, %{"identity_provider_id" => id, "template_type" => ...
method update_template (line 60) | def update_template(conn, %{
method delete_template (line 73) | def delete_template(conn, %{"identity_provider_id" => id, "template_ty...
method ensure_open_for_edition (line 78) | defp ensure_open_for_edition(identity_provider_id) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/key_pair_controller.ex
class BorutaAdminWeb.KeyPairController (line 1) | defmodule BorutaAdminWeb.KeyPairController
method index (line 16) | def index(conn, _params) do
method create (line 21) | def create(conn, %{"key_pair" => key_pair_params}) do
method show (line 30) | def show(conn, %{"id" => id}) do
method rotate (line 35) | def rotate(conn, %{"id" => id}) do
method update (line 43) | def update(conn, %{"id" => id, "key_pair" => key_pair_params}) do
method delete (line 51) | def delete(conn, %{"id" => id}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/logs_controller.ex
class BorutaAdminWeb.LogsController (line 1) | defmodule BorutaAdminWeb.LogsController
method index (line 15) | def index(
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/organization_controller.ex
class BorutaAdminWeb.OrganizationController (line 1) | defmodule BorutaAdminWeb.OrganizationController
method index (line 16) | def index(conn, params) do
method show (line 32) | def show(conn, %{"id" => id}) do
method create (line 42) | def create(conn, %{"organization" => organization_params}) do
method create (line 53) | def create(_conn, _params), do: {:error, :bad_request}
method update (line 55) | def update(conn, %{"id" => id, "organization" => organization_params}) do
method update (line 72) | def update(_conn, _params), do: {:error, :bad_request}
method delete (line 74) | def delete(conn, %{"id" => organization}) do
method ensure_open_for_edition (line 81) | defp ensure_open_for_edition(_user_id, _conn) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/page_controller.ex
class BorutaAdminWeb.PageController (line 1) | defmodule BorutaAdminWeb.PageController
method index (line 4) | def index(conn, _params) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/role_controller.ex
class BorutaAdminWeb.RoleController (line 1) | defmodule BorutaAdminWeb.RoleController
method index (line 16) | def index(conn, _params) do
method create (line 21) | def create(conn, %{"role" => role_params}) do
method show (line 30) | def show(conn, %{"id" => id}) do
method update (line 35) | def update(conn, %{"id" => id, "role" => role_params}) do
method delete (line 44) | def delete(conn, %{"id" => id}) do
method ensure_open_for_edition (line 53) | def ensure_open_for_edition(_role) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/upstream_controller.ex
class BorutaAdminWeb.UpstreamController (line 1) | defmodule BorutaAdminWeb.UpstreamController
method index (line 16) | def index(conn, _params) do
method node_list (line 21) | def node_list(conn, _params) do
method show (line 30) | def show(conn, %{"id" => id}) do
method create (line 35) | def create(conn, %{"upstream" => upstream_params}) do
method update (line 44) | def update(conn, %{"id" => id, "upstream" => upstream_params}) do
method delete (line 52) | def delete(conn, %{"id" => id}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/controllers/user_controller.ex
class BorutaAdminWeb.UserController (line 1) | defmodule BorutaAdminWeb.UserController
method index (line 18) | def index(conn, params) do
method show (line 34) | def show(conn, %{"id" => id}) do
method create (line 44) | def create(conn, %{"backend_id" => backend_id, "user" => user_params}) do
method create (line 70) | def create(conn, %{"backend_id" => backend_id, "file" => file_params} ...
method create (line 106) | def create(_conn, _params), do: {:error, :bad_request}
method update (line 108) | def update(conn, %{"id" => id, "user" => user_params}) do
method update (line 129) | def update(_conn, _params), do: {:error, :bad_request}
method delete (line 131) | def delete(conn, %{"id" => user_id}) do
method ensure_open_for_edition (line 144) | defp ensure_open_for_edition(user_id, conn) do
FILE: apps/boruta_admin/lib/boruta_admin_web/endpoint.ex
class BorutaAdminWeb.Endpoint (line 1) | defmodule BorutaAdminWeb.Endpoint
method log_level (line 38) | def log_level(%{path_info: ["healthcheck" | _]}), do: false
method log_level (line 39) | def log_level(%{path_info: ["favicon.ico" | _]}), do: false
method log_level (line 40) | def log_level(_), do: :info
FILE: apps/boruta_admin/lib/boruta_admin_web/gettext.ex
class BorutaAdminWeb.Gettext (line 1) | defmodule BorutaAdminWeb.Gettext
FILE: apps/boruta_admin/lib/boruta_admin_web/plugs/authorization.ex
class BorutaAdminWeb.Authorization (line 1) | defmodule BorutaAdminWeb.Authorization
method require_authenticated (line 17) | def require_authenticated(conn, _opts \\ []) do
method unauthorized (line 54) | def unauthorized(_conn, error) do
method userinfo_fetched (line 59) | def userinfo_fetched(_conn, userinfo_response) do
method authorize (line 68) | def authorize(conn, [_h | _t] = scopes) do
method authorize (line 84) | def authorize(conn, _opts) do
method userinfo (line 93) | def userinfo(access_token) do
method respond_unauthorized (line 110) | defp respond_unauthorized(conn, e) do
method maybe_validate_user (line 120) | defp maybe_validate_user(userinfo) do
FILE: apps/boruta_admin/lib/boruta_admin_web/plugs/logger.ex
class BorutaAdminWeb.Logger (line 1) | defmodule BorutaAdminWeb.Logger
method init (line 9) | def init(opts) do
method call (line 14) | def call(conn, level) do
method duration (line 52) | defp duration(duration) do
method connection_type (line 62) | defp connection_type(%{state: :set_chunked}), do: "Chunked"
method connection_type (line 63) | defp connection_type(_), do: "Sent"
FILE: apps/boruta_admin/lib/boruta_admin_web/router.ex
class BorutaAdminWeb.Router (line 1) | defmodule BorutaAdminWeb.Router
method handle_errors (line 104) | def handle_errors(conn, %{kind: _kind, reason: reason, stack: _stack}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/telemetry.ex
class BorutaAdminWeb.Telemetry (line 1) | defmodule BorutaAdminWeb.Telemetry
method start_link (line 7) | def start_link(arg) do
method init (line 12) | def init(_arg) do
method metrics (line 24) | def metrics do
method periodic_measurements (line 50) | defp periodic_measurements do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/backend_view.ex
class BorutaAdminWeb.BackendView (line 1) | defmodule BorutaAdminWeb.BackendView
method render (line 8) | def render("index.json", %{backends: backends}) do
method render (line 12) | def render("show.json", %{backend: backend}) do
method render (line 16) | def render("show_email_template.json", %{email_template: template}) do
method render (line 20) | def render("backend.json", %{backend: backend}) do
method render (line 52) | def render("email_template.json", %{template: template}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/changeset_view.ex
class BorutaAdminWeb.ChangesetView (line 1) | defmodule BorutaAdminWeb.ChangesetView
method translate_errors (line 10) | def translate_errors(changeset) do
method render (line 14) | def render("error.json", %{changeset: changeset}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/client_view.ex
class BorutaAdminWeb.ClientView (line 1) | defmodule BorutaAdminWeb.ClientView
method render (line 8) | def render("index.json", %{clients: clients}) do
method render (line 12) | def render("show.json", %{client: client}) do
method render (line 16) | def render("client.json", %{client: client}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/configuration_view.ex
class BorutaAdminWeb.ConfigurationView (line 1) | defmodule BorutaAdminWeb.ConfigurationView
method render (line 6) | def render("show_error_template.json", %{template: template}) do
method render (line 10) | def render("error_template.json", %{template: template}) do
method render (line 18) | def render("configuration.json", %{configurations: configurations}) do
method render (line 24) | def render("file_upload.json", %{result: result, file_content: file_co...
FILE: apps/boruta_admin/lib/boruta_admin_web/views/error_helpers.ex
class BorutaAdminWeb.ErrorHelpers (line 1) | defmodule BorutaAdminWeb.ErrorHelpers
method error_tag (line 11) | def error_tag(form, field) do
method translate_error (line 23) | def translate_error({msg, opts}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/error_view.ex
class BorutaAdminWeb.ErrorView (line 1) | defmodule BorutaAdminWeb.ErrorView
method render (line 4) | def render("400.json", _assigns) do
method render (line 14) | def render("404.json", _assigns) do
method render (line 24) | def render("401.json", _assigns) do
method render (line 34) | def render("403.json", _assigns) do
method render (line 44) | def render("protected_resource.json", _assigns) do
method template_not_found (line 54) | def template_not_found(template, _assigns) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/identity_provider_view.ex
class BorutaAdminWeb.IdentityProviderView (line 1) | defmodule BorutaAdminWeb.IdentityProviderView
method render (line 6) | def render("index.json", %{identity_providers: identity_providers}) do
method render (line 10) | def render("show.json", %{identity_provider: identity_provider}) do
method render (line 14) | def render("show_template.json", %{template: template}) do
method render (line 18) | def render("identity_provider.json", %{identity_provider: identity_pro...
method render (line 37) | def render("template.json", %{template: template}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/key_pair_view.ex
class BorutaAdminWeb.KeyPairView (line 1) | defmodule BorutaAdminWeb.KeyPairView
method render (line 5) | def render("index.json", %{key_pairs: key_pairs}) do
method render (line 9) | def render("show.json", %{key_pair: key_pair}) do
method render (line 13) | def render("key_pair.json", %{key_pair: key_pair}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/logs_view.ex
class BorutaAdminWeb.LogsView (line 1) | defmodule BorutaAdminWeb.LogsView
method render (line 4) | def render("index.json", %{stats: stats}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/organization_view.ex
class BorutaAdminWeb.OrganizationView (line 1) | defmodule BorutaAdminWeb.OrganizationView
method render (line 6) | def render("index.json", %{
method render (line 22) | def render("show.json", %{organization: organization}) do
method render (line 26) | def render("organization.json", %{organization: organization}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/page_view.ex
class BorutaAdminWeb.PageView (line 1) | defmodule BorutaAdminWeb.PageView
FILE: apps/boruta_admin/lib/boruta_admin_web/views/role_view.ex
class BorutaAdminWeb.RoleView (line 1) | defmodule BorutaAdminWeb.RoleView
method render (line 5) | def render("index.json", %{roles: roles}) do
method render (line 9) | def render("show.json", %{role: role}) do
method render (line 13) | def render("role.json", %{role: role}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/scope_view.ex
class BorutaAdminWeb.ScopeView (line 1) | defmodule BorutaAdminWeb.ScopeView
method render (line 5) | def render("index.json", %{scopes: scopes}) do
method render (line 9) | def render("show.json", %{scope: scope}) do
method render (line 13) | def render("scope.json", %{scope: scope}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/upstream_view.ex
class BorutaAdminWeb.UpstreamView (line 1) | defmodule BorutaAdminWeb.UpstreamView
method render (line 5) | def render("index.json", %{upstreams: upstreams}) do
method render (line 15) | def render("node_list.json", %{nodes: nodes}) do
method render (line 19) | def render("show.json", %{upstream: upstream}) do
method render (line 23) | def render("upstream.json", %{upstream: upstream}) do
FILE: apps/boruta_admin/lib/boruta_admin_web/views/user_view.ex
class BorutaAdminWeb.UserView (line 1) | defmodule BorutaAdminWeb.UserView
method render (line 11) | def render("index.json", %{
method render (line 27) | def render("show.json", %{user: user}) do
method render (line 31) | def render("user.json", %{user: user}) do
method render (line 55) | def render("import_result.json", %{import_result: import_result}) do
FILE: apps/boruta_admin/mix.exs
class BorutaAdmin.MixProject (line 1) | defmodule BorutaAdmin.MixProject
method project (line 4) | def project do
method application (line 24) | def application do
method elixirc_paths (line 32) | defp elixirc_paths(:test), do: ["lib", "test/support"]
method elixirc_paths (line 33) | defp elixirc_paths(_), do: ["lib"]
method deps (line 38) | defp deps do
method aliases (line 69) | defp aliases do
FILE: apps/boruta_admin/priv/repo/migrations/20240508054424_create_configurations.exs
class BorutaAdmin.Repo.Migrations.CreateConfigurations (line 1) | defmodule BorutaAdmin.Repo.Migrations.CreateConfigurations
method change (line 4) | def change do
FILE: apps/boruta_admin/test/boruta_admin/configuration_loader_test.exs
class BorutaAdmin.ConfigurationLoaderTest (line 1) | defmodule BorutaAdmin.ConfigurationLoaderTest
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/backend_controller_test.exs
class BorutaAdminWeb.BackendControllerTest (line 1) | defmodule BorutaAdminWeb.BackendControllerTest
method fixture (line 430) | def fixture(:backend) do
method create_backend (line 435) | defp create_backend(_) do
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/client_controller_test.exs
class BorutaAdminWeb.ClientControllerTest (line 1) | defmodule BorutaAdminWeb.ClientControllerTest
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/configuration_controller_test.exs
class BorutaAdminWeb.ConfigurationControllerTest (line 1) | defmodule BorutaAdminWeb.ConfigurationControllerTest
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/identity_provider_controller_test.exs
class BorutaAdminWeb.IdentityProviderControllerTest (line 1) | defmodule BorutaAdminWeb.IdentityProviderControllerTest
method fixture (line 20) | def fixture(:identity_provider) do
method create_identity_provider (line 561) | defp create_identity_provider(_) do
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/key_pair_controller_test.exs
class BorutaAdminWeb.KeyPairControllerTest (line 1) | defmodule BorutaAdminWeb.KeyPairControllerTest
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/logs_controller_test.exs
class BorutaAdminWeb.LogsControllerTest (line 1) | defmodule BorutaAdminWeb.LogsControllerTest
method request_log_line_serie (line 533) | defp request_log_line_serie(fun) do
method business_log_line_serie (line 541) | defp business_log_line_serie(fun) do
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/organization_controller_test.exs
class BorutaAdminWeb.OrganizationControllerTest (line 1) | defmodule BorutaAdminWeb.OrganizationControllerTest
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/page_controller_test.exs
class BorutaAdminWeb.PageControllerTest (line 1) | defmodule BorutaAdminWeb.PageControllerTest
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/role_controller_test.exs
class BorutaAdminWeb.RoleControllerTest (line 1) | defmodule BorutaAdminWeb.RoleControllerTest
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/scope_controller_test.exs
class BorutaAdminWeb.ScopeControllerTest (line 1) | defmodule BorutaAdminWeb.ScopeControllerTest
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/upstream_controller_test.exs
class BorutaAdminWeb.UpstreamControllerTest (line 1) | defmodule BorutaAdminWeb.UpstreamControllerTest
method fixture (line 19) | def fixture(:upstream) do
FILE: apps/boruta_admin/test/boruta_admin_web/controllers/user_controller_test.exs
class BorutaAdminWeb.UserControllerTest (line 1) | defmodule BorutaAdminWeb.UserControllerTest
FILE: apps/boruta_admin/test/boruta_admin_web/views/error_view_test.exs
class BorutaAdminWeb.ErrorViewTest (line 1) | defmodule BorutaAdminWeb.ErrorViewTest
FILE: apps/boruta_admin/test/boruta_admin_web/views/page_view_test.exs
class BorutaAdminWeb.PageViewTest (line 1) | defmodule BorutaAdminWeb.PageViewTest
FILE: apps/boruta_admin/test/support/boruta_factory.ex
class Boruta.Factory (line 1) | defmodule Boruta.Factory
method client_factory (line 8) | def client_factory do
method scope_factory (line 21) | def scope_factory do
method token_factory (line 28) | def token_factory do
FILE: apps/boruta_admin/test/support/boruta_identity_factory.ex
class BorutaIdentity.Factory (line 1) | defmodule BorutaIdentity.Factory
method user_factory (line 22) | def user_factory do
method internal_user_factory (line 30) | def internal_user_factory do
method consent_factory (line 38) | def consent_factory do
method client_identity_provider_factory (line 45) | def client_identity_provider_factory do
method identity_provider_factory (line 52) | def identity_provider_factory do
method backend_factory (line 59) | def backend_factory do
method default_backend_factory (line 66) | def default_backend_factory do
method template_factory (line 74) | def template_factory do
method error_template_factory (line 82) | def error_template_factory do
method email_template_factory (line 89) | def email_template_factory do
method reset_password_instructions_email_template_factory (line 97) | def reset_password_instructions_email_template_factory do
method role_factory (line 105) | def role_factory do
method role_scope_factory (line 111) | def role_scope_factory do
method organization_factory (line 115) | def organization_factory do
FILE: apps/boruta_admin/test/support/conn_case.ex
class BorutaAdminWeb.ConnCase (line 1) | defmodule BorutaAdminWeb.ConnCase
method merge_tags_params (line 60) | def merge_tags_params(conn, tags) do
method authorized_params (line 79) | def authorized_params(conn, scopes) do
method user_authorized_params (line 92) | def user_authorized_params(conn, scopes) do
FILE: apps/boruta_admin/test/support/data_case.ex
class BorutaAdmin.DataCase (line 1) | defmodule BorutaAdmin.DataCase
method errors_on (line 58) | def errors_on(changeset) do
FILE: apps/boruta_auth/lib/boruta_auth.ex
class BorutaAuth (line 1) | defmodule BorutaAuth
method hello (line 15) | def hello do
FILE: apps/boruta_auth/lib/boruta_auth/application.ex
class BorutaAuth.Application (line 1) | defmodule BorutaAuth.Application
method start (line 6) | def start(_type, _args) do
method setup_database (line 18) | def setup_database do
FILE: apps/boruta_auth/lib/boruta_auth/key_pairs.ex
class BorutaAuth.KeyPairs (line 1) | defmodule BorutaAuth.KeyPairs
method list_key_pairs (line 11) | def list_key_pairs do
method get_key_pair! (line 15) | def get_key_pair!(id) do
method list_jwks (line 19) | def list_jwks do
method create_key_pair (line 24) | def create_key_pair(attrs \\ %{}) do
method update_key_pair (line 29) | def update_key_pair(key_pair, attrs \\ %{}) do
method delete_key_pair (line 34) | def delete_key_pair(%KeyPair{} = key_pair) do
method rotate (line 40) | def rotate(%KeyPair{private_key: private_key} = key_pair) do
method rsa_key (line 53) | defp rsa_key(%KeyPair{} = key_pair) do
FILE: apps/boruta_auth/lib/boruta_auth/key_pairs/schemas/key_pair.ex
class BorutaAuth.KeyPairs.KeyPair (line 1) | defmodule BorutaAuth.KeyPairs.KeyPair
method default! (line 26) | def default! do
method changeset (line 42) | def changeset(key_pair, attrs) do
method delete_changeset (line 50) | def delete_changeset(key_pair) do
method rotate_changeset (line 55) | def rotate_changeset(key_pair) do
method set_default (line 67) | defp set_default(%Ecto.Changeset{changes: %{is_default: true}} = chang...
method set_default (line 84) | defp set_default(changeset), do: changeset
method generate_key_pair (line 86) | defp generate_key_pair(changeset) do
method check_default (line 104) | defp check_default(changeset) do
FILE: apps/boruta_auth/lib/boruta_auth/log_rotate.ex
class BorutaAuth.LogRotate (line 1) | defmodule BorutaAuth.LogRotate
method rotate (line 4) | def rotate do
method path (line 26) | def path(application, type, date) do
method log_dates (line 30) | defp log_dates(start_date, end_date) do
FILE: apps/boruta_auth/lib/boruta_auth/repo.ex
class BorutaAuth.Repo (line 1) | defmodule BorutaAuth.Repo
FILE: apps/boruta_auth/lib/boruta_auth/scheduler.ex
class BorutaAuth.Scheduler (line 1) | defmodule BorutaAuth.Scheduler
FILE: apps/boruta_auth/mix.exs
class BorutaAuth.MixProject (line 1) | defmodule BorutaAuth.MixProject
method project (line 4) | def project do
method application (line 18) | def application do
method deps (line 25) | defp deps do
FILE: apps/boruta_auth/priv/repo/migrations/20201129024828_create_boruta.exs
class BorutaWeb.Repo.Migrations.CreateBoruta (line 1) | defmodule BorutaWeb.Repo.Migrations.CreateBoruta
method change (line 4) | def change do
FILE: apps/boruta_auth/priv/repo/migrations/20210114202055_usec_timestamps.exs
class Boruta.Repo.Migrations.UsecTimestamps (line 1) | defmodule Boruta.Repo.Migrations.UsecTimestamps
method change (line 4) | def change do
FILE: apps/boruta_auth/priv/repo/migrations/20210202095024_add_key_pair_to_clients.exs
class Boruta.Repo.Migrations.AddKeyPairToClients (line 1) | defmodule Boruta.Repo.Migrations.AddKeyPairToClients
method change (line 4) | def change do
FILE: apps/boruta_auth/priv/repo/migrations/20210301123331_add_label_to_scopes.exs
class Boruta.Repo.Migrations.AddLabelToScopes (line 1) | defmodule Boruta.Repo.Migrations.AddLabelToScopes
method change (line 4) | def change do
FILE: apps/boruta_auth/priv/repo/migrations/20210514211510_add_default_redirect_uris_to_clients.exs
class BorutaWeb.Repo.Migrations.AddDefaultRedirectUrisToClients (line 1) | defmodule BorutaWeb.Repo.Migrations.AddDefaultRedirectUrisToClients
method change (line 9) | def change do
FILE: apps/boruta_auth/priv/repo/migrations/20210919174149_openid_connect.exs
class BorutaWeb.Repo.Migrations.OpenidConnect (line 1) | defmodule BorutaWeb.Repo.Migrations.OpenidConnect
FILE: apps/boruta_auth/priv/repo/migrations/20210919174150_clients_refresh_tokens.exs
class BorutaWeb.Repo.Migrations.ClientsRefreshTokens (line 1) | defmodule BorutaWeb.Repo.Migrations.ClientsRefreshTokens
FILE: apps/boruta_auth/priv/repo/migrations/20211013161324_clients_public_revoke.exs
class BorutaWeb.Repo.Migrations.ClientsPublicRevoke (line 1) | defmodule BorutaWeb.Repo.Migrations.ClientsPublicRevoke
FILE: apps/boruta_auth/priv/repo/migrations/20220113221532_store_previous_token.exs
class BorutaWeb.Repo.Migrations.StorePreviousToken (line 1) | defmodule BorutaWeb.Repo.Migrations.StorePreviousToken
FILE: apps/boruta_auth/priv/repo/migrations/20220603211852_id_token_signature_alg_configuration.exs
class BorutaAuth.Repo.Migrations.IdTokenSignatureAlgConfiguration (line 1) | defmodule BorutaAuth.Repo.Migrations.IdTokenSignatureAlgConfiguration
FILE: apps/boruta_auth/priv/repo/migrations/20220625203958_confidential_clients.exs
class BorutaAuth.Repo.Migrations.ConfidentialClients (line 1) | defmodule BorutaAuth.Repo.Migrations.ConfidentialClients
FILE: apps/boruta_auth/priv/repo/migrations/20220824105115_refresh_token_rotation.exs
class BorutaAuth.Repo.Migrations.RefreshTokenRotation (line 1) | defmodule BorutaAuth.Repo.Migrations.RefreshTokenRotation
FILE: apps/boruta_auth/priv/repo/migrations/20221025084535_authorization_code_chains.exs
class BorutaAuth.Repo.Migrations.AuthorizationCodeChains (line 1) | defmodule BorutaAuth.Repo.Migrations.AuthorizationCodeChains
FILE: apps/boruta_auth/priv/repo/migrations/20221122131429_client_authentication_methods.exs
class BorutaAuth.Repo.Migrations.ClientAuthenticationMethods (line 1) | defmodule BorutaAuth.Repo.Migrations.ClientAuthenticationMethods
FILE: apps/boruta_auth/priv/repo/migrations/20221129120152_signed_userinfo_response.exs
class BorutaAuth.Repo.Migrations.SignedUserinfoResponse (line 1) | defmodule BorutaAuth.Repo.Migrations.SignedUserinfoResponse
FILE: apps/boruta_auth/priv/repo/migrations/20230506151359_optional_public_key_for_oauth_clients.exs
class BorutaAuth.Repo.Migrations.OptionalPublicKeyForOauthClients (line 1) | defmodule BorutaAuth.Repo.Migrations.OptionalPublicKeyForOauthClients
FILE: apps/boruta_auth/priv/repo/migrations/20230514134306_clients_jwks_uri.exs
class BorutaAuth.Repo.Migrations.ClientsJwksUri (line 1) | defmodule BorutaAuth.Repo.Migrations.ClientsJwksUri
FILE: apps/boruta_auth/priv/repo/migrations/20230515093131_create_key_pairs.exs
class BorutaAuth.Repo.Migrations.CreateKeyPairs (line 1) | defmodule BorutaAuth.Repo.Migrations.CreateKeyPairs
method change (line 4) | def change do
FILE: apps/boruta_auth/priv/repo/migrations/20230515152140_client_id_token_kid.exs
class BorutaAuth.Repo.Migrations.ClientIdTokenKid (line 1) | defmodule BorutaAuth.Repo.Migrations.ClientIdTokenKid
FILE: apps/boruta_auth/priv/repo/migrations/20231217091349_add_metadata_to_clients.exs
class BorutaAuth.Repo.Migrations.AddMetadataToClients (line 1) | defmodule BorutaAuth.Repo.Migrations.AddMetadataToClients
FILE: apps/boruta_auth/priv/repo/migrations/20231217144905_oid4vci_implementation.exs
class BorutaAuth.Repo.Migrations.Oid4vciImplementation (line 1) | defmodule BorutaAuth.Repo.Migrations.Oid4vciImplementation
FILE: apps/boruta_auth/priv/repo/migrations/20240127081327_siopv2_implementation.exs
class BorutaAuth.Repo.Migrations.Siopv2Implementation (line 1) | defmodule BorutaAuth.Repo.Migrations.Siopv2Implementation
FILE: apps/boruta_auth/priv/repo/migrations/20240321101558_dpop_implementation.exs
class BorutaAuth.Repo.Migrations.DpopImplementation (line 1) | defmodule BorutaAuth.Repo.Migrations.DpopImplementation
FILE: apps/boruta_auth/priv/repo/migrations/20240417052138_par_implementation.exs
class BorutaAuth.Repo.Migrations.ParImplementation (line 1) | defmodule BorutaAuth.Repo.Migrations.ParImplementation
FILE: apps/boruta_auth/priv/repo/migrations/20240506083712_c_nonce_implementation.exs
class BorutaAuth.Repo.Migrations.CNonceImplementation (line 1) | defmodule BorutaAuth.Repo.Migrations.CNonceImplementation
FILE: apps/boruta_auth/priv/repo/migrations/20240812111902_defered_credentials.exs
class BorutaAuth.Repo.Migrations.DeferedCredentials (line 1) | defmodule BorutaAuth.Repo.Migrations.DeferedCredentials
FILE: apps/boruta_auth/priv/repo/migrations/20240824191208_clients_did.exs
class BorutaAuth.Repo.Migrations.ClientsDid (line 1) | defmodule BorutaAuth.Repo.Migrations.ClientsDid
FILE: apps/boruta_auth/priv/repo/migrations/20240908082918_verifiable_presentation_definitions.exs
class BorutaAuth.Repo.Migrations.VerifiablePresentationDefinitions (line 1) | defmodule BorutaAuth.Repo.Migrations.VerifiablePresentationDefinitions
FILE: apps/boruta_auth/priv/repo/migrations/20240914084657_clients_response_mode.exs
class BorutaAuth.Repo.Migrations.ClientsResponseMode (line 1) | defmodule BorutaAuth.Repo.Migrations.ClientsResponseMode
FILE: apps/boruta_auth/priv/repo/migrations/20241021132955_clients_key_pair_types.exs
class BorutaAuth.Repo.Migrations.ClientsKeyPairTypes (line 1) | defmodule BorutaAuth.Repo.Migrations.ClientsKeyPairTypes
FILE: apps/boruta_auth/priv/repo/migrations/20241209110846_tokens_tx_code.exs
class BorutaAuth.Repo.Migrations.TokensTxCode (line 1) | defmodule BorutaAuth.Repo.Migrations.TokensTxCode
FILE: apps/boruta_auth/priv/repo/migrations/20241220104923_clients_signatures_adapters.exs
class BorutaAuth.Repo.Migrations.ClientsSignaturesAdapters (line 1) | defmodule BorutaAuth.Repo.Migrations.ClientsSignaturesAdapters
FILE: apps/boruta_auth/priv/repo/migrations/20250315084213_fix_oauth_clients_did.exs
class BorutaAuth.Repo.Migrations.FixOauthClientsDid (line 1) | defmodule BorutaAuth.Repo.Migrations.FixOauthClientsDid
FILE: apps/boruta_auth/priv/repo/migrations/20250413070457_agent_credentials.exs
class BorutaAuth.Repo.Migrations.AgentCredentials (line 1) | defmodule BorutaAuth.Repo.Migrations.AgentCredentials
FILE: apps/boruta_auth/priv/repo/migrations/20250524160749_public_client_id.exs
class BorutaAuth.Repo.Migrations.PublicClientId (line 1) | defmodule BorutaAuth.Repo.Migrations.PublicClientId
FILE: apps/boruta_auth/priv/repo/migrations/20260324152715_codes_response_type.exs
class BorutaAuth.Repo.Migrations.CodesResponseType (line 1) | defmodule BorutaAuth.Repo.Migrations.CodesResponseType
FILE: apps/boruta_auth/priv/repo/migrations/20260324152716_code_metadata_policy.exs
class BorutaAuth.Repo.Migrations.CodeMetadataPolicy (line 1) | defmodule BorutaAuth.Repo.Migrations.CodeMetadataPolicy
FILE: apps/boruta_auth/priv/repo/migrations/20260330112657_siopv2_encryption.exs
class BorutaAuth.Repo.Migrations.Siopv2Encryption (line 1) | defmodule BorutaAuth.Repo.Migrations.Siopv2Encryption
FILE: apps/boruta_auth/priv/repo/migrations/20260428121802_requested_scope.exs
class BorutaAuth.Repo.Migrations.RequestedScope (line 1) | defmodule BorutaAuth.Repo.Migrations.RequestedScope
FILE: apps/boruta_auth/test/boruta_auth/key_pairs_test.exs
class BorutaAuth.KeyPairsTest (line 1) | defmodule BorutaAuth.KeyPairsTest
FILE: apps/boruta_gateway/lib/boruta_gateway.ex
class BorutaGateway (line 1) | defmodule BorutaGateway
FILE: apps/boruta_gateway/lib/boruta_gateway/application.ex
class BorutaGateway.Application (line 1) | defmodule BorutaGateway.Application
method start (line 12) | def start(_type, _args) do
method setup_database (line 72) | def setup_database do
FILE: apps/boruta_gateway/lib/boruta_gateway/configuration_loader.ex
class BorutaGateway.ConfigurationLoader (line 1) | defmodule BorutaGateway.ConfigurationLoader
method node_name (line 8) | def node_name do
method from_file! (line 33) | def from_file!(path) do
method load_configuration! (line 39) | defp load_configuration!(%{"gateway" => gateway_configurations} = conf...
method load_configuration! (line 56) | defp load_configuration!(%{"microgateway" => microgateway_configuratio...
method load_configuration! (line 83) | defp load_configuration!(%{}), do: :ok
FILE: apps/boruta_gateway/lib/boruta_gateway/configuration_schemas/gateway.ex
class BorutaGateway.ConfigurationSchemas.GatewaySchema (line 1) | defmodule BorutaGateway.ConfigurationSchemas.GatewaySchema
method gateway (line 6) | def gateway do
method microgateway (line 51) | def microgateway do
FILE: apps/boruta_gateway/lib/boruta_gateway/gateway_pipeline.ex
class BorutaGateway.GatewayPipeline (line 1) | defmodule BorutaGateway.GatewayPipeline
FILE: apps/boruta_gateway/lib/boruta_gateway/logger.ex
class BorutaGateway.Logger (line 1) | defmodule BorutaGateway.Logger
method start (line 6) | def start do
method boruta_gateway_server_handler (line 25) | def boruta_gateway_server_handler(_, %{duration: duration}, %{conn: co...
method boruta_gateway_request_handler (line 56) | def boruta_gateway_request_handler(
method business_status (line 98) | defp business_status(conn) do
method put_access_token (line 105) | defp put_access_token(log_line, conn) do
method put_upstream_attributes (line 118) | defp put_upstream_attributes(log_line, conn, request_time) do
method put_upstream_error (line 140) | defp put_upstream_error(log_line, conn) do
method log_attribute (line 150) | defp log_attribute(_key, nil), do: ""
method log_attribute (line 151) | defp log_attribute(key, attribute), do: " #{key}=#{attribute}"
method log_level (line 154) | defp log_level(nil, _conn), do: :info
method connection_type (line 161) | defp connection_type(:set_chunked), do: "chunked"
method connection_type (line 162) | defp connection_type(_), do: "sent"
method duration (line 164) | defp duration(nil), do: ["0", "µs"]
method duration (line 166) | defp duration(duration) do
FILE: apps/boruta_gateway/lib/boruta_gateway/microgateway_pipeline.ex
class BorutaGateway.MicrogatewayPipeline (line 1) | defmodule BorutaGateway.MicrogatewayPipeline
FILE: apps/boruta_gateway/lib/boruta_gateway/plugs/assign_sidecar_upstream.ex
class BorutaGateway.Plug.AssignSidecarUpstream (line 1) | defmodule BorutaGateway.Plug.AssignSidecarUpstream
method init (line 12) | def init(options), do: options
method call (line 14) | def call(
FILE: apps/boruta_gateway/lib/boruta_gateway/plugs/assign_upstream.ex
class BorutaGateway.Plug.AssignUpstream (line 1) | defmodule BorutaGateway.Plug.AssignUpstream
method init (line 11) | def init(options), do: options
method call (line 13) | def call(
FILE: apps/boruta_gateway/lib/boruta_gateway/plugs/authorize.ex
class BorutaGateway.Plug.Authorize (line 1) | defmodule BorutaGateway.Plug.Authorize
method init (line 21) | def init(options), do: options
method call (line 23) | def call(
method call (line 55) | def call(
method validate_scopes (line 68) | defp validate_scopes(scope, required_scopes, method) do
FILE: apps/boruta_gateway/lib/boruta_gateway/plugs/handler.ex
class BorutaGateway.Plug.Handler (line 1) | defmodule BorutaGateway.Plug.Handler
method init (line 10) | def init(options), do: options
method call (line 12) | def call(
FILE: apps/boruta_gateway/lib/boruta_gateway/plugs/metrics.ex
class BorutaGateway.Plug.Metrics (line 1) | defmodule BorutaGateway.Plug.Metrics
method init (line 8) | def init(_options), do: []
method call (line 10) | def call(
FILE: apps/boruta_gateway/lib/boruta_gateway/release.ex
class BorutaGateway.Release (line 1) | defmodule BorutaGateway.Release
method migrate (line 5) | def migrate do
method load_configuration (line 13) | def load_configuration do
method rollback (line 21) | def rollback(repo, version) do
method setup (line 27) | def setup do
method repos (line 31) | defp repos do
FILE: apps/boruta_gateway/lib/boruta_gateway/repo.ex
class BorutaGateway.Repo (line 1) | defmodule BorutaGateway.Repo
method listen (line 7) | def listen(event_name) do
FILE: apps/boruta_gateway/lib/boruta_gateway/router.ex
class BorutaGateway.Router (line 1) | defmodule BorutaGateway.Router
FILE: apps/boruta_gateway/lib/boruta_gateway/server.ex
class BorutaGateway.Server (line 1) | defmodule BorutaGateway.Server
method start_link (line 6) | def start_link(args) do
method init (line 11) | def init(args) do
FILE: apps/boruta_gateway/lib/boruta_gateway/sidecar_router.ex
class BorutaGateway.SidecarRouter (line 1) | defmodule BorutaGateway.SidecarRouter
FILE: apps/boruta_gateway/lib/boruta_gateway/upstreams.ex
class BorutaGateway.Upstreams (line 1) | defmodule BorutaGateway.Upstreams
method match (line 12) | def match(path) do
method sidecar_match (line 16) | def sidecar_match(path) do
method list_upstreams (line 29) | def list_upstreams do
method get_upstream! (line 49) | def get_upstream!(id), do: Repo.get!(Upstream, id)
method create_upstream (line 63) | def create_upstream(attrs \\ %{}) do
method update_upstream (line 81) | def update_upstream(%Upstream{} = upstream, attrs) do
method delete_upstream (line 99) | def delete_upstream(%Upstream{} = upstream) do
method change_upstream (line 112) | def change_upstream(%Upstream{} = upstream) do
FILE: apps/boruta_gateway/lib/boruta_gateway/upstreams/client.ex
class BorutaGateway.Upstreams.Client (line 1) | defmodule BorutaGateway.Upstreams.Client
method child_spec (line 21) | def child_spec(upstream) do
method start_link (line 38) | def start_link(upstream) do
method init (line 43) | def init(upstream) do
method upstream (line 58) | def upstream(client) do
method http_client (line 62) | def http_client(client) do
method request (line 66) | def request(%Upstream{http_client: http_client} = upstream, conn) do
method handle_call (line 79) | def handle_call({:get, :upstream}, _from, %{upstream: upstream} = stat...
method handle_call (line 83) | def handle_call({:get, :http_client}, _from, %{http_client: http_clien...
method transform_method (line 87) | defp transform_method(%Plug.Conn{method: method}) do
method transform_headers (line 91) | defp transform_headers(
method signer (line 129) | def signer(
method signature_type (line 148) | defp signature_type(%Upstream{forwarded_token_signature_alg: signature...
method transform_body (line 156) | defp transform_body(conn) do
method transform_url (line 163) | defp transform_url(
class Token (line 13) | defmodule Token
method token_config (line 18) | def token_config, do: %{}
FILE: apps/boruta_gateway/lib/boruta_gateway/upstreams/client/supervisor.ex
class BorutaGateway.Upstreams.ClientSupervisor (line 1) | defmodule BorutaGateway.Upstreams.ClientSupervisor
method start_link (line 9) | def start_link(_init_arg) do
method init (line 14) | def init([]) do
method start_child (line 21) | def start_child(upstream) do
method client_for_upstream (line 26) | def client_for_upstream(upstream) do
method kill (line 38) | def kill(nil), do: {:error, :not_started}
method kill (line 39) | def kill(client) do
FILE: apps/boruta_gateway/lib/boruta_gateway/upstreams/store.ex
class BorutaGateway.Upstreams.Store (line 1) | defmodule BorutaGateway.Upstreams.Store
method start_link (line 13) | def start_link do
method init (line 18) | def init(_args) do
method terminate (line 25) | def terminate(reason, state) do
method hydrate (line 37) | def hydrate do
method subscribe (line 41) | def subscribe do
method match (line 46) | def match(path_info) do
method sidecar_match (line 51) | def sidecar_match(path_info) do
method all (line 55) | def all do
method handle_call (line 60) | def handle_call(:all, _from, %{upstreams: upstreams} = state) do
method handle_call (line 64) | def handle_call({:match, path_info}, _from, %{upstreams: upstreams} = ...
method handle_call (line 78) | def handle_call({:sidecar_match, path_info}, _from, %{upstreams: upstr...
method handle_cast (line 95) | def handle_cast(:hydrate, state) do
method handle_cast (line 111) | def handle_cast(:subscribe, state) do
method handle_info (line 119) | def handle_info(
method update_upstreams (line 132) | defp update_upstreams(upstreams, %{"operation" => "INSERT", "record" =...
method update_upstreams (line 146) | defp update_upstreams(upstreams, %{"operation" => "UPDATE", "record" =...
method update_upstreams (line 167) | defp update_upstreams(upstreams, %{"operation" => "DELETE", "record" =...
method structure (line 182) | defp structure(upstreams) do
FILE: apps/boruta_gateway/lib/boruta_gateway/upstreams/upstream.ex
class BorutaGateway.Upstreams.Upstream (line 1) | defmodule BorutaGateway.Upstreams.Upstream
method with_http_client (line 72) | def with_http_client(%__MODULE__{http_client: nil} = upstream) do
method changeset (line 100) | def changeset(upstream, attrs) do
method validate_uris (line 131) | defp validate_uris(
method validate_uris (line 142) | defp validate_uris(changeset), do: changeset
method validate_required_scopes_format (line 144) | defp validate_required_scopes_format(
method validate_required_scopes_format (line 160) | defp validate_required_scopes_format(changeset), do: changeset
method maybe_put_forwarded_token_secret (line 162) | defp maybe_put_forwarded_token_secret(%Ecto.Changeset{data: data, chan...
method maybe_generate_key_pair (line 189) | defp maybe_generate_key_pair(changeset) do
FILE: apps/boruta_gateway/lib/mix/tasks/server.ex
class Mix.Tasks.BorutaGateway.Server (line 1) | defmodule Mix.Tasks.BorutaGateway.Server
method run (line 6) | def run(_args) do
FILE: apps/boruta_gateway/mix.exs
class BorutaGateway.MixProject (line 1) | defmodule BorutaGateway.MixProject
method project (line 4) | def project do
method application (line 23) | def application do
method elixirc_paths (line 31) | defp elixirc_paths(:test), do: ["lib", "test/support"]
method elixirc_paths (line 32) | defp elixirc_paths(_), do: ["lib"]
method deps (line 37) | defp deps do
method aliases (line 58) | defp aliases do
FILE: apps/boruta_gateway/priv/repo/migrations/20200219201345_create_upstreams.exs
class Boruta.Repo.Migrations.CreateUpstreams (line 1) | defmodule Boruta.Repo.Migrations.CreateUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20200326185929_upstreams_notify.exs
class Boruta.Repo.Migrations.UpstreamsNotify (line 1) | defmodule Boruta.Repo.Migrations.UpstreamsNotify
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20210111144958_change_upstreams_required_scopes_type.exs
class BorutaGateway.Repo.Migrations.ChangeUpstreamsRequiredScopesType (line 1) | defmodule BorutaGateway.Repo.Migrations.ChangeUpstreamsRequiredScopesType
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20220319220305_add_pool_size_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddPoolSizeToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddPoolSizeToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20220728122802_add_max_idle_time_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddMaxIdleTimeToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddMaxIdleTimeToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20220729040405_add_pool_count_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddPoolCountToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddPoolCountToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20220810082956_add_forbidden_response_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddForbiddenResponseToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddForbiddenResponseToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20220810084238_add_error_content_type_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddErrorContentTypeToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddErrorContentTypeToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20220810084450_add_unauthorized_response_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddUnauthorizedResponseToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddUnauthorizedResponseToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20221024100810_add_forwarded_token_signature_algorithm_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddForwardedTokenSignatureAlgorithmToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddForwardedTokenSignatureAlgori...
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20221024122642_add_forwarded_token_secret_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddForwardedTokenSecretToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddForwardedTokenSecretToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20221024132312_add_forwarded_token_key_pair_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddForwardedTokenKeyPairToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddForwardedTokenKeyPairToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20230413190522_upstreams_unique_indices.exs
class BorutaGateway.Repo.Migrations.UpstreamsUniqueIndices (line 1) | defmodule BorutaGateway.Repo.Migrations.UpstreamsUniqueIndices
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20230421135202_add_node_name_to_upstreams.exs
class BorutaGateway.Repo.Migrations.AddNodeNameToUpstreams (line 1) | defmodule BorutaGateway.Repo.Migrations.AddNodeNameToUpstreams
method change (line 4) | def change do
FILE: apps/boruta_gateway/priv/repo/migrations/20230422083455_update_upstreams_unique_constraint.exs
class BorutaGateway.Repo.Migrations.UpdateUpstreamsUniqueConstraint (line 1) | defmodule BorutaGateway.Repo.Migrations.UpdateUpstreamsUniqueConstraint
method change (line 4) | def change do
FILE: apps/boruta_gateway/test/boruta_gateway/configuration_loader_test.exs
class BorutaGateway.ConfigurationLoaderTest (line 1) | defmodule BorutaGateway.ConfigurationLoaderTest
FILE: apps/boruta_gateway/test/boruta_gateway/integration/requests_test.exs
class BorutaGateway.RequestsIntegrationTest (line 1) | defmodule BorutaGateway.RequestsIntegrationTest
FILE: apps/boruta_gateway/test/boruta_gateway/upstreams/client_test.exs
class BorutaGateway.Upstreams.ClientTest (line 1) | defmodule BorutaGateway.Upstreams.ClientTest
FILE: apps/boruta_gateway/test/boruta_gateway/upstreams/store_test.exs
class BorutaGateway.Upstreams.StoreTest (line 1) | defmodule BorutaGateway.Upstreams.StoreTest
FILE: apps/boruta_gateway/test/boruta_gateway/upstreams_test.exs
class BorutaGateway.UpstreamsTest (line 1) | defmodule BorutaGateway.UpstreamsTest
FILE: apps/boruta_gateway/test/support/data_case.ex
class BorutaGateway.DataCase (line 1) | defmodule BorutaGateway.DataCase
method errors_on (line 52) | def errors_on(changeset) do
FILE: apps/boruta_identity/assets/wallet/src/registerServiceWorker.ts
method ready (line 6) | ready () {
method registered (line 12) | registered () {
method cached (line 15) | cached () {
method updatefound (line 18) | updatefound () {
method updated (line 21) | updated () {
method offline (line 24) | offline () {
method error (line 27) | error (error) {
FILE: apps/boruta_identity/assets/wallet/src/store/index.ts
method credentials (line 13) | credentials ({ credentials }) {
method refreshCredentials (line 18) | async refreshCredentials(state) {
method deleteCredential (line 21) | deleteCredential(state, credential) {
FILE: apps/boruta_identity/lib/boruta_identity.ex
class BorutaIdentity (line 1) | defmodule BorutaIdentity
FILE: apps/boruta_identity/lib/boruta_identity/accounts.ex
class BorutaIdentity.Accounts (line 83) | defmodule BorutaIdentity.Accounts
class BorutaIdentity.Accounts.Utils (line 1) | defmodule BorutaIdentity.Accounts.Utils
method client_identity_provider (line 9) | def client_identity_provider(nil), do: {:error, "Client identifier n...
method client_identity_provider (line 11) | def client_identity_provider(client_id) do
class BorutaIdentity.Accounts.IdentityProviderError (line 66) | defmodule BorutaIdentity.Accounts.IdentityProviderError
method message (line 78) | def message(exception) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/backends/federated.ex
class BorutaIdentity.Accounts.Federated (line 1) | defmodule BorutaIdentity.Accounts.Federated
method features (line 14) | def features, do: @features
method account_type (line 18) | def account_type, do: @account_type
method domain_user! (line 21) | def domain_user!(federated_server_name, access_token, backend) do
method delete_user (line 78) | def delete_user(_uid), do: :ok
method get_resource! (line 80) | defp get_resource!(url, access_token) do
method claims_from_response (line 97) | defp claims_from_response(endpoint, body) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/backends/internal.ex
class BorutaIdentity.Accounts.Internal (line 1) | defmodule BorutaIdentity.Accounts.Internal
method features (line 32) | def features, do: @features
method account_type (line 36) | def account_type, do: @account_type
method register (line 39) | def register(backend, registration_params) do
method get_user (line 66) | def get_user(_authentication_params), do: {:error, "Cannot find an use...
method domain_user! (line 69) | def domain_user!(
method check_user_against (line 104) | def check_user_against(backend, user, authentication_params) do
method check_user_password (line 108) | defp check_user_password(backend, user, password) do
method reset_password (line 116) | def reset_password(backend, reset_password_params) do
method update_user (line 128) | def update_user(backend, user, params) do
method delete_user (line 142) | def delete_user(uid) do
method create_user (line 150) | def create_user(backend, params) do
method create_raw_user (line 174) | def create_raw_user(backend, params) do
method get_user_by_reset_password_token (line 190) | defp get_user_by_reset_password_token(token) do
method reset_user_password_multi (line 200) | defp reset_user_password_multi(backend, user, reset_password_params) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/backends/internal/user.ex
class BorutaIdentity.Accounts.Internal.User (line 1) | defmodule BorutaIdentity.Accounts.Internal.User
method registration_changeset (line 51) | def registration_changeset(user, attrs, %{backend: backend} = opts) do
method raw_registration_changeset (line 60) | def raw_registration_changeset(user, attrs, %{backend: backend}) do
method validate_email (line 68) | defp validate_email(changeset) do
method validate_password (line 75) | defp validate_password(changeset, opts) do
method maybe_hash_password (line 84) | defp maybe_hash_password(changeset, %{backend: backend} = opts) do
method update_changeset (line 103) | def update_changeset(user, attrs, opts) do
method password_changeset (line 123) | def password_changeset(user, attrs, opts) do
method valid_password? (line 141) | def valid_password?(backend, _, _) do
method validate_current_password (line 155) | def validate_current_password(backend, changeset, password) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/backends/ldap.ex
class BorutaIdentity.Accounts.LdapError (line 1) | defmodule BorutaIdentity.Accounts.LdapError
method message (line 13) | def message(exception) do
class BorutaIdentity.Accounts.Ldap (line 18) | defmodule BorutaIdentity.Accounts.Ldap
method account_type (line 48) | def account_type, do: "ldap"
method features (line 52) | def features, do: @features
method get_user (line 55) | def get_user(backend, %{email: email}) do
method domain_user! (line 69) | def domain_user!(
method check_user_against (line 99) | def check_user_against(backend, ldap_user, authentication_params) do
method update_user (line 119) | def update_user(backend, user, params) do
method delete_user (line 141) | def delete_user(_id) do
method reset_password (line 146) | def reset_password(backend, reset_password_params) do
method create_user (line 170) | def create_user(_backend, _params) do
method create_raw_user (line 175) | def create_raw_user(_backend, _params) do
method pool_name (line 180) | def pool_name(backend) do
method start_link (line 199) | def start_link(backend) do
method init_worker (line 208) | def init_worker(%{backend: backend}) do
method handle_checkout (line 216) | def handle_checkout(:checkout, _from, ldap, pool_state) do
method handle_checkin (line 221) | def handle_checkin(ldap, _from, ldap, pool_state) do
method terminate_worker (line 226) | def terminate_worker(_reason, ldap, pool_state) do
method fetch_user_from_ldap (line 235) | defp fetch_user_from_ldap(ldap, backend, email) do
method update_user_in_ldap (line 267) | defp update_user_in_ldap(
method update_user_in_ldap (line 303) | defp update_user_in_ldap(_ldap, _backend, user, _params), do: {:ok, user}
method get_user_by_reset_password_token (line 305) | defp get_user_by_reset_password_token(ldap, backend, token) do
method reset_password_in_ldap (line 332) | defp reset_password_in_ldap(_ldap, _backend, _user, _reset_password_pa...
method check_password_confirmation (line 343) | defp check_password_confirmation(_reset_password_params),
method lazy_start (line 346) | defp lazy_start(backend) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/backends/ldap/user.ex
class BorutaIdentity.Accounts.Ldap.User (line 1) | defmodule BorutaIdentity.Accounts.Ldap.User
FILE: apps/boruta_identity/lib/boruta_identity/accounts/choose_sessions.ex
class BorutaIdentity.Accounts.ChooseSessionApplication (line 1) | defmodule BorutaIdentity.Accounts.ChooseSessionApplication
class BorutaIdentity.Accounts.ChooseSessions (line 14) | defmodule BorutaIdentity.Accounts.ChooseSessions
method new_choose_session_template (line 32) | defp new_choose_session_template(identity_provider) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/confirmations.ex
class BorutaIdentity.Accounts.ConfirmationError (line 1) | defmodule BorutaIdentity.Accounts.ConfirmationError
method message (line 13) | def message(exception) do
class BorutaIdentity.Accounts.ConfirmationApplication (line 18) | defmodule BorutaIdentity.Accounts.ConfirmationApplication
class BorutaIdentity.Accounts.Confirmations (line 41) | defmodule BorutaIdentity.Accounts.Confirmations
method confirm_user (line 104) | def confirm_user(context, _client_id, token, module) do
method new_confirmation_instructions_template (line 116) | defp new_confirmation_instructions_template(identity_provider) do
method confirm_user (line 123) | defp confirm_user(token) do
method confirm_user_multi (line 134) | defp confirm_user_multi(user) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/consents.ex
class BorutaIdentity.Accounts.ConsentApplication (line 1) | defmodule BorutaIdentity.Accounts.ConsentApplication
class BorutaIdentity.Accounts.Consents (line 20) | defmodule BorutaIdentity.Accounts.Consents
method consented? (line 88) | def consented?(%User{}, _client_id, []), do: true
method consented? (line 90) | def consented?(%User{id: user_id}, client_id, scopes) do
method consented? (line 97) | def consented?(_, _, _), do: false
method new_consent_template (line 99) | defp new_consent_template(identity_provider) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/deliveries.ex
class BorutaIdentity.Accounts.Deliveries (line 1) | defmodule BorutaIdentity.Accounts.Deliveries
method deliver_user_reset_password_instructions (line 44) | def deliver_user_reset_password_instructions(backend, %User{} = user, ...
method deliver_tx_code (line 60) | def deliver_tx_code(backend, %User{} = user, tx_code) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/deliveries/email_template.ex
class BorutaIdentity.Accounts.EmailTemplate (line 1) | defmodule BorutaIdentity.Accounts.EmailTemplate
method template_types (line 68) | def template_types, do: @template_types
method default_template (line 86) | def default_template(_type), do: nil
method changeset (line 89) | def changeset(template, attrs) do
method assoc_changeset (line 100) | def assoc_changeset(template, attrs) do
method put_default_txt (line 109) | defp put_default_txt(changeset) do
method put_default_html (line 122) | defp put_default_html(changeset) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/deliveries/user_notifier.ex
class BorutaIdentity.Accounts.UserNotifier (line 1) | defmodule BorutaIdentity.Accounts.UserNotifier
method smtp_adapter (line 11) | def smtp_adapter do
method deliver (line 18) | def deliver(email, backend) do
method deliver_confirmation_instructions (line 57) | def deliver_confirmation_instructions(backend, user, url) do
method deliver_reset_password_instructions (line 84) | def deliver_reset_password_instructions(backend, user, url) do
method deliver_tx_code (line 108) | def deliver_tx_code(backend, user, tx_code) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/registrations.ex
class BorutaIdentity.Accounts.RegistrationError (line 1) | defmodule BorutaIdentity.Accounts.RegistrationError
method message (line 16) | def message(exception) do
class BorutaIdentity.Accounts.RegistrationApplication (line 21) | defmodule BorutaIdentity.Accounts.RegistrationApplication
class BorutaIdentity.Accounts.Registrations (line 44) | defmodule BorutaIdentity.Accounts.Registrations
method create_user (line 138) | defp create_user(client_idp, registration_params) do
method maybe_deliver_confirmation_email (line 144) | defp maybe_deliver_confirmation_email(_backend, _user, _confirmation_u...
method maybe_deliver_confirmation_email (line 150) | defp maybe_deliver_confirmation_email(backend, user, confirmation_url_...
method maybe_create_session (line 163) | defp maybe_create_session(user, %IdentityProvider{confirmable: true}) do
method maybe_create_session (line 167) | defp maybe_create_session(user, %IdentityProvider{confirmable: false}) do
method new_registration_template (line 171) | defp new_registration_template(identity_provider) do
method new_confirmation_instructions_template (line 175) | defp new_confirmation_instructions_template(identity_provider) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/reset_passwords.ex
class BorutaIdentity.Accounts.ResetPasswordError (line 1) | defmodule BorutaIdentity.Accounts.ResetPasswordError
method message (line 16) | def message(exception) do
class BorutaIdentity.Accounts.ResetPasswordApplication (line 21) | defmodule BorutaIdentity.Accounts.ResetPasswordApplication
class BorutaIdentity.Accounts.ResetPasswords (line 51) | defmodule BorutaIdentity.Accounts.ResetPasswords
method send_reset_password_instructions (line 191) | defp send_reset_password_instructions(backend, user, reset_password_ur...
method reset_password_changeset (line 205) | defp reset_password_changeset(_backend, token) do
method get_user_by_reset_password_token (line 212) | defp get_user_by_reset_password_token(token) do
method new_reset_password_template (line 221) | defp new_reset_password_template(identity_provider) do
method edit_reset_password_template (line 225) | defp edit_reset_password_template(identity_provider) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/schemas/consent.ex
class BorutaIdentity.Accounts.Consent (line 1) | defmodule BorutaIdentity.Accounts.Consent
method changeset (line 30) | def changeset(consent, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/schemas/role.ex
class BorutaIdentity.Accounts.Role (line 1) | defmodule BorutaIdentity.Accounts.Role
method changeset (line 21) | def changeset(role, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/schemas/role_scope.ex
class BorutaIdentity.Accounts.RoleScope (line 1) | defmodule BorutaIdentity.Accounts.RoleScope
method changeset (line 17) | def changeset(role_scope, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/schemas/user.ex
class BorutaIdentity.Accounts.User (line 1) | defmodule BorutaIdentity.Accounts.User
method account_types (line 57) | def account_types, do: [
method implementation_changeset (line 94) | def implementation_changeset(attrs, backend) do
method changeset (line 112) | def changeset(user, attrs \\ %{}) do
method login_changeset (line 119) | def login_changeset(user) do
method confirm_changeset (line 125) | def confirm_changeset(user) do
method unconfirm_changeset (line 130) | def unconfirm_changeset(user) do
method webauthn_challenge_changeset (line 134) | def webauthn_challenge_changeset(user) do
method webauthn_public_key_changeset (line 138) | def webauthn_public_key_changeset(user, cose_key, identifier) do
method totp_changeset (line 146) | def totp_changeset(user, totp_secret) do
method consent_changeset (line 150) | def consent_changeset(user, attrs) do
method confirmed? (line 157) | def confirmed?(%__MODULE__{confirmed_at: nil}), do: false
method confirmed? (line 158) | def confirmed?(%__MODULE__{confirmed_at: _confirmed_at}), do: true
method metadata_filter (line 161) | def metadata_filter(metadata, %Backend{
method user_metadata_filter (line 175) | def user_metadata_filter(
method metadata_template_filter (line 223) | defp metadata_template_filter(changeset, _backend), do: changeset
method validate_group (line 225) | defp validate_group(changeset) do
method validate_metadata (line 247) | defp validate_metadata(
method validate_metadata (line 263) | defp validate_metadata(changeset), do: changeset
class CoseKey (line 4) | defmodule CoseKey
method type (line 9) | def type, do: :binary
method cast (line 10) | def cast(bin), do: {:ok, Base.decode64!(bin) |> :erlang.binary_to_term()}
method load (line 11) | def load(bin), do: {:ok, Base.decode64!(bin) |> :erlang.binary_to_term()}
method dump (line 12) | def dump(bin), do: {:ok, :erlang.term_to_binary(bin) |> Base.encode64()}
method equal? (line 13) | def equal?(a, b), do: a == b
method embed_as (line 14) | def embed_as(_a), do: :self
FILE: apps/boruta_identity/lib/boruta_identity/accounts/schemas/user_authorized_scope.ex
class BorutaIdentity.Accounts.UserAuthorizedScope (line 1) | defmodule BorutaIdentity.Accounts.UserAuthorizedScope
method changeset (line 26) | def changeset(scope, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/schemas/user_role.ex
class BorutaIdentity.Accounts.UserRole (line 1) | defmodule BorutaIdentity.Accounts.UserRole
method changeset (line 26) | def changeset(user_role, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/schemas/user_token.ex
class BorutaIdentity.Accounts.UserToken (line 1) | defmodule BorutaIdentity.Accounts.UserToken
method build_session_token (line 36) | def build_session_token(user) do
method verify_session_token_query (line 48) | def verify_session_token_query(token) do
method build_email_token (line 69) | def build_email_token(user, context) do
method build_hashed_token (line 73) | defp build_hashed_token(user, context, sent_to) do
method verify_email_token_query (line 91) | def verify_email_token_query(token, context) do
method revoke_email_token_query (line 113) | def revoke_email_token_query(token, context) do
method days_for_context (line 124) | defp days_for_context("confirm"), do: @confirm_validity_in_days
method days_for_context (line 125) | defp days_for_context("reset_password"), do: @reset_password_validity_...
method verify_confirm_email_token_query (line 132) | def verify_confirm_email_token_query(token, context) do
method token_and_context_query (line 151) | def token_and_context_query(token, context) do
method user_and_contexts_query (line 158) | def user_and_contexts_query(user, :all) do
method user_and_contexts_query (line 162) | def user_and_contexts_query(user, [_ | _] = contexts) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/sessions.ex
class BorutaIdentity.Accounts.SessionError (line 1) | defmodule BorutaIdentity.Accounts.SessionError
method message (line 15) | def message(exception) do
class BorutaIdentity.Accounts.SessionApplication (line 20) | defmodule BorutaIdentity.Accounts.SessionApplication
class BorutaIdentity.Accounts.Sessions (line 46) | defmodule BorutaIdentity.Accounts.Sessions
method get_user (line 126) | def get_user(%{email: email}, %IdentityProvider{check_password: false}...
method get_user (line 136) | def get_user(authentication_params, %IdentityProvider{check_password: ...
method maybe_check_password (line 142) | def maybe_check_password(user, _authentication_params, %IdentityProvid...
method maybe_check_password (line 144) | def maybe_check_password(user, authentication_params, %IdentityProvide...
method delete_session (line 163) | def delete_session(context, _client_id, session_token, module) do
method create_user_session (line 176) | def create_user_session(%User{} = user) do
method ensure_user_confirmed (line 184) | defp ensure_user_confirmed(_user, %IdentityProvider{confirmable: false...
method ensure_user_confirmed (line 186) | defp ensure_user_confirmed(user, %IdentityProvider{confirmable: true}) do
method new_session_template (line 193) | defp new_session_template(identity_provider) do
method new_confirmation_instructions_template (line 197) | defp new_confirmation_instructions_template(identity_provider) do
method delete_session (line 204) | def delete_session(nil), do: {:error, "Session not found."}
method delete_session (line 206) | def delete_session(session_token) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/settings.ex
class BorutaIdentity.Accounts.SettingsError (line 1) | defmodule BorutaIdentity.Accounts.SettingsError
method message (line 15) | def message(exception) do
class BorutaIdentity.Accounts.SettingsApplication (line 20) | defmodule BorutaIdentity.Accounts.SettingsApplication
class BorutaIdentity.Accounts.Settings (line 50) | defmodule BorutaIdentity.Accounts.Settings
method maybe_unconfirm_user (line 193) | defp maybe_unconfirm_user(old_user, user, %IdentityProvider{confirmabl...
method maybe_unconfirm_user (line 200) | defp maybe_unconfirm_user(_old_user, user, %IdentityProvider{confirmab...
method maybe_deliver_email_confirmation_instructions (line 204) | defp maybe_deliver_email_confirmation_instructions(
method maybe_deliver_email_confirmation_instructions (line 214) | defp maybe_deliver_email_confirmation_instructions(
method email_changed? (line 237) | defp email_changed?(%{email: email}, %User{username: email}), do: false
method email_changed? (line 238) | defp email_changed?(%{email: _email}, %User{username: nil}), do: false
method email_changed? (line 239) | defp email_changed?(_user, _user_update_params), do: true
method edit_user_template (line 241) | defp edit_user_template(identity_provider) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/users.ex
class BorutaIdentity.Accounts.Users (line 1) | defmodule BorutaIdentity.Accounts.Users
method get_user (line 49) | def get_user(_), do: nil
method get_user_by_session_token (line 55) | def get_user_by_session_token(token) do
method get_user_scopes (line 61) | def get_user_scopes(user_id) do
method get_user_roles (line 76) | def get_user_roles(user_id) do
method get_user_organizations (line 115) | def get_user_organizations(user_id) do
method put_user_webauthn_challenge (line 128) | def put_user_webauthn_challenge(user) do
FILE: apps/boruta_identity/lib/boruta_identity/accounts/verifiable_credentials.ex
class BorutaIdentity.Accounts.VerifiableCredentials (line 1) | defmodule BorutaIdentity.Accounts.VerifiableCredentials
method credentials (line 26) | def credentials do
method credentials_supported (line 33) | def credentials_supported do
method credential_configurations_supported (line 53) | def credential_configurations_supported do
method authorization_details (line 119) | def authorization_details(%User{backend: %Backend{} = backend}, scope) do
method authorization_details (line 148) | def authorization_details(_user, scope), do: default_authorization_det...
method default_authorization_details (line 150) | def default_authorization_details(scope) do
method public_credential_configuration (line 179) | def public_credential_configuration do
method credential_configuration (line 201) | def credential_configuration(%User{backend: %Backend{} = backend}) do
method credential_configuration (line 223) | def credential_configuration(_user), do: public_credential_configurati...
FILE: apps/boruta_identity/lib/boruta_identity/accounts/verifiable_presentations.ex
class BorutaIdentity.Accounts.VerifiablePresentations (line 1) | defmodule BorutaIdentity.Accounts.VerifiablePresentations
method presentation_configuration (line 7) | def presentation_configuration(%User{backend: %Backend{} = backend}) do
method presentation_configuration (line 17) | def presentation_configuration(_user) do
method public_presentation_configuration (line 21) | def public_presentation_configuration do
FILE: apps/boruta_identity/lib/boruta_identity/admin.ex
class BorutaIdentity.Admin (line 1) | defmodule BorutaIdentity.Admin
method list_users (line 50) | def list_users(params \\ %{}) do
method search_users (line 58) | def search_users(query, params \\ %{}) do
method get_user (line 80) | def get_user(id) do
method create_user (line 98) | def create_user(backend, params) do
method create_raw_user (line 115) | def create_raw_user(backend, params) do
method import_users (line 132) | def import_users(backend, csv_path, opts \\ %{}) do
method update_user_authorized_scopes (line 231) | def update_user_authorized_scopes(%User{id: user_id} = user, scopes) do
method update_user_roles (line 257) | def update_user_roles(%User{id: user_id} = user, roles) do
method update_user_organizations (line 283) | def update_user_organizations(%User{id: user_id} = user, organizations...
method update_user (line 309) | def update_user(user, user_params) do
method delete_user_authorized_scopes_by_id (line 348) | def delete_user_authorized_scopes_by_id(scope_id) do
method user_preloads (line 356) | defp user_preloads(%User{} = user) do
method user_preloads (line 360) | defp user_preloads(queryable) do
method list_roles (line 379) | def list_roles do
method get_role! (line 409) | def get_role!(id) do
method create_role (line 427) | def create_role(attrs \\ %{}) do
method update_role (line 436) | def update_role(%Role{} = role, attrs) do
method delete_role (line 445) | def delete_role(%Role{} = role) do
method change_role (line 449) | def change_role(%Role{} = role, attrs \\ %{}) do
FILE: apps/boruta_identity/lib/boruta_identity/application.ex
class BorutaIdentity.Application (line 1) | defmodule BorutaIdentity.Application
method start (line 8) | def start(_type, _args) do
method config_change (line 26) | def config_change(changed, _new, removed) do
method setup_database (line 31) | def setup_database do
FILE: apps/boruta_identity/lib/boruta_identity/clients.ex
class BorutaIdentity.Clients (line 1) | defmodule BorutaIdentity.Clients
method create_client (line 10) | def create_client(client_params) do
method insert_global_key_pair (line 29) | def insert_global_key_pair(%Client{} = client, nil), do: {:ok, client}
method insert_global_key_pair (line 30) | def insert_global_key_pair(%Client{} = client, key_pair_id) do
FILE: apps/boruta_identity/lib/boruta_identity/configuration.ex
class BorutaIdentity.Configuration (line 1) | defmodule BorutaIdentity.Configuration
method get_error_template! (line 9) | def get_error_template!(type) do
method upsert_error_template (line 16) | def upsert_error_template(%ErrorTemplate{id: template_id} = template, ...
method delete_error_template! (line 25) | def delete_error_template!(type) do
FILE: apps/boruta_identity/lib/boruta_identity/configuration/error_template.ex
class BorutaIdentity.Configuration.ErrorTemplate (line 1) | defmodule BorutaIdentity.Configuration.ErrorTemplate
method template_types (line 59) | def template_types, do: @template_types
method default_template (line 73) | def default_template(_type), do: nil
method changeset (line 76) | def changeset(template, attrs) do
method put_default (line 84) | defp put_default(changeset) do
FILE: apps/boruta_identity/lib/boruta_identity/federated_accounts.ex
class BorutaIdentity.Accounts.FederatedSessionApplication (line 1) | defmodule BorutaIdentity.Accounts.FederatedSessionApplication
class BorutaIdentity.FederatedAccounts (line 20) | defmodule BorutaIdentity.FederatedAccounts
method new_session_template (line 91) | defp new_session_template(identity_provider) do
FILE: apps/boruta_identity/lib/boruta_identity/hooks/post_user_creation_hook.ex
class BorutaIdentity.PostUserCreationHook (line 1) | defmodule BorutaIdentity.PostUserCreationHook
method post_user_creation_hook (line 11) | def post_user_creation_hook(_options, body, _context) do
method maybe_create_organization (line 22) | def maybe_create_organization(
method maybe_create_organization (line 38) | def maybe_create_organization(user), do: {:ok, user}
FILE: apps/boruta_identity/lib/boruta_identity/identity_providers.ex
class BorutaIdentity.IdentityProviders (line 1) | defmodule BorutaIdentity.IdentityProviders
method list_identity_providers (line 16) | def list_identity_providers do
method get_identity_provider! (line 25) | def get_identity_provider!(id) do
method create_identity_provider (line 41) | def create_identity_provider(attrs \\ %{}) do
method update_identity_provider (line 50) | def update_identity_provider(%IdentityProvider{} = identity_provider, ...
method delete_identity_provider (line 58) | def delete_identity_provider(%IdentityProvider{} = identity_provider) do
method change_identity_provider (line 66) | def change_identity_provider(%IdentityProvider{} = identity_provider, ...
method upsert_client_identity_provider (line 70) | def upsert_client_identity_provider(client_id, identity_provider_id) do
method clear_identity_provider_by_client_id_cache (line 84) | defp clear_identity_provider_by_client_id_cache do
method remove_client_identity_provider (line 98) | def remove_client_identity_provider(client_id) do
method get_identity_provider_by_client_id (line 118) | def get_identity_provider_by_client_id(client_id) do
method get_identity_provider_template! (line 142) | def get_identity_provider_template!(identity_provider_id, type) do
method upsert_template (line 160) | def upsert_template(%Template{id: template_id} = template, attrs) do
method delete_identity_provider_template! (line 175) | def delete_identity_provider_template!(identity_provider_id, type) do
method list_backends (line 203) | def list_backends do
method get_backend! (line 208) | def get_backend!(id) do
method create_backend (line 232) | def create_backend(attrs \\ %{}) do
method update_backend (line 241) | def update_backend(%Backend{} = backend, attrs) do
method update_backend_roles (line 263) | def update_backend_roles(%Backend{id: backend_id} = backend, roles) do
method get_backend_roles (line 293) | def get_backend_roles(backend_id) do
method delete_backend (line 320) | def delete_backend(%Backend{} = backend) do
method change_backend (line 348) | def change_backend(%Backend{} = backend, attrs \\ %{}) do
method get_backend_email_template! (line 352) | def get_backend_email_template!(backend_id, type) do
method upsert_email_template (line 368) | def upsert_email_template(%EmailTemplate{id: template_id} = template, ...
method delete_email_template! (line 390) | def delete_email_template!(backend_id, type) do
FILE: apps/boruta_identity/lib/boruta_identity/identity_providers/backend.ex
class BorutaIdentity.IdentityProviders.Backend (line 1) | defmodule BorutaIdentity.IdentityProviders.Backend
method account_implementations (line 78) | def account_implementations do
method backend_types (line 252) | def backend_types, do: @backend_types
method default! (line 301) | def default! do
method implementation (line 307) | def implementation(%__MODULE__{type: type}, account_type \\ nil) do
method features (line 317) | def features(backend) do
method password_hashing_module (line 322) | def password_hashing_module(%__MODULE__{password_hashing_alg: password...
method password_hashing_opts (line 327) | def password_hashing_opts(%__MODULE__{password_hashing_opts: password_...
method federated_login_url (line 358) | def federated_login_url(%__MODULE__{} = backend, federated_server_name...
method federated_oauth_client (line 376) | def federated_oauth_client(
method federated_server_scope (line 428) | def federated_server_scope(
method discover_federated_server_urls (line 443) | defp discover_federated_server_urls(
method federated_redirect_url (line 495) | def federated_redirect_url(%__MODULE__{id: backend_id}, federated_serv...
method changeset (line 517) | def changeset(backend, attrs) do
method delete_changeset (line 560) | def delete_changeset(%__MODULE__{id: backend_id} = backend) do
method validate_metadata_fields (line 579) | defp validate_metadata_fields(
method validate_metadata_fields (line 593) | defp validate_metadata_fields(changeset), do: changeset
method validate_federated_servers (line 595) | defp validate_federated_servers(
method validate_federated_servers (line 611) | defp validate_federated_servers(changeset), do: changeset
method validate_verifiable_credentials (line 613) | defp validate_verifiable_credentials(
method validate_verifiable_credentials (line 629) | defp validate_verifiable_credentials(changeset), do: changeset
method validate_verifiable_presentations (line 631) | defp validate_verifiable_presentations(
method validate_verifiable_presentations (line 652) | defp validate_verifiable_presentations(changeset), do: changeset
method set_default (line 654) | defp set_default(%Ecto.Changeset{changes: %{is_default: false}} = chan...
method set_default (line 662) | defp set_default(%Ecto.Changeset{changes: %{is_default: _is_default}} ...
method set_default (line 681) | defp set_default(changeset), do: changeset
method validate_backend_by_type (line 683) | defp validate_backend_by_type(changeset) do
method validate_backend (line 689) | defp validate_backend(changeset, Internal) do
method validate_backend (line 695) | defp validate_backend(changeset, Ldap) do
method validate_backend (line 706) | defp validate_backend(changeset, _implementation), do: changeset
method validate_password_hashing_opts (line 708) | defp validate_password_hashing_opts(changeset) do
class AuthCodeStrategy (line 4) | defmodule AuthCodeStrategy
method authorize_url (line 10) | def authorize_url(client, params) do
method get_token (line 19) | def get_token(client, params, headers) do
FILE: apps/boruta_identity/lib/boruta_identity/identity_providers/backend_role.ex
class BorutaIdentity.IdentityProviders.BackendRole (line 1) | defmodule BorutaIdentity.IdentityProviders.BackendRole
method changeset (line 26) | def changeset(role_scope, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/identity_providers/client_identity_provider.ex
class BorutaIdentity.IdentityProviders.ClientIdentityProvider (line 1) | defmodule BorutaIdentity.IdentityProviders.ClientIdentityProvider
method changeset (line 28) | def changeset(client_identity_provider, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/identity_providers/identity_provider.ex
class BorutaIdentity.IdentityProviders.IdentityProvider (line 1) | defmodule BorutaIdentity.IdentityProviders.IdentityProvider
method implementation (line 154) | def implementation(%__MODULE__{backend: backend}) do
method check_feature (line 160) | def check_feature(identity_provider, requested_action_name) do
method changeset (line 178) | def changeset(identity_provider, attrs) do
method delete_changeset (line 204) | def delete_changeset(identity_provider) do
FILE: apps/boruta_identity/lib/boruta_identity/identity_providers/template.ex
class BorutaIdentity.IdentityProviders.Template (line 1) | defmodule BorutaIdentity.IdentityProviders.Template
method template_types (line 130) | def template_types, do: @template_types
method default_template (line 144) | def default_template(_type), do: nil
method changeset (line 147) | def changeset(template, attrs) do
method assoc_changeset (line 157) | def assoc_changeset(template, attrs) do
method put_default (line 165) | defp put_default(changeset) do
FILE: apps/boruta_identity/lib/boruta_identity/ldap_repo.ex
class BorutaIdentity.LdapRepo (line 1) | defmodule BorutaIdentity.LdapRepo
method open (line 40) | def open(host, opts \\ []), do: impl().open(host, opts)
method close (line 42) | def close(handle), do: impl().close(handle)
method simple_bind (line 44) | def simple_bind(handle, dn, password), do: impl().simple_bind(handle, ...
method search (line 46) | def search(handle, backend, username), do: impl().search(handle, backe...
method modify (line 48) | def modify(handle, backend, user, username), do: impl().modify(handle,...
method modify_password (line 50) | def modify_password(handle, user, new_password, old_password),
method modify_password (line 53) | def modify_password(handle, user, new_password),
method impl (line 56) | defp impl do
class BorutaIdentity.LdapAdapter (line 67) | defmodule BorutaIdentity.LdapAdapter
method open (line 75) | def open(host, opts \\ []) do
method close (line 80) | def close(handle) do
method simple_bind (line 85) | def simple_bind(handle, dn, password) do
method search (line 92) | def search(handle, backend, username) do
method modify (line 126) | def modify(handle, backend, %Ldap.User{dn: dn}, username) do
FILE: apps/boruta_identity/lib/boruta_identity/logger.ex
class BorutaIdentity.Logger (line 1) | defmodule BorutaIdentity.Logger
method start (line 8) | def start do
method boruta_identity_request_handler (line 77) | def boruta_identity_request_handler(_, %{duration: duration}, %{conn: ...
method authentication_log_in_success_handler (line 112) | def authentication_log_in_success_handler(
method authentication_log_in_failure_handler (line 139) | def authentication_log_in_failure_handler(
method authentication_log_out_success_handler (line 164) | def authentication_log_out_success_handler(
method registration_create_success_handler (line 191) | def registration_create_success_handler(
method registration_create_failure_handler (line 218) | def registration_create_failure_handler(
method registration_confirm_success_handler (line 245) | def registration_confirm_success_handler(
method registration_confirm_failure_handler (line 272) | def registration_confirm_failure_handler(
method registration_update_success_handler (line 298) | def registration_update_success_handler(
method registration_update_failure_handler (line 354) | def registration_update_failure_handler(
method authorization_consent_success_handler (line 389) | def authorization_consent_success_handler(
method authorization_consent_failure_handler (line 417) | def authorization_consent_failure_handler(
method log_attribute (line 446) | defp log_attribute(_key, nil), do: ""
method log_attribute (line 447) | defp log_attribute(key, attribute), do: " #{key}=#{attribute}"
method log_level (line 450) | defp log_level(nil, _conn), do: :info
method connection_type (line 457) | defp connection_type(:set_chunked), do: "chunked"
method connection_type (line 458) | defp connection_type(_), do: "sent"
method duration (line 460) | defp duration(duration) do
FILE: apps/boruta_identity/lib/boruta_identity/organizations.ex
class BorutaIdentity.Organizations (line 1) | defmodule BorutaIdentity.Organizations
method list_organizations (line 16) | def list_organizations(params \\ %{}) do
method create_organization (line 33) | def create_organization(organization_params) do
method delete_organization (line 40) | def delete_organization(organization_id) do
method get_organization (line 51) | def get_organization(organization_id) do
method update_organization (line 65) | def update_organization(organization, organization_params) do
FILE: apps/boruta_identity/lib/boruta_identity/organizations/organization.ex
class BorutaIdentity.Organizations.Organization (line 1) | defmodule BorutaIdentity.Organizations.Organization
method changeset (line 25) | def changeset(organization, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/organizations/organization_user.ex
class BorutaIdentity.Organizations.OrganizationUser (line 1) | defmodule BorutaIdentity.Organizations.OrganizationUser
method changeset (line 27) | def changeset(organization_user, attrs) do
FILE: apps/boruta_identity/lib/boruta_identity/repo.ex
class BorutaIdentity.Repo (line 1) | defmodule BorutaIdentity.Repo
method set_limit (line 8) | def set_limit(conn) do
FILE: apps/boruta_identity/lib/boruta_identity/resource_owners.ex
class BorutaIdentity.ResourceOwners (line 1) | defmodule BorutaIdentity.ResourceOwners
method get_by (line 19) | def get_by(username: username) do
method get_by (line 40) | def get_by(sub: "unknown", scope: _scope), do: %User{}
method get_by (line 41) | def get_by(sub: "did:" <> _key, scope: _scope), do: %User{}
method get_by (line 67) | def get_by(_), do: {:error, "Invalid username or password."}
method check_password (line 70) | def check_password(%ResourceOwner{extra_claims: extra_claims}, passwor...
method authorized_scopes (line 87) | def authorized_scopes(%ResourceOwner{sub: "unknown"}), do: []
method authorized_scopes (line 88) | def authorized_scopes(%ResourceOwner{sub: "did:" <> _key}), do: []
method authorized_scopes (line 94) | def authorized_scopes(_), do: []
method claims (line 97) | def claims(%ResourceOwner{sub: sub}, scope) do
method metadata (line 115) | def metadata(user, scope) do
method merge_claims (line 123) | defp merge_claims(
method merge_claims (line 138) | defp merge_claims("profile", acc, _user, sub) do
method merge_claims (line 155) | defp merge_claims(_, acc, _user, _sub), do: acc
method metadata_scope_filter (line 157) | defp metadata_scope_filter(metadata, request_scope, %Backend{metadata_...
FILE: apps/boruta_identity/lib/boruta_identity/totp.ex
class BorutaIdentity.TotpError (line 1) | defmodule BorutaIdentity.TotpError
method message (line 18) | def message(exception) do
class BorutaIdentity.TotpRegistrationApplication (line 23) | defmodule BorutaIdentity.TotpRegistrationApplication
class BorutaIdentity.TotpAuthenticationApplication (line 43) | defmodule BorutaIdentity.TotpAuthenticationApplication
class BorutaIdentity.Totp (line 67) | defmodule BorutaIdentity.Totp
method new_totp_registration_template (line 251) | defp new_totp_registration_template(identity_provider) do
method new_totp_authentication_template (line 258) | defp new_totp_authentication_template(identity_provider) do
class Hotp (line 70) | defmodule Hotp
method generate_hotp (line 83) | def generate_hotp(secret, counter) do
method truncate_hash (line 96) | defp truncate_hash(hmac_value) do
method format_hotp (line 105) | defp format_hotp(hotp) do
class Admin (line 110) | defmodule Admin
method generate_totp (line 121) | def generate_totp(secret) do
method check_totp (line 137) | def check_totp(_totp, _secret), do: {:error, "Given TOTP is invalid."}
method generate_secret (line 139) | def generate_secret do
method url (line 143) | def url(username, secret) do
method number_of_time_steps (line 147) | defp number_of_time_steps do
FILE: apps/boruta_identity/lib/boruta_identity/webauthn.ex
class BorutaIdentity.WebauthnError (line 1) | defmodule BorutaIdentity.WebauthnError
method message (line 17) | def message(exception) do
class BorutaIdentity.WebauthnRegistrationApplication (line 22) | defmodule BorutaIdentity.WebauthnRegistrationApplication
class BorutaIdentity.WebauthnAuthenticationApplication (line 42) | defmodule BorutaIdentity.WebauthnAuthenticationApplication
class BorutaIdentity.Webauthn (line 67) | defmodule BorutaIdentity.Webauthn
method options (line 119) | def options(user, true) do
method options (line 139) | def options(user, false) do
method new_webauthn_registration_template (line 319) | defp new_webauthn_registration_template(identity_provider) do
method new_webauthn_authentication_template (line 326) | defp new_webauthn_authentication_template(identity_provider) do
class Options (line 70) | defmodule Options
FILE: apps/boruta_identity/lib/boruta_identity_web.ex
class BorutaIdentityWeb (line 1) | defmodule BorutaIdentityWeb
method controller (line 20) | def controller do
method view (line 30) | def view do
method router (line 45) | def router do
method channel (line 54) | def channel do
method view_helpers (line 61) | defp view_helpers do
FILE: apps/boruta_identity/lib/boruta_identity_web/concerns/authenticable.ex
class BorutaIdentityWeb.Authenticable (line 1) | defmodule BorutaIdentityWeb.Authenticable
method remember_me_cookie (line 19) | def remember_me_cookie, do: @remember_me_cookie
method store_user_session (line 23) | def store_user_session(%Plug.Conn{body_params: params} = conn, session...
method get_user_session (line 34) | def get_user_session(conn) do
method remove_user_session (line 39) | def remove_user_session(conn) do
method maybe_write_remember_me_cookie (line 50) | defp maybe_write_remember_me_cookie(conn, _token, _params) do
method after_sign_in_path (line 55) | def after_sign_in_path(conn), do: user_return_to_from_request(conn) ||...
method after_registration_path (line 58) | def after_registration_path(conn), do: user_return_to_from_request(con...
method after_sign_out_path (line 61) | def after_sign_out_path(%Plug.Conn{query_params: query_params} = conn) do
method request_param (line 66) | def request_param(conn) do
method scope_from_request (line 111) | def scope_from_request(%Plug.Conn{query_params: query_params}) do
method client_id_from_request (line 125) | def client_id_from_request(%Plug.Conn{query_params: query_params}) do
method user_return_to_from_request (line 139) | def user_return_to_from_request(%Plug.Conn{query_params: query_params}...
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/backends_controller.ex
class BorutaIdentityWeb.BackendsController (line 1) | defmodule BorutaIdentityWeb.BackendsController
method authorize (line 21) | def authorize(
method callback (line 49) | def callback(conn, %{"federated_server_name" => federated_server_name}...
method user_authenticated (line 63) | def user_authenticated(conn, user, session_token) do
method authentication_failure (line 85) | def authentication_failure(%Plug.Conn{} = conn, %SessionError{
method request_from_session (line 114) | defp request_from_session(conn) do
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/choose_session_controller.ex
class BorutaIdentityWeb.ChooseSessionController (line 1) | defmodule BorutaIdentityWeb.ChooseSessionController
method index (line 12) | def index(conn, _params) do
method choose_session_initialized (line 19) | def choose_session_initialized(conn, template) do
method choose_session_not_required (line 30) | def choose_session_not_required(conn) do
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/fallback_controller.ex
class BorutaIdentityWeb.FallbackController (line 1) | defmodule BorutaIdentityWeb.FallbackController
method call (line 11) | def call(conn, {:error, :not_found}) do
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/totp_controller.ex
class BorutaIdentityWeb.TotpController (line 1) | defmodule BorutaIdentityWeb.TotpController
method new (line 17) | def new(conn, _params) do
method register (line 29) | def register(conn, %{"totp" => totp_params}) do
method totp_registration_initialized (line 42) | def totp_registration_initialized(conn, totp_secret, template) do
method totp_registration_error (line 58) | def totp_registration_error(conn, %TotpError{
method totp_registration_error (line 78) | def totp_registration_error(conn, %TotpError{
method totp_registration_success (line 100) | def totp_registration_success(%Plug.Conn{} = conn, _user) do
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/user_confirmation_controller.ex
class BorutaIdentityWeb.UserConfirmationController (line 1) | defmodule BorutaIdentityWeb.UserConfirmationController
method new (line 12) | def new(conn, _params) do
method create (line 18) | def create(%Plug.Conn{query_params: query_params} = conn, %{"user" => ...
method confirm (line 37) | def confirm(conn, %{"token" => token}) do
method user_confirmed (line 44) | def user_confirmed(%Plug.Conn{query_params: query_params} = conn, user...
method user_confirmation_failure (line 64) | def user_confirmation_failure(%Plug.Conn{query_params: query_params} =...
method confirmation_instructions_delivered (line 91) | def confirmation_instructions_delivered(%Plug.Conn{query_params: query...
method confirmation_instructions_initialized (line 102) | def confirmation_instructions_initialized(conn, template) do
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/user_consent_controller.ex
class BorutaIdentityWeb.UserConsentController (line 1) | defmodule BorutaIdentityWeb.UserConsentController
method index (line 15) | def index(conn, _params) do
method consent (line 23) | def consent(conn, params) do
method consent_initialized (line 36) | def consent_initialized(conn, client, scopes, template) do
method consent_not_required (line 50) | def consent_not_required(conn) do
method consented (line 55) | def consented(conn, scopes) do
method consent_failed (line 74) | def consent_failed(%Plug.Conn{query_params: query_params} = conn, chan...
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/user_registration_controller.ex
class BorutaIdentityWeb.UserRegistrationController (line 1) | defmodule BorutaIdentityWeb.UserRegistrationController
method new (line 13) | def new(conn, _params) do
method create (line 19) | def create(%Plug.Conn{query_params: query_params} = conn, %{"user" => ...
method registration_initialized (line 39) | def registration_initialized(%Plug.Conn{} = conn, template) do
method registration_failure (line 47) | def registration_failure(%Plug.Conn{} = conn, %RegistrationError{
method registration_failure (line 74) | def registration_failure(%Plug.Conn{} = conn, %RegistrationError{
method registration_failure (line 100) | def registration_failure(%Plug.Conn{} = conn, %RegistrationError{
method user_registered (line 132) | def user_registered(conn, user, session_token) do
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/user_reset_password_controller.ex
class BorutaIdentityWeb.UserResetPasswordController (line 1) | defmodule BorutaIdentityWeb.UserResetPasswordController
method new (line 12) | def new(conn, _params) do
method create (line 18) | def create(%Plug.Conn{query_params: query_params} = conn, %{"user" => ...
method edit (line 35) | def edit(conn, params) do
method update (line 41) | def update(conn, params) do
method password_instructions_initialized (line 56) | def password_instructions_initialized(
method reset_password_instructions_delivered (line 70) | def reset_password_instructions_delivered(%Plug.Conn{query_params: que...
method password_reset_initialized (line 82) | def password_reset_initialized(
method password_reseted (line 97) | def password_reseted(%Plug.Conn{query_params: query_params} = conn, _u...
method password_reset_failure (line 108) | def password_reset_failure(%Plug.Conn{} = conn, %ResetPasswordError{
method password_reset_failure (line 126) | def password_reset_failure(conn, %ResetPasswordError{
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/user_session_controller.ex
class BorutaIdentityWeb.UserSessionController (line 1) | defmodule BorutaIdentityWeb.UserSessionController
method new (line 26) | def new(conn, _params) do
method create (line 32) | def create(conn, %{"user" => user_params}) do
method delete (line 43) | def delete(conn, _params) do
method initialize_totp (line 50) | def initialize_totp(conn, _params) do
method authenticate_totp (line 58) | def authenticate_totp(conn, %{"totp" => totp_params}) do
method initialize_webauthn (line 69) | def initialize_webauthn(conn, _params) do
method authenticate_webauthn (line 78) | def authenticate_webauthn(conn, params) do
method webauthn_registration_missing (line 94) | def webauthn_registration_missing(%Plug.Conn{query_params: query_param...
method session_initialized (line 103) | def session_initialized(%Plug.Conn{} = conn, template) do
method user_authenticated (line 114) | def user_authenticated(conn, user, session_token) do
method authentication_failure (line 133) | def authentication_failure(%Plug.Conn{} = conn, %SessionError{
method session_deleted (line 161) | def session_deleted(conn) do
method totp_not_required (line 182) | def totp_not_required(conn) do
method totp_registration_missing (line 189) | def totp_registration_missing(%Plug.Conn{query_params: query_params} =...
method totp_initialized (line 198) | def totp_initialized(%Plug.Conn{} = conn, template) do
method webauthn_initialized (line 213) | def webauthn_initialized(%Plug.Conn{} = conn, webauthn_options, templa...
method totp_authenticated (line 229) | def totp_authenticated(%Plug.Conn{} = conn, _user) do
method totp_authentication_failure (line 241) | def totp_authentication_failure(%Plug.Conn{} = conn, %TotpError{
method webauthn_not_required (line 261) | def webauthn_not_required(conn) do
method webauthn_authenticated (line 268) | def webauthn_authenticated(%Plug.Conn{} = conn, _user) do
method webauthn_authentication_failure (line 280) | def webauthn_authentication_failure(%Plug.Conn{} = conn, %WebauthnError{
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/user_settings_controller.ex
class BorutaIdentityWeb.UserSettingsController (line 1) | defmodule BorutaIdentityWeb.UserSettingsController
method edit (line 18) | def edit(conn, _params) do
method update (line 25) | def update(%Plug.Conn{query_params: query_params} = conn, %{"user" => ...
method destroy (line 45) | def destroy(conn, _params) do
method edit_user_initialized (line 53) | def edit_user_initialized(conn, user, template) do
method user_updated (line 61) | def user_updated(%Plug.Conn{query_params: query_params} = conn, user) do
method user_update_failure (line 81) | def user_update_failure(%Plug.Conn{} = conn, %SettingsError{
method user_update_failure (line 110) | def user_update_failure(%Plug.Conn{} = conn, %SettingsError{
method user_destroyed (line 140) | def user_destroyed(conn, user) do
method session_deleted (line 161) | def session_deleted(conn) do
method user_destroy_failure (line 182) | def user_destroy_failure(%Plug.Conn{} = conn, %SettingsError{
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/wallet_controller.ex
class BorutaIdentityWeb.WalletController (line 1) | defmodule BorutaIdentityWeb.WalletController
method index (line 4) | def index(conn, _params) do
FILE: apps/boruta_identity/lib/boruta_identity_web/controllers/webauthn_controller.ex
class BorutaIdentityWeb.WebauthnController (line 1) | defmodule BorutaIdentityWeb.WebauthnController
method new (line 17) | def new(conn, _params) do
method register (line 29) | def register(conn, params) do
method webauthn_registration_initialized (line 44) | def webauthn_registration_initialized(conn, webauthn_options, template...
method webauthn_registration_error (line 60) | def webauthn_registration_error(conn, %WebauthnError{
method webauthn_registration_success (line 81) | def webauthn_registration_success(%Plug.Conn{} = conn, _user) do
FILE: apps/boruta_identity/lib/boruta_identity_web/endpoint.ex
class BorutaIdentityWeb.Endpoint (line 1) | defmodule BorutaIdentityWeb.Endpoint
method log_level (line 36) | def log_level(%{path_info: ["healthcheck" | _]}), do: false
method log_level (line 37) | def log_level(_), do: :info
FILE: apps/boruta_identity/lib/boruta_identity_web/gettext.ex
class BorutaIdentityWeb.Gettext (line 1) | defmodule BorutaIdentityWeb.Gettext
FILE: apps/boruta_identity/lib/boruta_identity_web/plugs/sessions.ex
class BorutaIdentityWeb.Sessions (line 1) | defmodule BorutaIdentityWeb.Sessions
method fetch_current_user (line 15) | def fetch_current_user(conn, _opts) do
method ensure_user_token (line 21) | defp ensure_user_token(conn) do
method redirect_if_user_is_authenticated (line 39) | def redirect_if_user_is_authenticated(conn, _opts) do
method require_authenticated_user (line 56) | def require_authenticated_user(conn, _opts) do
FILE: apps/boruta_identity/lib/boruta_identity_web/router.ex
class BorutaIdentityWeb.Router (line 1) | defmodule BorutaIdentityWeb.Router
method handle_errors (line 88) | def handle_errors(conn, %{reason: %Plug.CSRFProtection.InvalidCSRFToke...
method handle_errors (line 105) | def handle_errors(conn, %{reason: reason}) do
method render_error (line 113) | defp render_error(conn, reason) do
FILE: apps/boruta_identity/lib/boruta_identity_web/telemetry.ex
class BorutaIdentityWeb.Telemetry (line 1) | defmodule BorutaIdentityWeb.Telemetry
method start_link (line 7) | def start_link(arg) do
method init (line 12) | def init(_arg) do
method metrics (line 24) | def metrics do
method periodic_measurements (line 50) | defp periodic_measurements do
FILE: apps/boruta_identity/lib/boruta_identity_web/token.ex
class BorutaIdentityWeb.Token (line 1) | defmodule BorutaIdentityWeb.Token
method application_signer (line 6) | def application_signer do
FILE: apps/boruta_identity/lib/boruta_identity_web/views/error_helpers.ex
class BorutaIdentityWeb.ErrorHelpers (line 1) | defmodule BorutaIdentityWeb.ErrorHelpers
method error_messages (line 8) | def error_messages(nil), do: []
method error_messages (line 10) | def error_messages(%Ecto.Changeset{} = changeset) do
method error_message (line 19) | def error_message({field, messages}) do
method errors_tag (line 31) | def errors_tag(errors) do
method error_tag (line 38) | def error_tag({field, {_msg, _opts} = error}) do
method error_tag (line 52) | def error_tag({field, ["" <> _first | _rest] = messages}) do
method error_tag (line 83) | def error_tag(form, field) do
method translate_error (line 92) | def translate_error({msg, opts}) do
FILE: apps/boruta_identity/lib/boruta_identity_web/views/error_view.ex
class BorutaIdentityWeb.ErrorView (line 1) | defmodule BorutaIdentityWeb.ErrorView
FILE: apps/boruta_identity/lib/boruta_identity_web/views/template_view.ex
class BorutaIdentityWeb.TemplateView (line 1) | defmodule BorutaIdentityWeb.TemplateView
method render (line 7) | def render("template.html", %{
method context (line 32) | def context(context, %{conn: conn, identity_provider: identity_provide...
method context (line 60) | def context(context, %{current_user: current_user, totp_secret: totp_s...
method context (line 75) | def context(context, %{client: client} = assigns) do
method context (line 83) | def context(context, %{resource_owner: resource_owner} = assigns) do
method context (line 91) | def context(context, %{credential_offer: credential_offer} = assigns) do
method context (line 106) | def context(context, %{presentation_deeplink: presentation_deeplink} =...
method context (line 120) | def context(context, %{webauthn_options: webauthn_options} = assigns) do
method context (line 128) | def context(context, %{code: code} = assigns) do
method context (line 135) | def context(context, %{current_user: current_user} = assigns) do
method context (line 153) | def context(context, %{scopes: scopes} = assigns) do
method context (line 161) | def context(context, %{}), do: context
method text_from_credential_offer (line 163) | defp text_from_credential_offer(credential_offer) do
method paths (line 172) | defp paths(conn, assigns) do
method errors (line 229) | defp errors(%{errors: errors}) do
method errors (line 235) | defp errors(%{changeset: changeset}) do
method errors (line 244) | defp errors(_assigns), do: %{errors: [], valid?: true}
method messages (line 246) | defp messages(conn) do
method identity_provider_configurations (line 256) | defp identity_provider_configurations(identity_provider) do
FILE: apps/boruta_identity/lib/boruta_identity_web/views/wallet_view.ex
class BorutaIdentityWeb.WalletView (line 1) | defmodule BorutaIdentityWeb.WalletView
FILE: apps/boruta_identity/mix.exs
class BorutaIdentity.MixProject (line 1) | defmodule BorutaIdentity.MixProject
method project (line 4) | def project do
method application (line 24) | def application do
method elixirc_paths (line 32) | defp elixirc_paths(:test), do: ["lib", "test/support"]
method elixirc_paths (line 33) | defp elixirc_paths(_), do: ["lib"]
method deps (line 38) | defp deps do
method aliases (line 84) | defp aliases do
FILE: apps/boruta_identity/priv/repo/migrations/20210127190501_create_users_auth_tables.exs
class BorutaIdentity.Repo.Migrations.CreateUsersAuthTables (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateUsersAuthTables
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20210128080043_create_users_authorized_scopes.exs
class BorutaIdentity.Repo.Migrations.CreateUsersAuthorizedScopes (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateUsersAuthorizedScopes
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20210208110903_user_authorized_scopes_unique_index.exs
class BorutaIdentity.Repo.Migrations.UserAuthorizedScopesUniqueIndex (line 1) | defmodule BorutaIdentity.Repo.Migrations.UserAuthorizedScopesUniqueIndex
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20210302213536_create_consents.exs
class BorutaIdentity.Repo.Migrations.CreateConsents (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateConsents
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20210806194842_add_last_login_at_to_users.exs
class BorutaIdentity.Repo.Migrations.AddLastLoginAtToUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddLastLoginAtToUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20211002132445_modify_users_confirmed_at.exs
class BorutaIdentity.Repo.Migrations.ModifyUsersConfirmedAt (line 1) | defmodule BorutaIdentity.Repo.Migrations.ModifyUsersConfirmedAt
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20211129225646_create_relying_parties.exs
class BorutaIdentity.Repo.Migrations.CreateRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20211130230927_create_clients_relying_parties.exs
class BorutaIdentity.Repo.Migrations.CreateClientsRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateClientsRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220117220007_add_registrable_to_relying_parties.exs
class BorutaIdentity.Repo.Migrations.AddRegistrableToRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddRegistrableToRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220118122834_add_unique_name_to_relying_parties.exs
class BorutaIdentity.Repo.Migrations.AddUniqueNameToRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddUniqueNameToRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220120214356_create_relying_party_templates.exs
class BorutaIdentity.Repo.Migrations.CreateRelyingPartyTemplates (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateRelyingPartyTemplates
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220131133951_add_confirmable_to_relying_parties.exs
class BorutaIdentity.Repo.Migrations.AddConfirmableToRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddConfirmableToRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220218144931_add_consentable_to_relying_parties.exs
class BorutaIdentity.Repo.Migrations.AddConsentableToRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddConsentableToRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220221123627_add_choose_session_to_relying_parties.exs
class BorutaIdentity.Repo.Migrations.AddChooseSessionToRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddChooseSessionToRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220520212652_add_user_editable_to_relying_parties.exs
class BorutaIdentity.Repo.Migrations.AddUserEditableToRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddUserEditableToRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220528155902_create_internal_users.exs
class BorutaIdentity.Repo.Migrations.CreateInternalUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateInternalUsers
method up (line 4) | def up do
method down (line 68) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20220607201657_add_user_authorized_scopes_scope_id.exs
class BorutaIdentity.Repo.Migrations.AddUserAuthorizedScopesScopeId (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddUserAuthorizedScopesScopeId
method up (line 7) | def up do
method down (line 56) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20220617195827_rename_relying_parties.exs
class BorutaIdentity.Repo.Migrations.RenameRelyingParties (line 1) | defmodule BorutaIdentity.Repo.Migrations.RenameRelyingParties
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220628073937_create_error_templates.exs
class BorutaAuth.Repo.Migrations.CreateErrorTemplates (line 1) | defmodule BorutaAuth.Repo.Migrations.CreateErrorTemplates
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220812123254_create_backends.exs
class BorutaIdentity.Repo.Migrations.CreateBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220815073225_add_backend_id_to_identity_providers.exs
class BorutaIdentity.Repo.Migrations.AddBackendIdToIdentityProviders (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddBackendIdToIdentityProviders
method up (line 4) | def up do
method down (line 24) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20220815091033_remove_type_from_identity_providers.exs
class BorutaIdentity.Repo.Migrations.RemoveTypeFromIdentityProviders (line 1) | defmodule BorutaIdentity.Repo.Migrations.RemoveTypeFromIdentityProviders
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220815115719_add_default_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddDefaultToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddDefaultToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220816074610_add_password_hashing_opts_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddPasswordHashingOptsToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddPasswordHashingOptsToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220817134821_change_users_provider_to_backend_id.exs
class BorutaIdentity.Repo.Migrations.ChangeUsersProviderToBackendId (line 1) | defmodule BorutaIdentity.Repo.Migrations.ChangeUsersProviderToBackendId
method up (line 4) | def up do
method down (line 27) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20220817150643_add_backend_id_to_internal_users.exs
class BorutaIdentity.Repo.Migrations.AddBackendIdToInternalUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddBackendIdToInternalUsers
method up (line 4) | def up do
method down (line 26) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20220826055043_add_mail_configuration_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddMailConfigurationToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddMailConfigurationToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220904073628_create_pg_trgm_extension.exs
class BorutaIdentity.Repo.Migrations.CreatePgTrgmExtension (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreatePgTrgmExtension
method up (line 4) | def up do
method down (line 8) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20220904183116_create_trgm_index.exs
class BorutaIdentity.Repo.Migrations.CreateTrgmIndex (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateTrgmIndex
method up (line 4) | def up do
method down (line 8) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20220911195248_add_ldap_configuration_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddLdapConfigurationToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddLdapConfigurationToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20220915191039_add_ldap_ser_rdn_attribute_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddLdapSerRdnAttributeToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddLdapSerRdnAttributeToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20221008202236_add_ldap_master_credentials_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddLdapMasterCredentialsToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddLdapMasterCredentialsToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20221026092004_create_email_templates.exs
class BorutaIdentity.Repo.Migrations.CreateEmailTemplates (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateEmailTemplates
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20221026211130_add_smtp_ssl_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddSmtpSslToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddSmtpSslToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20221028083326_add_revoked_at_to_users_tokens.exs
class BorutaIdentity.Repo.Migrations.AddRevokedAtToUsersTokens (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddRevokedAtToUsersTokens
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20221108140432_add_metadata_fields_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddMetadataFieldsToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddMetadataFieldsToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20221108144651_add_metadata_to_users.exs
class BorutaIdentity.Repo.Migrations.AddMetadataToUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddMetadataToUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230303151220_add_group_to_users.exs
class BorutaIdentity.Repo.Migrations.AddGroupToUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddGroupToUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230502111802_add_identity_federation_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddIdentityFederationToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddIdentityFederationToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230605073651_create_roles.exs
class BorutaIdentity.Repo.Migrations.CreateRoles (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateRoles
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230605074117_create_roles_scopes.exs
class BorutaIdentity.Repo.Migrations.CreateRolesScopes (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateRolesScopes
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230615082520_create_roles_users.exs
class BorutaIdentity.Repo.Migrations.CreateRolesUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateRolesUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230626064411_create_backends_roles.exs
class BorutaIdentity.Repo.Migrations.CreateBackendsRoles (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateBackendsRoles
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230805134343_add_totpable_to_identity_providers.exs
class BorutaIdentity.Repo.Migrations.AddTotpableToIdentityProviders (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddTotpableToIdentityProviders
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230805160200_add_totp_to_users.exs
class BorutaIdentity.Repo.Migrations.AddTotpToUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddTotpToUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230810130509_add_enforce_totp_to_identity_providers.exs
class BorutaIdentity.Repo.Migrations.AddEnforceTotpToIdentityProviders (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddEnforceTotpToIdentityProviders
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230903150227_create_organizations.exs
class BorutaIdentity.Repo.Migrations.CreateOrganizations (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateOrganizations
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230908094746_add_label_to_organizations.exs
class BorutaIdentity.Repo.Migrations.AddLabelToOrganizations (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddLabelToOrganizations
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230908113944_create_organizations_users.exs
class BorutaIdentity.Repo.Migrations.CreateOrganizationsUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.CreateOrganizationsUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20230909103013_add_create_default_organization_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddCreateDefaultOrganizationToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddCreateDefaultOrganizationToB...
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20240109125818_add_verifiable_credentails_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddVerifiableCredentailsToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddVerifiableCredentailsToBackends
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20240110094020_add_federated_metadata_to_users.exs
class BorutaIdentity.Repo.Migrations.AddFederatedMetadataToUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddFederatedMetadataToUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20240426110841_organizations_users_reference.exs
class BorutaIdentity.Repo.Migrations.OrganizationsUsersReference (line 1) | defmodule BorutaIdentity.Repo.Migrations.OrganizationsUsersReference
method up (line 4) | def up do
method down (line 14) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20240505104631_organizations_users_reference2.exs
class BorutaIdentity.Repo.Migrations.OrganizationsUsersReference2 (line 1) | defmodule BorutaIdentity.Repo.Migrations.OrganizationsUsersReference2
method up (line 4) | def up do
method down (line 14) | def down do
FILE: apps/boruta_identity/priv/repo/migrations/20240808195715_add_webauthn_challenge_to_users.exs
class BorutaIdentity.Repo.Migrations.AddWebauthnChallengeToUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddWebauthnChallengeToUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20240820140733_add_webauthn_public_key_to_users.exs
class BorutaIdentity.Repo.Migrations.AddWebauthnPublicKeyToUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddWebauthnPublicKeyToUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20240820233604_add_webauthn_to_identity_providers.exs
class BorutaIdentity.Repo.Migrations.AddWebauthnToIdentityProviders (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddWebauthnToIdentityProviders
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20240907103609_add_verifiable_presentations_to_backends.exs
class BorutaIdentity.Repo.Migrations.AddVerifiablePresentationsToBackends (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddVerifiablePresentationsToBac...
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20241017153124_add_account_type_to_users.exs
class BorutaIdentity.Repo.Migrations.AddAccountTypeToUsers (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddAccountTypeToUsers
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20241130000259_add_check_password_to_identity_providers.exs
class BorutaIdentity.Repo.Migrations.AddCheckPasswordToIdentityProviders (line 1) | defmodule BorutaIdentity.Repo.Migrations.AddCheckPasswordToIdentityProvi...
method change (line 4) | def change do
FILE: apps/boruta_identity/priv/repo/migrations/20250302193825_remove_global_email_unique_constraint.exs
class BorutaIdentity.Repo.Migrations.RemoveGlobalEmailUniqueConstraint (line 1) | defmodule BorutaIdentity.Repo.Migrations.RemoveGlobalEmailUniqueConstraint
method change (line 4) | def change do
FILE: apps/boruta_identity/test/boruta_identity/accounts/deliveries_test.exs
class BorutaIdentity.Accounts.DeliveriesTest (line 1) | defmodule BorutaIdentity.Accounts.DeliveriesTest
FILE: apps/boruta_identity/test/boruta_identity/accounts_test.exs
class BorutaIdentity.AccountsTest (line 1) | defmodule BorutaIdentity.AccountsTest
class DummyRegistration (line 23) | defmodule DummyRegistration
method registration_initialized (line 27) | def registration_initialized(context, template) do
method user_registered (line 32) | def user_registered(context, user, session_token) do
method registration_failure (line 37) | def registration_failure(context, error) do
class DummySession (line 42) | defmodule DummySession
method session_initialized (line 46) | def session_initialized(context, template) do
method user_authenticated (line 51) | def user_authenticated(context, user, session_token) do
method authentication_failure (line 56) | def authentication_failure(context, error) do
method session_deleted (line 61) | def session_deleted(context) do
class DummyConfirmation (line 66) | defmodule DummyConfirmation
method confirmation_instructions_initialized (line 70) | def confirmation_instructions_initialized(context, template) do
method confirmation_instructions_delivered (line 75) | def confirmation_instructions_delivered(context) do
method user_confirmed (line 80) | def user_confirmed(context, user) do
method user_confirmation_failure (line 85) | def user_confirmation_failure(context, error) do
class DummySettings (line 90) | defmodule DummySettings
method edit_user_initialized (line 94) | def edit_user_initialized(context, user, template) do
method user_updated (line 99) | def user_updated(context, user) do
method user_destroy_failure (line 104) | def user_destroy_failure(context, error) do
method user_destroyed (line 109) | def user_destroyed(context, user) do
method user_update_failure (line 114) | def user_update_failure(context, error) do
class DummyResetPasswords (line 119) | defmodule DummyResetPasswords
method password_instructions_initialized (line 123) | def password_instructions_initialized(context, template) do
method reset_password_instructions_delivered (line 128) | def reset_password_instructions_delivered(context) do
method password_reset_initialized (line 133) | def password_reset_initialized(context, token, template) do
method password_reseted (line 138) | def password_reseted(context, user) do
method password_reset_failure (line 143) | def password_reset_failure(context, error) do
FILE: apps/boruta_identity/test/boruta_identity/admin_test.exs
class BorutaIdentity.AdminTest (line 1) | defmodule BorutaIdentity.AdminTest
class OrganizationsTest (line 429) | defmodule OrganizationsTest
FILE: apps/boruta_identity/test/boruta_identity/configuration_test.exs
class BorutaIdentity.ConfigurationTest (line 1) | defmodule BorutaIdentity.ConfigurationTest
FILE: apps/boruta_identity/test/boruta_identity/federated_accounts_test.exs
class BorutaIdentity.FederatedAccountsTest (line 1) | defmodule BorutaIdentity.FederatedAccountsTest
class DummyFederatedSessions (line 9) | defmodule DummyFederatedSessions
method user_authenticated (line 13) | def user_authenticated(context, user, session_token) do
method authentication_failure (line 18) | def authentication_failure(context, error) do
FILE: apps/boruta_identity/test/boruta_identity/identity_providers/backend_test.exs
class BorutaIdentity.IdentityProviders.BackendTest (line 1) | defmodule BorutaIdentity.IdentityProviders.BackendTest
FILE: apps/boruta_identity/test/boruta_identity/identity_providers/identity_provider_test.exs
class BorutaIdentity.IdentityProviders.IdentityProviderTest (line 1) | defmodule BorutaIdentity.IdentityProviders.IdentityProviderTest
FILE: apps/boruta_identity/test/boruta_identity/identity_providers_test.exs
class BorutaIdentity.IdentityProvidersTest (line 1) | defmodule BorutaIdentity.IdentityProvidersTest
FILE: apps/boruta_identity/test/boruta_identity/resource_owners_test.exs
class BorutaIdentity.ResourceOwnersTest (line 1) | defmodule BorutaIdentity.ResourceOwnersTest
FILE: apps/boruta_identity/test/boruta_identity/totp_test.exs
class BorutaIdentity.TotpTest (line 1) | defmodule BorutaIdentity.TotpTest
class DummyTotpRegistrationApplication (line 2) | defmodule DummyTotpRegistrationApplication
method totp_registration_initialized (line 6) | def totp_registration_initialized(context, totp_secret, template) do
method totp_registration_error (line 11) | def totp_registration_error(context, error) do
method totp_registration_success (line 16) | def totp_registration_success(context, user) do
class DummyTotpAuthenticationApplication (line 21) | defmodule DummyTotpAuthenticationApplication
method totp_initialized (line 25) | def totp_initialized(context, template) do
method totp_not_required (line 30) | def totp_not_required(context) do
method totp_registration_missing (line 35) | def totp_registration_missing(context) do
method totp_authenticated (line 40) | def totp_authenticated(context, current_user) do
method totp_authentication_failure (line 45) | def totp_authentication_failure(context, error) do
class HotpTest (line 50) | defmodule HotpTest
class AdminTest (line 73) | defmodule AdminTest
FILE: apps/boruta_identity/test/boruta_identity/webauthn_test.exs
class BorutaIdentity.WebauthnTest (line 1) | defmodule BorutaIdentity.WebauthnTest
FILE: apps/boruta_identity/test/boruta_identity_web/concerns/authenticable_test.exs
class BorutaIdentityWeb.AuthenticableTest (line 1) | defmodule BorutaIdentityWeb.AuthenticableTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/choose_session_controller_test.exs
class BorutaIdentityWeb.ChooseSessionControllerTest (line 1) | defmodule BorutaIdentityWeb.ChooseSessionControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/page_controller_test.exs
class BorutaIdentityWeb.PageControllerTest (line 1) | defmodule BorutaIdentityWeb.PageControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/totp_controller_test.exs
class BorutaIdentityWeb.TotpControllerTest (line 1) | defmodule BorutaIdentityWeb.TotpControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/user_confirmation_controller_test.exs
class BorutaIdentityWeb.UserConfirmationControllerTest (line 1) | defmodule BorutaIdentityWeb.UserConfirmationControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/user_consent_controller_test.exs
class BorutaIdentityWeb.UserConsentControllerTest (line 1) | defmodule BorutaIdentityWeb.UserConsentControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/user_registration_controller_test.exs
class BorutaIdentityWeb.UserRegistrationControllerTest (line 1) | defmodule BorutaIdentityWeb.UserRegistrationControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/user_reset_password_controller_test.exs
class BorutaIdentityWeb.UserResetPasswordControllerTest (line 1) | defmodule BorutaIdentityWeb.UserResetPasswordControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/user_session_controller_test.exs
class BorutaIdentityWeb.UserSessionControllerTest (line 1) | defmodule BorutaIdentityWeb.UserSessionControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/controllers/user_settings_controller_test.exs
class BorutaIdentityWeb.UserSettingsControllerTest (line 1) | defmodule BorutaIdentityWeb.UserSettingsControllerTest
FILE: apps/boruta_identity/test/boruta_identity_web/plugs/sessions_test.exs
class BorutaIdentityWeb.SessionsTest (line 1) | defmodule BorutaIdentityWeb.SessionsTest
FILE: apps/boruta_identity/test/boruta_identity_web/views/error_view_test.exs
class BorutaIdentityWeb.ErrorViewTest (line 1) | defmodule BorutaIdentityWeb.ErrorViewTest
FILE: apps/boruta_identity/test/boruta_identity_web/views/layout_view_test.exs
class BorutaIdentityWeb.LayoutViewTest (line 1) | defmodule BorutaIdentityWeb.LayoutViewTest
FILE: apps/boruta_identity/test/boruta_identity_web/views/page_view_test.exs
class BorutaIdentityWeb.PageViewTest (line 1) | defmodule BorutaIdentityWeb.PageViewTest
FILE: apps/boruta_identity/test/support/boruta_factory.ex
class Boruta.Factory (line 1) | defmodule Boruta.Factory
method client_factory (line 8) | def client_factory do
method scope_factory (line 21) | def scope_factory do
method token_factory (line 28) | def token_factory do
FILE: apps/boruta_identity/test/support/boruta_identity_factory.ex
class BorutaIdentity.Factory (line 1) | defmodule BorutaIdentity.Factory
method user_factory (line 25) | def user_factory do
method user_authorized_scope_factory (line 33) | def user_authorized_scope_factory do
method user_role_factory (line 37) | def user_role_factory do
method reset_password_user_token_factory (line 41) | def reset_password_user_token_factory do
method internal_user_factory (line 52) | def internal_user_factory do
method consent_factory (line 60) | def consent_factory do
method client_identity_provider_factory (line 67) | def client_identity_provider_factory do
method identity_provider_factory (line 74) | def identity_provider_factory do
method backend_factory (line 81) | def backend_factory do
method federated_backend_factory (line 88) | def federated_backend_factory do
method ldap_backend_factory (line 104) | def ldap_backend_factory do
method smtp_backend_factory (line 116) | def smtp_backend_factory do
method template_factory (line 130) | def template_factory do
method new_registration_template_factory (line 137) | def new_registration_template_factory do
method email_template_factory (line 144) | def email_template_factory do
method reset_password_instructions_email_template_factory (line 152) | def reset_password_instructions_email_template_factory do
method error_template_factory (line 160) | def error_template_factory do
method role_factory (line 167) | def role_factory do
method role_scope_factory (line 173) | def role_scope_factory do
method organization_factory (line 177) | def organization_factory do
FILE: apps/boruta_identity/test/support/conn_case.ex
class BorutaIdentityWeb.ConnCase (line 1) | defmodule BorutaIdentityWeb.ConnCase
method register_and_log_in (line 59) | def register_and_log_in(%{conn: conn}) do
method generate_user_session_token (line 68) | def generate_user_session_token(%User{id: user_id}) do
method log_in (line 82) | def log_in(conn, user, params \\ %{}) do
method with_a_request (line 91) | def with_a_request(_params) do
FILE: apps/boruta_identity/test/support/data_case.ex
class BorutaIdentity.DataCase (line 1) | defmodule BorutaIdentity.DataCase
method errors_on (line 53) | def errors_on(changeset) do
FILE: apps/boruta_identity/test/support/fixtures/accounts_fixtures.ex
class BorutaIdentity.AccountsFixtures (line 1) | defmodule BorutaIdentity.AccountsFixtures
method unique_user_email (line 16) | def unique_user_email, do: "user#{System.unique_integer()}@example.com"
method valid_user_password (line 17) | def valid_user_password, do: @password
method user_fixture (line 19) | def user_fixture(attrs \\ %{}, account_type \\ "internal") do
method user_scopes_fixture (line 33) | def user_scopes_fixture(user, attrs \\ %{}) do
method extract_user_token (line 48) | def extract_user_token(fun) do
FILE: apps/boruta_identity/test/support/fixtures/admin_fixtures.ex
class BorutaIdentity.AdminFixtures (line 1) | defmodule BorutaIdentity.AdminFixtures
method role_fixture (line 7) | def role_fixture(attrs \\ %{}) do
FILE: apps/boruta_identity/test/support/fixtures/identity_providers_fixtures.ex
class BorutaIdentity.IdentityProvidersFixtures (line 1) | defmodule BorutaIdentity.IdentityProvidersFixtures
method backend_fixture (line 10) | def backend_fixture(attrs \\ %{}) do
FILE: apps/boruta_web/lib/boruta/status_resolver.ex
class Boruta.Did.StatusResolver (line 1) | defmodule Boruta.Did.StatusResolver
method resolve (line 4) | def resolve(_status) do
FILE: apps/boruta_web/lib/boruta_web.ex
class BorutaWeb (line 1) | defmodule BorutaWeb
method controller (line 20) | def controller do
method view (line 29) | def view do
method router (line 47) | def router do
method channel (line 55) | def channel do
FILE: apps/boruta_web/lib/boruta_web/application.ex
class BorutaWeb.Application (line 1) | defmodule BorutaWeb.Application
method start (line 8) | def start(_type, _args) do
method config_change (line 30) | def config_change(changed, _new, removed) do
method setup_database (line 35) | def setup_database do
method seed (line 56) | defp seed do
FILE: apps/boruta_web/lib/boruta_web/controllers/did_controller.ex
class BorutaWeb.DidController (line 1) | defmodule BorutaWeb.DidController
method resolve_status (line 6) | def resolve_status(conn, %{"status" => salt}) do
FILE: apps/boruta_web/lib/boruta_web/controllers/fallback_controller.ex
class BorutaWeb.FallbackController (line 1) | defmodule BorutaWeb.FallbackController
method call (line 9) | def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
method call (line 16) | def call(conn, {:error, :not_found}) do
FILE: apps/boruta_web/lib/boruta_web/controllers/monitoring_controller.ex
class BorutaWeb.MonitoringController (line 1) | defmodule BorutaWeb.MonitoringController
method healthcheck (line 6) | def healthcheck(conn, _params) do
FILE: apps/boruta_web/lib/boruta_web/controllers/oauth/authorize_controller.ex
class BorutaWeb.AuthorizeError (line 1) | defmodule BorutaWeb.AuthorizeError
class BorutaWeb.Oauth.AuthorizeController (line 6) | defmodule BorutaWeb.Oauth.AuthorizeController
method authorize (line 38) | def authorize(%Plug.Conn{} = conn, _params) do
method authenticated? (line 70) | def authenticated?(conn, %{"code" => code}) do
method public_client? (line 89) | def public_client?(
method public_client? (line 95) | def public_client?(
method public_client? (line 101) | def public_client?(
method public_client? (line 107) | def public_client?(conn), do: {:unchanged, conn}
method redirect_if_mfa_required (line 109) | defp redirect_if_mfa_required(conn, current_user) do
method ensure_mfa (line 149) | defp ensure_mfa(%Plug.Conn{query_params: query_params} = conn, current...
method do_enforce_mfa (line 161) | defp do_enforce_mfa(
method do_enforce_mfa (line 170) | defp do_enforce_mfa(
method do_enforce_mfa (line 185) | defp do_enforce_mfa(
method do_enforce_mfa (line 200) | defp do_enforce_mfa(
method do_enforce_mfa (line 215) | defp do_enforce_mfa(
method do_enforce_mfa (line 230) | defp do_enforce_mfa(_identity_provider, _user, _totp_authenticated, _w...
method check_preauthorized (line 234) | defp check_preauthorized(conn) do
method max_age_redirection (line 257) | defp max_age_redirection(
method max_age_redirection (line 278) | defp max_age_redirection(conn, _current_user), do: {:unchanged, conn}
method prompt_redirection (line 280) | defp prompt_redirection(
method prompt_redirection (line 300) | defp prompt_redirection(%Plug.Conn{query_params: %{"prompt" => "login"...
method prompt_redirection (line 312) | defp prompt_redirection(conn, _current_user), do: {:unchanged, conn}
method preauthorize (line 314) | defp preauthorize(conn, nil), do: {:unchanged, conn}
method preauthorize (line 316) | defp preauthorize(conn, current_user) do
method do_authorize (line 327) | defp do_authorize(conn, current_user) do
method preauthorize_success (line 337) | def preauthorize_success(conn, %AuthorizationSuccess{
method preauthorize_success (line 360) | def preauthorize_success(conn, _authorization) do
method preauthorize_error (line 390) | def preauthorize_error(conn, error) do
method authorize_success (line 415) | def authorize_success(
method authorize_success (line 442) | def authorize_success(
method authorize_success (line 470) | def authorize_success(
method authorize_success (line 488) | def authorize_success(
method authorize_success (line 506) | def authorize_success(
method authorize_success (line 534) | def authorize_success(
method authorize_success (line 573) | def authorize_success(
method authorize_error (line 614) | def authorize_error(
method authorize_error (line 621) | def authorize_error(
method authorize_error (line 648) | def authorize_error(
method emit_authorize_error_event (line 662) | defp emit_authorize_error_event(%Plug.Conn{query_params: query_params}...
method login_expired? (line 680) | defp login_expired?(current_user, max_age) do
method put_unsigned_request (line 692) | defp put_unsigned_request(%Plug.Conn{query_params: query_params} = con...
method resource_owner (line 706) | defp resource_owner(conn, current_user) do
FILE: apps/boruta_web/lib/boruta_web/controllers/oauth/introspect_controller.ex
class BorutaWeb.Oauth.IntrospectController (line 1) | defmodule BorutaWeb.Oauth.IntrospectController
method introspect (line 11) | def introspect(%Plug.Conn{} = conn, _params) do
method introspect_success (line 16) | def introspect_success(%Plug.Conn{body_params: body_params} = conn, %I...
method introspect_error (line 37) | def introspect_error(%Plug.Conn{body_params: body_params} = conn, %Error{
FILE: apps/boruta_web/lib/boruta_web/controllers/oauth/pushed_authorization_request_controller.ex
class BorutaWeb.Oauth.PushedAuthorizationRequestController (line 1) | defmodule BorutaWeb.Oauth.PushedAuthorizationRequestController
method pushed_authorization_request (line 10) | def pushed_authorization_request(%Plug.Conn{} = conn, _params) do
method request_stored (line 15) | def request_stored(conn, response) do
method pushed_authorization_error (line 23) | def pushed_authorization_error(conn, %Error{
FILE: apps/boruta_web/lib/boruta_web/controllers/oauth/revoke_controller.ex
class BorutaWeb.Oauth.RevokeController (line 1) | defmodule BorutaWeb.Oauth.RevokeController
method revoke (line 10) | def revoke(%Plug.Conn{} = conn, _params) do
method revoke_success (line 15) | def revoke_success(%Plug.Conn{body_params: body_params} = conn) do
method revoke_error (line 31) | def revoke_error(%Plug.Conn{body_params: body_params} = conn, %Error{
FILE: apps/boruta_web/lib/boruta_web/controllers/oauth/token_controller.ex
class BorutaWeb.Oauth.TokenController (line 1) | defmodule BorutaWeb.Oauth.TokenController
method token (line 16) | def token(%Plug.Conn{} = conn, _params) do
method token_success (line 21) | def token_success(conn, %TokenResponse{} = response) do
method token_error (line 45) | def token_error(conn, %Error{status: status, error: error, error_descr...
method direct_post (line 63) | def direct_post(conn, %{"code_id" => code_id} = params) do
method code_not_found (line 89) | def code_not_found(conn) do
method authentication_failure (line 94) | def authentication_failure(conn, %Error{
method authentication_failure (line 106) | def authentication_failure(conn, %Error{} = error) do
FILE: apps/boruta_web/lib/boruta_web/controllers/openid/credential_controller.ex
class BorutaWeb.Openid.CredentialController (line 1) | defmodule BorutaWeb.Openid.CredentialController
method credential (line 13) | def credential(conn, params) do
method defered_credential (line 22) | def defered_credential(conn, _params) do
method credential_created (line 27) | def credential_created(conn, %CredentialResponse{} = response) do
method credential_created (line 35) | def credential_created(conn, %DeferedCredentialResponse{} = response) do
method credential_failure (line 42) | def credential_failure(conn, %Error{
FILE: apps/boruta_web/lib/boruta_web/controllers/openid/dynamic_registration_controller.ex
class BorutaWeb.Openid.DynamicRegistrationController (line 1) | defmodule BorutaWeb.Openid.DynamicRegistrationController
method register_client (line 15) | def register_client(conn, params) do
method client_registered (line 27) | def client_registered(conn, %Oauth.Client{id: client_id} = client) do
method registration_failure (line 48) | def registration_failure(conn, changeset) do
method insert_global_key_pair (line 55) | defp insert_global_key_pair(%Oauth.Client{id: client_id}) do
FILE: apps/boruta_web/lib/boruta_web/controllers/openid/jwks_controller.ex
class BorutaWeb.Openid.JwksController (line 1) | defmodule BorutaWeb.Openid.JwksController
method jwks_index (line 10) | def jwks_index(conn, _params) do
method jwk_list (line 15) | def jwk_list(conn, jwk_keys) do
FILE: apps/boruta_web/lib/boruta_web/controllers/openid/userinfo_controller.ex
class BorutaWeb.Openid.UserinfoController (line 1) | defmodule BorutaWeb.Openid.UserinfoController
method userinfo (line 10) | def userinfo(conn, _params) do
method userinfo_fetched (line 15) | def userinfo_fetched(conn, response) do
method unauthorized (line 23) | def unauthorized(conn, error) do
FILE: apps/boruta_web/lib/boruta_web/controllers/openid_controller.ex
class BorutaWeb.OpenidController (line 1) | defmodule BorutaWeb.OpenidController
method well_known (line 6) | def well_known(conn, _params) do
method openid_credential_issuer (line 14) | def openid_credential_issuer(conn, _params) do
FILE: apps/boruta_web/lib/boruta_web/endpoint.ex
class BorutaWeb.Endpoint (line 1) | defmodule BorutaWeb.Endpoint
method put_secret_key_base (line 36) | def put_secret_key_base(conn, _) do
method log_level (line 46) | def log_level(%{private: %{BorutaIdentityWeb.Router => {["accounts"], ...
method log_level (line 47) | def log_level(%{path_info: ["healthcheck" | _]}), do: false
method log_level (line 48) | def log_level(%{path_info: path_info}) do
FILE: apps/boruta_web/lib/boruta_web/gettext.ex
class BorutaWeb.Gettext (line 1) | defmodule BorutaWeb.Gettext
FILE: apps/boruta_web/lib/boruta_web/logger.ex
class BorutaWeb.Logger (line 1) | defmodule BorutaWeb.Logger
method start (line 6) | def start do
method boruta_web_request_handler (line 60) | def boruta_web_request_handler(_, %{duration: duration}, %{conn: conn}...
method authorization_authorize_success_handler (line 95) | def authorization_authorize_success_handler(
method authorization_authorize_failure_handler (line 129) | def authorization_authorize_failure_handler(
method authorization_token_success_handler (line 159) | def authorization_token_success_handler(
method authorization_token_failure_handler (line 193) | def authorization_token_failure_handler(
method authorization_introspect_success_handler (line 219) | def authorization_introspect_success_handler(
method authorization_introspect_failure_handler (line 247) | def authorization_introspect_failure_handler(
method authorization_revoke_success_handler (line 275) | def authorization_revoke_success_handler(
method authorization_revoke_failure_handler (line 297) | def authorization_revoke_failure_handler(
method log_attribute (line 325) | defp log_attribute(_key, nil), do: ""
method log_attribute (line 326) | defp log_attribute(key, attribute), do: " #{key}=#{attribute}"
method log_level (line 329) | defp log_level(nil, _conn), do: :info
method connection_type (line 336) | defp connection_type(:set_chunked), do: "chunked"
method connection_type (line 337) | defp connection_type(_), do: "sent"
method duration (line 339) | defp duration(duration) do
FILE: apps/boruta_web/lib/boruta_web/plugs/rate_limit.ex
class BorutaWeb.Plugs.RateLimit (line 1) | defmodule BorutaWeb.Plugs.RateLimit
method init (line 83) | def init(options), do: options
method call (line 85) | def call(conn, options) do
class Counter (line 4) | defmodule Counter
method start_link (line 18) | def start_link(_args) do
method get (line 22) | def get(ip, time_unit) do
method throttling_timeout (line 31) | def throttling_timeout(ip, count, time_unit, penality) do
method increment (line 64) | def increment(ip, time_unit) do
FILE: apps/boruta_web/lib/boruta_web/presentation_server.ex
class BorutaWeb.PresentationServer (line 1) | defmodule BorutaWeb.PresentationServer
method start_link (line 6) | def start_link do
method init (line 10) | def init(_args) do
method start_presentation (line 14) | def start_presentation(code) do
method authenticated (line 18) | def authenticated(code, redirect_uri) do
method message (line 22) | def message(code, message) do
method handle_call (line 26) | def handle_call({:start_presentation, code}, {pid, _}, state) do
method handle_cast (line 38) | def handle_cast({:authenticated, code, redirect_uri}, state) do
method handle_cast (line 48) | def handle_cast({:message, code, message}, state) do
FILE: apps/boruta_web/lib/boruta_web/release.ex
class BorutaWeb.Release (line 1) | defmodule BorutaWeb.Release
method migrate (line 5) | def migrate do
method rollback (line 13) | def rollback(repo, version) do
method seed (line 19) | def seed do
method setup (line 28) | def setup do
method repos (line 33) | defp repos do
FILE: apps/boruta_web/lib/boruta_web/repo.ex
class BorutaWeb.Repo (line 1) | defmodule BorutaWeb.Repo
FILE: apps/boruta_web/lib/boruta_web/router.ex
class BorutaWeb.Router (line 1) | defmodule BorutaWeb.Router
method handle_errors (line 97) | def handle_errors(conn, error) do
FILE: apps/boruta_web/lib/boruta_web/token.ex
class BorutaWeb.Token (line 1) | defmodule BorutaWeb.Token
method application_signer (line 6) | def application_signer do
FILE: apps/boruta_web/lib/boruta_web/views/error_helpers.ex
class BorutaWeb.ErrorHelpers (line 1) | defmodule BorutaWeb.ErrorHelpers
method error_tag (line 11) | def error_tag(form, field) do
method translate_error (line 20) | def translate_error({msg, opts}) do
FILE: apps/boruta_web/lib/boruta_web/views/error_view.ex
class BorutaWeb.ErrorView (line 1) | defmodule BorutaWeb.ErrorView
method template_not_found (line 13) | def template_not_found(template, _assigns) do
method render (line 17) | def render("error.json", %{error: error, message: message}) do
FILE: apps/boruta_web/lib/boruta_web/views/oauth_view.ex
class BorutaWeb.OauthView (line 1) | defmodule BorutaWeb.OauthView
method render (line 8) | def render("token.json", %{response: %Boruta.Oauth.TokenResponse{} = r...
method render (line 12) | def render("introspect.json", %{response: %Boruta.Oauth.IntrospectResp...
method render (line 16) | def render("introspect.json", %{response: %Boruta.Oauth.IntrospectResp...
method render (line 20) | def render("introspect.jwt", %{response: %Boruta.Oauth.IntrospectRespo...
method render (line 28) | def render("introspect.jwt", %{
method render (line 42) | def render("error.json", %{error: error, error_description: error_desc...
method render (line 49) | def render("well_known.json", %{routes: routes, scopes: scopes}) do
method render (line 99) | def render("openid_credential_issuer.json", %{routes: routes}) do
method render (line 113) | def render("credential.json", %{credential_response: credential_respon...
method render (line 123) | def render("defered_credential.json", %{credential_response: credentia...
method render (line 131) | def render("pushed_authorization_request.json", %{
FILE: apps/boruta_web/lib/boruta_web/views/openid_view.ex
class BorutaWeb.OpenidView (line 1) | defmodule BorutaWeb.OpenidView
method render (line 6) | def render("userinfo.json", %{response: response}) do
method render (line 10) | def render("jwks.json", %{keys: keys}) do
method render (line 16) | def render("jwk.json", %{client: %Boruta.Ecto.Client{id: client_id, pu...
method render (line 24) | def render("userinfo.jwt", %{response: response}) do
method render (line 28) | def render("show.json", %{client: client}) do
method render (line 32) | def render("client.json", %{client: client}) do
method render (line 40) | def render("registration_error.json", %{changeset: changeset}) do
method errors_full_message (line 47) | defp errors_full_message(changeset) do
FILE: apps/boruta_web/lib/mix/tasks/server.ex
class Mix.Tasks.Boruta.Server (line 1) | defmodule Mix.Tasks.Boruta.Server
method run (line 6) | def run(args) do
FILE: apps/boruta_web/mix.exs
class BorutaWeb.MixProject (line 1) | defmodule BorutaWeb.MixProject
method project (line 4) | def project do
method application (line 23) | def application do
method elixirc_paths (line 31) | defp elixirc_paths(:test), do: ["lib", "test/support"]
method elixirc_paths (line 32) | defp elixirc_paths(_), do: ["lib"]
method deps (line 37) | defp deps do
method aliases (line 67) | defp aliases do
FILE: apps/boruta_web/test/boruta_web/controllers/credential_controller_test.exs
class BorutaWeb.CredentialControllerTest (line 1) | defmodule BorutaWeb.CredentialControllerTest
method public_key_fixture (line 175) | def public_key_fixture do
method private_key_fixture (line 179) | def private_key_fixture do
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/authorization_code_test.exs
class BorutaWeb.Oauth.AuthorizationCodeTest (line 1) | defmodule BorutaWeb.Oauth.AuthorizationCodeTest
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/authorize_controller_test.exs
class BorutaWeb.AuthorizeControllerTest (line 1) | defmodule BorutaWeb.AuthorizeControllerTest
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/client_credentials_test.exs
class BorutaWeb.Oauth.ClientCredentialsTest (line 1) | defmodule BorutaWeb.Oauth.ClientCredentialsTest
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/direct_post_test.exs
class BorutaWeb.Integration.DirectPostTest (line 1) | defmodule BorutaWeb.Integration.DirectPostTest
method public_key_fixture (line 85) | def public_key_fixture do
method private_key_fixture (line 89) | def private_key_fixture do
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/implicit_test.exs
class BorutaWeb.Oauth.ImplicitTest (line 1) | defmodule BorutaWeb.Oauth.ImplicitTest
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/introspect_test.exs
class BorutaWeb.Oauth.IntrospectTest (line 1) | defmodule BorutaWeb.Oauth.IntrospectTest
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/openid_connect_test.exs
class BorutaWeb.Integration.OpenidConnectTest (line 1) | defmodule BorutaWeb.Integration.OpenidConnectTest
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/password_test.exs
class BorutaWeb.Oauth.PasswordTest (line 1) | defmodule BorutaWeb.Oauth.PasswordTest
FILE: apps/boruta_web/test/boruta_web/controllers/oauth/revoke_test.exs
class BorutaWeb.Oauth.RevokeTest (line 1) | defmodule BorutaWeb.Oauth.RevokeTest
FILE: apps/boruta_web/test/boruta_web/controllers/pushed_authorization_request_controller_test.exs
class BorutaWeb.Oauth.PushedAuthorizationRequestControllerTest (line 1) | defmodule BorutaWeb.Oauth.PushedAuthorizationRequestControllerTest
FILE: apps/boruta_web/test/boruta_web/plugs/rate_limit_test.exs
class BorutaWeb.Plugs.RateLimitTest (line 1) | defmodule BorutaWeb.Plugs.RateLimitTest
FILE: apps/boruta_web/test/boruta_web/views/error_view_test.exs
class BorutaWeb.ErrorViewTest (line 1) | defmodule BorutaWeb.ErrorViewTest
FILE: apps/boruta_web/test/boruta_web/views/layout_view_test.exs
class BorutaWeb.LayoutViewTest (line 1) | defmodule BorutaWeb.LayoutViewTest
FILE: apps/boruta_web/test/boruta_web/views/page_view_test.exs
class BorutaWeb.PageViewTest (line 1) | defmodule BorutaWeb.PageViewTest
FILE: apps/boruta_web/test/support/boruta_factory.ex
class Boruta.Factory (line 1) | defmodule Boruta.Factory
method client_factory (line 8) | def client_factory do
method scope_factory (line 21) | def scope_factory do
method token_factory (line 28) | def token_factory do
FILE: apps/boruta_web/test/support/boruta_identity_factory.ex
class BorutaIdentity.Factory (line 1) | defmodule BorutaIdentity.Factory
method user_factory (line 20) | def user_factory do
method internal_user_factory (line 28) | def internal_user_factory do
method consent_factory (line 36) | def consent_factory do
method client_identity_provider_factory (line 43) | def client_identity_provider_factory do
method identity_provider_factory (line 50) | def identity_provider_factory do
method backend_factory (line 57) | def backend_factory do
method template_factory (line 64) | def template_factory do
method new_registration_template_factory (line 71) | def new_registration_template_factory do
method error_template_factory (line 78) | def error_template_factory do
method role_factory (line 85) | def role_factory do
method role_scope_factory (line 91) | def role_scope_factory do
FILE: apps/boruta_web/test/support/conn_case.ex
class BorutaWeb.ConnCase (line 1) | defmodule BorutaWeb.ConnCase
FILE: mix.exs
class Boruta.Umbrella.MixProject (line 1) | defmodule Boruta.Umbrella.MixProject
method project (line 4) | def project do
method deps (line 57) | defp deps do
method aliases (line 64) | defp aliases do
Condensed preview — 669 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,800K chars).
[
{
"path": ".credo.exs",
"chars": 6712,
"preview": "# This file contains the configuration for Credo and you are probably reading\n# this after creating it with `mix credo.g"
},
{
"path": ".formatter.exs",
"chars": 72,
"preview": "[\n inputs: [\"mix.exs\", \"config/*.exs\"],\n subdirectories: [\"apps/*\"]\n]\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 768,
"preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
},
{
"path": ".github/workflows/deploy.yml",
"chars": 5452,
"preview": "name: Deployment\n\non:\n push:\n branches:\n - provider-policies-registration\n workflow_run:\n workflows:\n "
},
{
"path": ".github/workflows/elixir.yml",
"chars": 2404,
"preview": "name: Continuous Integration\n\non:\n push:\n branches:\n - master\n pull_request:\n branches:\n - master\n\njob"
},
{
"path": ".gitignore",
"chars": 196,
"preview": "/_build/\n/cover/\n/deps/\n/doc/\n/tmp/\n/log/\n/.fetch\nerl_crash.dump\n*.ez\n\n.env.sh\n.env\n\n*.swp\n*.swo\n*.orig\ntags*\n\napps/*/pr"
},
{
"path": ".gitlab-ci.yml",
"chars": 2728,
"preview": "stages:\n - test\n - build\n - deploy\n\nservices:\n - postgres:latest\n\n.elixir-task:\n image: elixir:1.12.1\n before_scri"
},
{
"path": ".tool-versions",
"chars": 52,
"preview": "nodejs 25.2.1\nerlang 25.3.2.21\nelixir 1.14.5-otp-25\n"
},
{
"path": "CHANGELOG.md",
"chars": 5828,
"preview": "# Changelog\n\n> Note that 0.X.X releases are reverved for the beta version of the server and may include breaking changes"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 6867,
"preview": "# Code of Conduct\n\n## 1. Why share this code of conduct?\n\nA code of conduct aims to set the frame of community interacti"
},
{
"path": "Dockerfile.admin",
"chars": 840,
"preview": "FROM node:25.2.1 AS assets\n\n# For packages not compatible with OpenSSL 3.0 https://nodejs.org/en/blog/release/v17.0.0/\nE"
},
{
"path": "Dockerfile.auth",
"chars": 919,
"preview": "FROM node:25.2.1 AS identity_assets\n\nARG BORUTA_OAUTH_BASE_URL\n\n# For packages not compatible with OpenSSL 3.0 https://n"
},
{
"path": "Dockerfile.full",
"chars": 1752,
"preview": "FROM node:25.2.1 AS admin_assets\n\n# For packages not compatible with OpenSSL 3.0 https://nodejs.org/en/blog/release/v17."
},
{
"path": "Dockerfile.gateway",
"chars": 907,
"preview": "FROM elixir:1.14-otp-25-alpine AS builder\n\nRUN apk --no-cache --update add build-base git\n\nENV MIX_ENV=prod\n\nRUN mix loc"
},
{
"path": "GENERAL_TERMS_AND_CONDITIONS.md",
"chars": 7188,
"preview": "### General Terms and Conditions for Boruta (Open Beta)\n\n#### **1. Introduction**\nWelcome to the open beta of Boruta, an"
},
{
"path": "LICENSE.md",
"chars": 11371,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 13599,
"preview": "\n\nboruta is a standalone authorization server that aims to implement OAuth 2.0 and"
},
{
"path": "ansible/.kube/kubeconfig-k8s-boruta.yaml",
"chars": 7871,
"preview": "$ANSIBLE_VAULT;1.1;AES256\n61666431343966366336333965363036373037353566316363333465633762663931623438373666\n6238346264616"
},
{
"path": "ansible/deploy.yml",
"chars": 14468,
"preview": "- hosts: localhost\n tasks:\n - name: Add stable bitnami repo\n kubernetes.core.helm_repository:\n name: bit"
},
{
"path": "ansible/hosts",
"chars": 18,
"preview": "[local]\nlocalhost\n"
},
{
"path": "ansible/inventories/gke",
"chars": 53,
"preview": "[gke]\nlocalhost\n\n[gke:vars]\nansible_connection=local\n"
},
{
"path": "ansible/inventories/local",
"chars": 57,
"preview": "[local]\nlocalhost\n\n[local:vars]\nansible_connection=local\n"
},
{
"path": "ansible/inventories/scaleway",
"chars": 63,
"preview": "[scaleway]\nlocalhost\n\n[scaleway:vars]\nansible_connection=local\n"
},
{
"path": "apps/boruta_admin/.formatter.exs",
"chars": 159,
"preview": "[\n import_deps: [:ecto, :phoenix],\n inputs: [\"*.{ex,exs}\", \"priv/*/seeds.exs\", \"{config,lib,test}/**/*.{ex,exs}\"],\n s"
},
{
"path": "apps/boruta_admin/.gitignore",
"chars": 893,
"preview": "# The directory Mix will write compiled artifacts to.\n/_build/\n\n# If you run \"mix test --cover\", coverage assets end up "
},
{
"path": "apps/boruta_admin/assets/.browserslistrc",
"chars": 21,
"preview": "> 1%\nlast 2 versions\n"
},
{
"path": "apps/boruta_admin/assets/.editorconfig",
"chars": 121,
"preview": "[*.{js,jsx,ts,tsx,vue}]\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\ninsert_final_newline = true"
},
{
"path": "apps/boruta_admin/assets/.eslintrc.js",
"chars": 510,
"preview": "module.exports = {\n root: true,\n env: {\n node: true\n },\n 'extends': [\n 'plugin:vue/essential',\n '@vue/stand"
},
{
"path": "apps/boruta_admin/assets/.gitignore",
"chars": 214,
"preview": ".DS_Store\nnode_modules\n/dist\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\nnpm-debug.log*\nyarn-debug.log*\nyarn"
},
{
"path": "apps/boruta_admin/assets/index.html",
"chars": 1133,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\"/>\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE"
},
{
"path": "apps/boruta_admin/assets/jsconfig.json",
"chars": 40,
"preview": "{\n \"include\": [\n \"./src/**/*\"\n ]\n}\n"
},
{
"path": "apps/boruta_admin/assets/package.json",
"chars": 1289,
"preview": "{\n \"name\": \"boruta-admin\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"serve\": \"vite\",\n \"build\": \"v"
},
{
"path": "apps/boruta_admin/assets/postcss.config.js",
"chars": 59,
"preview": "module.exports = {\n plugins: {\n autoprefixer: {}\n }\n}\n"
},
{
"path": "apps/boruta_admin/assets/src/App.vue",
"chars": 218,
"preview": "<template>\n <router-view></router-view>\n</template>\n\n<script>\nexport default {\n name: 'App'\n}\n</script>\n\n<style lang=\""
},
{
"path": "apps/boruta_admin/assets/src/components/Breadcrumb.vue",
"chars": 3881,
"preview": "<template>\n <div class=\"ui breadcrumb\">\n <span v-for=\"(item, index) in items\" :key=\"item.path\">\n <span v-if=\"in"
},
{
"path": "apps/boruta_admin/assets/src/components/Feedback.vue",
"chars": 2752,
"preview": "<template>\n <div class=\"feedback\">\n <div @click=\"toggle()\" class=\"ui yellow feedback button\">Feedback</div>\n <div"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/BackendForm.vue",
"chars": 26331,
"preview": "<template>\n <div class=\"ui backend-form segment\">\n <FormErrors :errors=\"backend.errors\" v-if=\"backend.errors\" />\n "
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/ClientForm.vue",
"chars": 17990,
"preview": "<template>\n <div class=\"ui client-form segment\">\n <FormErrors v-if=\"client.errors\" :errors=\"client.errors\" />\n <f"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/FormErrors.vue",
"chars": 1699,
"preview": "<template>\n <div @click=\"hide()\" class=\"form-errors ui error message\" v-if=\"show\" :class=\"{ 'inline': inline }\">\n <d"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/GatewayScopesField.vue",
"chars": 2243,
"preview": "<template>\n <div class=\"field edit-scopes\">\n <div v-for=\"(authorizedScope, index) in currentScopes\" class=\"field\" :k"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/IdentityProviderField.vue",
"chars": 1170,
"preview": "<template>\n <div class=\"field\">\n <label>identity provider</label>\n <select v-model=\"currentIdentityProviderId\">\n "
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/IdentityProviderForm.vue",
"chars": 13721,
"preview": "<template>\n <div class=\"ui identity-provider-form segment\">\n <FormErrors v-if=\"identityProvider.errors\" :errors=\"ide"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/OrganizationForm.vue",
"chars": 875,
"preview": "<template>\n <div class=\"ui organization-form segment\">\n <FormErrors :errors=\"organization.errors\" v-if=\"organization"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/OrganizationsField.vue",
"chars": 1805,
"preview": "<template>\n <div class=\"field edit-organizations\">\n <div v-for=\"(organization, index) in currentOrganizations\" class"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/RoleForm.vue",
"chars": 1645,
"preview": "<template>\n <div class=\"role-form\">\n <div class=\"ui segment\">\n <FormErrors v-if=\"role.errors\" :errors=\"role.err"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/RolesField.vue",
"chars": 1479,
"preview": "<template>\n <div class=\"field edit-roles\">\n <div v-for=\"(role, index) in currentRoles\" class=\"field\" :key=\"index\">\n "
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/ScopesField.vue",
"chars": 1596,
"preview": "<template>\n <div class=\"field edit-scopes\">\n <div v-for=\"(authorizedScope, index) in currentScopes\" class=\"field\" :k"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/ScopesFieldByName.vue",
"chars": 984,
"preview": "<template>\n <div class=\"field edit-scopes\">\n <div v-for=\"(scope, index) in currentScopes\" class=\"field\" :key=\"index\""
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/TextEditor.vue",
"chars": 1648,
"preview": "<template>\n <div class=\"text-editor\">\n <div class=\"editor lang-markup\" ref=\"editor\"></div>\n </div>\n</template>\n\n<sc"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/UpstreamForm.vue",
"chars": 9276,
"preview": "<template>\n <div class=\"ui upstream-form segment\">\n <FormErrors v-if=\"upstream.errors\" :errors=\"upstream.errors\" />\n"
},
{
"path": "apps/boruta_admin/assets/src/components/Forms/UserForm.vue",
"chars": 6703,
"preview": "<template>\n <div class=\"ui user-form segment\">\n <FormErrors :errors=\"user.errors\" v-if=\"user.errors\" />\n <form cl"
},
{
"path": "apps/boruta_admin/assets/src/components/Header.vue",
"chars": 1735,
"preview": "<template>\n <div class=\"header\" :class=\"{ 'dark': darkMode }\">\n <div class=\"ui main menu\" :class=\"{ 'inverted': dark"
},
{
"path": "apps/boruta_admin/assets/src/components/Toaster.vue",
"chars": 1093,
"preview": "<template>\n <div @mouseover=\"activate()\" @mouseleave=\"deactivate()\" class=\"ui icon hidden floating message\" :class=\"typ"
},
{
"path": "apps/boruta_admin/assets/src/components/VerifiableCredentialClaim.vue",
"chars": 4230,
"preview": "<template>\n <div class=\"ui claim segment\">\n <i class=\"ui large close icon\" @click=\"deleteVerifiableCredentialClaim(c"
},
{
"path": "apps/boruta_admin/assets/src/main.js",
"chars": 197,
"preview": "import { createApp } from 'vue'\nimport App from './App.vue'\nimport router from './router'\nimport store from './store'\n\nc"
},
{
"path": "apps/boruta_admin/assets/src/models/backend.model.js",
"chars": 12342,
"preview": "import axios from \"axios\";\nimport { addClientErrorInterceptor } from \"./utils\";\nimport Role from './role.model'\n\nconst d"
},
{
"path": "apps/boruta_admin/assets/src/models/business-log-stats.model.js",
"chars": 1870,
"preview": "import axios from 'axios'\nimport moment from 'moment'\nimport { addClientErrorInterceptor } from './utils'\n\nconst default"
},
{
"path": "apps/boruta_admin/assets/src/models/client.model.js",
"chars": 10418,
"preview": "import axios from 'axios'\nimport Scope from './scope.model'\nimport IdentityProvider from './identity-provider.model'\nimp"
},
{
"path": "apps/boruta_admin/assets/src/models/email-template.model.js",
"chars": 2483,
"preview": "import axios from 'axios'\nimport { addClientErrorInterceptor } from './utils'\n\nconst defaults = {\n id: null,\n txt_cont"
},
{
"path": "apps/boruta_admin/assets/src/models/error-template.model.js",
"chars": 2592,
"preview": "import axios from 'axios'\nimport { addClientErrorInterceptor } from './utils'\n\nconst templates = [\n { type: 400, name: "
},
{
"path": "apps/boruta_admin/assets/src/models/identity-provider.model.js",
"chars": 3781,
"preview": "import axios from 'axios'\nimport { addClientErrorInterceptor } from './utils'\nimport Backend from './backend.model'\n\ncon"
},
{
"path": "apps/boruta_admin/assets/src/models/key-pair.model.js",
"chars": 2390,
"preview": "import axios from 'axios'\nimport { addClientErrorInterceptor } from './utils'\n\nconst defaults = {\n}\n\nconst assign = {\n "
},
{
"path": "apps/boruta_admin/assets/src/models/organization.model.js",
"chars": 2544,
"preview": "import axios from 'axios'\nimport Scope from './scope.model'\nimport Role from './role.model'\nimport Backend from './backe"
},
{
"path": "apps/boruta_admin/assets/src/models/request-log-stats.model.js",
"chars": 1822,
"preview": "import axios from 'axios'\nimport moment from 'moment'\nimport { addClientErrorInterceptor } from './utils'\n\nconst default"
},
{
"path": "apps/boruta_admin/assets/src/models/role.model.js",
"chars": 2305,
"preview": "import axios from 'axios'\nimport Scope from './scope.model'\nimport { addClientErrorInterceptor } from './utils'\n\nconst d"
},
{
"path": "apps/boruta_admin/assets/src/models/scope.model.js",
"chars": 2378,
"preview": "import axios from 'axios'\nimport { addClientErrorInterceptor } from './utils'\n\nconst defaults = {\n name: '',\n edit: fa"
},
{
"path": "apps/boruta_admin/assets/src/models/template.model.js",
"chars": 2422,
"preview": "import axios from 'axios'\nimport { addClientErrorInterceptor } from './utils'\n\nconst defaults = {\n id: null,\n content:"
},
{
"path": "apps/boruta_admin/assets/src/models/upstream.model.js",
"chars": 5414,
"preview": "import axios from 'axios'\nimport Scope from './scope.model'\nimport { addClientErrorInterceptor } from './utils'\n\nconst d"
},
{
"path": "apps/boruta_admin/assets/src/models/user.model.js",
"chars": 6035,
"preview": "import axios from 'axios'\nimport Scope from './scope.model'\nimport Role from './role.model'\nimport Organization from './"
},
{
"path": "apps/boruta_admin/assets/src/models/utils.js",
"chars": 1091,
"preview": "import axios from 'axios'\nimport router from '../router'\nimport oauth from '../services/oauth.service'\n\nexport function "
},
{
"path": "apps/boruta_admin/assets/src/router.js",
"chars": 19519,
"preview": "import { createWebHistory, createRouter } from \"vue-router\";\nimport oauth from \"./services/oauth.service\";\n\nimport Main "
},
{
"path": "apps/boruta_admin/assets/src/services/configuration-file.service.js",
"chars": 1334,
"preview": "import axios from 'axios'\nimport { addClientErrorInterceptor } from \"../models/utils\";\n\nexport default class Configurati"
},
{
"path": "apps/boruta_admin/assets/src/services/oauth.service.js",
"chars": 3206,
"preview": "import decode from 'jwt-decode'\nimport { BorutaOauth } from 'boruta-client'\n\nclass Oauth {\n constructor () {\n const "
},
{
"path": "apps/boruta_admin/assets/src/store.js",
"chars": 531,
"preview": "import { createStore } from 'vuex'\n\nimport oauth from './services/oauth.service'\n\nexport default createStore({\n state: "
},
{
"path": "apps/boruta_admin/assets/src/views/BadRequest.vue",
"chars": 405,
"preview": "<template>\n <div class=\"bad-request\">\n <div class=\"ui container\">\n <div class=\"ui placeholder segment\">\n "
},
{
"path": "apps/boruta_admin/assets/src/views/Clients/Client.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Clients/ClientList.vue",
"chars": 4586,
"preview": "<template>\n <div class=\"client-list\">\n <Toaster :active=\"deleted\" message=\"Client has been deleted\" type=\"warning\" /"
},
{
"path": "apps/boruta_admin/assets/src/views/Clients/EditClient.vue",
"chars": 2222,
"preview": "<template>\n <div class=\"edit-client\">\n <Toaster :active=\"success\" message=\"Client has been updated\" type=\"success\" /"
},
{
"path": "apps/boruta_admin/assets/src/views/Clients/KeyPairList.vue",
"chars": 3030,
"preview": "<template>\n <div class=\"key-pair-list\">\n <Toaster :active=\"created\" message=\"Key pair has been created\" type=\"succes"
},
{
"path": "apps/boruta_admin/assets/src/views/Clients/NewClient.vue",
"chars": 1200,
"preview": "<template>\n <div class=\"new-client\">\n <div class=\"container\">\n <div class=\"ui stackable grid\">\n <div cla"
},
{
"path": "apps/boruta_admin/assets/src/views/Clients.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Configuration/ConfigurationFileUpload.vue",
"chars": 3135,
"preview": "<template>\n <div class=\"configuration-file-upload\">\n <div class=\"container\">\n <div class=\"ui stackable grid\">\n "
},
{
"path": "apps/boruta_admin/assets/src/views/Configuration/EditBadRequestTemplate.vue",
"chars": 1768,
"preview": "<template>\n <div class=\"container edit-bad-request-template\">\n <Toaster :active=\"success\" message=\"Template has been"
},
{
"path": "apps/boruta_admin/assets/src/views/Configuration/EditForbiddenTemplate.vue",
"chars": 1762,
"preview": "<template>\n <div class=\"container edit-forbidden-template\">\n <Toaster :active=\"success\" message=\"Template has been u"
},
{
"path": "apps/boruta_admin/assets/src/views/Configuration/EditInternalServerErrorTemplate.vue",
"chars": 1786,
"preview": "<template>\n <div class=\"container edit-internal-server-error-template\">\n <Toaster :active=\"success\" message=\"Templat"
},
{
"path": "apps/boruta_admin/assets/src/views/Configuration/EditNotFoundTemplate.vue",
"chars": 1762,
"preview": "<template>\n <div class=\"container edit-not-found-template\">\n <Toaster :active=\"success\" message=\"Template has been u"
},
{
"path": "apps/boruta_admin/assets/src/views/Configuration/ErrorTemplateList.vue",
"chars": 986,
"preview": "<template>\n <div class=\"error-template-list\">\n <div class=\"container\">\n <div class=\"ui info message\">\n H"
},
{
"path": "apps/boruta_admin/assets/src/views/Configuration.vue",
"chars": 53,
"preview": "<template>\n <router-view></router-view>\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Dashboard/BusinessEvents.vue",
"chars": 16021,
"preview": "<template>\n <div class=\"dashboard\">\n <div class=\"container\">\n <div class=\"ui error message\" v-if=\"error\">\n "
},
{
"path": "apps/boruta_admin/assets/src/views/Dashboard/Requests.vue",
"chars": 11970,
"preview": "<template>\n <div class=\"dashboard\">\n <div class=\"container\">\n <div class=\"ui error message\" v-if=\"error\">\n "
},
{
"path": "apps/boruta_admin/assets/src/views/Dashboard.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Home.vue",
"chars": 6142,
"preview": "<template>\n <div class=\"home\">\n <div class=\"ui container\">\n <div class=\"ui center aligned segment\">\n <h2"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/BackendList.vue",
"chars": 2857,
"preview": "<template>\n <div class=\"backend-list\">\n <Toaster :active=\"deleted\" message=\"backend has been deleted\" type=\"warning\""
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/Backends/Backend.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/Backends/EditConfirmationInstructionsEmailTemplate.vue",
"chars": 2371,
"preview": "<template>\n <div class=\"container edit-confirmation-instructions-email-template\">\n <Toaster :active=\"success\" messag"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/Backends/EditResetPasswordInstructionsEmailTemplate.vue",
"chars": 2377,
"preview": "<template>\n <div class=\"container edit-reset-password-instructions-email-template\">\n <Toaster :active=\"success\" mess"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/Backends/EditTxCodeEmailTemplate.vue",
"chars": 2317,
"preview": "<template>\n <div class=\"container edit-tx-code-email-template\">\n <Toaster :active=\"success\" message=\"Template has be"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/Backends.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditBackend.vue",
"chars": 2016,
"preview": "<template>\n <div class=\"edit-backend\">\n <Toaster :active=\"success\" message=\"backend has been updated\" type=\"success\""
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditCredentialOfferTemplate.vue",
"chars": 2151,
"preview": "<template>\n <div class=\"container edit-credential-offer-template\">\n <Toaster :active=\"success\" message=\"Template has"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditCrossDevicePresentationTemplate.vue",
"chars": 2187,
"preview": "<template>\n <div class=\"container edit-cross-device-presentation-template\">\n <Toaster :active=\"success\" message=\"Tem"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditEditResetPasswordTemplate.vue",
"chars": 2163,
"preview": "<template>\n <div class=\"container edit-edit-reset-password-template\">\n <Toaster :active=\"success\" message=\"Template "
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditEditUserTemplate.vue",
"chars": 2123,
"preview": "<template>\n <div class=\"container edit-edit-user-template\">\n <Toaster :active=\"success\" message=\"Template has been u"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditIdentityProvider.vue",
"chars": 2396,
"preview": "<template>\n <div class=\"edit-identity-provider\">\n <Toaster :active=\"success\" message=\"identity provider has been upd"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditLayoutTemplate.vue",
"chars": 2111,
"preview": "<template>\n <div class=\"container edit-layout-template\">\n <Toaster :active=\"success\" message=\"Template has been upda"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditNewChooseSessionTemplate.vue",
"chars": 2128,
"preview": "<template>\n <div class=\"container choose-session-template\">\n <Toaster :active=\"success\" message=\"Template has been u"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditNewConfirmationTemplate.vue",
"chars": 2165,
"preview": "<template>\n <div class=\"container edit-new-confirmation-template\">\n <Toaster :active=\"success\" message=\"Template has"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditNewConsentTemplate.vue",
"chars": 2119,
"preview": "<template>\n <div class=\"container edit-consent-template\">\n <Toaster :active=\"success\" message=\"Template has been upd"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditNewResetPasswordTemplate.vue",
"chars": 2159,
"preview": "<template>\n <div class=\"container edit-new-reset-password-template\">\n <Toaster :active=\"success\" message=\"Template h"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditOrganization.vue",
"chars": 1790,
"preview": "<template>\n <div class=\"edit-organization\">\n <Toaster :active=\"success\" message=\"Organization has been updated\" type"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditRegistrationTemplate.vue",
"chars": 2139,
"preview": "<template>\n <div class=\"container edit-registration-template\">\n <Toaster :active=\"success\" message=\"Template has bee"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditSessionTemplate.vue",
"chars": 2119,
"preview": "<template>\n <div class=\"container edit-session-template\">\n <Toaster :active=\"success\" message=\"Template has been upd"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditTotpAuthenticationTemplate.vue",
"chars": 2167,
"preview": "<template>\n <div class=\"container edit-totp-authentication-template\">\n <Toaster :active=\"success\" message=\"Template "
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditTotpRegistrationTemplate.vue",
"chars": 2159,
"preview": "<template>\n <div class=\"container edit-totp-registration-template\">\n <Toaster :active=\"success\" message=\"Template ha"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditUser.vue",
"chars": 2605,
"preview": "<template>\n <div class=\"edit-user\">\n <Toaster :active=\"success\" message=\"User has been updated\" type=\"success\" />\n "
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditWebauthnAuthenticationTemplate.vue",
"chars": 2183,
"preview": "<template>\n <div class=\"container edit-webauthn-authentication-template\">\n <Toaster :active=\"success\" message=\"Templ"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/EditWebauthnRegistrationTemplate.vue",
"chars": 2175,
"preview": "<template>\n <div class=\"container edit-webauthn-registration-template\">\n <Toaster :active=\"success\" message=\"Templat"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/IdentityProvider.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/IdentityProviderList.vue",
"chars": 3101,
"preview": "<template>\n <div class=\"identityProvider-list\">\n <Toaster :active=\"deleted\" message=\"identity provider has been dele"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/NewBackend.vue",
"chars": 809,
"preview": "<template>\n <div class=\"new-backend\">\n <div class=\"ui container\">\n <BackendForm :backend=\"backend\" @submit=\"cre"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/NewIdentityProvider.vue",
"chars": 1217,
"preview": "<template>\n <div class=\"new-identity-provider\">\n <div class=\"ui container\">\n <IdentityProviderForm :identityPro"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/NewOrganization.vue",
"chars": 1026,
"preview": "<template>\n <div class=\"new-organization\">\n <Toaster :active=\"success\" message=\"Organization has been created\" type="
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/NewUser.vue",
"chars": 1150,
"preview": "<template>\n <div class=\"new-user\">\n <div class=\"container\">\n <div class=\"ui stackable grid\">\n <div class"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/OrganizationList.vue",
"chars": 4904,
"preview": "<template>\n <div class=\"organization-list\">\n <Toaster :active=\"deleted\" message=\"Organization has been deleted\" type"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/Organizations.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/UserImport.vue",
"chars": 5387,
"preview": "<template>\n <div class=\"user-import\">\n <div class=\"container\">\n <div class=\"ui segment\">\n <FormErrors :e"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/UserList.vue",
"chars": 5932,
"preview": "<template>\n <div class=\"user-list\">\n <Toaster :active=\"deleted\" message=\"User has been deleted\" type=\"warning\" />\n "
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders/Users.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/IdentityProviders.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Layouts/Main.vue",
"chars": 18963,
"preview": "<template>\n <div id=\"app\" :class=\"{ 'dark': currentMode }\">\n <Header ref=\"header\" :darkMode=\"currentMode\" />\n <di"
},
{
"path": "apps/boruta_admin/assets/src/views/NotFound.vue",
"chars": 414,
"preview": "<template>\n <div class=\"not-found\">\n <div class=\"ui container\">\n <div class=\"ui placeholder segment\">\n <"
},
{
"path": "apps/boruta_admin/assets/src/views/OauthCallback.vue",
"chars": 457,
"preview": "<template>\n <div class=\"oauth-callback\">\n <div class=\"ui container\">\n <div class=\"ui loading placeholder segmen"
},
{
"path": "apps/boruta_admin/assets/src/views/Roles/EditRole.vue",
"chars": 1213,
"preview": "<template>\n <div class=\"edit-role\">\n <Toaster :active=\"success\" message=\"Role has been updated\" type=\"success\" />\n "
},
{
"path": "apps/boruta_admin/assets/src/views/Roles/NewRole.vue",
"chars": 940,
"preview": "<template>\n <div class=\"new-role\">\n <div class=\"ui container\">\n <RoleForm :role=\"role\" @submit=\"createRole()\" @"
},
{
"path": "apps/boruta_admin/assets/src/views/Roles/Role.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Roles/RoleList.vue",
"chars": 2422,
"preview": "<template>\n <div class=\"role-list\">\n <Toaster :active=\"deleted\" message=\"Role has been deleted\" type=\"warning\" />\n "
},
{
"path": "apps/boruta_admin/assets/src/views/Roles.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Scopes/ScopeList.vue",
"chars": 5577,
"preview": "<template>\n <div id=\"scope-list\">\n <Toaster :active=\"saved\" message=\"Scope has been saved\" type=\"success\" />\n <To"
},
{
"path": "apps/boruta_admin/assets/src/views/Scopes.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Upstreams/EditUpstream.vue",
"chars": 1680,
"preview": "<template>\n <div class=\"edit-upstream\">\n <Toaster :active=\"success\" message=\"Upstream has been updated\" type=\"succes"
},
{
"path": "apps/boruta_admin/assets/src/views/Upstreams/NewUpstream.vue",
"chars": 1335,
"preview": "<template>\n <div class=\"new-upstream\">\n <div class=\"container\">\n <div class=\"ui stackable grid\">\n <div c"
},
{
"path": "apps/boruta_admin/assets/src/views/Upstreams/Upstream.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/src/views/Upstreams/UpstreamList.vue",
"chars": 2965,
"preview": "<template>\n <div class=\"upstream-list\">\n <Toaster :active=\"deleted\" message=\"Upstream has been deleted\" type=\"warnin"
},
{
"path": "apps/boruta_admin/assets/src/views/Upstreams.vue",
"chars": 41,
"preview": "<template>\n <router-view />\n</template>\n"
},
{
"path": "apps/boruta_admin/assets/tests/unit/.eslintrc.js",
"chars": 50,
"preview": "module.exports = {\n env: {\n mocha: true\n }\n}\n"
},
{
"path": "apps/boruta_admin/assets/vite.config.js",
"chars": 1192,
"preview": "import { defineConfig } from 'vite'\nimport { viteSingleFile } from 'vite-plugin-singlefile'\nimport vue from '@vitejs/plu"
},
{
"path": "apps/boruta_admin/config/config.exs",
"chars": 860,
"preview": "import Config\n\nconfig :boruta_admin,\n ecto_repos: [\n BorutaAdmin.Repo,\n BorutaAuth.Repo,\n BorutaIdentity.Repo,"
},
{
"path": "apps/boruta_admin/config/dev.exs",
"chars": 1372,
"preview": "import Config\n\nconfig :boruta_admin, BorutaAdmin.Repo,\n username: System.get_env(\"POSTGRES_USER\") || \"postgres\",\n pass"
},
{
"path": "apps/boruta_admin/config/prod.exs",
"chars": 14,
"preview": "import Config\n"
},
{
"path": "apps/boruta_admin/config/test.exs",
"chars": 2637,
"preview": "import Config\n\n# Configure your database\n#\n# The MIX_TEST_PARTITION environment variable can be used\n# to provide built-"
},
{
"path": "apps/boruta_admin/lib/boruta_admin/application.ex",
"chars": 2324,
"preview": "defmodule BorutaAdmin.Application do\n @moduledoc false\n\n require Logger\n\n use Application\n\n def start(_type, _args) "
},
{
"path": "apps/boruta_admin/lib/boruta_admin/configuration_loader/schema.ex",
"chars": 13139,
"preview": "defmodule BorutaAdmin.ConfigurationLoader.Schema do\n @moduledoc false\n\n alias ExJsonSchema.Schema\n\n def gateway do\n "
},
{
"path": "apps/boruta_admin/lib/boruta_admin/configuration_loader.ex",
"chars": 11440,
"preview": "defmodule BorutaAdmin.ConfigurationLoader do\n @moduledoc false\n\n alias Boruta.Ecto.Admin\n alias BorutaAdmin.Configura"
},
{
"path": "apps/boruta_admin/lib/boruta_admin/configurations/configuration.ex",
"chars": 700,
"preview": "defmodule BorutaAdmin.Configurations.Configuration do\n @moduledoc false\n\n use Ecto.Schema\n import Ecto.Changeset\n\n @"
},
{
"path": "apps/boruta_admin/lib/boruta_admin/configurations.ex",
"chars": 645,
"preview": "defmodule BorutaAdmin.Configurations do\n @moduledoc false\n\n alias BorutaAdmin.Configurations.Configuration\n alias Bor"
},
{
"path": "apps/boruta_admin/lib/boruta_admin/logs.ex",
"chars": 10360,
"preview": "defmodule BorutaAdmin.Logs.FileTooLargeError do\n @enforce_keys [:message]\n defexception [:message, plug_status: 422]\n\n"
},
{
"path": "apps/boruta_admin/lib/boruta_admin/release.ex",
"chars": 291,
"preview": "defmodule BorutaAdmin.Release do\n @moduledoc false\n\n def load_configuration do\n Application.ensure_all_started(:bor"
},
{
"path": "apps/boruta_admin/lib/boruta_admin/repo.ex",
"chars": 115,
"preview": "defmodule BorutaAdmin.Repo do\n use Ecto.Repo,\n otp_app: :boruta_admin,\n adapter: Ecto.Adapters.Postgres\nend\n"
},
{
"path": "apps/boruta_admin/lib/boruta_admin.ex",
"chars": 259,
"preview": "defmodule BorutaAdmin do\n @moduledoc \"\"\"\n BorutaAdmin keeps the contexts that define your domain\n and business logic."
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/backend_controller.ex",
"chars": 3102,
"preview": "defmodule BorutaAdminWeb.BackendController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorization,\n"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/boruta/client_controller.ex",
"chars": 3671,
"preview": "defmodule BorutaAdminWeb.ClientController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorization,\n "
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/boruta/scope_controller.ex",
"chars": 2122,
"preview": "defmodule BorutaAdminWeb.ScopeController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorization,\n "
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/configuration_controller.ex",
"chars": 3570,
"preview": "defmodule BorutaAdminWeb.ConfigurationController do\n use BorutaAdminWeb, :controller\n\n import Boruta.Config, only: [is"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/fallback_controller.ex",
"chars": 1353,
"preview": "defmodule BorutaAdminWeb.FallbackController do\n @moduledoc \"\"\"\n Translates controller action results into valid `Plug."
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/identity_provider_controller.ex",
"chars": 3311,
"preview": "defmodule BorutaAdminWeb.IdentityProviderController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Author"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/key_pair_controller.ex",
"chars": 1604,
"preview": "defmodule BorutaAdminWeb.KeyPairController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorization,\n"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/logs_controller.ex",
"chars": 1007,
"preview": "defmodule BorutaAdminWeb.LogsController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorization,\n "
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/organization_controller.ex",
"chars": 2353,
"preview": "defmodule BorutaAdminWeb.OrganizationController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorizat"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/page_controller.ex",
"chars": 180,
"preview": "defmodule BorutaAdminWeb.PageController do\n use BorutaAdminWeb, :controller\n\n def index(conn, _params) do\n conn\n "
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/role_controller.ex",
"chars": 1395,
"preview": "defmodule BorutaAdminWeb.RoleController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorization,\n "
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/upstream_controller.ex",
"chars": 1726,
"preview": "defmodule BorutaAdminWeb.UpstreamController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorization,"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/controllers/user_controller.ex",
"chars": 4593,
"preview": "defmodule BorutaAdminWeb.UserController do\n use BorutaAdminWeb, :controller\n\n import BorutaAdminWeb.Authorization,\n "
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/endpoint.ex",
"chars": 1074,
"preview": "defmodule BorutaAdminWeb.Endpoint do\n use Phoenix.Endpoint, otp_app: :boruta_admin\n\n # sets the same session as :borut"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/gettext.ex",
"chars": 732,
"preview": "defmodule BorutaAdminWeb.Gettext do\n @moduledoc \"\"\"\n A module providing Internationalization with a gettext-based API."
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/plugs/authorization.ex",
"chars": 4119,
"preview": "defmodule BorutaAdminWeb.Authorization do\n @moduledoc false\n @dialyzer {:no_unused, {:maybe_validate_user, 1}}\n\n @beh"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/plugs/logger.ex",
"chars": 1416,
"preview": "defmodule BorutaAdminWeb.Logger do\n @moduledoc false\n\n require Logger\n alias Plug.Conn\n @behaviour Plug\n\n @impl tru"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/router.ex",
"chars": 3679,
"preview": "defmodule BorutaAdminWeb.Router do\n use BorutaAdminWeb, :router\n use Plug.ErrorHandler\n\n alias Plug.Conn.Status\n\n im"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/telemetry.ex",
"chars": 1872,
"preview": "defmodule BorutaAdminWeb.Telemetry do\n @moduledoc false\n\n use Supervisor\n import Telemetry.Metrics\n\n def start_link("
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/templates/error/404.html.eex",
"chars": 862,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\"/>\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/templates/error/500.html.eex",
"chars": 863,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\"/>\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/templates/page/admin.html.eex",
"chars": 1338,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\"/>\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/backend_view.ex",
"chars": 2161,
"preview": "defmodule BorutaAdminWeb.BackendView do\n use BorutaAdminWeb, :view\n\n alias BorutaAdminWeb.BackendView\n alias BorutaId"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/changeset_view.ex",
"chars": 558,
"preview": "defmodule BorutaAdminWeb.ChangesetView do\n use BorutaWeb, :view\n\n @doc \"\"\"\n Traverses and translates changeset errors"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/client_view.ex",
"chars": 2318,
"preview": "defmodule BorutaAdminWeb.ClientView do\n use BorutaAdminWeb, :view\n\n alias BorutaAdminWeb.ClientView\n alias BorutaIden"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/configuration_view.ex",
"chars": 1106,
"preview": "defmodule BorutaAdminWeb.ConfigurationView do\n use BorutaAdminWeb, :view\n\n alias BorutaAdminWeb.ChangesetView\n\n def r"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/error_helpers.ex",
"chars": 771,
"preview": "defmodule BorutaAdminWeb.ErrorHelpers do\n @moduledoc \"\"\"\n Conveniences for translating and building error messages.\n "
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/error_view.ex",
"chars": 1378,
"preview": "defmodule BorutaAdminWeb.ErrorView do\n use BorutaAdminWeb, :view\n\n def render(\"400.json\", _assigns) do\n %{\n co"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/identity_provider_view.ex",
"chars": 1667,
"preview": "defmodule BorutaAdminWeb.IdentityProviderView do\n use BorutaAdminWeb, :view\n\n alias BorutaAdminWeb.BackendView\n\n def "
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/key_pair_view.ex",
"chars": 522,
"preview": "defmodule BorutaAdminWeb.KeyPairView do\n use BorutaAdminWeb, :view\n alias BorutaAdminWeb.KeyPairView\n\n def render(\"in"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/logs_view.ex",
"chars": 133,
"preview": "defmodule BorutaAdminWeb.LogsView do\n use BorutaAdminWeb, :view\n\n def render(\"index.json\", %{stats: stats}) do\n sta"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/organization_view.ex",
"chars": 881,
"preview": "defmodule BorutaAdminWeb.OrganizationView do\n use BorutaAdminWeb, :view\n\n alias BorutaAdminWeb.OrganizationView\n\n def"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/page_view.ex",
"chars": 69,
"preview": "defmodule BorutaAdminWeb.PageView do\n use BorutaAdminWeb, :view\nend\n"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/role_view.ex",
"chars": 596,
"preview": "defmodule BorutaAdminWeb.RoleView do\n use BorutaAdminWeb, :view\n alias BorutaAdminWeb.RoleView\n\n def render(\"index.js"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/scope_view.ex",
"chars": 478,
"preview": "defmodule BorutaAdminWeb.ScopeView do\n use BorutaAdminWeb, :view\n alias BorutaAdminWeb.ScopeView\n\n def render(\"index."
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/upstream_view.ex",
"chars": 1513,
"preview": "defmodule BorutaAdminWeb.UpstreamView do\n use BorutaAdminWeb, :view\n alias BorutaAdminWeb.UpstreamView\n\n def render(\""
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web/views/user_view.ex",
"chars": 2343,
"preview": "defmodule BorutaAdminWeb.UserView do\n use BorutaAdminWeb, :view\n\n alias BorutaAdminWeb.BackendView\n alias BorutaAdmin"
},
{
"path": "apps/boruta_admin/lib/boruta_admin_web.ex",
"chars": 1958,
"preview": "defmodule BorutaAdminWeb do\n @moduledoc \"\"\"\n The entrypoint for defining your web interface, such\n as controllers, vi"
},
{
"path": "apps/boruta_admin/mix.exs",
"chars": 2290,
"preview": "defmodule BorutaAdmin.MixProject do\n use Mix.Project\n\n def project do\n [\n app: :boruta_admin,\n version: \""
},
{
"path": "apps/boruta_admin/priv/examples/configuration.yml",
"chars": 2220,
"preview": "# Example configuration file\n---\nversion: \"1.0\"\nconfiguration:\n backend:\n - id: 00000000-0000-0000-0000-000000000001"
},
{
"path": "apps/boruta_admin/priv/gettext/en/LC_MESSAGES/errors.po",
"chars": 2197,
"preview": "## `msgid`s in this file come from POT (.pot) files.\n##\n## Do not add, change, or remove `msgid`s manually here as\n## th"
}
]
// ... and 469 more files (download for full content)
About this extraction
This page contains the full source code of the malach-it/boruta-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 669 files (1.6 MB), approximately 430.4k tokens, and a symbol index with 1748 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.