Compare commits
1 Commits
docusaurus
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
3d8be6d699 |
4
.github/dependabot.yml
vendored
@ -78,13 +78,13 @@ updates:
|
||||
patterns:
|
||||
- "@goauthentik/*"
|
||||
- package-ecosystem: npm
|
||||
directory: "/docs"
|
||||
directory: "/website"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "04:00"
|
||||
open-pull-requests-limit: 10
|
||||
commit-message:
|
||||
prefix: "docs:"
|
||||
prefix: "website:"
|
||||
labels:
|
||||
- dependencies
|
||||
groups:
|
||||
|
2
.github/pull_request_template.md
vendored
@ -31,4 +31,4 @@ If changes to the frontend have been made
|
||||
If applicable
|
||||
|
||||
- [ ] The documentation has been updated
|
||||
- [ ] The documentation has been formatted (`make docs`)
|
||||
- [ ] The documentation has been formatted (`make website`)
|
||||
|
83
.github/workflows/ci-api-docs.yml
vendored
@ -1,83 +0,0 @@
|
||||
name: authentik-ci-api-docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- next
|
||||
- version-*
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- version-*
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
command:
|
||||
- prettier-check
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Dependencies
|
||||
working-directory: docs/
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
working-directory: docs/
|
||||
run: npm run ${{ matrix.command }}
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: docs/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: docs/package-lock.json
|
||||
- working-directory: docs/
|
||||
name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Build API Docs via Docusaurus
|
||||
working-directory: docs
|
||||
run: npm run build -w api
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: api-docs
|
||||
path: docs/api/build
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- lint
|
||||
- build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: api-docs
|
||||
path: docs/api/build
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: docs/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: docs/package-lock.json
|
||||
- working-directory: docs/
|
||||
name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Deploy Netlify (Production)
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
env:
|
||||
NETLIFY_SITE_ID: authentik-api-docs.netlify.app
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
working-directory: docs/api
|
||||
run: npx netlify deploy --no-build --prod
|
||||
|
||||
- name: Deploy Netlify (Preview)
|
||||
if: github.event_name == 'pull_request' || github.ref != 'refs/heads/main'
|
||||
env:
|
||||
NETLIFY_SITE_ID: authentik-api-docs.netlify.app
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
working-directory: docs/api
|
||||
run: npx netlify deploy --no-build --alias=deploy-preview-${{ github.event.number }}
|
4
.github/workflows/ci-outpost.yml
vendored
@ -24,8 +24,8 @@ jobs:
|
||||
run: |
|
||||
# Create folder structure for go embeds
|
||||
mkdir -p web/dist
|
||||
mkdir -p docs/help
|
||||
touch web/dist/test docs/help/test
|
||||
mkdir -p website/help
|
||||
touch web/dist/test website/help/test
|
||||
- name: Generate API
|
||||
run: make gen-client-go
|
||||
- name: golangci-lint
|
||||
|
@ -1,4 +1,4 @@
|
||||
name: authentik-ci-docs
|
||||
name: authentik-ci-website
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -18,47 +18,50 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
command:
|
||||
- lint:lockfile
|
||||
- prettier-check
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
working-directory: docs/
|
||||
- working-directory: website/
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
working-directory: docs/
|
||||
working-directory: website/
|
||||
run: npm run ${{ matrix.command }}
|
||||
build-topics:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: docs/package.json
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: docs/package-lock.json
|
||||
- working-directory: docs/
|
||||
name: Install Dependencies
|
||||
cache-dependency-path: website/package-lock.json
|
||||
- working-directory: website/
|
||||
run: npm ci
|
||||
- name: Build Documentation via Docusaurus
|
||||
working-directory: docs/
|
||||
run: npm run build
|
||||
build-integrations:
|
||||
- name: test
|
||||
working-directory: website/
|
||||
run: npm test
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: ${{ matrix.job }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
- build
|
||||
- build:integrations
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: docs/package.json
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: docs/package-lock.json
|
||||
- working-directory: docs/
|
||||
name: Install Dependencies
|
||||
cache-dependency-path: website/package-lock.json
|
||||
- working-directory: website/
|
||||
run: npm ci
|
||||
- name: Build Integrations via Docusaurus
|
||||
working-directory: docs/
|
||||
run: npm run build -w integrations
|
||||
- name: build
|
||||
working-directory: website/
|
||||
run: npm run ${{ matrix.job }}
|
||||
build-container:
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
@ -95,7 +98,7 @@ jobs:
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
tags: ${{ steps.ev.outputs.imageTags }}
|
||||
file: docs/Dockerfile
|
||||
file: website/Dockerfile
|
||||
push: ${{ steps.ev.outputs.shouldPush == 'true' }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
@ -108,12 +111,12 @@ jobs:
|
||||
subject-name: ${{ steps.ev.outputs.attestImageNames }}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
ci-docs-mark:
|
||||
ci-website-mark:
|
||||
if: always()
|
||||
needs:
|
||||
- lint
|
||||
- build-topics
|
||||
- build-integrations
|
||||
- test
|
||||
- build
|
||||
- build-container
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
2
.github/workflows/release-publish.yml
vendored
@ -52,7 +52,7 @@ jobs:
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
tags: ${{ steps.ev.outputs.imageTags }}
|
||||
file: docs/Dockerfile
|
||||
file: website/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
|
@ -10,7 +10,7 @@ coverage
|
||||
dist
|
||||
out
|
||||
.docusaurus
|
||||
docs/api/reference
|
||||
website/docs/developer-docs/api/**/*
|
||||
|
||||
## Environment
|
||||
*.env
|
||||
|
44
.vscode/tasks.json
vendored
@ -4,7 +4,12 @@
|
||||
{
|
||||
"label": "authentik/core: make",
|
||||
"command": "uv",
|
||||
"args": ["run", "make", "lint-fix", "lint"],
|
||||
"args": [
|
||||
"run",
|
||||
"make",
|
||||
"lint-fix",
|
||||
"lint"
|
||||
],
|
||||
"presentation": {
|
||||
"panel": "new"
|
||||
},
|
||||
@ -13,7 +18,11 @@
|
||||
{
|
||||
"label": "authentik/core: run",
|
||||
"command": "uv",
|
||||
"args": ["run", "ak", "server"],
|
||||
"args": [
|
||||
"run",
|
||||
"ak",
|
||||
"server"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
@ -23,13 +32,17 @@
|
||||
{
|
||||
"label": "authentik/web: make",
|
||||
"command": "make",
|
||||
"args": ["web"],
|
||||
"args": [
|
||||
"web"
|
||||
],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "authentik/web: watch",
|
||||
"command": "make",
|
||||
"args": ["web-watch"],
|
||||
"args": [
|
||||
"web-watch"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
@ -39,19 +52,26 @@
|
||||
{
|
||||
"label": "authentik: install",
|
||||
"command": "make",
|
||||
"args": ["install", "-j4"],
|
||||
"args": [
|
||||
"install",
|
||||
"-j4"
|
||||
],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "authentik/docs: make",
|
||||
"label": "authentik/website: make",
|
||||
"command": "make",
|
||||
"args": ["docs"],
|
||||
"args": [
|
||||
"website"
|
||||
],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "authentik/docs: watch",
|
||||
"label": "authentik/website: watch",
|
||||
"command": "make",
|
||||
"args": ["docs-watch"],
|
||||
"args": [
|
||||
"website-watch"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
@ -61,7 +81,11 @@
|
||||
{
|
||||
"label": "authentik/api: generate",
|
||||
"command": "uv",
|
||||
"args": ["run", "make", "gen"],
|
||||
"args": [
|
||||
"run",
|
||||
"make",
|
||||
"gen"
|
||||
],
|
||||
"group": "build"
|
||||
}
|
||||
]
|
||||
|
@ -32,8 +32,8 @@ tests/wdio/ @goauthentik/frontend
|
||||
locale/ @goauthentik/backend @goauthentik/frontend
|
||||
web/xliff/ @goauthentik/backend @goauthentik/frontend
|
||||
# Docs & Website
|
||||
docs/ @goauthentik/docs
|
||||
website/ @goauthentik/docs
|
||||
CODE_OF_CONDUCT.md @goauthentik/docs
|
||||
# Security
|
||||
SECURITY.md @goauthentik/security @goauthentik/docs
|
||||
docs/security/ @goauthentik/security @goauthentik/docs
|
||||
website/docs/security/ @goauthentik/security @goauthentik/docs
|
||||
|
@ -18,7 +18,7 @@ RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
|
||||
|
||||
COPY ./package.json /work
|
||||
COPY ./web /work/web/
|
||||
COPY ./docs /work/docs/
|
||||
COPY ./website /work/website/
|
||||
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
||||
|
||||
RUN npm run build && \
|
||||
|
2
LICENSE
@ -1,7 +1,7 @@
|
||||
Copyright (c) 2023 Jens Langhammer
|
||||
|
||||
Portions of this software are licensed as follows:
|
||||
* All content residing under the "docs/" directory of this repository is licensed under "Creative Commons: CC BY-SA 4.0 license".
|
||||
* All content residing under the "website/" directory of this repository is licensed under "Creative Commons: CC BY-SA 4.0 license".
|
||||
* All content that resides under the "authentik/enterprise/" directory of this repository, if that directory exists, is licensed under the license defined in "authentik/enterprise/LICENSE".
|
||||
* All client-side JavaScript (when served directly or after being compiled, arranged, augmented, or combined), is licensed under the "MIT Expat" license.
|
||||
* All third party components incorporated into the authentik are licensed under the original license provided by the owner of the applicable component.
|
||||
|
26
Makefile
@ -1,4 +1,4 @@
|
||||
.PHONY: gen dev-reset all clean test web docs
|
||||
.PHONY: gen dev-reset all clean test web website
|
||||
|
||||
SHELL := /usr/bin/env bash
|
||||
.SHELLFLAGS += ${SHELLFLAGS} -e -o pipefail
|
||||
@ -70,10 +70,10 @@ core-i18n-extract:
|
||||
--ignore internal \
|
||||
--ignore ${GEN_API_TS} \
|
||||
--ignore ${GEN_API_GO} \
|
||||
--ignore docs \
|
||||
--ignore website \
|
||||
-l en
|
||||
|
||||
install: web-install docs-install core-install ## Install all requires dependencies for `web`, `docs` and `core`
|
||||
install: web-install website-install core-install ## Install all requires dependencies for `web`, `website` and `core`
|
||||
|
||||
dev-drop-db:
|
||||
dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
|
||||
@ -221,22 +221,22 @@ web-i18n-extract:
|
||||
cd web && npm run extract-locales
|
||||
|
||||
#########################
|
||||
## Docs
|
||||
## Website
|
||||
#########################
|
||||
|
||||
docs: docs-lint-fix docs-build ## Automatically fix formatting issues in the Authentik docs source code, lint the code, and compile it
|
||||
website: website-lint-fix website-build ## Automatically fix formatting issues in the Authentik website/docs source code, lint the code, and compile it
|
||||
|
||||
docs-install:
|
||||
npm ci --prefix docs
|
||||
website-install:
|
||||
cd website && npm ci
|
||||
|
||||
docs-lint-fix: lint-codespell
|
||||
npm run prettier --prefix docs
|
||||
website-lint-fix: lint-codespell
|
||||
cd website && npm run prettier
|
||||
|
||||
docs-build:
|
||||
npm run build --prefix docs
|
||||
website-build:
|
||||
cd website && npm run build
|
||||
|
||||
docs-watch: ## Build and watch the documentation website, updating automatically
|
||||
npm run watch --prefix docs
|
||||
website-watch: ## Build and watch the documentation website, updating automatically
|
||||
cd website && npm run watch
|
||||
|
||||
#########################
|
||||
## Docker
|
||||
|
@ -8,12 +8,12 @@
|
||||
# make gen-dev-config
|
||||
# ```
|
||||
#
|
||||
# You may edit the generated file to override the configuration below.
|
||||
# You may edit the generated file to override the configuration below.
|
||||
#
|
||||
# When making modifying the default configuration file,
|
||||
# When making modifying the default configuration file,
|
||||
# ensure that the corresponding documentation is updated to match.
|
||||
#
|
||||
# @see {@link ../../docs/topics/install-config/configuration/configuration.mdx Configuration documentation} for more information.
|
||||
# @see {@link ../../website/docs/install-config/configuration/configuration.mdx Configuration documentation} for more information.
|
||||
|
||||
postgresql:
|
||||
host: localhost
|
||||
|
@ -1,9 +0,0 @@
|
||||
[production]
|
||||
> 0.2%
|
||||
not dead
|
||||
not op_mini all
|
||||
|
||||
[development]
|
||||
last 1 chrome version
|
||||
last 1 firefox version
|
||||
last 1 safari version
|
@ -1,20 +0,0 @@
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-slim AS docs-builder
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
WORKDIR /work/docs
|
||||
|
||||
COPY ./docs/package.json ./docs/package-lock.json /work/docs/
|
||||
|
||||
RUN npm ci --include=dev
|
||||
|
||||
COPY ./docs /work/docs/
|
||||
COPY ./blueprints /work/blueprints/
|
||||
COPY ./schema.yml /work/
|
||||
COPY ./SECURITY.md /work/
|
||||
|
||||
RUN npm run build
|
||||
|
||||
FROM docker.io/library/nginx:1.29.0
|
||||
|
||||
COPY --from=docs-builder /work/docs/topics/build /usr/share/nginx/html
|
@ -1,18 +0,0 @@
|
||||
---
|
||||
title: Authentication
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
For any of the token-based methods, set the `Authorization` header to `Bearer <token>`.
|
||||
|
||||
### Session
|
||||
|
||||
When authenticating with a flow, you'll get an authenticated Session cookie, that can be used for authentication. Keep in mind that in this context, a CSRF header is also required.
|
||||
|
||||
### API Token
|
||||
|
||||
Users can create tokens to authenticate as any user with a static key, which can optionally be expiring and auto-rotate.
|
||||
|
||||
### JWT Token
|
||||
|
||||
OAuth2 clients can request the scope `goauthentik.io/api`, which allows their OAuth Access token to be used to authenticate to the API.
|
@ -1,15 +0,0 @@
|
||||
---
|
||||
title: API Client Overview
|
||||
---
|
||||
|
||||
import DocCardList from "@theme/DocCardList";
|
||||
|
||||
These API clients are officially supported and maintained.
|
||||
|
||||
:::info
|
||||
|
||||
These API clients are primarily built around creating/updating/deleting configuration objects in authentik, and in most cases can **not** be used to implemented SSO into your application.
|
||||
|
||||
:::
|
||||
|
||||
<DocCardList />
|
@ -1,17 +0,0 @@
|
||||
---
|
||||
title: Go API Client
|
||||
sidebar_label: Golang
|
||||
description: A Golang client for the authentik API.
|
||||
---
|
||||
|
||||
The [Go API client](https://pkg.go.dev/goauthentik.io/api/v3) is generated using the [OpenAPI Generator](https://openapi-generator.tech/) and the [OpenAPI v3 schema](https://docs.goauthentik.io/schema.yml).
|
||||
|
||||
```bash
|
||||
go get goauthentik.io/api/v3
|
||||
```
|
||||
|
||||
## Building the Go Client
|
||||
|
||||
The Go client is used by the Outpost to communicate with the backend authentik server. To build the go client, run `make gen-client-go`.
|
||||
|
||||
The generated files are stored in `/gen-go-api` in the root of the repository.
|
@ -1,33 +0,0 @@
|
||||
---
|
||||
title: Node.js API Client
|
||||
sidebar_label: Node.js
|
||||
description: A TypeScript client for the authentik API.
|
||||
---
|
||||
|
||||
The [Node.js API client](https://www.npmjs.com/package/@goauthentik/api) is generated using the [OpenAPI Generator](https://openapi-generator.tech/) and the [OpenAPI v3 schema](https://docs.goauthentik.io/schema.yml).
|
||||
|
||||
```bash npm2yarn
|
||||
npm install @goauthentik/api
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { AdminApi, Configuration } from "@goauthentik/api";
|
||||
|
||||
const config = new Configuration({
|
||||
basePath: "authentik.company/api/v3",
|
||||
});
|
||||
|
||||
const status = await new AdminApi(DEFAULT_CONFIG).adminSystemRetrieve();
|
||||
```
|
||||
|
||||
## Building the Node.js Client
|
||||
|
||||
The web client is used by the web-interface and web-FlowExecutor to communicate with authentik. To build the client, run `make gen-client-ts`.
|
||||
|
||||
Since the client is normally distributed as an npm package, running `make gen-client-ts` will overwrite the locally installed client with the newly built one.
|
||||
|
||||
:::caution
|
||||
Running `npm i` in the `/web` folder after using `make gen-client-ts` will overwrite the custom client and revert to the upstream client.
|
||||
:::
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
title: Python API Client
|
||||
sidebar_label: Python
|
||||
description: A Python client for the authentik API.
|
||||
---
|
||||
|
||||
The [Python API client](https://pypi.org/project/authentik-client/) is generated using the [OpenAPI Generator](https://openapi-generator.tech/) and the [OpenAPI v3 schema](https://docs.goauthentik.io/schema.yml).
|
||||
|
||||
```bash
|
||||
pip install authentik-client
|
||||
# Or
|
||||
uv pip install authentik-client
|
||||
```
|
@ -1 +0,0 @@
|
||||
module.exports = import("./docusaurus.config.esm.mjs").then(($) => $.default);
|
@ -1,161 +0,0 @@
|
||||
/**
|
||||
* @file Docusaurus config.
|
||||
*
|
||||
* @import { Config } from "@docusaurus/types";
|
||||
* @import { UserThemeConfig, UserThemeConfigExtra } from "@goauthentik/docusaurus-config";
|
||||
* @import { Options as DocsPluginOptions } from "@docusaurus/plugin-content-docs";
|
||||
* @import * as OpenApiPlugin from "docusaurus-plugin-openapi-docs";
|
||||
*/
|
||||
import { createDocusaurusConfig } from "@goauthentik/docusaurus-config";
|
||||
import { remarkLinkRewrite } from "@goauthentik/docusaurus-theme/remark";
|
||||
|
||||
import { GlobExcludeDefault } from "@docusaurus/utils";
|
||||
import { createApiPageMD } from "docusaurus-plugin-openapi-docs/lib/markdown/index.js";
|
||||
import { cp } from "node:fs/promises";
|
||||
import { createRequire } from "node:module";
|
||||
import { basename, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { gzip } from "pako";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
|
||||
const rootStaticDirectory = resolve(__dirname, "..", "static");
|
||||
|
||||
//#region Copy static files
|
||||
|
||||
const authentikModulePath = resolve(__dirname, "..", "..");
|
||||
|
||||
const files = [
|
||||
resolve(authentikModulePath, "docker-compose.yml"),
|
||||
resolve(authentikModulePath, "schema.yml"),
|
||||
];
|
||||
|
||||
await Promise.all(
|
||||
files.map((file) => {
|
||||
const fileName = basename(file);
|
||||
const destPath = resolve(rootStaticDirectory, fileName);
|
||||
return cp(file, destPath, {
|
||||
recursive: true,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Configuration
|
||||
|
||||
//#region Configuration
|
||||
|
||||
/**
|
||||
* Documentation site configuration for Docusaurus.
|
||||
* @satisfies {Partial<Config>}
|
||||
*/
|
||||
const config = {
|
||||
staticDirectories: [
|
||||
// ---
|
||||
"static",
|
||||
rootStaticDirectory,
|
||||
],
|
||||
|
||||
onBrokenAnchors: "ignore",
|
||||
onBrokenLinks: "ignore",
|
||||
onBrokenMarkdownLinks: "ignore",
|
||||
onDuplicateRoutes: "ignore",
|
||||
|
||||
themes: ["@docusaurus/theme-mermaid", "docusaurus-theme-openapi-docs"],
|
||||
|
||||
themeConfig: /** @type {UserThemeConfig & UserThemeConfigExtra} */ ({
|
||||
navbarReplacements: {
|
||||
DOCS_URL: "/",
|
||||
},
|
||||
docs: {
|
||||
sidebar: {
|
||||
hideable: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
plugins: [
|
||||
[
|
||||
"@docusaurus/theme-classic",
|
||||
{
|
||||
customCss: require.resolve("@goauthentik/docusaurus-config/css/index.css"),
|
||||
},
|
||||
],
|
||||
|
||||
//#region Docs Content Plugin
|
||||
|
||||
[
|
||||
"@docusaurus/plugin-content-docs",
|
||||
/** @type {DocsPluginOptions} */ ({
|
||||
showLastUpdateAuthor: false,
|
||||
showLastUpdateTime: false,
|
||||
numberPrefixParser: false,
|
||||
id: "docs",
|
||||
routeBasePath: "/",
|
||||
path: ".",
|
||||
exclude: [...GlobExcludeDefault],
|
||||
include: ["**/*.mdx", "**/*.md"],
|
||||
sidebarPath: "./sidebar.mjs",
|
||||
docItemComponent: "@theme/ApiItem",
|
||||
beforeDefaultRemarkPlugins: [
|
||||
remarkLinkRewrite([
|
||||
// ---
|
||||
["/integrations", "https://integrations.goauthentik.io"],
|
||||
["/docs", "https://docs.goauthentik.io"],
|
||||
]),
|
||||
],
|
||||
}),
|
||||
],
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region OpenAPI Docs Plugin
|
||||
[
|
||||
"docusaurus-plugin-openapi-docs",
|
||||
{
|
||||
id: "open-api-docs",
|
||||
docsPluginId: "docs",
|
||||
config: {
|
||||
authentik: /** @type {OpenApiPlugin.Options} */ ({
|
||||
specPath: resolve("..", "..", "schema.yml"),
|
||||
outputDir: "./reference",
|
||||
hideSendButton: true,
|
||||
disableCompression: true,
|
||||
sidebarOptions: {
|
||||
groupPathsBy: "tag",
|
||||
},
|
||||
template: "src/templates/api.mustache",
|
||||
markdownGenerators: {
|
||||
createApiPageMD: (pageData) => {
|
||||
const {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
info,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
postman,
|
||||
...coreAPI
|
||||
} = pageData.api;
|
||||
|
||||
return [
|
||||
createApiPageMD(pageData),
|
||||
`export const api = "${btoa(
|
||||
String.fromCharCode(
|
||||
...gzip(JSON.stringify(coreAPI), {
|
||||
level: 9,
|
||||
}),
|
||||
),
|
||||
)}";`,
|
||||
].join("\n");
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
//#endregion
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
export default createDocusaurusConfig(config);
|
@ -1,11 +0,0 @@
|
||||
import { createRequire } from "node:module";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
try {
|
||||
require.resolve("#reference/sidebar");
|
||||
} catch (_error) {
|
||||
console.error(
|
||||
"\n⛔️ API Reference sidebar not found.\n\nRun `npm run build:api` to generate files.",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
---
|
||||
title: API Overview
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
Our API reference documentation is generated from the [OpenAPI v3 schema](https://docs.goauthentik.io/schema.yml).
|
||||
|
||||
You can also access your installation's own, instance-specific API Browser. Starting with 2021.3.5, every authentik instance has a built-in API browser, which can be accessed at <code>https://<em>authentik.company</em>/api/v3/</code>.
|
||||
|
||||
To generate an API client you can use the OpenAPI v3 schema at <code>https://<em>authentik.company</em>/api/v3/schema/</code>.
|
||||
|
||||
## Making schema changes
|
||||
|
||||
Some backend changes might require new/different fields or remove other fields. To create a new schema after changing a Serializer, run `make gen-build`.
|
||||
|
||||
This will update the `schema.yml` file in the root of the repository.
|
@ -1,30 +0,0 @@
|
||||
[[plugins]]
|
||||
package = "netlify-plugin-cache"
|
||||
|
||||
[plugins.inputs]
|
||||
paths = [".docusaurus", ".cache", 'node_modules/.cache']
|
||||
|
||||
[[plugins]]
|
||||
package = "netlify-plugin-debug-cache"
|
||||
|
||||
[build]
|
||||
base = "docs"
|
||||
package = "api"
|
||||
command = "npm run build -w api"
|
||||
publish = "api/build"
|
||||
|
||||
[dev]
|
||||
command = "npm start"
|
||||
targetPort = 3000
|
||||
publish = "api/build"
|
||||
|
||||
[context.production.environment]
|
||||
NODE_ENV = "production"
|
||||
|
||||
[context.dev.environment]
|
||||
NODE_ENV = "development"
|
||||
|
||||
[[headers]]
|
||||
for = "/*"
|
||||
[headers.values]
|
||||
X-Frame-Options = "DENY"
|
@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "@goauthentik/api-docs",
|
||||
"version": "0.0.0",
|
||||
"description": "API Documentation",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "run-s build:api build:types build:docusaurus",
|
||||
"build:api": "docusaurus gen-api-docs all",
|
||||
"build:docusaurus": "docusaurus build",
|
||||
"build:types": "tsc -b .",
|
||||
"deploy": "docusaurus deploy",
|
||||
"docusaurus": "docusaurus",
|
||||
"serve": "docusaurus serve",
|
||||
"start": "docusaurus start",
|
||||
"swizzle": "docusaurus swizzle"
|
||||
},
|
||||
"imports": {
|
||||
"#reference/sidebar": "./reference/sidebar.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@goauthentik/docusaurus-theme": "*"
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/**
|
||||
* @file Sidebar configuration for documentation entries.
|
||||
*
|
||||
* @import { SidebarItemConfig } from "@docusaurus/plugin-content-docs/src/sidebars/types.js"
|
||||
*/
|
||||
import "./ensure-reference-sidebar.mjs";
|
||||
|
||||
// No file extensions for Docusaurus's automatic resolution.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore - Allows for project-wide type checking when partially building docs.
|
||||
import apiReference from "./reference/sidebar";
|
||||
|
||||
const DOCS_URL = process.env.DOCS_URL || "https://docs.goauthentik.io";
|
||||
|
||||
/**
|
||||
* @type {SidebarItemConfig}
|
||||
*/
|
||||
const sidebar = {
|
||||
reference: [
|
||||
{
|
||||
type: "link",
|
||||
label: "← Back to Developer Docs",
|
||||
href: new URL("/developer-docs", DOCS_URL).href,
|
||||
className: "navbar-sidebar__upwards",
|
||||
},
|
||||
{
|
||||
type: "doc",
|
||||
label: "API Overview",
|
||||
className: "api-overview",
|
||||
id: "index",
|
||||
},
|
||||
|
||||
{
|
||||
type: "category",
|
||||
label: "Clients",
|
||||
collapsed: false,
|
||||
collapsible: false,
|
||||
link: {
|
||||
type: "doc",
|
||||
id: "clients",
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: "autogenerated",
|
||||
dirName: "clients",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
label: "API Reference",
|
||||
className: "api-reference",
|
||||
collapsed: false,
|
||||
collapsible: false,
|
||||
link: {
|
||||
type: "doc",
|
||||
id: apiReference[0].id,
|
||||
},
|
||||
|
||||
items: apiReference.slice(1),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default sidebar;
|
@ -1,25 +0,0 @@
|
||||
---
|
||||
id: {{{id}}}
|
||||
title: "{{{title}}}"
|
||||
description: "{{{frontMatter.description}}}"
|
||||
{{^api}}
|
||||
sidebar_label: Introduction
|
||||
sidebar_position: 0
|
||||
{{/api}}
|
||||
hide_title: true
|
||||
{{#api}}
|
||||
hide_table_of_contents: true
|
||||
{{/api}}
|
||||
{{#json}}
|
||||
api: true
|
||||
{{/json}}
|
||||
{{#api.method}}
|
||||
sidebar_class_name: "{{{api.method}}} api-method"
|
||||
{{/api.method}}
|
||||
{{#infoPath}}
|
||||
info_path: {{{infoPath}}}
|
||||
{{/infoPath}}
|
||||
hide_send_button: true
|
||||
---
|
||||
|
||||
{{{markdown}}}
|
@ -1,75 +0,0 @@
|
||||
import { useDoc } from "@docusaurus/plugin-content-docs/client";
|
||||
import { useWindowSize } from "@docusaurus/theme-common";
|
||||
import type { Props } from "@theme/ApiItem/Layout";
|
||||
import ContentVisibility from "@theme/ContentVisibility";
|
||||
import DocBreadcrumbs from "@theme/DocBreadcrumbs";
|
||||
import DocItemContent from "@theme/DocItem/Content";
|
||||
import DocItemFooter from "@theme/DocItem/Footer";
|
||||
import DocItemPaginator from "@theme/DocItem/Paginator";
|
||||
import DocItemTOCDesktop from "@theme/DocItem/TOC/Desktop";
|
||||
import DocItemTOCMobile from "@theme/DocItem/TOC/Mobile";
|
||||
import DocVersionBadge from "@theme/DocVersionBadge";
|
||||
import DocVersionBanner from "@theme/DocVersionBanner";
|
||||
import clsx from "clsx";
|
||||
import React, { type JSX } from "react";
|
||||
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
/**
|
||||
* Decide if the toc should be rendered, on mobile or desktop viewports
|
||||
*/
|
||||
function useDocTOC() {
|
||||
const { frontMatter, toc } = useDoc();
|
||||
const windowSize = useWindowSize();
|
||||
|
||||
const hidden = frontMatter.hide_table_of_contents;
|
||||
const canRender = !hidden && toc.length > 0;
|
||||
|
||||
const mobile = canRender ? <DocItemTOCMobile /> : undefined;
|
||||
|
||||
const desktop =
|
||||
canRender && (windowSize === "desktop" || windowSize === "ssr") ? (
|
||||
<DocItemTOCDesktop />
|
||||
) : undefined;
|
||||
|
||||
return {
|
||||
hidden,
|
||||
mobile,
|
||||
desktop,
|
||||
};
|
||||
}
|
||||
|
||||
export default function DocItemLayout({ children }: Props): JSX.Element {
|
||||
const docTOC = useDocTOC();
|
||||
const { metadata, frontMatter } = useDoc() as DocContextValue;
|
||||
const { api, schema } = frontMatter;
|
||||
|
||||
return (
|
||||
<div className="row">
|
||||
<div className={clsx("col", !docTOC.hidden && styles.docItemCol)}>
|
||||
<ContentVisibility metadata={metadata} />
|
||||
<DocVersionBanner />
|
||||
<div className={styles.docItemContainer}>
|
||||
<article>
|
||||
<DocBreadcrumbs />
|
||||
<DocVersionBadge />
|
||||
{docTOC.mobile}
|
||||
<DocItemContent>{children}</DocItemContent>
|
||||
<div className="row">
|
||||
<div className={clsx("col", api || schema ? "col--7" : "col--12")}>
|
||||
<DocItemFooter />
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<div className="row">
|
||||
<div className={clsx("col", api || schema ? "col--7" : "col--12")}>
|
||||
<DocItemPaginator />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{docTOC.desktop ? <div className="col col--3">{docTOC.desktop}</div> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
.docItemContainer header + *,
|
||||
.docItemContainer article > *:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 997px) {
|
||||
.docItemCol {
|
||||
max-width: 75% !important;
|
||||
}
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
import BrowserOnly from "@docusaurus/BrowserOnly";
|
||||
import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
|
||||
import { DocProvider } from "@docusaurus/plugin-content-docs/client";
|
||||
import { HtmlClassNameProvider } from "@docusaurus/theme-common";
|
||||
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
||||
import useIsBrowser from "@docusaurus/useIsBrowser";
|
||||
import type { ApiExplorerProps } from "@theme/APIExplorer";
|
||||
import { createAuth } from "@theme/ApiExplorer/Authorization/slice";
|
||||
import { createPersistanceMiddleware } from "@theme/ApiExplorer/persistanceMiddleware";
|
||||
import DocItemLayout from "@theme/ApiItem/Layout";
|
||||
import CodeBlock from "@theme/CodeBlock";
|
||||
import DocItemMetadata from "@theme/DocItem/Metadata";
|
||||
import SkeletonLoader from "@theme/SkeletonLoader";
|
||||
import clsx from "clsx";
|
||||
import { ParameterObject, ServerObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
|
||||
import type { ApiItem as ApiItemType } from "docusaurus-plugin-openapi-docs/src/types";
|
||||
import type { ThemeConfig } from "docusaurus-theme-openapi-docs/src/types";
|
||||
import { ungzip } from "pako";
|
||||
import React from "react";
|
||||
import { Provider } from "react-redux";
|
||||
|
||||
import { APIStore, createStoreWithState, createStoreWithoutState } from "./store";
|
||||
|
||||
let ApiExplorer: React.FC<ApiExplorerProps> = () => <div />;
|
||||
|
||||
if (ExecutionEnvironment.canUseDOM) {
|
||||
// @ts-expect-error - Dynamic import
|
||||
ApiExplorer = await import("@theme/ApiExplorer").then((mod) => mod.default);
|
||||
}
|
||||
|
||||
function base64ToUint8Array(base64: string) {
|
||||
const binary = atob(base64);
|
||||
const len = binary.length;
|
||||
const bytes = new Uint8Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function decodeAPI(encodedAPI: string): ApiItemType | null {
|
||||
try {
|
||||
return JSON.parse(
|
||||
ungzip(base64ToUint8Array(encodedAPI), {
|
||||
to: "string",
|
||||
}),
|
||||
);
|
||||
} catch (_error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface APIItemSchemeProps {
|
||||
content: PropDocContent;
|
||||
}
|
||||
|
||||
const APIItemScheme: React.FC<APIItemSchemeProps> = (props) => {
|
||||
const MDXComponent = props.content;
|
||||
const docHtmlClassName = `docs-doc-id-${props.content.metadata.id}`;
|
||||
|
||||
const { frontMatter } = MDXComponent;
|
||||
const { sample } = frontMatter;
|
||||
|
||||
return (
|
||||
<DocProvider content={props.content}>
|
||||
<HtmlClassNameProvider className={docHtmlClassName}>
|
||||
<DocItemMetadata />
|
||||
<DocItemLayout>
|
||||
<div className={clsx("row", "theme-api-markdown")}>
|
||||
<div className="col col--7 openapi-left-panel__container schema">
|
||||
<MDXComponent />
|
||||
</div>
|
||||
<div className="col col--5 openapi-right-panel__container">
|
||||
{sample ? (
|
||||
<CodeBlock language="json" title={`${frontMatter.title}`}>
|
||||
{JSON.stringify(sample, null, 2)}
|
||||
</CodeBlock>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</DocItemLayout>
|
||||
</HtmlClassNameProvider>
|
||||
</DocProvider>
|
||||
);
|
||||
};
|
||||
|
||||
interface APIItemAPIProps {
|
||||
content: PropDocContent;
|
||||
api: ApiItemType;
|
||||
}
|
||||
|
||||
const APIItemAPI: React.FC<APIItemAPIProps> = ({ content: MDXComponent, api }) => {
|
||||
const docHtmlClassName = `docs-doc-id-${MDXComponent.metadata.id}`;
|
||||
|
||||
const frontMatter = MDXComponent.frontMatter;
|
||||
|
||||
const { siteConfig } = useDocusaurusContext();
|
||||
const themeConfig = siteConfig.themeConfig as ThemeConfig;
|
||||
const options = themeConfig.api;
|
||||
const isBrowser = useIsBrowser();
|
||||
|
||||
// Regex for 2XX status
|
||||
const statusRegex = new RegExp("(20[0-9]|2[1-9][0-9])");
|
||||
|
||||
let store: APIStore;
|
||||
const persistanceMiddleware = createPersistanceMiddleware(options);
|
||||
|
||||
// Init store for SSR
|
||||
if (!isBrowser) {
|
||||
store = createStoreWithoutState({}, [persistanceMiddleware]);
|
||||
} else {
|
||||
// Init store for CSR to hydrate components
|
||||
// Create list of only 2XX response content types to create request samples from
|
||||
const acceptArrayInit: string[][] = [];
|
||||
for (const [code, content] of Object.entries(api.responses ?? [])) {
|
||||
if (statusRegex.test(code)) {
|
||||
acceptArrayInit.push(Object.keys(content.content ?? {}));
|
||||
}
|
||||
}
|
||||
const acceptArray = acceptArrayInit.flat();
|
||||
|
||||
const content = api.requestBody?.content ?? {};
|
||||
const contentTypeArray = Object.keys(content);
|
||||
const servers = api.servers ?? [];
|
||||
const params = {
|
||||
path: [] as ParameterObject[],
|
||||
query: [] as ParameterObject[],
|
||||
header: [] as ParameterObject[],
|
||||
cookie: [] as ParameterObject[],
|
||||
};
|
||||
|
||||
api.parameters?.forEach((param: { in: "path" | "query" | "header" | "cookie" }) => {
|
||||
const paramType = param.in;
|
||||
const paramsArray: ParameterObject[] = params[paramType];
|
||||
paramsArray.push(param as ParameterObject);
|
||||
});
|
||||
|
||||
const auth = createAuth({
|
||||
security: api.security,
|
||||
securitySchemes: api.securitySchemes,
|
||||
options,
|
||||
});
|
||||
|
||||
const server = window?.sessionStorage.getItem("server");
|
||||
const serverObject = (JSON.parse(server!) as ServerObject) ?? {};
|
||||
|
||||
store = createStoreWithState(
|
||||
{
|
||||
accept: {
|
||||
value: acceptArray[0],
|
||||
options: acceptArray,
|
||||
},
|
||||
contentType: {
|
||||
value: contentTypeArray[0],
|
||||
options: contentTypeArray,
|
||||
},
|
||||
server: {
|
||||
value: serverObject.url ? serverObject : undefined,
|
||||
options: servers,
|
||||
},
|
||||
response: { value: undefined },
|
||||
body: { type: "empty" },
|
||||
params,
|
||||
auth,
|
||||
},
|
||||
[persistanceMiddleware],
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DocProvider content={MDXComponent}>
|
||||
<HtmlClassNameProvider className={docHtmlClassName}>
|
||||
<DocItemMetadata />
|
||||
<DocItemLayout>
|
||||
<Provider store={store}>
|
||||
<div className={clsx("row", "theme-api-markdown")}>
|
||||
<div className="col col--7 openapi-left-panel__container">
|
||||
<MDXComponent />
|
||||
</div>
|
||||
<div className="col col--5 openapi-right-panel__container">
|
||||
<BrowserOnly fallback={<SkeletonLoader size="lg" />}>
|
||||
{() => {
|
||||
return (
|
||||
<ApiExplorer
|
||||
item={api}
|
||||
infoPath={frontMatter.info_path}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</BrowserOnly>
|
||||
</div>
|
||||
</div>
|
||||
</Provider>
|
||||
</DocItemLayout>
|
||||
</HtmlClassNameProvider>
|
||||
</DocProvider>
|
||||
);
|
||||
};
|
||||
|
||||
interface APIItemProps {
|
||||
content: PropDocContent;
|
||||
}
|
||||
|
||||
const ApiItem: React.FC<APIItemProps> = ({ content: MDXComponent }) => {
|
||||
const frontMatter = MDXComponent.frontMatter;
|
||||
|
||||
if (frontMatter.schema) {
|
||||
return <APIItemScheme content={MDXComponent} />;
|
||||
}
|
||||
|
||||
if (!MDXComponent.api) {
|
||||
// Non-API docs
|
||||
return (
|
||||
<DocProvider content={MDXComponent}>
|
||||
<HtmlClassNameProvider className={`docs-doc-id-${MDXComponent.metadata.id}`}>
|
||||
<DocItemMetadata />
|
||||
<DocItemLayout>
|
||||
<div className="row">
|
||||
<div className="col col--12 markdown">
|
||||
<MDXComponent />
|
||||
</div>
|
||||
</div>
|
||||
</DocItemLayout>
|
||||
</HtmlClassNameProvider>
|
||||
</DocProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<BrowserOnly fallback={<SkeletonLoader size="lg" />}>
|
||||
{() => {
|
||||
const api = decodeAPI(MDXComponent.api!);
|
||||
|
||||
if (!api) {
|
||||
console.error("Failed to decode API", frontMatter);
|
||||
throw new Error("Failed to decode API");
|
||||
}
|
||||
|
||||
return <APIItemAPI content={MDXComponent} api={api} />;
|
||||
}}
|
||||
</BrowserOnly>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApiItem;
|
@ -1,44 +0,0 @@
|
||||
import { combineReducers, configureStore } from "@reduxjs/toolkit";
|
||||
import { Middleware } from "@reduxjs/toolkit";
|
||||
import accept from "@theme/ApiExplorer/Accept/slice";
|
||||
import auth from "@theme/ApiExplorer/Authorization/slice";
|
||||
import body from "@theme/ApiExplorer/Body/slice";
|
||||
import contentType from "@theme/ApiExplorer/ContentType/slice";
|
||||
import params from "@theme/ApiExplorer/ParamOptions/slice";
|
||||
import response from "@theme/ApiExplorer/Response/slice";
|
||||
import server from "@theme/ApiExplorer/Server/slice";
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
accept,
|
||||
contentType,
|
||||
response,
|
||||
server,
|
||||
body,
|
||||
params,
|
||||
auth,
|
||||
});
|
||||
|
||||
export type RootState = ReturnType<typeof rootReducer>;
|
||||
|
||||
export function createStoreWithState(preloadedState: RootState, middlewares: Middleware[]) {
|
||||
return configureStore({
|
||||
reducer: rootReducer,
|
||||
preloadedState,
|
||||
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(...middlewares),
|
||||
});
|
||||
}
|
||||
|
||||
export type APIStore = ReturnType<typeof createStoreWithState>;
|
||||
|
||||
export function createStoreWithoutState(
|
||||
preloadedState: Partial<RootState>,
|
||||
middlewares: Middleware[],
|
||||
) {
|
||||
return configureStore({
|
||||
reducer: rootReducer,
|
||||
preloadedState,
|
||||
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(...middlewares),
|
||||
});
|
||||
}
|
||||
|
||||
export type AppDispatch = ReturnType<typeof createStoreWithState>["dispatch"];
|
@ -1,70 +0,0 @@
|
||||
import Link from "@docusaurus/Link";
|
||||
import isInternalUrl from "@docusaurus/isInternalUrl";
|
||||
import { isActiveSidebarItem } from "@docusaurus/plugin-content-docs/client";
|
||||
import { ThemeClassNames } from "@docusaurus/theme-common";
|
||||
import type { Props } from "@theme/DocSidebarItem/Link";
|
||||
import IconExternalLink from "@theme/Icon/ExternalLink";
|
||||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
const docsURL = new URL(process.env.DOCS_URL || "https://docs.goauthentik.io");
|
||||
function isInternalUrlOrDocsUrl(url: string) {
|
||||
if (isInternalUrl(url)) return true;
|
||||
|
||||
const inputURL = new URL(url);
|
||||
|
||||
return inputURL.origin === docsURL.origin;
|
||||
}
|
||||
|
||||
const DocSidebarItemLink: React.FC<Props> = ({
|
||||
item,
|
||||
onItemClick,
|
||||
activePath,
|
||||
level,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
index,
|
||||
...props
|
||||
}) => {
|
||||
const { href, label, className, autoAddBaseUrl } = item;
|
||||
const isActive = isActiveSidebarItem(item, activePath);
|
||||
const internalLink = isInternalUrlOrDocsUrl(href);
|
||||
|
||||
return (
|
||||
<li
|
||||
className={clsx(
|
||||
ThemeClassNames.docs.docSidebarItemLink,
|
||||
ThemeClassNames.docs.docSidebarItemLinkLevel(level),
|
||||
"menu__list-item",
|
||||
className,
|
||||
)}
|
||||
key={label}
|
||||
>
|
||||
<Link
|
||||
className={clsx("menu__link", {
|
||||
"menu__link--external": !internalLink,
|
||||
"menu__link--active": isActive,
|
||||
})}
|
||||
autoAddBaseUrl={autoAddBaseUrl}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
to={href}
|
||||
{...(internalLink && {
|
||||
onClick: onItemClick ? () => onItemClick(item) : undefined,
|
||||
})}
|
||||
{...props}
|
||||
>
|
||||
{item.className?.includes("api-method") ? (
|
||||
<div className="badge-container">
|
||||
<span role="img" className="badge method" />
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{label}
|
||||
{!internalLink && <IconExternalLink />}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export default DocSidebarItemLink;
|
@ -1,127 +0,0 @@
|
||||
.theme-layout-main {
|
||||
--doc-sidebar-width: 400px;
|
||||
}
|
||||
|
||||
.navbar-sidebar__upwards {
|
||||
.menu__link {
|
||||
font-size: var(--ifm-h6-font-size);
|
||||
font-weight: var(--ifm-font-weight-bold);
|
||||
color: var(--ifm-color-info-light);
|
||||
padding-block: calc(var(--ifm-spacing-vertical) / 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
.theme-doc-sidebar-item-category.api-reference {
|
||||
> .menu__list-item-collapsible {
|
||||
font-weight: 900;
|
||||
font-size: var(--ifm-h3-font-size);
|
||||
}
|
||||
|
||||
.menu__list {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.theme-doc-sidebar-item-category-level-2 .menu__list-item-collapsible {
|
||||
font-size: var(--ifm-h4-font-size);
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
.menu__link.menu__link--external {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.menu__list-item.api-method {
|
||||
.badge-container {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
> .menu__link {
|
||||
--menu-border-width: 2px;
|
||||
|
||||
color: var(--menu-item-contrast-foreground, red);
|
||||
background-color: var(--menu-item-background-color, transparent);
|
||||
flex-flow: column;
|
||||
font-family: var(--ifm-font-family-monospace);
|
||||
font-weight: 600;
|
||||
gap: 0.25em;
|
||||
padding-inline-end: 0.25em;
|
||||
word-break: break-all;
|
||||
align-items: start;
|
||||
border-radius: 0;
|
||||
margin-inline-end: calc(var(--ifm-menu-link-padding-horizontal) / 2);
|
||||
font-size: var(--ifm-h6-font-size);
|
||||
letter-spacing: 0.015em;
|
||||
text-rendering: optimizelegibility;
|
||||
position: relative;
|
||||
box-shadow: var(--ifm-global-shadow-lw);
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: var(--menu-border-width);
|
||||
height: 100%;
|
||||
display: block;
|
||||
z-index: 1;
|
||||
background-color: var(--ifm-badge-color, var(--ifm-color-primary));
|
||||
content: "";
|
||||
transition: width 0.2s var(--ifm-transition-timing-default);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.menu__link--active {
|
||||
--menu-border-width: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&.get {
|
||||
--method-label: "GET";
|
||||
--menu-item-contrast-foreground: var(--ifm-color-content);
|
||||
--menu-item-background-color: var(--ifm-card-background-color);
|
||||
--ifm-badge-color: var(--ifm-color-primary-light);
|
||||
}
|
||||
|
||||
&.post {
|
||||
--method-label: "POST";
|
||||
--menu-item-contrast-foreground: var(--ifm-color-success-contrast-foreground);
|
||||
--menu-item-background-color: var(--ifm-color-success-contrast-background);
|
||||
--ifm-badge-color: var(--ifm-color-success-lightest);
|
||||
}
|
||||
|
||||
&.put {
|
||||
--method-label: "PUT";
|
||||
--menu-item-contrast-foreground: var(--ifm-color-info-contrast-foreground);
|
||||
--menu-item-background-color: var(--ifm-color-info-contrast-background);
|
||||
--ifm-badge-color: var(--ifm-color-info-lightest);
|
||||
}
|
||||
|
||||
&.patch {
|
||||
--method-label: "PATCH";
|
||||
--menu-item-contrast-foreground: var(--ifm-color-warning-contrast-foreground);
|
||||
--menu-item-background-color: var(--ifm-color-warning-contrast-background);
|
||||
--ifm-badge-color: var(--ifm-color-warning-lightest);
|
||||
}
|
||||
|
||||
&.delete {
|
||||
--method-label: "DELETE";
|
||||
--menu-item-contrast-foreground: var(--ifm-color-danger-contrast-foreground);
|
||||
--menu-item-background-color: var(--ifm-color-danger-contrast-background);
|
||||
--ifm-badge-color: var(--ifm-color-danger-lightest);
|
||||
}
|
||||
}
|
||||
|
||||
.badge.method {
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
user-select: none;
|
||||
|
||||
&::before {
|
||||
content: var(--method-label, "METHOD");
|
||||
display: block;
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"references": [
|
||||
{
|
||||
"path": "../docusaurus-theme"
|
||||
}
|
||||
]
|
||||
}
|
37
docs/api/types/api-plugin.d.ts
vendored
@ -1,37 +0,0 @@
|
||||
/// <reference types="docusaurus-theme-openapi-docs" />
|
||||
/// <reference types="docusaurus-plugin-openapi-docs" />
|
||||
|
||||
declare module "@docusaurus/plugin-content-docs/src/sidebars/types" {
|
||||
export * from "@docusaurus/plugin-content-docs/src/sidebars/types.ts";
|
||||
}
|
||||
|
||||
declare module "@theme/RequestSchema";
|
||||
declare module "@theme/ParamsDetails";
|
||||
declare module "@theme/StatusCodes";
|
||||
declare module "@theme/OperationTabs";
|
||||
|
||||
declare module "@theme/SkeletonLoader" {
|
||||
import { FC } from "react";
|
||||
|
||||
const SkeletonLoader: FC<{ size: "sm" | "md" | "lg" }>;
|
||||
export default SkeletonLoader;
|
||||
}
|
||||
|
||||
declare module "@theme/APIExplorer" {
|
||||
import { FC } from "react";
|
||||
|
||||
export interface ApiExplorerProps {
|
||||
item: unknown;
|
||||
infoPath: unknown;
|
||||
}
|
||||
|
||||
const ApiExplorer: FC<ApiExplorerProps>;
|
||||
export default ApiExplorer;
|
||||
}
|
||||
|
||||
declare module "@theme/ApiExplorer/persistanceMiddleware" {
|
||||
import { Middleware } from "@reduxjs/toolkit";
|
||||
import type { ThemeConfig } from "docusaurus-theme-openapi-docs/src/types";
|
||||
|
||||
export const createPersistanceMiddleware: (options: ThemeConfig["api"]) => Middleware;
|
||||
}
|
34
docs/api/types/globals.d.ts
vendored
@ -1,34 +0,0 @@
|
||||
/**
|
||||
* @file Supplemental type definitions for Docusaurus.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Docusaurus uses an unconventional module resolution strategy, which can lead to
|
||||
* issues when using TypeScript.
|
||||
*
|
||||
* The types in this file are intended to expose less visible types to TypeScript's
|
||||
* project references, allowing for better type checking and autocompletion.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
||||
/// <reference types="@docusaurus/plugin-content-docs" />
|
||||
/// <reference types="@docusaurus/theme-classic" />
|
||||
import type { PropDocContent as BasePropDocContent } from "@docusaurus/plugin-content-docs";
|
||||
import type { DocContextValue as BaseDocContextValue } from "@docusaurus/plugin-content-docs/client";
|
||||
|
||||
declare global {
|
||||
export interface APIDocFrontMatter {
|
||||
readonly info_path?: string;
|
||||
readonly api?: string;
|
||||
readonly schema?: boolean;
|
||||
readonly sample?: unknown;
|
||||
}
|
||||
|
||||
export interface PropDocContent extends BasePropDocContent {
|
||||
readonly api?: string;
|
||||
frontMatter: APIDocFrontMatter & BasePropDocContent["frontMatter"];
|
||||
}
|
||||
|
||||
export interface DocContextValue extends BaseDocContextValue {
|
||||
frontMatter: APIDocFrontMatter & BasePropDocContent["frontMatter"];
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
import {
|
||||
createVersionURL,
|
||||
isPrerelease,
|
||||
parseHostnameSemVer,
|
||||
} from "#components/VersionPicker/utils.ts";
|
||||
|
||||
import clsx from "clsx";
|
||||
import React, { memo } from "react";
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
export interface VersionDropdownProps {
|
||||
/**
|
||||
* The hostname of the client.
|
||||
*/
|
||||
hostname: string | null;
|
||||
/**
|
||||
* The origin of the prerelease documentation.
|
||||
*
|
||||
* @format url
|
||||
*/
|
||||
prereleaseOrigin: string;
|
||||
/**
|
||||
* The available versions of the documentation.
|
||||
*
|
||||
* @format semver
|
||||
*/
|
||||
releases: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A dropdown that shows the available versions of the documentation.
|
||||
*/
|
||||
export const VersionDropdown = memo<VersionDropdownProps>(
|
||||
({ hostname, prereleaseOrigin, releases }) => {
|
||||
const prerelease = isPrerelease(hostname);
|
||||
const parsedSemVer = !prerelease ? parseHostnameSemVer(hostname) : null;
|
||||
|
||||
const currentLabel = parsedSemVer || "Pre-Release";
|
||||
|
||||
const endIndex = parsedSemVer ? releases.indexOf(parsedSemVer) : -1;
|
||||
|
||||
const visibleReleases = releases.slice(0, endIndex === -1 ? 3 : endIndex + 3);
|
||||
|
||||
return (
|
||||
<li className="navbar__item dropdown dropdown--hoverable dropdown--right ak-version-selector">
|
||||
<div
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
role="button"
|
||||
className="navbar__link menu__link"
|
||||
>
|
||||
Version: {currentLabel}
|
||||
</div>
|
||||
|
||||
<ul className="dropdown__menu menu__list-item--collapsed">
|
||||
{!prerelease ? (
|
||||
<li>
|
||||
<a
|
||||
href={prereleaseOrigin}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="dropdown__link menu__link"
|
||||
>
|
||||
Pre-Release
|
||||
</a>
|
||||
</li>
|
||||
) : null}
|
||||
|
||||
{visibleReleases.map((semVer, idx) => {
|
||||
const label = semVer;
|
||||
|
||||
// TODO: Flesh this out after we settle on versioning strategy.
|
||||
// if (idx === 0) {
|
||||
// label += " (Current Release)";
|
||||
// }
|
||||
|
||||
return (
|
||||
<li key={idx}>
|
||||
<a
|
||||
href={createVersionURL(semVer)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={clsx("dropdown__link menu__link", {
|
||||
"menu__link--active": semVer === currentLabel,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
},
|
||||
);
|
@ -1,76 +0,0 @@
|
||||
import { VersionDropdown } from "#components/VersionPicker/VersionDropdown.tsx";
|
||||
import { LocalhostAliases, ProductionURL, useHostname } from "#components/VersionPicker/utils.ts";
|
||||
|
||||
import { AKReleasesPluginData } from "@goauthentik/docusaurus-theme/releases/plugin";
|
||||
|
||||
import useIsBrowser from "@docusaurus/useIsBrowser";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
|
||||
export interface VersionPickerLoaderProps {
|
||||
pluginData: AKReleasesPluginData;
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-fetching component that loads available versions of the documentation.
|
||||
*
|
||||
* @see {@linkcode VersionPicker} for the component.
|
||||
* @see {@linkcode AKReleasesPluginData} for the plugin data.
|
||||
* @client
|
||||
*/
|
||||
export const VersionPickerLoader: React.FC<VersionPickerLoaderProps> = ({ pluginData }) => {
|
||||
const [releases, setReleases] = useState(pluginData.releases);
|
||||
|
||||
const browser = useIsBrowser();
|
||||
const hostname = useHostname();
|
||||
|
||||
const prereleaseOrigin = useMemo(() => {
|
||||
if (browser && LocalhostAliases.has(window.location.hostname)) {
|
||||
return window.location.origin;
|
||||
}
|
||||
|
||||
return ProductionURL.href;
|
||||
}, [browser]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!browser || !prereleaseOrigin) return;
|
||||
|
||||
const controller = new AbortController();
|
||||
const updateURL = new URL(pluginData.publicPath, prereleaseOrigin);
|
||||
|
||||
fetch(updateURL, {
|
||||
signal: controller.signal,
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch new releases: ${response.status}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((data: unknown) => {
|
||||
// We're extra cautious here to be ready if the API shape ever changes.
|
||||
if (!data) throw new Error("Failed to parse releases");
|
||||
|
||||
if (!Array.isArray(data)) throw new Error("Releases must be an array");
|
||||
|
||||
if (!data.every((item) => typeof item === "string"))
|
||||
throw new Error("Releases must be an array of strings");
|
||||
|
||||
setReleases(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn(`Failed to fetch new releases: ${error}`);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line consistent-return
|
||||
return () => controller.abort("unmount");
|
||||
}, [browser, pluginData.publicPath, prereleaseOrigin]);
|
||||
|
||||
return (
|
||||
<VersionDropdown
|
||||
hostname={hostname}
|
||||
prereleaseOrigin={prereleaseOrigin}
|
||||
releases={releases}
|
||||
/>
|
||||
);
|
||||
};
|
@ -1,32 +0,0 @@
|
||||
import { VersionDropdown } from "#components/VersionPicker/VersionDropdown.tsx";
|
||||
import { useHostname, usePrereleaseOrigin } from "#components/VersionPicker/utils.ts";
|
||||
|
||||
import { AKReleasesPluginData } from "@goauthentik/docusaurus-theme/releases/plugin";
|
||||
|
||||
import { usePluginData } from "@docusaurus/useGlobalData";
|
||||
|
||||
/**
|
||||
* A component that shows the available versions of the documentation.
|
||||
*
|
||||
* @see {@linkcode VersionPickerLoader} for the data-fetching component.
|
||||
*/
|
||||
export const VersionPicker: React.FC = () => {
|
||||
const hostname = useHostname();
|
||||
const prereleaseOrigin = usePrereleaseOrigin();
|
||||
|
||||
const pluginData = usePluginData("ak-releases-plugin", undefined) as
|
||||
| AKReleasesPluginData
|
||||
| undefined;
|
||||
|
||||
if (!pluginData?.releases.length) return null;
|
||||
|
||||
// return <VersionPickerLoader pluginData={pluginData} />;
|
||||
|
||||
return (
|
||||
<VersionDropdown
|
||||
hostname={hostname}
|
||||
prereleaseOrigin={prereleaseOrigin}
|
||||
releases={pluginData.releases}
|
||||
/>
|
||||
);
|
||||
};
|
@ -1,33 +0,0 @@
|
||||
.theme-doc-sidebar-menu {
|
||||
--ak-version-selector-padding: calc(var(--ifm-spacing-vertical) / 2);
|
||||
|
||||
.dropdown.ak-version-selector {
|
||||
width: calc(100% - (var(--ifm-spacing-horizontal) / 2));
|
||||
border-block-end: var(--ifm-hr-height) solid var(--ifm-color-emphasis-200);
|
||||
padding-block-start: calc(var(--ak-version-selector-padding) / 2);
|
||||
padding-block-end: var(--ak-version-selector-padding);
|
||||
margin-block-end: var(--ak-version-selector-padding);
|
||||
|
||||
&:has(+ .navbar-sidebar__upwards) {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
|
||||
.navbar__link.menu__link {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
font-weight: var(--ifm-font-weight-semibold);
|
||||
|
||||
&::after {
|
||||
color: var(--ifm-color-emphasis-400);
|
||||
filter: var(--ifm-menu-link-sublist-icon-filter);
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown__menu {
|
||||
background: var(--ifm-dropdown-background-color);
|
||||
box-shadow: var(--ifm-global-shadow-lw);
|
||||
border: 1px solid var(--ifm-color-emphasis-200);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
import useIsBrowser from "@docusaurus/useIsBrowser";
|
||||
import { useMemo } from "react";
|
||||
import { coerce } from "semver";
|
||||
|
||||
export const ProductionURL = new URL("https://docs.goauthentik.io");
|
||||
|
||||
export const LocalhostAliases: ReadonlySet<string> = new Set(["localhost", "127.0.0.1"]);
|
||||
|
||||
/**
|
||||
* Given a semver, create the URL for the version.
|
||||
*/
|
||||
export function createVersionURL(semver: string): string {
|
||||
const subdomain = `version-${semver.replace(".", "-")}`;
|
||||
|
||||
return `https://${subdomain}.goauthentik.io`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Predicate to determine if a hostname appears to be a prerelease origin.
|
||||
*/
|
||||
export function isPrerelease(hostname: string | null): boolean {
|
||||
if (!hostname) return false;
|
||||
|
||||
if (hostname === ProductionURL.hostname) return true;
|
||||
if (hostname.endsWith(".netlify.app")) return true;
|
||||
|
||||
if (LocalhostAliases.has(hostname)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a hostname, parse the semver from the subdomain.
|
||||
*/
|
||||
export function parseHostnameSemVer(hostname: string | null): string | null {
|
||||
if (!hostname) return null;
|
||||
|
||||
const [, possibleSemVer] = hostname.match(/version-(.+)\.goauthentik\.io/) || [];
|
||||
|
||||
if (!possibleSemVer) return null;
|
||||
|
||||
const formattedSemVer = possibleSemVer.replace("-", ".");
|
||||
|
||||
if (!coerce(formattedSemVer)) return null;
|
||||
|
||||
return formattedSemVer;
|
||||
}
|
||||
|
||||
export function useHostname() {
|
||||
const browser = useIsBrowser();
|
||||
|
||||
const hostname = useMemo(() => {
|
||||
if (!browser) return null;
|
||||
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
// Query parameter used for debugging.
|
||||
// Note that this doesn't synchronize with Docusaurus's router state.
|
||||
const subdomain = searchParams.get("version");
|
||||
|
||||
if (subdomain) return subdomain;
|
||||
|
||||
return window.location.hostname;
|
||||
}, [browser]);
|
||||
|
||||
return hostname;
|
||||
}
|
||||
|
||||
export function usePrereleaseOrigin() {
|
||||
const browser = useIsBrowser();
|
||||
|
||||
const prereleaseOrigin = useMemo(() => {
|
||||
if (browser && LocalhostAliases.has(window.location.hostname)) {
|
||||
return window.location.origin;
|
||||
}
|
||||
|
||||
return ProductionURL.href;
|
||||
}, [browser]);
|
||||
|
||||
return prereleaseOrigin;
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/**
|
||||
* @file Docusaurus config.
|
||||
*
|
||||
* @import { Config } from "@docusaurus/types";
|
||||
* @import { UserThemeConfig, UserThemeConfigExtra } from "@goauthentik/docusaurus-config";
|
||||
* @import { Options as DocsPluginOptions } from "@docusaurus/plugin-content-docs";
|
||||
* @import { BuildUrlValues } from "remark-github";
|
||||
*/
|
||||
import {
|
||||
remarkEnterpriseDirective,
|
||||
remarkPreviewDirective,
|
||||
remarkSupportDirective,
|
||||
remarkVersionDirective,
|
||||
} from "#remark";
|
||||
|
||||
import remarkNPM2Yarn from "@docusaurus/remark-plugin-npm2yarn";
|
||||
import remarkDirective from "remark-directive";
|
||||
import remarkGithub, { defaultBuildUrl } from "remark-github";
|
||||
|
||||
//#region Common configuration
|
||||
|
||||
/**
|
||||
* @satisfies {DocsPluginOptions}
|
||||
*/
|
||||
export const CommonDocsPluginOptions = {
|
||||
id: "docs",
|
||||
routeBasePath: "/",
|
||||
path: "docs",
|
||||
sidebarPath: "./docs/sidebar.mjs",
|
||||
showLastUpdateTime: false,
|
||||
editUrl: "https://github.com/goauthentik/authentik/edit/main/docs/",
|
||||
|
||||
//#region Docs Plugins
|
||||
|
||||
beforeDefaultRemarkPlugins: [
|
||||
remarkDirective,
|
||||
remarkVersionDirective,
|
||||
remarkEnterpriseDirective,
|
||||
remarkPreviewDirective,
|
||||
remarkSupportDirective,
|
||||
],
|
||||
|
||||
remarkPlugins: [
|
||||
[remarkNPM2Yarn, { sync: true }],
|
||||
[
|
||||
remarkGithub,
|
||||
{
|
||||
repository: "goauthentik/authentik",
|
||||
/**
|
||||
* @param {BuildUrlValues} values
|
||||
*/
|
||||
buildUrl: (values) => {
|
||||
// Only replace issues and PR links
|
||||
return values.type === "issue" || values.type === "mention"
|
||||
? defaultBuildUrl(values)
|
||||
: false;
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* Documentation site configuration for Docusaurus.
|
||||
* @satisfies {Partial<Config>}
|
||||
*/
|
||||
export const CommonConfig = {
|
||||
themes: ["@docusaurus/theme-mermaid"],
|
||||
themeConfig: /** @type {UserThemeConfig & UserThemeConfigExtra} */ ({
|
||||
algolia: {
|
||||
appId: "36ROD0O0FV",
|
||||
apiKey: "727db511300ca9aec5425645bbbddfb5",
|
||||
indexName: "goauthentik",
|
||||
},
|
||||
}),
|
||||
plugins: [
|
||||
[
|
||||
"@docusaurus/plugin-google-gtag",
|
||||
{
|
||||
trackingID: ["G-9MVR9WZFZH"],
|
||||
anonymizeIP: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
@ -1,3 +0,0 @@
|
||||
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
|
||||
|
||||
export default createESLintPackageConfig();
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @file Docusaurus theme plugin.
|
||||
* @import { Plugin } from "@docusaurus/types";
|
||||
*/
|
||||
|
||||
/**
|
||||
* @returns {Plugin<void>}
|
||||
*/
|
||||
export default function docusaurusThemeAuthentik() {
|
||||
return {
|
||||
name: "docusaurus-theme-authentik",
|
||||
|
||||
getThemePath() {
|
||||
return "./theme";
|
||||
},
|
||||
|
||||
getTypeScriptThemePath() {
|
||||
return "./theme";
|
||||
},
|
||||
};
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "@goauthentik/docusaurus-theme",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./index.js",
|
||||
"./config": "./config.js",
|
||||
"./remark": "./remark/index.mjs",
|
||||
"./components/*": "./components/*",
|
||||
"./releases/plugin": "./releases/plugin.mjs",
|
||||
"./releases/utils": "./releases/utils.mjs"
|
||||
},
|
||||
"imports": {
|
||||
"#remark": "./remark/index.mjs",
|
||||
"#remark/*": "./remark/*",
|
||||
"#components/*": "./components/*",
|
||||
"#hooks/*": "./hooks/*",
|
||||
"#theme/*": "./theme/*"
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
/**
|
||||
* @file Docusaurus releases plugin.
|
||||
*
|
||||
* @import { LoadContext, Plugin } from "@docusaurus/types"
|
||||
*/
|
||||
import * as fs from "node:fs/promises";
|
||||
import * as path from "node:path";
|
||||
|
||||
import { collectReleaseFiles } from "./utils.mjs";
|
||||
|
||||
const PLUGIN_NAME = "ak-releases-plugin";
|
||||
const RELEASES_FILENAME = "releases.gen.json";
|
||||
|
||||
/**
|
||||
* @typedef {object} ReleasesPluginOptions
|
||||
* @property {string} docsDirectory The path to the documentation directory.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {object} AKReleasesPluginData
|
||||
* @property {string} publicPath The URL to the plugin's public directory.
|
||||
* @property {string[]} releases The available versions of the documentation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {LoadContext} loadContext
|
||||
* @param {ReleasesPluginOptions} options
|
||||
* @returns {Promise<Plugin<AKReleasesPluginData>>}
|
||||
*/
|
||||
async function akReleasesPlugin(loadContext, { docsDirectory }) {
|
||||
return {
|
||||
name: PLUGIN_NAME,
|
||||
|
||||
async loadContent() {
|
||||
console.log(`🚀 ${PLUGIN_NAME} loaded`);
|
||||
|
||||
const releases = collectReleaseFiles(docsDirectory).map((release) => release.name);
|
||||
|
||||
const outputPath = path.join(loadContext.siteDir, "static", RELEASES_FILENAME);
|
||||
|
||||
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
||||
await fs.writeFile(outputPath, JSON.stringify(releases, null, 2), "utf-8");
|
||||
console.log(`✅ ${RELEASES_FILENAME} generated`);
|
||||
|
||||
/**
|
||||
* @type {AKReleasesPluginData}
|
||||
*/
|
||||
const content = {
|
||||
releases,
|
||||
publicPath: path.join("/", RELEASES_FILENAME),
|
||||
};
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
contentLoaded({ content, actions }) {
|
||||
const { setGlobalData } = actions;
|
||||
|
||||
setGlobalData(content);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default akReleasesPlugin;
|
@ -1,69 +0,0 @@
|
||||
/**
|
||||
* @file Docusaurus release utils.
|
||||
*
|
||||
* @import { SidebarItemConfig } from "@docusaurus/plugin-content-docs/src/sidebars/types.js"
|
||||
*/
|
||||
import FastGlob from "fast-glob";
|
||||
import * as path from "node:path";
|
||||
import { coerce } from "semver";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} releasesParentDirectory
|
||||
* @returns {FastGlob.Entry[]}
|
||||
*/
|
||||
export function collectReleaseFiles(releasesParentDirectory) {
|
||||
const releaseFiles = FastGlob.sync("releases/**/v*.{md,mdx}", {
|
||||
cwd: releasesParentDirectory,
|
||||
onlyFiles: true,
|
||||
objectMode: true,
|
||||
})
|
||||
.map((fileEntry) => {
|
||||
return {
|
||||
...fileEntry,
|
||||
path: fileEntry.path.replace(/\.mdx?$/, ""),
|
||||
name: fileEntry.name.replace(/^v/, "").replace(/\.mdx?$/, ""),
|
||||
};
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const aSemVer = coerce(a.name);
|
||||
const bSemVer = coerce(b.name);
|
||||
|
||||
if (aSemVer && bSemVer) {
|
||||
return bSemVer.compare(aSemVer);
|
||||
}
|
||||
|
||||
return b.name.localeCompare(a.name);
|
||||
});
|
||||
|
||||
return releaseFiles;
|
||||
}
|
||||
|
||||
export const SUPPORTED_RELEASE_COUNT = 3;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {FastGlob.Entry[]} releaseFiles
|
||||
*/
|
||||
export function createReleaseSidebarEntries(releaseFiles) {
|
||||
/**
|
||||
* @type {SidebarItemConfig[]}
|
||||
*/
|
||||
let sidebarEntries = releaseFiles.map((fileEntry) => {
|
||||
return path.join(fileEntry.path);
|
||||
});
|
||||
|
||||
if (releaseFiles.length > SUPPORTED_RELEASE_COUNT) {
|
||||
// Then we add the rest of the releases as a category.
|
||||
sidebarEntries = [
|
||||
...sidebarEntries.slice(0, SUPPORTED_RELEASE_COUNT),
|
||||
{
|
||||
type: "category",
|
||||
label: "Previous versions",
|
||||
items: sidebarEntries.slice(SUPPORTED_RELEASE_COUNT),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return sidebarEntries;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
export * from "./enterprise-directive.mjs";
|
||||
export * from "./link-rewrite-directive.mjs";
|
||||
export * from "./preview-directive.mjs";
|
||||
export * from "./support-directive.mjs";
|
||||
export * from "./version-directive.mjs";
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* @import { Root } from "mdast";
|
||||
*/
|
||||
import { SKIP, visit } from "unist-util-visit";
|
||||
|
||||
/**
|
||||
* @typedef {[pattern: string | RegExp, replacement: string]} Rewrite
|
||||
*/
|
||||
|
||||
/**
|
||||
* Remark plugin to transform relative links to docs to absolute URLs
|
||||
* @param {Iterable<[string, string]>} rewrites Map of urls to rewrite where the key is the prefix to check for and the value is the domain to add
|
||||
*/
|
||||
export function remarkLinkRewrite(rewrites) {
|
||||
const map = new Map(rewrites);
|
||||
|
||||
return () => {
|
||||
/**
|
||||
* @param {Root} tree The MDAST tree to transform.
|
||||
*/
|
||||
return (tree) => {
|
||||
visit(tree, "link", (node) => {
|
||||
for (const [pattern, replacement] of map) {
|
||||
if (!node.url.startsWith(pattern)) continue;
|
||||
|
||||
node.url = node.url.replace(pattern, replacement);
|
||||
}
|
||||
|
||||
return SKIP;
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default remarkLinkRewrite;
|
@ -1,26 +0,0 @@
|
||||
/// <reference types="@docusaurus/plugin-content-docs" />
|
||||
import { VersionPicker } from "#components/VersionPicker/index.tsx";
|
||||
|
||||
import {
|
||||
DocSidebarItemsExpandedStateProvider,
|
||||
useVisibleSidebarItems,
|
||||
} from "@docusaurus/plugin-content-docs/client";
|
||||
import DocSidebarItem from "@theme/DocSidebarItem";
|
||||
import type { Props as DocSidebarItemsProps } from "@theme/DocSidebarItems";
|
||||
import { memo } from "react";
|
||||
|
||||
const DocSidebarItems = ({ items, ...props }: DocSidebarItemsProps): JSX.Element => {
|
||||
const visibleItems = useVisibleSidebarItems(items, props.activePath);
|
||||
const includeVersionPicker = props.level === 1 && !props.activePath.startsWith("/integrations");
|
||||
|
||||
return (
|
||||
<DocSidebarItemsExpandedStateProvider>
|
||||
{includeVersionPicker ? <VersionPicker /> : null}
|
||||
{visibleItems.map((item, index) => (
|
||||
<DocSidebarItem key={index} item={item} index={index} {...props} />
|
||||
))}
|
||||
</DocSidebarItemsExpandedStateProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(DocSidebarItems);
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json"
|
||||
}
|
44
docs/docusaurus-theme/types/globals.d.ts
vendored
@ -1,44 +0,0 @@
|
||||
/**
|
||||
* @file Supplemental type definitions for Docusaurus.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Docusaurus uses an unconventional module resolution strategy, which can lead to
|
||||
* issues when using TypeScript.
|
||||
*
|
||||
* The types in this file are intended to expose less visible types to TypeScript's
|
||||
* project references, allowing for better type checking and autocompletion.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
||||
/// <reference types="@docusaurus/plugin-content-docs" />
|
||||
/// <reference types="@docusaurus/theme-classic" />
|
||||
import type { PropDocContent as BasePropDocContent } from "@docusaurus/plugin-content-docs";
|
||||
import type { DocContextValue as BaseDocContextValue } from "@docusaurus/plugin-content-docs/client";
|
||||
|
||||
declare global {
|
||||
/**
|
||||
* @monkeypatch
|
||||
*/
|
||||
export interface DocFrontMatter {
|
||||
support_level?: string;
|
||||
authentik_version?: string;
|
||||
authentik_preview: boolean;
|
||||
authentik_enterprise: boolean;
|
||||
}
|
||||
|
||||
export interface APIDocFrontMatter {
|
||||
readonly info_path?: string;
|
||||
readonly api?: string;
|
||||
readonly schema?: boolean;
|
||||
readonly sample?: unknown;
|
||||
}
|
||||
|
||||
export interface PropDocContent extends BasePropDocContent {
|
||||
readonly api?: string;
|
||||
frontMatter: APIDocFrontMatter & BasePropDocContent["frontMatter"];
|
||||
}
|
||||
|
||||
export interface DocContextValue extends BaseDocContextValue {
|
||||
frontMatter: DocFrontMatter & APIDocFrontMatter & BasePropDocContent["frontMatter"];
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import { DefaultIgnorePatterns, createESLintPackageConfig } from "@goauthentik/eslint-config";
|
||||
|
||||
export default createESLintPackageConfig({
|
||||
ignorePatterns: [
|
||||
// ---
|
||||
...DefaultIgnorePatterns,
|
||||
"**/.docusaurus/",
|
||||
"**/build",
|
||||
"**/reference",
|
||||
],
|
||||
});
|
@ -1,7 +0,0 @@
|
||||
.theme-doc-sidebar-item-category-level-1 .menu__list-item-collapsible {
|
||||
border-top: 0.5px solid;
|
||||
border-top-color: var(--ifm-category-color, var(--ifm-menu-color-background-active));
|
||||
border-radius: 0;
|
||||
font-weight: 600;
|
||||
padding-block: 0.25em;
|
||||
}
|
@ -1 +0,0 @@
|
||||
module.exports = import("./docusaurus.config.esm.mjs").then(($) => $.default);
|
@ -1,87 +0,0 @@
|
||||
/**
|
||||
* @file Docusaurus Integrations config.
|
||||
*
|
||||
* @import { Config } from "@docusaurus/types";
|
||||
* @import { UserThemeConfig, UserThemeConfigExtra } from "@goauthentik/docusaurus-config";
|
||||
* @import { Options as DocsPluginOptions } from "@docusaurus/plugin-content-docs";
|
||||
*/
|
||||
import { createDocusaurusConfig } from "@goauthentik/docusaurus-config";
|
||||
import { CommonConfig, CommonDocsPluginOptions } from "@goauthentik/docusaurus-theme/config";
|
||||
import { remarkLinkRewrite } from "@goauthentik/docusaurus-theme/remark";
|
||||
|
||||
import { GlobExcludeDefault } from "@docusaurus/utils";
|
||||
import { deepmerge } from "deepmerge-ts";
|
||||
import { createRequire } from "node:module";
|
||||
import { resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
|
||||
//#region Configuration
|
||||
|
||||
/**
|
||||
* Documentation site configuration for Docusaurus.
|
||||
* @satisfies {Partial<Config>}
|
||||
*/
|
||||
const config = {
|
||||
staticDirectories: [
|
||||
// ---
|
||||
resolve(__dirname, "..", "static"),
|
||||
"static",
|
||||
],
|
||||
|
||||
themes: ["@goauthentik/docusaurus-theme"],
|
||||
|
||||
themeConfig: /** @type {UserThemeConfig & UserThemeConfigExtra} */ ({
|
||||
navbarReplacements: {
|
||||
INTEGRATIONS_URL: "/",
|
||||
},
|
||||
algolia: {
|
||||
externalUrlRegex: /^(?:https?:\/\/)(integrations|api).?(goauthentik.io)/.source,
|
||||
},
|
||||
}),
|
||||
|
||||
plugins: [
|
||||
[
|
||||
"@docusaurus/theme-classic",
|
||||
{
|
||||
customCss: [
|
||||
"./custom.css",
|
||||
require.resolve("@goauthentik/docusaurus-config/css/index.css"),
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
//#region Documentation
|
||||
[
|
||||
"@docusaurus/plugin-content-docs",
|
||||
deepmerge(
|
||||
CommonDocsPluginOptions,
|
||||
/** @type {DocsPluginOptions} */ ({
|
||||
id: "docs",
|
||||
routeBasePath: "/",
|
||||
path: ".",
|
||||
exclude: [...GlobExcludeDefault],
|
||||
include: ["**/*.mdx", "**/*.md"],
|
||||
sidebarPath: "./sidebar.mjs",
|
||||
showLastUpdateTime: false,
|
||||
editUrl:
|
||||
"https://github.com/goauthentik/authentik/edit/main/docs/topics/integrations/",
|
||||
|
||||
//#region Docs Plugins
|
||||
|
||||
beforeDefaultRemarkPlugins: [
|
||||
remarkLinkRewrite([
|
||||
// ---
|
||||
["/api", "https://api.goauthentik.io"],
|
||||
["/docs", "https://docs.goauthentik.io"],
|
||||
]),
|
||||
],
|
||||
}),
|
||||
),
|
||||
],
|
||||
],
|
||||
};
|
||||
|
||||
export default /** @type {Config} */ (deepmerge(CommonConfig, createDocusaurusConfig(config)));
|
@ -1,10 +0,0 @@
|
||||
import { DefaultIgnorePatterns, createESLintPackageConfig } from "@goauthentik/eslint-config";
|
||||
|
||||
export default createESLintPackageConfig({
|
||||
ignorePatterns: [
|
||||
// ---
|
||||
...DefaultIgnorePatterns,
|
||||
".docusaurus/",
|
||||
"./build",
|
||||
],
|
||||
});
|
@ -1,30 +0,0 @@
|
||||
[[plugins]]
|
||||
package = "netlify-plugin-cache"
|
||||
|
||||
[plugins.inputs]
|
||||
paths = [".docusaurus", ".cache", 'node_modules/.cache']
|
||||
|
||||
[[plugins]]
|
||||
package = "netlify-plugin-debug-cache"
|
||||
|
||||
[build]
|
||||
base = "docs"
|
||||
package = "integrations"
|
||||
command = "npm run build -w integrations"
|
||||
publish = "integrations/build"
|
||||
|
||||
[dev]
|
||||
command = "npm start"
|
||||
targetPort = 3000
|
||||
publish = "integrations/build"
|
||||
|
||||
[context.production.environment]
|
||||
NODE_ENV = "production"
|
||||
|
||||
[context.dev.environment]
|
||||
NODE_ENV = "development"
|
||||
|
||||
[[headers]]
|
||||
for = "/*"
|
||||
[headers.values]
|
||||
X-Frame-Options = "DENY"
|
@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "@goauthentik/integration-docs",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "run-s build:types build:docusaurus",
|
||||
"build:docusaurus": "docusaurus build",
|
||||
"build:types": "tsc -b .",
|
||||
"deploy": "docusaurus deploy",
|
||||
"docusaurus": "docusaurus",
|
||||
"serve": "docusaurus serve",
|
||||
"start": "docusaurus start",
|
||||
"test": "node --test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@goauthentik/docusaurus-theme": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24"
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/**
|
||||
* @file Sidebar configuration for the authentik integrations.
|
||||
*
|
||||
* @import { SidebarItemConfig } from "@docusaurus/plugin-content-docs/src/sidebars/types.js"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {ReadonlyArray<readonly [string, string]>}
|
||||
*/
|
||||
const categories = [
|
||||
["chat-communication-collaboration", "Chat, Communication & Collaboration"],
|
||||
["device-management", "Device Management"],
|
||||
["cloud-providers", "Cloud Providers"],
|
||||
["dashboards", "Dashboards"],
|
||||
["development", "Development"],
|
||||
["documentation", "Documentation"],
|
||||
["hypervisors-orchestrators", "Hypervisors / Orchestrators"],
|
||||
["infrastructure", "Infrastructure"],
|
||||
["networking", "Networking"],
|
||||
["media", "Media"],
|
||||
["miscellaneous", "Miscellaneous"],
|
||||
["monitoring", "Monitoring"],
|
||||
["platforms", "Platforms"],
|
||||
["security", "Security"],
|
||||
];
|
||||
|
||||
export default /** @type {SidebarItemConfig} */
|
||||
({
|
||||
integrations: [
|
||||
{
|
||||
type: "doc",
|
||||
id: "index",
|
||||
},
|
||||
{
|
||||
type: "doc",
|
||||
id: "applications",
|
||||
},
|
||||
...categories.map(([dirName, label]) => ({
|
||||
type: "category",
|
||||
label,
|
||||
items: [
|
||||
{
|
||||
type: "autogenerated",
|
||||
dirName,
|
||||
},
|
||||
],
|
||||
})),
|
||||
],
|
||||
});
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"references": [
|
||||
{
|
||||
"path": "../docusaurus-theme"
|
||||
}
|
||||
]
|
||||
}
|
13
docs/integrations/types/globals.d.ts
vendored
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @file Supplemental type definitions for Docusaurus.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Docusaurus uses an unconventional module resolution strategy, which can lead to
|
||||
* issues when using TypeScript.
|
||||
*
|
||||
* The types in this file are intended to expose less visible types to TypeScript's
|
||||
* project references, allowing for better type checking and autocompletion.
|
||||
*/
|
||||
/// <reference types="@docusaurus/plugin-content-docs" />
|
||||
/// <reference types="@docusaurus/theme-classic" />
|
@ -1,101 +0,0 @@
|
||||
{
|
||||
"name": "@goauthentik/docs",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "run-s build:types build:docusaurus",
|
||||
"build:docusaurus": "npm run build -w topics",
|
||||
"build:types": "tsc -b",
|
||||
"docusaurus": "docusaurus",
|
||||
"lint": "eslint --fix .",
|
||||
"lint-check": "eslint --max-warnings 0 .",
|
||||
"prettier": "prettier --write .",
|
||||
"prettier-check": "prettier --check .",
|
||||
"start": "npm start -w topics"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^3.8.1",
|
||||
"@docusaurus/faster": "^3.8.1",
|
||||
"@docusaurus/module-type-aliases": "^3.8.1",
|
||||
"@docusaurus/plugin-client-redirects": "^3.8.1",
|
||||
"@docusaurus/plugin-content-docs": "^3.8.1",
|
||||
"@docusaurus/preset-classic": "^3.8.1",
|
||||
"@docusaurus/remark-plugin-npm2yarn": "^3.8.1",
|
||||
"@docusaurus/theme-common": "^3.8.1",
|
||||
"@docusaurus/theme-mermaid": "^3.8.1",
|
||||
"@docusaurus/tsconfig": "^3.8.1",
|
||||
"@docusaurus/types": "^3.8.1",
|
||||
"@eslint/js": "^9.29.0",
|
||||
"@goauthentik/docusaurus-config": "^2.1.1",
|
||||
"@goauthentik/docusaurus-theme": "*",
|
||||
"@goauthentik/eslint-config": "^1.0.5",
|
||||
"@goauthentik/prettier-config": "^2.0.1",
|
||||
"@goauthentik/tsconfig": "^1.0.4",
|
||||
"@mdx-js/react": "^3.1.0",
|
||||
"@reduxjs/toolkit": "^1.7.1",
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"@types/lodash": "^4.17.18",
|
||||
"@types/node": "^24.0.3",
|
||||
"@types/pako": "^2.0.3",
|
||||
"@types/pidusage": "^2.0.5",
|
||||
"@types/postman-collection": "^3.5.11",
|
||||
"@types/react": "^18.3.23",
|
||||
"@types/react-dom": "^18.3.7",
|
||||
"@types/semver": "^7.7.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.34.1",
|
||||
"@typescript-eslint/parser": "^8.34.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"docusaurus-plugin-openapi-docs": "^4.4.0",
|
||||
"docusaurus-theme-openapi-docs": "^4.4.0",
|
||||
"eslint": "^9.29.0",
|
||||
"fast-glob": "^3.3.3",
|
||||
"netlify-cli": "^22.2.1",
|
||||
"netlify-plugin-cache": "^1.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"pako": "^2.1.0",
|
||||
"pidtree": "^0.6.0",
|
||||
"pidusage": "^4.0.1",
|
||||
"postcss": "^8.5.6",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-packagejson": "^2.5.15",
|
||||
"prism-react-renderer": "^2.4.1",
|
||||
"react": "^18.3.1",
|
||||
"react-before-after-slider-component": "^1.1.8",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-redux": "^7.2.0",
|
||||
"remark-directive": "^4.0.0",
|
||||
"remark-github": "^12.0.0",
|
||||
"semver": "^7.7.2",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.35.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rspack/binding-darwin-arm64": "1.3.15",
|
||||
"@rspack/binding-linux-arm64-gnu": "1.3.15",
|
||||
"@rspack/binding-linux-x64-gnu": "1.3.15",
|
||||
"@swc/core-darwin-arm64": "1.12.7",
|
||||
"@swc/core-linux-arm64-gnu": "1.12.7",
|
||||
"@swc/core-linux-x64-gnu": "1.12.7",
|
||||
"@swc/html-darwin-arm64": "1.12.7",
|
||||
"@swc/html-linux-arm64-gnu": "1.12.7",
|
||||
"@swc/html-linux-x64-gnu": "1.12.7",
|
||||
"lightningcss-darwin-arm64": "1.30.1",
|
||||
"lightningcss-linux-arm64-gnu": "1.30.1",
|
||||
"lightningcss-linux-x64-gnu": "1.30.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24"
|
||||
},
|
||||
"workspaces": [
|
||||
"api",
|
||||
"docusaurus-theme",
|
||||
"integrations",
|
||||
"topics"
|
||||
],
|
||||
"prettier": "@goauthentik/prettier-config",
|
||||
"overrides": {
|
||||
"@rspack/core": "1.4.0-rc.0"
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
module.exports = import("./docusaurus.config.esm.mjs").then(($) => $.default);
|
@ -1,92 +0,0 @@
|
||||
/**
|
||||
* @file Docusaurus Documentation config.
|
||||
*
|
||||
* @import { Config } from "@docusaurus/types";
|
||||
* @import { UserThemeConfig, UserThemeConfigExtra } from "@goauthentik/docusaurus-config";
|
||||
* @import { Options as DocsPluginOptions } from "@docusaurus/plugin-content-docs";
|
||||
* @import { ReleasesPluginOptions } from "@goauthentik/docusaurus-theme/releases/plugin"
|
||||
*/
|
||||
import { createDocusaurusConfig } from "@goauthentik/docusaurus-config";
|
||||
import { CommonConfig, CommonDocsPluginOptions } from "@goauthentik/docusaurus-theme/config";
|
||||
import { remarkLinkRewrite } from "@goauthentik/docusaurus-theme/remark";
|
||||
|
||||
import { GlobExcludeDefault } from "@docusaurus/utils";
|
||||
import { deepmerge } from "deepmerge-ts";
|
||||
import { createRequire } from "node:module";
|
||||
import { resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
/**
|
||||
* Documentation site configuration for Docusaurus.
|
||||
* @satisfies {Partial<Config>}
|
||||
*/
|
||||
const config = {
|
||||
staticDirectories: [
|
||||
// ---
|
||||
resolve(__dirname, "..", "static"),
|
||||
"static",
|
||||
],
|
||||
|
||||
themes: ["@goauthentik/docusaurus-theme"],
|
||||
|
||||
themeConfig: /** @type {UserThemeConfig & UserThemeConfigExtra} */ ({
|
||||
navbarReplacements: {
|
||||
DOCS_URL: "/",
|
||||
},
|
||||
algolia: {
|
||||
externalUrlRegex: /^(?:https?:\/\/)(integrations|api).?(goauthentik.io)/.source,
|
||||
},
|
||||
}),
|
||||
|
||||
plugins: [
|
||||
[
|
||||
"@docusaurus/theme-classic",
|
||||
{
|
||||
customCss: require.resolve("@goauthentik/docusaurus-config/css/index.css"),
|
||||
},
|
||||
],
|
||||
|
||||
[
|
||||
"@goauthentik/docusaurus-theme/releases/plugin",
|
||||
/** @type {ReleasesPluginOptions} */ ({
|
||||
docsDirectory: __dirname,
|
||||
}),
|
||||
],
|
||||
|
||||
//#region Documentation
|
||||
|
||||
[
|
||||
"@docusaurus/plugin-content-docs",
|
||||
deepmerge(
|
||||
CommonDocsPluginOptions,
|
||||
/** @type {DocsPluginOptions} */ ({
|
||||
id: "docs",
|
||||
routeBasePath: "/",
|
||||
path: ".",
|
||||
exclude: [...GlobExcludeDefault],
|
||||
include: ["**/*.mdx", "**/*.md"],
|
||||
|
||||
sidebarPath: "./sidebar.mjs",
|
||||
showLastUpdateTime: false,
|
||||
editUrl: "https://github.com/goauthentik/authentik/edit/main/docs/",
|
||||
|
||||
//#region Docs Plugins
|
||||
|
||||
beforeDefaultRemarkPlugins: [
|
||||
remarkLinkRewrite([
|
||||
// ---
|
||||
["/docs", ""],
|
||||
["/api", "https://api.goauthentik.io"],
|
||||
["/integrations", "https://integrations.goauthentik.io"],
|
||||
]),
|
||||
],
|
||||
}),
|
||||
),
|
||||
],
|
||||
],
|
||||
};
|
||||
|
||||
export default /** @type {Config} */ (deepmerge(CommonConfig, createDocusaurusConfig(config)));
|
@ -1,46 +0,0 @@
|
||||
[[plugins]]
|
||||
package = "netlify-plugin-cache"
|
||||
|
||||
[plugins.inputs]
|
||||
paths = [".docusaurus", ".cache", 'node_modules/.cache']
|
||||
|
||||
[[plugins]]
|
||||
package = "netlify-plugin-debug-cache"
|
||||
|
||||
[build]
|
||||
base = "docs"
|
||||
package = "topics"
|
||||
command = "npm run build -w topics"
|
||||
publish = "topics/build"
|
||||
|
||||
[dev]
|
||||
command = "npm start"
|
||||
targetPort = 3000
|
||||
publish = "topics/build"
|
||||
|
||||
[context.production.environment]
|
||||
NODE_ENV = "production"
|
||||
|
||||
[context.dev.environment]
|
||||
NODE_ENV = "development"
|
||||
|
||||
# Migration from docs to separate directory
|
||||
[[redirects]]
|
||||
from = "/docs/integrations/*"
|
||||
to = "https://integrations.goauthentik.io/:splat"
|
||||
status = 302
|
||||
|
||||
[[redirects]]
|
||||
from = "/integrations/*"
|
||||
to = "https://integrations.goauthentik.io/:splat"
|
||||
status = 302
|
||||
|
||||
[[redirects]]
|
||||
from = "/docs/*"
|
||||
to = "/:splat"
|
||||
status = 302
|
||||
|
||||
[[headers]]
|
||||
for = "/*"
|
||||
[headers.values]
|
||||
X-Frame-Options = "DENY"
|
@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "@goauthentik/docs-topics",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "run-s build:types build:docusaurus",
|
||||
"build:docusaurus": "docusaurus build",
|
||||
"build:types": "tsc -b .",
|
||||
"deploy": "docusaurus deploy",
|
||||
"docusaurus": "docusaurus",
|
||||
"serve": "docusaurus serve",
|
||||
"start": "docusaurus start",
|
||||
"test": "node --test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@goauthentik/docusaurus-theme": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24"
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"references": [
|
||||
{
|
||||
"path": "../docusaurus-theme"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// @file TSConfig used by the docs package during development.
|
||||
//
|
||||
// @remarks
|
||||
// While this configuration will influence the IDE experience,
|
||||
// Docusaurus will instead use an internal configuration to build the site.
|
||||
//
|
||||
// @see https://docusaurus.io/docs/typescript-support
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./docusaurus-theme"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "./api"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "./integrations"
|
||||
},
|
||||
{
|
||||
"path": "./topics"
|
||||
}
|
||||
]
|
||||
}
|
@ -23,8 +23,8 @@ export const DefaultIgnorePatterns = [
|
||||
"**/out",
|
||||
"**/dist",
|
||||
"**/.wireit",
|
||||
"docs/**/build/**",
|
||||
"docs/.docusaurus/**",
|
||||
"website/build/**",
|
||||
"website/.docusaurus/**",
|
||||
"**/node_modules",
|
||||
"**/coverage",
|
||||
"**/storybook-static",
|
||||
|
@ -144,9 +144,7 @@ skip = [
|
||||
"**/web/out",
|
||||
"./web/storybook-static",
|
||||
"./web/custom-elements.json",
|
||||
"./docs/build",
|
||||
"./docs/api/build",
|
||||
"./docs/integrations/build",
|
||||
"./website/build",
|
||||
"./gen-ts-api",
|
||||
"./gen-py-api",
|
||||
"./gen-go-api",
|
||||
@ -201,7 +199,7 @@ omit = [
|
||||
"*/migrations/*",
|
||||
"*/management/commands/*",
|
||||
"*/apps.py",
|
||||
"docs/",
|
||||
"website/",
|
||||
]
|
||||
|
||||
[tool.coverage.report]
|
||||
|
@ -39,10 +39,8 @@ const pluginName = "mdx-plugin";
|
||||
* @returns {Plugin}
|
||||
*/
|
||||
export function mdxPlugin({ root }) {
|
||||
const prefix = "~docs";
|
||||
|
||||
// TODO: Replace with `resolvePackage` after NPM Workspaces support is added.
|
||||
const docsPackageRoot = path.resolve(MonoRepoRoot, "docs");
|
||||
const docsPackageRoot = path.resolve(MonoRepoRoot, "website");
|
||||
|
||||
/**
|
||||
* @param {PluginBuild} build
|
||||
@ -56,8 +54,7 @@ export function mdxPlugin({ root }) {
|
||||
if (!args.path.startsWith("~")) return args;
|
||||
|
||||
return {
|
||||
path: path.join(docsPackageRoot, "topics", args.path.slice(prefix.length)),
|
||||
|
||||
path: path.resolve(docsPackageRoot, args.path.slice(1)),
|
||||
pluginName,
|
||||
};
|
||||
}
|
||||
@ -77,7 +74,7 @@ export function mdxPlugin({ root }) {
|
||||
|
||||
const publicPath = path.resolve(
|
||||
"/",
|
||||
path.relative(path.join(root, "docs", "topics"), data.path),
|
||||
path.relative(path.join(root, "website"), data.path),
|
||||
);
|
||||
const publicDirectory = path.dirname(publicPath);
|
||||
|
||||
|
@ -163,7 +163,7 @@ export class ProxyProviderViewPage extends AKElement {
|
||||
return input;
|
||||
}
|
||||
const extHost = new URL(this.provider.externalHost);
|
||||
// See docs/topics/add-secure-apps/providers/proxy/forward_auth.mdx
|
||||
// See website/docs/add-secure-apps/providers/proxy/forward_auth.mdx
|
||||
if (this.provider?.mode === ProxyMode.ForwardSingle) {
|
||||
return input
|
||||
.replaceAll("authentik.company", window.location.hostname)
|
||||
|
@ -7,6 +7,7 @@ import { MDXWrapper } from "#elements/ak-mdx/components/MDXWrapper";
|
||||
import { remarkAdmonition } from "#elements/ak-mdx/remark/remark-admonition";
|
||||
import { remarkHeadings } from "#elements/ak-mdx/remark/remark-headings";
|
||||
import { remarkLists } from "#elements/ak-mdx/remark/remark-lists";
|
||||
import { WithAuthentikConfig } from "#elements/mixins/config";
|
||||
import { DistDirectoryName, StaticDirectoryName } from "#paths";
|
||||
import { compile as compileMDX, run as runMDX } from "@mdx-js/mdx";
|
||||
import apacheGrammar from "highlight.js/lib/languages/apache";
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { useMDXModule } from "#elements/ak-mdx/MDXModuleContext";
|
||||
import { useMDXModule } from "@goauthentik/elements/ak-mdx/MDXModuleContext";
|
||||
import { resolve } from "node:path";
|
||||
import React from "react";
|
||||
import React, { memo } from "react";
|
||||
|
||||
const DOCS_DOMAIN = "https://docs.goauthentik.io";
|
||||
const DOCS_DOMAIN = "https://goauthentik.io";
|
||||
|
||||
/**
|
||||
* A custom anchor element that applies special behavior for MDX content.
|
||||
|
12
docs/.gitignore → website/.gitignore
vendored
@ -2,8 +2,6 @@
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/api/build
|
||||
/integrations/build
|
||||
/build
|
||||
/out
|
||||
/help
|
||||
@ -11,7 +9,6 @@
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
cache-output.json
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
@ -27,8 +24,7 @@ npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
**/static/docker-compose.yml
|
||||
**/static/schema.yml
|
||||
**/static/releases.gen.json
|
||||
api/reference
|
||||
!integrations/**/media
|
||||
static/docker-compose.yml
|
||||
static/schema.yml
|
||||
static/releases.gen.json
|
||||
docs/developer-docs/api/reference/**
|
21
website/Dockerfile
Normal file
@ -0,0 +1,21 @@
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24 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,id=npm-website,sharing=shared,target=/root/.npm \
|
||||
npm ci --include=dev
|
||||
|
||||
COPY ./website /work/website/
|
||||
COPY ./blueprints /work/blueprints/
|
||||
COPY ./schema.yml /work/
|
||||
COPY ./SECURITY.md /work/
|
||||
|
||||
RUN npm run build-bundled
|
||||
|
||||
FROM docker.io/library/nginx:1.27.5
|
||||
|
||||
COPY --from=website-builder /work/website/build /usr/share/nginx/html
|
@ -1,11 +1,11 @@
|
||||
# authentik documentation source
|
||||
|
||||
This directory contains the source files for the [authentik technical documentation](https://docs.goauthentik.io/docs?utm_source=github) and the [authentik integration guides](https://integrations.goauthentik.io?utm_source=github).
|
||||
This directory contains the source files for the [authentik technical documentation](https://docs.goauthentik.io/docs?utm_source=github) and the [authentik integration guides](https://docs.goauthentik.io/integrations?utm_source=github).
|
||||
|
||||
Contributions are welcome! Please refer to our [contributor guidelines](https://docs.goauthentik.io/developer-docs?utm_source=github) for details about contributing code or docs.
|
||||
Contributions are welcome! Please refer to our [contributor guidelines](https://docs.goauthentik.io/docs/developer-docs?utm_source=github) for details about contributing code or docs.
|
||||
|
||||
For instructions to set up your local environment for building docs locally, refer to our [Docs development environment](https://docs.goauthentik.io/developer-docs/setup/website-dev-environment?utm_source=github) page.
|
||||
For instructions to set up your local environment for building docs locally, refer to our [Docs development environment](https://docs.goauthentik.io/docs/developer-docs/setup/website-dev-environment?utm_source=github) page.
|
||||
|
||||
For instructions for writing the docs and then testing in your local build, plus tips on writing, links to our Style Guide and templates, see the [Writing documentation guide](https://docs.goauthentik.io/developer-docs/docs/writing-documentation?utm_source=github).
|
||||
For instructions for writing the docs and then testing in your local build, plus tips on writing, links to our Style Guide and templates, see the [Writing documentation guide](https://docs.goauthentik.io/docs/developer-docs/docs/writing-documentation?utm_source=github).
|
||||
|
||||
To ensure a smooth review process, we encourage you to build the documentation locally to preview and test your documentation contributions. Be sure to test locally before opening a pull request. Let us know if you have any questions or want help with any part of the process.
|
@ -45,7 +45,7 @@ When multiple policies/groups/users are attached, you can configure the _Policy
|
||||
|
||||
Application entitlements can be used through authentik to manage authorization within an application (what areas of the app users or groups can access). Entitlements are scoped to a single application and can be bound to multiple users and/or groups (binding policies is not currently supported), giving them access to the entitlement. An application can either check for the name of the entitlement (via the `entitlements` scope), or via attributes stored in entitlements.
|
||||
|
||||
An authentik admin can create an entitlement [in the Admin interface](#create-an-application-entitlement) or using the [authentik API](/api).
|
||||
An authentik admin can create an entitlement [in the Admin interface](#create-an-application-entitlement) or using the [authentik API](../../developer-docs/api/api.md).
|
||||
|
||||
Because entitlements exist within an application, names of entitlements must be unique within an application. This also means that entitlements are deleted when an application is deleted.
|
||||
|
@ -7,7 +7,7 @@ As covered in the [overview](./index.md), bindings interact with many other comp
|
||||
For instructions to create a binding, refer to the documentation for the specific components:
|
||||
|
||||
- [Bind a stage to a flow](../stages/index.md#bind-a-stage-to-a-flow)
|
||||
- [Bind a policy to a flow or stage](../../../customize/policies/working_with_policies.md#bind-a-policy-to-a-flow-or-stage)
|
||||
- [Bind a policy to a flow or stage](../../../customize/policies/working_with_policies#bind-a-policy-to-a-flow-or-stage)
|
||||
- [Bind users or groups to a specific application with an Application Entitlement](../../applications/manage_apps.mdx#application-entitlements)
|
||||
- [Bind a policy to a specific application when you create a new application and provider](../../applications/manage_apps.mdx#instructions)
|
||||
- [Bind users and groups to a stage binding, to define whether or not that stage is shown](../stages/index.md#bind-users-and-groups-to-a-flows-stage-binding)
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
@ -5,7 +5,7 @@ title: Default
|
||||
This is the default, web-based environment that flows are executed in. All stages are compatible with this environment and no limitations are imposed.
|
||||
|
||||
:::info
|
||||
All flow executors use the same [API](/api/docs/flow-executor), which allows for the implementation of custom flow executors.
|
||||
All flow executors use the same [API](../../../../developer-docs/api/flow-executor.md), which allows for the implementation of custom flow executors.
|
||||
:::
|
||||
|
||||
## Layouts
|
Before Width: | Height: | Size: 564 KiB After Width: | Height: | Size: 564 KiB |
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 2.8 MiB |
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 2.8 MiB |
Before Width: | Height: | Size: 2.2 MiB After Width: | Height: | Size: 2.2 MiB |