Merge branch 'main' into application-wizard-2

* main:
  web/flows: fix identification stage band color (#6489)
  providers/proxy: only intercept auth header when a value is set (#6488)
  web: bump @goauthentik/api from 2023.6.1-1691242648 to 2023.6.1-1691266058 in /web (#6486)
  providers/proxy: set outpost session cookie to httponly and secure wh… (#6482)
  web: bump @esbuild/linux-arm64 from 0.18.17 to 0.18.18 in /web (#6483)
  web/admin: fix user sorting by active field (#6485)
  web: bump @esbuild/darwin-arm64 from 0.18.17 to 0.18.18 in /web (#6484)
  web: bump storybook (#6481)
  web: bump the sentry group in /web with 2 updates (#6480)
  web: bump API Client version (#6479)
  api: optimise pagination in API schema (#6478)
  website/dev-docs: tweaks to template (#6474)
  website: bump react-tooltip from 5.19.0 to 5.20.0 in /website (#6471)
  website: bump prettier from 3.0.0 to 3.0.1 in /website (#6472)
This commit is contained in:
Ken Sternberg 2023-08-07 08:23:00 -07:00
commit fa0a9166d1
22 changed files with 2289 additions and 4844 deletions

View File

@ -2,6 +2,43 @@
from rest_framework import pagination
from rest_framework.response import Response
PAGINATION_COMPONENT_NAME = "Pagination"
PAGINATION_SCHEMA = {
"type": "object",
"properties": {
"next": {
"type": "number",
},
"previous": {
"type": "number",
},
"count": {
"type": "number",
},
"current": {
"type": "number",
},
"total_pages": {
"type": "number",
},
"start_index": {
"type": "number",
},
"end_index": {
"type": "number",
},
},
"required": [
"next",
"previous",
"count",
"current",
"total_pages",
"start_index",
"end_index",
],
}
class Pagination(pagination.PageNumberPagination):
"""Pagination which includes total pages and current page"""
@ -35,41 +72,7 @@ class Pagination(pagination.PageNumberPagination):
return {
"type": "object",
"properties": {
"pagination": {
"type": "object",
"properties": {
"next": {
"type": "number",
},
"previous": {
"type": "number",
},
"count": {
"type": "number",
},
"current": {
"type": "number",
},
"total_pages": {
"type": "number",
},
"start_index": {
"type": "number",
},
"end_index": {
"type": "number",
},
},
"required": [
"next",
"previous",
"count",
"current",
"total_pages",
"start_index",
"end_index",
],
},
"pagination": {"$ref": f"#/components/schemas/{PAGINATION_COMPONENT_NAME}"},
"results": schema,
},
"required": ["pagination", "results"],

View File

@ -1,5 +1,6 @@
"""Error Response schema, from https://github.com/axnsan12/drf-yasg/issues/224"""
from django.utils.translation import gettext_lazy as _
from drf_spectacular.generators import SchemaGenerator
from drf_spectacular.plumbing import (
ResolvedComponent,
build_array_type,
@ -9,6 +10,8 @@ from drf_spectacular.plumbing import (
from drf_spectacular.settings import spectacular_settings
from drf_spectacular.types import OpenApiTypes
from authentik.api.pagination import PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA
def build_standard_type(obj, **kwargs):
"""Build a basic type with optional add owns."""
@ -36,7 +39,19 @@ VALIDATION_ERROR = build_object_type(
)
def postprocess_schema_responses(result, generator, **kwargs): # noqa: W0613
def create_component(generator: SchemaGenerator, name, schema, type_=ResolvedComponent.SCHEMA):
"""Register a component and return a reference to it."""
component = ResolvedComponent(
name=name,
type=type_,
schema=schema,
object=name,
)
generator.registry.register_on_missing(component)
return component
def postprocess_schema_responses(result, generator: SchemaGenerator, **kwargs): # noqa: W0613
"""Workaround to set a default response for endpoints.
Workaround suggested at
<https://github.com/tfranzel/drf-spectacular/issues/119#issuecomment-656970357>
@ -44,19 +59,10 @@ def postprocess_schema_responses(result, generator, **kwargs): # noqa: W0613
<https://github.com/tfranzel/drf-spectacular/issues/101>.
"""
def create_component(name, schema, type_=ResolvedComponent.SCHEMA):
"""Register a component and return a reference to it."""
component = ResolvedComponent(
name=name,
type=type_,
schema=schema,
object=name,
)
generator.registry.register_on_missing(component)
return component
create_component(generator, PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA)
generic_error = create_component("GenericError", GENERIC_ERROR)
validation_error = create_component("ValidationError", VALIDATION_ERROR)
generic_error = create_component(generator, "GenericError", GENERIC_ERROR)
validation_error = create_component(generator, "ValidationError", VALIDATION_ERROR)
for path in result["paths"].values():
for method in path.values():

View File

@ -15,7 +15,13 @@ from django.utils.http import urlencode
from django.utils.text import slugify
from django.utils.timezone import now
from django.utils.translation import gettext as _
from django_filters.filters import BooleanFilter, CharFilter, ModelMultipleChoiceFilter, UUIDFilter
from django_filters.filters import (
BooleanFilter,
CharFilter,
ModelMultipleChoiceFilter,
MultipleChoiceFilter,
UUIDFilter,
)
from django_filters.filterset import FilterSet
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import (
@ -300,11 +306,11 @@ class UsersFilter(FilterSet):
is_superuser = BooleanFilter(field_name="ak_groups", lookup_expr="is_superuser")
uuid = UUIDFilter(field_name="uuid")
path = CharFilter(
field_name="path",
)
path = CharFilter(field_name="path")
path_startswith = CharFilter(field_name="path", lookup_expr="startswith")
type = MultipleChoiceFilter(field_name="type")
groups_by_name = ModelMultipleChoiceFilter(
field_name="ak_groups__name",
to_field_name="name",

View File

@ -13,6 +13,30 @@ import (
"goauthentik.io/internal/constants"
)
// Attempt to set basic auth based on user's attributes
func (a *Application) setAuthorizationHeader(headers http.Header, c *Claims) {
if !*a.proxyConfig.BasicAuthEnabled {
return
}
userAttributes := c.Proxy.UserAttributes
var ok bool
var password string
if password, ok = userAttributes[*a.proxyConfig.BasicAuthPasswordAttribute].(string); !ok {
password = ""
}
// Check if we should use email or a custom attribute as username
var username string
if username, ok = userAttributes[*a.proxyConfig.BasicAuthUserAttribute].(string); !ok {
username = c.Email
}
if username == "" && password == "" {
return
}
authVal := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
a.log.WithField("username", username).Trace("setting http basic auth")
headers.Set("Authorization", fmt.Sprintf("Basic %s", authVal))
}
func (a *Application) addHeaders(headers http.Header, c *Claims) {
// https://goauthentik.io/docs/providers/proxy/proxy
headers.Set("X-authentik-username", c.PreferredUsername)
@ -33,22 +57,7 @@ func (a *Application) addHeaders(headers http.Header, c *Claims) {
return
}
userAttributes := c.Proxy.UserAttributes
// Attempt to set basic auth based on user's attributes
if *a.proxyConfig.BasicAuthEnabled {
var ok bool
var password string
if password, ok = userAttributes[*a.proxyConfig.BasicAuthPasswordAttribute].(string); !ok {
password = ""
}
// Check if we should use email or a custom attribute as username
var username string
if username, ok = userAttributes[*a.proxyConfig.BasicAuthUserAttribute].(string); !ok {
username = c.Email
}
authVal := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
a.log.WithField("username", username).Trace("setting http basic auth")
headers.Set("Authorization", fmt.Sprintf("Basic %s", authVal))
}
a.setAuthorizationHeader(headers, c)
// Check if user has additional headers set that we should sent
if additionalHeaders, ok := userAttributes["additionalHeaders"].(map[string]interface{}); ok {
a.log.WithField("headers", additionalHeaders).Trace("setting additional headers")

View File

@ -3,6 +3,7 @@ package application
import (
"fmt"
"math"
"net/http"
"net/url"
"os"
"path"
@ -37,7 +38,12 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL)
rs.SetMaxLength(math.MaxInt)
rs.SetKeyPrefix(RedisKeyPrefix)
rs.Options.HttpOnly = true
if strings.ToLower(externalHost.Scheme) == "https" {
rs.Options.Secure = true
}
rs.Options.Domain = *p.CookieDomain
rs.Options.SameSite = http.SameSiteLaxMode
a.log.Trace("using redis session backend")
return rs
}
@ -51,7 +57,12 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL)
// Note, when using the FilesystemStore only the session.ID is written to a browser cookie, so this is explicit for the storage on disk
cs.MaxLength(math.MaxInt)
cs.Options.HttpOnly = true
if strings.ToLower(externalHost.Scheme) == "https" {
cs.Options.Secure = true
}
cs.Options.Domain = *p.CookieDomain
cs.Options.SameSite = http.SameSiteLaxMode
a.log.WithField("dir", dir).Trace("using filesystem session backend")
return cs
}

2117
schema.yml

File diff suppressed because it is too large Load Diff

4735
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@
"tsc:execute": "tsc --noEmit -p .",
"tsc": "run-s build-locales tsc:execute",
"storybook": "storybook dev -p 6006",
"storybook:build": "storybook build",
"storybook:build": "node --max-old-space-size=4096 ./node_modules/.bin/storybook build",
"background-image": "sharp resize 2650 --mozjpeg -i src/assets/images/flow_background.jpg -o src/assets/images/flow_background.jpg"
},
"dependencies": {
@ -35,14 +35,14 @@
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.4.0",
"@fortawesome/fontawesome-free": "^6.4.2",
"@goauthentik/api": "^2023.6.1-1690455444",
"@goauthentik/api": "^2023.6.1-1691266058",
"@lit-labs/context": "^0.3.3",
"@lit-labs/task": "^3.0.0",
"@lit/localize": "^0.11.4",
"@patternfly/elements": "^2.3.2",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.61.0",
"@sentry/tracing": "^7.61.0",
"@sentry/browser": "^7.61.1",
"@sentry/tracing": "^7.61.1",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"chart.js": "^4.3.3",
@ -77,11 +77,11 @@
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-typescript": "^11.1.2",
"@storybook/addon-essentials": "^7.1.1",
"@storybook/addon-links": "^7.1.1",
"@storybook/addon-essentials": "^7.2.1",
"@storybook/addon-links": "^7.2.1",
"@storybook/blocks": "^7.1.1",
"@storybook/web-components": "^7.1.0",
"@storybook/web-components-vite": "^7.1.1",
"@storybook/web-components": "^7.2.1",
"@storybook/web-components-vite": "^7.2.1",
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@types/chart.js": "^2.9.37",
"@types/codemirror": "5.60.8",
@ -108,7 +108,7 @@
"rollup-plugin-postcss-lit": "^2.1.0",
"rollup-plugin-terser": "^7.0.2",
"sharp-cli": "^4.1.1",
"storybook": "^7.1.1",
"storybook": "^7.2.1",
"storybook-addon-mock": "^4.1.0",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.6.1",
@ -117,8 +117,8 @@
"vite-tsconfig-paths": "^4.2.0"
},
"optionalDependencies": {
"@esbuild/darwin-arm64": "^0.18.17",
"@esbuild/darwin-arm64": "^0.18.18",
"@esbuild/linux-amd64": "^0.18.11",
"@esbuild/linux-arm64": "^0.18.17"
"@esbuild/linux-arm64": "^0.18.18"
}
}

View File

@ -39,7 +39,7 @@ export class MemberSelectTable extends TableModal<User> {
columns(): TableColumn[] {
return [
new TableColumn(msg("Name"), "username"),
new TableColumn(msg("Active"), "active"),
new TableColumn(msg("Active"), "is_active"),
new TableColumn(msg("Last login"), "last_login"),
];
}

View File

@ -49,6 +49,8 @@ export class SystemTaskListPage extends TablePage<Task> {
startIndex: 1,
endIndex: tasks.length,
current: page,
next: 0,
previous: 0,
},
results: tasks,
};

View File

@ -31,7 +31,14 @@ import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";
import PFBanner from "@patternfly/patternfly/components/Banner/banner.css";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import { CapabilitiesEnum, CoreApi, Group, ResponseError, User } from "@goauthentik/api";
import {
CapabilitiesEnum,
CoreApi,
CoreUsersListTypeEnum,
Group,
ResponseError,
User,
} from "@goauthentik/api";
@customElement("ak-user-related-add")
export class RelatedUserAdd extends Form<{ users: number[] }> {
@ -127,10 +134,8 @@ export class RelatedUserList extends Table<User> {
pageSize: (await uiConfig()).pagination.perPage,
search: this.search || "",
groupsByPk: this.targetGroup ? [this.targetGroup.pk] : [],
attributes: this.hideServiceAccounts
? JSON.stringify({
"goauthentik.io/user/service-account__isnull": true,
})
type: this.hideServiceAccounts
? [CoreUsersListTypeEnum.External, CoreUsersListTypeEnum.Internal]
: undefined,
});
}
@ -138,7 +143,7 @@ export class RelatedUserList extends Table<User> {
columns(): TableColumn[] {
return [
new TableColumn(msg("Name"), "username"),
new TableColumn(msg("Active"), "active"),
new TableColumn(msg("Active"), "is_active"),
new TableColumn(msg("Last login"), "last_login"),
new TableColumn(msg("Actions")),
];

View File

@ -94,7 +94,7 @@ export class UserListPage extends TablePage<User> {
columns(): TableColumn[] {
return [
new TableColumn(msg("Name"), "username"),
new TableColumn(msg("Active"), "active"),
new TableColumn(msg("Active"), "is_active"),
new TableColumn(msg("Last login"), "last_login"),
new TableColumn(msg("Actions")),
];

View File

@ -264,7 +264,7 @@ select[multiple] option:checked {
filter: invert(1);
}
.pf-c-login__main-footer-band {
background-color: var(--ak-dark-background-lighter);
--pf-c-login__main-footer-band--BackgroundColor: var(--ak-dark-background-lighter);
color: var(--ak-dark-foreground);
}
.form-control-static {

View File

@ -47,6 +47,8 @@ export class DeleteObjectsTable<T> extends Table<T> {
totalPages: 1,
startIndex: 1,
endIndex: this.objects.length,
next: 0,
previous: 0,
},
results: this.objects,
});

View File

@ -7,7 +7,6 @@ import "@goauthentik/elements/chips/Chip";
import "@goauthentik/elements/chips/ChipGroup";
import { getURLParam, updateURLParams } from "@goauthentik/elements/router/RouteMatch";
import "@goauthentik/elements/table/TablePagination";
import { Pagination } from "@goauthentik/elements/table/TablePagination";
import "@goauthentik/elements/table/TableSearch";
import { msg } from "@lit/localize";
@ -24,6 +23,8 @@ import PFToolbar from "@patternfly/patternfly/components/Toolbar/toolbar.css";
import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { Pagination } from "@goauthentik/api";
export class TableColumn {
title: string;
orderBy?: string;

View File

@ -8,17 +8,7 @@ import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFPagination from "@patternfly/patternfly/components/Pagination/pagination.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
export interface Pagination {
next?: number;
previous?: number;
count: number;
current: number;
totalPages: number;
startIndex: number;
endIndex: number;
}
import { Pagination } from "@goauthentik/api";
@customElement("ak-table-pagination")
export class TablePagination extends AKElement {

View File

@ -28,6 +28,8 @@ export class UserDeviceList extends MFADevicesPage {
totalPages: 1,
startIndex: 1,
endIndex: res.length,
next: 0,
previous: 0,
},
results: res,
};

View File

@ -49,6 +49,8 @@ export class MFADevicesPage extends Table<Device> {
totalPages: 1,
startIndex: 1,
endIndex: devices.length,
next: 0,
previous: 0,
},
results: devices,
};

View File

@ -8,7 +8,7 @@ The most common types are:
- [**Procedural**](./procedural.md): these are How To docs, the HOW information, with step-by-step instructions for accomplishing a task. This is what most people are looking for when they open the docs... and best practice is to separate the procedural docs from long, lengthy conceptual or reference docs.
- **Conceptual**: these docs provide the WHY information, and explain when to use a feature (or when not to!), and general concepts behind the fature or functioanlity.
- **Conceptual**: these docs provide the WHY information, and explain when to use a feature (or when not to!), and general concepts behind the feature or functioanlity.
- **Reference**: this is typically tables or lists of reference information, such as configuration values, or most commmonly APIs.

View File

@ -2,9 +2,9 @@
title: "Procedural topic"
---
Use a title that focuses on the task you are writing about... for example, "Add a new Group" or "Edit user profiles". For procedural docs, there should be a verb in the tilte, and usually the noun (the thing you are working on). For the title (and all headings) use the infinitive form of the verb (i.e. "add") not the gerund form (i.e. "adding").
Use a title that focuses on the task you are writing about... for example, "Add a new Group" or "Edit user profiles". For procedural docs, there should be a verb in the title, and usually the noun (the component or object you are working on). For the title (and all headings) use the infinitive form of the verb (i.e. "add") not the gerund form (i.e. "adding").
In this first section write one or two sentences about the task. Keep it brief; if it goes on too long, then create a separate conceptual topic, in a separate `.md` file. We don't want readers to have to scroll through paragraphs of conceptual info before they get to Step 1.
In this first section, right after the title, write one or two sentences about the task. Keep it brief; if it goes on too long, then create a separate conceptual topic, in a separate `.md` file. We don't want readers to have to scroll through paragraphs of conceptual info before they get to Step 1.
## Prerequisites (optional section)
@ -16,7 +16,7 @@ If the task is quite long or complex, it might be good to add a bullet list of t
## first several group steps
If the task involves a lot of steps, try to group them into simalr steps and have a Head3 or Hedad4 title for each group.
If the task involves a lot of steps, try to group them into similar steps and have a Head3 or Head4 title for each group.
In this section, help the reader get oriented... where do they need to be (i.e. in the GUI, on a CLI, etc).
@ -34,4 +34,4 @@ Use screenshots sparingly, only for complex UIs where it is difficult to describ
## verify the steps
Whenever possible, it is useful to add verification steps at the end of a procedural topic. For example, if the procedural was about installing a product, use this section to tell them how they can verify that the install was successful
Whenever possible, it is useful to add verification steps at the end of a procedural topic. For example, if the procedural was about installing a product, use this section to tell them how they can verify that the install was successful.

View File

@ -22,11 +22,11 @@
"react-dom": "^17.0.2",
"react-feather": "^2.0.10",
"react-toggle": "^4.1.3",
"react-tooltip": "^5.19.0",
"react-tooltip": "^5.20.0",
"remark-github": "^11.2.4"
},
"devDependencies": {
"prettier": "3.0.0"
"prettier": "3.0.1"
}
},
"node_modules/@algolia/autocomplete-core": {
@ -10008,9 +10008,9 @@
}
},
"node_modules/prettier": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
"integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz",
"integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
@ -10591,9 +10591,9 @@
}
},
"node_modules/react-tooltip": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.19.0.tgz",
"integrity": "sha512-NSUk77GMpxYKHFKJVNHL++QQXRuH2QW1qDrXPtJnp2s/MJvUnU73N5TTADwDyrO2+xGlr0xHhjvQphkF60cMEA==",
"version": "5.20.0",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.20.0.tgz",
"integrity": "sha512-LWBIHEZjwDW9ZJ/Dn2xeZrsz+WKMii61CIsx2XPfs1IiIRnWyvKJXrgy6uEGOXYvrnCd4jiEvurn8Y+zJ1bw5Q==",
"dependencies": {
"@floating-ui/dom": "^1.0.0",
"classnames": "^2.3.0"
@ -20927,9 +20927,9 @@
"integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA=="
},
"prettier": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
"integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz",
"integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==",
"dev": true
},
"pretty-error": {
@ -21361,9 +21361,9 @@
}
},
"react-tooltip": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.19.0.tgz",
"integrity": "sha512-NSUk77GMpxYKHFKJVNHL++QQXRuH2QW1qDrXPtJnp2s/MJvUnU73N5TTADwDyrO2+xGlr0xHhjvQphkF60cMEA==",
"version": "5.20.0",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.20.0.tgz",
"integrity": "sha512-LWBIHEZjwDW9ZJ/Dn2xeZrsz+WKMii61CIsx2XPfs1IiIRnWyvKJXrgy6uEGOXYvrnCd4jiEvurn8Y+zJ1bw5Q==",
"requires": {
"@floating-ui/dom": "^1.0.0",
"classnames": "^2.3.0"

View File

@ -29,7 +29,7 @@
"react-dom": "^17.0.2",
"react-feather": "^2.0.10",
"react-toggle": "^4.1.3",
"react-tooltip": "^5.19.0",
"react-tooltip": "^5.20.0",
"remark-github": "^11.2.4"
},
"browserslist": {
@ -45,6 +45,6 @@
]
},
"devDependencies": {
"prettier": "3.0.0"
"prettier": "3.0.1"
}
}