Compare commits

..

420 Commits

Author SHA1 Message Date
4b33971155 release: 2021.3.4 2021-03-16 19:17:50 +01:00
9e71287c25 Merge branch 'next' into version-2021.3 2021-03-16 19:12:55 +01:00
9784c6c828 tests/e2e: fix checks for ak-sidebar since ak-interface uses shadowdom now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 18:38:17 +01:00
732b6a3556 root: fix typo in bumpversion
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:45:56 +01:00
dc1e17ba0c Merge branch 'master' into version-2021.3 2021-03-16 17:38:39 +01:00
f05d5973af root: fix typo in bumpversion
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:38:34 +01:00
deb48487f3 root: fix typo in bumpversion
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:38:01 +01:00
78f3abc64f web: use sections in sidebar, adjust colouring
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:34:19 +01:00
e45bc3834a web: use ShadowDom for all elements, embed smaller CSS in skeleton
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:24:02 +01:00
0d9db1b6f2 web: use chunking for vendor and api
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:00:02 +01:00
ce555aa5e9 root: fix hash for docker build
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 16:45:53 +01:00
07ca82e599 admin: include git build hash in gh-* tags and show build hash in admin overview
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 14:42:01 +01:00
a9339589bb web: fix outpost health display
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 14:02:50 +01:00
c8ed650f1c web: fix system task index
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 14:02:04 +01:00
cd78d8d3fa build(deps-dev): bump @typescript-eslint/parser in /web (#640)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.17.0 to 4.18.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.18.0/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-16 12:09:00 +01:00
7fdc935fb9 build(deps-dev): bump @typescript-eslint/eslint-plugin in /web (#641)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.17.0 to 4.18.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.18.0/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-16 11:50:18 +01:00
c8069325b3 build(deps): bump rollup from 2.41.1 to 2.41.2 in /web (#637)
Bumps [rollup](https://github.com/rollup/rollup) from 2.41.1 to 2.41.2.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.41.1...v2.41.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-15 10:17:54 +01:00
9d08e02fe1 build(deps-dev): bump eslint from 7.21.0 to 7.22.0 in /web (#638)
Bumps [eslint](https://github.com/eslint/eslint) from 7.21.0 to 7.22.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.21.0...v7.22.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-15 10:17:42 +01:00
a11ea598a2 build(deps): bump react and react-dom in /website (#639)
Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom). These dependencies needed to be updated together.

Updates `react` from 16.14.0 to 17.0.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v17.0.1/packages/react)

Updates `react-dom` from 16.14.0 to 17.0.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v17.0.1/packages/react-dom)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-15 10:17:27 +01:00
2713b05e8c Merge branch 'master' into version-2021.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	docker-compose.yml
#	helm/README.md
#	web/src/authentik.css
#	web/src/flows/FlowExecutor.ts
#	web/src/flows/stages/identification/IdentificationStage.ts
#	website/docs/installation/kubernetes.md
2021-03-13 21:36:17 +01:00
fef5a5ca52 Merge branch 'master' into next 2021-03-13 21:27:51 +01:00
9d339d8b11 policies: fix error when clearing policy cache when no policies are cached
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-13 21:10:13 +01:00
4e86aa3f59 sources/oauth: fix error on user enrollment when no enrollment flow is defined
fixes #636

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-13 21:08:31 +01:00
221e4b665c docs: add beta opt-in docs 2021-03-12 18:04:42 +01:00
e67f235a9f website: add docs for compose configuration options 2021-03-12 16:43:31 +01:00
741ebbacca Merge branch 'master' into next 2021-03-12 12:41:34 +01:00
b63b789f77 web: prevent duplicate messages 2021-03-12 12:41:17 +01:00
a63702ef90 web: add close button to messages 2021-03-12 12:27:57 +01:00
a4a4550753 Merge branch 'master' into next 2021-03-12 10:06:38 +01:00
fd864655f6 build(deps): bump @sentry/tracing from 6.2.1 to 6.2.2 in /web (#633) 2021-03-12 09:02:44 +01:00
c1da09507a build(deps): bump rollup from 2.41.0 to 2.41.1 in /web (#632) 2021-03-12 09:01:53 +01:00
ed2ea220bf build(deps): bump boto3 from 1.17.25 to 1.17.26 (#634) 2021-03-12 09:01:25 +01:00
7738cbe751 build(deps): bump golang from 1.16.1 to 1.16.2 in /outpost (#635) 2021-03-12 09:01:16 +01:00
bf16ea3607 build(deps): bump @sentry/browser from 6.2.1 to 6.2.2 in /web (#631) 2021-03-12 09:00:10 +01:00
d6f44e069c docs: add notice for launch URL for vcenter 7u2 2021-03-11 22:17:16 +01:00
899cf392f4 web: improve compatibility with password managers 2021-03-11 22:04:59 +01:00
d99451b45c outposts: improve logs for outpost connection 2021-03-11 17:50:57 +01:00
5b31f8edf6 Merge branch 'master' into next
# Conflicts:
#	helm/templates/geoip-pvc.yaml
2021-03-11 17:43:28 +01:00
00235e039b helm: add initial geoip 2021-03-11 17:43:03 +01:00
2dfaef4220 helm: add initial geoip 2021-03-11 17:37:38 +01:00
13fceacfe4 root: add geoip config to docker-compose 2021-03-11 16:42:19 +01:00
f8dc32b387 events: don't fail on boot when geoip can't be opened 2021-03-11 16:38:14 +01:00
828f2f8b92 web: use loadingState for autosubmitStage 2021-03-11 15:39:59 +01:00
734399755d web: improve layout of expanded event info 2021-03-11 15:15:17 +01:00
d8f106b976 web: improve styling for application list 2021-03-11 10:56:22 +01:00
9a524dd671 web: show related edit button for bound stages and policies 2021-03-11 10:12:22 +01:00
0775296003 website: bump postcss 2021-03-11 09:57:33 +01:00
390534c14e build(deps): bump boto3 from 1.17.24 to 1.17.25 (#629)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.24 to 1.17.25.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.24...1.17.25)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-11 09:37:13 +01:00
2a644f64ad build(deps): bump golang from 1.16.0 to 1.16.1 in /outpost (#630)
Bumps golang from 1.16.0 to 1.16.1.

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-11 09:36:39 +01:00
e0298141cf web: backport fix: add missing background filter
# Conflicts:
#	authentik/core/templates/login/base_full.html
2021-03-10 23:23:25 +01:00
df7119bb22 web: backport fix: add missing background filter 2021-03-10 23:22:39 +01:00
1d5bba831e root: add comment for error reporting to compose 2021-03-10 23:15:38 +01:00
0b4be70c00 web: fix path for fallback flow view 2021-03-10 23:15:25 +01:00
786737650b build(deps): bump @docusaurus/core in /website (#628)
Bumps [@docusaurus/core](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus) from 2.0.0-alpha.70 to 2.0.0-alpha.71.
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/master/CHANGELOG-2.x.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v2.0.0-alpha.71/packages/docusaurus)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:19:36 +01:00
54c80a2e1f build(deps-dev): bump rollup-plugin-minify-html-literals in /web (#624)
Bumps [rollup-plugin-minify-html-literals](https://github.com/asyncLiz/rollup-plugin-minify-html-literals) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/asyncLiz/rollup-plugin-minify-html-literals/releases)
- [Changelog](https://github.com/asyncLiz/rollup-plugin-minify-html-literals/blob/master/CHANGELOG.md)
- [Commits](https://github.com/asyncLiz/rollup-plugin-minify-html-literals/compare/v1.2.5...v1.2.6)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:14:16 +01:00
b376211a0e build(deps): bump boto3 from 1.17.23 to 1.17.24 (#625)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.23 to 1.17.24.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.23...1.17.24)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:13:53 +01:00
1990a3063e build(deps): bump github.com/sirupsen/logrus in /outpost (#627)
Bumps [github.com/sirupsen/logrus](https://github.com/sirupsen/logrus) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/sirupsen/logrus/releases)
- [Changelog](https://github.com/sirupsen/logrus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sirupsen/logrus/compare/v1.8.0...v1.8.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:13:44 +01:00
5abf22ad8a build(deps): bump @docusaurus/preset-classic in /website (#626)
Bumps [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) from 2.0.0-alpha.70 to 2.0.0-alpha.71.
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/master/CHANGELOG-2.x.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v2.0.0-alpha.71/packages/docusaurus-preset-classic)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:13:35 +01:00
b7b87d87fc build(deps): bump @patternfly/patternfly from 4.87.3 to 4.90.5 in /web (#622)
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.87.3 to 4.90.5.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.87.3...prerelease-v4.90.5)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:12:49 +01:00
20184424ab build(deps): bump rollup from 2.40.0 to 2.41.0 in /web (#623)
Bumps [rollup](https://github.com/rollup/rollup) from 2.40.0 to 2.41.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.40.0...v2.41.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:12:26 +01:00
d5de12b69e release: 2021.3.3 2021-03-09 18:03:53 +01:00
d1a3350085 release: 2021.3.3 2021-03-09 14:24:01 +01:00
e0b84c71a7 docs: add 2021.3.3 2021-03-09 14:23:48 +01:00
3bc1d6a690 web: fix Source icons not being displayed on firefox
# Conflicts:
#	web/src/elements/stages/identification/IdentificationStage.ts
2021-03-09 13:09:50 +01:00
786c74ef2c stages/authenticator_static: fix error when disable static tokens 2021-03-09 13:09:18 +01:00
3e9b5f5449 stages/authenticator_webauthn: add missing migration 2021-03-09 13:09:07 +01:00
5d071488d3 providers/oauth2: allow protected_resource_view when method is OPTIONS
# Conflicts:
#	authentik/providers/oauth2/views/provider.py
2021-03-09 13:08:33 +01:00
90d234a458 web: fix Colours for user settings in dark mode 2021-03-09 13:07:53 +01:00
0032bb6aee web: fix styling for static token list 2021-03-09 13:07:40 +01:00
6e6755d805 web: fix Flow executor not showing spinner when redirecting
# Conflicts:
#	web/src/pages/generic/FlowExecutor.ts
2021-03-09 13:07:32 +01:00
132b990f10 web: fix Source icons not being displayed on firefox 2021-03-09 13:06:17 +01:00
34a3d81eff stages/authenticator_*: add API for authenticator devices 2021-03-09 10:38:07 +01:00
43a4217497 web: add optional checkboxes to table 2021-03-09 10:38:07 +01:00
e0ec5826ca web: add edit button to LibraryView when user is superuser 2021-03-09 10:38:07 +01:00
5413a01360 web: fix drawer not updating after marking notification as seen 2021-03-09 10:38:07 +01:00
d9c3a29404 build(deps-dev): bump @typescript-eslint/parser in /web (#618)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.16.1 to 4.17.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.17.0/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-09 10:37:56 +01:00
bcce91476c build(deps-dev): bump @typescript-eslint/eslint-plugin in /web (#619)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.16.1 to 4.17.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.17.0/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-09 09:18:03 +01:00
56f0f454d0 build(deps): bump boto3 from 1.17.22 to 1.17.23 (#620)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.22 to 1.17.23.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.22...1.17.23)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-09 09:17:53 +01:00
25e63edf77 build(deps): bump defusedxml from 0.7.0 to 0.7.1 (#621) 2021-03-09 09:05:50 +01:00
d150851ff5 root: fix date settings 2021-03-08 15:24:11 +01:00
2e2840c71e helm: add service monitors 2021-03-08 13:02:02 +01:00
ff276fcc58 web: fix layout for search 2021-03-08 12:55:13 +01:00
2852fa3c5e web: use generated API Client (#616)
* api: fix types for config API

* api: remove broken swagger UI

* admin: re-fix system task enum

* events: make event optional

* events: fix Schema for notification transport test

* flows: use APIView for Flow Executor

* core: fix schema for Metrics APIs

* web: rewrite to use generated API client

* web: generate API Client in CI

* admin: use x_cord and y_cord to prevent yaml issues

* events: fix linting errors

* web: don't lint generated code

* core: fix fields not being required in TypeSerializer

* flows: fix missing permission_classes

* web: cleanup

* web: fix rendering of graph on Overview page

* web: cleanup imports

* core: fix missing background image filter

* flows: fix flows not advancing properly

* stages/*: fix warnings during get_challenge

* web: send Flow response as JSON instead of FormData

* web: fix styles for horizontal tabs

* web: add base chart class and custom chart for application view

* root: generate ts client for e2e tests

* web: don't attempt to connect to websocket in selenium tests

* web: fix UserTokenList not being included in the build

* web: fix styling for static token list

* web: fix CSRF Token missing

* stages/authenticator_static: fix error when disable static tokens

* core: fix display issue when updating user info

* web: fix Flow executor not showing spinner when redirecting
2021-03-08 11:14:00 +01:00
1c6d498621 web: fix Flow executor not showing spinner when redirecting
# Conflicts:
#	web/src/pages/generic/FlowExecutor.ts
2021-03-08 10:26:42 +01:00
3f0e4bb654 stages/authenticator_static: fix error when disable static tokens 2021-03-08 10:26:03 +01:00
a59d78a7c7 web: fix styling for static token list 2021-03-08 10:25:56 +01:00
0a24202f1e build(deps): bump boto3 from 1.17.21 to 1.17.22 (#617) 2021-03-08 07:45:40 +01:00
cbc86d674d web: fix Colours for user settings in dark mode 2021-03-06 23:00:29 +01:00
082628771b tests/integration: add more tests for docker outpost 2021-03-05 19:09:13 +01:00
93b50e7d6e tests/e2e: add tests for OIDC implicit flow 2021-03-05 17:18:50 +01:00
c6de4e47d7 providers/oauth2: allow protected_resource_view when method is OPTIONS 2021-03-05 16:57:37 +01:00
0e9e378bdf docs: update manual k8s outpost deployment 2021-03-05 15:30:41 +01:00
de4b3d6290 providers/oauth2: always set CORS headers on provider info view 2021-03-05 14:27:16 +01:00
56f75aecc7 docs: bump version of outpost in docs 2021-03-05 14:14:37 +01:00
0fe009d37c stages/authenticator_webauthn: add missing migration 2021-03-05 14:14:37 +01:00
49db283e71 build(deps): bump boto3 from 1.17.20 to 1.17.21 (#613)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.20 to 1.17.21.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.20...1.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-05 09:27:03 +01:00
7058366623 build(deps): bump defusedxml from 0.6.0 to 0.7.0 (#614)
Bumps [defusedxml](https://github.com/tiran/defusedxml) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/tiran/defusedxml/releases)
- [Changelog](https://github.com/tiran/defusedxml/blob/master/CHANGES.txt)
- [Commits](https://github.com/tiran/defusedxml/compare/v0.6.0...v0.7.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-05 09:26:42 +01:00
ced45513b8 build(deps-dev): bump typescript from 4.2.2 to 4.2.3 in /web (#615)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.2.2 to 4.2.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-05 09:26:18 +01:00
15e15c9635 docs: add 2021.3.2 2021-03-04 09:40:27 +01:00
d53c82eee2 core: fix link on login template 2021-03-04 09:39:13 +01:00
e1e0b0cf7d release: 2021.3.2 2021-03-04 09:33:25 +01:00
33e013a59f build(deps): bump boto3 from 1.17.19 to 1.17.20 (#611)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.19 to 1.17.20.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.19...1.17.20)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-04 08:55:05 +01:00
96a74776f8 build(deps): bump sentry-sdk from 0.20.3 to 1.0.0 (#612)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 0.20.3 to 1.0.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/0.20.3...1.0.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-04 08:54:57 +01:00
bb63d08682 web: fix submit in Modal reloading page in firefox 2021-03-03 23:01:47 +01:00
32655567da sources/ldap: fix sync for Users without pwdLastSet 2021-03-03 22:54:05 +01:00
ff5f5f65e8 web: fix date display issue 2021-03-03 21:53:30 +01:00
1f97aa09fa docs: fix typos in release notes 2021-03-03 21:15:17 +01:00
32e5ebb8a3 release: 2021.3.1 2021-03-03 20:53:43 +01:00
597e00dd86 root: update bumpversion config 2021-03-03 20:53:38 +01:00
dd31191845 Merge branch 'master' into version-2021.3 2021-03-03 20:48:02 +01:00
e9d95b1311 docs: Add Wiki.js integration docs (#610)
* docs(wikijs): Add Wiki.js integration docs

* docs(wikijs): Add to sidebar.
2021-03-03 20:31:02 +01:00
3319547a0e outposts: improve error handling for kubernetes outpost 2021-03-03 20:27:38 +01:00
1a00730cdd core: cleanup output for backup task 2021-03-03 20:11:55 +01:00
466723573c api: fix types for config API 2021-03-03 20:05:43 +01:00
ea784d47f4 admin: fix mismatched Swagger schema 2021-03-03 17:44:47 +01:00
77d5ba2862 events: fix typo in events API 2021-03-03 16:54:59 +01:00
f4580a1097 api: remove legacy messages API as its WS only 2021-03-03 15:02:20 +01:00
9e3d1f0baa web: fix circular dependency 2021-03-03 11:38:30 +01:00
c002c4b610 api: make pagination required 2021-03-03 10:37:03 +01:00
dde5e910cf root: fix name of docker images 2021-03-03 10:36:46 +01:00
5218332bce web: improve error handing for fetch in AdminLoginChart 2021-03-03 10:06:54 +01:00
28cd08bbba core: make user settings use vertical tabs 2021-03-03 10:05:12 +01:00
3cb0575a1e root: fix swagger pagination not matching API 2021-03-03 09:28:22 +01:00
dc1c1b9569 build(deps): bump boto3 from 1.17.18 to 1.17.19 (#609) 2021-03-03 08:58:24 +01:00
662d117b66 root: replace ghcr with harbor for expiry 2021-03-03 00:07:42 +01:00
b2449757f9 web/stages/authenticator_validate: only show back button when multiple challenges 2021-03-02 22:30:21 +01:00
a0753bfc88 docs: add docs for deny stage 2021-03-02 22:25:28 +01:00
e2a771bdaa docs: update screenshot in captcha stage 2021-03-02 22:25:00 +01:00
23de9df2a5 stages/authenticator_validate: cleanup 2021-03-02 22:20:54 +01:00
5c739ebed2 docs: add authenticator_webauthn stage docs 2021-03-02 22:20:05 +01:00
d3f8d7120f docs: cleanup, add 2021.3 to sidebar 2021-03-02 22:10:54 +01:00
21fd251edf docs: add apache guacamole integration 2021-03-02 22:04:53 +01:00
28cededb90 docs: update integration for harbor 2021-03-02 21:49:04 +01:00
d420719649 release: 2021.3.1-rc2 2021-03-02 21:41:30 +01:00
0018fbacd3 Merge branch 'master' into version-2021.3
# Conflicts:
#	web/src/constants.ts
2021-03-02 21:39:30 +01:00
8c41d2f4cb stages/authenticator_webauthn: add views to update and delete devices 2021-03-02 21:26:31 +01:00
3941590d0c web: fix missing create buttons on user token list 2021-03-02 21:16:14 +01:00
dc4a7c35da core: fix errors on user token views 2021-03-02 21:16:03 +01:00
e8c9b70ae8 sources/ldap: check pwdLastSet when syncing Users 2021-03-02 21:05:02 +01:00
74d240dfd4 admin: use spinner-button for modal forms 2021-03-02 20:37:23 +01:00
7d296b2119 root: align image on readme 2021-03-02 17:00:36 +01:00
373793ce9a policies: show more information when provider fails to resolve application 2021-03-02 16:58:55 +01:00
5c0ec7554b web: fix lists not being paginated 2021-03-02 15:12:26 +01:00
792fa45dca providers/oauth2: add logout URL to Setup URLs API 2021-03-02 15:11:18 +01:00
743aaea15e policies: improve logging 2021-03-02 15:04:31 +01:00
de03ed0aec web: fix background for shell without flow executor 2021-03-02 15:04:14 +01:00
e68ec16a34 web: improve display of notification age 2021-03-02 15:03:58 +01:00
68a0219d0f docs: update debug screenshot 2021-03-02 13:29:09 +01:00
38d9533afd root: update screenshots 2021-03-02 12:15:32 +01:00
7538af5e09 docs: fix download links for compose 2021-03-02 10:07:46 +01:00
2e659c1ab0 release: 2021.3.1-rc1 2021-03-02 09:41:09 +01:00
ad0cc5f0be Merge branch 'master' into version-2021.3 2021-03-02 09:41:00 +01:00
7ae9482e7b web: fix mismatched version 2021-03-02 09:40:43 +01:00
7fb95dfabf stages/password: improve logging 2021-03-02 09:40:32 +01:00
83cc5d24f2 stages/password: improve logging 2021-03-02 09:30:29 +01:00
38b3096c9a build(deps-dev): bump @typescript-eslint/eslint-plugin in /web (#603)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.15.2 to 4.16.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.16.1/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-02 09:20:53 +01:00
df8f21e559 build(deps): bump @sentry/tracing from 6.2.0 to 6.2.1 in /web (#604)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.2.0...6.2.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-02 09:20:45 +01:00
f4979fcf19 build(deps-dev): bump @typescript-eslint/parser in /web (#605)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.15.2 to 4.16.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.16.1/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-02 09:13:01 +01:00
431b7375c1 build(deps): bump @sentry/browser from 6.2.0 to 6.2.1 in /web (#606)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.2.0...6.2.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-02 09:12:45 +01:00
a6627145c8 build(deps): bump boto3 from 1.17.17 to 1.17.18 (#607)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.17 to 1.17.18.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.17...1.17.18)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-02 09:12:28 +01:00
3045cf1aef web: make user password-reset button use action button 2021-03-01 20:41:54 +01:00
c65b2944b3 stages/reputation: add API for user and IP Score 2021-03-01 20:22:37 +01:00
2ae5a81c15 stages/deny: add deny stage 2021-03-01 20:16:54 +01:00
ed8b78600e stages/authenticator_validate: add configuration stage to configure Authenticator 2021-03-01 19:23:59 +01:00
644a03e40e lib: don't order_by on widget because PolicyBindingModel, order in form 2021-03-01 19:23:09 +01:00
88ce93ab04 policies: fix tests creating policies with empty names 2021-03-01 19:22:35 +01:00
8878dc61d3 web: Add Policy create button to BoundPoliciesList 2021-03-01 18:34:36 +01:00
03d38557e5 stages/*: simplify __str__ of classes 2021-03-01 18:30:47 +01:00
37b59bb5b9 lib: sort GroupedModelChoiceField by name
closes #602
2021-03-01 18:30:27 +01:00
19eea68e0f web: use vertical list for related application links 2021-03-01 17:23:00 +01:00
ce7aae16c9 stages/password: fix ?next param for password change 2021-03-01 17:17:44 +01:00
fd9ba97479 core: remove source's ui_additional_info 2021-03-01 16:57:51 +01:00
919debdd13 root: lock twisted to 20.3.0 whilst its causing issues with uvloop 2021-03-01 16:26:05 +01:00
36690de285 root: push PR and branch images to GHCR (#601) 2021-03-01 12:04:56 +01:00
ca4ead8fd8 events: fix event creation with anonymous user 2021-03-01 12:04:27 +01:00
a81f981471 lib: fix being unable to set authentik. options 2021-03-01 11:11:00 +01:00
d6fd2b0afa sources/saml: add Metadata API 2021-03-01 10:50:45 +01:00
0478ae3da8 web: add missing SAML Source display page 2021-03-01 10:49:00 +01:00
9c33f4858f web: fix more height issues and sidebar not correctly activating 2021-03-01 10:32:25 +01:00
f2eaa9052e build(deps-dev): bump coverage from 5.4 to 5.5 (#598)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.4 to 5.5.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.4...coverage-5.5)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-01 09:01:08 +01:00
21d0641110 build(deps): bump rollup from 2.39.1 to 2.40.0 in /web (#599)
Bumps [rollup](https://github.com/rollup/rollup) from 2.39.1 to 2.40.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.39.1...v2.40.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-01 09:00:39 +01:00
67d05f99e9 build(deps-dev): bump eslint from 7.20.0 to 7.21.0 in /web (#600)
Bumps [eslint](https://github.com/eslint/eslint) from 7.20.0 to 7.21.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.20.0...v7.21.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-01 09:00:31 +01:00
21d6a28715 root: fix branch Name extraction to work on non PRs 2021-02-28 14:24:16 +01:00
1149a8d9a4 flows: fix tests for diagram 2021-02-28 11:01:34 +01:00
5e98172afb website/docs: update next docs 2021-02-28 10:44:00 +01:00
9b3e94c7c8 flows: fix flow diagram showing policy after stage and not before 2021-02-28 10:28:37 +01:00
30a1b65e94 web: fix BoundPoliciesList not showing policy correctly 2021-02-28 10:19:19 +01:00
9bb46ecb88 build(deps): bump boto3 from 1.17.16 to 1.17.17 (#597) 2021-02-28 09:47:31 +01:00
269e6c4f38 Merge pull request #564 from BeryJu/stage-challenge 2021-02-28 01:30:52 +01:00
7f65ae3f92 Merge branch 'master' into stage-challenge
# Conflicts:
#	web/package-lock.json
2021-02-28 00:47:18 +01:00
ee6b365003 tests/e2e: fix SAML source tests 2021-02-28 00:30:33 +01:00
2ad4bd5c0a tests/e2e: fix oauth source tests 2021-02-28 00:27:18 +01:00
0958740b51 providers/saml: fix Autosubmit Challenge 2021-02-28 00:09:08 +01:00
9cdfd8b75a tests/e2e: fix other provider tests 2021-02-28 00:08:57 +01:00
3c8a0081bc tests/e2e: fix more test, add requirements for crypto 2021-02-27 23:33:15 +01:00
088e0e736a tests/e2e: fix more tests, cleanup 2021-02-27 22:57:15 +01:00
cbb0681f95 web/stages/consent: use data- attribute for permission id 2021-02-27 22:54:20 +01:00
55c408a8bf tests/e2e: replace apply_default_data with @apply_migration decorator 2021-02-27 22:32:48 +01:00
07379acf7f tests/e2e: fix enroll tests 2021-02-27 22:09:40 +01:00
a1af93f8be web: disable CaptureConsoleIntegration 2021-02-27 22:09:10 +01:00
b9a9da4ec7 web/stages/prompt: render later so fields aren't cached 2021-02-27 21:05:20 +01:00
05a5b5b675 stages/prompt: fix fields not being sorted correctly 2021-02-27 21:03:57 +01:00
0fb17eee43 web: fix URLs for clear buttons 2021-02-27 21:00:55 +01:00
a1474e09e5 website/docs: fix type for username input 2021-02-27 21:00:42 +01:00
a33c7d7786 web: fix admin url for Prompt 2021-02-27 21:00:33 +01:00
c08d9762d9 web: add button to edit stage on flow BoundStageList 2021-02-27 20:45:59 +01:00
d43e6e5736 web: fix styling on dark mode for band on flow 2021-02-27 20:45:46 +01:00
380786bfde tests/e2e: fix URLs, use self.login() 2021-02-27 19:02:29 +01:00
ffcf064f83 Merge branch 'version-2021.2'
# Conflicts:
#	authentik/policies/group_membership/forms.py
#	web/package.json
#	web/src/constants.ts
#	web/src/elements/buttons/TokenCopyButton.ts
2021-02-27 18:29:30 +01:00
252718bbaf docs: add changelog for 2021.2.6 2021-02-27 18:18:36 +01:00
402afa1e85 Merge branch 'master' into stage-challenge
# Conflicts:
#	web/src/elements/buttons/SpinnerButton.ts
2021-02-27 18:10:08 +01:00
5b4e75000b web: fix colourstyles not being included in common_styles 2021-02-27 17:38:21 +01:00
1a052913e9 web: add sentry CaptureConsole 2021-02-27 17:18:42 +01:00
e930a1d0dc root: run ci on version-* branches 2021-02-27 17:07:11 +01:00
4cbfaaa72b sources/ldap: fix password setter on users which are not LDAP 2021-02-27 16:49:59 +01:00
92943f08d9 sources/ldap: fix API error when source has not synced yet 2021-02-27 16:29:36 +01:00
10ef1c7e93 admin: fix missing success_url for clean views 2021-02-27 16:27:42 +01:00
02c762c268 flows: handle error when app cannot be found during import 2021-02-27 16:26:06 +01:00
bbf0ca92af website/flows: fix default value for session_duration 2021-02-27 16:09:58 +01:00
d2dfc6d63b Merge branch 'master' into stage-challenge 2021-02-27 16:04:57 +01:00
a18240fcd7 providers/oauth2: fix error when no login event could be found 2021-02-27 16:02:07 +01:00
d36e5dccf9 docs: add docs for recovery keys 2021-02-27 16:00:05 +01:00
9af1d6f63b events: fix error when event can't be loaded into rule task 2021-02-27 15:22:43 +01:00
ab6d46558b docs: remove dummy stage 2021-02-27 15:20:33 +01:00
e94abfc986 flows: fix glob pattern for doc flows 2021-02-27 13:23:16 +01:00
5c652c1f79 policies: sort groups in groupmembership policy and binding
closes #595
2021-02-27 13:19:38 +01:00
89aa0f0cc8 Merge branch 'master' into stage-challenge 2021-02-27 13:14:38 +01:00
085589bcec docs(exampleFlows): Rename pbflow to akflow (#596)
* docs(exampleFlows): Rename enrollment-2-stage.pbflow

* docs(exampleFlows): Rename enrollment-email-verification.pbflow

* docs(exampleFlows): Rename login-2fa.pbflow

* docs(exampleFlows): Rename login-conditional-captcha.pbflow

* docs(exampleFlows): Rename recovery-email-verification.pbflow

* docs(exampleFlows): Rename unenrollment.pbflow

* docs(exampleFlows): Fix links.
2021-02-27 13:11:41 +01:00
95d0d6f3e8 tests/e2e: add login method 2021-02-26 16:47:01 +01:00
c62ef4ae81 stages/identification: don't pass entire application 2021-02-26 16:44:45 +01:00
3df81ca6f0 root: don't use failfast 2021-02-26 15:39:50 +01:00
578326eccd tests/e2e: don't use reverse for self.shell_url 2021-02-26 15:13:31 +01:00
2335ccddaa root: add fallback URL for websocket 2021-02-26 15:12:58 +01:00
477e30f542 core: fix path for blank avatar when avatars are disabled 2021-02-26 15:07:30 +01:00
7bf3d7e10a Merge branch 'master' into stage-challenge
# Conflicts:
#	Pipfile.lock
2021-02-26 12:02:49 +01:00
1bef659b10 stages/captcha: remove dependency on captcha app 2021-02-26 10:13:58 +01:00
e3f7bd8ab8 build(deps): bump @types/chart.js from 2.9.30 to 2.9.31 in /web (#593)
Bumps [@types/chart.js](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/chart.js) from 2.9.30 to 2.9.31.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/chart.js)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-26 09:25:55 +01:00
45c731de3c build(deps): bump boto3 from 1.17.15 to 1.17.16 (#594)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.15 to 1.17.16.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.15...1.17.16)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-26 09:25:44 +01:00
535770abbd tests/e2e: fix authenticator tests 2021-02-25 22:54:39 +01:00
eccea8eba0 web/stages/authenticator_totp: fix enter button triggering copy button 2021-02-25 22:43:42 +01:00
ab200a1dfb web: add hidden input with totp config url 2021-02-25 21:43:00 +01:00
ca122b20c9 web: fix spacing for messages 2021-02-25 21:23:31 +01:00
74b407ebc7 web: add button to copy TOTP URL
closes #591
2021-02-25 21:22:57 +01:00
fbf2fe2404 stages/authenticator_validate: fix webauthn validation 2021-02-25 21:00:32 +01:00
b968adffc1 stages/authenticator_totp: fix error when disabling device 2021-02-25 21:00:18 +01:00
c275992f7b web: re-enable fallback to siteshell for now 2021-02-25 20:55:22 +01:00
4e2c686db1 Merge branch 'master' into stage-challenge
# Conflicts:
#	Pipfile.lock
2021-02-25 20:13:17 +01:00
bfc69562d8 root: remove qr and captcha from backend dependencies 2021-02-25 20:06:20 +01:00
9e6a7bf16b stages/captcha: migrated to SPA 2021-02-25 19:58:38 +01:00
890e0e9054 *: remove unused templates and code, move avatar to User model 2021-02-25 19:58:23 +01:00
cf7e7c44ff stages/password: fix recovery link not being shown in SPA 2021-02-25 15:09:48 +01:00
0f169f176d stages/authenticator_validate: implement validation, add button to go back to device picker 2021-02-25 12:07:32 +01:00
429fc921b1 build(deps): bump codemirror from 5.59.3 to 5.59.4 in /web (#590)
Bumps [codemirror](https://github.com/codemirror/CodeMirror) from 5.59.3 to 5.59.4.
- [Release notes](https://github.com/codemirror/CodeMirror/releases)
- [Changelog](https://github.com/codemirror/CodeMirror/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codemirror/CodeMirror/compare/5.59.3...5.59.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-25 09:18:15 +01:00
e7a9a41a2f build(deps): bump boto3 from 1.17.14 to 1.17.15 (#589)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.14 to 1.17.15.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.14...1.17.15)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-25 09:18:02 +01:00
d1c24f47b2 build(deps): bump docker from 4.4.3 to 4.4.4 (#588)
Bumps [docker](https://github.com/docker/docker-py) from 4.4.3 to 4.4.4.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.4.3...4.4.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-25 09:17:45 +01:00
007676b400 stages/authenticator_validate: fix post from code form 2021-02-24 20:39:39 +01:00
c0c235bead helm: fix initialDelaySeconds 2021-02-24 19:39:35 +01:00
a3aacb5285 docs: add 2021.2.5 2021-02-24 10:22:55 +01:00
5977c09b05 Merge branch 'version-2021.2'
# Conflicts:
#	authentik/admin/templates/administration/policy/list.html
#	web/src/pages/outposts/OutpostListPage.ts
2021-02-24 10:20:48 +01:00
9049593ff5 sources/oauth: fix buttons not being ak-root-link 2021-02-24 09:23:19 +01:00
e74c098b7a web: fix library not being full height, again 2021-02-24 09:21:16 +01:00
d06a44378d build(deps): bump boto3 from 1.17.13 to 1.17.14 (#586)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.13 to 1.17.14.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.13...1.17.14)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-24 09:13:20 +01:00
0a8da376fc build(deps-dev): bump typescript from 4.1.5 to 4.2.2 in /web (#587)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.1.5 to 4.2.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-24 09:13:07 +01:00
2a0f940a42 Merge branch 'master' into stage-challenge 2021-02-23 23:43:51 +01:00
8aa067795a web: replace default flow background for 2021.3 2021-02-23 23:43:37 +01:00
3cdb81c5ba stages/authenticator_validate: create challenge per device, implement class switcher 2021-02-23 23:43:13 +01:00
e8259791f0 stages/authenticator_webauthn: fix rp_id and origin generation 2021-02-23 23:39:00 +01:00
55af786852 Merge branch 'master' into stage-challenge 2021-02-23 23:17:03 +01:00
8a916602c4 docs: update for 2021.2.4-stable 2021-02-23 23:16:32 +01:00
7101c7987c Merge branch 'version-2021.2' 2021-02-23 23:02:05 +01:00
66e5958283 core: fix user-settings not loading sources 2021-02-23 22:53:17 +01:00
9db445c3ee admin: fix success_urls 2021-02-23 22:53:05 +01:00
574438b51e web: fix /-/user/ not loading 2021-02-23 22:46:11 +01:00
a05885140d Merge branch 'master' into stage-challenge 2021-02-23 18:27:04 +01:00
8878fac4e7 stages/authenticator_validate: send challenge for each device 2021-02-23 18:25:58 +01:00
7ee97a961c build(deps): bump github.com/getsentry/sentry-go in /outpost (#584)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.9.0 to 0.10.0.
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.9.0...v0.10.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-23 16:25:52 +01:00
737ff62e92 build(deps): bump golang from 1.15 to 1.16.0 in /outpost (#582)
Bumps golang from 1.15 to 1.16.0.

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-23 16:19:31 +01:00
07ada5a1b7 build(deps): bump rollup from 2.39.0 to 2.39.1 in /web (#583)
Bumps [rollup](https://github.com/rollup/rollup) from 2.39.0 to 2.39.1.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.39.0...v2.39.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-23 16:19:24 +01:00
8caeed6b18 build(deps): bump github.com/sirupsen/logrus in /outpost (#585)
Bumps [github.com/sirupsen/logrus](https://github.com/sirupsen/logrus) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/sirupsen/logrus/releases)
- [Changelog](https://github.com/sirupsen/logrus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sirupsen/logrus/compare/v1.7.0...v1.8.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-23 16:19:10 +01:00
b5adff5327 root: fix paths for dependabot 2021-02-23 15:20:10 +01:00
3894895d32 stages/authenticator_validate: start rewrite to SPA 2021-02-23 13:50:47 +01:00
7f53c97fb2 Merge branch 'master' into stage-challenge 2021-02-23 13:18:35 +01:00
44bd4b9511 build(deps-dev): bump @typescript-eslint/eslint-plugin in /web (#580)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.15.1 to 4.15.2.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.15.2/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-23 10:17:21 +01:00
2a1b5e0154 docs: add hardware requirements to docker-compose 2021-02-23 09:46:07 +01:00
8c0d48fe0a build(deps): bump boto3 from 1.17.12 to 1.17.13 (#579)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.12 to 1.17.13.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.12...1.17.13)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-23 09:25:56 +01:00
0863e60d29 build(deps-dev): bump @typescript-eslint/parser in /web (#581)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.15.1 to 4.15.2.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.15.2/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-23 09:25:36 +01:00
451c117ea4 stages/authenticator_webauthn: fix incorrect response being sent 2021-02-22 19:54:05 +01:00
388c8c8bec web: fix autofocus in ak-form-element 2021-02-22 19:26:50 +01:00
5904070bb2 flows: add ensure_csrf_cookie() to flow shell view 2021-02-22 18:42:15 +01:00
35ac87ec10 Merge branch 'master' into stage-challenge 2021-02-22 17:42:12 +01:00
8f8c2a291b root: add discord badge to readme 2021-02-22 17:27:16 +01:00
592a2dcede build(deps): bump codemirror from 5.59.2 to 5.59.3 in /web (#577)
Bumps [codemirror](https://github.com/codemirror/CodeMirror) from 5.59.2 to 5.59.3.
- [Release notes](https://github.com/codemirror/CodeMirror/releases)
- [Changelog](https://github.com/codemirror/CodeMirror/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codemirror/CodeMirror/compare/5.59.2...5.59.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-22 08:44:18 +01:00
a3221475e5 build(deps): bump boto3 from 1.17.11 to 1.17.12 (#575)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.11 to 1.17.12.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.11...1.17.12)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-22 08:44:10 +01:00
25f5031422 build(deps): bump django from 3.1.6 to 3.1.7 (#574)
Bumps [django](https://github.com/django/django) from 3.1.6 to 3.1.7.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.1.6...3.1.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-22 08:44:02 +01:00
63b94263af build(deps): bump uvicorn from 0.13.3 to 0.13.4 (#576)
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.13.3 to 0.13.4.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.13.3...0.13.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-22 08:43:52 +01:00
217595bb01 tests: start fixing selenium tests 2021-02-21 23:39:02 +01:00
2dd8119abe web: fix linting 2021-02-21 23:26:16 +01:00
20e0fe3941 web: move ak-form-element to separate file 2021-02-21 23:09:08 +01:00
0fa97de06e web/stages: fix cancel URL 2021-02-21 22:10:32 +01:00
38da13fea3 web: use ak-spinner everywhere 2021-02-21 22:01:48 +01:00
fb9880bff4 web: add loading animation to flowexecutor 2021-02-21 22:01:35 +01:00
acc790f590 stages/authenticator_webauthn: fix formatting of card 2021-02-21 21:42:40 +01:00
76c572cf7c stages/authenticator_webauthn: migrate to SPA 2021-02-21 20:53:23 +01:00
0904fea109 flows: fix migration for e2e tests 2021-02-21 20:47:23 +01:00
6df89e7abf stages/authenticator_static: migrate to SPA 2021-02-21 19:34:49 +01:00
21afda6dc2 stages/authenticator_totp: migrate to SPA 2021-02-21 19:10:50 +01:00
74c0ed27ba web: fix /-/user/ not loading 2021-02-21 19:03:43 +01:00
dc680a3385 flows: set pending_user in ChallengeStageView 2021-02-21 18:58:08 +01:00
88e5b22d16 flows: add get_pending_user() for WithUserInfoChallenge 2021-02-21 18:35:21 +01:00
27cd10e072 stages/prompt: migrate to SPA 2021-02-21 18:27:34 +01:00
d35f524865 core: remove old templates 2021-02-21 14:59:37 +01:00
ca223fa4df providers/saml: migrate to challenge for submit 2021-02-21 14:36:22 +01:00
14962eb6cc stages/email: migrate to SPA 2021-02-21 13:42:55 +01:00
b9f409d6d9 stages/consent: migrate to SPA 2021-02-21 13:15:45 +01:00
a8681ac88f root: fix typo 2021-02-21 00:22:14 +01:00
c1e6786ea1 stages/password: Migrate to SPA 2021-02-21 00:14:42 +01:00
1c8d101fc3 stages/identification: remove templates 2021-02-20 23:47:18 +01:00
7a9140bdcd core: move UILoginButtonSerializer into core 2021-02-20 23:42:35 +01:00
511f94fc7f *: cleanup code, return errors in challenge_invalid, fixup rendering 2021-02-20 23:34:10 +01:00
548b1ead2f flows: challenge error response in challenge format 2021-02-20 20:28:57 +01:00
33f67140f2 stages/identification: move user validation to serializer 2021-02-20 20:16:20 +01:00
8787dc23d0 web: fix linting errors 2021-02-20 19:59:24 +01:00
e0ae92ccc7 stages/*: update tests for new response 2021-02-20 19:41:48 +01:00
bdb86d7119 *: replace shortcuts.reverse with urls.reverse 2021-02-20 19:13:50 +01:00
a1a3d316e3 stages/identification: implement challenge 2021-02-20 18:28:11 +01:00
672b86ef88 web: fix old Links 2021-02-20 18:27:19 +01:00
a3c9d5873c web: fix URL for flows cached count 2021-02-20 18:27:03 +01:00
0e975757b8 core: remove UILoginButton's icon_path 2021-02-20 18:26:43 +01:00
391ee10cb8 Merge branch 'master' into stage-challenge
# Conflicts:
#	authentik/api/v2/urls.py
2021-02-20 12:51:10 +01:00
4f374c0c01 web: add 404 page, don't auto-redirect to home 2021-02-20 00:28:00 +01:00
dde303f13a admin: remove dead code 2021-02-20 00:27:22 +01:00
264c678eaa web: migrate user token list to web 2021-02-20 00:20:01 +01:00
854d94056e web: migrate remaining list views to web 2021-02-20 00:19:53 +01:00
9d4c22c706 web: show header while loading application info 2021-02-19 23:34:06 +01:00
9b12895fab admin: remove unneeded code 2021-02-19 19:32:46 +01:00
93478a55d7 web: migrate Stage List to web 2021-02-19 19:29:17 +01:00
a76cbf8b70 flows: separate flows api into smaller files 2021-02-19 19:14:16 +01:00
6597d5bd28 web: migrate Token List to web 2021-02-19 19:09:30 +01:00
fd28f37c0d web: migrate User list to web 2021-02-19 18:43:57 +01:00
d219f65e7a web: migrate System Task list to web 2021-02-19 18:12:23 +01:00
865f652476 web: migrate Outpost Service Connection to web 2021-02-19 17:49:34 +01:00
8008918d8b admin: remove PolicyBinding list 2021-02-19 17:37:19 +01:00
75d0bd01c2 admin: remove StageBinding list 2021-02-19 17:19:48 +01:00
029c6cd182 web: migrate Group list to web 2021-02-19 17:18:09 +01:00
71f771c22c core: add types API to propertymapping 2021-02-19 17:10:30 +01:00
0993d5ce4a web: reset retryDelay for WS connection after successful connect 2021-02-19 17:10:16 +01:00
38bd05867d web: migrate Policy list to web 2021-02-19 17:05:02 +01:00
79089d8981 policies: add bound count to api 2021-02-19 16:53:30 +01:00
44e51970e1 web: update for new cached actions 2021-02-19 16:37:50 +01:00
47bde052ca policies: add types action to policy API, use MetaNameSerializer 2021-02-19 16:34:33 +01:00
bd6a473d4f flows: add cached as action to flow API 2021-02-19 16:34:12 +01:00
cd23053007 web: fix height on table pages 2021-02-19 16:22:52 +01:00
6e11fd0f2e web: fix application library not being full height 2021-02-19 16:13:55 +01:00
277b4336d3 stages/authenticator_validate: update autocomplete for code input 2021-02-19 16:00:59 +01:00
1c1f9b6cb8 web: fix SiteShell not being full height 2021-02-19 15:34:21 +01:00
c23df5e1d5 build(deps): bump @sentry/browser from 6.1.0 to 6.2.0 in /web (#571)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.1.0...6.2.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-19 12:16:50 +01:00
c47cef6fbf build(deps): bump sentry-sdk from 0.20.2 to 0.20.3 (#567)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 0.20.2 to 0.20.3.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/0.20.2...0.20.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-19 09:22:30 +01:00
83b7b3257a build(deps): bump boto3 from 1.17.10 to 1.17.11 (#568)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.10 to 1.17.11.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.10...1.17.11)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-19 09:22:16 +01:00
270be95e68 build(deps): bump structlog from 20.2.0 to 21.1.0 (#569)
Bumps [structlog](https://github.com/hynek/structlog) from 20.2.0 to 21.1.0.
- [Release notes](https://github.com/hynek/structlog/releases)
- [Changelog](https://github.com/hynek/structlog/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/hynek/structlog/compare/20.2.0...21.1.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-19 09:22:06 +01:00
1c919b8b88 build(deps): bump docker from 4.4.2 to 4.4.3 (#570)
Bumps [docker](https://github.com/docker/docker-py) from 4.4.2 to 4.4.3.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.4.2...4.4.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-19 09:21:49 +01:00
1e51a2cdd7 build(deps): bump rollup-plugin-copy from 3.3.0 to 3.4.0 in /web (#572)
Bumps [rollup-plugin-copy](https://github.com/vladshcherbin/rollup-plugin-copy) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/vladshcherbin/rollup-plugin-copy/releases)
- [Commits](https://github.com/vladshcherbin/rollup-plugin-copy/compare/3.3.0...3.4.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-19 09:21:34 +01:00
7ba44b15a7 build(deps): bump @sentry/tracing from 6.1.0 to 6.2.0 in /web (#573)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.1.0...6.2.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-19 09:21:26 +01:00
4a94f515b3 root: add next branch 2021-02-18 21:24:34 +01:00
b229b2f40d Merge branch 'master' into stage-challenge
# Conflicts:
#	authentik/stages/authenticator_validate/stage.py
#	authentik/stages/identification/stage.py
2021-02-18 14:04:35 +01:00
e4f0613fab *: replace tuple and set from typing with normal 2021-02-18 13:53:57 +01:00
ecff810021 *: replace List from typing with normal list 2021-02-18 13:45:46 +01:00
fdde97cbbf *: replace Dict from typing with normal dict 2021-02-18 13:41:03 +01:00
c2a5641e6a Merge branch 'master' into stage-challenge 2021-02-18 12:46:28 +01:00
5a47c4850d build(deps): bump @patternfly/patternfly from 4.87.2 to 4.87.3 in /web (#566)
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.87.2 to 4.87.3.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.87.2...prerelease-v4.87.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-18 09:12:31 +01:00
70b8a941bb build(deps): bump boto3 from 1.17.9 to 1.17.10 (#565)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.9 to 1.17.10.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.9...1.17.10)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-18 09:12:18 +01:00
eb01b42425 flows: mount executor under api, implement initial challenge design 2021-02-17 23:52:49 +01:00
8708e487ae stages: add WebAuthn stage (#550)
* core: add User.uid for globally unique user ID

* admin: fix ?next for Flow list

* stages: add initial webauthn implementation

* web: add ak-flow-submit event to submit flow stage

* web: show error message for webauthn registration

* admin: fix next param not redirecting correctly

* stages/webauthn: remove form

* stages/webauthn: add API

* web: update flow diagram on ak-refresh

* stages/webauthn: add initial authentication

* stages/webauthn: initial authentication implementation

* web: cleanup webauthn utils

* stages: rename otp_* to authenticator and move webauthn to authenticator

* docs: fix broken links

* stages/authenticator_*: fix template paths

* stages/authenticator_validate: add device classes

* stages/authenticator_webauthn: implement django_otp.devices

* stages/authenticator_*: update default stage names

* web: add button to create stage on flow page

* web: don't minify HTML, remove nbsp

* admin: fix typo in stage list

* stages/*: use common base class for stage serializer

* stages/authenticator_*: create default objects after rename

* tests/e2e: adjust stage order
2021-02-17 20:49:58 +01:00
e020b8bf32 build(deps): bump boto3 from 1.17.8 to 1.17.9 (#562)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.8 to 1.17.9.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.8...1.17.9)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-17 09:28:40 +01:00
8e27121e10 build(deps): bump @patternfly/patternfly from 4.80.3 to 4.87.2 in /web (#563)
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.80.3 to 4.87.2.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.80.3...prerelease-v4.87.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-17 09:24:34 +01:00
06870b4f64 web: improve styling on model info 2021-02-16 23:19:01 +01:00
4cfcc48b23 admin: migrate certificate-keypair list to web 2021-02-16 23:16:52 +01:00
60c244c31d core: add User.uid for globally unique user ID 2021-02-16 23:04:48 +01:00
d122bddae2 web: update flow diagram on ak-refresh 2021-02-16 22:54:14 +01:00
69e6221906 web: port flow list 2021-02-16 22:52:54 +01:00
68eefd083e web: fix linting errors 2021-02-16 22:35:55 +01:00
a647917074 providers/saml: use redirect binding first 2021-02-16 21:35:19 +01:00
099197ba8c providers/saml: fix AuthnRequestsSigned and WantAssertionsSigned not loaded correctly 2021-02-16 21:30:15 +01:00
baa2ed5ecc web: fix download button for SAML Metadata download 2021-02-16 21:04:03 +01:00
f8ba623fc1 web: add more related links, add policy/user/group support for bindings 2021-02-16 20:52:59 +01:00
6bcdf36ca6 admin: add ?provider for ApplicationCreateView 2021-02-16 20:00:52 +01:00
416d949d80 web: add button to create application on provider page 2021-02-16 20:00:34 +01:00
0b75a0028b providers/saml: fix error when getting metadata of provider with no application 2021-02-16 19:58:04 +01:00
0901d7461e providers/saml: fix redirect error 2021-02-16 19:28:18 +01:00
61772b75ff providers/saml: fix managed mappings not being set on import 2021-02-16 19:20:52 +01:00
0ade57b5a6 docs: replace Autogenerated with managed mappings 2021-02-16 19:18:57 +01:00
61604adf9a root: fix request_id not being logged for actual asgi requests 2021-02-16 19:14:08 +01:00
8bd147b205 web: fix spacing on boudstagelist 2021-02-16 17:03:37 +01:00
724f53e972 build(deps): bump boto3 from 1.17.7 to 1.17.8 (#557)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.7 to 1.17.8.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.7...1.17.8)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-16 09:07:56 +00:00
c10478ec68 build(deps-dev): bump @typescript-eslint/eslint-plugin in /web (#560)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.15.0 to 4.15.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.15.1/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-16 09:03:57 +00:00
cdf12ee03d build(deps): bump docker from 4.4.1 to 4.4.2 (#558)
Bumps [docker](https://github.com/docker/docker-py) from 4.4.1 to 4.4.2.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.4.1...4.4.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-16 09:18:30 +01:00
964a8dbb82 build(deps): bump sentry-sdk from 0.20.1 to 0.20.2 (#559)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 0.20.1 to 0.20.2.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/0.20.1...0.20.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-16 09:17:21 +01:00
7ad48bfc44 build(deps-dev): bump @typescript-eslint/parser in /web (#561)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.15.0 to 4.15.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.15.1/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-16 09:17:07 +01:00
da90510b98 build(deps): bump rollup from 2.38.5 to 2.39.0 in /web (#553)
Bumps [rollup](https://github.com/rollup/rollup) from 2.38.5 to 2.39.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.38.5...v2.39.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-15 09:28:08 +01:00
4bd1598c2c build(deps): bump construct-style-sheets-polyfill in /web (#556)
Bumps [construct-style-sheets-polyfill](https://github.com/calebdwilliams/adoptedStyleSheets) from 2.4.9 to 2.4.16.
- [Release notes](https://github.com/calebdwilliams/adoptedStyleSheets/releases)
- [Changelog](https://github.com/calebdwilliams/construct-style-sheets/blob/master/CHANGELOG.md)
- [Commits](https://github.com/calebdwilliams/adoptedStyleSheets/compare/v2.4.9...v2.4.16)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-15 09:27:44 +01:00
6aa8d56d9f build(deps-dev): bump eslint from 7.19.0 to 7.20.0 in /web (#554)
Bumps [eslint](https://github.com/eslint/eslint) from 7.19.0 to 7.20.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.19.0...v7.20.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-15 09:27:31 +01:00
ccf7d794e9 build(deps): bump sentry-sdk from 0.20.0 to 0.20.1 (#552)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 0.20.0 to 0.20.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/0.20.0...0.20.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-15 09:27:10 +01:00
50ed2fb257 build(deps): bump boto3 from 1.17.6 to 1.17.7 (#551)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.6 to 1.17.7.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.6...1.17.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-15 09:26:56 +01:00
5ae030997a providers/saml: fix missing import 2021-02-15 09:25:22 +01:00
52dabcaad9 build(deps-dev): bump @rollup/plugin-typescript in /web (#555)
Bumps [@rollup/plugin-typescript](https://github.com/rollup/plugins) from 8.1.1 to 8.2.0.
- [Release notes](https://github.com/rollup/plugins/releases)
- [Commits](https://github.com/rollup/plugins/compare/typescript-v8.1.1...typescript-v8.2.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-15 09:05:01 +01:00
35e8a0c374 admin: fix ?next for Flow list 2021-02-14 18:39:36 +01:00
be292729a5 web: fix SiteShell breaking links when handlers are updated twice 2021-02-13 18:11:29 +01:00
1649c478b6 web: fix outpost edit/delete buttons 2021-02-12 11:56:54 +01:00
42feb54d80 helm: add initial wait for healthcheck 2021-02-12 11:53:49 +01:00
bbd088a957 events: fix geoip case when not configured 2021-02-12 10:43:00 +01:00
5417d0a90c *: bump pyright version 2021-02-12 10:19:38 +01:00
417b5d61a4 root: add initial geoip implementation 2021-02-12 09:52:14 +01:00
f13aad21cb build(deps): bump boto3 from 1.17.5 to 1.17.6 (#549)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.5 to 1.17.6.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.5...1.17.6)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-12 09:19:37 +01:00
79e8ee46c0 web: also use json logs for static parts 2021-02-12 00:00:11 +01:00
e3eaaeaf17 outpost: improve logging output, ensure fields match api server 2021-02-11 23:52:00 +01:00
e550216f85 events: fix user QuerySet being passed 2021-02-11 23:36:22 +01:00
1afb4a7a76 policies: add ability to directly assign groups in bindings 2021-02-11 20:36:48 +01:00
391eb9d469 admin: fix policy list not having a refresh button 2021-02-11 20:17:45 +01:00
494f094fa1 events: pass Event's user to Notification policy engine when present 2021-02-11 19:56:39 +01:00
aa0f5df218 policies/*: cleanup api and forms, use correct inheritance 2021-02-11 19:50:02 +01:00
6fc740a98b build(deps-dev): bump typescript from 4.1.4 to 4.1.5 in /web (#547)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.1.4 to 4.1.5.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.1.4...v4.1.5)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-11 09:12:09 +01:00
639 changed files with 52554 additions and 12120 deletions

View File

@ -1,9 +1,11 @@
[bumpversion]
current_version = 2021.2.6-stable
current_version = 2021.3.4
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)
serialize = {major}.{minor}.{patch}-{release}
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
serialize =
{major}.{minor}.{patch}-{release}
{major}.{minor}.{patch}
message = release: {new_version}
tag_name = version/{new_version}
@ -34,3 +36,7 @@ values =
[bumpversion:file:outpost/pkg/version.go]
[bumpversion:file:web/src/constants.ts]
[bumpversion:file:website/docs/outposts/manual-deploy-docker-compose.md]
[bumpversion:file:website/docs/outposts/manual-deploy-kubernetes.md]

View File

@ -1,7 +1,7 @@
version: 2
updates:
- package-ecosystem: gomod
directory: "/proxy"
directory: "/outpost"
schedule:
interval: daily
time: "04:00"
@ -41,7 +41,7 @@ updates:
assignees:
- BeryJu
- package-ecosystem: docker
directory: "/proxy"
directory: "/outpost"
schedule:
interval: daily
time: "04:00"

View File

@ -18,11 +18,11 @@ jobs:
- name: Building Docker Image
run: docker build
--no-cache
-t beryju/authentik:2021.2.6-stable
-t beryju/authentik:2021.3.4
-t beryju/authentik:latest
-f Dockerfile .
- name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik:2021.2.6-stable
run: docker push beryju/authentik:2021.3.4
- name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik:latest
build-proxy:
@ -48,17 +48,20 @@ jobs:
cd outpost/
docker build \
--no-cache \
-t beryju/authentik-proxy:2021.2.6-stable \
-t beryju/authentik-proxy:2021.3.4 \
-t beryju/authentik-proxy:latest \
-f proxy.Dockerfile .
- name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik-proxy:2021.2.6-stable
run: docker push beryju/authentik-proxy:2021.3.4
- name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik-proxy:latest
build-static:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: prepare ts api client
run: |
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/src/api --additional-properties=typescriptThreePlus=true
- name: Docker Login Registry
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
@ -69,11 +72,11 @@ jobs:
cd web/
docker build \
--no-cache \
-t beryju/authentik-static:2021.2.6-stable \
-t beryju/authentik-static:2021.3.4 \
-t beryju/authentik-static:latest \
-f Dockerfile .
- name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik-static:2021.2.6-stable
run: docker push beryju/authentik-static:2021.3.4
- name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik-static:latest
test-release:
@ -107,5 +110,5 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
tagName: 2021.2.6-stable
tagName: 2021.3.4
environment: beryjuorg-prod

1
.gitignore vendored
View File

@ -201,3 +201,4 @@ local.env.yml
selenium_screenshots/
backups/
media/
*mmdb

View File

@ -15,12 +15,15 @@ WORKDIR /
COPY --from=locker /app/requirements.txt /
COPY --from=locker /app/requirements-dev.txt /
ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates gnupg && \
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
echo "deb http://apt.postgresql.org/pub/repos/apt buster-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
apt-get update && \
apt-get install -y --no-install-recommends postgresql-client-12 postgresql-client-11 build-essential libxmlsec1-dev pkg-config && \
apt-get install -y --no-install-recommends postgresql-client-12 postgresql-client-11 build-essential libxmlsec1-dev pkg-config libmaxminddb0 && \
apt-get clean && \
pip install -r /requirements.txt --no-cache-dir && \
apt-get remove --purge -y build-essential && \
@ -45,4 +48,5 @@ COPY ./lifecycle/ /lifecycle
USER authentik
STOPSIGNAL SIGINT
ENV TMPDIR /dev/shm/
ENV PYTHONUBUFFERED 1
ENTRYPOINT [ "/lifecycle/bootstrap.sh" ]

View File

@ -1,20 +1,15 @@
all: lint-fix lint coverage gen
test-full:
coverage run manage.py test --failfast -v 3 .
coverage html
coverage report
test-integration:
k3d cluster create || exit 0
k3d kubeconfig write -o ~/.kube/config --overwrite
coverage run manage.py test --failfast -v 3 tests/integration
coverage run manage.py test -v 3 tests/integration
test-e2e:
coverage run manage.py test --failfast -v 3 tests/e2e
coverage run manage.py test -v 3 tests/e2e
coverage:
coverage run manage.py test --failfast -v 3 authentik
coverage run manage.py test -v 3 authentik
coverage html
coverage report

24
Pipfile
View File

@ -6,6 +6,9 @@ verify_ssl = true
[packages]
boto3 = "*"
celery = "*"
channels = "*"
channels-redis = "*"
dacite = "*"
defusedxml = "*"
django = "*"
django-cors-middleware = "*"
@ -15,35 +18,33 @@ django-guardian = "*"
django-model-utils = "*"
django-otp = "*"
django-prometheus = "*"
django-recaptcha = "*"
django-redis = "*"
djangorestframework = "*"
django-storages = "*"
djangorestframework = "*"
djangorestframework-guardian = "*"
docker = "*"
drf_yasg2 = "*"
facebook-sdk = "*"
geoip2 = "*"
gunicorn = "*"
kubernetes = "*"
ldap3 = "*"
lxml = "*"
packaging = "*"
psycopg2-binary = "*"
pycryptodome = "*"
pyjwkest = "*"
uvicorn = {extras = ["standard"],version = "*"}
gunicorn = "*"
pyyaml = "*"
qrcode = "*"
requests-oauthlib = "*"
sentry-sdk = "*"
service_identity = "*"
structlog = "*"
swagger-spec-validator = "*"
urllib3 = {extras = ["secure"],version = "*"}
dacite = "*"
channels = "*"
channels-redis = "*"
kubernetes = "*"
docker = "*"
uvicorn = {extras = ["standard"],version = "*"}
webauthn = "*"
xmlsec = "*"
twisted = "==20.3.0"
[requires]
python_version = "3.9"
@ -55,8 +56,7 @@ black = "==20.8b1"
bumpversion = "*"
colorama = "*"
coverage = "*"
django-debug-toolbar = "*"
pylint = "*"
pylint = "<=2.6.0"
pylint-django = "*"
selenium = "*"
prospector = "*"

601
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "53ad00e394a5f2e2462837c4ceff837d1e593469af9505726048bed72ce0b81a"
"sha256": "d2d51b999d57d01e1f8e6450ae54f8e58e1eb213ae457cc43f7314daa8e11541"
},
"pipfile-spec": 6,
"requires": {
@ -16,6 +16,48 @@
]
},
"default": {
"aiohttp": {
"hashes": [
"sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe",
"sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe",
"sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5",
"sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8",
"sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd",
"sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb",
"sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c",
"sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87",
"sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0",
"sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290",
"sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5",
"sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287",
"sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde",
"sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf",
"sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8",
"sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16",
"sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf",
"sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809",
"sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213",
"sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f",
"sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013",
"sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b",
"sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9",
"sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5",
"sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb",
"sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df",
"sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4",
"sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439",
"sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f",
"sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22",
"sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f",
"sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5",
"sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970",
"sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009",
"sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc",
"sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a",
"sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95"
],
"version": "==3.7.4.post0"
},
"aioredis": {
"hashes": [
"sha256:15f8af30b044c771aee6787e5ec24694c048184c7b9e54c3b60c750a4b93273a",
@ -53,10 +95,10 @@
},
"autobahn": {
"hashes": [
"sha256:93df8fc9d1821c9dabff9fed52181a9ad6eea5e9989d53102c391607d7c1666e",
"sha256:cceed2121b7a93024daa93c91fae33007f8346f0e522796421f36a6183abea99"
"sha256:9195df8af03b0ff29ccd4b7f5abbde957ee90273465942205f9a1bad6c3f07ac",
"sha256:e126c1f583e872fb59e79d36977cfa1f2d0a8a79f90ae31f406faae7664b8e03"
],
"version": "==21.1.1"
"version": "==21.3.1"
},
"automat": {
"hashes": [
@ -74,17 +116,17 @@
},
"boto3": {
"hashes": [
"sha256:d6aafb804fca2b67c65dda78ad8b4afed901e004071208b84c804d345ad9ebba"
"sha256:64a8900b3a110e2d6ff4d87f4d8cd56f0c8527361d9fc9385fcb50efe7a4975a",
"sha256:8e9ff8006c41889ed8a11831dee62adf922e071f14d54c52946d1f7855ae7a8e"
],
"index": "pypi",
"version": "==1.17.5"
"version": "==1.17.26"
},
"botocore": {
"hashes": [
"sha256:04a1df759681f5f171accb354d863bfed0774d64a4e8ee35ff49835755660a4e",
"sha256:3c55f0db5e08920727f4fa24a87aed60060643f4b0b5665c62ec762f79e82d6b"
"sha256:4a785847a351e59f2329627fc9a19cf50f07644ea68996a1595d5a20487a423f"
],
"version": "==1.20.5"
"version": "==1.20.26"
},
"cachetools": {
"hashes": [
@ -93,6 +135,12 @@
],
"version": "==4.2.1"
},
"cbor2": {
"hashes": [
"sha256:a33aa2e5534fd74401ac95686886e655e3b2ce6383b3f958199b6e70a87c94bf"
],
"version": "==5.2.0"
},
"celery": {
"hashes": [
"sha256:5e8d364e058554e83bbb116e8377d90c79be254785f357cb2cec026e79febe13",
@ -110,45 +158,45 @@
},
"cffi": {
"hashes": [
"sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e",
"sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d",
"sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a",
"sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec",
"sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362",
"sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668",
"sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c",
"sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b",
"sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06",
"sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698",
"sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2",
"sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c",
"sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7",
"sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009",
"sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03",
"sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b",
"sha256:7ef7d4ced6b325e92eb4d3502946c78c5367bc416398d387b39591532536734e",
"sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909",
"sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53",
"sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35",
"sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26",
"sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b",
"sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01",
"sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb",
"sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293",
"sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd",
"sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d",
"sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3",
"sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d",
"sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e",
"sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca",
"sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d",
"sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775",
"sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375",
"sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b",
"sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b",
"sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f"
"sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
"sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
"sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
"sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
"sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
"sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
"sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
"sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
"sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
"sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
"sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
"sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
"sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
"sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
"sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
"sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
"sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
"sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
"sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
"sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
"sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
"sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
"sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
"sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
"sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
"sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
"sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
"sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
"sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
"sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
"sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
"sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
"sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
"sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
"sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
"sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
"sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
],
"version": "==1.14.4"
"version": "==1.14.5"
},
"channels": {
"hashes": [
@ -223,15 +271,20 @@
},
"cryptography": {
"hashes": [
"sha256:287032b6a7d86abc98e8e977b20138c53fea40e5b24e29090d5a675a973dcd10",
"sha256:288c65eea20bd89b11102c47b118bc1e0749386b0a0dfebba414076c5d4c8188",
"sha256:7eed937ad9b53280a5f53570d3a7dc93cb4412b6a3d58d4c6bb78cc26319c729",
"sha256:dab437c2e84628703e3358f0f06555a6259bc5039209d51aa3b05af667ff4fd0",
"sha256:ee5e19f0856b6fbbdbab15c2787ca65d203801d2d65d0b8de6218f424206c848",
"sha256:f21be9ec6b44c223b2024bbe59d394fadc7be320d18a8d595419afadb6cd5620",
"sha256:f6ea140d2736b7e1f0de4f988c43f76b0b3f3d365080e091715429ba218dce28"
"sha256:066bc53f052dfeda2f2d7c195cf16fb3e5ff13e1b6b7415b468514b40b381a5b",
"sha256:0923ba600d00718d63a3976f23cab19aef10c1765038945628cd9be047ad0336",
"sha256:2d32223e5b0ee02943f32b19245b61a62db83a882f0e76cc564e1cec60d48f87",
"sha256:4169a27b818de4a1860720108b55a2801f32b6ae79e7f99c00d79f2a2822eeb7",
"sha256:57ad77d32917bc55299b16d3b996ffa42a1c73c6cfa829b14043c561288d2799",
"sha256:5ecf2bcb34d17415e89b546dbb44e73080f747e504273e4d4987630493cded1b",
"sha256:600cf9bfe75e96d965509a4c0b2b183f74a4fa6f5331dcb40fb7b77b7c2484df",
"sha256:66b57a9ca4b3221d51b237094b0303843b914b7d5afd4349970bb26518e350b0",
"sha256:93cfe5b7ff006de13e1e89830810ecbd014791b042cbe5eec253be11ac2b28f3",
"sha256:9e98b452132963678e3ac6c73f7010fe53adf72209a32854d55690acac3f6724",
"sha256:df186fcbf86dc1ce56305becb8434e4b6b7504bc724b71ad7a3239e0c9d14ef2",
"sha256:fec7fb46b10da10d9e1d078d1ff8ed9e05ae14f431fdbd11145edd0550b9a964"
],
"version": "==3.4.4"
"version": "==3.4.6"
},
"dacite": {
"hashes": [
@ -250,19 +303,19 @@
},
"defusedxml": {
"hashes": [
"sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93",
"sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"
"sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69",
"sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"
],
"index": "pypi",
"version": "==0.6.0"
"version": "==0.7.1"
},
"django": {
"hashes": [
"sha256:169e2e7b4839a7910b393eec127fd7cbae62e80fa55f89c6510426abf673fe5f",
"sha256:c6c0462b8b361f8691171af1fb87eceb4442da28477e12200c40420176206ba7"
"sha256:32ce792ee9b6a0cbbec340123e229ac9f765dff8c2a4ae9247a14b2ba3a365a7",
"sha256:baf099db36ad31f970775d0be5587cc58a6256a6771a44eb795b554d45f211b8"
],
"index": "pypi",
"version": "==3.1.6"
"version": "==3.1.7"
},
"django-cors-middleware": {
"hashes": [
@ -319,13 +372,6 @@
"index": "pypi",
"version": "==2.1.0"
},
"django-recaptcha": {
"hashes": [
"sha256:567784963fd5400feaf92e8951d8dbbbdb4b4c48a76e225d4baa63a2c9d2cd8c"
],
"index": "pypi",
"version": "==2.0.6"
},
"django-redis": {
"hashes": [
"sha256:1133b26b75baa3664164c3f44b9d5d133d1b8de45d94d79f38d1adc5b1d502e5",
@ -360,11 +406,11 @@
},
"docker": {
"hashes": [
"sha256:0604a74719d5d2de438753934b755bfcda6f62f49b8e4b30969a4b0a2a8a1220",
"sha256:e455fa49aabd4f22da9f4e1c1f9d16308286adc60abaf64bf3e1feafaed81d06"
"sha256:d3393c878f575d3a9ca3b94471a3c89a6d960b35feb92f033c0de36cc9d934db",
"sha256:f3607d5695be025fa405a12aca2e5df702a57db63790c73b927eb6a94aac60af"
],
"index": "pypi",
"version": "==4.4.1"
"version": "==4.4.4"
},
"drf-yasg2": {
"hashes": [
@ -388,12 +434,20 @@
],
"version": "==0.18.2"
},
"geoip2": {
"hashes": [
"sha256:57d8d15de2527e0697bbef44fc16812bba709f03a07ef99297bd56c1df3b1efd",
"sha256:707025542ef076bd8fd80e97138bebdb7812527b2a007d141a27ad98b0370fff"
],
"index": "pypi",
"version": "==4.1.0"
},
"google-auth": {
"hashes": [
"sha256:008e23ed080674f69f9d2d7d80db4c2591b9bb307d136cea7b3bc129771d211d",
"sha256:514e39f4190ca972200ba33876da5a8857c5665f2b4ccc36c8b8ee21228aae80"
"sha256:63a5636d7eacfe6ef5b7e36e112b3149fa1c5b5ad77dd6df54910459bcd6b89f",
"sha256:d8958af6968e4ecd599f82357ebcfeb126f826ed0656126ad68416f810f7531e"
],
"version": "==1.25.0"
"version": "==1.27.1"
},
"gunicorn": {
"hashes": [
@ -494,10 +548,10 @@
},
"incremental": {
"hashes": [
"sha256:717e12246dddf231a349175f48d74d93e2897244939173b01974ab6661406b9f",
"sha256:7b751696aaf36eebfab537e458929e194460051ccad279c72b755a167eebd4b3"
"sha256:02f5de5aff48f6b9f665d99d48bfc7ec03b6e3943210de7cfc88856d755d6f57",
"sha256:92014aebc6a20b78a8084cdd5645eeaa7f74b8933f70fa3ada2cfbd1e3b54321"
],
"version": "==17.5.0"
"version": "==21.3.0"
},
"inflection": {
"hashes": [
@ -657,6 +711,12 @@
],
"version": "==1.1.1"
},
"maxminddb": {
"hashes": [
"sha256:47e86a084dd814fac88c99ea34ba3278a74bc9de5a25f4b815b608798747c7dc"
],
"version": "==2.0.3"
},
"msgpack": {
"hashes": [
"sha256:0cb94ee48675a45d3b86e61d13c1e6f1696f0183f0715544976356ff86f741d9",
@ -690,6 +750,48 @@
],
"version": "==1.0.2"
},
"multidict": {
"hashes": [
"sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a",
"sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93",
"sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632",
"sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656",
"sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79",
"sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7",
"sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d",
"sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5",
"sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224",
"sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26",
"sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea",
"sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348",
"sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6",
"sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76",
"sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1",
"sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f",
"sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952",
"sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a",
"sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37",
"sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9",
"sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359",
"sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8",
"sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da",
"sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3",
"sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d",
"sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf",
"sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841",
"sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d",
"sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93",
"sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f",
"sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647",
"sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635",
"sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456",
"sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda",
"sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5",
"sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281",
"sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80"
],
"version": "==5.1.0"
},
"oauthlib": {
"hashes": [
"sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889",
@ -714,10 +816,10 @@
},
"prompt-toolkit": {
"hashes": [
"sha256:7e966747c18ececaec785699626b771c1ba8344c8d31759a1915d6b12fad6525",
"sha256:c96b30925025a7635471dc083ffb6af0cc67482a00611bd81aeaeeeb7e5a5e12"
"sha256:4cea7d09e46723885cb8bc54678175453e5071e9449821dce6f017b1d1fbfc1a",
"sha256:9397a7162cf45449147ad6042fa37983a081b8a73363a5253dd4072666333137"
],
"version": "==3.0.14"
"version": "==3.0.17"
},
"psycopg2-binary": {
"hashes": [
@ -921,27 +1023,27 @@
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
"sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
"sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
"sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
"sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
"sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
"sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
"sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
"sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
],
"index": "pypi",
"version": "==5.4.1"
},
"qrcode": {
"hashes": [
"sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5",
"sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369"
],
"index": "pypi",
"version": "==6.1"
},
"redis": {
"hashes": [
"sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2",
@ -966,18 +1068,55 @@
},
"rsa": {
"hashes": [
"sha256:69805d6b69f56eb05b62daea3a7dbd7aa44324ad1306445e05da8060232d00f4",
"sha256:a8774e55b59fd9fc893b0d05e9bfc6f47081f46ff5b46f39ccf24631b7be356b"
"sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2",
"sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9"
],
"markers": "python_version >= '3.6'",
"version": "==4.7"
"version": "==4.7.2"
},
"ruamel.yaml": {
"hashes": [
"sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5",
"sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e"
"sha256:64b06e7873eb8e1125525ecef7345447d786368cadca92a7cd9b59eae62e95a3",
"sha256:bb48c514222702878759a05af96f4b7ecdba9b33cd4efcf25c86b882cef3a942"
],
"version": "==0.16.12"
"version": "==0.16.13"
},
"ruamel.yaml.clib": {
"hashes": [
"sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b",
"sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f",
"sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c",
"sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91",
"sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc",
"sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7",
"sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3",
"sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7",
"sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6",
"sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6",
"sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd",
"sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0",
"sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62",
"sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99",
"sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5",
"sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026",
"sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb",
"sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2",
"sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1",
"sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4",
"sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b",
"sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923",
"sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e",
"sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c",
"sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988",
"sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f",
"sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5",
"sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a",
"sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1",
"sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2",
"sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f"
],
"markers": "platform_python_implementation == 'CPython' and python_version < '3.10'",
"version": "==0.2.2"
},
"s3transfer": {
"hashes": [
@ -988,11 +1127,11 @@
},
"sentry-sdk": {
"hashes": [
"sha256:0a711ec952441c2ec89b8f5d226c33bc697914f46e876b44a4edd3e7864cf4d0",
"sha256:737a094e49a529dd0fdcaafa9e97cf7c3d5eb964bd229821d640bc77f3502b3f"
"sha256:71de00c9711926816f750bc0f57ef2abbcb1bfbdf5378c601df7ec978f44857a",
"sha256:9221e985f425913204989d0e0e1cbb719e8b7fa10540f1bc509f660c06a34e66"
],
"index": "pypi",
"version": "==0.19.5"
"version": "==1.0.0"
},
"service-identity": {
"hashes": [
@ -1018,11 +1157,11 @@
},
"structlog": {
"hashes": [
"sha256:33dd6bd5f49355e52c1c61bb6a4f20d0b48ce0328cc4a45fe872d38b97a05ccd",
"sha256:af79dfa547d104af8d60f86eac12fb54825f54a46bc998e4504ef66177103174"
"sha256:62f06fc0ee32fb8580f0715eea66cb87271eb7efb0eaf9af6b639cba8981de47",
"sha256:d9d2d890532e8db83c6977a2a676fb1889922ff0c26ad4dc0ecac26f9fafbc57"
],
"index": "pypi",
"version": "==20.2.0"
"version": "==21.1.0"
},
"swagger-spec-validator": {
"hashes": [
@ -1061,14 +1200,23 @@
"sha256:f058bd0168271de4dcdc39845b52dd0a4a2fecf5f1246335f13f5e96eaebb467",
"sha256:f3c19e5bd42bbe4bf345704ad7c326c74d3fd7a1b3844987853bef180be638d4"
],
"index": "pypi",
"version": "==20.3.0"
},
"txaio": {
"hashes": [
"sha256:1488d31d564a116538cc1265ac3f7979fb6223bb5a9e9f1479436ee2c17d8549",
"sha256:a8676d6c68aea1f0e2548c4afdb8e6253873af3bc2659bb5bcd9f39dff7ff90f"
"sha256:7d6f89745680233f1c4db9ddb748df5e88d2a7a37962be174c0fd04c8dba1dc8",
"sha256:c16b55f9a67b2419cfdf8846576e2ec9ba94fe6978a83080c352a80db31c93fb"
],
"version": "==20.12.1"
"version": "==21.2.1"
},
"typing-extensions": {
"hashes": [
"sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
"sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
"sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
],
"version": "==3.7.4.3"
},
"uritemplate": {
"hashes": [
@ -1093,25 +1241,26 @@
"standard"
],
"hashes": [
"sha256:1079c50a06f6338095b4f203e7861dbff318dde5f22f3a324fc6e94c7654164c",
"sha256:ef1e0bb5f7941c6fe324e06443ddac0331e1632a776175f87891c7bd02694355"
"sha256:3292251b3c7978e8e4a7868f4baf7f7f7bb7e40c759ecc125c37e99cdea34202",
"sha256:7587f7b08bd1efd2b9bad809a3d333e972f1d11af8a5e52a9371ee3a5de71524"
],
"index": "pypi",
"version": "==0.13.3"
"version": "==0.13.4"
},
"uvloop": {
"hashes": [
"sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd",
"sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e",
"sha256:4315d2ec3ca393dd5bc0b0089d23101276778c304d42faff5dc4579cb6caef09",
"sha256:4544dcf77d74f3a84f03dd6278174575c44c67d7165d4c42c71db3fdc3860726",
"sha256:afd5513c0ae414ec71d24f6f123614a80f3d27ca655a4fcf6cabe50994cc1891",
"sha256:b4f591aa4b3fa7f32fb51e2ee9fea1b495eb75b0b3c8d0ca52514ad675ae63f7",
"sha256:bcac356d62edd330080aed082e78d4b580ff260a677508718f88016333e2c9c5",
"sha256:e7514d7a48c063226b7d06617cbb12a14278d4323a065a8d46a7962686ce2e95",
"sha256:f07909cd9fc08c52d294b1570bba92186181ca01fe3dc9ffba68955273dd7362"
"sha256:114543c84e95df1b4ff546e6e3a27521580466a30127f12172a3278172ad68bc",
"sha256:19fa1d56c91341318ac5d417e7b61c56e9a41183946cc70c411341173de02c69",
"sha256:2bb0624a8a70834e54dde8feed62ed63b50bad7a1265c40d6403a2ac447bce01",
"sha256:42eda9f525a208fbc4f7cecd00fa15c57cc57646c76632b3ba2fe005004f051d",
"sha256:44cac8575bf168601424302045234d74e3561fbdbac39b2b54cc1d1d00b70760",
"sha256:6de130d0cb78985a5d080e323b86c5ecaf3af82f4890492c05981707852f983c",
"sha256:7ae39b11a5f4cec1432d706c21ecc62f9e04d116883178b09671aa29c46f7a47",
"sha256:90e56f17755e41b425ad19a08c41dc358fa7bf1226c0f8e54d4d02d556f7af7c",
"sha256:b45218c99795803fb8bdbc9435ff7f54e3a591b44cd4c121b02fa83affb61c7c",
"sha256:e5e5f855c9bf483ee6cd1eb9a179b740de80cb0ae2988e3fa22309b78e2ea0e7"
],
"version": "==0.14.0"
"version": "==0.15.2"
},
"vine": {
"hashes": [
@ -1122,10 +1271,10 @@
},
"watchgod": {
"hashes": [
"sha256:59700dab7445aa8e6067a5b94f37bae90fc367554549b1ed2e9d0f4f38a90d2a",
"sha256:e9cca0ab9c63f17fc85df9fd8bd18156ff00aff04ebe5976cee473f4968c6858"
"sha256:48140d62b0ebe9dd9cf8381337f06351e1f2e70b2203fa9c6eff4e572ca84f29",
"sha256:d6c1ea21df37847ac0537ca0d6c2f4cdf513562e95f77bb93abbcf05573407b7"
],
"version": "==0.6"
"version": "==0.7"
},
"wcwidth": {
"hashes": [
@ -1134,12 +1283,20 @@
],
"version": "==0.2.5"
},
"webauthn": {
"hashes": [
"sha256:238391b2e2cc60fb51a2cd2d2d6be149920b9af6184651353d9f95856617a9e7",
"sha256:8ad9072ff1d6169f3be30d4dc8733ea563dd266962397bc58b40f674a6af74ac"
],
"index": "pypi",
"version": "==0.4.7"
},
"websocket-client": {
"hashes": [
"sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549",
"sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010"
"sha256:44b5df8f08c74c3d82d28100fdc81f4536809ce98a17f0757557813275fbb663",
"sha256:63509b41d158ae5b7f67eb4ad20fecbb4eee99434e73e140354dc3ff8e09716f"
],
"version": "==0.57.0"
"version": "==0.58.0"
},
"websockets": {
"hashes": [
@ -1187,6 +1344,48 @@
"index": "pypi",
"version": "==1.3.9"
},
"yarl": {
"hashes": [
"sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e",
"sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434",
"sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366",
"sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3",
"sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec",
"sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959",
"sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e",
"sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c",
"sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6",
"sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a",
"sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6",
"sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424",
"sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e",
"sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f",
"sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50",
"sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2",
"sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc",
"sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4",
"sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970",
"sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10",
"sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0",
"sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406",
"sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896",
"sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643",
"sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721",
"sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478",
"sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724",
"sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e",
"sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8",
"sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96",
"sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25",
"sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76",
"sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2",
"sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2",
"sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c",
"sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a",
"sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71"
],
"version": "==1.6.3"
},
"zope.interface": {
"hashes": [
"sha256:05a97ba92c1c7c26f25c9f671aa1ef85ffead6cdad13770e5b689cf983adc7e1",
@ -1253,13 +1452,6 @@
],
"version": "==1.4.4"
},
"asgiref": {
"hashes": [
"sha256:5ee950735509d04eb673bd7f7120f8fa1c9e2df495394992c73234d526907e17",
"sha256:7162a3cb30ab0609f1a4c95938fd73e8604f63bdba516a7f7d64b83ff09478f0"
],
"version": "==3.3.1"
},
"astroid": {
"hashes": [
"sha256:4c17cea3e592c21b6e222f673868961bad77e1f985cb1694ed077475a89229c1",
@ -1329,74 +1521,61 @@
},
"coverage": {
"hashes": [
"sha256:03ed2a641e412e42cc35c244508cf186015c217f0e4d496bf6d7078ebe837ae7",
"sha256:04b14e45d6a8e159c9767ae57ecb34563ad93440fc1b26516a89ceb5b33c1ad5",
"sha256:0cdde51bfcf6b6bd862ee9be324521ec619b20590787d1655d005c3fb175005f",
"sha256:0f48fc7dc82ee14aeaedb986e175a429d24129b7eada1b7e94a864e4f0644dde",
"sha256:107d327071061fd4f4a2587d14c389a27e4e5c93c7cba5f1f59987181903902f",
"sha256:1375bb8b88cb050a2d4e0da901001347a44302aeadb8ceb4b6e5aa373b8ea68f",
"sha256:14a9f1887591684fb59fdba8feef7123a0da2424b0652e1b58dd5b9a7bb1188c",
"sha256:16baa799ec09cc0dcb43a10680573269d407c159325972dd7114ee7649e56c66",
"sha256:1b811662ecf72eb2d08872731636aee6559cae21862c36f74703be727b45df90",
"sha256:1ccae21a076d3d5f471700f6d30eb486da1626c380b23c70ae32ab823e453337",
"sha256:2f2cf7a42d4b7654c9a67b9d091ec24374f7c58794858bff632a2039cb15984d",
"sha256:322549b880b2d746a7672bf6ff9ed3f895e9c9f108b714e7360292aa5c5d7cf4",
"sha256:32ab83016c24c5cf3db2943286b85b0a172dae08c58d0f53875235219b676409",
"sha256:3fe50f1cac369b02d34ad904dfe0771acc483f82a1b54c5e93632916ba847b37",
"sha256:4a780807e80479f281d47ee4af2eb2df3e4ccf4723484f77da0bb49d027e40a1",
"sha256:4a8eb7785bd23565b542b01fb39115a975fefb4a82f23d407503eee2c0106247",
"sha256:5bee3970617b3d74759b2d2df2f6a327d372f9732f9ccbf03fa591b5f7581e39",
"sha256:60a3307a84ec60578accd35d7f0c71a3a971430ed7eca6567399d2b50ef37b8c",
"sha256:6625e52b6f346a283c3d563d1fd8bae8956daafc64bb5bbd2b8f8a07608e3994",
"sha256:66a5aae8233d766a877c5ef293ec5ab9520929c2578fd2069308a98b7374ea8c",
"sha256:68fb816a5dd901c6aff352ce49e2a0ffadacdf9b6fae282a69e7a16a02dad5fb",
"sha256:6b588b5cf51dc0fd1c9e19f622457cc74b7d26fe295432e434525f1c0fae02bc",
"sha256:6c4d7165a4e8f41eca6b990c12ee7f44fef3932fac48ca32cecb3a1b2223c21f",
"sha256:6d2e262e5e8da6fa56e774fb8e2643417351427604c2b177f8e8c5f75fc928ca",
"sha256:6d9c88b787638a451f41f97446a1c9fd416e669b4d9717ae4615bd29de1ac135",
"sha256:755c56beeacac6a24c8e1074f89f34f4373abce8b662470d3aa719ae304931f3",
"sha256:7e40d3f8eb472c1509b12ac2a7e24158ec352fc8567b77ab02c0db053927e339",
"sha256:812eaf4939ef2284d29653bcfee9665f11f013724f07258928f849a2306ea9f9",
"sha256:84df004223fd0550d0ea7a37882e5c889f3c6d45535c639ce9802293b39cd5c9",
"sha256:859f0add98707b182b4867359e12bde806b82483fb12a9ae868a77880fc3b7af",
"sha256:87c4b38288f71acd2106f5d94f575bc2136ea2887fdb5dfe18003c881fa6b370",
"sha256:89fc12c6371bf963809abc46cced4a01ca4f99cba17be5e7d416ed7ef1245d19",
"sha256:9564ac7eb1652c3701ac691ca72934dd3009997c81266807aef924012df2f4b3",
"sha256:9754a5c265f991317de2bac0c70a746efc2b695cf4d49f5d2cddeac36544fb44",
"sha256:a565f48c4aae72d1d3d3f8e8fb7218f5609c964e9c6f68604608e5958b9c60c3",
"sha256:a636160680c6e526b84f85d304e2f0bb4e94f8284dd765a1911de9a40450b10a",
"sha256:a839e25f07e428a87d17d857d9935dd743130e77ff46524abb992b962eb2076c",
"sha256:b62046592b44263fa7570f1117d372ae3f310222af1fc1407416f037fb3af21b",
"sha256:b7f7421841f8db443855d2854e25914a79a1ff48ae92f70d0a5c2f8907ab98c9",
"sha256:ba7ca81b6d60a9f7a0b4b4e175dcc38e8fef4992673d9d6e6879fd6de00dd9b8",
"sha256:bb32ca14b4d04e172c541c69eec5f385f9a075b38fb22d765d8b0ce3af3a0c22",
"sha256:c0ff1c1b4d13e2240821ef23c1efb1f009207cb3f56e16986f713c2b0e7cd37f",
"sha256:c669b440ce46ae3abe9b2d44a913b5fd86bb19eb14a8701e88e3918902ecd345",
"sha256:c67734cff78383a1f23ceba3b3239c7deefc62ac2b05fa6a47bcd565771e5880",
"sha256:c6809ebcbf6c1049002b9ac09c127ae43929042ec1f1dbd8bb1615f7cd9f70a0",
"sha256:cd601187476c6bed26a0398353212684c427e10a903aeafa6da40c63309d438b",
"sha256:ebfa374067af240d079ef97b8064478f3bf71038b78b017eb6ec93ede1b6bcec",
"sha256:fbb17c0d0822684b7d6c09915677a32319f16ff1115df5ec05bdcaaee40b35f3",
"sha256:fff1f3a586246110f34dc762098b5afd2de88de507559e63553d7da643053786"
"sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c",
"sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6",
"sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45",
"sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a",
"sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03",
"sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529",
"sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a",
"sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a",
"sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2",
"sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6",
"sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759",
"sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53",
"sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a",
"sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4",
"sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff",
"sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502",
"sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793",
"sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb",
"sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905",
"sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821",
"sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b",
"sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81",
"sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0",
"sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b",
"sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3",
"sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184",
"sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701",
"sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a",
"sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82",
"sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638",
"sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5",
"sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083",
"sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6",
"sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90",
"sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465",
"sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a",
"sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3",
"sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e",
"sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066",
"sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf",
"sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b",
"sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae",
"sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669",
"sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873",
"sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b",
"sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6",
"sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb",
"sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160",
"sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c",
"sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079",
"sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d",
"sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"
],
"index": "pypi",
"version": "==5.4"
},
"django": {
"hashes": [
"sha256:169e2e7b4839a7910b393eec127fd7cbae62e80fa55f89c6510426abf673fe5f",
"sha256:c6c0462b8b361f8691171af1fb87eceb4442da28477e12200c40420176206ba7"
],
"index": "pypi",
"version": "==3.1.6"
},
"django-debug-toolbar": {
"hashes": [
"sha256:84e2607d900dbd571df0a2acf380b47c088efb787dce9805aefeb407341961d2",
"sha256:9e5a25d0c965f7e686f6a8ba23613ca9ca30184daa26487706d4829f5cfb697a"
],
"index": "pypi",
"version": "==3.2"
"version": "==5.5"
},
"dodgy": {
"hashes": [
@ -1428,10 +1607,10 @@
},
"gitpython": {
"hashes": [
"sha256:8621a7e777e276a5ec838b59280ba5272dd144a18169c36c903d8b38b99f750a",
"sha256:c5347c81d232d9b8e7f47b68a83e5dc92e7952127133c5f2df9133f2c75a1b29"
"sha256:3283ae2fba31c913d857e12e5ba5f9a7772bbc064ae2bb09efafa71b0dd4939b",
"sha256:be27633e7509e58391f10207cd32b2a6cf5b908f92d9cd30da2e514e1137af61"
],
"version": "==3.1.13"
"version": "==3.1.14"
},
"iniconfig": {
"hashes": [
@ -1616,13 +1795,6 @@
"index": "pypi",
"version": "==4.1.0"
},
"pytz": {
"hashes": [
"sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
"sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
],
"version": "==2021.1"
},
"pyyaml": {
"hashes": [
"sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf",
@ -1637,15 +1809,23 @@
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
"sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
"sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
"sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
"sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
"sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
"sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
"sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
"sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
],
"index": "pypi",
"version": "==5.4.1"
@ -1737,13 +1917,6 @@
],
"version": "==2.1.0"
},
"sqlparse": {
"hashes": [
"sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0",
"sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"
],
"version": "==0.4.1"
},
"stevedore": {
"hashes": [
"sha256:3a5bbd0652bf552748871eaa73a4a8dc2899786bc497a2aa1fcb4dcdb0debeee",

View File

@ -1,7 +1,10 @@
<img src="https://goauthentik.io/img/icon_top_brand_colour.svg" height="250" alt="authentik logo">
<p align="center">
<img src="https://goauthentik.io/img/icon_top_brand_colour.svg" height="150" alt="authentik logo">
</p>
---
[![](https://img.shields.io/discord/809154715984199690?label=Discord&style=flat-square)](https://discord.gg/KPnmtNWy)
[![CI Build status](https://img.shields.io/azure-devops/build/beryjuorg/authentik/1?style=flat-square)](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=1)
[![Tests](https://img.shields.io/azure-devops/tests/beryjuorg/authentik/1?compact_message&style=flat-square)](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=1)
[![Code Coverage](https://img.shields.io/codecov/c/gh/beryju/authentik?style=flat-square)](https://codecov.io/gh/BeryJu/authentik)
@ -21,8 +24,10 @@ For bigger setups, there is a Helm Chart in the `helm/` directory. This is docum
## Screenshots
![](https://goauthentik.io/img/screen_apps.png)
![](https://goauthentik.io/img/screen_admin.png)
Light | Dark
--- | ---
![](https://goauthentik.io/img/screen_apps_light.png) | ![](https://goauthentik.io/img/screen_apps_dark.png)
![](https://goauthentik.io/img/screen_admin_light.png) | ![](https://goauthentik.io/img/screen_admin_dark.png)
## Development

View File

@ -4,9 +4,9 @@
| Version | Supported |
| ---------- | ------------------ |
| 0.13.x | :white_check_mark: |
| 0.14.x | :white_check_mark: |
| 2021.1.x | :white_check_mark: |
| 2021.2.x | :white_check_mark: |
| 2021.3.x | :white_check_mark: |
## Reporting a Vulnerability

View File

@ -1,2 +1,3 @@
"""authentik"""
__version__ = "2021.2.6-stable"
__version__ = "2021.3.4"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -2,14 +2,13 @@
import time
from collections import Counter
from datetime import timedelta
from typing import Dict, List
from django.db.models import Count, ExpressionWrapper, F, Model
from django.db.models.fields import DurationField
from django.db.models.functions import ExtractHour
from django.utils.timezone import now
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.fields import SerializerMethodField
from drf_yasg2.utils import swagger_auto_schema, swagger_serializer_method
from rest_framework.fields import IntegerField, SerializerMethodField
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
from rest_framework.response import Response
@ -19,7 +18,7 @@ from rest_framework.viewsets import ViewSet
from authentik.events.models import Event, EventAction
def get_events_per_1h(**filter_kwargs) -> List[Dict[str, int]]:
def get_events_per_1h(**filter_kwargs) -> list[dict[str, int]]:
"""Get event count by hour in the last day, fill with zeros"""
date_from = now() - timedelta(days=1)
result = (
@ -32,29 +31,45 @@ def get_events_per_1h(**filter_kwargs) -> List[Dict[str, int]]:
.annotate(count=Count("pk"))
.order_by("age_hours")
)
data = Counter({d["age_hours"]: d["count"] for d in result})
data = Counter({int(d["age_hours"]): d["count"] for d in result})
results = []
_now = now()
for hour in range(0, -24, -1):
results.append(
{
"x": time.mktime((_now + timedelta(hours=hour)).timetuple()) * 1000,
"y": data[hour * -1],
"x_cord": time.mktime((_now + timedelta(hours=hour)).timetuple())
* 1000,
"y_cord": data[hour * -1],
}
)
return results
class AdministrationMetricsSerializer(Serializer):
class CoordinateSerializer(Serializer):
"""Coordinates for diagrams"""
x_cord = IntegerField(read_only=True)
y_cord = IntegerField(read_only=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model:
raise NotImplementedError
class LoginMetricsSerializer(Serializer):
"""Login Metrics per 1h"""
logins_per_1h = SerializerMethodField()
logins_failed_per_1h = SerializerMethodField()
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
def get_logins_per_1h(self, _):
"""Get successful logins per hour for the last 24 hours"""
return get_events_per_1h(action=EventAction.LOGIN)
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
def get_logins_failed_per_1h(self, _):
"""Get failed logins per hour for the last 24 hours"""
return get_events_per_1h(action=EventAction.LOGIN_FAILED)
@ -71,8 +86,8 @@ class AdministrationMetricsViewSet(ViewSet):
permission_classes = [IsAdminUser]
@swagger_auto_schema(responses={200: AdministrationMetricsSerializer(many=True)})
@swagger_auto_schema(responses={200: LoginMetricsSerializer(many=False)})
def list(self, request: Request) -> Response:
"""Login Metrics per 1h"""
serializer = AdministrationMetricsSerializer(True)
serializer = LoginMetricsSerializer(True)
return Response(serializer.data)

View File

@ -7,14 +7,14 @@ from django.http.response import Http404
from django.utils.translation import gettext_lazy as _
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.fields import CharField, DateTimeField, IntegerField, ListField
from rest_framework.fields import CharField, ChoiceField, DateTimeField, ListField
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.viewsets import ViewSet
from authentik.events.monitored_tasks import TaskInfo
from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus
class TaskSerializer(Serializer):
@ -24,7 +24,10 @@ class TaskSerializer(Serializer):
task_description = CharField()
task_finish_timestamp = DateTimeField(source="finish_timestamp")
status = IntegerField(source="result.status.value")
status = ChoiceField(
source="result.status.name",
choices=[(x.name, x.name) for x in TaskResultStatus],
)
messages = ListField(source="result.messages")
def create(self, validated_data: dict) -> Model:

View File

@ -1,4 +1,6 @@
"""authentik administration overview"""
from os import environ
from django.core.cache import cache
from django.db.models import Model
from drf_yasg2.utils import swagger_auto_schema
@ -11,7 +13,7 @@ from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.viewsets import GenericViewSet
from authentik import __version__
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version
@ -20,8 +22,13 @@ class VersionSerializer(Serializer):
version_current = SerializerMethodField()
version_latest = SerializerMethodField()
build_hash = SerializerMethodField()
outdated = SerializerMethodField()
def get_build_hash(self, _) -> str:
"""Get build hash, if version is not latest or released"""
return environ.get(ENV_GIT_HASH_KEY, "")
def get_version_current(self, _) -> str:
"""Get current version"""
return __version__
@ -55,7 +62,7 @@ class VersionViewSet(ListModelMixin, GenericViewSet):
def get_queryset(self): # pragma: no cover
return None
@swagger_auto_schema(responses={200: VersionSerializer(many=True)})
@swagger_auto_schema(responses={200: VersionSerializer(many=False)})
def list(self, request: Request) -> Response:
"""Get running and latest version."""
return Response(VersionSerializer(True).data)

View File

@ -1,122 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-key"></i>
{% trans 'Certificate-Key Pairs' %}
</h1>
<p>{% trans "Import certificates of external providers or create certificates to sign requests with." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-generate' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Generate' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Private Key available' %}</th>
<th role="columnheader" scope="col">{% trans 'Fingerprint' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for kp in object_list %}
<tr role="row">
<th role="columnheader">
<div>
<div>{{ kp.name }}</div>
</div>
</th>
<td role="cell">
<span>
{% if kp.key_data is not None %}
{% trans 'Yes' %}
{% else %}
{% trans 'No' %}
{% endif %}
</span>
</td>
<td role="cell">
<code>{{ kp.fingerprint }}</code>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-update' pk=kp.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-delete' pk=kp.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-key pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Certificates.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any certificates." %}
{% else %}
{% trans 'Currently no certificates exist. Click the button below to create one.' %}
{% endif %}
</div>
<ak-modal-button href="{% url 'authentik_admin:certificatekeypair-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,135 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-process-automation"></i>
{% trans 'Flows' %}
</h1>
<p>{% trans "Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_admin:flow-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:flow-import' %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Import' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Identifier' %}</th>
<th role="columnheader" scope="col">{% trans 'Designation' %}</th>
<th role="columnheader" scope="col">{% trans 'Stages' %}</th>
<th role="columnheader" scope="col">{% trans 'Policies' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for flow in object_list %}
<tr role="row">
<th role="columnheader">
<a href="/flows/{{ flow.slug }}">
<div><code>{{ flow.slug }}</code></div>
<small>{{ flow.name }}</small>
</a>
</th>
<td role="cell">
<span>
{{ flow.designation }}
</span>
</td>
<td role="cell">
<span>
{{ flow.stages.all|length }}
</span>
</td>
<td role="cell">
<span>
{{ flow.policies.all|length }}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:flow-update' pk=flow.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:flow-delete' pk=flow.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<a class="pf-c-button pf-m-secondary ak-root-link" href="{% url 'authentik_admin:flow-execute' pk=flow.pk %}?next={{ request.get_full_path }}">{% trans 'Execute' %}</a>
<a class="pf-c-button pf-m-secondary ak-root-link" href="{% url 'authentik_admin:flow-export' pk=flow.pk %}?next={{ request.get_full_path }}">{% trans 'Export' %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-process-automation pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Flows.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any flows." %}
{% else %}
{% trans 'Currently no flows exist. Click the button below to create one.' %}
{% endif %}
</div>
<ak-modal-button href="{% url 'authentik_admin:flow-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:flow-import' %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Import' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,114 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-users"></i>
{% trans 'Groups' %}
</h1>
<p>{% trans "Group users together and give them permissions based on the membership." %}
</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_admin:group-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Parent' %}</th>
<th role="columnheader" scope="col">{% trans 'Members' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for group in object_list %}
<tr role="row">
<td role="cell">
<span>
{{ group.name }}
</span>
</td>
<td role="cell">
<span>
{{ group.parent }}
</span>
</td>
<td role="cell">
<span>
{{ group.users.all|length }}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:group-update' pk=group.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:group-delete' pk=group.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-users pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Groups.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any groups." %}
{% else %}
{% trans 'Currently no group exist. Click the button below to create one.' %}
{% endif %}
</div>
<ak-modal-button href="{% url 'authentik_admin:group-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,153 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load humanize %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon-integration"></i>
{% trans 'Outpost Service-Connections' %}
</h1>
<p>{% trans "Outpost Service-Connections define how authentik connects to external platforms to manage and deploy Outposts." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
{% for type, name in types.items %}
<li>
<ak-modal-button href="{% url 'authentik_admin:outpost-service-connection-create' %}?type={{ type }}">
<button slot="trigger" class="pf-c-dropdown__menu-item">
{{ name|verbose_name }}<br>
<small>
{{ name|doc }}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
{% endfor %}
</ul>
</ak-dropdown>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Type' %}</th>
<th role="columnheader" scope="col">{% trans 'Local?' %}</th>
<th role="columnheader" scope="col">{% trans 'Status' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for sc in object_list %}
<tr role="row">
<th role="columnheader">
<span>{{ sc.name }}</span>
</th>
<td role="cell">
<span>
{{ sc|verbose_name }}
</span>
</td>
<td role="cell">
<span>
{{ sc.local|yesno:"Yes,No" }}
</span>
</td>
<td role="cell">
<span>
{% if sc.state.healthy %}
<i class="fas fa-check pf-m-success"></i> {{ sc.state.version }}
{% else %}
<i class="fas fa-times pf-m-danger"></i> {% trans 'Unhealthy' %}
{% endif %}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:outpost-service-connection-update' pk=sc.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:outpost-service-connection-delete' pk=sc.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="fas fa-map-marker pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Outpost Service Connections.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any outposts." %}
{% else %}
{% trans 'Currently no service connections exist. Click the button below to create one.' %}
{% endif %}
</div>
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
{% for type, name in types.items %}
<li>
<ak-modal-button href="{% url 'authentik_admin:outpost-service-connection-create' %}?type={{ type }}">
<button slot="trigger" class="pf-c-dropdown__menu-item">
{{ name|verbose_name }}<br>
<small>
{{ name|doc }}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
{% endfor %}
</ul>
</ak-dropdown>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,151 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-infrastructure"></i>
{% trans 'Policies' %}
</h1>
<p>{% trans "Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
{% for type, name in types.items %}
<li>
<ak-modal-button href="{% url 'authentik_admin:policy-create' %}?type={{ type }}">
<button slot="trigger" class="pf-c-dropdown__menu-item">
{{ name|verbose_name }}<br>
<small>
{{ name|doc }}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
{% endfor %}
</ul>
</ak-dropdown>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Type' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for policy in object_list %}
<tr role="row">
<th role="columnheader">
<div>
<div>{{ policy.name }}</div>
{% if not policy.bindings.exists and not policy.promptstage_set.exists %}
<i class="pf-icon pf-icon-warning-triangle"></i>
<small>{% trans 'Warning: Policy is not assigned.' %}</small>
{% else %}
<i class="pf-icon pf-icon-ok"></i>
<small>{% blocktrans with object_count=policy.bindings.all|length %}Assigned to {{ object_count }} objects.{% endblocktrans %}</small>
{% endif %}
</div>
</th>
<td role="cell">
<span>
{{ policy|verbose_name }}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:policy-update' pk=policy.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:policy-test' pk=policy.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Test' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:policy-delete' pk=policy.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-infrastructure pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Policies.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any policies." %}
{% else %}
{% trans 'Currently no policies exist. Click the button below to create one.' %}
{% endif %}
</div>
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
{% for type, name in types.items %}
<li>
<ak-modal-button href="{% url 'authentik_admin:policy-create' %}?type={{ type }}">
<button slot="trigger" class="pf-c-dropdown__menu-item">
{{ name|verbose_name }}<br>
<small>
{{ name|doc }}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
{% endfor %}
</ul>
</ak-dropdown>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,119 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-infrastructure"></i>
{% trans 'Policy Bindings' %}
</h1>
<p>{% trans "Bind existing Policies to Models accepting policies." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_admin:policy-binding-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Policy' %}</th>
<th role="columnheader" scope="col">{% trans 'Enabled' %}</th>
<th role="columnheader" scope="col">{% trans 'Order' %}</th>
<th role="columnheader" scope="col">{% trans 'Timeout' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for pbm in object_list %}
<tr role="role">
<td>
{{ pbm }}
<small>
{{ pbm|fieldtype }}
</small>
</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
{% for binding in pbm.bindings %}
<tr class="row pf-c-table__expandable-row pf-m-expanded">
<th role="cell">
<div>{{ binding.policy }}</div>
<small>
{{ binding.policy|fieldtype }}
</small>
</th>
<th role="cell">
<div>{{ binding.enabled }}</div>
</th>
<th role="cell">
<div>{{ binding.order }}</div>
</th>
<th role="cell">
<div>{{ binding.timeout }}</div>
</th>
<td>
<ak-modal-button href="{% url 'authentik_admin:policy-binding-update' pk=binding.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:policy-binding-delete' pk=binding.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="fas fa-cubes pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Policy Bindings.' %}
</h1>
<div class="pf-c-empty-state__body">
{% trans 'Currently no policy bindings exist. Click the button below to create one.' %}
</div>
<ak-modal-button href="{% url 'authentik_admin:policy-binding-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,28 +0,0 @@
{% extends 'generic/form.html' %}
{% load i18n %}
{% block above_form %}
<h1>{% blocktrans with property_mapping=property_mapping %}Test {{ property_mapping }}{% endblocktrans %}</h1>
{% endblock %}
{% block beneath_form %}
{% if result %}
<div class="pf-c-form__group ">
<div class="pf-c-form__group-label">
<label class="pf-c-form__label" for="context-1">
<span class="pf-c-form__label-text">{% trans 'Result' %}</span>
</label>
</div>
<div class="pf-c-form__group-control">
<div class="c-form__horizontal-group">
<ak-codemirror mode="javascript"><textarea class="pf-c-form-control">{{ result }}</textarea></ak-codemirror>
</div>
</div>
</div>
{% endif %}
{% endblock %}
{% block action %}
{% trans 'Test' %}
{% endblock %}

View File

@ -1,148 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-middleware"></i>
{% trans 'Source' %}
</h1>
<p>{% trans "External Sources which can be used to get Identities into authentik, for example Social Providers like Twiter and GitHub or Enterprise Providers like ADFS and LDAP." %}
</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
{% for type, name in types.items %}
<li>
<ak-modal-button href="{% url 'authentik_admin:source-create' %}?type={{ type }}">
<button slot="trigger" class="pf-c-dropdown__menu-item">
{{ name|verbose_name }}<br>
<small>
{{ name|doc }}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
{% endfor %}
</ul>
</ak-dropdown>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Type' %}</th>
<th role="columnheader" scope="col">{% trans 'Additional Info' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for source in object_list %}
<tr role="row">
<th role="columnheader">
<a href="/sources/{{ source.slug }}">
<div>{{ source.name }}</div>
{% if not source.enabled %}
<small>{% trans 'Disabled' %}</small>
{% endif %}
</a>
</th>
<td role="cell">
<span>
{{ source|fieldtype }}
</span>
</td>
<td role="cell">
<span>
{{ source.ui_additional_info|default:""|safe }}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:source-update' pk=source.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:source-delete' pk=source.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-middleware pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Sources.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any sources." %}
{% else %}
{% trans 'Currently no sources exist. Click the button below to create one.' %}
{% endif %}
</div>
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
{% for type, name in types.items %}
<li>
<ak-modal-button href="{% url 'authentik_admin:source-create' %}?type={{ type }}">
<button slot="trigger" class="pf-c-dropdown__menu-item">
{{ name|verbose_name }}<br>
<small>
{{ name|doc }}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
{% endfor %}
</ul>
</ak-dropdown>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,143 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-plugged"></i>
{% trans 'Stages' %}
</h1>
<p>{% trans "Stages are single steps of a Flow that a user is guided through." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
{% for type, name in types.items %}
<li>
<ak-modal-button href="{% url 'authentik_admin:stage-create' %}?type={{ type }}">
<button slot="trigger" class="pf-c-dropdown__menu-item">
{{ name|verbose_name }}<br>
<small>
{{ name|doc }}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
{% endfor %}
</ul>
</ak-dropdown>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Flows' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for stage in object_list %}
<tr role="row">
<th role="columnheader">
<div>
<div>{{ stage.name }}</div>
<small>{{ stage|verbose_name }}</small>
</div>
</th>
<td role="cell">
<ul>
{% for flow in stage.flow_set.all %}
<li>{{ flow.slug }}<</li>
{% empty %}
<li>-</li>
{% endfor %}
</ul>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:stage-update' pk=stage.stage_uuid %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:stage-delete' pk=stage.stage_uuid %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-plugged pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Stages.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any stages." %}
{% else %}
{% trans 'Currently no stages exist. Click the button below to create one.' %}
{% endif %}
</div>
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">{% trans 'Create' %}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
{% for type, name in types.items %}
<li>
<ak-modal-button href="{% url 'authentik_admin:stage-create' %}?type={{ type }}">
<button slot="trigger" class="pf-c-dropdown__menu-item">
{{ name|verbose_name }}<br>
<small>
{{ name|doc }}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
{% endfor %}
</ul>
</ak-dropdown>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,125 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-infrastructure"></i>
{% trans 'Stage Bindings' %}
</h1>
<p>{% trans "Bind existing Stages to Flows." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_admin:stage-binding-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Order' %}</th>
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Stage Type' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% regroup object_list by target as grouped_bindings %}
{% for flow in grouped_bindings %}
<tr role="role">
<td>
{% blocktrans with slug=flow.grouper.slug %}
Flow {{ slug }}
{% endblocktrans %}
</td>
<td></td>
<td></td>
<td></td>
</tr>
{% for binding in flow.list %}
<tr class="pf-c-table__expandable-row pf-m-expanded" role="row">
<td role="cell">
<span>
{{ binding.order }}
</span>
</td>
<th role="columnheader">
<div>
<div>{{ binding.target.slug }}</div>
<small>
{{ binding.target.name }}
</small>
</div>
</th>
<td role="cell">
<div>
<div>
{{ binding.stage.name }}
</div>
<small>
{{ binding.stage }}
</small>
</div>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:stage-binding-update' pk=binding.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Update' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:stage-binding-delete' pk=binding.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="fas fa-cubes pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Flow-Stage Bindings.' %}
</h1>
<div class="pf-c-empty-state__body">
{% trans 'Currently no flow-stage bindings exist. Click the button below to create one.' %}
</div>
<ak-modal-button href="{% url 'authentik_admin:stage-binding-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,109 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-migration"></i>
{% trans 'Invitations' %}
</h1>
<p>{% trans "Create Invitation Links to enroll Users, and optionally force specific attributes of their account." %}
</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_admin:stage-invitation-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'ID' %}</th>
<th role="columnheader" scope="col">{% trans 'Created by' %}</th>
<th role="columnheader" scope="col">{% trans 'Expiry' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for invitation in object_list %}
<tr role="row">
<td role="cell">
<span>
{{ invitation.invite_uuid }}
</span>
</td>
<td role="cell">
<span>
{{ invitation.created_by }}
</span>
</td>
<td role="cell">
<span>
{{ invitation.expiry|default:"-" }}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:stage-invitation-delete' pk=invitation.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-migration pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Invitations.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any invitations." %}
{% else %}
{% trans 'Currently no invitations exist. Click the button below to create one.' %}
{% endif %}
</div>
<ak-modal-button href="{% url 'authentik_admin:stage-invitation-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,125 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-plugged"></i>
{% trans 'Prompts' %}
</h1>
<p>{% trans "Single Prompts that can be used for Prompt Stages." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_admin:stage-prompt-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Field' %}</th>
<th role="columnheader" scope="col">{% trans 'Label' %}</th>
<th role="columnheader" scope="col">{% trans 'Type' %}</th>
<th role="columnheader" scope="col">{% trans 'Order' %}</th>
<th role="columnheader" scope="col">{% trans 'Flows' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for prompt in object_list %}
<tr role="row">
<th role="columnheader">
<div>
<div>{{ prompt.field_key }}</div>
</div>
</th>
<td role="cell">
<div>
{{ prompt.label }}
</div>
</td>
<td role="cell">
<div>
{{ prompt.type }}
</div>
</td>
<td role="cell">
<div>
{{ prompt.order }}
</div>
</td>
<td role="cell">
<ul>
{% for flow in prompt.flow_set.all %}
<li>{{ flow.slug }}</li>
{% empty %}
<li>-</li>
{% endfor %}
</ul>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:stage-prompt-update' pk=prompt.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Update' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_admin:stage-prompt-delete' pk=prompt.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-plugged pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Stage Prompts.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any stage prompts." %}
{% else %}
{% trans 'Currently no stage prompts exist. Click the button below to create one.' %}
{% endif %}
</div>
<a href="{% url 'authentik_admin:stage-prompt-create' %}?back={{ request.get_full_path }}" class="pf-c-button pf-m-primary" type="button">{% trans 'Create' %}</a>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,84 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load humanize %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-automation"></i>
{% trans 'System Tasks' %}
</h1>
<p>{% trans "Long-running operations which authentik executes in the background." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Identifier' %}</th>
<th role="columnheader" scope="col">{% trans 'Description' %}</th>
<th role="columnheader" scope="col">{% trans 'Last Run' %}</th>
<th role="columnheader" scope="col">{% trans 'Status' %}</th>
<th role="columnheader" scope="col">{% trans 'Messages' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for task in object_list %}
<tr role="row">
<th role="columnheader">
<span>{{ task.html_name|join:"_&shy;" }}</span>
</th>
<td role="cell">
<span>
{{ task.task_description }}
</span>
</td>
<td role="cell">
<span>
{{ task.finish_timestamp|naturaltime }}
</span>
</td>
<td role="cell">
<span>
{% if task.result.status == task_successful %}
<i class="fas fa-check pf-m-success"></i> {% trans 'Successful' %}
{% elif task.result.status == task_warning %}
<i class="fas fa-exclamation-triangle pf-m-warning"></i> {% trans 'Warning' %}
{% elif task.result.status == task_error %}
<i class="fas fa-times pf-m-danger"></i> {% trans 'Error' %}
{% else %}
<i class="fas fa-question-circle"></i> {% trans 'Unknown' %}
{% endif %}
</span>
</td>
<td>
{% for message in task.result.messages %}
<div>
{{ message }}
</div>
{% endfor %}
</td>
<td>
<ak-action-button url="{% url 'authentik_api:admin_system_tasks-retry' pk=task.task_name %}">
{% trans 'Retry Task' %}
</ak-action-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
{% endblock %}

View File

@ -1,102 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-security"></i>
{% trans 'Tokens' %}
</h1>
<p>{% trans "Tokens are used throughout authentik for Email validation stages, Recovery keys and API access." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Identifier' %}</th>
<th role="columnheader" scope="col">{% trans 'User' %}</th>
<th role="columnheader" scope="col">{% trans 'Expires?' %}</th>
<th role="columnheader" scope="col">{% trans 'Expiry Date' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for token in object_list %}
<tr role="row">
<th role="columnheader">
<div>{{ token.identifier }}</div>
</th>
<td role="cell">
<span>
{{ token.user }}
</span>
</td>
<td role="cell">
<span>
{{ token.expiring|yesno:"Yes,No" }}
</span>
</td>
<td role="cell">
<span>
{% if not token.expiring %}
-
{% else %}
{{ token.expires }}
{% endif %}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:token-delete' pk=token.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-token-copy-button identifier="{{ token.identifier }}">
{% trans 'Copy token' %}
</ak-token-copy-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="fas fa-key pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Tokens.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any token." %}
{% else %}
{% trans 'Currently no tokens exist.' %}
{% endif %}
</div>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -1,125 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-user"></i>
{% trans 'Users' %}
</h1>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_admin:user-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<button role="ak-refresh" class="pf-c-button pf-m-primary">
{% trans 'Refresh' %}
</button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Active' %}</th>
<th role="columnheader" scope="col">{% trans 'Last Login' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for user in object_list %}
<tr role="row">
<th role="columnheader">
<div>
<div>{{ user.username }}</div>
<small>{{ user.name }}</small>
</div>
</th>
<td role="cell">
<span>
{{ user.is_active }}
</span>
</td>
<td role="cell">
<span>
{{ user.last_login }}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_admin:user-update' pk=user.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
{% if user.is_active %}
<ak-modal-button href="{% url 'authentik_admin:user-disable' pk=user.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-warning">
{% trans 'Disable' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
{% else %}
<ak-modal-button href="{% url 'authentik_admin:user-delete' pk=user.pk %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Enable' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
{% endif %}
<a class="pf-c-button pf-m-tertiary ak-root-link" href="{% url 'authentik_admin:user-password-reset' pk=user.pk %}?back={{ request.get_full_path }}">{% trans 'Reset Password' %}</a>
<a class="pf-c-button pf-m-tertiary ak-root-link" href="{% url 'authentik_core:impersonate-init' user_id=user.pk %}">{% trans 'Impersonate' %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
</div>
</div>
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="pf-icon pf-icon-user pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Users.' %}
</h1>
<div class="pf-c-empty-state__body">
{% if request.GET.search != "" %}
{% trans "Your search query doesn't match any users." %}
{% else %}
{% trans 'Currently no users exist. How did you even get here.' %}
{% endif %}
</div>
<ak-modal-button href="{% url 'authentik_admin:user-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
</div>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -27,7 +27,9 @@
</div>
</section>
<footer class="pf-c-modal-box__footer">
<input class="pf-c-button pf-m-primary" type="submit" form="main-form" value="{% block action %}{% endblock %}" />
<ak-spinner-button form="main-form">
{% block action %}{% endblock %}
</ak-spinner-button>&nbsp;
<a class="pf-c-button pf-m-secondary" href="{% back %}">{% trans "Cancel" %}</a>
</footer>
{% endblock %}

View File

@ -1,8 +1,8 @@
"""test admin api"""
from json import loads
from django.shortcuts import reverse
from django.test import TestCase
from django.urls import reverse
from authentik import __version__
from authentik.core.models import Group, User

View File

@ -3,8 +3,8 @@ from importlib import import_module
from typing import Callable
from django.forms import ModelForm
from django.shortcuts import reverse
from django.test import Client, TestCase
from django.urls import reverse
from django.urls.exceptions import NoReverseMatch
from authentik.admin.urls import urlpatterns

View File

@ -20,7 +20,6 @@ from authentik.admin.views import (
stages_bindings,
stages_invitations,
stages_prompts,
tasks,
tokens,
users,
)
@ -54,7 +53,6 @@ urlpatterns = [
name="application-delete",
),
# Tokens
path("tokens/", tokens.TokenListView.as_view(), name="tokens"),
path(
"tokens/<uuid:pk>/delete/",
tokens.TokenDeleteView.as_view(),
@ -73,7 +71,6 @@ urlpatterns = [
name="source-delete",
),
# Policies
path("policies/", policies.PolicyListView.as_view(), name="policies"),
path("policies/create/", policies.PolicyCreateView.as_view(), name="policy-create"),
path(
"policies/<uuid:pk>/update/",
@ -91,11 +88,6 @@ urlpatterns = [
name="policy-test",
),
# Policy bindings
path(
"policies/bindings/",
policies_bindings.PolicyBindingListView.as_view(),
name="policies-bindings",
),
path(
"policies/bindings/create/",
policies_bindings.PolicyBindingCreateView.as_view(),
@ -133,7 +125,6 @@ urlpatterns = [
name="provider-delete",
),
# Stages
path("stages/", stages.StageListView.as_view(), name="stages"),
path("stages/create/", stages.StageCreateView.as_view(), name="stage-create"),
path(
"stages/<uuid:pk>/update/",
@ -146,11 +137,6 @@ urlpatterns = [
name="stage-delete",
),
# Stage bindings
path(
"stages/bindings/",
stages_bindings.StageBindingListView.as_view(),
name="stage-bindings",
),
path(
"stages/bindings/create/",
stages_bindings.StageBindingCreateView.as_view(),
@ -167,11 +153,6 @@ urlpatterns = [
name="stage-binding-delete",
),
# Stage Prompts
path(
"stages_prompts/",
stages_prompts.PromptListView.as_view(),
name="stage-prompts",
),
path(
"stages_prompts/create/",
stages_prompts.PromptCreateView.as_view(),
@ -188,11 +169,6 @@ urlpatterns = [
name="stage-prompt-delete",
),
# Stage Invitations
path(
"stages/invitations/",
stages_invitations.InvitationListView.as_view(),
name="stage-invitations",
),
path(
"stages/invitations/create/",
stages_invitations.InvitationCreateView.as_view(),
@ -204,7 +180,6 @@ urlpatterns = [
name="stage-invitation-delete",
),
# Flows
path("flows/", flows.FlowListView.as_view(), name="flows"),
path(
"flows/create/",
flows.FlowCreateView.as_view(),
@ -257,7 +232,6 @@ urlpatterns = [
name="property-mapping-test",
),
# Users
path("users/", users.UserListView.as_view(), name="users"),
path("users/create/", users.UserCreateView.as_view(), name="user-create"),
path("users/<int:pk>/update/", users.UserUpdateView.as_view(), name="user-update"),
path("users/<int:pk>/delete/", users.UserDeleteView.as_view(), name="user-delete"),
@ -271,7 +245,6 @@ urlpatterns = [
name="user-password-reset",
),
# Groups
path("groups/", groups.GroupListView.as_view(), name="groups"),
path("groups/create/", groups.GroupCreateView.as_view(), name="group-create"),
path(
"groups/<uuid:pk>/update/",
@ -284,11 +257,6 @@ urlpatterns = [
name="group-delete",
),
# Certificate-Key Pairs
path(
"crypto/certificates/",
certificate_key_pair.CertificateKeyPairListView.as_view(),
name="certificate_key_pair",
),
path(
"crypto/certificates/create/",
certificate_key_pair.CertificateKeyPairCreateView.as_view(),
@ -326,11 +294,6 @@ urlpatterns = [
name="outpost-delete",
),
# Outpost Service Connections
path(
"outpost_service_connections/",
outposts_service_connections.OutpostServiceConnectionListView.as_view(),
name="outpost-service-connections",
),
path(
"outpost_service_connections/create/",
outposts_service_connections.OutpostServiceConnectionCreateView.as_view(),
@ -346,12 +309,6 @@ urlpatterns = [
outposts_service_connections.OutpostServiceConnectionDeleteView.as_view(),
name="outpost-service-connection-delete",
),
# Tasks
path(
"tasks/",
tasks.TaskListView.as_view(),
name="tasks",
),
# Event Notification Transpots
path(
"events/transports/create/",

View File

@ -1,4 +1,6 @@
"""authentik Application administration"""
from typing import Any
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import (
PermissionRequiredMixin as DjangoPermissionRequiredMixin,
@ -7,8 +9,9 @@ from django.contrib.messages.views import SuccessMessageMixin
from django.utils.translation import gettext as _
from django.views.generic import UpdateView
from guardian.mixins import PermissionRequiredMixin
from guardian.shortcuts import get_objects_for_user
from authentik.admin.views.utils import BackSuccessUrlMixin, DeleteMessageView
from authentik.admin.views.utils import DeleteMessageView
from authentik.core.forms.applications import ApplicationForm
from authentik.core.models import Application
from authentik.lib.views import CreateAssignPermView
@ -16,7 +19,6 @@ from authentik.lib.views import CreateAssignPermView
class ApplicationCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -31,10 +33,25 @@ class ApplicationCreateView(
template_name = "generic/create.html"
success_message = _("Successfully created Application")
def get_initial(self) -> dict[str, Any]:
if "provider" in self.request.GET:
try:
initial_provider_pk = int(self.request.GET["provider"])
except ValueError:
return super().get_initial()
providers = (
get_objects_for_user(self.request.user, "authentik_core.view_provider")
.filter(pk=initial_provider_pk)
.select_subclasses()
)
if not providers.exists():
return {}
return {"provider": providers.first()}
return super().get_initial()
class ApplicationUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,

View File

@ -7,16 +7,11 @@ from django.contrib.messages.views import SuccessMessageMixin
from django.http.response import HttpResponse
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import ListView, UpdateView
from django.views.generic import UpdateView
from django.views.generic.edit import FormView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.forms import (
CertificateKeyPairForm,
@ -26,26 +21,8 @@ from authentik.crypto.models import CertificateKeyPair
from authentik.lib.views import CreateAssignPermView
class CertificateKeyPairListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
ListView,
):
"""Show list of all keypairs"""
model = CertificateKeyPair
permission_required = "authentik_crypto.view_certificatekeypair"
ordering = "name"
template_name = "administration/certificatekeypair/list.html"
search_fields = ["name"]
class CertificateKeyPairCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -57,13 +34,12 @@ class CertificateKeyPairCreateView(
permission_required = "authentik_crypto.add_certificatekeypair"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:certificate_key_pair")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Certificate-Key Pair")
class CertificateKeyPairGenerateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
FormView,
@ -75,7 +51,7 @@ class CertificateKeyPairGenerateView(
permission_required = "authentik_crypto.add_certificatekeypair"
template_name = "administration/certificatekeypair/generate.html"
success_url = reverse_lazy("authentik_admin:certificate_key_pair")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully generated Certificate-Key Pair")
def form_valid(self, form: CertificateKeyPairGenerateForm) -> HttpResponse:
@ -91,7 +67,6 @@ class CertificateKeyPairGenerateView(
class CertificateKeyPairUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,
@ -103,7 +78,7 @@ class CertificateKeyPairUpdateView(
permission_required = "authentik_crypto.change_certificatekeypair"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:certificate_key_pair")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated Certificate-Key Pair")
@ -116,5 +91,5 @@ class CertificateKeyPairDeleteView(
permission_required = "authentik_crypto.delete_certificatekeypair"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:certificate_key_pair")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Certificate-Key Pair")

View File

@ -8,7 +8,7 @@ from django.utils.translation import gettext as _
from django.views.generic import UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import BackSuccessUrlMixin, DeleteMessageView
from authentik.admin.views.utils import DeleteMessageView
from authentik.events.forms import NotificationRuleForm
from authentik.events.models import NotificationRule
from authentik.lib.views import CreateAssignPermView
@ -16,7 +16,6 @@ from authentik.lib.views import CreateAssignPermView
class NotificationRuleCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -34,7 +33,6 @@ class NotificationRuleCreateView(
class NotificationRuleUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,

View File

@ -8,7 +8,7 @@ from django.utils.translation import gettext as _
from django.views.generic import UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import BackSuccessUrlMixin, DeleteMessageView
from authentik.admin.views.utils import DeleteMessageView
from authentik.events.forms import NotificationTransportForm
from authentik.events.models import NotificationTransport
from authentik.lib.views import CreateAssignPermView
@ -16,7 +16,6 @@ from authentik.lib.views import CreateAssignPermView
class NotificationTransportCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -33,7 +32,6 @@ class NotificationTransportCreateView(
class NotificationTransportUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,

View File

@ -8,15 +8,10 @@ from django.contrib.messages.views import SuccessMessageMixin
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import DetailView, FormView, ListView, UpdateView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from django.views.generic import DetailView, FormView, UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.flows.exceptions import FlowNonApplicableException
from authentik.flows.forms import FlowForm, FlowImportForm
from authentik.flows.models import Flow
@ -29,25 +24,8 @@ from authentik.lib.utils.urls import redirect_with_qs
from authentik.lib.views import CreateAssignPermView, bad_request_message
class FlowListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
ListView,
):
"""Show list of all flows"""
model = Flow
permission_required = "authentik_flows.view_flow"
ordering = "name"
template_name = "administration/flow/list.html"
search_fields = ["name", "slug", "designation", "title"]
class FlowCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -59,13 +37,12 @@ class FlowCreateView(
permission_required = "authentik_flows.add_flow"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:flows")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Flow")
class FlowUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,
@ -77,7 +54,7 @@ class FlowUpdateView(
permission_required = "authentik_flows.change_flow"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:flows")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated Flow")
@ -88,7 +65,7 @@ class FlowDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageV
permission_required = "authentik_flows.delete_flow"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:flows")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Flow")
@ -128,7 +105,7 @@ class FlowImportView(LoginRequiredMixin, FormView):
form_class = FlowImportForm
template_name = "administration/flow/import.html"
success_url = reverse_lazy("authentik_admin:flows")
success_url = reverse_lazy("authentik_core:shell")
def dispatch(self, request, *args, **kwargs):
if not request.user.is_superuser:

View File

@ -6,39 +6,17 @@ from django.contrib.auth.mixins import (
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import ListView, UpdateView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from django.views.generic import UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.core.forms.groups import GroupForm
from authentik.core.models import Group
from authentik.lib.views import CreateAssignPermView
class GroupListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
ListView,
):
"""Show list of all groups"""
model = Group
permission_required = "authentik_core.view_group"
ordering = "name"
template_name = "administration/group/list.html"
search_fields = ["name", "attributes"]
class GroupCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -50,13 +28,12 @@ class GroupCreateView(
permission_required = "authentik_core.add_group"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:groups")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Group")
class GroupUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,
@ -68,7 +45,7 @@ class GroupUpdateView(
permission_required = "authentik_core.change_group"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:groups")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated Group")
@ -79,5 +56,5 @@ class GroupDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessage
permission_required = "authentik_flows.delete_group"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:groups")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Group")

View File

@ -1,6 +1,6 @@
"""authentik Outpost administration"""
from dataclasses import asdict
from typing import Any, Dict
from typing import Any
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import (
@ -11,7 +11,7 @@ from django.utils.translation import gettext as _
from django.views.generic import UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import BackSuccessUrlMixin, DeleteMessageView
from authentik.admin.views.utils import DeleteMessageView
from authentik.lib.views import CreateAssignPermView
from authentik.outposts.forms import OutpostForm
from authentik.outposts.models import Outpost, OutpostConfig
@ -19,7 +19,6 @@ from authentik.outposts.models import Outpost, OutpostConfig
class OutpostCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -33,7 +32,7 @@ class OutpostCreateView(
template_name = "generic/create.html"
success_message = _("Successfully created Outpost")
def get_initial(self) -> Dict[str, Any]:
def get_initial(self) -> dict[str, Any]:
return {
"_config": asdict(
OutpostConfig(authentik_host=self.request.build_absolute_uri("/"))
@ -43,7 +42,6 @@ class OutpostCreateView(
class OutpostUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,

View File

@ -6,39 +6,18 @@ from django.contrib.auth.mixins import (
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
InheritanceCreateView,
InheritanceListView,
InheritanceUpdateView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.outposts.models import OutpostServiceConnection
class OutpostServiceConnectionListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
InheritanceListView,
):
"""Show list of all outpost-service-connections"""
model = OutpostServiceConnection
permission_required = "authentik_outposts.add_outpostserviceconnection"
template_name = "administration/outpost_service_connection/list.html"
ordering = "pk"
search_fields = ["pk", "name"]
class OutpostServiceConnectionCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
InheritanceCreateView,
@ -49,13 +28,12 @@ class OutpostServiceConnectionCreateView(
permission_required = "authentik_outposts.add_outpostserviceconnection"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:outpost-service-connections")
success_message = _("Successfully created OutpostServiceConnection")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Outpost Service Connection")
class OutpostServiceConnectionUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
InheritanceUpdateView,
@ -66,8 +44,8 @@ class OutpostServiceConnectionUpdateView(
permission_required = "authentik_outposts.change_outpostserviceconnection"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:outpost-service-connections")
success_message = _("Successfully updated OutpostServiceConnection")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated Outpost Service Connection")
class OutpostServiceConnectionDeleteView(
@ -79,5 +57,5 @@ class OutpostServiceConnectionDeleteView(
permission_required = "authentik_outposts.delete_outpostserviceconnection"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:outpost-service-connections")
success_message = _("Successfully deleted OutpostServiceConnection")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Outpost Service Connection")

View File

@ -1,5 +1,5 @@
"""authentik Policy administration"""
from typing import Any, Dict
from typing import Any
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import (
@ -11,41 +11,20 @@ from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import FormView
from django.views.generic.detail import DetailView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.forms.policies import PolicyTestForm
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
InheritanceCreateView,
InheritanceListView,
InheritanceUpdateView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.policies.models import Policy, PolicyBinding
from authentik.policies.process import PolicyProcess, PolicyRequest
class PolicyListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
InheritanceListView,
):
"""Show list of all policies"""
model = Policy
permission_required = "authentik_policies.view_policy"
ordering = "name"
template_name = "administration/policy/list.html"
search_fields = ["name"]
class PolicyCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
InheritanceCreateView,
@ -56,13 +35,12 @@ class PolicyCreateView(
permission_required = "authentik_policies.add_policy"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:policies")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Policy")
class PolicyUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
InheritanceUpdateView,
@ -73,7 +51,7 @@ class PolicyUpdateView(
permission_required = "authentik_policies.change_policy"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:policies")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated Policy")
@ -84,7 +62,7 @@ class PolicyDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessag
permission_required = "authentik_policies.delete_policy"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:policies")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Policy")
@ -102,7 +80,7 @@ class PolicyTestView(LoginRequiredMixin, DetailView, PermissionRequiredMixin, Fo
Policy.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first()
)
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
kwargs["policy"] = self.get_object()
return super().get_context_data(**kwargs)
@ -116,7 +94,7 @@ class PolicyTestView(LoginRequiredMixin, DetailView, PermissionRequiredMixin, Fo
p_request = PolicyRequest(user)
p_request.debug = True
p_request.http_request = self.request
p_request.set_http_request(self.request)
p_request.context = form.cleaned_data.get("context", {})
proc = PolicyProcess(PolicyBinding(policy=policy), p_request, None)

View File

@ -6,55 +6,20 @@ from django.contrib.auth.mixins import (
PermissionRequiredMixin as DjangoPermissionRequiredMixin,
)
from django.contrib.messages.views import SuccessMessageMixin
from django.db.models import Max, QuerySet
from django.db.models import Max
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import ListView, UpdateView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from guardian.shortcuts import get_objects_for_user
from django.views.generic import UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.lib.views import CreateAssignPermView
from authentik.policies.forms import PolicyBindingForm
from authentik.policies.models import PolicyBinding, PolicyBindingModel
class PolicyBindingListView(
LoginRequiredMixin, PermissionListMixin, UserPaginateListMixin, ListView
):
"""Show list of all policies"""
model = PolicyBinding
permission_required = "authentik_policies.view_policybinding"
ordering = ["order", "target"]
template_name = "administration/policy_binding/list.html"
def get_queryset(self) -> QuerySet:
# Since `select_subclasses` does not work with a foreign key, we have to do two queries here
# First, get all pbm objects that have bindings attached
objects = (
get_objects_for_user(
self.request.user, "authentik_policies.view_policybindingmodel"
)
.filter(policies__isnull=False)
.select_subclasses()
.select_related()
.order_by("pk")
)
for pbm in objects:
pbm.bindings = get_objects_for_user(
self.request.user, self.permission_required
).filter(target__pk=pbm.pbm_uuid)
return objects
class PolicyBindingCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -66,7 +31,7 @@ class PolicyBindingCreateView(
form_class = PolicyBindingForm
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:policies-bindings")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created PolicyBinding")
def get_initial(self) -> dict[str, Any]:
@ -88,7 +53,6 @@ class PolicyBindingCreateView(
class PolicyBindingUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,
@ -100,7 +64,7 @@ class PolicyBindingUpdateView(
form_class = PolicyBindingForm
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:policies-bindings")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated PolicyBinding")
@ -113,5 +77,5 @@ class PolicyBindingDeleteView(
permission_required = "authentik_policies.delete_policybinding"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:policies-bindings")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted PolicyBinding")

View File

@ -15,7 +15,6 @@ from guardian.mixins import PermissionRequiredMixin
from authentik.admin.forms.policies import PolicyTestForm
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
InheritanceCreateView,
InheritanceUpdateView,
@ -25,7 +24,6 @@ from authentik.core.models import PropertyMapping
class PropertyMappingCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
InheritanceCreateView,
@ -41,7 +39,6 @@ class PropertyMappingCreateView(
class PropertyMappingUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
InheritanceUpdateView,

View File

@ -8,7 +8,6 @@ from django.utils.translation import gettext as _
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
InheritanceCreateView,
InheritanceUpdateView,
@ -18,7 +17,6 @@ from authentik.core.models import Provider
class ProviderCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
InheritanceCreateView,
@ -34,7 +32,6 @@ class ProviderCreateView(
class ProviderUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
InheritanceUpdateView,

View File

@ -8,7 +8,6 @@ from django.utils.translation import gettext as _
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
InheritanceCreateView,
InheritanceUpdateView,
@ -18,7 +17,6 @@ from authentik.core.models import Source
class SourceCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
InheritanceCreateView,
@ -35,7 +33,6 @@ class SourceCreateView(
class SourceUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
InheritanceUpdateView,

View File

@ -6,39 +6,18 @@ from django.contrib.auth.mixins import (
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
InheritanceCreateView,
InheritanceListView,
InheritanceUpdateView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.flows.models import Stage
class StageListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
InheritanceListView,
):
"""Show list of all stages"""
model = Stage
template_name = "administration/stage/list.html"
permission_required = "authentik_flows.view_stage"
ordering = "name"
search_fields = ["name"]
class StageCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
InheritanceCreateView,
@ -49,13 +28,12 @@ class StageCreateView(
template_name = "generic/create.html"
permission_required = "authentik_flows.add_stage"
success_url = reverse_lazy("authentik_admin:stages")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Stage")
class StageUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
InheritanceUpdateView,
@ -65,7 +43,7 @@ class StageUpdateView(
model = Stage
permission_required = "authentik_flows.update_application"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:stages")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated Stage")
@ -75,5 +53,5 @@ class StageDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessage
model = Stage
template_name = "generic/delete.html"
permission_required = "authentik_flows.delete_stage"
success_url = reverse_lazy("authentik_admin:stages")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Stage")

View File

@ -9,33 +9,17 @@ from django.contrib.messages.views import SuccessMessageMixin
from django.db.models import Max
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import ListView, UpdateView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from django.views.generic import UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.flows.forms import FlowStageBindingForm
from authentik.flows.models import Flow, FlowStageBinding
from authentik.lib.views import CreateAssignPermView
class StageBindingListView(
LoginRequiredMixin, PermissionListMixin, UserPaginateListMixin, ListView
):
"""Show list of all flows"""
model = FlowStageBinding
permission_required = "authentik_flows.view_flowstagebinding"
ordering = ["target", "order"]
template_name = "administration/stage_binding/list.html"
class StageBindingCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -47,7 +31,7 @@ class StageBindingCreateView(
form_class = FlowStageBindingForm
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:stage-bindings")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created StageBinding")
def get_initial(self) -> dict[str, Any]:
@ -67,7 +51,6 @@ class StageBindingCreateView(
class StageBindingUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,
@ -79,7 +62,7 @@ class StageBindingUpdateView(
form_class = FlowStageBindingForm
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:stage-bindings")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated StageBinding")
@ -92,5 +75,5 @@ class StageBindingDeleteView(
permission_required = "authentik_flows.delete_flowstagebinding"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:stage-bindings")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted FlowStageBinding")

View File

@ -7,39 +7,16 @@ from django.contrib.messages.views import SuccessMessageMixin
from django.http import HttpResponseRedirect
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import ListView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.lib.views import CreateAssignPermView
from authentik.stages.invitation.forms import InvitationForm
from authentik.stages.invitation.models import Invitation
class InvitationListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
ListView,
):
"""Show list of all invitations"""
model = Invitation
permission_required = "authentik_stages_invitation.view_invitation"
template_name = "administration/stage_invitation/list.html"
ordering = "-expires"
search_fields = ["created_by__username", "expires", "fixed_data"]
class InvitationCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -51,7 +28,7 @@ class InvitationCreateView(
permission_required = "authentik_stages_invitation.add_invitation"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:stage-invitations")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Invitation")
def form_valid(self, form):
@ -70,5 +47,5 @@ class InvitationDeleteView(
permission_required = "authentik_stages_invitation.delete_invitation"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:stage-invitations")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Invitation")

View File

@ -6,44 +6,17 @@ from django.contrib.auth.mixins import (
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import ListView, UpdateView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from django.views.generic import UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.lib.views import CreateAssignPermView
from authentik.stages.prompt.forms import PromptAdminForm
from authentik.stages.prompt.models import Prompt
class PromptListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
ListView,
):
"""Show list of all prompts"""
model = Prompt
permission_required = "authentik_stages_prompt.view_prompt"
ordering = "order"
template_name = "administration/stage_prompt/list.html"
search_fields = [
"field_key",
"label",
"type",
"placeholder",
]
class PromptCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -55,13 +28,12 @@ class PromptCreateView(
permission_required = "authentik_stages_prompt.add_prompt"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:stage-prompts")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Prompt")
class PromptUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,
@ -73,7 +45,7 @@ class PromptUpdateView(
permission_required = "authentik_stages_prompt.change_prompt"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:stage-prompts")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated Prompt")
@ -84,5 +56,5 @@ class PromptDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessag
permission_required = "authentik_stages_prompt.delete_prompt"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:stage-prompts")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Prompt")

View File

@ -1,23 +0,0 @@
"""authentik Tasks List"""
from typing import Any, Dict
from django.views.generic.base import TemplateView
from authentik.admin.mixins import AdminRequiredMixin
from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus
class TaskListView(AdminRequiredMixin, TemplateView):
"""Show list of all background tasks"""
template_name = "administration/task/list.html"
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
kwargs = super().get_context_data(**kwargs)
kwargs["object_list"] = sorted(
TaskInfo.all().values(), key=lambda x: x.task_name
)
kwargs["task_successful"] = TaskResultStatus.SUCCESSFUL
kwargs["task_warning"] = TaskResultStatus.WARNING
kwargs["task_error"] = TaskResultStatus.ERROR
return kwargs

View File

@ -2,38 +2,12 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import ListView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.views.utils import (
DeleteMessageView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.core.models import Token
class TokenListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
ListView,
):
"""Show list of all tokens"""
model = Token
permission_required = "authentik_core.view_token"
ordering = "expires"
template_name = "administration/token/list.html"
search_fields = [
"identifier",
"intent",
"user__username",
"description",
]
class TokenDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView):
"""Delete token"""
@ -41,5 +15,5 @@ class TokenDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessage
permission_required = "authentik_core.delete_token"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:tokens")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Token")

View File

@ -8,49 +8,20 @@ from django.contrib.messages.views import SuccessMessageMixin
from django.http import HttpRequest, HttpResponse
from django.http.response import HttpResponseRedirect
from django.shortcuts import redirect
from django.urls import reverse, reverse_lazy
from django.urls import reverse_lazy
from django.utils.http import urlencode
from django.utils.translation import gettext as _
from django.views.generic import DetailView, ListView, UpdateView
from guardian.mixins import (
PermissionListMixin,
PermissionRequiredMixin,
get_anonymous_user,
)
from django.views.generic import DetailView, UpdateView
from guardian.mixins import PermissionRequiredMixin
from authentik.admin.forms.users import UserForm
from authentik.admin.views.utils import (
BackSuccessUrlMixin,
DeleteMessageView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.core.models import Token, User
from authentik.lib.views import CreateAssignPermView
class UserListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
ListView,
):
"""Show list of all users"""
model = User
permission_required = "authentik_core.view_user"
ordering = "username"
template_name = "administration/user/list.html"
search_fields = ["username", "name", "attributes"]
def get_queryset(self):
return super().get_queryset().exclude(pk=get_anonymous_user().pk)
class UserCreateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
@ -62,13 +33,12 @@ class UserCreateView(
permission_required = "authentik_core.add_user"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:users")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created User")
class UserUpdateView(
SuccessMessageMixin,
BackSuccessUrlMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UpdateView,
@ -82,7 +52,7 @@ class UserUpdateView(
# By default the object's name is user which is used by other checks
context_object_name = "object"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:users")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated User")
@ -95,13 +65,11 @@ class UserDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageV
# By default the object's name is user which is used by other checks
context_object_name = "object"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:users")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted User")
class UserDisableView(
LoginRequiredMixin, PermissionRequiredMixin, BackSuccessUrlMixin, DeleteMessageView
):
class UserDisableView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView):
"""Disable user"""
object: User
@ -112,7 +80,7 @@ class UserDisableView(
# By default the object's name is user which is used by other checks
context_object_name = "object"
template_name = "administration/user/disable.html"
success_url = reverse_lazy("authentik_admin:users")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully disabled User")
def delete(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
@ -123,9 +91,7 @@ class UserDisableView(
return HttpResponseRedirect(success_url)
class UserEnableView(
LoginRequiredMixin, PermissionRequiredMixin, BackSuccessUrlMixin, DetailView
):
class UserEnableView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
"""Enable user"""
object: User
@ -135,15 +101,14 @@ class UserEnableView(
# By default the object's name is user which is used by other checks
context_object_name = "object"
success_url = reverse_lazy("authentik_admin:users")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully enabled User")
def get(self, request: HttpRequest, *args, **kwargs):
self.object: User = self.get_object()
success_url = self.get_success_url()
self.object.is_active = True
self.object.save()
return HttpResponseRedirect(success_url)
return HttpResponseRedirect(self.success_url)
class UserPasswordResetView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
@ -160,9 +125,7 @@ class UserPasswordResetView(LoginRequiredMixin, PermissionRequiredMixin, DetailV
)
querystring = urlencode({"token": token.key})
link = request.build_absolute_uri(
reverse("authentik_flows:default-recovery") + f"?{querystring}"
reverse_lazy("authentik_flows:default-recovery") + f"?{querystring}"
)
messages.success(
request, _("Password reset link: <pre>%(link)s</pre>" % {"link": link})
)
return redirect("authentik_admin:users")
messages.success(request, _("Password reset link: %(link)s" % {"link": link}))
return redirect("/")

View File

@ -1,15 +1,11 @@
"""authentik admin util views"""
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from typing import Any
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.postgres.search import SearchQuery, SearchVector
from django.db.models import QuerySet
from django.http import Http404
from django.http.request import HttpRequest
from django.views.generic import DeleteView, ListView, UpdateView
from django.views.generic.list import MultipleObjectMixin
from django.urls import reverse_lazy
from django.views.generic import DeleteView, UpdateView
from authentik.lib.utils.reflection import all_subclasses
from authentik.lib.views import CreateAssignPermView
@ -18,42 +14,13 @@ from authentik.lib.views import CreateAssignPermView
class DeleteMessageView(SuccessMessageMixin, DeleteView):
"""DeleteView which shows `self.success_message` on successful deletion"""
success_url = reverse_lazy("authentik_core:shell")
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs)
class InheritanceListView(ListView):
"""ListView for objects using InheritanceManager"""
def get_context_data(self, **kwargs):
kwargs["types"] = {x.__name__: x for x in all_subclasses(self.model)}
return super().get_context_data(**kwargs)
def get_queryset(self):
return super().get_queryset().select_subclasses()
class SearchListMixin(MultipleObjectMixin):
"""Accept search query using `search` querystring parameter. Requires self.search_fields,
a list of all fields to search. Can contain special lookups like __icontains"""
search_fields: List[str]
def get_queryset(self) -> QuerySet:
queryset = super().get_queryset()
if "search" in self.request.GET:
raw_query = self.request.GET["search"]
if raw_query == "":
# Empty query, don't search at all
return queryset
search = SearchQuery(raw_query, search_type="websearch")
return queryset.annotate(search=SearchVector(*self.search_fields)).filter(
search=search
)
return queryset
class InheritanceCreateView(CreateAssignPermView):
"""CreateView for objects using InheritanceManager"""
@ -67,7 +34,7 @@ class InheritanceCreateView(CreateAssignPermView):
raise Http404 from exc
return model().form
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
kwargs = super().get_context_data(**kwargs)
form_cls = self.get_form_class()
if hasattr(form_cls, "template_name"):
@ -78,7 +45,7 @@ class InheritanceCreateView(CreateAssignPermView):
class InheritanceUpdateView(UpdateView):
"""UpdateView for objects using InheritanceManager"""
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
kwargs = super().get_context_data(**kwargs)
form_cls = self.get_form_class()
if hasattr(form_cls, "template_name"):
@ -94,31 +61,3 @@ class InheritanceUpdateView(UpdateView):
.select_subclasses()
.first()
)
class BackSuccessUrlMixin:
"""Checks if a relative URL has been given as ?back param, and redirect to it. Otherwise
default to self.success_url."""
request: HttpRequest
success_url: Optional[str]
def get_success_url(self) -> str:
"""get_success_url from FormMixin"""
back_param = self.request.GET.get("back")
if back_param:
if not bool(urlparse(back_param).netloc):
return back_param
return str(self.success_url)
class UserPaginateListMixin:
"""Get paginate_by value from user's attributes, defaulting to 15"""
request: HttpRequest
# pylint: disable=unused-argument
def get_paginate_by(self, queryset: QuerySet) -> int:
"""get_paginate_by Function of ListView"""
return self.request.user.attributes.get("paginate_by", 15)

View File

@ -1,7 +1,7 @@
"""API Authentication"""
from base64 import b64decode
from binascii import Error
from typing import Any, Optional, Tuple, Union
from typing import Any, Optional, Union
from rest_framework.authentication import BaseAuthentication, get_authorization_header
from rest_framework.request import Request
@ -44,7 +44,7 @@ def token_from_header(raw_header: bytes) -> Optional[Token]:
class AuthentikTokenAuthentication(BaseAuthentication):
"""Token-based authentication using HTTP Basic authentication"""
def authenticate(self, request: Request) -> Union[Tuple[User, Any], None]:
def authenticate(self, request: Request) -> Union[tuple[User, Any], None]:
"""Token-based authentication using HTTP Basic authentication"""
auth = get_authorization_header(request)

View File

@ -6,6 +6,7 @@ from rest_framework.response import Response
class Pagination(pagination.PageNumberPagination):
"""Pagination which includes total pages and current page"""
page_query_param = "page"
page_size_query_param = "page_size"
def get_paginated_response(self, data):

View File

@ -0,0 +1,97 @@
"""Swagger Pagination Schema class"""
from typing import OrderedDict
from drf_yasg2 import openapi
from drf_yasg2.inspectors import PaginatorInspector
class PaginationInspector(PaginatorInspector):
"""Swagger Pagination Schema class"""
def get_paginated_response(self, paginator, response_schema):
"""
:param BasePagination paginator: the paginator
:param openapi.Schema response_schema: the response schema that must be paged.
:rtype: openapi.Schema
"""
return openapi.Schema(
type=openapi.TYPE_OBJECT,
properties=OrderedDict(
(
(
"pagination",
openapi.Schema(
type=openapi.TYPE_OBJECT,
properties=OrderedDict(
(
("next", openapi.Schema(type=openapi.TYPE_NUMBER)),
(
"previous",
openapi.Schema(type=openapi.TYPE_NUMBER),
),
("count", openapi.Schema(type=openapi.TYPE_NUMBER)),
(
"current",
openapi.Schema(type=openapi.TYPE_NUMBER),
),
(
"total_pages",
openapi.Schema(type=openapi.TYPE_NUMBER),
),
(
"start_index",
openapi.Schema(type=openapi.TYPE_NUMBER),
),
(
"end_index",
openapi.Schema(type=openapi.TYPE_NUMBER),
),
)
),
required=[
"next",
"previous",
"count",
"current",
"total_pages",
"start_index",
"end_index",
],
),
),
("results", response_schema),
)
),
required=["results", "pagination"],
)
def get_paginator_parameters(self, paginator):
"""
Get the pagination parameters for a single paginator **instance**.
Should return :data:`.NotHandled` if this inspector
does not know how to handle the given `paginator`.
:param BasePagination paginator: the paginator
:rtype: list[openapi.Parameter]
"""
return [
openapi.Parameter(
"page",
openapi.IN_QUERY,
"Page Index",
False,
None,
openapi.TYPE_INTEGER,
),
openapi.Parameter(
"page_size",
openapi.IN_QUERY,
"Page Size",
False,
None,
openapi.TYPE_INTEGER,
),
]

View File

@ -1,10 +1,11 @@
"""core Configs API"""
from django.db.models import Model
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.fields import BooleanField, CharField
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ReadOnlyField, Serializer
from rest_framework.serializers import Serializer
from rest_framework.viewsets import ViewSet
from authentik.lib.config import CONFIG
@ -13,12 +14,12 @@ from authentik.lib.config import CONFIG
class ConfigSerializer(Serializer):
"""Serialize authentik Config into DRF Object"""
branding_logo = ReadOnlyField()
branding_title = ReadOnlyField()
branding_logo = CharField(read_only=True)
branding_title = CharField(read_only=True)
error_reporting_enabled = ReadOnlyField()
error_reporting_environment = ReadOnlyField()
error_reporting_send_pii = ReadOnlyField()
error_reporting_enabled = BooleanField(read_only=True)
error_reporting_environment = CharField(read_only=True)
error_reporting_send_pii = BooleanField(read_only=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
@ -32,7 +33,7 @@ class ConfigsViewSet(ViewSet):
permission_classes = [AllowAny]
@swagger_auto_schema(responses={200: ConfigSerializer(many=True)})
@swagger_auto_schema(responses={200: ConfigSerializer(many=False)})
def list(self, request: Request) -> Response:
"""Retrive public configuration options"""
config = ConfigSerializer(

View File

@ -1,37 +0,0 @@
"""core messages API"""
from django.contrib.messages import get_messages
from django.db.models import Model
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ReadOnlyField, Serializer
from rest_framework.viewsets import ViewSet
class MessageSerializer(Serializer):
"""Serialize Django Message into DRF Object"""
message = ReadOnlyField()
level = ReadOnlyField()
tags = ReadOnlyField()
extra_tags = ReadOnlyField()
level_tag = ReadOnlyField()
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model:
raise NotImplementedError
class MessagesViewSet(ViewSet):
"""Read-only view set that returns the current session's messages"""
permission_classes = [AllowAny]
@swagger_auto_schema(responses={200: MessageSerializer(many=True)})
def list(self, request: Request) -> Response:
"""List current messages and pass into Serializer"""
all_messages = list(get_messages(request))
return Response(MessageSerializer(all_messages, many=True).data)

View File

@ -1,4 +1,5 @@
"""api v2 urls"""
from django.conf import settings
from django.urls import path, re_path
from drf_yasg2 import openapi
from drf_yasg2.views import get_schema_view
@ -10,7 +11,6 @@ from authentik.admin.api.tasks import TaskViewSet
from authentik.admin.api.version import VersionViewSet
from authentik.admin.api.workers import WorkerViewSet
from authentik.api.v2.config import ConfigsViewSet
from authentik.api.v2.messages import MessagesViewSet
from authentik.core.api.applications import ApplicationViewSet
from authentik.core.api.groups import GroupViewSet
from authentik.core.api.propertymappings import PropertyMappingViewSet
@ -23,23 +23,17 @@ from authentik.events.api.event import EventViewSet
from authentik.events.api.notification import NotificationViewSet
from authentik.events.api.notification_rule import NotificationRuleViewSet
from authentik.events.api.notification_transport import NotificationTransportViewSet
from authentik.flows.api import (
FlowCacheViewSet,
FlowStageBindingViewSet,
FlowViewSet,
StageViewSet,
)
from authentik.flows.api.bindings import FlowStageBindingViewSet
from authentik.flows.api.flows import FlowViewSet
from authentik.flows.api.stages import StageViewSet
from authentik.flows.views import FlowExecutorView
from authentik.outposts.api.outpost_service_connections import (
DockerServiceConnectionViewSet,
KubernetesServiceConnectionViewSet,
ServiceConnectionViewSet,
)
from authentik.outposts.api.outposts import OutpostViewSet
from authentik.policies.api import (
PolicyBindingViewSet,
PolicyCacheViewSet,
PolicyViewSet,
)
from authentik.policies.api import PolicyBindingViewSet, PolicyViewSet
from authentik.policies.dummy.api import DummyPolicyViewSet
from authentik.policies.event_matcher.api import EventMatcherPolicyViewSet
from authentik.policies.expiry.api import PasswordExpiryPolicyViewSet
@ -47,7 +41,11 @@ from authentik.policies.expression.api import ExpressionPolicyViewSet
from authentik.policies.group_membership.api import GroupMembershipPolicyViewSet
from authentik.policies.hibp.api import HaveIBeenPwendPolicyViewSet
from authentik.policies.password.api import PasswordPolicyViewSet
from authentik.policies.reputation.api import ReputationPolicyViewSet
from authentik.policies.reputation.api import (
IPReputationViewSet,
ReputationPolicyViewSet,
UserReputationViewSet,
)
from authentik.providers.oauth2.api import OAuth2ProviderViewSet, ScopeMappingViewSet
from authentik.providers.proxy.api import (
ProxyOutpostConfigViewSet,
@ -57,15 +55,31 @@ from authentik.providers.saml.api import SAMLPropertyMappingViewSet, SAMLProvide
from authentik.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet
from authentik.sources.oauth.api import OAuthSourceViewSet
from authentik.sources.saml.api import SAMLSourceViewSet
from authentik.stages.authenticator_static.api import (
AuthenticatorStaticStageViewSet,
StaticAdminDeviceViewSet,
StaticDeviceViewSet,
)
from authentik.stages.authenticator_totp.api import (
AuthenticatorTOTPStageViewSet,
TOTPAdminDeviceViewSet,
TOTPDeviceViewSet,
)
from authentik.stages.authenticator_validate.api import (
AuthenticatorValidateStageViewSet,
)
from authentik.stages.authenticator_webauthn.api import (
AuthenticateWebAuthnStageViewSet,
WebAuthnAdminDeviceViewSet,
WebAuthnDeviceViewSet,
)
from authentik.stages.captcha.api import CaptchaStageViewSet
from authentik.stages.consent.api import ConsentStageViewSet
from authentik.stages.deny.api import DenyStageViewSet
from authentik.stages.dummy.api import DummyStageViewSet
from authentik.stages.email.api import EmailStageViewSet
from authentik.stages.identification.api import IdentificationStageViewSet
from authentik.stages.invitation.api import InvitationStageViewSet, InvitationViewSet
from authentik.stages.otp_static.api import OTPStaticStageViewSet
from authentik.stages.otp_time.api import OTPTimeStageViewSet
from authentik.stages.otp_validate.api import OTPValidateStageViewSet
from authentik.stages.password.api import PasswordStageViewSet
from authentik.stages.prompt.api import PromptStageViewSet, PromptViewSet
from authentik.stages.user_delete.api import UserDeleteStageViewSet
@ -75,7 +89,6 @@ from authentik.stages.user_write.api import UserWriteStageViewSet
router = routers.DefaultRouter()
router.register("root/messages", MessagesViewSet, basename="messages")
router.register("root/config", ConfigsViewSet, basename="configs")
router.register("admin/version", VersionViewSet, basename="admin_version")
@ -97,7 +110,6 @@ router.register(
router.register("outposts/proxy", ProxyOutpostConfigViewSet)
router.register("flows/instances", FlowViewSet)
router.register("flows/cached", FlowCacheViewSet, basename="flows_cache")
router.register("flows/bindings", FlowStageBindingViewSet)
router.register("crypto/certificatekeypairs", CertificateKeyPairViewSet)
@ -113,7 +125,6 @@ router.register("sources/saml", SAMLSourceViewSet)
router.register("sources/oauth", OAuthSourceViewSet)
router.register("policies/all", PolicyViewSet)
router.register("policies/cached", PolicyCacheViewSet, basename="policies_cache")
router.register("policies/bindings", PolicyBindingViewSet)
router.register("policies/expression", ExpressionPolicyViewSet)
router.register("policies/event_matcher", EventMatcherPolicyViewSet)
@ -121,6 +132,8 @@ router.register("policies/group_membership", GroupMembershipPolicyViewSet)
router.register("policies/haveibeenpwned", HaveIBeenPwendPolicyViewSet)
router.register("policies/password_expiry", PasswordExpiryPolicyViewSet)
router.register("policies/password", PasswordPolicyViewSet)
router.register("policies/reputation/users", UserReputationViewSet)
router.register("policies/reputation/ips", IPReputationViewSet)
router.register("policies/reputation", ReputationPolicyViewSet)
router.register("providers/all", ProviderViewSet)
@ -133,16 +146,25 @@ router.register("propertymappings/ldap", LDAPPropertyMappingViewSet)
router.register("propertymappings/saml", SAMLPropertyMappingViewSet)
router.register("propertymappings/scope", ScopeMappingViewSet)
router.register("authenticators/static", StaticDeviceViewSet)
router.register("authenticators/totp", TOTPDeviceViewSet)
router.register("authenticators/webauthn", WebAuthnDeviceViewSet)
router.register("authenticators/admin/static", StaticAdminDeviceViewSet)
router.register("authenticators/admin/totp", TOTPAdminDeviceViewSet)
router.register("authenticators/admin/webauthn", WebAuthnAdminDeviceViewSet)
router.register("stages/all", StageViewSet)
router.register("stages/authenticator/static", AuthenticatorStaticStageViewSet)
router.register("stages/authenticator/totp", AuthenticatorTOTPStageViewSet)
router.register("stages/authenticator/validate", AuthenticatorValidateStageViewSet)
router.register("stages/authenticator/webauthn", AuthenticateWebAuthnStageViewSet)
router.register("stages/captcha", CaptchaStageViewSet)
router.register("stages/consent", ConsentStageViewSet)
router.register("stages/deny", DenyStageViewSet)
router.register("stages/email", EmailStageViewSet)
router.register("stages/identification", IdentificationStageViewSet)
router.register("stages/invitation", InvitationStageViewSet)
router.register("stages/invitation/invitations", InvitationViewSet)
router.register("stages/otp_static", OTPStaticStageViewSet)
router.register("stages/otp_time", OTPTimeStageViewSet)
router.register("stages/otp_validate", OTPValidateStageViewSet)
router.register("stages/invitation/stages", InvitationStageViewSet)
router.register("stages/password", PasswordStageViewSet)
router.register("stages/prompt/prompts", PromptViewSet)
router.register("stages/prompt/stages", PromptStageViewSet)
@ -162,22 +184,26 @@ info = openapi.Info(
name="GNU GPLv3", url="https://github.com/BeryJu/authentik/blob/master/LICENSE"
),
)
SchemaView = get_schema_view(
info,
public=True,
permission_classes=(AllowAny,),
)
SchemaView = get_schema_view(info, public=True, permission_classes=(AllowAny,))
urlpatterns = [
urlpatterns = router.urls + [
path(
"flows/executor/<slug:flow_slug>/",
FlowExecutorView.as_view(),
name="flow-executor",
),
re_path(
r"^swagger(?P<format>\.json|\.yaml)$",
SchemaView.without_ui(cache_timeout=0),
name="schema-json",
),
path(
"swagger/",
SchemaView.with_ui("swagger", cache_timeout=0),
name="schema-swagger-ui",
),
path("redoc/", SchemaView.with_ui("redoc", cache_timeout=0), name="schema-redoc"),
] + router.urls
]
if settings.DEBUG:
urlpatterns = urlpatterns + [
path(
"swagger/",
SchemaView.with_ui("swagger", cache_timeout=0),
name="schema-swagger-ui",
),
]

View File

@ -2,6 +2,7 @@
from django.core.cache import cache
from django.db.models import QuerySet
from django.http.response import Http404
from drf_yasg2.utils import swagger_auto_schema
from guardian.shortcuts import get_objects_for_user
from rest_framework.decorators import action
from rest_framework.fields import SerializerMethodField
@ -13,7 +14,7 @@ from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
from structlog.stdlib import get_logger
from authentik.admin.api.metrics import get_events_per_1h
from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h
from authentik.core.api.providers import ProviderSerializer
from authentik.core.models import Application
from authentik.events.models import EventAction
@ -109,6 +110,7 @@ class ApplicationViewSet(ModelViewSet):
serializer = self.get_serializer(allowed_applications, many=True)
return self.get_paginated_response(serializer.data)
@swagger_auto_schema(responses={200: CoordinateSerializer(many=True)})
@action(detail=True)
def metrics(self, request: Request, slug: str):
"""Metrics for application logins"""

View File

@ -19,3 +19,6 @@ class GroupViewSet(ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
search_fields = ["name", "is_superuser"]
filterset_fields = ["name", "is_superuser"]
ordering = ["name"]

View File

@ -1,9 +1,16 @@
"""PropertyMapping API Views"""
from django.urls import reverse
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import ReadOnlyModelViewSet
from authentik.core.api.utils import MetaNameSerializer
from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer
from authentik.core.models import PropertyMapping
from authentik.lib.templatetags.authentik_utils import verbose_name
from authentik.lib.utils.reflection import all_subclasses
class PropertyMappingSerializer(ModelSerializer, MetaNameSerializer):
@ -47,3 +54,19 @@ class PropertyMappingViewSet(ReadOnlyModelViewSet):
def get_queryset(self):
return PropertyMapping.objects.select_subclasses()
@swagger_auto_schema(responses={200: TypeCreateSerializer(many=True)})
@action(detail=False)
def types(self, request: Request) -> Response:
"""Get all creatable property-mapping types"""
data = []
for subclass in all_subclasses(self.queryset.model):
data.append(
{
"name": verbose_name(subclass),
"description": subclass.__doc__,
"link": reverse("authentik_admin:property-mapping-create")
+ f"?type={subclass.__name__}",
}
)
return Response(TypeCreateSerializer(data, many=True).data)

View File

@ -1,5 +1,5 @@
"""Provider API Views"""
from django.shortcuts import reverse
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.decorators import action

View File

@ -1,5 +1,5 @@
"""Source API Views"""
from django.shortcuts import reverse
from django.urls import reverse
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.request import Request
@ -25,7 +25,7 @@ class SourceSerializer(ModelSerializer, MetaNameSerializer):
class Meta:
model = Source
fields = SOURCE_SERIALIZER_FIELDS = [
fields = [
"pk",
"name",
"slug",

View File

@ -9,6 +9,7 @@ from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.users import UserSerializer
from authentik.core.models import Token
from authentik.events.models import Event, EventAction
@ -16,10 +17,21 @@ from authentik.events.models import Event, EventAction
class TokenSerializer(ModelSerializer):
"""Token Serializer"""
user = UserSerializer()
class Meta:
model = Token
fields = ["pk", "identifier", "intent", "user", "description"]
fields = [
"pk",
"identifier",
"intent",
"user",
"description",
"expires",
"expiring",
]
depth = 2
class TokenViewSerializer(Serializer):
@ -40,6 +52,19 @@ class TokenViewSet(ModelViewSet):
lookup_field = "identifier"
queryset = Token.filter_not_expired()
serializer_class = TokenSerializer
search_fields = [
"identifier",
"intent",
"user__username",
"description",
]
filterset_fields = [
"identifier",
"intent",
"user__username",
"description",
]
ordering = ["expires"]
@swagger_auto_schema(responses={200: TokenViewSerializer(many=False)})
@action(detail=True)

View File

@ -2,33 +2,35 @@
from drf_yasg2.utils import swagger_auto_schema
from guardian.utils import get_anonymous_user
from rest_framework.decorators import action
from rest_framework.fields import CharField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import (
BooleanField,
ModelSerializer,
SerializerMethodField,
)
from rest_framework.serializers import BooleanField, ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.models import User
from authentik.lib.templatetags.authentik_utils import avatar
class UserSerializer(ModelSerializer):
"""User Serializer"""
is_superuser = BooleanField(read_only=True)
avatar = SerializerMethodField()
def get_avatar(self, user: User) -> str:
"""Add user's avatar as URL"""
return avatar(user)
avatar = CharField(read_only=True)
class Meta:
model = User
fields = ["pk", "username", "name", "is_superuser", "email", "avatar"]
fields = [
"pk",
"username",
"name",
"is_active",
"last_login",
"is_superuser",
"email",
"avatar",
"attributes",
]
class UserViewSet(ModelViewSet):
@ -36,6 +38,8 @@ class UserViewSet(ModelViewSet):
queryset = User.objects.none()
serializer_class = UserSerializer
search_fields = ["username", "name", "is_active"]
filterset_fields = ["username", "name", "is_active"]
def get_queryset(self):
return User.objects.all().exclude(pk=get_anonymous_user().pk)

View File

@ -1,6 +1,6 @@
"""API Utilities"""
from django.db.models import Model
from rest_framework.fields import CharField
from rest_framework.fields import CharField, IntegerField
from rest_framework.serializers import Serializer, SerializerMethodField
@ -28,9 +28,21 @@ class MetaNameSerializer(Serializer):
class TypeCreateSerializer(Serializer):
"""Types of an object that can be created"""
name = CharField(read_only=True)
description = CharField(read_only=True)
link = CharField(read_only=True)
name = CharField(required=True)
description = CharField(required=True)
link = CharField(required=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model:
raise NotImplementedError
class CacheSerializer(Serializer):
"""Generic cache stats for an object"""
count = IntegerField(read_only=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError

View File

@ -9,10 +9,10 @@ from authentik.lib.widgets import GroupedModelChoiceField
class ApplicationForm(forms.ModelForm):
"""Application Form"""
def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs): # pragma: no cover
super().__init__(*args, **kwargs)
self.fields["provider"].queryset = (
Provider.objects.all().order_by("pk").select_subclasses()
Provider.objects.all().order_by("name").select_subclasses()
)
class Meta:

View File

@ -1,15 +1,20 @@
"""authentik core models"""
from datetime import timedelta
from typing import Any, Dict, Optional, Type
from hashlib import md5, sha256
from typing import Any, Optional, Type
from urllib.parse import urlencode
from uuid import uuid4
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import UserManager as DjangoUserManager
from django.db import models
from django.db.models import Q, QuerySet
from django.forms import ModelForm
from django.http import HttpRequest
from django.templatetags.static import static
from django.utils.functional import cached_property
from django.utils.html import escape
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from guardian.mixins import GuardianUserMixin
@ -21,6 +26,7 @@ from authentik.core.exceptions import PropertyMappingExpressionException
from authentik.core.signals import password_changed
from authentik.core.types import UILoginButton
from authentik.flows.models import Flow
from authentik.lib.config import CONFIG
from authentik.lib.models import CreatedUpdatedModel, SerializerModel
from authentik.managed.models import ManagedModel
from authentik.policies.models import PolicyBindingModel
@ -29,6 +35,9 @@ LOGGER = get_logger()
USER_ATTRIBUTE_DEBUG = "goauthentik.io/user/debug"
USER_ATTRIBUTE_SA = "goauthentik.io/user/service-account"
GRAVATAR_URL = "https://secure.gravatar.com"
DEFAULT_AVATAR = static("dist/assets/images/user_default.png")
def default_token_duration():
"""Default duration a Token is valid"""
@ -81,7 +90,7 @@ class UserManager(DjangoUserManager):
class User(GuardianUserMixin, AbstractUser):
"""Custom User model to allow easier adding o f user-based settings"""
"""Custom User model to allow easier adding of user-based settings"""
uuid = models.UUIDField(default=uuid4, editable=False)
name = models.TextField(help_text=_("User's display name."))
@ -94,7 +103,7 @@ class User(GuardianUserMixin, AbstractUser):
objects = UserManager()
def group_attributes(self) -> Dict[str, Any]:
def group_attributes(self) -> dict[str, Any]:
"""Get a dictionary containing the attributes from all groups the user belongs to,
including the users attributes"""
final_attributes = {}
@ -119,6 +128,30 @@ class User(GuardianUserMixin, AbstractUser):
self.password_change_date = now()
return super().set_password(password)
@property
def uid(self) -> str:
"""Generate a globall unique UID, based on the user ID and the hashed secret key"""
return sha256(f"{self.id}-{settings.SECRET_KEY}".encode("ascii")).hexdigest()
@property
def avatar(self) -> str:
"""Get avatar, depending on authentik.avatar setting"""
mode = CONFIG.raw.get("authentik").get("avatars")
if mode == "none":
return DEFAULT_AVATAR
if mode == "gravatar":
parameters = [
("s", "158"),
("r", "g"),
]
# gravatar uses md5 for their URLs, so md5 can't be avoided
mail_hash = md5(self.email.encode("utf-8")).hexdigest() # nosec
gravatar_url = (
f"{GRAVATAR_URL}/avatar/{mail_hash}?{urlencode(parameters, doseq=True)}"
)
return escape(gravatar_url)
raise ValueError(f"Invalid avatar mode {mode}")
class Meta:
permissions = (
@ -252,11 +285,6 @@ class Source(SerializerModel, PolicyBindingModel):
button. If source doesn't use http-based flow, return None."""
return None
@property
def ui_additional_info(self) -> Optional[str]:
"""Return additional Info, such as a callback URL. Show in the administration interface."""
return None
@property
def ui_user_settings(self) -> Optional[str]:
"""Entrypoint to integrate with User settings. Can either return None if no

View File

@ -46,8 +46,7 @@ def backup_database(self: MonitoredTask): # pragma: no cover
TaskResult(
TaskResultStatus.SUCCESSFUL,
[
f"Successfully finished database backup {naturaltime(start)}",
out.getvalue(),
f"Successfully finished database backup {naturaltime(start)} {out.getvalue()}",
],
)
)

View File

@ -1,12 +0,0 @@
{% extends "base/skeleton.html" %}
{% load i18n %}
{% block body %}
<ak-message-container></ak-message-container>
<div class="pf-c-page">
<a class="pf-c-skip-to-content pf-c-button pf-m-primary" href="#main-content">{% trans 'Skip to content' %}</a>
{% block page_content %}
{% endblock %}
</div>
{% endblock %}

View File

@ -11,12 +11,9 @@
<title>{% block title %}{% trans title|default:config.authentik.branding.title %}{% endblock %}</title>
<link rel="icon" type="image/png" href="{% static 'dist/assets/icons/icon.png' %}?v={{ ak_version }}">
<link rel="shortcut icon" type="image/png" href="{% static 'dist/assets/icons/icon.png' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly-addons.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/fontawesome.min.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly-base.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}?v={{ ak_version }}">
<script src="{% url 'javascript-catalog' %}?v={{ ak_version }}"></script>
<script src="{% static 'dist/main.js' %}?v={{ ak_version }}" type="module"></script>
{% block head %}
{% endblock %}
</head>

View File

@ -1,4 +1,4 @@
{% extends 'base/page.html' %}
{% extends 'base/skeleton.html' %}
{% load i18n %}
{% load authentik_utils %}

View File

@ -1,31 +0,0 @@
{% extends "login/base.html" %}
{% load authentik_utils %}
{% load i18n %}
{% block title %}
{{ title }}
{% endblock %}
{% block card %}
<form method="POST" action="{{ url }}" autosubmit>
{% csrf_token %}
{% for key, value in attrs.items %}
<input type="hidden" name="{{ key }}" value="{{ value }}">
{% endfor %}
<div class="pf-c-form__group pf-u-display-flex pf-u-justify-content-center">
<div class="pf-c-form__group-control">
<span class="pf-c-spinner" role="progressbar" aria-valuetext="Loading...">
<span class="pf-c-spinner__clipper"></span>
<span class="pf-c-spinner__lead-ball"></span>
<span class="pf-c-spinner__tail-ball"></span>
</span>
</div>
</div>
<div class="pf-c-form__group pf-m-action">
<div class="pf-c-form__actions">
<button class="pf-c-button pf-m-primary pf-m-block" type="submit">{% trans 'Continue' %}</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -1,9 +1,6 @@
{% extends container_template|default:"administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
{% block above_form %}
@ -38,4 +35,3 @@
<input class="pf-c-button pf-m-danger" type="submit" form="delete-form" value="{% trans 'Delete' %}" />
<a class="pf-c-button pf-m-secondary" href="{% back %}">{% trans "Back" %}</a>
</footer>
{% endblock %}

View File

@ -1,53 +0,0 @@
{% load i18n %}
<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-applications"></i>
{% trans 'Applications' %}
</h1>
</div>
</section>
<section class="pf-c-page__main-section">
{% if applications %}
<div class="pf-l-gallery pf-m-gutter">
{% for app in applications %}
<a href="{{ app.get_launch_url }}" class="pf-c-card pf-m-hoverable pf-m-compact ak-root-link">
<div class="pf-c-card__header">
{% if app.meta_icon %}
<img class="app-icon pf-c-avatar" src="{{ app.meta_icon.url }}" alt="{% trans 'Application Icon' %}">
{% else %}
<i class="pf-icon pf-icon-arrow"></i>
{% endif %}
</div>
<div class="pf-c-card__title">
<p id="card-1-check-label">{{ app.name }}</p>
<div class="pf-c-content">
<small>{{ app.meta_publisher }}</small>
</div>
</div>
<div class="pf-c-card__body">
{% trans app.meta_description|truncatewords:35 %}
</div>
</a>
{% endfor %}
</div>
{% else %}
<div class="pf-c-empty-state pf-m-full-height">
<div class="pf-c-empty-state__content">
<i class="fas fa-cubes pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">{% trans 'No Applications available.' %}</h1>
<div class="pf-c-empty-state__body">
{% trans "Either no applications are defined, or you don't have access to any." %}
</div>
{% if perms.authentik_core.add_application %}
<a href="{% url 'authentik_admin:application-create' %}" class="pf-c-button pf-m-primary" type="button">
{% trans 'Create Application' %}
</a>
{% endif %}
</div>
</div>
{% endif %}
</section>
</main>

View File

@ -28,10 +28,8 @@
{% for source in sources %}
<li class="pf-c-login__main-footer-links-item">
<a href="{{ source.url }}" class="pf-c-login__main-footer-links-item-link">
{% if source.icon_path %}
<img src="{% static source.icon_path %}" alt="{{ source.name }}">
{% elif source.icon_url %}
<img src="icon_url" alt="{{ source.name }}">
{% if source.icon_url %}
<img src="{{ source.icon_url }}" alt="{{ source.name }}">
{% else %}
<i class="pf-icon pf-icon-arrow" title="{{ source.name }}"></i>
{% endif %}

View File

@ -18,7 +18,7 @@
<div class="pf-c-background-image">
<svg xmlns="http://www.w3.org/2000/svg" class="pf-c-background-image__filter" width="0" height="0">
<filter id="image_overlay">
<feColorMatrix type="matrix" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0"></feColorMatrix>
<feColorMatrix in="SourceGraphic" type="matrix" values="1.3 0 0 0 0 0 1.3 0 0 0 0 0 1.3 0 0 0 0 0 1 0" />
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
<feFuncR type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncR>
<feFuncG type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncG>
@ -48,7 +48,7 @@
{% endfor %}
{% if config.authentik.branding.title != "authentik" %}
<li>
<a href="https://github.com/beryju/authentik">
<a href="https://goauthentik.io">
{% trans 'Powered by authentik' %}
</a>
</li>

View File

@ -1,19 +0,0 @@
{% extends 'login/base.html' %}
{% load static %}
{% load i18n %}
{% block card %}
<form method="POST" class="pf-c-form">
{% block above_form %}
{% endblock %}
{% include 'partials/form.html' %}
{% block beneath_form %}
{% endblock %}
<div class="pf-c-form__group pf-m-action">
<button class="pf-c-button pf-m-primary pf-m-block" type="submit">{% trans primary_action %}</button>
</div>
</form>
{% endblock %}

View File

@ -1,18 +0,0 @@
{% extends 'login/form.html' %}
{% load i18n %}
{% load authentik_utils %}
{% block above_form %}
<div class="pf-c-form__group">
<div class="form-control-static">
<div class="left">
<img class="pf-c-avatar" src="{% avatar user %}" alt="">
{{ user.username }}
</div>
<div class="right">
<a href="{% url 'authentik_flows:cancel' %}">{% trans 'Not you?' %}</a>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,24 +0,0 @@
{% extends 'login/base.html' %}
{% load static %}
{% load i18n %}
{% load authentik_utils %}
{% block title %}
{% trans title %}
{% endblock %}
{% block head %}
<meta http-equiv="refresh" content="0; url={{ target_url }}" />
{% endblock %}
{% block card %}
<header class="login-pf-header">
<h1>{% trans title %}</h1>
</header>
<form>
<div class="form-group">
<div class="spinner spinner-lg"></div>
</div>
</form>
{% endblock %}

View File

@ -3,7 +3,7 @@
{% csrf_token %}
{% if form.non_field_errors %}
<div class="pf-c-form__group has-error">
<div class="pf-c-form__group">
<p class="pf-c-form__helper-text pf-m-error">
{{ form.non_field_errors }}
</p>
@ -13,7 +13,7 @@
{% if field.field.widget|fieldtype == 'HiddenInput' %}
{{ field }}
{% else %}
<div class="pf-c-form__group {% if field.errors %} has-error {% endif %}">
<div class="pf-c-form__group">
{% if field.field.widget|fieldtype == 'RadioSelect' %}
<label class="pf-c-form__label" {% if field.field.required %}class="required" {% endif %}
for="{{ field.name }}-{{ forloop.counter0 }}">

View File

@ -1,42 +0,0 @@
{% load i18n %}
{% load authentik_utils %}
<div class="pf-c-toolbar__item pf-m-pagination ">
<div class="pf-c-pagination pf-m-compact pf-m-hidden pf-m-visible-on-md">
<div class="pf-c-pagination pf-m-compact pf-m-compact pf-m-hidden pf-m-visible-on-md">
<div class="pf-c-options-menu">
<div class="pf-c-options-menu__toggle pf-m-text pf-m-plain">
<span class="pf-c-options-menu__toggle-text">
{% blocktrans with start_index=page_obj.start_index end_index=page_obj.end_index total_items=paginator.count %}
{{ start_index }} - {{ end_index }} of {{ total_items }}
{% endblocktrans %}
</span>
</div>
</div>
<nav class="pf-c-pagination__nav" aria-label="Pagination">
<div class="pf-c-pagination__nav-control pf-m-prev">
<a class="pf-c-button pf-m-plain"
{% if page_obj.has_previous %}
href="{{ request.path }}?{% query_transform page=page_obj.previous_page_number %}"
{% else %}
disabled
{% endif %}
aria-label="{% trans 'Go to previous page' %}">
<i class="fas fa-angle-left" aria-hidden="true"></i>
</a>
</div>
<div class="pf-c-pagination__nav-control pf-m-next">
<a class="pf-c-button pf-m-plain"
{% if page_obj.has_next %}
href="{{ request.path }}?{% query_transform page=page_obj.next_page_number %}"
{% else %}
disabled
{% endif %}
aria-label="{% trans 'Go to next page' %}">
<i class="fas fa-angle-right" aria-hidden="true"></i>
</a>
</div>
</nav>
</div>
</div>
</div>

View File

@ -1,13 +0,0 @@
<div class="pf-c-toolbar__group pf-m-filter-group">
<div class="pf-c-toolbar__item pf-m-search-filter">
<form class="pf-c-input-group" method="GET">
{# include page data for pagination #}
<input type="hidden" name="page" value="{{ page_obj.number }}">
<input class="pf-c-form-control" name="search" type="search" placeholder="Search..." value="{{ request.GET.search }}">
<button class="pf-c-button pf-m-control" type="submit">
<i class="fas fa-search" aria-hidden="true"></i>
</button>
</form>
</div>
</div>

View File

@ -1,5 +1,11 @@
{% extends "base/skeleton.html" %}
{% load static %}
{% block head %}
<script src="{% static 'dist/main.js' %}?v={{ ak_version }}" type="module"></script>
{% endblock %}
{% block body %}
<ak-interface-admin></ak-interface-admin>
{% endblock %}

View File

@ -13,7 +13,7 @@
<p>{% trans "Configure settings relevant to your user profile." %}</p>
</div>
</section>
<ak-tabs>
<ak-tabs vertical="true" style="height: 100%;">
<section slot="page-1" data-tab-title="{% trans 'User details' %}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
@ -24,9 +24,7 @@
</div>
</section>
<section slot="page-2" data-tab-title="{% trans 'Tokens' %}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<ak-site-shell url="{% url 'authentik_core:user-tokens' %}">
<div slot="body"></div>
</ak-site-shell>
<ak-token-user-list></ak-token-user-list>
</section>
{% user_stages as user_stages_loc %}
{% for stage, stage_link in user_stages_loc.items %}

View File

@ -1,100 +0,0 @@
{% load i18n %}
<div class="pf-c-card">
<div class="pf-c-card__header pf-c-title pf-m-md">
<p>{% trans "Tokens can be used to access authentik's API." %}</p>
</div>
{% if object_list %}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">
{% include 'partials/toolbar_search.html' %}
<div class="pf-c-toolbar__bulk-select">
<ak-modal-button href="{% url 'authentik_core:user-tokens-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
{% include 'partials/pagination.html' %}
</div>
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Identifier' %}</th>
<th role="columnheader" scope="col">{% trans 'Expires?' %}</th>
<th role="columnheader" scope="col">{% trans 'Expiry Date' %}</th>
<th role="columnheader" scope="col">{% trans 'Description' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for token in object_list %}
<tr role="row">
<th role="columnheader">
<div>{{ token.identifier }}</div>
</th>
<td role="cell">
<span>
{{ token.expiring|yesno:"Yes,No" }}
</span>
</td>
<td role="cell">
<span>
{% if not token.expiring %}
-
{% else %}
{{ token.expires }}
{% endif %}
</span>
</td>
<td role="cell">
<span>
{{ token.description }}
</span>
</td>
<td>
<ak-modal-button href="{% url 'authentik_core:user-tokens-update' identifier=token.identifier %}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
{% trans 'Edit' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="{% url 'authentik_core:user-tokens-delete' identifier=token.identifier %}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
{% trans 'Delete' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-token-copy-button identifier="{{ token.identifier }}">
{% trans 'Copy token' %}
</ak-token-copy-button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-pagination pf-m-bottom">
{% include 'partials/pagination.html' %}
</div>
{% else %}
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="fas fa-cubes pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans 'No Tokens.' %}
</h1>
<div class="pf-c-empty-state__body">
{% trans 'Currently no tokens exist. Click the button below to create one.' %}
</div>
<ak-modal-button href="{% url 'authentik_core:user-tokens-create' %}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
{% trans 'Create' %}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</div>
</div>
{% endif %}
</div>

View File

@ -1,6 +1,6 @@
"""impersonation tests"""
from django.shortcuts import reverse
from django.test.testcases import TestCase
from django.urls import reverse
from authentik.core.models import User

View File

@ -2,8 +2,8 @@
import string
from random import SystemRandom
from django.shortcuts import reverse
from django.test import TestCase
from django.urls import reverse
from authentik.core.models import User
@ -28,9 +28,3 @@ class TestOverviewViews(TestCase):
self.assertEqual(
self.client.get(reverse("authentik_core:shell")).status_code, 200
)
def test_overview(self):
"""Test overview"""
self.assertEqual(
self.client.get(reverse("authentik_core:overview")).status_code, 200
)

View File

@ -2,8 +2,8 @@
import string
from random import SystemRandom
from django.shortcuts import reverse
from django.test import TestCase
from django.urls import reverse
from authentik.core.models import User

View File

@ -2,6 +2,10 @@
from dataclasses import dataclass
from typing import Optional
from django.db.models.base import Model
from rest_framework.fields import CharField
from rest_framework.serializers import Serializer
@dataclass
class UILoginButton:
@ -13,8 +17,19 @@ class UILoginButton:
# URL Which Button points to
url: str
# Icon name, ran through django's static
icon_path: Optional[str] = None
# Icon URL, used as-is
icon_url: Optional[str] = None
class UILoginButtonSerializer(Serializer):
"""Serializer for Login buttons of sources"""
name = CharField()
url = CharField()
icon_url = CharField()
def create(self, validated_data: dict) -> Model:
return Model()
def update(self, instance: Model, validated_data: dict) -> Model:
return Model()

View File

@ -1,14 +1,13 @@
"""authentik URL Configuration"""
from django.urls import path
from authentik.core.views import impersonate, library, shell, user
from authentik.core.views import impersonate, shell, user
urlpatterns = [
path("", shell.ShellView.as_view(), name="shell"),
# User views
path("-/user/", user.UserSettingsView.as_view(), name="user-settings"),
path("-/user/details/", user.UserDetailsView.as_view(), name="user-details"),
path("-/user/tokens/", user.TokenListView.as_view(), name="user-tokens"),
path(
"-/user/tokens/create/",
user.TokenCreateView.as_view(),
@ -24,8 +23,6 @@ urlpatterns = [
user.TokenDeleteView.as_view(),
name="user-tokens-delete",
),
# Libray
path("library", library.LibraryView.as_view(), name="overview"),
# Impersonation
path(
"-/impersonation/<int:user_id>/",

View File

@ -1,23 +0,0 @@
"""authentik library view"""
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
from authentik.core.models import Application
from authentik.policies.engine import PolicyEngine
class LibraryView(LoginRequiredMixin, TemplateView):
"""Overview for logged in user, incase user opens authentik directly
and is not being forwarded"""
template_name = "library.html"
def get_context_data(self, **kwargs):
kwargs["applications"] = []
for application in Application.objects.all().order_by("name"):
engine = PolicyEngine(application, self.request.user, self.request)
engine.build()
if engine.passing:
kwargs["applications"].append(application)
return super().get_context_data(**kwargs)

View File

@ -1,25 +1,20 @@
"""authentik core user views"""
from typing import Any, Dict
from typing import Any
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import (
PermissionRequiredMixin as DjangoPermissionRequiredMixin,
)
from django.contrib.messages.views import SuccessMessageMixin
from django.db.models.query import QuerySet
from django.http.response import HttpResponse
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import ListView, UpdateView
from django.views.generic import UpdateView
from django.views.generic.base import TemplateView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from guardian.mixins import PermissionRequiredMixin
from guardian.shortcuts import get_objects_for_user
from authentik.admin.views.utils import (
DeleteMessageView,
SearchListMixin,
UserPaginateListMixin,
)
from authentik.admin.views.utils import DeleteMessageView
from authentik.core.forms.token import UserTokenForm
from authentik.core.forms.users import UserDetailForm
from authentik.core.models import Token, TokenIntents
@ -45,7 +40,7 @@ class UserDetailsView(SuccessMessageMixin, LoginRequiredMixin, UpdateView):
def get_object(self):
return self.request.user
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
kwargs = super().get_context_data(**kwargs)
unenrollment_flow = Flow.with_policy(
self.request, designation=FlowDesignation.UNRENOLLMENT
@ -54,30 +49,6 @@ class UserDetailsView(SuccessMessageMixin, LoginRequiredMixin, UpdateView):
return kwargs
class TokenListView(
LoginRequiredMixin,
PermissionListMixin,
UserPaginateListMixin,
SearchListMixin,
ListView,
):
"""Show list of all tokens"""
model = Token
ordering = "expires"
permission_required = "authentik_core.view_token"
template_name = "user/token_list.html"
search_fields = [
"identifier",
"intent",
"description",
]
def get_queryset(self) -> QuerySet:
return super().get_queryset().filter(intent=TokenIntents.INTENT_API)
class TokenCreateView(
SuccessMessageMixin,
LoginRequiredMixin,
@ -91,7 +62,7 @@ class TokenCreateView(
permission_required = "authentik_core.add_token"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_core:user-tokens")
success_url = "/"
success_message = _("Successfully created Token")
def form_valid(self, form: UserTokenForm) -> HttpResponse:
@ -109,7 +80,7 @@ class TokenUpdateView(
form_class = UserTokenForm
permission_required = "authentik_core.change_token"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_core:user-tokens")
success_url = "/"
success_message = _("Successfully updated Token")
def get_object(self) -> Token:
@ -129,7 +100,7 @@ class TokenDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessage
model = Token
permission_required = "authentik_core.delete_token"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_core:user-tokens")
success_url = "/"
success_message = _("Successfully deleted Token")
def get_object(self) -> Token:

View File

@ -20,11 +20,16 @@ class CertificateKeyPairSerializer(ModelSerializer):
cert_expiry = DateTimeField(source="certificate.not_valid_after", read_only=True)
cert_subject = SerializerMethodField()
private_key_available = SerializerMethodField()
def get_cert_subject(self, instance: CertificateKeyPair) -> str:
"""Get certificate subject as full rfc4514"""
return instance.certificate.subject.rfc4514_string()
def get_private_key_available(self, instance: CertificateKeyPair) -> bool:
"""Show if this keypair has a private key configured or not"""
return instance.key_data != "" and instance.key_data is not None
def validate_certificate_data(self, value):
"""Verify that input is a valid PEM x509 Certificate"""
try:
@ -58,6 +63,7 @@ class CertificateKeyPairSerializer(ModelSerializer):
"key_data",
"cert_expiry",
"cert_subject",
"private_key_available",
]
extra_kwargs = {
"key_data": {"write_only": True},

View File

@ -29,7 +29,7 @@ class EventSerializer(ModelSerializer):
]
class EventTopPerUserSerialier(Serializer):
class EventTopPerUserSerializer(Serializer):
"""Response object of Event's top_per_user"""
application = DictField()
@ -60,7 +60,7 @@ class EventViewSet(ReadOnlyModelViewSet):
filterset_fields = ["action"]
@swagger_auto_schema(
method="GET", responses={200: EventTopPerUserSerialier(many=True)}
method="GET", responses={200: EventTopPerUserSerializer(many=True)}
)
@action(detail=False, methods=["GET"])
def top_per_user(self, request: Request):

View File

@ -13,7 +13,7 @@ class NotificationSerializer(ModelSerializer):
body = ReadOnlyField()
severity = ReadOnlyField()
event = EventSerializer()
event = EventSerializer(required=False)
class Meta:

View File

@ -1,11 +1,12 @@
"""NotificationTransport API Views"""
from django.http.response import Http404
from drf_yasg2.utils import no_body, swagger_auto_schema
from guardian.shortcuts import get_objects_for_user
from rest_framework.decorators import action
from rest_framework.fields import SerializerMethodField
from rest_framework.fields import CharField, ListField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework.viewsets import ModelViewSet
from authentik.events.models import (
@ -38,12 +39,28 @@ class NotificationTransportSerializer(ModelSerializer):
]
class NotificationTransportTestSerializer(Serializer):
"""Notification test serializer"""
messages = ListField(child=CharField())
def create(self, request: Request) -> Response:
raise NotImplementedError
def update(self, request: Request) -> Response:
raise NotImplementedError
class NotificationTransportViewSet(ModelViewSet):
"""NotificationTransport Viewset"""
queryset = NotificationTransport.objects.all()
serializer_class = NotificationTransportSerializer
@swagger_auto_schema(
responses={200: NotificationTransportTestSerializer(many=False)},
request_body=no_body,
)
@action(detail=True, methods=["post"])
# pylint: disable=invalid-name
def test(self, request: Request, pk=None) -> Response:
@ -61,6 +78,10 @@ class NotificationTransportViewSet(ModelViewSet):
user=request.user,
)
try:
return Response(transport.send(notification))
response = NotificationTransportTestSerializer(
data={"messages": transport.send(notification)}
)
response.is_valid()
return Response(response.data)
except NotificationTransportError as exc:
return Response(str(exc.__cause__ or None), status=503)

21
authentik/events/geo.py Normal file
View File

@ -0,0 +1,21 @@
"""events GeoIP Reader"""
from typing import Optional
from geoip2.database import Reader
from authentik.lib.config import CONFIG
def get_geoip_reader() -> Optional[Reader]:
"""Get GeoIP Reader, if configured, otherwise none"""
path = CONFIG.y("authentik.geoip")
if path == "" or not path:
return None
try:
return Reader(path)
except OSError:
return None
GEOIP_READER = get_geoip_reader()

Some files were not shown because too many files have changed in this diff Show More