Compare commits

...

238 Commits

Author SHA1 Message Date
2a6479062f don't overwrite connections for other sources
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-27 12:54:33 +02:00
52463b8f96 add group connection
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-27 12:44:45 +02:00
330f639a7e ldap source connection
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-27 12:43:39 +02:00
85ea4651e4 minor cleanup
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-27 12:43:36 +02:00
b15002a992 flows: stage_invalid() makes flow restart depending on invalid_response_action setting (#6780)
* flows: stage_invalid() makes flow restart depending on invalid_response_action setting

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-27 12:34:02 +02:00
82cbc16c45 core: bump psycopg from 3.1.11 to 3.1.12 (#6997)
Bumps [psycopg](https://github.com/psycopg/psycopg) from 3.1.11 to 3.1.12.
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.1.11...3.1.12)

---
updated-dependencies:
- dependency-name: psycopg
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 11:16:48 +02:00
4833a87009 core: bump pydantic from 2.4.0 to 2.4.1 (#6998)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.4.0...v2.4.1)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 11:16:39 +02:00
4e42c1df2a web: bump the sentry group in /web with 2 updates (#6999)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.71.0 to 7.72.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.71.0...7.72.0)

Updates `@sentry/tracing` from 7.71.0 to 7.72.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.71.0...7.72.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 11:16:27 +02:00
1dd39b2612 web: bump pyright from 1.1.328 to 1.1.329 in /web (#7000)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.328 to 1.1.329.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.329/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 11:15:59 +02:00
f7927114e5 website/blog: improved sentence (#6995)
kens catch

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-09-26 14:57:14 -05:00
4bb53fc3e8 website/blog: fix missing link in m2m post (#6994)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-26 21:41:55 +02:00
8e39ad2cda web/user: fix incorrect link to admin interface (#6993) 2023-09-26 19:51:45 +02:00
e55e27d060 root: disable APPEND_SLASH (#6928)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-26 18:59:28 +02:00
c93c6ee6f9 root: replace boj/redistore with vendored version of rbcervilla/redisstore (#6988)
* root: replace boj/redistore with vendored version of rbcervilla/redisstore

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* setup env for go tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-26 18:56:37 +02:00
90aa5409cd sources/ldap: add default property mapping to mirror directory structure (#6990)
* sources/ldap: add default property mapping to mirror directory structure

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* adjust name

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-26 18:55:33 +02:00
017771ddf7 website/blogs: Blog about m2m (#6974)
* m2m blog

* fix image ext

* tweak

* updated dependency

* formatting

* removed old tag

* Optimised images with calibre/image-actions

* fixed errors marc and samir found

* typo

* tweak

* image rename fighting me

---------

Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-09-26 11:14:27 -05:00
0e5952650b root: make Celery worker concurrency configurable (#6837)
* root: made Celery worker concurrency configurable

* core: fixed Celery worker command to set autoscaling options to account for worker concurrency setting

* Update website/docs/installation/configuration.md

Signed-off-by: Jens L. <jens@beryju.org>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens L. <jens@beryju.org>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@beryju.org>
2023-09-26 10:37:22 +00:00
e807f9f12c root: make postgres connection in makefile customizable (#6977)
* core/allow alternative postgres credentials

This commit allows the `dev-reset` command in the Makefile to pick up and use credentials from the
`.env` file if they are present, or fallback to the defaults provided if they are not. This is the
only place in the Makefile where the database credentials are used directly against postgresql
binaries. The syntax was tested with bash, zsh, and csh, and did not fail under those.

The `$${:-}` syntax is a combination of a Makefile idiom for "Pass a single `$` to the environment
where this command will be executed," and the shell expresion `${VARIABLE:-default}` means
"dereference the environment variable; if it is undefined, used the default value provided."

* Re-arrange sequence to avoid recursive make.

Nothing wrong with recursive make; it just wasn't essential
here.  `migrate` is just a build target, not a task.

* Cleanup according to the Usage:
  checkmake [options] <makefile>...
  checkmake -h | --help
  checkmake --version
  checkmake --list-rules Makefile linting tool.

* core: added 'help' to the Makefile

* get postgres config from authentik config loader

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* don't set -x by default

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* sort help

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update help strings

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-26 12:10:18 +02:00
3e81824388 core: prevent self-impersonation (#6885)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-26 12:04:40 +02:00
44ac944706 web: bump @typescript-eslint/parser from 6.7.2 to 6.7.3 in /web (#6984)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.7.2 to 6.7.3.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.7.3/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 10:48:36 +02:00
ee151b9e17 core: bump pydantic from 2.3.0 to 2.4.0 (#6979)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.3.0...v2.4.0)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 10:48:22 +02:00
0f87d97594 core: bump selenium from 4.12.0 to 4.13.0 (#6981)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.12.0 to 4.13.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.12.0...selenium-4.13.0)

---
updated-dependencies:
- dependency-name: selenium
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 10:47:54 +02:00
5fcf4cb592 core: bump pylint from 2.17.5 to 2.17.6 (#6980)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 2.17.5 to 2.17.6.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v2.17.5...v2.17.6)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 10:47:36 +02:00
47f6ed48dd web: bump the sentry group in /web with 2 updates (#6982)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.70.0 to 7.71.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.70.0...7.71.0)

Updates `@sentry/tracing` from 7.70.0 to 7.71.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.70.0...7.71.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 10:47:00 +02:00
c92f416146 web: bump @rollup/plugin-typescript from 11.1.3 to 11.1.4 in /web (#6985)
Bumps [@rollup/plugin-typescript](https://github.com/rollup/plugins/tree/HEAD/packages/typescript) from 11.1.3 to 11.1.4.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/typescript/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/typescript-v11.1.4/packages/typescript)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 10:46:29 +02:00
310099650f web: bump the eslint group in /web with 1 update (#6983)
Bumps the eslint group in /web with 1 update: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin).

- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.7.3/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 10:44:33 +02:00
0d6c4c41fd translate: Updates for file web/xliff/en.xlf in zh_CN on branch main (#6975)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-25 23:19:06 +02:00
036a1cbde8 translate: Updates for file web/xliff/en.xlf in zh-Hans on branch main (#6976)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-25 23:18:49 +02:00
2398157b0b website/blogs: Swap em dash and hyphen on blog post (#6978)
Swap em dash and hyphen

Signed-off-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
2023-09-25 23:08:30 +02:00
ce1a071d16 web/user: fix unenrollment flow not being shown (#6972)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-25 16:59:45 +02:00
ea264ffc13 root: remove outdated sponsorship section on readme (#6973)
Improve reliability somewhat

Signed-off-by: okami <43506079+okamidash@users.noreply.github.com>
2023-09-25 16:38:50 +02:00
80e86c52e7 web/flows: improve WebAuthn error messages (#6957)
* web/flows: improve WebAuthn error messages

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* include localhost

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-25 12:43:24 +02:00
07ca318535 website: bump remark-github from 11.2.4 to 12.0.0 in /website (#6963)
* website: bump remark-github from 11.2.4 to 12.0.0 in /website

Bumps [remark-github](https://github.com/remarkjs/remark-github) from 11.2.4 to 12.0.0.
- [Release notes](https://github.com/remarkjs/remark-github/releases)
- [Commits](https://github.com/remarkjs/remark-github/compare/11.2.4...12.0.0)

---
updated-dependencies:
- dependency-name: remark-github
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

* fix build

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-25 12:42:54 +02:00
01ea6a402f web: bump the eslint group in /web with 1 update (#6969)
Bumps the eslint group in /web with 1 update: [eslint](https://github.com/eslint/eslint).

- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.49.0...v8.50.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:28:10 +02:00
385f949238 web: bump the babel group in /web with 3 updates (#6971)
Bumps the babel group in /web with 3 updates: [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core), [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) and [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript).


Updates `@babel/core` from 7.22.20 to 7.23.0
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.0/packages/babel-core)

Updates `@babel/plugin-proposal-decorators` from 7.22.15 to 7.23.0
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.0/packages/babel-plugin-proposal-decorators)

Updates `@babel/preset-typescript` from 7.22.15 to 7.23.0
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.0/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: babel
- dependency-name: "@babel/plugin-proposal-decorators"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: babel
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: babel
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:27:06 +02:00
af33f8c014 web: bump the storybook group in /web with 5 updates (#6968)
Bumps the storybook group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `7.4.3` | `7.4.5` |
| [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `7.4.3` | `7.4.5` |
| [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) | `7.4.3` | `7.4.5` |
| [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite) | `7.4.3` | `7.4.5` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `7.4.3` | `7.4.5` |


Updates `@storybook/addon-essentials` from 7.4.3 to 7.4.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.5/code/addons/essentials)

Updates `@storybook/addon-links` from 7.4.3 to 7.4.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.5/code/addons/links)

Updates `@storybook/web-components` from 7.4.3 to 7.4.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.5/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 7.4.3 to 7.4.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.5/code/frameworks/web-components-vite)

Updates `storybook` from 7.4.3 to 7.4.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.5/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:18:05 +02:00
bcf7545cad core: bump psycopg from 3.1.10 to 3.1.11 (#6964)
Bumps [psycopg](https://github.com/psycopg/psycopg) from 3.1.10 to 3.1.11.
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.1.10...3.1.11)

---
updated-dependencies:
- dependency-name: psycopg
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:17:45 +02:00
bf149a1102 web: bump rollup from 3.29.2 to 3.29.3 in /web (#6970)
Bumps [rollup](https://github.com/rollup/rollup) from 3.29.2 to 3.29.3.
- [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/v3.29.2...v3.29.3)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:17:23 +02:00
3dfb10ae23 core: bump ruff from 0.0.290 to 0.0.291 (#6965)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.290 to 0.0.291.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.290...v0.0.291)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:17:02 +02:00
1853ce1591 core: bump django-silk from 5.0.3 to 5.0.4 (#6967)
Bumps [django-silk](https://github.com/jazzband/django-silk) from 5.0.3 to 5.0.4.
- [Release notes](https://github.com/jazzband/django-silk/releases)
- [Changelog](https://github.com/jazzband/django-silk/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jazzband/django-silk/compare/5.0.3...5.0.4)

---
updated-dependencies:
- dependency-name: django-silk
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:16:39 +02:00
b88b469f94 core: bump drf-spectacular from 0.26.4 to 0.26.5 (#6966)
Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.26.4 to 0.26.5.
- [Release notes](https://github.com/tfranzel/drf-spectacular/releases)
- [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.26.4...0.26.5)

---
updated-dependencies:
- dependency-name: drf-spectacular
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:16:11 +02:00
1a50e9f8d0 translate: Updates for file locale/en/LC_MESSAGES/django.po in fr on branch main (#6960)
Translate locale/en/LC_MESSAGES/django.po in fr

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'fr'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-23 12:42:44 +00:00
db2c0667a9 website/integrations: fix typo
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-22 19:10:15 +02:00
671b7156ed web: improve testability (#6952)
web/improve testability

This is a trio of small hacks that allow the E2E tests to find several components
on the page while the test is running:

- Add a `data-managed-for` field to SearchSelect's positioned elements. If a search
  has a `name` field, it will be reflected here, allowing tests to find specific
  instances of the dropdown elements.
- Add a forwarder to the search select wrappers we use for our SearchSelect.
- Added aria details to the UserLibrary header to make it easy to identify.
2023-09-22 09:04:30 -07:00
355c5f0f74 core: bump cryptography from 41.0.3 to 41.0.4 (#6951)
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.3 to 41.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.3...41.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-22 16:24:42 +02:00
cfb392196b root: don't exclude enterprise from container image (#6956)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-22 16:22:16 +02:00
7c3194e9b5 core: bump twilio from 8.8.0 to 8.9.0 (#6953)
Bumps [twilio](https://github.com/twilio/twilio-python) from 8.8.0 to 8.9.0.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/8.8.0...8.9.0)

---
updated-dependencies:
- dependency-name: twilio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-22 11:02:01 +02:00
a32755b6c8 root: Add setting to adjust database config for pgpool (#6949) 2023-09-21 12:54:18 +02:00
9ab3f26082 website: bump the docusaurus group in /website with 3 updates (#6943)
Bumps the docusaurus group in /website with 3 updates: [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects), [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) and [@docusaurus/theme-mermaid](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-theme-mermaid).


Updates `@docusaurus/plugin-client-redirects` from 2.4.1 to 2.4.3
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v2.4.3/packages/docusaurus-plugin-client-redirects)

Updates `@docusaurus/preset-classic` from 2.4.1 to 2.4.3
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v2.4.3/packages/docusaurus-preset-classic)

Updates `@docusaurus/theme-mermaid` from 2.4.1 to 2.4.3
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v2.4.3/packages/docusaurus-theme-mermaid)

---
updated-dependencies:
- dependency-name: "@docusaurus/plugin-client-redirects"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/preset-classic"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/theme-mermaid"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 11:50:46 +02:00
37bd01998a web: bump the sentry group in /web with 2 updates (#6944)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.69.0 to 7.70.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.69.0...7.70.0)

Updates `@sentry/tracing` from 7.69.0 to 7.70.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.69.0...7.70.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 11:50:03 +02:00
0e0661b395 web: bump the eslint group in /web with 1 update (#6946)
Bumps the eslint group in /web with 1 update: [eslint-plugin-storybook](https://github.com/storybookjs/eslint-plugin-storybook).

- [Release notes](https://github.com/storybookjs/eslint-plugin-storybook/releases)
- [Changelog](https://github.com/storybookjs/eslint-plugin-storybook/blob/main/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/eslint-plugin-storybook/compare/v0.6.13...v0.6.14)

---
updated-dependencies:
- dependency-name: eslint-plugin-storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 11:49:29 +02:00
5f3bacb7a9 web: bump the storybook group in /web with 6 updates (#6945)
Bumps the storybook group in /web with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `7.4.2` | `7.4.3` |
| [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `7.4.2` | `7.4.3` |
| [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) | `7.4.2` | `7.4.3` |
| [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite) | `7.4.2` | `7.4.3` |
| [eslint-plugin-storybook](https://github.com/storybookjs/eslint-plugin-storybook) | `0.6.13` | `0.6.14` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `7.4.2` | `7.4.3` |


Updates `@storybook/addon-essentials` from 7.4.2 to 7.4.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.3/code/addons/essentials)

Updates `@storybook/addon-links` from 7.4.2 to 7.4.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.3/code/addons/links)

Updates `@storybook/web-components` from 7.4.2 to 7.4.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.3/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 7.4.2 to 7.4.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.3/code/frameworks/web-components-vite)

Updates `eslint-plugin-storybook` from 0.6.13 to 0.6.14
- [Release notes](https://github.com/storybookjs/eslint-plugin-storybook/releases)
- [Changelog](https://github.com/storybookjs/eslint-plugin-storybook/blob/main/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/eslint-plugin-storybook/compare/v0.6.13...v0.6.14)

Updates `storybook` from 7.4.2 to 7.4.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.3/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: eslint-plugin-storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 11:49:11 +02:00
475ef8b057 web: bump @types/grecaptcha from 3.0.4 to 3.0.5 in /web (#6947)
Bumps [@types/grecaptcha](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/grecaptcha) from 3.0.4 to 3.0.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/grecaptcha)

---
updated-dependencies:
- dependency-name: "@types/grecaptcha"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 11:48:51 +02:00
16db9f220a core: bump urllib3 from 2.0.4 to 2.0.5 (#6948)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.4 to 2.0.5.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.0.4...v2.0.5)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 11:48:36 +02:00
0370040473 core: bump node from 20.5 to 20.6 (#6784)
* core: bump node from 20.5 to 20.6

Bumps node from 20.5 to 20.6.

---
updated-dependencies:
- dependency-name: node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

* unlock everywhere

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-20 12:28:47 +02:00
9a35e893ec web: bump pyright from 1.1.327 to 1.1.328 in /web (#6940)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.327 to 1.1.328.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.328/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-20 11:09:54 +02:00
87e37af273 web: bump the storybook group in /web with 1 update (#6939)
Bumps the storybook group in /web with 1 update: [storybook-addon-mock](https://github.com/nutboltu/storybook-addon-mock).

- [Release notes](https://github.com/nutboltu/storybook-addon-mock/releases)
- [Commits](https://github.com/nutboltu/storybook-addon-mock/compare/4.2.1...4.3.0)

---
updated-dependencies:
- dependency-name: storybook-addon-mock
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-20 11:09:34 +02:00
7585f2aa9a web: bump the eslint group in /web with 1 update (#6933)
Bumps the eslint group in /web with 1 update: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin).

- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.7.2/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 16:15:22 +02:00
cf9a094019 website: bump postcss from 8.4.29 to 8.4.30 in /website (#6932)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.29 to 8.4.30.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.29...8.4.30)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 15:22:43 +02:00
a16c0e5e8f web: bump @typescript-eslint/parser from 6.7.0 to 6.7.2 in /web (#6934)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.7.0 to 6.7.2.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.7.2/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 15:22:06 +02:00
3772379e1c web: bump turnstile-types from 1.1.2 to 1.1.3 in /web (#6935)
Bumps [turnstile-types](https://github.com/le0developer/turnstile-types) from 1.1.2 to 1.1.3.
- [Changelog](https://github.com/Le0Developer/turnstile-types/blob/master/HISTORY.md)
- [Commits](https://github.com/le0developer/turnstile-types/commits)

---
updated-dependencies:
- dependency-name: turnstile-types
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 15:21:38 +02:00
99a42c6fd8 website/docs: add info about our docs (#6936)
add info about our docs

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-09-19 05:22:09 -05:00
000244e387 sources/ldap: add lock to sync (#6930) 2023-09-18 21:38:01 +02:00
42c3cfa65d web/admin: user details few tooltip buttons (#6899)
* Web: Detangling some circular dependencies in Admin and User

Admin, User, and Flow should not dependend upon each other, at least
not in a circular way.  If Admin and User depend on Flow, that's
fine, but Flow should not correspondingly depend upon elements of
either; if they have something in common, let's put them in
`@goauthentik/common` or find some other smart place to store them.

This commit refactors the intentToLabel and actionToLabel functions
into `@goauthentik/common/labels` and converts them to static tables
for maintenance purposes.

* web: "Consistency is the hobgoblin of small minds" - Ralph Waldo Emerson

* web: I found these confusing to look at, so I added comments.

* web: remove admin-to-user component reference(s)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* web: remove admin from elements

This commit removes the two references from `elements` to `admin`: the list of UserEvents and a
reference to the FlowSearch type, used by the Forms manager to decide how to extract a value.
For FlowSearch, a different convention for detecting the type was implemented (instances of the
object have a unique fieldname for the value holder).  UserEvents and ObjectChangelog have been
moved to `components` as they're clearly dependent upon the API.

This defers work on removing Admin from Components, as that is (again) references going the
wrong way, but that can happen later.

* web: remove admin-to-user component reference(s) (#6856)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* This was supposed to be merged.

* web: remove `./element`⇢`./user` references

The offender here is UserDevicesList, which despite being in `elements` is only
used by the admin/user/UserViewPage.  The problem is that UserDevicesList,
despite being in `admin`, inherits from `user`, so moving it would have created
a new admin⇢user reference, and the whole point of this exercise is to get rid
of references that point "up" from the foundational pieces to the views, or
that refer to components in sibling applications.

After examining UserDevicesList, I realized that *every feature* of MFADevicesList
had been overridden: the rows, the columns, the toolbar, and the endpoint all had
custom overrides.  Nothing was left of MFADevicesList after that.   Even the
property that the web component used had been completely changed.  The only thing
they had in common was that they both inherited from `Table<Device>`.

Refactoring UserDevicesList so that it inherited directly from `Table<Device>` and
then moving it into `./admin/users` was the obvious and correct step.

Both used the same label table, so that went into the `common/labels` folder.

Along the way, I cleaned up a few minor details. Just little things, like the repeated invocation
of:

```
new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorAdminMETHODDestroy({ id: device.pk });
```

This is repeated five times, once for each Method.  By creating these:

```
        const api = new AuthenticatorsApi(DEFAULT_CONFIG);
        const id = { id: device.pk };
```

The method invocation could be just `api.authenticatorsMETHODDestroy(id)`, which is easier on the
eyes.  See the MFADevicesPage for the full example.

Similarly,

```
return [
   new TableColumn(msg("Name"), ""),
   new TableColumn(msg("Type"), ""),
   new TableColumn("")
];
   ```

is more straightforward as:

```
const headers = [msg("Name"), msg("Type"), ""];
return headers.map((th) => new TableColumn(th, ""));
```

We've labeled what we're working with, and web developers ought to know that `th` is the HTML code
for `table header`.

I've had to alter what files are scanned in pre-commit mode; it doesn't handle renamed files very well,
and at the moment a file that is renamed is not scanned, as its "new" name is not straightforwardly
displayed, not even by `git porcelain`.

* web: make the table of column headers look like a table

* web: detangle `common` from `elements`.

And just like that, `common` no longer has a reference to `elements`.   I don't mind this little bit of
code duplication if it removes a cycle.  What it does point out is that there are bits of `common` that
are predicated on the presence of the browser, and that there are bits of `elements` that, if they rely
on `common`, can't be disentangled from the application as a whole.  Which seems to me that we have two
different things going on in common: things about an application, and things about elements that are
independent of the application.

I'll think about those later.

```
$ rg 'import.*@goauthentik' ./common/ | perl -ne 'm{"(@goauthentik[^"]*)"} && print "$1\n"' | sort | cut -d '/' -f1-2 | uniq | sort
@goauthentik/api
@goauthentik/common
$
```

* web: odd bug; merge-related?  Gonna investigate.

* web: build failure thanks to local cache; fixed

* web: detangle `components` from `admin`.

This was the last inappropriate reference: something from `./components` referencing something in
`./admin`, in this case the `ak-event-info` component.  Used by both Users and Admin, moving it
into `./components` was the obvious correct step.

`ak-event-info` is a lookup table relating specific events in the event log to rich, textual
representations; in the special case of model changes and email info, even more rich content is
available in a dl/dt format. I've tableized the model changes and email info renderer, and I've
extracted every event's textual representation into its own method, converting the `switch/case`
rendering statement into a `switch/case` dispatch switch. This has the virtue of isolating each
unique case and making the dispatch switch short and coherent.

The conversion was done mechanistically; I gave the refactorer (Tide, in this case) instructions to
duplicate the switch block and then convert every case into a method with a name patterned on the
`case`. Going back to the original switch block, it was easy to duplicate the pattern matching and
convert it into a dispatch switch.

And with this, there are zero cycles in the references between the different "packageable" sections
of the UI.  The only thing left to do is figure out how to redistribute `./elements` and `./components`
in a way that makes sense for each.

* Changed function name from 'emailMessageBody' to 'githubIssueMessageBody' to better reflect its usage.

* web: added comments about length and purpose of githubIssueMessageBody.

* Update web/src/common/labels.ts

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>

* Unwanted change.

* web/add tooltip buttons to user details page

This commit wraps the command buttons on the UserDetailsPage with tooltips providing greater copy
explaining what each button does. It also ensures that every button is a minimum of 11ems in width
(The longest phrase, 'Reset Password', results in a width of 10.75ems; this makes them all
consistent.)

The technique for giving the `ak-action-button` objects a mininum width uses the CSS `::part()`
syntax, which is new. CanIUse shows that it's at 95.3% of global usage; our weak points remain Opera
Mini and UC Browser for Android.

Oh, and IE. But the various Powers That Be™ agree we're no longer tracking or caring about IE.

* I added some text, so it's my responibility to add the language files.

* fix text

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* rework

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: enforce a max-width on the container for the buttons so that they don't look funky on ultrawide monitors.

* wbe: re-ran and confirmed prettier.

---------

Signed-off-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-09-18 10:27:13 -07:00
70630aab3a website/blogs: added emm dashes (#6927)
added emm dashes

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-09-18 05:22:53 -05:00
e0328d8373 core: bump goauthentik.io/api/v3 from 3.2023083.2 to 3.2023083.3 (#6925)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.2 to 3.2023083.3.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.2...v3.2023083.3)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:07:44 +02:00
177d1614ee core: bump ruff from 0.0.289 to 0.0.290 (#6923)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.289 to 0.0.290.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.289...v0.0.290)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:07:36 +02:00
14396cb70f web: bump the babel group in /web with 2 updates (#6919)
Bumps the babel group in /web with 2 updates: [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) and [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env).


Updates `@babel/core` from 7.22.19 to 7.22.20
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.20/packages/babel-core)

Updates `@babel/preset-env` from 7.22.15 to 7.22.20
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.20/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:07:16 +02:00
db66b00494 web: bump the storybook group in /web with 5 updates (#6920)
Bumps the storybook group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `7.4.1` | `7.4.2` |
| [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `7.4.1` | `7.4.2` |
| [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) | `7.4.1` | `7.4.2` |
| [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite) | `7.4.1` | `7.4.2` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `7.4.1` | `7.4.2` |


Updates `@storybook/addon-essentials` from 7.4.1 to 7.4.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.2/code/addons/essentials)

Updates `@storybook/addon-links` from 7.4.1 to 7.4.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.2/code/addons/links)

Updates `@storybook/web-components` from 7.4.1 to 7.4.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.2/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 7.4.1 to 7.4.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.2/code/frameworks/web-components-vite)

Updates `storybook` from 7.4.1 to 7.4.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.2/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:06:57 +02:00
98648bce46 web: bump rollup from 3.29.1 to 3.29.2 in /web (#6921)
Bumps [rollup](https://github.com/rollup/rollup) from 3.29.1 to 3.29.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/v3.29.1...v3.29.2)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:06:20 +02:00
5aa11eb102 core: bump pycryptodome from 3.18.0 to 3.19.0 (#6922)
Bumps [pycryptodome](https://github.com/Legrandin/pycryptodome) from 3.18.0 to 3.19.0.
- [Release notes](https://github.com/Legrandin/pycryptodome/releases)
- [Changelog](https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst)
- [Commits](https://github.com/Legrandin/pycryptodome/compare/v3.18.0...v3.19.0)

---
updated-dependencies:
- dependency-name: pycryptodome
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:06:00 +02:00
0d68c467bd core: bump django-filter from 23.2 to 23.3 (#6924)
Bumps [django-filter](https://github.com/carltongibson/django-filter) from 23.2 to 23.3.
- [Release notes](https://github.com/carltongibson/django-filter/releases)
- [Changelog](https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst)
- [Commits](https://github.com/carltongibson/django-filter/compare/23.2...23.3)

---
updated-dependencies:
- dependency-name: django-filter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:05:38 +02:00
884425e630 core: bump github.com/go-ldap/ldap/v3 from 3.4.5 to 3.4.6 (#6926)
Bumps [github.com/go-ldap/ldap/v3](https://github.com/go-ldap/ldap) from 3.4.5 to 3.4.6.
- [Release notes](https://github.com/go-ldap/ldap/releases)
- [Commits](https://github.com/go-ldap/ldap/compare/v3.4.5...v3.4.6)

---
updated-dependencies:
- dependency-name: github.com/go-ldap/ldap/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 11:04:39 +02:00
2da6b5078c web: bump API Client version (#6918)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-09-17 22:12:43 +00:00
7649a57495 core: create app transactional api (#6446)
* initial api and schema

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* separate blueprint importer from yaml parsing

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* cleanup

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add new "must_created" state to blueprints to prevent overwriting objects

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* rework validation and error response to make it actually usable

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix lint errors

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add defaults

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* rework transaction_rollback

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use static method for string imports of subclass

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* slight cleanup

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-17 23:55:21 +02:00
583c5e3ba7 sources/ldap: add warning when a property mapping returns None or bytes (#6913)
* sources/ldap: add warning when a property mapping returns None or bytes

closes #6889

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add test

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-16 00:37:20 +02:00
01eea902ec website: replace login card with png (#6911)
* website: replace login card with png

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Optimised images with calibre/image-actions

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-09-15 18:31:46 +02:00
3d91773191 core: compile backend translations (#6912)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <authentik-automation[bot]@users.noreply.github.com>
2023-09-15 18:30:51 +02:00
de15bdcdba translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans on branch main (#6910)
Translate django.po in zh-Hans

100% translated source file: 'django.po'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-15 18:28:31 +02:00
dcef5438f1 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN on branch main (#6907)
Translate locale/en/LC_MESSAGES/django.po in zh_CN

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-15 18:28:11 +02:00
21d8089074 translate: Updates for file web/xliff/en.xlf in zh_CN on branch main (#6908)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-15 18:27:58 +02:00
af8c4b3cd0 translate: Updates for file web/xliff/en.xlf in zh-Hans on branch main (#6909)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-15 18:27:47 +02:00
1ae4ed55ae web/admin: fix webauthn label order, add raw value (#6905)
* web/admin: fix webauthn label order, add raw value

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* revert codecov to v3

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-15 13:12:38 +02:00
e070dda67f ci: bump codecov/codecov-action from 3 to 4 (#6902)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-15 11:43:42 +02:00
a4cf5c7e90 website: bump react-tooltip from 5.21.3 to 5.21.4 in /website (#6903)
Bumps [react-tooltip](https://github.com/ReactTooltip/react-tooltip) from 5.21.3 to 5.21.4.
- [Release notes](https://github.com/ReactTooltip/react-tooltip/releases)
- [Changelog](https://github.com/ReactTooltip/react-tooltip/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ReactTooltip/react-tooltip/commits)

---
updated-dependencies:
- dependency-name: react-tooltip
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-15 11:43:26 +02:00
196aa5e213 core: bump goauthentik.io/api/v3 from 3.2023083.1 to 3.2023083.2 (#6904)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.1 to 3.2023083.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.1...v3.2023083.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-15 11:42:49 +02:00
a0d2aca61c web: detangle components from applications (#6891)
* Web: Detangling some circular dependencies in Admin and User

Admin, User, and Flow should not dependend upon each other, at least
not in a circular way.  If Admin and User depend on Flow, that's
fine, but Flow should not correspondingly depend upon elements of
either; if they have something in common, let's put them in
`@goauthentik/common` or find some other smart place to store them.

This commit refactors the intentToLabel and actionToLabel functions
into `@goauthentik/common/labels` and converts them to static tables
for maintenance purposes.

* web: "Consistency is the hobgoblin of small minds" - Ralph Waldo Emerson

* web: I found these confusing to look at, so I added comments.

* web: remove admin-to-user component reference(s)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* web: remove admin from elements

This commit removes the two references from `elements` to `admin`: the list of UserEvents and a
reference to the FlowSearch type, used by the Forms manager to decide how to extract a value.
For FlowSearch, a different convention for detecting the type was implemented (instances of the
object have a unique fieldname for the value holder).  UserEvents and ObjectChangelog have been
moved to `components` as they're clearly dependent upon the API.

This defers work on removing Admin from Components, as that is (again) references going the
wrong way, but that can happen later.

* web: remove admin-to-user component reference(s) (#6856)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* This was supposed to be merged.

* web: remove `./element`⇢`./user` references

The offender here is UserDevicesList, which despite being in `elements` is only
used by the admin/user/UserViewPage.  The problem is that UserDevicesList,
despite being in `admin`, inherits from `user`, so moving it would have created
a new admin⇢user reference, and the whole point of this exercise is to get rid
of references that point "up" from the foundational pieces to the views, or
that refer to components in sibling applications.

After examining UserDevicesList, I realized that *every feature* of MFADevicesList
had been overridden: the rows, the columns, the toolbar, and the endpoint all had
custom overrides.  Nothing was left of MFADevicesList after that.   Even the
property that the web component used had been completely changed.  The only thing
they had in common was that they both inherited from `Table<Device>`.

Refactoring UserDevicesList so that it inherited directly from `Table<Device>` and
then moving it into `./admin/users` was the obvious and correct step.

Both used the same label table, so that went into the `common/labels` folder.

Along the way, I cleaned up a few minor details. Just little things, like the repeated invocation
of:

```
new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorAdminMETHODDestroy({ id: device.pk });
```

This is repeated five times, once for each Method.  By creating these:

```
        const api = new AuthenticatorsApi(DEFAULT_CONFIG);
        const id = { id: device.pk };
```

The method invocation could be just `api.authenticatorsMETHODDestroy(id)`, which is easier on the
eyes.  See the MFADevicesPage for the full example.

Similarly,

```
return [
   new TableColumn(msg("Name"), ""),
   new TableColumn(msg("Type"), ""),
   new TableColumn("")
];
   ```

is more straightforward as:

```
const headers = [msg("Name"), msg("Type"), ""];
return headers.map((th) => new TableColumn(th, ""));
```

We've labeled what we're working with, and web developers ought to know that `th` is the HTML code
for `table header`.

I've had to alter what files are scanned in pre-commit mode; it doesn't handle renamed files very well,
and at the moment a file that is renamed is not scanned, as its "new" name is not straightforwardly
displayed, not even by `git porcelain`.

* web: make the table of column headers look like a table

* web: detangle `common` from `elements`.

And just like that, `common` no longer has a reference to `elements`.   I don't mind this little bit of
code duplication if it removes a cycle.  What it does point out is that there are bits of `common` that
are predicated on the presence of the browser, and that there are bits of `elements` that, if they rely
on `common`, can't be disentangled from the application as a whole.  Which seems to me that we have two
different things going on in common: things about an application, and things about elements that are
independent of the application.

I'll think about those later.

```
$ rg 'import.*@goauthentik' ./common/ | perl -ne 'm{"(@goauthentik[^"]*)"} && print "$1\n"' | sort | cut -d '/' -f1-2 | uniq | sort
@goauthentik/api
@goauthentik/common
$
```

* web: odd bug; merge-related?  Gonna investigate.

* web: build failure thanks to local cache; fixed

* web: detangle `components` from `admin`.

This was the last inappropriate reference: something from `./components` referencing something in
`./admin`, in this case the `ak-event-info` component.  Used by both Users and Admin, moving it
into `./components` was the obvious correct step.

`ak-event-info` is a lookup table relating specific events in the event log to rich, textual
representations; in the special case of model changes and email info, even more rich content is
available in a dl/dt format. I've tableized the model changes and email info renderer, and I've
extracted every event's textual representation into its own method, converting the `switch/case`
rendering statement into a `switch/case` dispatch switch. This has the virtue of isolating each
unique case and making the dispatch switch short and coherent.

The conversion was done mechanistically; I gave the refactorer (Tide, in this case) instructions to
duplicate the switch block and then convert every case into a method with a name patterned on the
`case`. Going back to the original switch block, it was easy to duplicate the pattern matching and
convert it into a dispatch switch.

And with this, there are zero cycles in the references between the different "packageable" sections
of the UI.  The only thing left to do is figure out how to redistribute `./elements` and `./components`
in a way that makes sense for each.

* Changed function name from 'emailMessageBody' to 'githubIssueMessageBody' to better reflect its usage.

* web: added comments about length and purpose of githubIssueMessageBody.

* Update web/src/common/labels.ts

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>

* Unwanted change.

---------

Signed-off-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-09-14 14:51:42 -07:00
55dd7013b4 web: detangle common from elements (#6888)
* Web: Detangling some circular dependencies in Admin and User

Admin, User, and Flow should not dependend upon each other, at least
not in a circular way.  If Admin and User depend on Flow, that's
fine, but Flow should not correspondingly depend upon elements of
either; if they have something in common, let's put them in
`@goauthentik/common` or find some other smart place to store them.

This commit refactors the intentToLabel and actionToLabel functions
into `@goauthentik/common/labels` and converts them to static tables
for maintenance purposes.

* web: "Consistency is the hobgoblin of small minds" - Ralph Waldo Emerson

* web: I found these confusing to look at, so I added comments.

* web: remove admin-to-user component reference(s)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* web: remove admin from elements

This commit removes the two references from `elements` to `admin`: the list of UserEvents and a
reference to the FlowSearch type, used by the Forms manager to decide how to extract a value.
For FlowSearch, a different convention for detecting the type was implemented (instances of the
object have a unique fieldname for the value holder).  UserEvents and ObjectChangelog have been
moved to `components` as they're clearly dependent upon the API.

This defers work on removing Admin from Components, as that is (again) references going the
wrong way, but that can happen later.

* web: remove admin-to-user component reference(s) (#6856)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* This was supposed to be merged.

* web: remove `./element`⇢`./user` references

The offender here is UserDevicesList, which despite being in `elements` is only
used by the admin/user/UserViewPage.  The problem is that UserDevicesList,
despite being in `admin`, inherits from `user`, so moving it would have created
a new admin⇢user reference, and the whole point of this exercise is to get rid
of references that point "up" from the foundational pieces to the views, or
that refer to components in sibling applications.

After examining UserDevicesList, I realized that *every feature* of MFADevicesList
had been overridden: the rows, the columns, the toolbar, and the endpoint all had
custom overrides.  Nothing was left of MFADevicesList after that.   Even the
property that the web component used had been completely changed.  The only thing
they had in common was that they both inherited from `Table<Device>`.

Refactoring UserDevicesList so that it inherited directly from `Table<Device>` and
then moving it into `./admin/users` was the obvious and correct step.

Both used the same label table, so that went into the `common/labels` folder.

Along the way, I cleaned up a few minor details. Just little things, like the repeated invocation
of:

```
new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorAdminMETHODDestroy({ id: device.pk });
```

This is repeated five times, once for each Method.  By creating these:

```
        const api = new AuthenticatorsApi(DEFAULT_CONFIG);
        const id = { id: device.pk };
```

The method invocation could be just `api.authenticatorsMETHODDestroy(id)`, which is easier on the
eyes.  See the MFADevicesPage for the full example.

Similarly,

```
return [
   new TableColumn(msg("Name"), ""),
   new TableColumn(msg("Type"), ""),
   new TableColumn("")
];
   ```

is more straightforward as:

```
const headers = [msg("Name"), msg("Type"), ""];
return headers.map((th) => new TableColumn(th, ""));
```

We've labeled what we're working with, and web developers ought to know that `th` is the HTML code
for `table header`.

I've had to alter what files are scanned in pre-commit mode; it doesn't handle renamed files very well,
and at the moment a file that is renamed is not scanned, as its "new" name is not straightforwardly
displayed, not even by `git porcelain`.

* web: make the table of column headers look like a table

* web: detangle `common` from `elements`.

And just like that, `common` no longer has a reference to `elements`.   I don't mind this little bit of
code duplication if it removes a cycle.  What it does point out is that there are bits of `common` that
are predicated on the presence of the browser, and that there are bits of `elements` that, if they rely
on `common`, can't be disentangled from the application as a whole.  Which seems to me that we have two
different things going on in common: things about an application, and things about elements that are
independent of the application.

I'll think about those later.

```
$ rg 'import.*@goauthentik' ./common/ | perl -ne 'm{"(@goauthentik[^"]*)"} && print "$1\n"' | sort | cut -d '/' -f1-2 | uniq | sort
@goauthentik/api
@goauthentik/common
$
```

* web: odd bug; merge-related?  Gonna investigate.

* web: build failure thanks to local cache; fixed

* Unwanted change.
2023-09-14 14:14:25 -07:00
f1ce694c21 web: bump API Client version (#6898)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-09-14 20:57:16 +02:00
895c6a349c policies: specify failure result (#6887) 2023-09-14 20:38:22 +02:00
687bc3a4b4 web: bump the babel group in /web with 1 update (#6897)
Bumps the babel group in /web with 1 update: [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core).

- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.19/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-14 19:31:05 +02:00
97d57adb3b website/blogs: Blog about closed source vs open source (#6890)
* draft for closed source blog

* tweaks to intro and closing

* Optimised images with calibre/image-actions

* rebecca edits

* tweaks

* further tweaks

* table wording

* Update website/blog/2023-09-14-closed-source-does-not-equal-secure/item.md

Co-authored-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/blog/2023-09-14-closed-source-does-not-equal-secure/item.md

Co-authored-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/blog/2023-09-14-closed-source-does-not-equal-secure/item.md

Co-authored-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/blog/2023-09-14-closed-source-does-not-equal-secure/item.md

Co-authored-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/blog/2023-09-14-closed-source-does-not-equal-secure/item.md

Co-authored-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* linter wars

* final tweaks

* update title

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-14 17:28:47 +00:00
a9398c92ce web: remove ./element./user references (#6866)
* Web: Detangling some circular dependencies in Admin and User

Admin, User, and Flow should not dependend upon each other, at least
not in a circular way.  If Admin and User depend on Flow, that's
fine, but Flow should not correspondingly depend upon elements of
either; if they have something in common, let's put them in
`@goauthentik/common` or find some other smart place to store them.

This commit refactors the intentToLabel and actionToLabel functions
into `@goauthentik/common/labels` and converts them to static tables
for maintenance purposes.

* web: "Consistency is the hobgoblin of small minds" - Ralph Waldo Emerson

* web: I found these confusing to look at, so I added comments.

* web: remove admin-to-user component reference(s)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* web: remove admin from elements

This commit removes the two references from `elements` to `admin`: the list of UserEvents and a
reference to the FlowSearch type, used by the Forms manager to decide how to extract a value.
For FlowSearch, a different convention for detecting the type was implemented (instances of the
object have a unique fieldname for the value holder).  UserEvents and ObjectChangelog have been
moved to `components` as they're clearly dependent upon the API.

This defers work on removing Admin from Components, as that is (again) references going the
wrong way, but that can happen later.

* web: remove admin-to-user component reference(s) (#6856)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* This was supposed to be merged.

* web: remove `./element`⇢`./user` references

The offender here is UserDevicesList, which despite being in `elements` is only
used by the admin/user/UserViewPage.  The problem is that UserDevicesList,
despite being in `admin`, inherits from `user`, so moving it would have created
a new admin⇢user reference, and the whole point of this exercise is to get rid
of references that point "up" from the foundational pieces to the views, or
that refer to components in sibling applications.

After examining UserDevicesList, I realized that *every feature* of MFADevicesList
had been overridden: the rows, the columns, the toolbar, and the endpoint all had
custom overrides.  Nothing was left of MFADevicesList after that.   Even the
property that the web component used had been completely changed.  The only thing
they had in common was that they both inherited from `Table<Device>`.

Refactoring UserDevicesList so that it inherited directly from `Table<Device>` and
then moving it into `./admin/users` was the obvious and correct step.

Both used the same label table, so that went into the `common/labels` folder.

Along the way, I cleaned up a few minor details. Just little things, like the repeated invocation
of:

```
new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorAdminMETHODDestroy({ id: device.pk });
```

This is repeated five times, once for each Method.  By creating these:

```
        const api = new AuthenticatorsApi(DEFAULT_CONFIG);
        const id = { id: device.pk };
```

The method invocation could be just `api.authenticatorsMETHODDestroy(id)`, which is easier on the
eyes.  See the MFADevicesPage for the full example.

Similarly,

```
return [
   new TableColumn(msg("Name"), ""),
   new TableColumn(msg("Type"), ""),
   new TableColumn("")
];
   ```

is more straightforward as:

```
const headers = [msg("Name"), msg("Type"), ""];
return headers.map((th) => new TableColumn(th, ""));
```

We've labeled what we're working with, and web developers ought to know that `th` is the HTML code
for `table header`.

I've had to alter what files are scanned in pre-commit mode; it doesn't handle renamed files very well,
and at the moment a file that is renamed is not scanned, as its "new" name is not straightforwardly
displayed, not even by `git porcelain`.

* web: make the table of column headers look like a table

* web: build failure thanks to local cache; fixed

* Update web/src/common/labels.ts

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>

---------

Signed-off-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-09-14 10:15:15 -07:00
1aebfd2370 core: bump sentry-sdk from 1.30.0 to 1.31.0 (#6893)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.30.0 to 1.31.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/1.30.0...1.31.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-14 12:03:20 +02:00
8c71a78696 web: bump the esbuild group in /web with 2 updates (#6892)
Bumps the esbuild group in /web with 2 updates: [@esbuild/darwin-arm64](https://github.com/evanw/esbuild) and [@esbuild/linux-arm64](https://github.com/evanw/esbuild).


Updates `@esbuild/darwin-arm64` from 0.19.2 to 0.19.3
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.19.2...v0.19.3)

Updates `@esbuild/linux-arm64` from 0.19.2 to 0.19.3
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.19.2...v0.19.3)

---
updated-dependencies:
- dependency-name: "@esbuild/darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-14 12:03:10 +02:00
67de1fcd68 core: bump github.com/getsentry/sentry-go from 0.24.0 to 0.24.1 (#6894)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.24.0 to 0.24.1.
- [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.24.0...v0.24.1)

---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-14 12:01:49 +02:00
d35c7df789 web: detangle element to admin references (#6864)
* Web: Detangling some circular dependencies in Admin and User

Admin, User, and Flow should not dependend upon each other, at least
not in a circular way.  If Admin and User depend on Flow, that's
fine, but Flow should not correspondingly depend upon elements of
either; if they have something in common, let's put them in
`@goauthentik/common` or find some other smart place to store them.

This commit refactors the intentToLabel and actionToLabel functions
into `@goauthentik/common/labels` and converts them to static tables
for maintenance purposes.

* web: "Consistency is the hobgoblin of small minds" - Ralph Waldo Emerson

* web: I found these confusing to look at, so I added comments.

* web: remove admin-to-user component reference(s)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* web: remove admin from elements

This commit removes the two references from `elements` to `admin`: the list of UserEvents and a
reference to the FlowSearch type, used by the Forms manager to decide how to extract a value.
For FlowSearch, a different convention for detecting the type was implemented (instances of the
object have a unique fieldname for the value holder).  UserEvents and ObjectChangelog have been
moved to `components` as they're clearly dependent upon the API.

This defers work on removing Admin from Components, as that is (again) references going the
wrong way, but that can happen later.

* web: remove admin-to-user component reference(s) (#6856)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* This was supposed to be merged.
2023-09-13 12:28:42 -07:00
3f8be6e9d4 root: split codeowners (#6884)
* root: split codeowners

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add fallback

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* re-order, format

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* re-order and remove stars

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add infrastructure

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-13 19:44:51 +02:00
28702b3a25 web: Detangling some circular dependencies in Admin and User (#6852)
* Web: Detangling some circular dependencies in Admin and User

Admin, User, and Flow should not dependend upon each other, at least
not in a circular way.  If Admin and User depend on Flow, that's
fine, but Flow should not correspondingly depend upon elements of
either; if they have something in common, let's put them in
`@goauthentik/common` or find some other smart place to store them.

This commit refactors the intentToLabel and actionToLabel functions
into `@goauthentik/common/labels` and converts them to static tables
for maintenance purposes.

* web: "Consistency is the hobgoblin of small minds" - Ralph Waldo Emerson

* web: I found these confusing to look at, so I added comments.

* web: remove admin-to-user component reference(s) (#6856)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.
2023-09-13 10:16:24 -07:00
58aa7ec623 sources/ldap: fix inverted interpretation of FreeIPA nsaccountlock (#6877)
sources/ldap: fix inverted interpretation of nsaccountlock

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-13 15:43:59 +02:00
0caa17623f root: add docker recipe to Makefile
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-13 15:42:23 +02:00
e17667de79 root: include generated ts client in dev builds
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-13 15:42:23 +02:00
ac312cccbc web: bump the sentry group in /web with 2 updates (#6878)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.68.0 to 7.69.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.68.0...7.69.0)

Updates `@sentry/tracing` from 7.68.0 to 7.69.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.68.0...7.69.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 15:38:28 +02:00
b10599fa45 core: bump debugpy from 1.7.0 to 1.8.0 (#6867)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: debugpy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 14:14:25 +02:00
1dddb3dfaf web: bump @lit/localize-tools from 0.6.9 to 0.6.10 in /web (#6869)
Bumps [@lit/localize-tools](https://github.com/lit/lit/tree/HEAD/packages/localize-tools) from 0.6.9 to 0.6.10.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/localize-tools/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit/localize-tools@0.6.10/packages/localize-tools)

---
updated-dependencies:
- dependency-name: "@lit/localize-tools"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 14:14:19 +02:00
49cb7adc43 web: bump pyright from 1.1.326 to 1.1.327 in /web (#6870)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.326 to 1.1.327.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.327/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 14:14:09 +02:00
9ccbe28209 web: bump @lit-labs/context from 0.4.0 to 0.4.1 in /web (#6871)
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.0 to 0.4.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.4.1/packages/labs/context)

---
updated-dependencies:
- dependency-name: "@lit-labs/context"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 14:13:59 +02:00
4dee89db00 ci: bump docker/setup-buildx-action from 2 to 3 (#6872)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 12:24:37 +02:00
61326bbada ci: bump docker/login-action from 2 to 3 (#6874)
Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 12:17:18 +02:00
fd5d49541f ci: bump docker/build-push-action from 4 to 5 (#6875)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 12:16:12 +02:00
c80630fb6f ci: bump docker/setup-qemu-action from 2.2.0 to 3.0.0 (#6873)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2.2.0 to 3.0.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2.2.0...v3.0.0)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 12:10:39 +02:00
ec9d9f629d core: bump ruff from 0.0.288 to 0.0.289 (#6868)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.288 to 0.0.289.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.288...v0.0.289)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 12:49:30 +03:00
c79e90964a website/docs: tweak Config page (#6854)
* used tabs to add k8s info

* tweaks

* changed to mdx

* wording tweaks and rearranged sections

* removed old md file renamed to mdx

* tweak

* added a redirect to toml file

* fix references

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-12 20:30:40 +00:00
515ce94a85 root: add option to disable beat when running worker (#6849)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-12 13:26:23 +02:00
b4eb5be580 core: bump ruff from 0.0.287 to 0.0.288 (#6858) 2023-09-12 11:16:04 +02:00
0f93e283f8 core: bump goauthentik.io/api/v3 from 3.2023082.6 to 3.2023083.1 (#6859) 2023-09-12 11:15:44 +02:00
f811266ba5 root: fix gunicorn not starting
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-12 11:04:31 +02:00
4c823b7428 providers/saml: set WantAuthnRequestsSigned in metadata (#6851) 2023-09-12 09:10:06 +02:00
e494756aa5 root: fix dumb-init
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 23:33:45 +02:00
4713010034 web: bump the eslint group in /web with 1 update (#6846) 2023-09-11 23:13:11 +02:00
b0242cca2b web: bump @typescript-eslint/parser from 6.6.0 to 6.7.0 in /web (#6847) 2023-09-11 22:43:17 +02:00
f5222ef321 web: bump API Client version (#6850)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-09-11 20:20:50 +00:00
5b6fb4a05a Merge branch 'version-2023.8'
Signed-off-by: Jens Langhammer <jens@goauthentik.io>

# Conflicts:
#	Dockerfile
#	poetry.lock
#	proxy.Dockerfile
#	web/src/admin/AdminInterface.ts
#	web/xliff/zh-Hans.xlf
2023-09-11 22:04:23 +02:00
6eb33f4f6c web/admin: simplify sidebar renderer (#6797)
* Added a 'Hard-Core' lint mode to pre-commit; this will not automagically
fix all your problems, but it will show you where some deeper issues arise.

* web: streamline sidebar renderer

The sidebar renderer had a lot of repetitive code that could easily be templatized,
so I extracted the content from it and turned it into a table.

* web: complexity of the Sidebar now below 10.

This commit incorporates SonarJS into the pre-commit (and *only*
the pre-commit) linting pass; SonarJS is much more comprehensive
in its complaints, and it's helpful in breaking long functions down
to their simplest forms.

In this case, the `renderSidebarItems()` function was considered
"unreadable," and I've managed to boil it down to its three special
cases (new version, impersonation, and enterprise notification) and
its routine case (the rest of the sidebar).

Going forward, I'd like all our commits to correspond to the
SonarJS settings I've established in .eslint.precommit.json, but
I'm not gonna hate on others if they don't quite hit it.  :-)

* web: modernization continues.

Three of our four Babel plug-ins have moved from 'proposed' to 'accepted'; I have
updated package.json and the .babelrc file to accept those.

Node's ability to set its max_old_space_size via the environment variable was
enable in 2019; using it here makes it easier to move this code toward a
multi-package monorepo in the future.

* Adding 'cross-env' so that the uses of the NODE_OPTIONS environment will work (theoretically) on Windows.
2023-09-11 12:58:55 -07:00
f885f8c039 release: 2023.8.3 2023-09-11 18:55:08 +02:00
b5b33ce8e9 website/docs: prepare 2023.8.3 release notes (#6843)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 18:54:58 +02:00
7dc2bf119b website/docs: prepare 2023.8.3 release notes (#6843)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 18:54:36 +02:00
b3966a5e7c website/blogs: blog about Sourcegraph (#6814)
* sourcegraph blog

* add image

* build error

* fixed build fail

* Optimised images with calibre/image-actions

* fixed heading level

* changed reference to last week

* changed dir name to new date

* small refinements

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 16:25:35 +00:00
ec5bd550c7 core: remove celery's duplicate max_tasks_per_child (#6840)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 18:15:17 +02:00
fe02720f8d providers/scim: check that a provider exists before starting scim task (#6841)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 18:15:12 +02:00
0580f32fe6 core: remove celery's duplicate max_tasks_per_child (#6840)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 18:12:18 +02:00
74ee97b472 providers/scim: check that a provider exists before starting scim task (#6841)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 18:12:04 +02:00
7b7c80364f try to not save new things in the root directory
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 15:44:26 +02:00
c55f26ca70 group copies together
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 15:44:26 +02:00
a7a4b18082 fix ak test-all dependencies
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
61bdbf243a copy robots|security.txt from web-builder
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
a1deaf7b87 dockerignore: add .git
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
fc27e4e3d0 fix poetry install
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
ab837558c4 mount binds all around
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
fe0ecb9013 add cache everywhere, rework python deps to install with poetry and cache them
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
bf15e7b169 docker: remove pip cache
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
f75c42ea7e dockerignore: ignore all dockerfiles
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
2fdafca4eb outposts: use buildkit cache for dependencies and intermediate build artifacts
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
e507a38d43 ci: go-lint: disable cache
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
aed01e9d5b ci: docker build: enable GHA cache
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-11 15:44:26 +02:00
67bd622aa4 web/admin: fix flow-search not being able to unset (#6838)
similar to https://github.com/goauthentik/authentik/pull/6767

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 14:16:52 +02:00
5ac30c4901 web/admin: fix flow-search not being able to unset (#6838)
similar to https://github.com/goauthentik/authentik/pull/6767

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 14:14:52 +02:00
f8b690dbec website/docs: add missing word to index.mdx (#6818)
Add missing word to index.mdx

Fix missing word.

Signed-off-by: Michael Barrow <michael@barrow.me>
2023-09-11 13:37:41 +02:00
dd18f9cd30 sources/ldap: dont prefetch useless items (#6812)
sources/ldap: Fixed fetching of useless data into redis
2023-09-11 12:44:49 +02:00
d36574fc1a sources/ldap: fix task timeout for ldap_sync_all and ldap_sync_single (#6809)
* sources/ldap: fix task timeout for ldap_sync_all and ldap_sync_single

* ldap_sync_all runs tasks async so doesn't need longer timeouts

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* bump time more as we run some tasks in serial and add more leeway

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-11 12:44:40 +02:00
e45b57071a sources/ldap: dont prefetch useless items (#6812)
sources/ldap: Fixed fetching of useless data into redis
2023-09-11 12:43:10 +02:00
ed3d0c9021 core: compile backend translations (#6835)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <authentik-automation[bot]@users.noreply.github.com>
2023-09-11 12:42:19 +02:00
53e60641ba web: bump the babel group in /web with 1 update (#6826)
Bumps the babel group in /web with 1 update: [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core).

- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.17/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 12:40:46 +02:00
ab4af40b06 translate: Updates for file locale/en/LC_MESSAGES/django.po in nl on branch main (#6820)
Translate locale/en/LC_MESSAGES/django.po in nl

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'nl'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-11 12:39:15 +02:00
797792dec8 translate: Updates for file web/xliff/en.xlf in nl on branch main (#6821)
Translate web/xliff/en.xlf in nl

100% translated source file: 'web/xliff/en.xlf'
on 'nl'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-11 12:38:58 +02:00
6f37ab2c17 web: bump vite-tsconfig-paths from 4.2.0 to 4.2.1 in /web (#6829)
Bumps [vite-tsconfig-paths](https://github.com/aleclarson/vite-tsconfig-paths) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/aleclarson/vite-tsconfig-paths/releases)
- [Commits](https://github.com/aleclarson/vite-tsconfig-paths/compare/v4.2.0...v4.2.1)

---
updated-dependencies:
- dependency-name: vite-tsconfig-paths
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 12:29:47 +02:00
04befe38bc web: bump @formatjs/intl-listformat from 7.4.1 to 7.4.2 in /web (#6830)
Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 7.4.1 to 7.4.2.
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@7.4.1...@formatjs/intl-listformat@7.4.2)

---
updated-dependencies:
- dependency-name: "@formatjs/intl-listformat"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 12:28:42 +02:00
4f23dc0485 web: bump the eslint group in /web with 1 update (#6827)
Bumps the eslint group in /web with 1 update: [eslint](https://github.com/eslint/eslint).

- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.48.0...v8.49.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 12:27:37 +02:00
3d0f5ea21c ci: bump tibdex/github-app-token from 1 to 2 (#6831)
Bumps [tibdex/github-app-token](https://github.com/tibdex/github-app-token) from 1 to 2.
- [Release notes](https://github.com/tibdex/github-app-token/releases)
- [Commits](https://github.com/tibdex/github-app-token/compare/v1...v2)

---
updated-dependencies:
- dependency-name: tibdex/github-app-token
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 12:27:07 +02:00
59b7532ef6 core: bump pdoc from 14.0.0 to 14.1.0 (#6832)
Bumps [pdoc](https://github.com/mitmproxy/pdoc) from 14.0.0 to 14.1.0.
- [Changelog](https://github.com/mitmproxy/pdoc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mitmproxy/pdoc/compare/v14.0.0...v14.1.0)

---
updated-dependencies:
- dependency-name: pdoc
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 12:24:53 +02:00
1b6fd30b4c core: bump black from 23.7.0 to 23.9.1 (#6833)
Bumps [black](https://github.com/psf/black) from 23.7.0 to 23.9.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.7.0...23.9.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 12:24:35 +02:00
8507e1929c web: bump rollup from 3.29.0 to 3.29.1 in /web
Bumps [rollup](https://github.com/rollup/rollup) from 3.29.0 to 3.29.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/v3.29.0...v3.29.1)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 10:56:32 +02:00
06850a2f57 sources/ldap: fix task timeout for ldap_sync_all and ldap_sync_single (#6809)
* sources/ldap: fix task timeout for ldap_sync_all and ldap_sync_single

* ldap_sync_all runs tasks async so doesn't need longer timeouts

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* bump time more as we run some tasks in serial and add more leeway

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-08 20:37:54 +02:00
619927a7d4 core: bump gitpython from 3.1.34 to 3.1.35 (#6805)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.34 to 3.1.35.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.34...3.1.35)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-08 10:37:22 +02:00
279150541d web: bump @formatjs/intl-listformat from 7.4.0 to 7.4.1 in /web (#6801)
Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 7.4.0 to 7.4.1.
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@7.4.0...@formatjs/intl-listformat@7.4.1)

---
updated-dependencies:
- dependency-name: "@formatjs/intl-listformat"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-08 10:15:36 +02:00
09880e3412 core: bump twilio from 8.7.0 to 8.8.0 (#6802)
Bumps [twilio](https://github.com/twilio/twilio-python) from 8.7.0 to 8.8.0.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/8.7.0...8.8.0)

---
updated-dependencies:
- dependency-name: twilio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-08 10:15:24 +02:00
420b51ca1d core: bump pytest from 7.4.1 to 7.4.2 (#6803)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.1 to 7.4.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.1...7.4.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-08 10:15:05 +02:00
ad052564dd web: bump core-js from 3.32.1 to 3.32.2 in /web (#6800)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.32.1 to 3.32.2.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.32.2/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-08 10:14:51 +02:00
1edc32dad0 core: bump debugpy from 1.6.7.post1 to 1.7.0 (#6799)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.6.7.post1 to 1.7.0.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.6.7.post1...v1.7.0)

---
updated-dependencies:
- dependency-name: debugpy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-08 10:14:30 +02:00
8ef33e0285 website/dev-docs: more raw templates, fixed wget link (#6778)
* fixed broken link to raw template

* removed problematic link to concept topic

* added raw concept topic

* added raw template for reference topic

* added How to use section

* fixed url for raw

* Update website/developer-docs/docs/templates/procedural.md

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/developer-docs/docs/templates/conceptual.tmpl.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* fixed empty file

* linter issue

* nother typo

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-09-07 15:31:36 -05:00
eeb124e869 core: bump golang from 1.21.0-bookworm to 1.21.1-bookworm (#6783)
Bumps golang from 1.21.0-bookworm to 1.21.1-bookworm.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-07 12:00:34 +02:00
b5c52daa8f website: bump react-tooltip from 5.21.1 to 5.21.3 in /website (#6785)
Bumps [react-tooltip](https://github.com/ReactTooltip/react-tooltip) from 5.21.1 to 5.21.3.
- [Release notes](https://github.com/ReactTooltip/react-tooltip/releases)
- [Changelog](https://github.com/ReactTooltip/react-tooltip/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ReactTooltip/react-tooltip/compare/v5.21.1...v5.21.3)

---
updated-dependencies:
- dependency-name: react-tooltip
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-07 12:00:18 +02:00
507255524a web: bump the sentry group in /web with 2 updates (#6787)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.67.0 to 7.68.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.67.0...7.68.0)

Updates `@sentry/tracing` from 7.67.0 to 7.68.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.67.0...7.68.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-07 12:00:00 +02:00
8d71dc3ba8 core: bump coverage from 7.3.0 to 7.3.1 (#6786)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.3.0 to 7.3.1.
- [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/7.3.0...7.3.1)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-07 11:59:41 +02:00
5f02b31e64 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN on branch main (#6789)
Translate locale/en/LC_MESSAGES/django.po in zh_CN

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-07 11:58:54 +02:00
cf2f9d4c79 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans on branch main (#6790)
Translate django.po in zh-Hans

100% translated source file: 'django.po'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-07 11:58:37 +02:00
febbbca728 translate: Updates for file web/xliff/en.xlf in zh_CN on branch main (#6788)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-07 11:58:00 +02:00
b8f9fdf10a translate: Updates for file web/xliff/en.xlf in zh-Hans on branch main (#6791)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-09-07 11:57:46 +02:00
dda69f2bcc website/docs: rework user reference page (#6777)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 17:56:07 +02:00
5ea67398ae website/dev-docs: add raw markdown template (#6768)
* add raw markdown template

* changed to truly raw markdown file

* fix download link

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 08:04:35 -05:00
f2754d278f root: lock node to 20.5 (#6776)
* root: lock node to 20.5

there are apparently some breaking issues in 20.6 with babel https://github.com/babel/babel/issues/15927

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use same version of setup-node everywhere

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	.github/workflows/ci-web.yml
#	.github/workflows/ci-website.yml
2023-09-06 14:01:05 +02:00
25ac04f4e5 web/admin: fix not being able to unset certificates (#6767)
* web: fix 6742: empty web certificate request needs to return null, not undefined

This replaces the `undefined` setting of the certificate search wrapper to
`null` when the admin requests no certificate.

* only set singleton if we don't have an instance

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 14:00:32 +02:00
ae91689fd8 policies/reputation: require either check to be enabled (#6764)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 14:00:29 +02:00
aa209efa90 stages/password: fix failed_attempts_before_cancel allowing one too m… (#6763)
* stages/password: fix failed_attempts_before_cancel allowing one too many tries

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 14:00:24 +02:00
7e9e2ec53d web: don't import entire SourceViewPage in flow and user interface (#6761)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 14:00:16 +02:00
77e7c31567 core: bump django from 4.2.4 to 4.2.5 (#6751)
Bumps [django](https://github.com/django/django) from 4.2.4 to 4.2.5.
- [Commits](https://github.com/django/django/compare/4.2.4...4.2.5)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 13:59:54 +02:00
4b20409a91 sources/ldap: fix FreeIPA nsaccountlock sync (#6745)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 13:59:36 +02:00
19e04d7837 core: bump celery from 5.3.1 to 5.3.4
Bumps [celery](https://github.com/celery/celery) from 5.3.1 to 5.3.4.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.3.1...v5.3.4)

---
updated-dependencies:
- dependency-name: celery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-06 13:59:32 +02:00
352ec55729 root: fix broken celery dependency (#6744)
celery 5.3.3 was yanked so downgrade

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 13:59:28 +02:00
5333050e5d core: compile backend translations (#6739)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2023-09-06 13:59:23 +02:00
9c448d74f7 web/admin: fix application icon size (#6738)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 13:59:19 +02:00
05a4649282 web: replace ampersand (#6737)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 13:59:02 +02:00
d79ed5a152 web: bump rollup from 3.28.1 to 3.29.0 in /web (#6775)
Bumps [rollup](https://github.com/rollup/rollup) from 3.28.1 to 3.29.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/v3.28.1...v3.29.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 12:22:41 +02:00
fb35e38323 core: bump github.com/getsentry/sentry-go from 0.23.0 to 0.24.0 (#6771)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.23.0 to 0.24.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.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 12:22:32 +02:00
2c8f8b9e13 root: lock node to 20.5 (#6776)
* root: lock node to 20.5

there are apparently some breaking issues in 20.6 with babel https://github.com/babel/babel/issues/15927

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use same version of setup-node everywhere

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-06 12:22:25 +02:00
912f8da915 core: bump golang.org/x/oauth2 from 0.11.0 to 0.12.0 (#6772)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.11.0 to 0.12.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.11.0...v0.12.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 11:49:29 +02:00
8eaef887aa core: bump goauthentik.io/api/v3 from 3.2023082.2 to 3.2023082.6 (#6770)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023082.2 to 3.2023082.6.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023082.2...v3.2023082.6)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 11:45:34 +02:00
d9bdf79f0e web: bump the sentry group in /web with 2 updates (#6773)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.66.0 to 7.67.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.66.0...7.67.0)

Updates `@sentry/tracing` from 7.66.0 to 7.67.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.66.0...7.67.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 11:45:11 +02:00
44e106878b web: bump pyright from 1.1.325 to 1.1.326 in /web (#6774)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.325 to 1.1.326.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.326/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 11:44:20 +02:00
0a9880547c web/admin: fix not being able to unset certificates (#6767)
* web: fix 6742: empty web certificate request needs to return null, not undefined

This replaces the `undefined` setting of the certificate search wrapper to
`null` when the admin requests no certificate.

* only set singleton if we don't have an instance

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-05 22:37:49 +00:00
bbdf8c054b stages/password: move password validation to serializer (#6766)
* handle non-applicable when restarting flow

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* flows: add StageInvalidException error to be used in challenge/response serializer validation to return a stage_invalid error

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* rework password stage

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-05 22:55:33 +02:00
8c3f578187 policies/reputation: require either check to be enabled (#6764)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-05 22:15:14 +02:00
e373bae189 flows: remove need for post() wrapper by using dispatch (#6765)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-05 22:15:03 +02:00
7cbce1bb3d stages/password: fix failed_attempts_before_cancel allowing one too m… (#6763)
* stages/password: fix failed_attempts_before_cancel allowing one too many tries

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-05 21:58:11 +02:00
15ac26edb8 web: don't import entire SourceViewPage in flow and user interface (#6761)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-05 21:34:34 +02:00
c0676b3720 core: bump goauthentik.io/api/v3 from 3.2023082.1 to 3.2023082.2 (#6752)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023082.1 to 3.2023082.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023082.1...v3.2023082.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 12:03:18 +02:00
d437927ee5 web: bump the babel group in /web with 5 updates (#6753)
Bumps the babel group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.22.11` | `7.22.15` |
| [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) | `7.22.10` | `7.22.15` |
| [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) | `7.22.10` | `7.22.15` |
| [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) | `7.22.14` | `7.22.15` |
| [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) | `7.22.11` | `7.22.15` |


Updates `@babel/core` from 7.22.11 to 7.22.15
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.15/packages/babel-core)

Updates `@babel/plugin-proposal-decorators` from 7.22.10 to 7.22.15
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.15/packages/babel-plugin-proposal-decorators)

Updates `@babel/plugin-transform-runtime` from 7.22.10 to 7.22.15
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.15/packages/babel-plugin-transform-runtime)

Updates `@babel/preset-env` from 7.22.14 to 7.22.15
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.15/packages/babel-preset-env)

Updates `@babel/preset-typescript` from 7.22.11 to 7.22.15
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.15/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/plugin-proposal-decorators"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 12:03:01 +02:00
6a9ca493ed web: bump @types/chart.js from 2.9.37 to 2.9.38 in /web (#6756)
Bumps [@types/chart.js](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/chart.js) from 2.9.37 to 2.9.38.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/chart.js)

---
updated-dependencies:
- dependency-name: "@types/chart.js"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 12:02:52 +02:00
1a2ab34586 web: bump the eslint group in /web with 1 update (#6755)
Bumps the eslint group in /web with 1 update: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin).

- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.6.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 12:02:37 +02:00
12779ffb5f web: bump @typescript-eslint/parser from 6.5.0 to 6.6.0 in /web (#6757)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.5.0 to 6.6.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.6.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 11:23:57 +02:00
5f8e33667f web: bump @types/codemirror from 5.60.9 to 5.60.10 in /web (#6758)
Bumps [@types/codemirror](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/codemirror) from 5.60.9 to 5.60.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/codemirror)

---
updated-dependencies:
- dependency-name: "@types/codemirror"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 11:23:49 +02:00
46ae61e68b core: bump django from 4.2.4 to 4.2.5 (#6751)
Bumps [django](https://github.com/django/django) from 4.2.4 to 4.2.5.
- [Commits](https://github.com/django/django/compare/4.2.4...4.2.5)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 11:23:07 +02:00
a610d11768 ci: bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-05 07:49:46 +02:00
c5f0b89a02 website/docs: enterprise: add note about upgrading the amount of users
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-04 18:06:00 +02:00
6aeef42e5b web: bump API Client version (#6748) 2023-09-04 11:52:20 +02:00
6612f729ec stages/authenticator: vendor otp (#6741)
* initial import

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update imports

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove email and hotp for now

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove things we don't need and clean up

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* initial merge static

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* initial merge totp

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* more fixes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix migrations

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update webui

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add system migration

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* more cleanup, add doctests to test_runner

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* more cleanup

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fixup more lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* cleanup last tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update docstrings

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* implement SerializerModel

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix web format

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-04 11:45:14 +02:00
3f12c7c013 sources/ldap: fix FreeIPA nsaccountlock sync (#6745)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-04 08:44:00 +02:00
7e51d9d52f core: bump goauthentik.io/api/v3 from 3.2023081.3 to 3.2023082.1 (#6747)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023081.3 to 3.2023082.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023081.3...v3.2023082.1)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 08:43:01 +02:00
5ded88127a core: bump celery from 5.3.1 to 5.3.4
Bumps [celery](https://github.com/celery/celery) from 5.3.1 to 5.3.4.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.3.1...v5.3.4)

---
updated-dependencies:
- dependency-name: celery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 08:39:13 +02:00
7030176183 web: bump rollup-plugin-copy from 3.4.0 to 3.5.0 in /web (#6743)
Bumps [rollup-plugin-copy](https://github.com/vladshcherbin/rollup-plugin-copy) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/vladshcherbin/rollup-plugin-copy/releases)
- [Commits](https://github.com/vladshcherbin/rollup-plugin-copy/compare/3.4.0...3.5.0)

---
updated-dependencies:
- dependency-name: rollup-plugin-copy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-03 22:32:38 +02:00
12f3f8c29e root: fix broken celery dependency (#6744)
celery 5.3.3 was yanked so downgrade

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-03 22:32:23 +02:00
2b9dc4ccd8 web/admin: fix circular dependency (#6740)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-03 03:12:20 +02:00
3970c38752 core: compile backend translations (#6739)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2023-09-02 19:27:19 +02:00
db61d6200a web/admin: fix application icon size (#6738)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-02 18:59:27 +02:00
7f9e8f469d web: replace ampersand (#6737)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-02 18:59:17 +02:00
fd561ac802 root: connect to backend via socket (#6720)
* root: connect to gunicorn via socket

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* put socket in temp folder

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use non-socket connection for debug

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* don't hardcode local url

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix dev_server missing websocket

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* dedupe logging config between gunicorn and main app

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* slight refactor for proxy errors

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-02 17:58:37 +02:00
c04e83c86c web: bump API Client version (#6734) 2023-09-01 19:30:15 +02:00
97e4c8d5e2 release: 2023.8.2 2023-09-01 17:27:16 +02:00
9681ccd90f website: update subtext (#6733)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-01 16:52:13 +02:00
b63420c069 website/blog: Blog about enterprise release (#6721)
* blog about Ent release

* add image and tweaks

* removed breaking link

* typo

* minor fixes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-01 16:11:37 +02:00
3d1bf85587 website/docs: prepare 2023.8.2 release (#6731)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-01 16:09:42 +02:00
caad5a888a web: bump API Client version (#6730) 2023-09-01 13:06:20 +02:00
a39fef11b8 providers/saml: fix SAML metadata import API requiring flow slug inst… (#6729)
* providers/saml: fix SAML metadata import API requiring flow slug instead of pk

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* replace format_exc_info with dict_tracebacks, and only for json logger

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-01 12:59:25 +02:00
8f219a813b website: fix sidebar text color on smaller viewports (#6728)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-01 11:51:51 +02:00
0772756eef crypto: fix has_key filter (#6727)
* crypto: fix has_key certificate filter

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-01 11:51:41 +02:00
d485a04153 core: bump goauthentik.io/api/v3 from 3.2023081.2 to 3.2023081.3 (#6723)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023081.2 to 3.2023081.3.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023081.2...v3.2023081.3)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-01 11:26:44 +02:00
252e1e8e5d core: bump selenium from 4.11.2 to 4.12.0 (#6724)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.11.2 to 4.12.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/commits/selenium-4.12.0)

---
updated-dependencies:
- dependency-name: selenium
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-01 11:26:37 +02:00
e6a2b12686 core: bump celery from 5.3.1 to 5.3.3 (#6725)
Bumps [celery](https://github.com/celery/celery) from 5.3.1 to 5.3.3.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.3.1...v5.3.3)

---
updated-dependencies:
- dependency-name: celery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-01 11:26:29 +02:00
281 changed files with 11945 additions and 8051 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2023.8.1
current_version = 2023.8.3
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)

View File

@ -1,10 +1,11 @@
env
htmlcov
*.env.yml
**/node_modules
dist/**
build/**
build_docs/**
Dockerfile
authentik/enterprise
*Dockerfile
blueprints/local
.git
!gen-ts-api/node_modules
!gen-ts-api/dist/**

View File

@ -33,7 +33,7 @@ jobs:
- ruff
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
- name: run job
@ -41,7 +41,7 @@ jobs:
test-migrations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
- name: run migrations
@ -50,7 +50,7 @@ jobs:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup authentik env
@ -91,7 +91,7 @@ jobs:
- 12-alpine
- 15-alpine
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
with:
@ -108,7 +108,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Create k8s Kind Cluster
@ -144,7 +144,7 @@ jobs:
- name: flows
glob: tests/e2e/test_flows*
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Setup e2e env (chrome, etc)
@ -186,28 +186,31 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.2.0
uses: docker/setup-qemu-action@v3.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
- name: Login to Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: generate ts client
run: make gen-client-ts
- name: Build Docker Image
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
secrets: |
GEOIPUPDATE_ACCOUNT_ID=${{ secrets.GEOIPUPDATE_ACCOUNT_ID }}
GEOIPUPDATE_LICENSE_KEY=${{ secrets.GEOIPUPDATE_LICENSE_KEY }}
@ -220,6 +223,8 @@ jobs:
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}
VERSION=${{ steps.ev.outputs.version }}
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Comment on PR
if: github.event_name == 'pull_request'
continue-on-error: true
@ -231,28 +236,31 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.2.0
uses: docker/setup-qemu-action@v3.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
- name: Login to Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: generate ts client
run: make gen-client-ts
- name: Build Docker Image
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
secrets: |
GEOIPUPDATE_ACCOUNT_ID=${{ secrets.GEOIPUPDATE_ACCOUNT_ID }}
GEOIPUPDATE_LICENSE_KEY=${{ secrets.GEOIPUPDATE_LICENSE_KEY }}
@ -266,3 +274,5 @@ jobs:
VERSION=${{ steps.ev.outputs.version }}
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
platforms: linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@ -14,7 +14,7 @@ jobs:
lint-golint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
@ -31,14 +31,16 @@ jobs:
with:
version: v1.52.2
args: --timeout 5000s --verbose
skip-pkg-cache: true
skip-cache: true
test-unittest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Generate API
run: make gen-client-go
- name: Go unittests
@ -64,20 +66,20 @@ jobs:
- radius
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.2.0
uses: docker/setup-qemu-action@v3.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
- name: Login to Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
with:
registry: ghcr.io
@ -86,7 +88,7 @@ jobs:
- name: Generate API
run: make gen-client-go
- name: Build Docker Image
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
push: ${{ steps.ev.outputs.shouldBuild == 'true' }}
tags: |
@ -99,6 +101,8 @@ jobs:
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
platforms: linux/amd64,linux/arm64
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
build-binary:
timeout-minutes: 120
needs:
@ -114,13 +118,13 @@ jobs:
goos: [linux]
goarch: [amd64, arm64]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
- uses: actions/setup-node@v3.8.1
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"

View File

@ -14,8 +14,8 @@ jobs:
lint-eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.8.1
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
@ -30,8 +30,8 @@ jobs:
lint-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.8.1
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
@ -46,8 +46,8 @@ jobs:
lint-prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.8.1
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
@ -62,8 +62,8 @@ jobs:
lint-lit-analyse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.8.1
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
@ -94,8 +94,8 @@ jobs:
- ci-web-mark
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.8.1
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"

View File

@ -14,8 +14,8 @@ jobs:
lint-prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.8.1
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
@ -28,8 +28,8 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.8.1
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
@ -49,8 +49,8 @@ jobs:
- build
- build-docs-only
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.8.1
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"

View File

@ -23,7 +23,7 @@ jobs:
language: ["go", "javascript", "python"]
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Initialize CodeQL

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Cleanup
run: |

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: generate_token
uses: tibdex/github-app-token@v1
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}

View File

@ -29,11 +29,11 @@ jobs:
github.event.pull_request.head.repo.full_name == github.repository)
steps:
- id: generate_token
uses: tibdex/github-app-token@v1
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
token: ${{ steps.generate_token.outputs.token }}
- name: Compress images

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
- name: generate docs

View File

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
environment: internal-production
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: main
- run: |

View File

@ -8,28 +8,31 @@ jobs:
build-server:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.2.0
uses: docker/setup-qemu-action@v3.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
- name: Docker Login Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: make empty ts client
run: mkdir -p ./gen-ts-client
- name: Build Docker Image
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name == 'release' }}
secrets: |
GEOIPUPDATE_ACCOUNT_ID=${{ secrets.GEOIPUPDATE_ACCOUNT_ID }}
@ -55,30 +58,30 @@ jobs:
- ldap
- radius
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.2.0
uses: docker/setup-qemu-action@v3.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
- name: Docker Login Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker Image
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
push: ${{ github.event_name == 'release' }}
tags: |
@ -106,11 +109,11 @@ jobs:
goos: [linux, darwin]
goarch: [amd64, arm64]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
- uses: actions/setup-node@v3.8.1
- uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
@ -141,7 +144,7 @@ jobs:
- build-outpost-binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run test suite in final docker images
run: |
echo "PG_PASS=$(openssl rand -base64 32)" >> .env
@ -157,7 +160,7 @@ jobs:
- build-outpost-binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev

View File

@ -10,7 +10,7 @@ jobs:
name: Create Release from Tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Pre-release test
run: |
echo "PG_PASS=$(openssl rand -base64 32)" >> .env
@ -23,7 +23,7 @@ jobs:
docker-compose start postgresql redis
docker-compose run -u root server test-all
- id: generate_token
uses: tibdex/github-app-token@v1
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}

View File

@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: generate_token
uses: tibdex/github-app-token@v1
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}

View File

@ -16,11 +16,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: generate_token
uses: tibdex/github-app-token@v1
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
token: ${{ steps.generate_token.outputs.token }}
- name: Setup authentik env

View File

@ -12,7 +12,7 @@ jobs:
if: ${{ github.event.pull_request.user.login == 'transifex-integration[bot]'}}
steps:
- id: generate_token
uses: tibdex/github-app-token@v1
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}

View File

@ -10,14 +10,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: generate_token
uses: tibdex/github-app-token@v1
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
token: ${{ steps.generate_token.outputs.token }}
- uses: actions/setup-node@v3.8.1
- uses: actions/setup-node@v3
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"

View File

@ -1,2 +1,23 @@
* @goauthentik/core
website/docs/security/** @goauthentik/security
# Fallback
* @goauthentik/backend @goauthentik/frontend
# Backend
authentik/ @goauthentik/backend
blueprints/ @goauthentik/backend
cmd/ @goauthentik/backend
internal/ @goauthentik/backend
lifecycle/ @goauthentik/backend
schemas/ @goauthentik/backend
scripts/ @goauthentik/backend
tests/ @goauthentik/backend
# Infrastructure
.github/ @goauthentik/infrastructure
Dockerfile @goauthentik/infrastructure
*Dockerfile @goauthentik/infrastructure
.dockerignore @goauthentik/infrastructure
docker-compose.yml @goauthentik/infrastructure
# Web
web/ @goauthentik/frontend
# Docs & Website
website/ @goauthentik/docs
# Security
website/docs/security/ @goauthentik/security

View File

@ -1,53 +1,65 @@
# Stage 1: Build website
FROM --platform=${BUILDPLATFORM} docker.io/node:20 as website-builder
ENV NODE_ENV=production
WORKDIR /work/website
RUN --mount=type=bind,target=/work/website/package.json,src=./website/package.json \
--mount=type=bind,target=/work/website/package-lock.json,src=./website/package-lock.json \
--mount=type=cache,target=/root/.npm \
npm ci --include=dev
COPY ./website /work/website/
COPY ./blueprints /work/blueprints/
COPY ./SECURITY.md /work/
ENV NODE_ENV=production
WORKDIR /work/website
RUN npm ci --include=dev && npm run build-docs-only
RUN npm run build-docs-only
# Stage 2: Build webui
FROM --platform=${BUILDPLATFORM} docker.io/node:20 as web-builder
ENV NODE_ENV=production
WORKDIR /work/web
RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \
--mount=type=cache,target=/root/.npm \
npm ci --include=dev
COPY ./web /work/web/
COPY ./website /work/website/
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
ENV NODE_ENV=production
WORKDIR /work/web
RUN npm ci --include=dev && npm run build
RUN npm run build
# Stage 3: Poetry to requirements.txt export
FROM docker.io/python:3.11.5-slim-bookworm AS poetry-locker
# Stage 3: Build go proxy
FROM docker.io/golang:1.21.1-bookworm AS go-builder
WORKDIR /work
COPY ./pyproject.toml /work
COPY ./poetry.lock /work
WORKDIR /go/src/goauthentik.io
RUN pip install --no-cache-dir poetry && \
poetry export -f requirements.txt --output requirements.txt && \
poetry export -f requirements.txt --dev --output requirements-dev.txt
RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \
--mount=type=bind,target=/go/src/goauthentik.io/go.sum,src=./go.sum \
--mount=type=cache,target=/go/pkg/mod \
go mod download
# Stage 4: Build go proxy
FROM docker.io/golang:1.21.0-bookworm AS go-builder
COPY ./cmd /go/src/goauthentik.io/cmd
COPY ./authentik/lib /go/src/goauthentik.io/authentik/lib
COPY ./web/static.go /go/src/goauthentik.io/web/static.go
COPY --from=web-builder /work/web/robots.txt /go/src/goauthentik.io/web/robots.txt
COPY --from=web-builder /work/web/security.txt /go/src/goauthentik.io/web/security.txt
COPY ./internal /go/src/goauthentik.io/internal
COPY ./go.mod /go/src/goauthentik.io/go.mod
COPY ./go.sum /go/src/goauthentik.io/go.sum
WORKDIR /work
ENV CGO_ENABLED=0
COPY --from=web-builder /work/web/robots.txt /work/web/robots.txt
COPY --from=web-builder /work/web/security.txt /work/web/security.txt
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go build -o /go/authentik ./cmd/server
COPY ./cmd /work/cmd
COPY ./authentik/lib /work/authentik/lib
COPY ./web/static.go /work/web/static.go
COPY ./internal /work/internal
COPY ./go.mod /work/go.mod
COPY ./go.sum /work/go.sum
RUN go build -o /work/bin/authentik ./cmd/server/
# Stage 5: MaxMind GeoIP
# Stage 4: MaxMind GeoIP
FROM ghcr.io/maxmind/geoipupdate:v6.0 as geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City"
@ -61,6 +73,29 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
mkdir -p /usr/share/GeoIP && \
/bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 5: Python dependencies
FROM docker.io/python:3.11.5-bookworm AS python-deps
WORKDIR /ak-root/poetry
ENV VENV_PATH="/ak-root/venv" \
POETRY_VIRTUALENVS_CREATE=false \
PATH="/ak-root/venv/bin:$PATH"
RUN --mount=type=cache,target=/var/cache/apt \
apt-get update && \
# Required for installing pip packages
apt-get install -y --no-install-recommends build-essential pkg-config libxmlsec1-dev zlib1g-dev libpq-dev
RUN --mount=type=bind,target=./pyproject.toml,src=./pyproject.toml \
--mount=type=bind,target=./poetry.lock,src=./poetry.lock \
--mount=type=cache,target=/root/.cache/pip \
--mount=type=cache,target=/root/.cache/pypoetry \
python -m venv /ak-root/venv/ && \
pip3 install --upgrade pip && \
pip3 install poetry && \
poetry install --only=main --no-ansi --no-interaction
# Stage 6: Run
FROM docker.io/python:3.11.5-slim-bookworm AS final-image
@ -76,46 +111,45 @@ LABEL org.opencontainers.image.revision ${GIT_BUILD_HASH}
WORKDIR /
COPY --from=poetry-locker /work/requirements.txt /
COPY --from=poetry-locker /work/requirements-dev.txt /
COPY --from=geoip /usr/share/GeoIP /geoip
# We cannot cache this layer otherwise we'll end up with a bigger image
RUN apt-get update && \
# Required for installing pip packages
apt-get install -y --no-install-recommends build-essential pkg-config libxmlsec1-dev zlib1g-dev libpq-dev python3-dev && \
# Required for runtime
apt-get install -y --no-install-recommends libpq5 openssl libxmlsec1-openssl libmaxminddb0 && \
# Required for bootstrap & healtcheck
apt-get install -y --no-install-recommends runit && \
pip install --no-cache-dir -r /requirements.txt && \
apt-get remove --purge -y build-essential pkg-config libxmlsec1-dev libpq-dev python3-dev && \
apt-get autoremove --purge -y && \
apt-get clean && \
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/ && \
adduser --system --no-create-home --uid 1000 --group --home /authentik authentik && \
mkdir -p /certs /media /blueprints && \
mkdir -p /authentik/.ssh && \
chown authentik:authentik /certs /media /authentik/.ssh
mkdir -p /ak-root && \
chown authentik:authentik /certs /media /authentik/.ssh /ak-root
COPY ./authentik/ /authentik
COPY ./pyproject.toml /
COPY ./poetry.lock /
COPY ./schemas /schemas
COPY ./locale /locale
COPY ./tests /tests
COPY ./manage.py /
COPY ./blueprints /blueprints
COPY ./lifecycle/ /lifecycle
COPY --from=go-builder /work/bin/authentik /bin/authentik
COPY --from=go-builder /go/authentik /bin/authentik
COPY --from=python-deps /ak-root/venv /ak-root/venv
COPY --from=web-builder /work/web/dist/ /web/dist/
COPY --from=web-builder /work/web/authentik/ /web/authentik/
COPY --from=website-builder /work/website/help/ /website/help/
COPY --from=geoip /usr/share/GeoIP /geoip
USER 1000
ENV TMPDIR /dev/shm/
ENV PYTHONUNBUFFERED 1
ENV PATH "/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/lifecycle"
ENV TMPDIR=/dev/shm/ \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/ak-root/venv/bin:$PATH" \
VENV_PATH="/ak-root/venv" \
POETRY_VIRTUALENVS_CREATE=false
HEALTHCHECK --interval=30s --timeout=30s --start-period=60s --retries=3 CMD [ "/lifecycle/ak", "healthcheck" ]
ENTRYPOINT [ "/usr/local/bin/dumb-init", "--", "/lifecycle/ak" ]
ENTRYPOINT [ "dumb-init", "--", "/lifecycle/ak" ]

View File

@ -1,9 +1,16 @@
.SHELLFLAGS += -x -e
.PHONY: gen dev-reset all clean test web website
.SHELLFLAGS += ${SHELLFLAGS} -e
PWD = $(shell pwd)
UID = $(shell id -u)
GID = $(shell id -g)
NPM_VERSION = $(shell python -m scripts.npm_version)
PY_SOURCES = authentik tests scripts lifecycle
DOCKER_IMAGE ?= "authentik:test"
pg_user := $(shell python -m authentik.lib.config postgresql.user 2>/dev/null)
pg_host := $(shell python -m authentik.lib.config postgresql.host 2>/dev/null)
pg_name := $(shell python -m authentik.lib.config postgresql.name 2>/dev/null)
CODESPELL_ARGS = -D - -D .github/codespell-dictionary.txt \
-I .github/codespell-words.txt \
@ -19,57 +26,78 @@ CODESPELL_ARGS = -D - -D .github/codespell-dictionary.txt \
website/integrations \
website/src
all: lint-fix lint test gen web
all: lint-fix lint test gen web ## Lint, build, and test everything
help: ## Show this help
@echo "\nSpecify a command. The choices are:\n"
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[0;36m%-24s\033[m %s\n", $$1, $$2}' | \
sort
@echo ""
test-go:
go test -timeout 0 -v -race -cover ./...
test-docker:
test-docker: ## Run all tests in a docker-compose
echo "PG_PASS=$(openssl rand -base64 32)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env
docker-compose pull -q
docker-compose up --no-start
docker-compose start postgresql redis
docker-compose run -u root server test
docker-compose run -u root server test-all
rm -f .env
test:
test: ## Run the server tests and produce a coverage report (locally)
coverage run manage.py test --keepdb authentik
coverage html
coverage report
lint-fix:
lint-fix: ## Lint and automatically fix errors in the python source code. Reports spelling errors.
isort authentik $(PY_SOURCES)
black authentik $(PY_SOURCES)
ruff authentik $(PY_SOURCES)
codespell -w $(CODESPELL_ARGS)
lint:
lint: ## Lint the python and golang sources
pylint $(PY_SOURCES)
bandit -r $(PY_SOURCES) -x node_modules
golangci-lint run -v
migrate:
migrate: ## Run the Authentik Django server's migrations
python -m lifecycle.migrate
i18n-extract: i18n-extract-core web-i18n-extract
i18n-extract: i18n-extract-core web-i18n-extract ## Extract strings that require translation into files to send to a translation service
i18n-extract-core:
ak makemessages --ignore web --ignore internal --ignore web --ignore web-api --ignore website -l en
install: web-install website-install ## Install all requires dependencies for `web`, `website` and `core`
poetry install
dev-drop-db:
echo dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
# Also remove the test-db if it exists
dropdb -U ${pg_user} -h ${pg_host} test_${pg_name} || true
echo redis-cli -n 0 flushall
dev-create-db:
createdb -U ${pg_user} -h ${pg_host} ${pg_name}
dev-reset: dev-drop-db dev-create-db migrate ## Drop and restore the Authentik PostgreSQL instance to a "fresh install" state.
#########################
## API Schema
#########################
gen-build:
gen-build: ## Extract the schema from the database
AUTHENTIK_DEBUG=true ak make_blueprint_schema > blueprints/schema.json
AUTHENTIK_DEBUG=true ak spectacular --file schema.yml
gen-changelog:
gen-changelog: ## (Release) generate the changelog based from the commits since the last tag
git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md
npx prettier --write changelog.md
gen-diff:
gen-diff: ## (Release) generate the changelog diff between the current schema and the last tag
git show $(shell git describe --tags $(shell git rev-list --tags --max-count=1)):schema.yml > old_schema.yml
docker run \
--rm -v ${PWD}:/local \
@ -84,7 +112,7 @@ gen-clean:
rm -rf web/api/src/
rm -rf api/
gen-client-ts:
gen-client-ts: ## Build and install the authentik API for Typescript into the authentik UI Application
docker run \
--rm -v ${PWD}:/local \
--user ${UID}:${GID} \
@ -100,7 +128,7 @@ gen-client-ts:
cd gen-ts-api && npm i
\cp -rfv gen-ts-api/* web/node_modules/@goauthentik/api
gen-client-go:
gen-client-go: ## Build and install the authentik API for Golang
mkdir -p ./gen-go-api ./gen-go-api/templates
wget https://raw.githubusercontent.com/goauthentik/client-go/main/config.yaml -O ./gen-go-api/config.yaml
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/README.mustache -O ./gen-go-api/templates/README.mustache
@ -117,7 +145,7 @@ gen-client-go:
go mod edit -replace goauthentik.io/api/v3=./gen-go-api
rm -rf ./gen-go-api/config.yaml ./gen-go-api/templates/
gen-dev-config:
gen-dev-config: ## Generate a local development config file
python -m scripts.generate_config
gen: gen-build gen-clean gen-client-ts
@ -126,21 +154,21 @@ gen: gen-build gen-clean gen-client-ts
## Web
#########################
web-build: web-install
web-build: web-install ## Build the Authentik UI
cd web && npm run build
web: web-lint-fix web-lint web-check-compile
web: web-lint-fix web-lint web-check-compile web-i18n-extract ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
web-install:
web-install: ## Install the necessary libraries to build the Authentik UI
cd web && npm ci
web-watch:
web-watch: ## Build and watch the Authentik UI for changes, updating automatically
rm -rf web/dist/
mkdir web/dist/
touch web/dist/.gitkeep
cd web && npm run watch
web-storybook-watch:
web-storybook-watch: ## Build and run the storybook documentation server
cd web && npm run storybook
web-lint-fix:
@ -160,7 +188,7 @@ web-i18n-extract:
## Website
#########################
website: website-lint-fix website-build
website: website-lint-fix website-build ## Automatically fix formatting issues in the Authentik website/docs source code, lint the code, and compile it
website-install:
cd website && npm ci
@ -171,11 +199,22 @@ website-lint-fix:
website-build:
cd website && npm run build
website-watch:
website-watch: ## Build and watch the documentation website, updating automatically
cd website && npm run watch
#########################
## Docker
#########################
docker: ## Build a docker image of the current source tree
DOCKER_BUILDKIT=1 docker build . --progress plain --tag ${DOCKER_IMAGE}
#########################
## CI
#########################
# These targets are use by GitHub actions to allow usage of matrix
# which makes the YAML File a lot smaller
ci--meta-debug:
python -V
node --version
@ -203,14 +242,3 @@ ci-pyright: ci--meta-debug
ci-pending-migrations: ci--meta-debug
ak makemigrations --check
install: web-install website-install
poetry install
dev-reset:
dropdb -U postgres -h localhost authentik
# Also remove the test-db if it exists
dropdb -U postgres -h localhost test_authentik || true
createdb -U postgres -h localhost authentik
redis-cli -n 0 flushall
make migrate

View File

@ -41,15 +41,3 @@ See [SECURITY.md](SECURITY.md)
## Adoption and Contributions
Your organization uses authentik? We'd love to add your logo to the readme and our website! Email us @ hello@goauthentik.io or open a GitHub Issue/PR! For more information on how to contribute to authentik, please refer to our [CONTRIBUTING.md file](./CONTRIBUTING.md).
## Sponsors
This project is proudly sponsored by:
<p>
<a href="https://www.digitalocean.com/?utm_medium=opensource&utm_source=goauthentik.io">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="201px">
</a>
</p>
DigitalOcean provides development and testing resources for authentik.

View File

@ -2,7 +2,7 @@
from os import environ
from typing import Optional
__version__ = "2023.8.1"
__version__ = "2023.8.3"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -49,7 +49,7 @@ class BlueprintInstanceSerializer(ModelSerializer):
if content == "":
return content
context = self.instance.context if self.instance else {}
valid, logs = Importer(content, context).validate()
valid, logs = Importer.from_string(content, context).validate()
if not valid:
text_logs = "\n".join([x["event"] for x in logs])
raise ValidationError(_("Failed to validate blueprint: %(logs)s" % {"logs": text_logs}))

View File

@ -18,7 +18,7 @@ class Command(BaseCommand):
"""Apply all blueprints in order, abort when one fails to import"""
for blueprint_path in options.get("blueprints", []):
content = BlueprintInstance(path=blueprint_path).retrieve()
importer = Importer(content)
importer = Importer.from_string(content)
valid, _ = importer.validate()
if not valid:
self.stderr.write("blueprint invalid")

View File

@ -9,6 +9,7 @@ from rest_framework.fields import Field, JSONField, UUIDField
from rest_framework.serializers import Serializer
from structlog.stdlib import get_logger
from authentik.blueprints.v1.common import BlueprintEntryDesiredState
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT, is_model_allowed
from authentik.blueprints.v1.meta.registry import BaseMetaModel, registry
from authentik.lib.models import SerializerModel
@ -110,7 +111,7 @@ class Command(BaseCommand):
"id": {"type": "string"},
"state": {
"type": "string",
"enum": ["absent", "present", "created"],
"enum": [s.value for s in BlueprintEntryDesiredState],
"default": "present",
},
"conditions": {"type": "array", "items": {"type": "boolean"}},

View File

@ -20,7 +20,7 @@ def apply_blueprint(*files: str):
def wrapper(*args, **kwargs):
for file in files:
content = BlueprintInstance(path=file).retrieve()
Importer(content).apply()
Importer.from_string(content).apply()
return func(*args, **kwargs)
return wrapper

View File

@ -25,7 +25,7 @@ def blueprint_tester(file_name: Path) -> Callable:
def tester(self: TestPackaged):
base = Path("blueprints/")
rel_path = Path(file_name).relative_to(base)
importer = Importer(BlueprintInstance(path=str(rel_path)).retrieve())
importer = Importer.from_string(BlueprintInstance(path=str(rel_path)).retrieve())
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())

View File

@ -21,14 +21,14 @@ class TestBlueprintsV1(TransactionTestCase):
def test_blueprint_invalid_format(self):
"""Test blueprint with invalid format"""
importer = Importer('{"version": 3}')
importer = Importer.from_string('{"version": 3}')
self.assertFalse(importer.validate()[0])
importer = Importer(
importer = Importer.from_string(
'{"version": 1,"entries":[{"identifiers":{},"attrs":{},'
'"model": "authentik_core.User"}]}'
)
self.assertFalse(importer.validate()[0])
importer = Importer(
importer = Importer.from_string(
'{"version": 1, "entries": [{"attrs": {"name": "test"}, '
'"identifiers": {}, '
'"model": "authentik_core.Group"}]}'
@ -54,7 +54,7 @@ class TestBlueprintsV1(TransactionTestCase):
},
)
importer = Importer(
importer = Importer.from_string(
'{"version": 1, "entries": [{"attrs": {"name": "test999", "attributes": '
'{"key": ["updated_value"]}}, "identifiers": {"attributes": {"other_key": '
'["other_value"]}}, "model": "authentik_core.Group"}]}'
@ -103,7 +103,7 @@ class TestBlueprintsV1(TransactionTestCase):
self.assertEqual(len(export.entries), 3)
export_yaml = exporter.export_to_string()
importer = Importer(export_yaml)
importer = Importer.from_string(export_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
@ -113,14 +113,14 @@ class TestBlueprintsV1(TransactionTestCase):
"""Test export and import it twice"""
count_initial = Prompt.objects.filter(field_key="username").count()
importer = Importer(load_fixture("fixtures/static_prompt_export.yaml"))
importer = Importer.from_string(load_fixture("fixtures/static_prompt_export.yaml"))
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
count_before = Prompt.objects.filter(field_key="username").count()
self.assertEqual(count_initial + 1, count_before)
importer = Importer(load_fixture("fixtures/static_prompt_export.yaml"))
importer = Importer.from_string(load_fixture("fixtures/static_prompt_export.yaml"))
self.assertTrue(importer.apply())
self.assertEqual(Prompt.objects.filter(field_key="username").count(), count_before)
@ -130,7 +130,7 @@ class TestBlueprintsV1(TransactionTestCase):
ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").delete()
Group.objects.filter(name="test").delete()
environ["foo"] = generate_id()
importer = Importer(load_fixture("fixtures/tags.yaml"), {"bar": "baz"})
importer = Importer.from_string(load_fixture("fixtures/tags.yaml"), {"bar": "baz"})
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
policy = ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").first()
@ -248,7 +248,7 @@ class TestBlueprintsV1(TransactionTestCase):
exporter = FlowExporter(flow)
export_yaml = exporter.export_to_string()
importer = Importer(export_yaml)
importer = Importer.from_string(export_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
self.assertTrue(UserLoginStage.objects.filter(name=stage_name).exists())
@ -297,7 +297,7 @@ class TestBlueprintsV1(TransactionTestCase):
exporter = FlowExporter(flow)
export_yaml = exporter.export_to_string()
importer = Importer(export_yaml)
importer = Importer.from_string(export_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())

View File

@ -18,7 +18,7 @@ class TestBlueprintsV1ConditionalFields(TransactionTestCase):
self.uid = generate_id()
import_yaml = load_fixture("fixtures/conditional_fields.yaml", uid=self.uid, user=user.pk)
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())

View File

@ -18,7 +18,7 @@ class TestBlueprintsV1Conditions(TransactionTestCase):
"fixtures/conditions_fulfilled.yaml", id1=flow_slug1, id2=flow_slug2
)
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
# Ensure objects exist
@ -35,7 +35,7 @@ class TestBlueprintsV1Conditions(TransactionTestCase):
"fixtures/conditions_not_fulfilled.yaml", id1=flow_slug1, id2=flow_slug2
)
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
# Ensure objects do not exist

View File

@ -15,7 +15,7 @@ class TestBlueprintsV1State(TransactionTestCase):
flow_slug = generate_id()
import_yaml = load_fixture("fixtures/state_present.yaml", id=flow_slug)
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
# Ensure object exists
@ -30,7 +30,7 @@ class TestBlueprintsV1State(TransactionTestCase):
self.assertEqual(flow.title, "bar")
# Ensure importer updates it
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
flow: Flow = Flow.objects.filter(slug=flow_slug).first()
@ -41,7 +41,7 @@ class TestBlueprintsV1State(TransactionTestCase):
flow_slug = generate_id()
import_yaml = load_fixture("fixtures/state_created.yaml", id=flow_slug)
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
# Ensure object exists
@ -56,7 +56,7 @@ class TestBlueprintsV1State(TransactionTestCase):
self.assertEqual(flow.title, "bar")
# Ensure importer doesn't update it
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
flow: Flow = Flow.objects.filter(slug=flow_slug).first()
@ -67,7 +67,7 @@ class TestBlueprintsV1State(TransactionTestCase):
flow_slug = generate_id()
import_yaml = load_fixture("fixtures/state_created.yaml", id=flow_slug)
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
# Ensure object exists
@ -75,7 +75,7 @@ class TestBlueprintsV1State(TransactionTestCase):
self.assertEqual(flow.slug, flow_slug)
import_yaml = load_fixture("fixtures/state_absent.yaml", id=flow_slug)
importer = Importer(import_yaml)
importer = Importer.from_string(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
flow: Flow = Flow.objects.filter(slug=flow_slug).first()

View File

@ -12,6 +12,7 @@ from uuid import UUID
from deepmerge import always_merger
from django.apps import apps
from django.db.models import Model, Q
from rest_framework.exceptions import ValidationError
from rest_framework.fields import Field
from rest_framework.serializers import Serializer
from yaml import SafeDumper, SafeLoader, ScalarNode, SequenceNode
@ -52,6 +53,7 @@ class BlueprintEntryDesiredState(Enum):
ABSENT = "absent"
PRESENT = "present"
CREATED = "created"
MUST_CREATED = "must_created"
@dataclass
@ -206,8 +208,8 @@ class KeyOf(YAMLTag):
):
return _entry._state.instance.pbm_uuid
return _entry._state.instance.pk
raise EntryInvalidError(
f"KeyOf: failed to find entry with `id` of `{self.id_from}` and a model instance"
raise EntryInvalidError.from_entry(
f"KeyOf: failed to find entry with `id` of `{self.id_from}` and a model instance", entry
)
@ -278,7 +280,7 @@ class Format(YAMLTag):
try:
return self.format_string % tuple(args)
except TypeError as exc:
raise EntryInvalidError(exc)
raise EntryInvalidError.from_entry(exc, entry)
class Find(YAMLTag):
@ -355,13 +357,15 @@ class Condition(YAMLTag):
args.append(arg)
if not args:
raise EntryInvalidError("At least one value is required after mode selection.")
raise EntryInvalidError.from_entry(
"At least one value is required after mode selection.", entry
)
try:
comparator = self._COMPARATORS[self.mode.upper()]
return comparator(tuple(bool(x) for x in args))
except (TypeError, KeyError) as exc:
raise EntryInvalidError(exc)
raise EntryInvalidError.from_entry(exc, entry)
class If(YAMLTag):
@ -393,7 +397,7 @@ class If(YAMLTag):
blueprint,
)
except TypeError as exc:
raise EntryInvalidError(exc)
raise EntryInvalidError.from_entry(exc, entry)
class Enumerate(YAMLTag, YAMLTagContext):
@ -425,9 +429,10 @@ class Enumerate(YAMLTag, YAMLTagContext):
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
if isinstance(self.iterable, EnumeratedItem) and self.iterable.depth == 0:
raise EntryInvalidError(
raise EntryInvalidError.from_entry(
f"{self.__class__.__name__} tag's iterable references this tag's context. "
"This is a noop. Check you are setting depth bigger than 0."
"This is a noop. Check you are setting depth bigger than 0.",
entry,
)
if isinstance(self.iterable, YAMLTag):
@ -436,9 +441,10 @@ class Enumerate(YAMLTag, YAMLTagContext):
iterable = self.iterable
if not isinstance(iterable, Iterable):
raise EntryInvalidError(
raise EntryInvalidError.from_entry(
f"{self.__class__.__name__}'s iterable must be an iterable "
"such as a sequence or a mapping"
"such as a sequence or a mapping",
entry,
)
if isinstance(iterable, Mapping):
@ -449,7 +455,7 @@ class Enumerate(YAMLTag, YAMLTagContext):
try:
output_class, add_fn = self._OUTPUT_BODIES[self.output_body.upper()]
except KeyError as exc:
raise EntryInvalidError(exc)
raise EntryInvalidError.from_entry(exc, entry)
result = output_class()
@ -461,8 +467,8 @@ class Enumerate(YAMLTag, YAMLTagContext):
resolved_body = entry.tag_resolver(self.item_body, blueprint)
result = add_fn(result, resolved_body)
if not isinstance(result, output_class):
raise EntryInvalidError(
f"Invalid {self.__class__.__name__} item found: {resolved_body}"
raise EntryInvalidError.from_entry(
f"Invalid {self.__class__.__name__} item found: {resolved_body}", entry
)
finally:
self.__current_context = tuple()
@ -489,12 +495,13 @@ class EnumeratedItem(YAMLTag):
)
except ValueError as exc:
if self.depth == 0:
raise EntryInvalidError(
raise EntryInvalidError.from_entry(
f"{self.__class__.__name__} tags are only usable "
f"inside an {Enumerate.__name__} tag"
f"inside an {Enumerate.__name__} tag",
entry,
)
raise EntryInvalidError(f"{self.__class__.__name__} tag: {exc}")
raise EntryInvalidError.from_entry(f"{self.__class__.__name__} tag: {exc}", entry)
return context_tag.get_context(entry, blueprint)
@ -508,7 +515,7 @@ class Index(EnumeratedItem):
try:
return context[0]
except IndexError: # pragma: no cover
raise EntryInvalidError(f"Empty/invalid context: {context}")
raise EntryInvalidError.from_entry(f"Empty/invalid context: {context}", entry)
class Value(EnumeratedItem):
@ -520,7 +527,7 @@ class Value(EnumeratedItem):
try:
return context[1]
except IndexError: # pragma: no cover
raise EntryInvalidError(f"Empty/invalid context: {context}")
raise EntryInvalidError.from_entry(f"Empty/invalid context: {context}", entry)
class BlueprintDumper(SafeDumper):
@ -574,8 +581,26 @@ class BlueprintLoader(SafeLoader):
class EntryInvalidError(SentryIgnoredException):
"""Error raised when an entry is invalid"""
serializer_errors: Optional[dict]
entry_model: Optional[str]
entry_id: Optional[str]
validation_error: Optional[ValidationError]
def __init__(self, *args: object, serializer_errors: Optional[dict] = None) -> None:
def __init__(self, *args: object, validation_error: Optional[ValidationError] = None) -> None:
super().__init__(*args)
self.serializer_errors = serializer_errors
self.entry_model = None
self.entry_id = None
self.validation_error = validation_error
@staticmethod
def from_entry(
msg_or_exc: str | Exception, entry: BlueprintEntry, *args, **kwargs
) -> "EntryInvalidError":
"""Create EntryInvalidError with the context of an entry"""
error = EntryInvalidError(msg_or_exc, *args, **kwargs)
if isinstance(msg_or_exc, ValidationError):
error.validation_error = msg_or_exc
# Make sure the model and id are strings, depending where the error happens
# they might still be YAMLTag instances
error.entry_model = str(entry.model)
error.entry_id = str(entry.id)
return error

View File

@ -8,9 +8,9 @@ from dacite.core import from_dict
from dacite.exceptions import DaciteError
from deepmerge import always_merger
from django.core.exceptions import FieldError
from django.db import transaction
from django.db.models import Model
from django.db.models.query_utils import Q
from django.db.transaction import atomic
from django.db.utils import IntegrityError
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import BaseSerializer, Serializer
@ -38,6 +38,7 @@ from authentik.core.models import (
from authentik.events.utils import cleanse_dict
from authentik.flows.models import FlowToken, Stage
from authentik.lib.models import SerializerModel
from authentik.lib.sentry import SentryIgnoredException
from authentik.outposts.models import OutpostServiceConnection
from authentik.policies.models import Policy, PolicyBindingModel
@ -72,41 +73,53 @@ def is_model_allowed(model: type[Model]) -> bool:
return model not in excluded_models and issubclass(model, (SerializerModel, BaseMetaModel))
class DoRollback(SentryIgnoredException):
"""Exception to trigger a rollback"""
@contextmanager
def transaction_rollback():
"""Enters an atomic transaction and always triggers a rollback at the end of the block."""
atomic = transaction.atomic()
# pylint: disable=unnecessary-dunder-call
atomic.__enter__()
yield
atomic.__exit__(IntegrityError, None, None)
try:
with atomic():
yield
raise DoRollback()
except DoRollback:
pass
class Importer:
"""Import Blueprint from YAML"""
"""Import Blueprint from raw dict or YAML/JSON"""
logger: BoundLogger
_import: Blueprint
def __init__(self, yaml_input: str, context: Optional[dict] = None):
def __init__(self, blueprint: Blueprint, context: Optional[dict] = None):
self.__pk_map: dict[Any, Model] = {}
self._import = blueprint
self.logger = get_logger()
ctx = {}
always_merger.merge(ctx, self._import.context)
if context:
always_merger.merge(ctx, context)
self._import.context = ctx
@staticmethod
def from_string(yaml_input: str, context: dict | None = None) -> "Importer":
"""Parse YAML string and create blueprint importer from it"""
import_dict = load(yaml_input, BlueprintLoader)
try:
self.__import = from_dict(
_import = from_dict(
Blueprint, import_dict, config=Config(cast=[BlueprintEntryDesiredState])
)
except DaciteError as exc:
raise EntryInvalidError from exc
ctx = {}
always_merger.merge(ctx, self.__import.context)
if context:
always_merger.merge(ctx, context)
self.__import.context = ctx
return Importer(_import, context)
@property
def blueprint(self) -> Blueprint:
"""Get imported blueprint"""
return self.__import
return self._import
def __update_pks_for_attrs(self, attrs: dict[str, Any]) -> dict[str, Any]:
"""Replace any value if it is a known primary key of an other object"""
@ -152,19 +165,19 @@ class Importer:
# pylint: disable-msg=too-many-locals
def _validate_single(self, entry: BlueprintEntry) -> Optional[BaseSerializer]:
"""Validate a single entry"""
if not entry.check_all_conditions_match(self.__import):
if not entry.check_all_conditions_match(self._import):
self.logger.debug("One or more conditions of this entry are not fulfilled, skipping")
return None
model_app_label, model_name = entry.get_model(self.__import).split(".")
model_app_label, model_name = entry.get_model(self._import).split(".")
model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
# Don't use isinstance since we don't want to check for inheritance
if not is_model_allowed(model):
raise EntryInvalidError(f"Model {model} not allowed")
raise EntryInvalidError.from_entry(f"Model {model} not allowed", entry)
if issubclass(model, BaseMetaModel):
serializer_class: type[Serializer] = model.serializer()
serializer = serializer_class(
data=entry.get_attrs(self.__import),
data=entry.get_attrs(self._import),
context={
SERIALIZER_CONTEXT_BLUEPRINT: entry,
},
@ -172,8 +185,10 @@ class Importer:
try:
serializer.is_valid(raise_exception=True)
except ValidationError as exc:
raise EntryInvalidError(
f"Serializer errors {serializer.errors}", serializer_errors=serializer.errors
raise EntryInvalidError.from_entry(
f"Serializer errors {serializer.errors}",
validation_error=exc,
entry=entry,
) from exc
return serializer
@ -182,7 +197,7 @@ class Importer:
# the full serializer for later usage
# Because a model might have multiple unique columns, we chain all identifiers together
# to create an OR query.
updated_identifiers = self.__update_pks_for_attrs(entry.get_identifiers(self.__import))
updated_identifiers = self.__update_pks_for_attrs(entry.get_identifiers(self._import))
for key, value in list(updated_identifiers.items()):
if isinstance(value, dict) and "pk" in value:
del updated_identifiers[key]
@ -190,12 +205,12 @@ class Importer:
query = self.__query_from_identifier(updated_identifiers)
if not query:
raise EntryInvalidError("No or invalid identifiers")
raise EntryInvalidError.from_entry("No or invalid identifiers", entry)
try:
existing_models = model.objects.filter(query)
except FieldError as exc:
raise EntryInvalidError(f"Invalid identifier field: {exc}") from exc
raise EntryInvalidError.from_entry(f"Invalid identifier field: {exc}", entry) from exc
serializer_kwargs = {}
model_instance = existing_models.first()
@ -208,6 +223,14 @@ class Importer:
)
serializer_kwargs["instance"] = model_instance
serializer_kwargs["partial"] = True
elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
raise EntryInvalidError.from_entry(
(
f"state is set to {BlueprintEntryDesiredState.MUST_CREATED} "
"and object exists already",
),
entry,
)
else:
self.logger.debug(
"initialised new serializer instance",
@ -220,9 +243,9 @@ class Importer:
model_instance.pk = updated_identifiers["pk"]
serializer_kwargs["instance"] = model_instance
try:
full_data = self.__update_pks_for_attrs(entry.get_attrs(self.__import))
full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
except ValueError as exc:
raise EntryInvalidError(exc) from exc
raise EntryInvalidError.from_entry(exc, entry) from exc
always_merger.merge(full_data, updated_identifiers)
serializer_kwargs["data"] = full_data
@ -235,15 +258,17 @@ class Importer:
try:
serializer.is_valid(raise_exception=True)
except ValidationError as exc:
raise EntryInvalidError(
f"Serializer errors {serializer.errors}", serializer_errors=serializer.errors
raise EntryInvalidError.from_entry(
f"Serializer errors {serializer.errors}",
validation_error=exc,
entry=entry,
) from exc
return serializer
def apply(self) -> bool:
"""Apply (create/update) models yaml, in database transaction"""
try:
with transaction.atomic():
with atomic():
if not self._apply_models():
self.logger.debug("Reverting changes due to error")
raise IntegrityError
@ -252,11 +277,11 @@ class Importer:
self.logger.debug("Committing changes")
return True
def _apply_models(self) -> bool:
def _apply_models(self, raise_errors=False) -> bool:
"""Apply (create/update) models yaml"""
self.__pk_map = {}
for entry in self.__import.entries:
model_app_label, model_name = entry.get_model(self.__import).split(".")
for entry in self._import.entries:
model_app_label, model_name = entry.get_model(self._import).split(".")
try:
model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
except LookupError:
@ -269,15 +294,21 @@ class Importer:
serializer = self._validate_single(entry)
except EntryInvalidError as exc:
# For deleting objects we don't need the serializer to be valid
if entry.get_state(self.__import) == BlueprintEntryDesiredState.ABSENT:
if entry.get_state(self._import) == BlueprintEntryDesiredState.ABSENT:
continue
self.logger.warning(f"entry invalid: {exc}", entry=entry, error=exc)
if raise_errors:
raise exc
return False
if not serializer:
continue
state = entry.get_state(self.__import)
if state in [BlueprintEntryDesiredState.PRESENT, BlueprintEntryDesiredState.CREATED]:
state = entry.get_state(self._import)
if state in [
BlueprintEntryDesiredState.PRESENT,
BlueprintEntryDesiredState.CREATED,
BlueprintEntryDesiredState.MUST_CREATED,
]:
instance = serializer.instance
if (
instance
@ -305,23 +336,23 @@ class Importer:
self.logger.debug("entry to delete with no instance, skipping")
return True
def validate(self) -> tuple[bool, list[EventDict]]:
def validate(self, raise_validation_errors=False) -> tuple[bool, list[EventDict]]:
"""Validate loaded blueprint export, ensure all models are allowed
and serializers have no errors"""
self.logger.debug("Starting blueprint import validation")
orig_import = deepcopy(self.__import)
if self.__import.version != 1:
orig_import = deepcopy(self._import)
if self._import.version != 1:
self.logger.warning("Invalid blueprint version")
return False, [{"event": "Invalid blueprint version"}]
with (
transaction_rollback(),
capture_logs() as logs,
):
successful = self._apply_models()
successful = self._apply_models(raise_errors=raise_validation_errors)
if not successful:
self.logger.debug("Blueprint validation failed")
for log in logs:
getattr(self.logger, log.get("log_level"))(**log)
self.logger.debug("Finished blueprint import validation")
self.__import = orig_import
self._import = orig_import
return successful, logs

View File

@ -190,7 +190,7 @@ def apply_blueprint(self: MonitoredTask, instance_pk: str):
self.set_uid(slugify(instance.name))
blueprint_content = instance.retrieve()
file_hash = sha512(blueprint_content.encode()).hexdigest()
importer = Importer(blueprint_content, instance.context)
importer = Importer.from_string(blueprint_content, instance.context)
if importer.blueprint.metadata:
instance.metadata = asdict(importer.blueprint.metadata)
valid, logs = importer.validate()

View File

@ -1,6 +1,4 @@
"""Authenticator Devices API Views"""
from django_otp import device_classes, devices_for_user
from django_otp.models import Device
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework.fields import BooleanField, CharField, IntegerField, SerializerMethodField
@ -10,6 +8,8 @@ from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from authentik.core.api.utils import MetaNameSerializer
from authentik.stages.authenticator import device_classes, devices_for_user
from authentik.stages.authenticator.models import Device
class DeviceSerializer(MetaNameSerializer):

View File

@ -0,0 +1,139 @@
"""transactional application and provider creation"""
from django.apps import apps
from drf_spectacular.utils import PolymorphicProxySerializer, extend_schema, extend_schema_field
from rest_framework.exceptions import ValidationError
from rest_framework.fields import BooleanField, CharField, ChoiceField, DictField, ListField
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from yaml import ScalarNode
from authentik.blueprints.v1.common import (
Blueprint,
BlueprintEntry,
BlueprintEntryDesiredState,
EntryInvalidError,
KeyOf,
)
from authentik.blueprints.v1.importer import Importer
from authentik.core.api.applications import ApplicationSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import Provider
from authentik.lib.utils.reflection import all_subclasses
def get_provider_serializer_mapping():
"""Get a mapping of all providers' model names and their serializers"""
mapping = {}
for model in all_subclasses(Provider):
if model._meta.abstract:
continue
mapping[f"{model._meta.app_label}.{model._meta.model_name}"] = model().serializer
return mapping
@extend_schema_field(
PolymorphicProxySerializer(
component_name="model",
serializers=get_provider_serializer_mapping,
resource_type_field_name="provider_model",
)
)
class TransactionProviderField(DictField):
"""Dictionary field which can hold provider creation data"""
class TransactionApplicationSerializer(PassiveSerializer):
"""Serializer for creating a provider and an application in one transaction"""
app = ApplicationSerializer()
provider_model = ChoiceField(choices=list(get_provider_serializer_mapping().keys()))
provider = TransactionProviderField()
_provider_model: type[Provider] = None
def validate_provider_model(self, fq_model_name: str) -> str:
"""Validate that the model exists and is a provider"""
if "." not in fq_model_name:
raise ValidationError("Invalid provider model")
try:
app, _, model_name = fq_model_name.partition(".")
model = apps.get_model(app, model_name)
if not issubclass(model, Provider):
raise ValidationError("Invalid provider model")
self._provider_model = model
except LookupError:
raise ValidationError("Invalid provider model")
return fq_model_name
def validate(self, attrs: dict) -> dict:
blueprint = Blueprint()
blueprint.entries.append(
BlueprintEntry(
model=attrs["provider_model"],
state=BlueprintEntryDesiredState.MUST_CREATED,
identifiers={
"name": attrs["provider"]["name"],
},
# Must match the name of the field on `self`
id="provider",
attrs=attrs["provider"],
)
)
app_data = attrs["app"]
app_data["provider"] = KeyOf(None, ScalarNode(tag="", value="provider"))
blueprint.entries.append(
BlueprintEntry(
model="authentik_core.application",
state=BlueprintEntryDesiredState.MUST_CREATED,
identifiers={
"slug": attrs["app"]["slug"],
},
attrs=app_data,
# Must match the name of the field on `self`
id="app",
)
)
importer = Importer(blueprint, {})
try:
valid, _ = importer.validate(raise_validation_errors=True)
if not valid:
raise ValidationError("Invalid blueprint")
except EntryInvalidError as exc:
raise ValidationError(
{
exc.entry_id: exc.validation_error.detail,
}
)
return blueprint
class TransactionApplicationResponseSerializer(PassiveSerializer):
"""Transactional creation response"""
applied = BooleanField()
logs = ListField(child=CharField())
class TransactionalApplicationView(APIView):
"""Create provider and application and attach them in a single transaction"""
permission_classes = [IsAdminUser]
@extend_schema(
request=TransactionApplicationSerializer(),
responses={
200: TransactionApplicationResponseSerializer(),
},
)
def put(self, request: Request) -> Response:
"""Convert data into a blueprint, validate it and apply it"""
data = TransactionApplicationSerializer(data=request.data)
data.is_valid(raise_exception=True)
importer = Importer(data.validated_data, {})
applied = importer.apply()
response = {"applied": False, "logs": []}
response["applied"] = applied
return Response(response, status=200)

View File

@ -616,8 +616,10 @@ class UserViewSet(UsedByMixin, ModelViewSet):
if not request.user.has_perm("impersonate"):
LOGGER.debug("User attempted to impersonate without permissions", user=request.user)
return Response(status=401)
user_to_be = self.get_object()
if user_to_be.pk == self.request.user.pk:
LOGGER.debug("User attempted to impersonate themselves", user=request.user)
return Response(status=401)
request.session[SESSION_KEY_IMPERSONATE_ORIGINAL_USER] = request.user
request.session[SESSION_KEY_IMPERSONATE_USER] = user_to_be

View File

@ -0,0 +1,9 @@
"""custom runserver command"""
from daphne.management.commands.runserver import Command as RunServer
class Command(RunServer):
"""custom runserver command, which doesn't show the misleading django startup message"""
def on_bind(self, server_port):
pass

View File

@ -16,6 +16,9 @@ LOGGER = get_logger()
class Command(BaseCommand):
"""Run worker"""
def add_arguments(self, parser):
parser.add_argument("-b", "--beat", action="store_true")
def handle(self, **options):
close_old_connections()
if CONFIG.get_bool("remote_debug"):
@ -26,10 +29,9 @@ class Command(BaseCommand):
no_color=False,
quiet=True,
optimization="fair",
max_tasks_per_child=1,
autoscale=(3, 1),
autoscale=(CONFIG.get_int("worker.concurrency"), 1),
task_events=True,
beat=True,
beat=options.get("beat", True),
schedule_filename=f"{tempdir}/celerybeat-schedule",
queues=["authentik", "authentik_scheduled", "authentik_events"],
)

View File

@ -0,0 +1,41 @@
# Generated by Django 4.2.5 on 2023-09-27 10:44
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0031_alter_user_type"),
]
operations = [
migrations.CreateModel(
name="GroupSourceConnection",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("created", models.DateTimeField(auto_now_add=True)),
("last_updated", models.DateTimeField(auto_now=True)),
(
"group",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="authentik_core.group"
),
),
(
"source",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="authentik_core.source"
),
),
],
options={
"unique_together": {("group", "source")},
},
),
]

View File

@ -575,6 +575,23 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel):
unique_together = (("user", "source"),)
class GroupSourceConnection(SerializerModel, CreatedUpdatedModel):
"""Connection between Group and Source."""
group = models.ForeignKey(Group, on_delete=models.CASCADE)
source = models.ForeignKey(Source, on_delete=models.CASCADE)
objects = InheritanceManager()
@property
def serializer(self) -> type[Serializer]:
"""Get serializer for this model"""
raise NotImplementedError
class Meta:
unique_together = (("group", "source"),)
class ExpiringModel(models.Model):
"""Base Model which can expire, and is automatically cleaned up."""

View File

@ -48,7 +48,7 @@ class Action(Enum):
class MessageStage(StageView):
"""Show a pre-configured message after the flow is done"""
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Show a pre-configured message after the flow is done"""
message = getattr(self.executor.current_stage, "message", "")
level = getattr(self.executor.current_stage, "level", messages.SUCCESS)
@ -59,10 +59,6 @@ class MessageStage(StageView):
)
return self.executor.stage_ok()
def post(self, request: HttpRequest) -> HttpResponse:
"""Wrapper for post requests"""
return self.get(request)
class SourceFlowManager:
"""Help sources decide what they should do after authorization. Based on source settings and

View File

@ -13,7 +13,7 @@ class PostUserEnrollmentStage(StageView):
"""Dynamically injected stage which saves the Connection after
the user has been enrolled."""
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
def dispatch(self, request: HttpRequest) -> HttpResponse:
"""Stage used after the user has been enrolled"""
connection: UserSourceConnection = self.executor.plan.context[
PLAN_CONTEXT_SOURCES_CONNECTION
@ -27,7 +27,3 @@ class PostUserEnrollmentStage(StageView):
source=connection.source,
).from_http(self.request)
return self.executor.stage_ok()
def post(self, request: HttpRequest) -> HttpResponse:
"""Wrapper for post requests"""
return self.get(request)

View File

@ -6,6 +6,7 @@ from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.config import CONFIG
class TestImpersonation(APITestCase):
@ -46,12 +47,42 @@ class TestImpersonation(APITestCase):
"""test impersonation without permissions"""
self.client.force_login(self.other_user)
self.client.get(reverse("authentik_api:user-impersonate", kwargs={"pk": self.user.pk}))
response = self.client.post(
reverse("authentik_api:user-impersonate", kwargs={"pk": self.user.pk})
)
self.assertEqual(response.status_code, 403)
response = self.client.get(reverse("authentik_api:user-me"))
response_body = loads(response.content.decode())
self.assertEqual(response_body["user"]["username"], self.other_user.username)
@CONFIG.patch("impersonation", False)
def test_impersonate_disabled(self):
"""test impersonation that is disabled"""
self.client.force_login(self.user)
response = self.client.post(
reverse("authentik_api:user-impersonate", kwargs={"pk": self.other_user.pk})
)
self.assertEqual(response.status_code, 401)
response = self.client.get(reverse("authentik_api:user-me"))
response_body = loads(response.content.decode())
self.assertEqual(response_body["user"]["username"], self.user.username)
def test_impersonate_self(self):
"""test impersonation that user can't impersonate themselves"""
self.client.force_login(self.user)
response = self.client.post(
reverse("authentik_api:user-impersonate", kwargs={"pk": self.user.pk})
)
self.assertEqual(response.status_code, 401)
response = self.client.get(reverse("authentik_api:user-me"))
response_body = loads(response.content.decode())
self.assertEqual(response_body["user"]["username"], self.user.username)
def test_un_impersonate_empty(self):
"""test un-impersonation without impersonating first"""
self.client.force_login(self.other_user)

View File

@ -0,0 +1,64 @@
"""Test Transactional API"""
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.models import OAuth2Provider
class TestTransactionalApplicationsAPI(APITestCase):
"""Test Transactional API"""
def setUp(self) -> None:
self.user = create_test_admin_user()
def test_create_transactional(self):
"""Test transactional Application + provider creation"""
self.client.force_login(self.user)
uid = generate_id()
authorization_flow = create_test_flow()
response = self.client.put(
reverse("authentik_api:core-transactional-application"),
data={
"app": {
"name": uid,
"slug": uid,
},
"provider_model": "authentik_providers_oauth2.oauth2provider",
"provider": {
"name": uid,
"authorization_flow": str(authorization_flow.pk),
},
},
)
self.assertJSONEqual(response.content.decode(), {"applied": True, "logs": []})
provider = OAuth2Provider.objects.filter(name=uid).first()
self.assertIsNotNone(provider)
app = Application.objects.filter(slug=uid).first()
self.assertIsNotNone(app)
self.assertEqual(app.provider.pk, provider.pk)
def test_create_transactional_invalid(self):
"""Test transactional Application + provider creation"""
self.client.force_login(self.user)
uid = generate_id()
response = self.client.put(
reverse("authentik_api:core-transactional-application"),
data={
"app": {
"name": uid,
"slug": uid,
},
"provider_model": "authentik_providers_oauth2.oauth2provider",
"provider": {
"name": uid,
"authorization_flow": "",
},
},
)
self.assertJSONEqual(
response.content.decode(),
{"provider": {"authorization_flow": ["This field may not be null."]}},
)

View File

@ -25,10 +25,10 @@ def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User:
"""Generate a test-admin user"""
uid = generate_id(20) if not name else name
group = Group.objects.create(name=uid, is_superuser=True)
kwargs.setdefault("email", f"{uid}@goauthentik.io")
kwargs.setdefault("username", uid)
user: User = User.objects.create(
username=uid,
name=uid,
email=f"{uid}@goauthentik.io",
**kwargs,
)
user.set_password(uid)

View File

@ -15,6 +15,7 @@ from authentik.core.api.propertymappings import PropertyMappingViewSet
from authentik.core.api.providers import ProviderViewSet
from authentik.core.api.sources import SourceViewSet, UserSourceConnectionViewSet
from authentik.core.api.tokens import TokenViewSet
from authentik.core.api.transactional_applications import TransactionalApplicationView
from authentik.core.api.users import UserViewSet
from authentik.core.views import apps
from authentik.core.views.debug import AccessDeniedView
@ -70,6 +71,11 @@ urlpatterns = [
api_urlpatterns = [
("core/authenticated_sessions", AuthenticatedSessionViewSet),
("core/applications", ApplicationViewSet),
path(
"core/transactional/applications/",
TransactionalApplicationView.as_view(),
name="core-transactional-application",
),
("core/groups", GroupViewSet),
("core/users", UserViewSet),
("core/tokens", TokenViewSet),

View File

@ -189,6 +189,8 @@ class CertificateKeyPairFilter(FilterSet):
def filter_has_key(self, queryset, name, value): # pragma: no cover
"""Only return certificate-key pairs with keys"""
if not value:
return queryset
return queryset.exclude(key_data__exact="")
class Meta:

View File

@ -128,8 +128,26 @@ class TestCrypto(APITestCase):
response = self.client.get(
reverse(
"authentik_api:certificatekeypair-list",
)
+ f"?name={cert.name}"
),
data={"name": cert.name},
)
self.assertEqual(200, response.status_code)
body = loads(response.content.decode())
api_cert = [x for x in body["results"] if x["name"] == cert.name][0]
self.assertEqual(api_cert["fingerprint_sha1"], cert.fingerprint_sha1)
self.assertEqual(api_cert["fingerprint_sha256"], cert.fingerprint_sha256)
def test_list_has_key_false(self):
"""Test API List with has_key set to false"""
cert = create_test_cert()
cert.key_data = ""
cert.save()
self.client.force_login(create_test_admin_user())
response = self.client.get(
reverse(
"authentik_api:certificatekeypair-list",
),
data={"name": cert.name, "has_key": False},
)
self.assertEqual(200, response.status_code)
body = loads(response.content.decode())
@ -144,8 +162,8 @@ class TestCrypto(APITestCase):
response = self.client.get(
reverse(
"authentik_api:certificatekeypair-list",
)
+ f"?name={cert.name}&include_details=false"
),
data={"name": cert.name, "include_details": False},
)
self.assertEqual(200, response.status_code)
body = loads(response.content.decode())
@ -168,8 +186,8 @@ class TestCrypto(APITestCase):
reverse(
"authentik_api:certificatekeypair-view-certificate",
kwargs={"pk": keypair.pk},
)
+ "?download",
),
data={"download": True},
)
self.assertEqual(200, response.status_code)
self.assertIn("Content-Disposition", response)
@ -189,8 +207,8 @@ class TestCrypto(APITestCase):
reverse(
"authentik_api:certificatekeypair-view-private-key",
kwargs={"pk": keypair.pk},
)
+ "?download",
),
data={"download": True},
)
self.assertEqual(200, response.status_code)
self.assertIn("Content-Disposition", response)
@ -200,7 +218,7 @@ class TestCrypto(APITestCase):
self.client.force_login(create_test_admin_user())
keypair = create_test_cert()
provider = OAuth2Provider.objects.create(
name="test",
name=generate_id(),
client_id="test",
client_secret=generate_key(),
authorization_flow=create_test_flow(),

View File

@ -1,44 +1,30 @@
"""Enterprise license policies"""
from typing import Optional
from rest_framework.serializers import BaseSerializer
from authentik.core.models import User, UserTypes
from authentik.enterprise.models import LicenseKey
from authentik.policies.models import Policy
from authentik.policies.types import PolicyRequest, PolicyResult
from authentik.policies.views import PolicyAccessView
class EnterprisePolicy(Policy):
"""Check that a user is correctly licensed for the request"""
@property
def component(self) -> str:
return ""
@property
def serializer(self) -> type[BaseSerializer]:
raise NotImplementedError
def passes(self, request: PolicyRequest) -> PolicyResult:
if not LicenseKey.get_total().is_valid():
return PolicyResult(False)
if request.user.type != UserTypes.INTERNAL:
return PolicyResult(False)
return PolicyResult(True)
class EnterprisePolicyAccessView(PolicyAccessView):
"""PolicyAccessView which also checks enterprise licensing"""
def check_license(self):
"""Check license"""
if not LicenseKey.get_total().is_valid():
return False
if self.request.user.type != UserTypes.INTERNAL:
return False
return True
def user_has_access(self, user: Optional[User] = None) -> PolicyResult:
user = user or self.request.user
request = PolicyRequest(user)
request.http_request = self.request
result = super().user_has_access(user)
enterprise_result = EnterprisePolicy().passes(request)
if not enterprise_result.passing:
enterprise_result = self.check_license()
if not enterprise_result:
return enterprise_result
return result

View File

@ -9,7 +9,6 @@ from django.core.exceptions import SuspiciousOperation
from django.db.models import Model
from django.db.models.signals import m2m_changed, post_save, pre_delete
from django.http import HttpRequest, HttpResponse
from django_otp.plugins.otp_static.models import StaticToken
from guardian.models import UserObjectPermission
from authentik.core.models import (
@ -30,6 +29,7 @@ from authentik.outposts.models import OutpostServiceConnection
from authentik.policies.models import Policy, PolicyBindingModel
from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken
from authentik.providers.scim.models import SCIMGroup, SCIMUser
from authentik.stages.authenticator_static.models import StaticToken
IGNORED_MODELS = (
Event,

View File

@ -181,7 +181,7 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
if not file:
return Response(data=import_response.initial_data, status=400)
importer = Importer(file.read().decode())
importer = Importer.from_string(file.read().decode())
valid, logs = importer.validate()
import_response.initial_data["logs"] = [sanitize_dict(log) for log in logs]
import_response.initial_data["success"] = valid

View File

@ -26,3 +26,8 @@ class EmptyFlowException(SentryIgnoredException):
class FlowSkipStageException(SentryIgnoredException):
"""Exception to skip a stage"""
class StageInvalidException(SentryIgnoredException):
"""Exception can be thrown in a `Challenge` or `ChallengeResponse` serializer's
validation to trigger a `executor.stage_invalid()` response"""

View File

@ -23,6 +23,7 @@ from authentik.flows.challenge import (
RedirectChallenge,
WithUserInfoChallenge,
)
from authentik.flows.exceptions import StageInvalidException
from authentik.flows.models import InvalidResponseAction
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_PENDING_USER
from authentik.lib.avatars import DEFAULT_AVATAR
@ -100,8 +101,14 @@ class ChallengeStageView(StageView):
def post(self, request: Request, *args, **kwargs) -> HttpResponse:
"""Handle challenge response"""
challenge: ChallengeResponse = self.get_response_instance(data=request.data)
if not challenge.is_valid():
valid = False
try:
challenge: ChallengeResponse = self.get_response_instance(data=request.data)
valid = challenge.is_valid()
except StageInvalidException as exc:
self.logger.debug("Got StageInvalidException", exc=exc)
return self.executor.stage_invalid()
if not valid:
if self.executor.current_binding.invalid_response_action in [
InvalidResponseAction.RESTART,
InvalidResponseAction.RESTART_WITH_CONTEXT,

View File

@ -21,8 +21,9 @@ def view_tester_factory(view_class: type[StageView]) -> Callable:
def tester(self: TestViews):
model_class = view_class(self.exec)
self.assertIsNotNone(model_class.post)
self.assertIsNotNone(model_class.get)
if not hasattr(model_class, "dispatch"):
self.assertIsNotNone(model_class.post)
self.assertIsNotNone(model_class.get)
return tester

View File

@ -42,6 +42,7 @@ from authentik.flows.models import (
FlowDesignation,
FlowStageBinding,
FlowToken,
InvalidResponseAction,
Stage,
)
from authentik.flows.planner import (
@ -73,40 +74,23 @@ QS_QUERY = "query"
def challenge_types():
"""This is a workaround for PolymorphicProxySerializer not accepting a callable for
`serializers`. This function returns a class which is an iterator, which returns the
"""This function returns a mapping which contains all subclasses of challenges
subclasses of Challenge, and Challenge itself."""
class Inner(dict):
"""dummy class with custom callback on .items()"""
def items(self):
mapping = {}
classes = all_subclasses(Challenge)
classes.remove(WithUserInfoChallenge)
for cls in classes:
mapping[cls().fields["component"].default] = cls
return mapping.items()
return Inner()
mapping = {}
for cls in all_subclasses(Challenge):
if cls == WithUserInfoChallenge:
continue
mapping[cls().fields["component"].default] = cls
return mapping
def challenge_response_types():
"""This is a workaround for PolymorphicProxySerializer not accepting a callable for
`serializers`. This function returns a class which is an iterator, which returns the
"""This function returns a mapping which contains all subclasses of challenges
subclasses of Challenge, and Challenge itself."""
class Inner(dict):
"""dummy class with custom callback on .items()"""
def items(self):
mapping = {}
classes = all_subclasses(ChallengeResponse)
for cls in classes:
mapping[cls(stage=None).fields["component"].default] = cls
return mapping.items()
return Inner()
mapping = {}
for cls in all_subclasses(ChallengeResponse):
mapping[cls(stage=None).fields["component"].default] = cls
return mapping
class InvalidStageError(SentryIgnoredException):
@ -122,7 +106,7 @@ class FlowExecutorView(APIView):
flow: Flow
plan: Optional[FlowPlan] = None
current_binding: FlowStageBinding
current_binding: Optional[FlowStageBinding] = None
current_stage: Stage
current_stage_view: View
@ -264,7 +248,7 @@ class FlowExecutorView(APIView):
responses={
200: PolymorphicProxySerializer(
component_name="ChallengeTypes",
serializers=challenge_types(),
serializers=challenge_types,
resource_type_field_name="component",
),
},
@ -295,7 +279,7 @@ class FlowExecutorView(APIView):
span.set_data("Method", "GET")
span.set_data("authentik Stage", self.current_stage_view)
span.set_data("authentik Flow", self.flow.slug)
stage_response = self.current_stage_view.get(request, *args, **kwargs)
stage_response = self.current_stage_view.dispatch(request)
return to_stage_response(request, stage_response)
except Exception as exc: # pylint: disable=broad-except
return self.handle_exception(exc)
@ -304,13 +288,13 @@ class FlowExecutorView(APIView):
responses={
200: PolymorphicProxySerializer(
component_name="ChallengeTypes",
serializers=challenge_types(),
serializers=challenge_types,
resource_type_field_name="component",
),
},
request=PolymorphicProxySerializer(
component_name="FlowChallengeResponse",
serializers=challenge_response_types(),
serializers=challenge_response_types,
resource_type_field_name="component",
),
parameters=[
@ -339,7 +323,7 @@ class FlowExecutorView(APIView):
span.set_data("Method", "POST")
span.set_data("authentik Stage", self.current_stage_view)
span.set_data("authentik Flow", self.flow.slug)
stage_response = self.current_stage_view.post(request, *args, **kwargs)
stage_response = self.current_stage_view.dispatch(request)
return to_stage_response(request, stage_response)
except Exception as exc: # pylint: disable=broad-except
return self.handle_exception(exc)
@ -362,10 +346,15 @@ class FlowExecutorView(APIView):
def restart_flow(self, keep_context=False) -> HttpResponse:
"""Restart the currently active flow, optionally keeping the current context"""
planner = FlowPlanner(self.flow)
planner.use_cache = False
default_context = None
if keep_context:
default_context = self.plan.context
plan = planner.plan(self.request, default_context)
try:
plan = planner.plan(self.request, default_context)
except FlowNonApplicableException as exc:
self._logger.warning("f(exec): Flow restart not applicable to current user", exc=exc)
return self.handle_invalid_flow(exc)
self.request.session[SESSION_KEY_PLAN] = plan
kwargs = self.kwargs
kwargs.update({"flow_slug": self.flow.slug})
@ -423,6 +412,19 @@ class FlowExecutorView(APIView):
Optionally, an exception can be passed, which will be shown if the current user
is a superuser."""
self._logger.debug("f(exec): Stage invalid")
if self.current_binding and self.current_binding.invalid_response_action in [
InvalidResponseAction.RESTART,
InvalidResponseAction.RESTART_WITH_CONTEXT,
]:
keep_context = (
self.current_binding.invalid_response_action
== InvalidResponseAction.RESTART_WITH_CONTEXT
)
self._logger.debug(
"f(exec): Invalid response, restarting flow",
keep_context=keep_context,
)
return self.restart_flow(keep_context)
self.cancel()
challenge_view = AccessDeniedChallengeView(self, error_message)
challenge_view.request = self.request

View File

@ -1,4 +1,4 @@
# update website/docs/installation/configuration.md
# update website/docs/installation/configuration.mdx
# This is the default configuration file
postgresql:
host: localhost
@ -7,6 +7,7 @@ postgresql:
port: 5432
password: "env://POSTGRES_PASSWORD"
use_pgbouncer: false
use_pgpool: false
listen:
listen_http: 0.0.0.0:9000
@ -110,3 +111,6 @@ web:
# No default here as it's set dynamically
# workers: 2
threads: 4
worker:
concurrency: 2

View File

@ -7,7 +7,6 @@ from typing import Any, Iterable, Optional
from cachetools import TLRUCache, cached
from django.core.exceptions import FieldError
from django_otp import devices_for_user
from guardian.shortcuts import get_anonymous_user
from rest_framework.serializers import ValidationError
from sentry_sdk.hub import Hub
@ -20,6 +19,7 @@ from authentik.lib.utils.http import get_http_session
from authentik.policies.models import Policy, PolicyBinding
from authentik.policies.process import PolicyProcess
from authentik.policies.types import PolicyRequest, PolicyResult
from authentik.stages.authenticator import devices_for_user
LOGGER = get_logger()

View File

@ -1,7 +1,112 @@
"""logging helpers"""
import logging
from logging import Logger
from os import getpid
import structlog
from authentik.lib.config import CONFIG
LOG_PRE_CHAIN = [
# Add the log level and a timestamp to the event_dict if the log entry
# is not from structlog.
structlog.stdlib.add_log_level,
structlog.stdlib.add_logger_name,
structlog.processors.TimeStamper(),
structlog.processors.StackInfoRenderer(),
]
def get_log_level():
"""Get log level, clamp trace to debug"""
level = CONFIG.get("log_level").upper()
# We could add a custom level to stdlib logging and structlog, but it's not easy or clean
# https://stackoverflow.com/questions/54505487/custom-log-level-not-working-with-structlog
# Additionally, the entire code uses debug as highest level
# so that would have to be re-written too
if level == "TRACE":
level = "DEBUG"
return level
def structlog_configure():
"""Configure structlog itself"""
structlog.configure_once(
processors=[
structlog.stdlib.add_log_level,
structlog.stdlib.add_logger_name,
structlog.contextvars.merge_contextvars,
add_process_id,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso", utc=False),
structlog.processors.StackInfoRenderer(),
structlog.processors.dict_tracebacks,
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.make_filtering_bound_logger(
getattr(logging, get_log_level(), logging.WARNING)
),
cache_logger_on_first_use=True,
)
def get_logger_config():
"""Configure python stdlib's logging"""
debug = CONFIG.get_bool("debug")
global_level = get_log_level()
base_config = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"json": {
"()": structlog.stdlib.ProcessorFormatter,
"processor": structlog.processors.JSONRenderer(sort_keys=True),
"foreign_pre_chain": LOG_PRE_CHAIN + [structlog.processors.dict_tracebacks],
},
"console": {
"()": structlog.stdlib.ProcessorFormatter,
"processor": structlog.dev.ConsoleRenderer(colors=debug),
"foreign_pre_chain": LOG_PRE_CHAIN,
},
},
"handlers": {
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "console" if debug else "json",
},
},
"loggers": {},
}
handler_level_map = {
"": global_level,
"authentik": global_level,
"django": "WARNING",
"django.request": "ERROR",
"celery": "WARNING",
"selenium": "WARNING",
"docker": "WARNING",
"urllib3": "WARNING",
"websockets": "WARNING",
"daphne": "WARNING",
"kubernetes": "INFO",
"asyncio": "WARNING",
"redis": "WARNING",
"silk": "INFO",
"fsevents": "WARNING",
"uvicorn": "WARNING",
"gunicorn": "INFO",
}
for handler_name, level in handler_level_map.items():
base_config["loggers"][handler_name] = {
"handlers": ["console"],
"level": level,
"propagate": False,
}
return base_config
def add_process_id(logger: Logger, method_name: str, event_dict):
"""Add the current process ID"""

View File

@ -77,6 +77,7 @@ class PolicyBindingSerializer(ModelSerializer):
"enabled",
"order",
"timeout",
"failure_result",
]
def validate(self, attrs: OrderedDict) -> OrderedDict:

View File

@ -0,0 +1,26 @@
# Generated by Django 4.2.5 on 2023-09-13 18:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_policies", "0010_alter_policy_name"),
]
operations = [
migrations.AddField(
model_name="policybinding",
name="failure_result",
field=models.BooleanField(
default=False, help_text="Result if the Policy execution fails."
),
),
migrations.AlterField(
model_name="policybinding",
name="timeout",
field=models.PositiveIntegerField(
default=30, help_text="Timeout after which Policy execution is terminated."
),
),
]

View File

@ -85,9 +85,12 @@ class PolicyBinding(SerializerModel):
default=False,
help_text=_("Negates the outcome of the policy. Messages are unaffected."),
)
timeout = models.IntegerField(
timeout = models.PositiveIntegerField(
default=30, help_text=_("Timeout after which Policy execution is terminated.")
)
failure_result = models.BooleanField(
default=False, help_text=_("Result if the Policy execution fails.")
)
order = models.IntegerField()

View File

@ -98,8 +98,8 @@ class PolicyProcess(PROCESS_CLASS):
# Create policy exception event, only when we're not debugging
if not self.request.debug:
self.create_event(EventAction.POLICY_EXCEPTION, message=error_string)
LOGGER.debug("P_ENG(proc): error", exc=src_exc)
policy_result = PolicyResult(False, str(src_exc))
LOGGER.debug("P_ENG(proc): error, using failure result", exc=src_exc)
policy_result = PolicyResult(self.binding.failure_result, str(src_exc))
policy_result.source_binding = self.binding
should_cache = self.request.should_cache
if should_cache:

View File

@ -1,5 +1,7 @@
"""Reputation policy API Views"""
from django.utils.translation import gettext_lazy as _
from rest_framework import mixins
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
@ -11,6 +13,11 @@ from authentik.policies.reputation.models import Reputation, ReputationPolicy
class ReputationPolicySerializer(PolicySerializer):
"""Reputation Policy Serializer"""
def validate(self, attrs: dict) -> dict:
if not attrs.get("check_ip", False) and not attrs.get("check_username", False):
raise ValidationError(_("Either IP or Username must be checked"))
return super().validate(attrs)
class Meta:
model = ReputationPolicy
fields = PolicySerializer.Meta.fields + [

View File

@ -3,6 +3,8 @@ from django.core.cache import cache
from django.test import RequestFactory, TestCase
from authentik.core.models import User
from authentik.lib.generators import generate_id
from authentik.policies.reputation.api import ReputationPolicySerializer
from authentik.policies.reputation.models import CACHE_KEY_PREFIX, Reputation, ReputationPolicy
from authentik.policies.reputation.tasks import save_reputation
from authentik.policies.types import PolicyRequest
@ -61,3 +63,8 @@ class TestReputationPolicy(TestCase):
name="reputation-test", threshold=0
)
self.assertTrue(policy.passes(request).passing)
def test_api(self):
"""Test API Validation"""
no_toggle = ReputationPolicySerializer(data={"name": generate_id(), "threshold": -5})
self.assertFalse(no_toggle.is_valid())

View File

@ -97,6 +97,17 @@ class TestPolicyEngine(TestCase):
self.assertEqual(result.passing, False)
self.assertEqual(result.messages, ("division by zero",))
def test_engine_policy_error_failure(self):
"""Test policy raising an error flag"""
pbm = PolicyBindingModel.objects.create()
PolicyBinding.objects.create(
target=pbm, policy=self.policy_raises, order=0, failure_result=True
)
engine = PolicyEngine(pbm, self.user)
result = engine.build().result
self.assertEqual(result.passing, True)
self.assertEqual(result.messages, ("division by zero",))
def test_engine_policy_type(self):
"""Test invalid policy type"""
pbm = PolicyBindingModel.objects.create()

View File

@ -13,10 +13,9 @@ from rest_framework.decorators import action
from rest_framework.fields import CharField, FileField, SerializerMethodField
from rest_framework.parsers import MultiPartParser
from rest_framework.permissions import AllowAny
from rest_framework.relations import SlugRelatedField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ValidationError
from rest_framework.serializers import PrimaryKeyRelatedField, ValidationError
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
@ -168,10 +167,8 @@ class SAMLProviderImportSerializer(PassiveSerializer):
"""Import saml provider from XML Metadata"""
name = CharField(required=True)
# Using SlugField because https://github.com/OpenAPITools/openapi-generator/issues/3278
authorization_flow = SlugRelatedField(
authorization_flow = PrimaryKeyRelatedField(
queryset=Flow.objects.filter(designation=FlowDesignation.AUTHORIZATION),
slug_field="slug",
)
file = FileField()

View File

@ -171,6 +171,8 @@ class MetadataProcessor:
entity_descriptor, f"{{{NS_SAML_METADATA}}}IDPSSODescriptor"
)
idp_sso_descriptor.attrib["protocolSupportEnumeration"] = NS_SAML_PROTOCOL
if self.provider.verification_kp:
idp_sso_descriptor.attrib["WantAuthnRequestsSigned"] = "true"
signing_descriptor = self.get_signing_key_descriptor()
if signing_descriptor is not None:

View File

@ -89,7 +89,7 @@ class TestSAMLProviderAPI(APITestCase):
{
"file": metadata,
"name": generate_id(),
"authorization_flow": create_test_flow(FlowDesignation.AUTHORIZATION).slug,
"authorization_flow": create_test_flow(FlowDesignation.AUTHORIZATION).pk,
},
format="multipart",
)
@ -106,7 +106,7 @@ class TestSAMLProviderAPI(APITestCase):
{
"file": metadata,
"name": generate_id(),
"authorization_flow": create_test_flow().slug,
"authorization_flow": create_test_flow().pk,
},
format="multipart",
)

View File

@ -12,7 +12,7 @@ from authentik.lib.xml import lxml_from_string
from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.metadata import MetadataProcessor
from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser
from authentik.sources.saml.processors.constants import NS_MAP
from authentik.sources.saml.processors.constants import NS_MAP, NS_SAML_METADATA
class TestServiceProviderMetadataParser(TestCase):
@ -55,6 +55,24 @@ class TestServiceProviderMetadataParser(TestCase):
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-metadata-2.0.xsd")) # nosec
self.assertTrue(schema.validate(metadata))
def test_schema_want_authn_requests_signed(self):
"""Test metadata generation with WantAuthnRequestsSigned"""
cert = create_test_cert()
provider = SAMLProvider.objects.create(
name=generate_id(),
authorization_flow=self.flow,
verification_kp=cert,
)
Application.objects.create(
name=generate_id(),
slug=generate_id(),
provider=provider,
)
request = self.factory.get("/")
metadata = lxml_from_string(MetadataProcessor(provider, request).build_entity_descriptor())
idp_sso_descriptor = metadata.findall(f"{{{NS_SAML_METADATA}}}IDPSSODescriptor")[0]
self.assertEqual(idp_sso_descriptor.attrib["WantAuthnRequestsSigned"], "true")
def test_simple(self):
"""Test simple metadata without Signing"""
metadata = ServiceProviderMetadataParser().parse(load_fixture("fixtures/simple.xml"))

View File

@ -23,6 +23,8 @@ def post_save_provider(sender: type[Model], instance, created: bool, **_):
@receiver(post_save, sender=Group)
def post_save_scim(sender: type[Model], instance: User | Group, created: bool, **_):
"""Post save handler"""
if not SCIMProvider.objects.filter(backchannel_application__isnull=False).exists():
return
scim_signal_direct.delay(class_to_path(instance.__class__), instance.pk, PatchOp.add.value)
@ -30,6 +32,8 @@ def post_save_scim(sender: type[Model], instance: User | Group, created: bool, *
@receiver(pre_delete, sender=Group)
def pre_delete_scim(sender: type[Model], instance: User | Group, **_):
"""Pre-delete handler"""
if not SCIMProvider.objects.filter(backchannel_application__isnull=False).exists():
return
scim_signal_direct.delay(class_to_path(instance.__class__), instance.pk, PatchOp.remove.value)
@ -40,6 +44,8 @@ def m2m_changed_scim(
"""Sync group membership"""
if action not in ["post_add", "post_remove"]:
return
if not SCIMProvider.objects.filter(backchannel_application__isnull=False).exists():
return
# reverse: instance is a Group, pk_set is a list of user pks
# non-reverse: instance is a User, pk_set is a list of groups
if reverse:

View File

@ -172,7 +172,7 @@ class ChannelsLoggingMiddleware:
LOGGER.info(
scope["path"],
scheme="ws",
remote=scope.get("client", [""])[0],
remote=headers.get(b"x-forwarded-for", b"").decode(),
user_agent=headers.get(b"user-agent", b"").decode(),
**kwargs,
)

View File

@ -1,25 +1,21 @@
"""root settings for authentik"""
import importlib
import logging
import os
from hashlib import sha512
from pathlib import Path
from urllib.parse import quote_plus
import structlog
from celery.schedules import crontab
from sentry_sdk import set_tag
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik.lib.config import CONFIG
from authentik.lib.logging import add_process_id
from authentik.lib.logging import get_logger_config, structlog_configure
from authentik.lib.sentry import sentry_init
from authentik.lib.utils.reflection import get_env
from authentik.stages.password import BACKEND_APP_PASSWORD, BACKEND_INBUILT, BACKEND_LDAP
LOGGER = structlog.get_logger()
BASE_DIR = Path(__file__).absolute().parent.parent.parent
STATICFILES_DIRS = [BASE_DIR / Path("web")]
MEDIA_ROOT = BASE_DIR / Path("media")
@ -41,6 +37,7 @@ CSRF_HEADER_NAME = "HTTP_X_AUTHENTIK_CSRF"
LANGUAGE_COOKIE_NAME = "authentik_language"
SESSION_COOKIE_NAME = "authentik_session"
SESSION_COOKIE_DOMAIN = CONFIG.get("cookie_domain", None)
APPEND_SLASH = False
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
@ -85,6 +82,7 @@ INSTALLED_APPS = [
"authentik.sources.oauth",
"authentik.sources.plex",
"authentik.sources.saml",
"authentik.stages.authenticator",
"authentik.stages.authenticator_duo",
"authentik.stages.authenticator_sms",
"authentik.stages.authenticator_static",
@ -282,6 +280,9 @@ DATABASES = {
}
}
if CONFIG.get_bool("postgresql.use_pgpool", False):
DATABASES["default"]["DISABLE_SERVER_SIDE_CURSORS"] = True
if CONFIG.get_bool("postgresql.use_pgbouncer", False):
# https://docs.djangoproject.com/en/4.0/ref/databases/#transaction-pooling-server-side-cursors
DATABASES["default"]["DISABLE_SERVER_SIDE_CURSORS"] = True
@ -332,7 +333,7 @@ LOCALE_PATHS = ["./locale"]
CELERY = {
"task_soft_time_limit": 600,
"worker_max_tasks_per_child": 50,
"worker_concurrency": 2,
"worker_concurrency": CONFIG.get_int("worker.concurrency"),
"beat_schedule": {
"clean_expired_models": {
"task": "authentik.core.tasks.clean_expired_models",
@ -368,91 +369,9 @@ MEDIA_URL = "/media/"
TEST = False
TEST_RUNNER = "authentik.root.test_runner.PytestTestRunner"
# We can't check TEST here as its set later by the test runner
LOG_LEVEL = CONFIG.get("log_level").upper() if "TF_BUILD" not in os.environ else "DEBUG"
# We could add a custom level to stdlib logging and structlog, but it's not easy or clean
# https://stackoverflow.com/questions/54505487/custom-log-level-not-working-with-structlog
# Additionally, the entire code uses debug as highest level so that would have to be re-written too
if LOG_LEVEL == "TRACE":
LOG_LEVEL = "DEBUG"
structlog.configure_once(
processors=[
structlog.stdlib.add_log_level,
structlog.stdlib.add_logger_name,
structlog.contextvars.merge_contextvars,
add_process_id,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso", utc=False),
structlog.processors.StackInfoRenderer(),
structlog.processors.dict_tracebacks,
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.make_filtering_bound_logger(
getattr(logging, LOG_LEVEL, logging.WARNING)
),
cache_logger_on_first_use=True,
)
LOG_PRE_CHAIN = [
# Add the log level and a timestamp to the event_dict if the log entry
# is not from structlog.
structlog.stdlib.add_log_level,
structlog.stdlib.add_logger_name,
structlog.processors.TimeStamper(),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
]
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"json": {
"()": structlog.stdlib.ProcessorFormatter,
"processor": structlog.processors.JSONRenderer(sort_keys=True),
"foreign_pre_chain": LOG_PRE_CHAIN,
},
"console": {
"()": structlog.stdlib.ProcessorFormatter,
"processor": structlog.dev.ConsoleRenderer(colors=DEBUG),
"foreign_pre_chain": LOG_PRE_CHAIN,
},
},
"handlers": {
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "console" if DEBUG else "json",
},
},
"loggers": {},
}
_LOGGING_HANDLER_MAP = {
"": LOG_LEVEL,
"authentik": LOG_LEVEL,
"django": "WARNING",
"django.request": "ERROR",
"celery": "WARNING",
"selenium": "WARNING",
"docker": "WARNING",
"urllib3": "WARNING",
"websockets": "WARNING",
"daphne": "WARNING",
"kubernetes": "INFO",
"asyncio": "WARNING",
"redis": "WARNING",
"silk": "INFO",
"fsevents": "WARNING",
}
for handler_name, level in _LOGGING_HANDLER_MAP.items():
LOGGING["loggers"][handler_name] = {
"handlers": ["console"],
"level": level,
"propagate": False,
}
structlog_configure()
LOGGING = get_logger_config()
_DISALLOWED_ITEMS = [

View File

@ -20,7 +20,7 @@ class PytestTestRunner: # pragma: no cover
self.failfast = failfast
self.keepdb = keepdb
self.args = ["-vv", "--full-trace"]
self.args = []
if self.failfast:
self.args.append("--exitfirst")
if self.keepdb:

View File

View File

@ -0,0 +1,40 @@
"""Property mapping API Views"""
from django_filters.filters import AllValuesMultipleFilter
from django_filters.filterset import FilterSet
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.propertymappings import PropertyMappingSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.sources.ldap.models import LDAPPropertyMapping
class LDAPPropertyMappingSerializer(PropertyMappingSerializer):
"""LDAP PropertyMapping Serializer"""
class Meta:
model = LDAPPropertyMapping
fields = PropertyMappingSerializer.Meta.fields + [
"object_field",
]
class LDAPPropertyMappingFilter(FilterSet):
"""Filter for LDAPPropertyMapping"""
managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed"))
class Meta:
model = LDAPPropertyMapping
fields = "__all__"
class LDAPPropertyMappingViewSet(UsedByMixin, ModelViewSet):
"""LDAP PropertyMapping Viewset"""
queryset = LDAPPropertyMapping.objects.all()
serializer_class = LDAPPropertyMappingSerializer
filterset_class = LDAPPropertyMappingFilter
search_fields = ["name"]
ordering = ["name"]

View File

@ -0,0 +1,32 @@
"""LDAP Source Serializer"""
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.viewsets import ModelViewSet
from authentik.api.authorization import OwnerFilter, OwnerSuperuserPermissions
from authentik.core.api.sources import UserSourceConnectionSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.sources.ldap.models import LDAPUserSourceConnection
class LDAPUserSourceConnectionSerializer(UserSourceConnectionSerializer):
"""LDAP Source Serializer"""
class Meta:
model = LDAPUserSourceConnection
fields = ["pk", "user", "source", "unique_identifier"]
extra_kwargs = {
"access_token": {"write_only": True},
}
class LDAPUserSourceConnectionViewSet(UsedByMixin, ModelViewSet):
"""Source Viewset"""
queryset = LDAPUserSourceConnection.objects.all()
serializer_class = LDAPUserSourceConnectionSerializer
filterset_fields = ["source__slug"]
search_fields = ["source__slug"]
permission_classes = [OwnerSuperuserPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
ordering = ["source__slug"]

View File

@ -1,10 +1,7 @@
"""Source API Views"""
from typing import Any
from django_filters.filters import AllValuesMultipleFilter
from django_filters.filterset import FilterSet
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema, extend_schema_field, inline_serializer
from drf_spectacular.utils import extend_schema, inline_serializer
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import DictField, ListField
@ -14,12 +11,11 @@ from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from authentik.admin.api.tasks import TaskSerializer
from authentik.core.api.propertymappings import PropertyMappingSerializer
from authentik.core.api.sources import SourceSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.crypto.models import CertificateKeyPair
from authentik.events.monitored_tasks import TaskInfo
from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
from authentik.sources.ldap.models import LDAPSource
from authentik.sources.ldap.tasks import SYNC_CLASSES
@ -154,33 +150,3 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
obj.pop("raw_dn", None)
all_objects[class_name].append(obj)
return Response(data=all_objects)
class LDAPPropertyMappingSerializer(PropertyMappingSerializer):
"""LDAP PropertyMapping Serializer"""
class Meta:
model = LDAPPropertyMapping
fields = PropertyMappingSerializer.Meta.fields + [
"object_field",
]
class LDAPPropertyMappingFilter(FilterSet):
"""Filter for LDAPPropertyMapping"""
managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed"))
class Meta:
model = LDAPPropertyMapping
fields = "__all__"
class LDAPPropertyMappingViewSet(UsedByMixin, ModelViewSet):
"""LDAP PropertyMapping Viewset"""
queryset = LDAPPropertyMapping.objects.all()
serializer_class = LDAPPropertyMappingSerializer
filterset_class = LDAPPropertyMappingFilter
search_fields = ["name"]
ordering = ["name"]

View File

@ -0,0 +1,58 @@
# Generated by Django 4.2.5 on 2023-09-27 10:44
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0032_groupsourceconnection"),
("authentik_sources_ldap", "0003_ldapsource_client_certificate_ldapsource_sni_and_more"),
]
operations = [
migrations.CreateModel(
name="LDAPGroupSourceConnection",
fields=[
(
"groupsourceconnection_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="authentik_core.groupsourceconnection",
),
),
("unique_identifier", models.TextField(unique=True)),
],
options={
"verbose_name": "LDAP Group Source Connection",
"verbose_name_plural": "LDAP Group Source Connections",
},
bases=("authentik_core.groupsourceconnection",),
),
migrations.CreateModel(
name="LDAPUserSourceConnection",
fields=[
(
"usersourceconnection_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="authentik_core.usersourceconnection",
),
),
("unique_identifier", models.TextField(unique=True)),
],
options={
"verbose_name": "LDAP User Source Connection",
"verbose_name_plural": "LDAP User Source Connections",
},
bases=("authentik_core.usersourceconnection",),
),
]

View File

@ -10,7 +10,13 @@ from ldap3 import ALL, NONE, RANDOM, Connection, Server, ServerPool, Tls
from ldap3.core.exceptions import LDAPInsufficientAccessRightsResult, LDAPSchemaError
from rest_framework.serializers import Serializer
from authentik.core.models import Group, PropertyMapping, Source
from authentik.core.models import (
Group,
GroupSourceConnection,
PropertyMapping,
Source,
UserSourceConnection,
)
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.config import CONFIG
from authentik.lib.models import DomainlessURLValidator
@ -113,7 +119,7 @@ class LDAPSource(Source):
@property
def serializer(self) -> type[Serializer]:
from authentik.sources.ldap.api import LDAPSourceSerializer
from authentik.sources.ldap.api.sources import LDAPSourceSerializer
return LDAPSourceSerializer
@ -202,7 +208,7 @@ class LDAPPropertyMapping(PropertyMapping):
@property
def serializer(self) -> type[Serializer]:
from authentik.sources.ldap.api import LDAPPropertyMappingSerializer
from authentik.sources.ldap.api.property_mappings import LDAPPropertyMappingSerializer
return LDAPPropertyMappingSerializer
@ -212,3 +218,35 @@ class LDAPPropertyMapping(PropertyMapping):
class Meta:
verbose_name = _("LDAP Property Mapping")
verbose_name_plural = _("LDAP Property Mappings")
class LDAPUserSourceConnection(UserSourceConnection):
"""Connection between an authentik user and an LDAP source."""
unique_identifier = models.TextField(unique=True)
@property
def serializer(self) -> Serializer:
from authentik.sources.ldap.api.source_connections import LDAPUserSourceConnectionSerializer
return LDAPUserSourceConnectionSerializer
class Meta:
verbose_name = _("LDAP User Source Connection")
verbose_name_plural = _("LDAP User Source Connections")
class LDAPGroupSourceConnection(GroupSourceConnection):
"""Connection between an authentik group and an LDAP source."""
unique_identifier = models.TextField(unique=True)
@property
def serializer(self) -> Serializer:
from authentik.sources.ldap.api.source_connections import LDAPUserSourceConnectionSerializer
return LDAPUserSourceConnectionSerializer
class Meta:
verbose_name = _("LDAP Group Source Connection")
verbose_name_plural = _("LDAP Group Source Connections")

View File

@ -133,7 +133,7 @@ class BaseLDAPSynchronizer:
def build_user_properties(self, user_dn: str, **kwargs) -> dict[str, Any]:
"""Build attributes for User object based on property mappings."""
props = self._build_object_properties(user_dn, self._source.property_mappings, **kwargs)
props["path"] = self._source.get_user_path()
props.setdefault("path", self._source.get_user_path())
return props
def build_group_properties(self, group_dn: str, **kwargs) -> dict[str, Any]:
@ -151,10 +151,14 @@ class BaseLDAPSynchronizer:
continue
mapping: LDAPPropertyMapping
try:
value = mapping.evaluate(user=None, request=None, ldap=kwargs, dn=object_dn)
value = mapping.evaluate(
user=None, request=None, ldap=kwargs, dn=object_dn, source=self._source
)
if value is None:
self._logger.warning("property mapping returned None", mapping=mapping)
continue
if isinstance(value, (bytes)):
self._logger.warning("property mapping returned bytes", mapping=mapping)
continue
object_field = mapping.object_field
if object_field.startswith("attributes."):

View File

@ -7,6 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE
from authentik.core.models import Group
from authentik.events.models import Event, EventAction
from authentik.sources.ldap.models import LDAPGroupSourceConnection
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer
@ -18,6 +19,9 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
return "groups"
def get_objects(self, **kwargs) -> Generator:
if not self._source.sync_groups:
self.message("Group syncing is disabled for this Source")
return iter(())
return self.search_paginator(
search_base=self.base_dn_groups,
search_filter=self._source.group_object_filter,
@ -60,7 +64,13 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
},
defaults,
)
self._logger.debug("Created group with attributes", **defaults)
LDAPGroupSourceConnection.objects.update_or_create(
defaults={
"unique_identifier": uniq,
},
source=self._source,
group=ak_group,
)
except (IntegrityError, FieldError, TypeError, AttributeError) as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,

View File

@ -24,6 +24,9 @@ class MembershipLDAPSynchronizer(BaseLDAPSynchronizer):
return "membership"
def get_objects(self, **kwargs) -> Generator:
if not self._source.sync_groups:
self.message("Group syncing is disabled for this Source")
return iter(())
return self.search_paginator(
search_base=self.base_dn_groups,
search_filter=self._source.group_object_filter,

View File

@ -7,6 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE
from authentik.core.models import User
from authentik.events.models import Event, EventAction
from authentik.sources.ldap.models import LDAPUserSourceConnection
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer
from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA
from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory
@ -20,6 +21,9 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
return "users"
def get_objects(self, **kwargs) -> Generator:
if not self._source.sync_users:
self.message("User syncing is disabled for this Source")
return iter(())
return self.search_paginator(
search_base=self.base_dn_users,
search_filter=self._source.user_object_filter,
@ -55,6 +59,13 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
ak_user, created = self.update_or_create_attributes(
User, {f"attributes__{LDAP_UNIQUENESS}": uniq}, defaults
)
LDAPUserSourceConnection.objects.update_or_create(
defaults={
"unique_identifier": uniq,
},
source=self._source,
user=ak_user,
)
except (IntegrityError, FieldError, TypeError, AttributeError) as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,
@ -69,6 +80,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
else:
self._logger.debug("Synced User", user=ak_user.username, created=created)
user_count += 1
# TODO: Optimise vendor sync to not create a new connection
MicrosoftActiveDirectory(self._source).sync(attributes, ak_user, created)
FreeIPA(self._source).sync(attributes, ak_user, created)
return user_count

View File

@ -45,7 +45,13 @@ class FreeIPA(BaseLDAPSynchronizer):
# 389-ds and this will trigger regardless
if "nsaccountlock" not in attributes:
return
is_active = attributes.get("nsaccountlock", False)
# For some reason, nsaccountlock is not defined properly in the schema as bool
# hence we get it as a list of strings
_is_locked = str(self._flatten(attributes.get("nsaccountlock", ["FALSE"])))
# So we have to attempt to convert it to a bool
is_locked = _is_locked.lower() == "true"
# And then invert it since freeipa saves locked and we save active
is_active = not is_locked
if is_active != user.is_active:
user.is_active = is_active
user.save()

View File

@ -4,6 +4,8 @@ from uuid import uuid4
from celery import chain, group
from django.core.cache import cache
from ldap3.core.exceptions import LDAPException
from redis.exceptions import LockError
from redis.lock import Lock
from structlog.stdlib import get_logger
from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus
@ -33,24 +35,40 @@ def ldap_sync_all():
ldap_sync_single(source.pk)
@CELERY_APP.task()
@CELERY_APP.task(
# We take the configured hours timeout time by 2.5 as we run user and
# group in parallel and then membership, so 2x is to cover the serial tasks,
# and 0.5x on top of that to give some more leeway
soft_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 2.5,
task_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 2.5,
)
def ldap_sync_single(source_pk: str):
"""Sync a single source"""
source: LDAPSource = LDAPSource.objects.filter(pk=source_pk).first()
if not source:
return
task = chain(
# User and group sync can happen at once, they have no dependencies on each other
group(
ldap_sync_paginator(source, UserLDAPSynchronizer)
+ ldap_sync_paginator(source, GroupLDAPSynchronizer),
),
# Membership sync needs to run afterwards
group(
ldap_sync_paginator(source, MembershipLDAPSynchronizer),
),
)
task()
lock = Lock(cache.client.get_client(), name=f"goauthentik.io/sources/ldap/sync-{source.slug}")
if lock.locked():
LOGGER.debug("LDAP sync locked, skipping task", source=source.slug)
return
try:
with lock:
task = chain(
# User and group sync can happen at once, they have no dependencies on each other
group(
ldap_sync_paginator(source, UserLDAPSynchronizer)
+ ldap_sync_paginator(source, GroupLDAPSynchronizer),
),
# Membership sync needs to run afterwards
group(
ldap_sync_paginator(source, MembershipLDAPSynchronizer),
),
)
task()
except LockError:
# This should never happen, we check if the lock is locked above so this
# would only happen if there was some other timeout
LOGGER.debug("Failed to acquire lock for LDAP sync", source=source.slug)
def ldap_sync_paginator(source: LDAPSource, sync: type[BaseLDAPSynchronizer]) -> list:

View File

@ -55,7 +55,7 @@ def mock_ad_connection(password: str) -> Connection:
"revision": 0,
"objectSid": "user0",
"objectClass": "person",
"distinguishedName": "cn=user0,ou=users,dc=goauthentik,dc=io",
"distinguishedName": "cn=user0,ou=foo,ou=users,dc=goauthentik,dc=io",
"userAccountControl": (
UserAccountControl.ACCOUNTDISABLE + UserAccountControl.NORMAL_ACCOUNT
),

View File

@ -0,0 +1,111 @@
"""ldap testing utils"""
from ldap3 import MOCK_SYNC, OFFLINE_DS389_1_3_3, Connection, Server
def mock_freeipa_connection(password: str) -> Connection:
"""Create mock FreeIPA-ish connection"""
server = Server("my_fake_server", get_info=OFFLINE_DS389_1_3_3)
_pass = "foo" # noqa # nosec
connection = Connection(
server,
user="cn=my_user,dc=goauthentik,dc=io",
password=_pass,
client_strategy=MOCK_SYNC,
)
# Entry for password checking
connection.strategy.add_entry(
"cn=user,ou=users,dc=goauthentik,dc=io",
{
"name": "test-user",
"uid": "unique-test-group",
"objectClass": "person",
"displayName": "Erin M. Hagens",
},
)
connection.strategy.add_entry(
"cn=group1,ou=groups,dc=goauthentik,dc=io",
{
"cn": "group1",
"uid": "unique-test-group",
"objectClass": "groupOfNames",
"member": ["cn=user0,ou=users,dc=goauthentik,dc=io"],
},
)
# Group without SID
connection.strategy.add_entry(
"cn=group2,ou=groups,dc=goauthentik,dc=io",
{
"cn": "group2",
"objectClass": "groupOfNames",
},
)
connection.strategy.add_entry(
"cn=user0,ou=users,dc=goauthentik,dc=io",
{
"userPassword": password,
"name": "user0_sn",
"uid": "user0_sn",
"objectClass": "person",
},
)
# User without SID
connection.strategy.add_entry(
"cn=user1,ou=users,dc=goauthentik,dc=io",
{
"userPassword": "test1111",
"name": "user1_sn",
"objectClass": "person",
},
)
# Duplicate users
connection.strategy.add_entry(
"cn=user2,ou=users,dc=goauthentik,dc=io",
{
"userPassword": "test2222",
"name": "user2_sn",
"uid": "unique-test2222",
"objectClass": "person",
},
)
connection.strategy.add_entry(
"cn=user3,ou=users,dc=goauthentik,dc=io",
{
"userPassword": "test2222",
"name": "user2_sn",
"uid": "unique-test2222",
"objectClass": "person",
},
)
# Group with posixGroup and memberUid
connection.strategy.add_entry(
"cn=group-posix,ou=groups,dc=goauthentik,dc=io",
{
"cn": "group-posix",
"objectClass": "posixGroup",
"memberUid": ["user-posix"],
},
)
# User with posixAccount
connection.strategy.add_entry(
"cn=user-posix,ou=users,dc=goauthentik,dc=io",
{
"userPassword": password,
"uid": "user-posix",
"cn": "user-posix",
"objectClass": "posixAccount",
},
)
# Locked out user
connection.strategy.add_entry(
"cn=user-nsaccountlock,ou=users,dc=goauthentik,dc=io",
{
"userPassword": password,
"uid": "user-nsaccountlock",
"cn": "user-nsaccountlock",
"objectClass": "person",
"nsaccountlock": ["TRUE"],
},
)
connection.bind()
return connection

View File

@ -4,7 +4,7 @@ from ldap3 import MOCK_SYNC, OFFLINE_SLAPD_2_4, Connection, Server
def mock_slapd_connection(password: str) -> Connection:
"""Create mock AD connection"""
"""Create mock SLAPD connection"""
server = Server("my_fake_server", get_info=OFFLINE_SLAPD_2_4)
_pass = "foo" # noqa # nosec
connection = Connection(

View File

@ -2,7 +2,7 @@
from rest_framework.test import APITestCase
from authentik.lib.generators import generate_key
from authentik.sources.ldap.api import LDAPSourceSerializer
from authentik.sources.ldap.api.sources import LDAPSourceSerializer
from authentik.sources.ldap.models import LDAPSource
LDAP_PASSWORD = generate_key()

View File

@ -9,7 +9,7 @@ from authentik.core.models import Group, User
from authentik.core.tests.utils import create_test_admin_user
from authentik.events.models import Event, EventAction
from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus
from authentik.lib.generators import generate_key
from authentik.lib.generators import generate_id, generate_key
from authentik.lib.utils.reflection import class_to_path
from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer
@ -17,6 +17,7 @@ from authentik.sources.ldap.sync.membership import MembershipLDAPSynchronizer
from authentik.sources.ldap.sync.users import UserLDAPSynchronizer
from authentik.sources.ldap.tasks import ldap_sync, ldap_sync_all
from authentik.sources.ldap.tests.mock_ad import mock_ad_connection
from authentik.sources.ldap.tests.mock_freeipa import mock_freeipa_connection
from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection
LDAP_PASSWORD = generate_key()
@ -70,6 +71,28 @@ class LDAPSyncTests(TestCase):
)
self.assertTrue(events.exists())
def test_sync_mapping(self):
"""Test property mappings"""
none = LDAPPropertyMapping.objects.create(
name=generate_id(), object_field="none", expression="return None"
)
byte_mapping = LDAPPropertyMapping.objects.create(
name=generate_id(), object_field="bytes", expression="return b''"
)
self.source.property_mappings.set(
LDAPPropertyMapping.objects.filter(
Q(managed__startswith="goauthentik.io/sources/ldap/default")
| Q(managed__startswith="goauthentik.io/sources/ldap/ms")
)
)
self.source.property_mappings.add(none, byte_mapping)
connection = MagicMock(return_value=mock_ad_connection(LDAP_PASSWORD))
# we basically just test that the mappings don't throw errors
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
user_sync = UserLDAPSynchronizer(self.source)
user_sync.sync_full()
def test_sync_users_ad(self):
"""Test user sync"""
self.source.property_mappings.set(
@ -78,7 +101,6 @@ class LDAPSyncTests(TestCase):
| Q(managed__startswith="goauthentik.io/sources/ldap/ms")
)
)
self.source.save()
connection = MagicMock(return_value=mock_ad_connection(LDAP_PASSWORD))
# Create the user beforehand so we can set attributes and check they aren't removed
@ -101,6 +123,7 @@ class LDAPSyncTests(TestCase):
user = User.objects.filter(username="user0_sn").first()
self.assertEqual(user.attributes["foo"], "bar")
self.assertFalse(user.is_active)
self.assertEqual(user.path, "goauthentik.io/sources/ldap/users/foo")
self.assertFalse(User.objects.filter(username="user1_sn").exists())
def test_sync_users_openldap(self):
@ -112,7 +135,6 @@ class LDAPSyncTests(TestCase):
| Q(managed__startswith="goauthentik.io/sources/ldap/openldap")
)
)
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
user_sync = UserLDAPSynchronizer(self.source)
@ -120,6 +142,23 @@ class LDAPSyncTests(TestCase):
self.assertTrue(User.objects.filter(username="user0_sn").exists())
self.assertFalse(User.objects.filter(username="user1_sn").exists())
def test_sync_users_freeipa_ish(self):
"""Test user sync (FreeIPA-ish), mainly testing vendor quirks"""
self.source.object_uniqueness_field = "uid"
self.source.property_mappings.set(
LDAPPropertyMapping.objects.filter(
Q(managed__startswith="goauthentik.io/sources/ldap/default")
| Q(managed__startswith="goauthentik.io/sources/ldap/openldap")
)
)
connection = MagicMock(return_value=mock_freeipa_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
user_sync = UserLDAPSynchronizer(self.source)
user_sync.sync_full()
self.assertTrue(User.objects.filter(username="user0_sn").exists())
self.assertFalse(User.objects.filter(username="user1_sn").exists())
self.assertFalse(User.objects.get(username="user-nsaccountlock").is_active)
def test_sync_groups_ad(self):
"""Test group sync"""
self.source.property_mappings.set(

View File

@ -1,7 +1,10 @@
"""API URLs"""
from authentik.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet
from authentik.sources.ldap.api.property_mappings import LDAPPropertyMappingViewSet
from authentik.sources.ldap.api.source_connections import LDAPUserSourceConnectionViewSet
from authentik.sources.ldap.api.sources import LDAPSourceViewSet
api_urlpatterns = [
("propertymappings/ldap", LDAPPropertyMappingViewSet),
("sources/user_connections/ldap", LDAPUserSourceConnectionViewSet),
("sources/ldap", LDAPSourceViewSet),
]

View File

@ -68,7 +68,7 @@ class OAuthSource(Source):
# we're using Type[] instead of type[] here since type[] interferes with the property above
@property
def serializer(self) -> Type[Serializer]:
from authentik.sources.oauth.api.source import OAuthSourceSerializer
from authentik.sources.oauth.api.sources import OAuthSourceSerializer
return OAuthSourceSerializer
@ -234,7 +234,7 @@ class UserOAuthSourceConnection(UserSourceConnection):
@property
def serializer(self) -> Serializer:
from authentik.sources.oauth.api.source_connection import (
from authentik.sources.oauth.api.source_connections import (
UserOAuthSourceConnectionSerializer,
)

View File

@ -3,7 +3,7 @@ from django.test import TestCase
from django.urls import reverse
from requests_mock import Mocker
from authentik.sources.oauth.api.source import OAuthSourceSerializer
from authentik.sources.oauth.api.sources import OAuthSourceSerializer
from authentik.sources.oauth.models import OAuthSource

View File

@ -2,8 +2,8 @@
from django.urls import path
from authentik.sources.oauth.api.source import OAuthSourceViewSet
from authentik.sources.oauth.api.source_connection import UserOAuthSourceConnectionViewSet
from authentik.sources.oauth.api.source_connections import UserOAuthSourceConnectionViewSet
from authentik.sources.oauth.api.sources import OAuthSourceViewSet
from authentik.sources.oauth.types.registry import RequestKind
from authentik.sources.oauth.views.dispatcher import DispatcherView

View File

@ -0,0 +1,129 @@
"""Authenticator devices helpers"""
from django.db import transaction
def verify_token(user, device_id, token):
"""
Attempts to verify a :term:`token` against a specific device, identified by
:attr:`~authentik.stages.authenticator.models.Device.persistent_id`.
This wraps the verification process in a transaction to ensure that things
like throttling polices are properly enforced.
:param user: The user supplying the token.
:type user: :class:`~django.contrib.auth.models.User`
:param str device_id: A device's persistent_id value.
:param str token: An OTP token to verify.
:returns: The device that accepted ``token``, if any.
:rtype: :class:`~authentik.stages.authenticator.models.Device` or ``None``
"""
from authentik.stages.authenticator.models import Device
verified = None
with transaction.atomic():
device = Device.from_persistent_id(device_id, for_verify=True)
if (device is not None) and (device.user_id == user.pk) and device.verify_token(token):
verified = device
return verified
def match_token(user, token):
"""
Attempts to verify a :term:`token` on every device attached to the given
user until one of them succeeds.
.. warning::
This originally existed for more convenient integration with the admin
site. Its use is no longer recommended and it is not guaranteed to
interact well with more recent features (such as throttling). Tokens
should always be verified against specific devices.
:param user: The user supplying the token.
:type user: :class:`~django.contrib.auth.models.User`
:param str token: An OTP token to verify.
:returns: The device that accepted ``token``, if any.
:rtype: :class:`~authentik.stages.authenticator.models.Device` or ``None``
"""
with transaction.atomic():
for device in devices_for_user(user, for_verify=True):
if device.verify_token(token):
break
else:
device = None
return device
def devices_for_user(user, confirmed=True, for_verify=False):
"""
Return an iterable of all devices registered to the given user.
Returns an empty iterable for anonymous users.
:param user: standard or custom user object.
:type user: :class:`~django.contrib.auth.models.User`
:param bool confirmed: If ``None``, all matching devices are returned.
Otherwise, this can be any true or false value to limit the query
to confirmed or unconfirmed devices, respectively.
:param bool for_verify: If ``True``, we'll load the devices with
:meth:`~django.db.models.query.QuerySet.select_for_update` to prevent
concurrent verifications from succeeding. In which case, this must be
called inside a transaction.
:rtype: iterable
"""
if user.is_anonymous:
return
for model in device_classes():
device_set = model.objects.devices_for_user(user, confirmed=confirmed)
if for_verify:
device_set = device_set.select_for_update()
yield from device_set
def user_has_device(user, confirmed=True):
"""
Return ``True`` if the user has at least one device.
Returns ``False`` for anonymous users.
:param user: standard or custom user object.
:type user: :class:`~django.contrib.auth.models.User`
:param confirmed: If ``None``, all matching devices are considered.
Otherwise, this can be any true or false value to limit the query
to confirmed or unconfirmed devices, respectively.
"""
try:
next(devices_for_user(user, confirmed=confirmed))
except StopIteration:
has_device = False
else:
has_device = True
return has_device
def device_classes():
"""
Returns an iterable of all loaded device models.
"""
from django.apps import apps # isort: skip
from authentik.stages.authenticator.models import Device
for config in apps.get_app_configs():
for model in config.get_models():
if issubclass(model, Device):
yield model

View File

@ -0,0 +1,10 @@
"""Authenticator"""
from django.apps import AppConfig
class AuthentikStageAuthenticatorConfig(AppConfig):
"""Authenticator App config"""
name = "authentik.stages.authenticator"
label = "authentik_stages_authenticator"
verbose_name = "authentik Stages.Authenticator"

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