Merge branch 'master' into version-2021.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> # Conflicts: # docker-compose.yml # helm/README.md # web/src/authentik.css # web/src/flows/FlowExecutor.ts # web/src/flows/stages/identification/IdentificationStage.ts # website/docs/installation/kubernetes.md
This commit is contained in:
commit
2713b05e8c
|
@ -36,3 +36,7 @@ values =
|
||||||
[bumpversion:file:outpost/pkg/version.go]
|
[bumpversion:file:outpost/pkg/version.go]
|
||||||
|
|
||||||
[bumpversion:file:web/src/constants.ts]
|
[bumpversion:file:web/src/constants.ts]
|
||||||
|
|
||||||
|
[bumpversion:file:website/docs/outpusts/manual-deploy-docker-compose.md]
|
||||||
|
|
||||||
|
[bumpversion:file:website/docs/outpusts/manual-deploy-kubernetes.md]
|
||||||
|
|
|
@ -59,6 +59,9 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
|
- name: prepare ts api client
|
||||||
|
run: |
|
||||||
|
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/src/api --additional-properties=typescriptThreePlus=true
|
||||||
- name: Docker Login Registry
|
- name: Docker Login Registry
|
||||||
env:
|
env:
|
||||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
|
@ -45,4 +45,5 @@ COPY ./lifecycle/ /lifecycle
|
||||||
USER authentik
|
USER authentik
|
||||||
STOPSIGNAL SIGINT
|
STOPSIGNAL SIGINT
|
||||||
ENV TMPDIR /dev/shm/
|
ENV TMPDIR /dev/shm/
|
||||||
|
ENV PYTHONUBUFFERED 1
|
||||||
ENTRYPOINT [ "/lifecycle/bootstrap.sh" ]
|
ENTRYPOINT [ "/lifecycle/bootstrap.sh" ]
|
||||||
|
|
|
@ -18,45 +18,45 @@
|
||||||
"default": {
|
"default": {
|
||||||
"aiohttp": {
|
"aiohttp": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:119feb2bd551e58d83d1b38bfa4cb921af8ddedec9fad7183132db334c3133e0",
|
"sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe",
|
||||||
"sha256:16d0683ef8a6d803207f02b899c928223eb219111bd52420ef3d7a8aa76227b6",
|
"sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe",
|
||||||
"sha256:2eb3efe243e0f4ecbb654b08444ae6ffab37ac0ef8f69d3a2ffb958905379daf",
|
"sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5",
|
||||||
"sha256:2ffea7904e70350da429568113ae422c88d2234ae776519549513c8f217f58a9",
|
"sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8",
|
||||||
"sha256:40bd1b101b71a18a528ffce812cc14ff77d4a2a1272dfb8b11b200967489ef3e",
|
"sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd",
|
||||||
"sha256:418597633b5cd9639e514b1d748f358832c08cd5d9ef0870026535bd5eaefdd0",
|
"sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb",
|
||||||
"sha256:481d4b96969fbfdcc3ff35eea5305d8565a8300410d3d269ccac69e7256b1329",
|
"sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c",
|
||||||
"sha256:4c1bdbfdd231a20eee3e56bd0ac1cd88c4ff41b64ab679ed65b75c9c74b6c5c2",
|
"sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87",
|
||||||
"sha256:5563ad7fde451b1986d42b9bb9140e2599ecf4f8e42241f6da0d3d624b776f40",
|
"sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0",
|
||||||
"sha256:58c62152c4c8731a3152e7e650b29ace18304d086cb5552d317a54ff2749d32a",
|
"sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290",
|
||||||
"sha256:5b50e0b9460100fe05d7472264d1975f21ac007b35dcd6fd50279b72925a27f4",
|
"sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5",
|
||||||
"sha256:5d84ecc73141d0a0d61ece0742bb7ff5751b0657dab8405f899d3ceb104cc7de",
|
"sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287",
|
||||||
"sha256:5dde6d24bacac480be03f4f864e9a67faac5032e28841b00533cd168ab39cad9",
|
"sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde",
|
||||||
"sha256:5e91e927003d1ed9283dee9abcb989334fc8e72cf89ebe94dc3e07e3ff0b11e9",
|
"sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf",
|
||||||
"sha256:62bc216eafac3204877241569209d9ba6226185aa6d561c19159f2e1cbb6abfb",
|
"sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8",
|
||||||
"sha256:6c8200abc9dc5f27203986100579fc19ccad7a832c07d2bc151ce4ff17190076",
|
"sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16",
|
||||||
"sha256:6ca56bdfaf825f4439e9e3673775e1032d8b6ea63b8953d3812c71bd6a8b81de",
|
"sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf",
|
||||||
"sha256:71680321a8a7176a58dfbc230789790639db78dad61a6e120b39f314f43f1907",
|
"sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809",
|
||||||
"sha256:7c7820099e8b3171e54e7eedc33e9450afe7cd08172632d32128bd527f8cb77d",
|
"sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213",
|
||||||
"sha256:7dbd087ff2f4046b9b37ba28ed73f15fd0bc9f4fdc8ef6781913da7f808d9536",
|
"sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f",
|
||||||
"sha256:822bd4fd21abaa7b28d65fc9871ecabaddc42767884a626317ef5b75c20e8a2d",
|
"sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013",
|
||||||
"sha256:8ec1a38074f68d66ccb467ed9a673a726bb397142c273f90d4ba954666e87d54",
|
"sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b",
|
||||||
"sha256:950b7ef08b2afdab2488ee2edaff92a03ca500a48f1e1aaa5900e73d6cf992bc",
|
"sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9",
|
||||||
"sha256:99c5a5bf7135607959441b7d720d96c8e5c46a1f96e9d6d4c9498be8d5f24212",
|
"sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5",
|
||||||
"sha256:b84ad94868e1e6a5e30d30ec419956042815dfaea1b1df1cef623e4564c374d9",
|
"sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb",
|
||||||
"sha256:bc3d14bf71a3fb94e5acf5bbf67331ab335467129af6416a437bd6024e4f743d",
|
"sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df",
|
||||||
"sha256:c2a80fd9a8d7e41b4e38ea9fe149deed0d6aaede255c497e66b8213274d6d61b",
|
"sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4",
|
||||||
"sha256:c44d3c82a933c6cbc21039326767e778eface44fca55c65719921c4b9661a3f7",
|
"sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439",
|
||||||
"sha256:cc31e906be1cc121ee201adbdf844522ea3349600dd0a40366611ca18cd40e81",
|
"sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f",
|
||||||
"sha256:d5d102e945ecca93bcd9801a7bb2fa703e37ad188a2f81b1e65e4abe4b51b00c",
|
"sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22",
|
||||||
"sha256:dd7936f2a6daa861143e376b3a1fb56e9b802f4980923594edd9ca5670974895",
|
"sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f",
|
||||||
"sha256:dee68ec462ff10c1d836c0ea2642116aba6151c6880b688e56b4c0246770f297",
|
"sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5",
|
||||||
"sha256:e76e78863a4eaec3aee5722d85d04dcbd9844bc6cd3bfa6aa880ff46ad16bfcb",
|
"sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970",
|
||||||
"sha256:eab51036cac2da8a50d7ff0ea30be47750547c9aa1aa2cf1a1b710a1827e7dbe",
|
"sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009",
|
||||||
"sha256:f4496d8d04da2e98cc9133e238ccebf6a13ef39a93da2e87146c8c8ac9768242",
|
"sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc",
|
||||||
"sha256:fbd3b5e18d34683decc00d9a360179ac1e7a320a5fee10ab8053ffd6deab76e0",
|
"sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a",
|
||||||
"sha256:feb24ff1226beeb056e247cf2e24bba5232519efb5645121c4aea5b6ad74c1f2"
|
"sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95"
|
||||||
],
|
],
|
||||||
"version": "==3.7.4"
|
"version": "==3.7.4.post0"
|
||||||
},
|
},
|
||||||
"aioredis": {
|
"aioredis": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -116,18 +116,17 @@
|
||||||
},
|
},
|
||||||
"boto3": {
|
"boto3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:2219f1ebe88d266afa5516f993983eba8742b957fa4fd6854f3c73aa3030e931",
|
"sha256:64a8900b3a110e2d6ff4d87f4d8cd56f0c8527361d9fc9385fcb50efe7a4975a",
|
||||||
"sha256:c0d51f344b71656c2d395d2168600d91bea252a64fb5d503a955ea96426cde8b"
|
"sha256:8e9ff8006c41889ed8a11831dee62adf922e071f14d54c52946d1f7855ae7a8e"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==1.17.20"
|
"version": "==1.17.26"
|
||||||
},
|
},
|
||||||
"botocore": {
|
"botocore": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:80c32a81fb1ee8bdfa074a79bfb885bb2006e8a9782f2353c0c9f6392704e13a",
|
"sha256:4a785847a351e59f2329627fc9a19cf50f07644ea68996a1595d5a20487a423f"
|
||||||
"sha256:e9e724b59278ebf5caf032be1e32bde0990d79e8052e3bbbb97b6c1d32feba28"
|
|
||||||
],
|
],
|
||||||
"version": "==1.20.20"
|
"version": "==1.20.26"
|
||||||
},
|
},
|
||||||
"cachetools": {
|
"cachetools": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -217,10 +216,10 @@
|
||||||
},
|
},
|
||||||
"chardet": {
|
"chardet": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
"sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
|
||||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
"sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
|
||||||
],
|
],
|
||||||
"version": "==3.0.4"
|
"version": "==4.0.0"
|
||||||
},
|
},
|
||||||
"click": {
|
"click": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -304,11 +303,11 @@
|
||||||
},
|
},
|
||||||
"defusedxml": {
|
"defusedxml": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93",
|
"sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69",
|
||||||
"sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"
|
"sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.6.0"
|
"version": "==0.7.1"
|
||||||
},
|
},
|
||||||
"django": {
|
"django": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -445,10 +444,10 @@
|
||||||
},
|
},
|
||||||
"google-auth": {
|
"google-auth": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:d3640ea61ee025d5af00e3ffd82ba0a06dd99724adaf50bdd52f49daf29f3f65",
|
"sha256:63a5636d7eacfe6ef5b7e36e112b3149fa1c5b5ad77dd6df54910459bcd6b89f",
|
||||||
"sha256:da5218cbf33b8461d7661d6b4ad91c12c0107e2767904d5e3ae6408031d5463e"
|
"sha256:d8958af6968e4ecd599f82357ebcfeb126f826ed0656126ad68416f810f7531e"
|
||||||
],
|
],
|
||||||
"version": "==1.27.0"
|
"version": "==1.27.1"
|
||||||
},
|
},
|
||||||
"gunicorn": {
|
"gunicorn": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -817,10 +816,10 @@
|
||||||
},
|
},
|
||||||
"prompt-toolkit": {
|
"prompt-toolkit": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0fa02fa80363844a4ab4b8d6891f62dd0645ba672723130423ca4037b80c1974",
|
"sha256:4cea7d09e46723885cb8bc54678175453e5071e9449821dce6f017b1d1fbfc1a",
|
||||||
"sha256:62c811e46bd09130fb11ab759012a4ae385ce4fb2073442d1898867a824183bd"
|
"sha256:9397a7162cf45449147ad6042fa37983a081b8a73363a5253dd4072666333137"
|
||||||
],
|
],
|
||||||
"version": "==3.0.16"
|
"version": "==3.0.17"
|
||||||
},
|
},
|
||||||
"psycopg2-binary": {
|
"psycopg2-binary": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -1024,15 +1023,23 @@
|
||||||
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
|
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
|
||||||
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
|
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
|
||||||
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
|
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
|
||||||
|
"sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
|
||||||
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
|
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
|
||||||
|
"sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
|
||||||
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
|
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
|
||||||
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
|
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
|
||||||
|
"sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
|
||||||
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
|
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
|
||||||
|
"sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
|
||||||
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
|
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
|
||||||
|
"sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
|
||||||
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
|
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
|
||||||
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
|
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
|
||||||
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
|
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
|
||||||
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"
|
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
|
||||||
|
"sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
|
||||||
|
"sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
|
||||||
|
"sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==5.4.1"
|
"version": "==5.4.1"
|
||||||
|
@ -1069,10 +1076,47 @@
|
||||||
},
|
},
|
||||||
"ruamel.yaml": {
|
"ruamel.yaml": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5",
|
"sha256:64b06e7873eb8e1125525ecef7345447d786368cadca92a7cd9b59eae62e95a3",
|
||||||
"sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e"
|
"sha256:bb48c514222702878759a05af96f4b7ecdba9b33cd4efcf25c86b882cef3a942"
|
||||||
],
|
],
|
||||||
"version": "==0.16.12"
|
"version": "==0.16.13"
|
||||||
|
},
|
||||||
|
"ruamel.yaml.clib": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b",
|
||||||
|
"sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f",
|
||||||
|
"sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c",
|
||||||
|
"sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91",
|
||||||
|
"sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc",
|
||||||
|
"sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7",
|
||||||
|
"sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3",
|
||||||
|
"sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7",
|
||||||
|
"sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6",
|
||||||
|
"sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6",
|
||||||
|
"sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd",
|
||||||
|
"sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0",
|
||||||
|
"sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62",
|
||||||
|
"sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99",
|
||||||
|
"sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5",
|
||||||
|
"sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026",
|
||||||
|
"sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb",
|
||||||
|
"sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2",
|
||||||
|
"sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1",
|
||||||
|
"sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4",
|
||||||
|
"sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b",
|
||||||
|
"sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923",
|
||||||
|
"sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e",
|
||||||
|
"sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c",
|
||||||
|
"sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988",
|
||||||
|
"sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f",
|
||||||
|
"sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5",
|
||||||
|
"sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a",
|
||||||
|
"sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1",
|
||||||
|
"sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2",
|
||||||
|
"sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f"
|
||||||
|
],
|
||||||
|
"markers": "platform_python_implementation == 'CPython' and python_version < '3.10'",
|
||||||
|
"version": "==0.2.2"
|
||||||
},
|
},
|
||||||
"s3transfer": {
|
"s3transfer": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -1765,15 +1809,23 @@
|
||||||
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
|
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
|
||||||
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
|
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
|
||||||
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
|
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
|
||||||
|
"sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
|
||||||
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
|
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
|
||||||
|
"sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
|
||||||
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
|
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
|
||||||
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
|
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
|
||||||
|
"sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
|
||||||
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
|
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
|
||||||
|
"sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
|
||||||
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
|
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
|
||||||
|
"sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
|
||||||
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
|
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
|
||||||
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
|
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
|
||||||
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
|
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
|
||||||
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"
|
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
|
||||||
|
"sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
|
||||||
|
"sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
|
||||||
|
"sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==5.4.1"
|
"version": "==5.4.1"
|
||||||
|
|
|
@ -7,8 +7,8 @@ from django.db.models import Count, ExpressionWrapper, F, Model
|
||||||
from django.db.models.fields import DurationField
|
from django.db.models.fields import DurationField
|
||||||
from django.db.models.functions import ExtractHour
|
from django.db.models.functions import ExtractHour
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from drf_yasg2.utils import swagger_auto_schema
|
from drf_yasg2.utils import swagger_auto_schema, swagger_serializer_method
|
||||||
from rest_framework.fields import SerializerMethodField
|
from rest_framework.fields import IntegerField, SerializerMethodField
|
||||||
from rest_framework.permissions import IsAdminUser
|
from rest_framework.permissions import IsAdminUser
|
||||||
from rest_framework.request import Request
|
from rest_framework.request import Request
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
@ -37,23 +37,39 @@ def get_events_per_1h(**filter_kwargs) -> list[dict[str, int]]:
|
||||||
for hour in range(0, -24, -1):
|
for hour in range(0, -24, -1):
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
"x": time.mktime((_now + timedelta(hours=hour)).timetuple()) * 1000,
|
"x_cord": time.mktime((_now + timedelta(hours=hour)).timetuple())
|
||||||
"y": data[hour * -1],
|
* 1000,
|
||||||
|
"y_cord": data[hour * -1],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
class AdministrationMetricsSerializer(Serializer):
|
class CoordinateSerializer(Serializer):
|
||||||
|
"""Coordinates for diagrams"""
|
||||||
|
|
||||||
|
x_cord = IntegerField(read_only=True)
|
||||||
|
y_cord = IntegerField(read_only=True)
|
||||||
|
|
||||||
|
def create(self, validated_data: dict) -> Model:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def update(self, instance: Model, validated_data: dict) -> Model:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class LoginMetricsSerializer(Serializer):
|
||||||
"""Login Metrics per 1h"""
|
"""Login Metrics per 1h"""
|
||||||
|
|
||||||
logins_per_1h = SerializerMethodField()
|
logins_per_1h = SerializerMethodField()
|
||||||
logins_failed_per_1h = SerializerMethodField()
|
logins_failed_per_1h = SerializerMethodField()
|
||||||
|
|
||||||
|
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
|
||||||
def get_logins_per_1h(self, _):
|
def get_logins_per_1h(self, _):
|
||||||
"""Get successful logins per hour for the last 24 hours"""
|
"""Get successful logins per hour for the last 24 hours"""
|
||||||
return get_events_per_1h(action=EventAction.LOGIN)
|
return get_events_per_1h(action=EventAction.LOGIN)
|
||||||
|
|
||||||
|
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
|
||||||
def get_logins_failed_per_1h(self, _):
|
def get_logins_failed_per_1h(self, _):
|
||||||
"""Get failed logins per hour for the last 24 hours"""
|
"""Get failed logins per hour for the last 24 hours"""
|
||||||
return get_events_per_1h(action=EventAction.LOGIN_FAILED)
|
return get_events_per_1h(action=EventAction.LOGIN_FAILED)
|
||||||
|
@ -70,8 +86,8 @@ class AdministrationMetricsViewSet(ViewSet):
|
||||||
|
|
||||||
permission_classes = [IsAdminUser]
|
permission_classes = [IsAdminUser]
|
||||||
|
|
||||||
@swagger_auto_schema(responses={200: AdministrationMetricsSerializer(many=True)})
|
@swagger_auto_schema(responses={200: LoginMetricsSerializer(many=False)})
|
||||||
def list(self, request: Request) -> Response:
|
def list(self, request: Request) -> Response:
|
||||||
"""Login Metrics per 1h"""
|
"""Login Metrics per 1h"""
|
||||||
serializer = AdministrationMetricsSerializer(True)
|
serializer = LoginMetricsSerializer(True)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
|
@ -25,8 +25,8 @@ class TaskSerializer(Serializer):
|
||||||
task_finish_timestamp = DateTimeField(source="finish_timestamp")
|
task_finish_timestamp = DateTimeField(source="finish_timestamp")
|
||||||
|
|
||||||
status = ChoiceField(
|
status = ChoiceField(
|
||||||
source="result.status.value",
|
source="result.status.name",
|
||||||
choices=[(x.value, x.name) for x in TaskResultStatus],
|
choices=[(x.name, x.name) for x in TaskResultStatus],
|
||||||
)
|
)
|
||||||
messages = ListField(source="result.messages")
|
messages = ListField(source="result.messages")
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"""api v2 urls"""
|
"""api v2 urls"""
|
||||||
|
from django.conf import settings
|
||||||
from django.urls import path, re_path
|
from django.urls import path, re_path
|
||||||
from drf_yasg2 import openapi
|
from drf_yasg2 import openapi
|
||||||
from drf_yasg2.views import get_schema_view
|
from drf_yasg2.views import get_schema_view
|
||||||
|
@ -54,12 +55,24 @@ from authentik.providers.saml.api import SAMLPropertyMappingViewSet, SAMLProvide
|
||||||
from authentik.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet
|
from authentik.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet
|
||||||
from authentik.sources.oauth.api import OAuthSourceViewSet
|
from authentik.sources.oauth.api import OAuthSourceViewSet
|
||||||
from authentik.sources.saml.api import SAMLSourceViewSet
|
from authentik.sources.saml.api import SAMLSourceViewSet
|
||||||
from authentik.stages.authenticator_static.api import AuthenticatorStaticStageViewSet
|
from authentik.stages.authenticator_static.api import (
|
||||||
from authentik.stages.authenticator_totp.api import AuthenticatorTOTPStageViewSet
|
AuthenticatorStaticStageViewSet,
|
||||||
|
StaticAdminDeviceViewSet,
|
||||||
|
StaticDeviceViewSet,
|
||||||
|
)
|
||||||
|
from authentik.stages.authenticator_totp.api import (
|
||||||
|
AuthenticatorTOTPStageViewSet,
|
||||||
|
TOTPAdminDeviceViewSet,
|
||||||
|
TOTPDeviceViewSet,
|
||||||
|
)
|
||||||
from authentik.stages.authenticator_validate.api import (
|
from authentik.stages.authenticator_validate.api import (
|
||||||
AuthenticatorValidateStageViewSet,
|
AuthenticatorValidateStageViewSet,
|
||||||
)
|
)
|
||||||
from authentik.stages.authenticator_webauthn.api import AuthenticateWebAuthnStageViewSet
|
from authentik.stages.authenticator_webauthn.api import (
|
||||||
|
AuthenticateWebAuthnStageViewSet,
|
||||||
|
WebAuthnAdminDeviceViewSet,
|
||||||
|
WebAuthnDeviceViewSet,
|
||||||
|
)
|
||||||
from authentik.stages.captcha.api import CaptchaStageViewSet
|
from authentik.stages.captcha.api import CaptchaStageViewSet
|
||||||
from authentik.stages.consent.api import ConsentStageViewSet
|
from authentik.stages.consent.api import ConsentStageViewSet
|
||||||
from authentik.stages.deny.api import DenyStageViewSet
|
from authentik.stages.deny.api import DenyStageViewSet
|
||||||
|
@ -133,6 +146,13 @@ router.register("propertymappings/ldap", LDAPPropertyMappingViewSet)
|
||||||
router.register("propertymappings/saml", SAMLPropertyMappingViewSet)
|
router.register("propertymappings/saml", SAMLPropertyMappingViewSet)
|
||||||
router.register("propertymappings/scope", ScopeMappingViewSet)
|
router.register("propertymappings/scope", ScopeMappingViewSet)
|
||||||
|
|
||||||
|
router.register("authenticators/static", StaticDeviceViewSet)
|
||||||
|
router.register("authenticators/totp", TOTPDeviceViewSet)
|
||||||
|
router.register("authenticators/webauthn", WebAuthnDeviceViewSet)
|
||||||
|
router.register("authenticators/admin/static", StaticAdminDeviceViewSet)
|
||||||
|
router.register("authenticators/admin/totp", TOTPAdminDeviceViewSet)
|
||||||
|
router.register("authenticators/admin/webauthn", WebAuthnAdminDeviceViewSet)
|
||||||
|
|
||||||
router.register("stages/all", StageViewSet)
|
router.register("stages/all", StageViewSet)
|
||||||
router.register("stages/authenticator/static", AuthenticatorStaticStageViewSet)
|
router.register("stages/authenticator/static", AuthenticatorStaticStageViewSet)
|
||||||
router.register("stages/authenticator/totp", AuthenticatorTOTPStageViewSet)
|
router.register("stages/authenticator/totp", AuthenticatorTOTPStageViewSet)
|
||||||
|
@ -164,27 +184,26 @@ info = openapi.Info(
|
||||||
name="GNU GPLv3", url="https://github.com/BeryJu/authentik/blob/master/LICENSE"
|
name="GNU GPLv3", url="https://github.com/BeryJu/authentik/blob/master/LICENSE"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
SchemaView = get_schema_view(
|
SchemaView = get_schema_view(info, public=True, permission_classes=(AllowAny,))
|
||||||
info,
|
|
||||||
public=True,
|
|
||||||
permission_classes=(AllowAny,),
|
|
||||||
)
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = router.urls + [
|
||||||
re_path(
|
|
||||||
r"^swagger(?P<format>\.json|\.yaml)$",
|
|
||||||
SchemaView.without_ui(cache_timeout=0),
|
|
||||||
name="schema-json",
|
|
||||||
),
|
|
||||||
path(
|
|
||||||
"swagger/",
|
|
||||||
SchemaView.with_ui("swagger", cache_timeout=0),
|
|
||||||
name="schema-swagger-ui",
|
|
||||||
),
|
|
||||||
path("redoc/", SchemaView.with_ui("redoc", cache_timeout=0), name="schema-redoc"),
|
|
||||||
path(
|
path(
|
||||||
"flows/executor/<slug:flow_slug>/",
|
"flows/executor/<slug:flow_slug>/",
|
||||||
FlowExecutorView.as_view(),
|
FlowExecutorView.as_view(),
|
||||||
name="flow-executor",
|
name="flow-executor",
|
||||||
),
|
),
|
||||||
] + router.urls
|
re_path(
|
||||||
|
r"^swagger(?P<format>\.json|\.yaml)$",
|
||||||
|
SchemaView.without_ui(cache_timeout=0),
|
||||||
|
name="schema-json",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
urlpatterns = urlpatterns + [
|
||||||
|
path(
|
||||||
|
"swagger/",
|
||||||
|
SchemaView.with_ui("swagger", cache_timeout=0),
|
||||||
|
name="schema-swagger-ui",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
from django.http.response import Http404
|
from django.http.response import Http404
|
||||||
|
from drf_yasg2.utils import swagger_auto_schema
|
||||||
from guardian.shortcuts import get_objects_for_user
|
from guardian.shortcuts import get_objects_for_user
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.fields import SerializerMethodField
|
from rest_framework.fields import SerializerMethodField
|
||||||
|
@ -13,7 +14,7 @@ from rest_framework.viewsets import ModelViewSet
|
||||||
from rest_framework_guardian.filters import ObjectPermissionsFilter
|
from rest_framework_guardian.filters import ObjectPermissionsFilter
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
from authentik.admin.api.metrics import get_events_per_1h
|
from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h
|
||||||
from authentik.core.api.providers import ProviderSerializer
|
from authentik.core.api.providers import ProviderSerializer
|
||||||
from authentik.core.models import Application
|
from authentik.core.models import Application
|
||||||
from authentik.events.models import EventAction
|
from authentik.events.models import EventAction
|
||||||
|
@ -109,6 +110,7 @@ class ApplicationViewSet(ModelViewSet):
|
||||||
serializer = self.get_serializer(allowed_applications, many=True)
|
serializer = self.get_serializer(allowed_applications, many=True)
|
||||||
return self.get_paginated_response(serializer.data)
|
return self.get_paginated_response(serializer.data)
|
||||||
|
|
||||||
|
@swagger_auto_schema(responses={200: CoordinateSerializer(many=True)})
|
||||||
@action(detail=True)
|
@action(detail=True)
|
||||||
def metrics(self, request: Request, slug: str):
|
def metrics(self, request: Request, slug: str):
|
||||||
"""Metrics for application logins"""
|
"""Metrics for application logins"""
|
||||||
|
|
|
@ -21,3 +21,4 @@ class GroupViewSet(ModelViewSet):
|
||||||
serializer_class = GroupSerializer
|
serializer_class = GroupSerializer
|
||||||
search_fields = ["name", "is_superuser"]
|
search_fields = ["name", "is_superuser"]
|
||||||
filterset_fields = ["name", "is_superuser"]
|
filterset_fields = ["name", "is_superuser"]
|
||||||
|
ordering = ["name"]
|
||||||
|
|
|
@ -28,9 +28,9 @@ class MetaNameSerializer(Serializer):
|
||||||
class TypeCreateSerializer(Serializer):
|
class TypeCreateSerializer(Serializer):
|
||||||
"""Types of an object that can be created"""
|
"""Types of an object that can be created"""
|
||||||
|
|
||||||
name = CharField(read_only=True)
|
name = CharField(required=True)
|
||||||
description = CharField(read_only=True)
|
description = CharField(required=True)
|
||||||
link = CharField(read_only=True)
|
link = CharField(required=True)
|
||||||
|
|
||||||
def create(self, validated_data: dict) -> Model:
|
def create(self, validated_data: dict) -> Model:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
{% extends container_template|default:"administration/base.html" %}
|
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load authentik_utils %}
|
{% load authentik_utils %}
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<section class="pf-c-page__main-section pf-m-light">
|
<section class="pf-c-page__main-section pf-m-light">
|
||||||
<div class="pf-c-content">
|
<div class="pf-c-content">
|
||||||
{% block above_form %}
|
{% block above_form %}
|
||||||
|
@ -38,4 +35,3 @@
|
||||||
<input class="pf-c-button pf-m-danger" type="submit" form="delete-form" value="{% trans 'Delete' %}" />
|
<input class="pf-c-button pf-m-danger" type="submit" form="delete-form" value="{% trans 'Delete' %}" />
|
||||||
<a class="pf-c-button pf-m-secondary" href="{% back %}">{% trans "Back" %}</a>
|
<a class="pf-c-button pf-m-secondary" href="{% back %}">{% trans "Back" %}</a>
|
||||||
</footer>
|
</footer>
|
||||||
{% endblock %}
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.contrib.auth.mixins import (
|
||||||
)
|
)
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.http.response import HttpResponse
|
from django.http.response import HttpResponse
|
||||||
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic import UpdateView
|
from django.views.generic import UpdateView
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
|
@ -34,7 +35,7 @@ class UserDetailsView(SuccessMessageMixin, LoginRequiredMixin, UpdateView):
|
||||||
form_class = UserDetailForm
|
form_class = UserDetailForm
|
||||||
|
|
||||||
success_message = _("Successfully updated user.")
|
success_message = _("Successfully updated user.")
|
||||||
success_url = "/"
|
success_url = reverse_lazy("authentik_core:user-details")
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self.request.user
|
return self.request.user
|
||||||
|
|
|
@ -13,7 +13,7 @@ class NotificationSerializer(ModelSerializer):
|
||||||
|
|
||||||
body = ReadOnlyField()
|
body = ReadOnlyField()
|
||||||
severity = ReadOnlyField()
|
severity = ReadOnlyField()
|
||||||
event = EventSerializer()
|
event = EventSerializer(required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
"""NotificationTransport API Views"""
|
"""NotificationTransport API Views"""
|
||||||
from django.http.response import Http404
|
from django.http.response import Http404
|
||||||
|
from drf_yasg2.utils import no_body, swagger_auto_schema
|
||||||
from guardian.shortcuts import get_objects_for_user
|
from guardian.shortcuts import get_objects_for_user
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.fields import SerializerMethodField
|
from rest_framework.fields import CharField, ListField, SerializerMethodField
|
||||||
from rest_framework.request import Request
|
from rest_framework.request import Request
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer, Serializer
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
|
|
||||||
from authentik.events.models import (
|
from authentik.events.models import (
|
||||||
|
@ -38,12 +39,28 @@ class NotificationTransportSerializer(ModelSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationTransportTestSerializer(Serializer):
|
||||||
|
"""Notification test serializer"""
|
||||||
|
|
||||||
|
messages = ListField(child=CharField())
|
||||||
|
|
||||||
|
def create(self, request: Request) -> Response:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def update(self, request: Request) -> Response:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class NotificationTransportViewSet(ModelViewSet):
|
class NotificationTransportViewSet(ModelViewSet):
|
||||||
"""NotificationTransport Viewset"""
|
"""NotificationTransport Viewset"""
|
||||||
|
|
||||||
queryset = NotificationTransport.objects.all()
|
queryset = NotificationTransport.objects.all()
|
||||||
serializer_class = NotificationTransportSerializer
|
serializer_class = NotificationTransportSerializer
|
||||||
|
|
||||||
|
@swagger_auto_schema(
|
||||||
|
responses={200: NotificationTransportTestSerializer(many=False)},
|
||||||
|
request_body=no_body,
|
||||||
|
)
|
||||||
@action(detail=True, methods=["post"])
|
@action(detail=True, methods=["post"])
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
def test(self, request: Request, pk=None) -> Response:
|
def test(self, request: Request, pk=None) -> Response:
|
||||||
|
@ -61,6 +78,10 @@ class NotificationTransportViewSet(ModelViewSet):
|
||||||
user=request.user,
|
user=request.user,
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
return Response(transport.send(notification))
|
response = NotificationTransportTestSerializer(
|
||||||
|
data={"messages": transport.send(notification)}
|
||||||
|
)
|
||||||
|
response.is_valid()
|
||||||
|
return Response(response.data)
|
||||||
except NotificationTransportError as exc:
|
except NotificationTransportError as exc:
|
||||||
return Response(str(exc.__cause__ or None), status=503)
|
return Response(str(exc.__cause__ or None), status=503)
|
||||||
|
|
|
@ -12,7 +12,10 @@ def get_geoip_reader() -> Optional[Reader]:
|
||||||
path = CONFIG.y("authentik.geoip")
|
path = CONFIG.y("authentik.geoip")
|
||||||
if path == "" or not path:
|
if path == "" or not path:
|
||||||
return None
|
return None
|
||||||
|
try:
|
||||||
return Reader(path)
|
return Reader(path)
|
||||||
|
except OSError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
GEOIP_READER = get_geoip_reader()
|
GEOIP_READER = get_geoip_reader()
|
||||||
|
|
|
@ -38,7 +38,9 @@ class Challenge(Serializer):
|
||||||
"""Challenge that gets sent to the client based on which stage
|
"""Challenge that gets sent to the client based on which stage
|
||||||
is currently active"""
|
is currently active"""
|
||||||
|
|
||||||
type = ChoiceField(choices=list(ChallengeTypes))
|
type = ChoiceField(
|
||||||
|
choices=[(x.name, x.name) for x in ChallengeTypes],
|
||||||
|
)
|
||||||
component = CharField(required=False)
|
component = CharField(required=False)
|
||||||
title = CharField(required=False)
|
title = CharField(required=False)
|
||||||
|
|
||||||
|
@ -90,7 +92,7 @@ class ChallengeResponse(Serializer):
|
||||||
|
|
||||||
stage: Optional["StageView"]
|
stage: Optional["StageView"]
|
||||||
|
|
||||||
def __init__(self, instance, data, **kwargs):
|
def __init__(self, instance=None, data=None, **kwargs):
|
||||||
self.stage = kwargs.pop("stage", None)
|
self.stage = kwargs.pop("stage", None)
|
||||||
super().__init__(instance=instance, data=data, **kwargs)
|
super().__init__(instance=instance, data=data, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.http import HttpRequest
|
||||||
from django.http.request import QueryDict
|
from django.http.request import QueryDict
|
||||||
from django.http.response import HttpResponse
|
from django.http.response import HttpResponse
|
||||||
from django.views.generic.base import View
|
from django.views.generic.base import View
|
||||||
|
from rest_framework.request import Request
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
from authentik.core.models import DEFAULT_AVATAR, User
|
from authentik.core.models import DEFAULT_AVATAR, User
|
||||||
|
@ -67,9 +68,9 @@ class ChallengeStageView(StageView):
|
||||||
return HttpChallengeResponse(challenge)
|
return HttpChallengeResponse(challenge)
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
def post(self, request: Request, *args, **kwargs) -> HttpResponse:
|
||||||
"""Handle challenge response"""
|
"""Handle challenge response"""
|
||||||
challenge: ChallengeResponse = self.get_response_instance(data=request.POST)
|
challenge: ChallengeResponse = self.get_response_instance(data=request.data)
|
||||||
if not challenge.is_valid():
|
if not challenge.is_valid():
|
||||||
return self.challenge_invalid(challenge)
|
return self.challenge_invalid(challenge)
|
||||||
return self.challenge_valid(challenge)
|
return self.challenge_valid(challenge)
|
||||||
|
|
|
@ -9,11 +9,16 @@ from django.template.response import TemplateResponse
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
||||||
from django.views.generic import TemplateView, View
|
from django.views.generic import TemplateView, View
|
||||||
|
from drf_yasg2.utils import no_body, swagger_auto_schema
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.views import APIView
|
||||||
from structlog.stdlib import BoundLogger, get_logger
|
from structlog.stdlib import BoundLogger, get_logger
|
||||||
|
|
||||||
from authentik.core.models import USER_ATTRIBUTE_DEBUG
|
from authentik.core.models import USER_ATTRIBUTE_DEBUG
|
||||||
from authentik.events.models import cleanse_dict
|
from authentik.events.models import cleanse_dict
|
||||||
from authentik.flows.challenge import (
|
from authentik.flows.challenge import (
|
||||||
|
Challenge,
|
||||||
|
ChallengeResponse,
|
||||||
ChallengeTypes,
|
ChallengeTypes,
|
||||||
HttpChallengeResponse,
|
HttpChallengeResponse,
|
||||||
RedirectChallenge,
|
RedirectChallenge,
|
||||||
|
@ -40,9 +45,11 @@ SESSION_KEY_GET = "authentik_flows_get"
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(xframe_options_sameorigin, name="dispatch")
|
@method_decorator(xframe_options_sameorigin, name="dispatch")
|
||||||
class FlowExecutorView(View):
|
class FlowExecutorView(APIView):
|
||||||
"""Stage 1 Flow executor, passing requests to Stage Views"""
|
"""Stage 1 Flow executor, passing requests to Stage Views"""
|
||||||
|
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
flow: Flow
|
flow: Flow
|
||||||
|
|
||||||
plan: Optional[FlowPlan] = None
|
plan: Optional[FlowPlan] = None
|
||||||
|
@ -113,8 +120,13 @@ class FlowExecutorView(View):
|
||||||
self.current_stage_view.request = request
|
self.current_stage_view.request = request
|
||||||
return super().dispatch(request)
|
return super().dispatch(request)
|
||||||
|
|
||||||
|
@swagger_auto_schema(
|
||||||
|
responses={200: Challenge()},
|
||||||
|
request_body=no_body,
|
||||||
|
operation_id="flows_executor_get",
|
||||||
|
)
|
||||||
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
"""pass get request to current stage"""
|
"""Get the next pending challenge from the currently active flow."""
|
||||||
self._logger.debug(
|
self._logger.debug(
|
||||||
"f(exec): Passing GET",
|
"f(exec): Passing GET",
|
||||||
view_class=class_to_path(self.current_stage_view.__class__),
|
view_class=class_to_path(self.current_stage_view.__class__),
|
||||||
|
@ -127,8 +139,13 @@ class FlowExecutorView(View):
|
||||||
self._logger.exception(exc)
|
self._logger.exception(exc)
|
||||||
return to_stage_response(request, FlowErrorResponse(request, exc))
|
return to_stage_response(request, FlowErrorResponse(request, exc))
|
||||||
|
|
||||||
|
@swagger_auto_schema(
|
||||||
|
responses={200: Challenge()},
|
||||||
|
request_body=ChallengeResponse(),
|
||||||
|
operation_id="flows_executor_solve",
|
||||||
|
)
|
||||||
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
"""pass post request to current stage"""
|
"""Solve the previously retrieved challenge and advanced to the next stage."""
|
||||||
self._logger.debug(
|
self._logger.debug(
|
||||||
"f(exec): Passing POST",
|
"f(exec): Passing POST",
|
||||||
view_class=class_to_path(self.current_stage_view.__class__),
|
view_class=class_to_path(self.current_stage_view.__class__),
|
||||||
|
@ -175,8 +192,10 @@ class FlowExecutorView(View):
|
||||||
"f(exec): Continuing with next stage",
|
"f(exec): Continuing with next stage",
|
||||||
reamining=len(self.plan.stages),
|
reamining=len(self.plan.stages),
|
||||||
)
|
)
|
||||||
|
kwargs = self.kwargs
|
||||||
|
kwargs.update({"flow_slug": self.flow.slug})
|
||||||
return redirect_with_qs(
|
return redirect_with_qs(
|
||||||
"authentik_api:flow-executor", self.request.GET, **self.kwargs
|
"authentik_api:flow-executor", self.request.GET, **kwargs
|
||||||
)
|
)
|
||||||
# User passed all stages
|
# User passed all stages
|
||||||
self._logger.debug(
|
self._logger.debug(
|
||||||
|
|
|
@ -13,6 +13,7 @@ redis:
|
||||||
ws_db: 2
|
ws_db: 2
|
||||||
|
|
||||||
debug: false
|
debug: false
|
||||||
|
|
||||||
log_level: info
|
log_level: info
|
||||||
|
|
||||||
# Error reporting, sends stacktrace to sentry.beryju.org
|
# Error reporting, sends stacktrace to sentry.beryju.org
|
||||||
|
|
|
@ -55,13 +55,21 @@ class OutpostConsumer(AuthJsonConsumer):
|
||||||
OutpostState(
|
OutpostState(
|
||||||
uid=self.channel_name, last_seen=datetime.now(), _outpost=self.outpost
|
uid=self.channel_name, last_seen=datetime.now(), _outpost=self.outpost
|
||||||
).save(timeout=OUTPOST_HELLO_INTERVAL * 1.5)
|
).save(timeout=OUTPOST_HELLO_INTERVAL * 1.5)
|
||||||
LOGGER.debug("added channel to cache", channel_name=self.channel_name)
|
LOGGER.debug(
|
||||||
|
"added outpost instace to cache",
|
||||||
|
outpost=self.outpost,
|
||||||
|
channel_name=self.channel_name,
|
||||||
|
)
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def disconnect(self, close_code):
|
def disconnect(self, close_code):
|
||||||
if self.outpost:
|
if self.outpost:
|
||||||
OutpostState.for_channel(self.outpost, self.channel_name).delete()
|
OutpostState.for_channel(self.outpost, self.channel_name).delete()
|
||||||
LOGGER.debug("removed channel from cache", channel_name=self.channel_name)
|
LOGGER.debug(
|
||||||
|
"removed outpost instance from cache",
|
||||||
|
outpost=self.outpost,
|
||||||
|
channel_name=self.channel_name,
|
||||||
|
)
|
||||||
|
|
||||||
def receive_json(self, content: Data):
|
def receive_json(self, content: Data):
|
||||||
msg = from_dict(WebsocketMessage, content)
|
msg = from_dict(WebsocketMessage, content)
|
||||||
|
|
|
@ -26,5 +26,5 @@ def invalidate_policy_cache(sender, instance, **_):
|
||||||
cache.delete_many(keys)
|
cache.delete_many(keys)
|
||||||
LOGGER.debug("Invalidating policy cache", policy=instance, keys=total)
|
LOGGER.debug("Invalidating policy cache", policy=instance, keys=total)
|
||||||
# Also delete user application cache
|
# Also delete user application cache
|
||||||
keys = cache.keys(user_app_cache_key("*"))
|
keys = cache.keys(user_app_cache_key("*")) or []
|
||||||
cache.delete_many(keys)
|
cache.delete_many(keys)
|
||||||
|
|
|
@ -74,7 +74,7 @@ class SAMLFlowFinalView(ChallengeStageView):
|
||||||
return super().get(
|
return super().get(
|
||||||
self.request,
|
self.request,
|
||||||
**{
|
**{
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-autosubmit",
|
"component": "ak-stage-autosubmit",
|
||||||
"title": "Redirecting to %(app)s..." % {"app": application.name},
|
"title": "Redirecting to %(app)s..." % {"app": application.name},
|
||||||
"url": provider.acs_url,
|
"url": provider.acs_url,
|
||||||
|
|
|
@ -150,7 +150,6 @@ SWAGGER_SETTINGS = {
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
"DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination",
|
"DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination",
|
||||||
"PAGE_SIZE": 100,
|
"PAGE_SIZE": 100,
|
||||||
"DATETIME_FORMAT": "%s",
|
|
||||||
"DEFAULT_FILTER_BACKENDS": [
|
"DEFAULT_FILTER_BACKENDS": [
|
||||||
"rest_framework_guardian.filters.ObjectPermissionsFilter",
|
"rest_framework_guardian.filters.ObjectPermissionsFilter",
|
||||||
"django_filters.rest_framework.DjangoFilterBackend",
|
"django_filters.rest_framework.DjangoFilterBackend",
|
||||||
|
|
|
@ -15,9 +15,11 @@ class OAuthSourceForm(forms.ModelForm):
|
||||||
self.fields["authentication_flow"].queryset = Flow.objects.filter(
|
self.fields["authentication_flow"].queryset = Flow.objects.filter(
|
||||||
designation=FlowDesignation.AUTHENTICATION
|
designation=FlowDesignation.AUTHENTICATION
|
||||||
)
|
)
|
||||||
|
self.fields["authentication_flow"].required = True
|
||||||
self.fields["enrollment_flow"].queryset = Flow.objects.filter(
|
self.fields["enrollment_flow"].queryset = Flow.objects.filter(
|
||||||
designation=FlowDesignation.ENROLLMENT
|
designation=FlowDesignation.ENROLLMENT
|
||||||
)
|
)
|
||||||
|
self.fields["enrollment_flow"].required = True
|
||||||
if hasattr(self.Meta, "overrides"):
|
if hasattr(self.Meta, "overrides"):
|
||||||
for overide_field, overide_value in getattr(self.Meta, "overrides").items():
|
for overide_field, overide_value in getattr(self.Meta, "overrides").items():
|
||||||
self.fields[overide_field].initial = overide_value
|
self.fields[overide_field].initial = overide_value
|
||||||
|
|
|
@ -4,6 +4,7 @@ from typing import Any, Optional
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.http import Http404, HttpRequest, HttpResponse
|
from django.http import Http404, HttpRequest, HttpResponse
|
||||||
|
from django.http.response import HttpResponseBadRequest
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
@ -151,6 +152,8 @@ class OAuthCallback(OAuthClientMixin, View):
|
||||||
PLAN_CONTEXT_REDIRECT: final_redirect,
|
PLAN_CONTEXT_REDIRECT: final_redirect,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
if not flow:
|
||||||
|
return HttpResponseBadRequest()
|
||||||
# We run the Flow planner here so we can pass the Pending user in the context
|
# We run the Flow planner here so we can pass the Pending user in the context
|
||||||
planner = FlowPlanner(flow)
|
planner = FlowPlanner(flow)
|
||||||
plan = planner.plan(self.request, kwargs)
|
plan = planner.plan(self.request, kwargs)
|
||||||
|
@ -233,6 +236,9 @@ class OAuthCallback(OAuthClientMixin, View):
|
||||||
PLAN_CONTEXT_SOURCES_OAUTH_ACCESS: access,
|
PLAN_CONTEXT_SOURCES_OAUTH_ACCESS: access,
|
||||||
}
|
}
|
||||||
# We run the Flow planner here so we can pass the Pending user in the context
|
# We run the Flow planner here so we can pass the Pending user in the context
|
||||||
|
if not source.enrollment_flow:
|
||||||
|
LOGGER.warning("source has no enrollment flow", source=source)
|
||||||
|
return HttpResponseBadRequest()
|
||||||
planner = FlowPlanner(source.enrollment_flow)
|
planner = FlowPlanner(source.enrollment_flow)
|
||||||
plan = planner.plan(self.request, context)
|
plan = planner.plan(self.request, context)
|
||||||
plan.append(in_memory_stage(PostUserEnrollmentStage))
|
plan.append(in_memory_stage(PostUserEnrollmentStage))
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
"""AuthenticatorStaticStage API Views"""
|
"""AuthenticatorStaticStage API Views"""
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from django_otp.plugins.otp_static.models import StaticDevice
|
||||||
|
from rest_framework.permissions import IsAdminUser
|
||||||
|
from rest_framework.serializers import ModelSerializer
|
||||||
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||||
|
|
||||||
from authentik.flows.api.stages import StageSerializer
|
from authentik.flows.api.stages import StageSerializer
|
||||||
from authentik.stages.authenticator_static.models import AuthenticatorStaticStage
|
from authentik.stages.authenticator_static.models import AuthenticatorStaticStage
|
||||||
|
@ -19,3 +22,39 @@ class AuthenticatorStaticStageViewSet(ModelViewSet):
|
||||||
|
|
||||||
queryset = AuthenticatorStaticStage.objects.all()
|
queryset = AuthenticatorStaticStage.objects.all()
|
||||||
serializer_class = AuthenticatorStaticStageSerializer
|
serializer_class = AuthenticatorStaticStageSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class StaticDeviceSerializer(ModelSerializer):
|
||||||
|
"""Serializer for static authenticator devices"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = StaticDevice
|
||||||
|
fields = ["name", "token_set"]
|
||||||
|
depth = 2
|
||||||
|
|
||||||
|
|
||||||
|
class StaticDeviceViewSet(ModelViewSet):
|
||||||
|
"""Viewset for static authenticator devices"""
|
||||||
|
|
||||||
|
queryset = StaticDevice.objects.none()
|
||||||
|
serializer_class = StaticDeviceSerializer
|
||||||
|
search_fields = ["name"]
|
||||||
|
filterset_fields = ["name"]
|
||||||
|
ordering = ["name"]
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if not self.request:
|
||||||
|
return super().get_queryset()
|
||||||
|
return StaticDevice.objects.filter(user=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
class StaticAdminDeviceViewSet(ReadOnlyModelViewSet):
|
||||||
|
"""Viewset for static authenticator devices (for admins)"""
|
||||||
|
|
||||||
|
permission_classes = [IsAdminUser]
|
||||||
|
queryset = StaticDevice.objects.all()
|
||||||
|
serializer_class = StaticDeviceSerializer
|
||||||
|
search_fields = ["name"]
|
||||||
|
filterset_fields = ["name"]
|
||||||
|
ordering = ["name"]
|
||||||
|
|
|
@ -31,7 +31,7 @@ class AuthenticatorStaticStageView(ChallengeStageView):
|
||||||
tokens: list[StaticToken] = self.request.session[SESSION_STATIC_TOKENS]
|
tokens: list[StaticToken] = self.request.session[SESSION_STATIC_TOKENS]
|
||||||
return AuthenticatorStaticChallenge(
|
return AuthenticatorStaticChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-authenticator-static",
|
"component": "ak-stage-authenticator-static",
|
||||||
"codes": [token.token for token in tokens],
|
"codes": [token.token for token in tokens],
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
"""AuthenticatorTOTPStage API Views"""
|
"""AuthenticatorTOTPStage API Views"""
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from django_otp.plugins.otp_totp.models import TOTPDevice
|
||||||
|
from rest_framework.permissions import IsAdminUser
|
||||||
|
from rest_framework.serializers import ModelSerializer
|
||||||
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||||
|
|
||||||
from authentik.flows.api.stages import StageSerializer
|
from authentik.flows.api.stages import StageSerializer
|
||||||
from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage
|
from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage
|
||||||
|
@ -19,3 +22,41 @@ class AuthenticatorTOTPStageViewSet(ModelViewSet):
|
||||||
|
|
||||||
queryset = AuthenticatorTOTPStage.objects.all()
|
queryset = AuthenticatorTOTPStage.objects.all()
|
||||||
serializer_class = AuthenticatorTOTPStageSerializer
|
serializer_class = AuthenticatorTOTPStageSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class TOTPDeviceSerializer(ModelSerializer):
|
||||||
|
"""Serializer for totp authenticator devices"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = TOTPDevice
|
||||||
|
fields = [
|
||||||
|
"name",
|
||||||
|
]
|
||||||
|
depth = 2
|
||||||
|
|
||||||
|
|
||||||
|
class TOTPDeviceViewSet(ModelViewSet):
|
||||||
|
"""Viewset for totp authenticator devices"""
|
||||||
|
|
||||||
|
queryset = TOTPDevice.objects.none()
|
||||||
|
serializer_class = TOTPDeviceSerializer
|
||||||
|
search_fields = ["name"]
|
||||||
|
filterset_fields = ["name"]
|
||||||
|
ordering = ["name"]
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if not self.request:
|
||||||
|
return super().get_queryset()
|
||||||
|
return TOTPDevice.objects.filter(user=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
class TOTPAdminDeviceViewSet(ReadOnlyModelViewSet):
|
||||||
|
"""Viewset for totp authenticator devices (for admins)"""
|
||||||
|
|
||||||
|
permission_classes = [IsAdminUser]
|
||||||
|
queryset = TOTPDevice.objects.all()
|
||||||
|
serializer_class = TOTPDeviceSerializer
|
||||||
|
search_fields = ["name"]
|
||||||
|
filterset_fields = ["name"]
|
||||||
|
ordering = ["name"]
|
||||||
|
|
|
@ -51,7 +51,7 @@ class AuthenticatorTOTPStageView(ChallengeStageView):
|
||||||
device: TOTPDevice = self.request.session[SESSION_TOTP_DEVICE]
|
device: TOTPDevice = self.request.session[SESSION_TOTP_DEVICE]
|
||||||
return AuthenticatorTOTPChallenge(
|
return AuthenticatorTOTPChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-authenticator-totp",
|
"component": "ak-stage-authenticator-totp",
|
||||||
"config_url": device.config_url,
|
"config_url": device.config_url,
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ class AuthenticatorValidateStageView(ChallengeStageView):
|
||||||
challenges = self.request.session["device_challenges"]
|
challenges = self.request.session["device_challenges"]
|
||||||
return AuthenticatorChallenge(
|
return AuthenticatorChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-authenticator-validate",
|
"component": "ak-stage-authenticator-validate",
|
||||||
"device_challenges": challenges,
|
"device_challenges": challenges,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
"""AuthenticateWebAuthnStage API Views"""
|
"""AuthenticateWebAuthnStage API Views"""
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.permissions import IsAdminUser
|
||||||
|
from rest_framework.serializers import ModelSerializer
|
||||||
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||||
|
|
||||||
from authentik.flows.api.stages import StageSerializer
|
from authentik.flows.api.stages import StageSerializer
|
||||||
from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnStage
|
from authentik.stages.authenticator_webauthn.models import (
|
||||||
|
AuthenticateWebAuthnStage,
|
||||||
|
WebAuthnDevice,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AuthenticateWebAuthnStageSerializer(StageSerializer):
|
class AuthenticateWebAuthnStageSerializer(StageSerializer):
|
||||||
|
@ -19,3 +24,41 @@ class AuthenticateWebAuthnStageViewSet(ModelViewSet):
|
||||||
|
|
||||||
queryset = AuthenticateWebAuthnStage.objects.all()
|
queryset = AuthenticateWebAuthnStage.objects.all()
|
||||||
serializer_class = AuthenticateWebAuthnStageSerializer
|
serializer_class = AuthenticateWebAuthnStageSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class WebAuthnDeviceSerializer(ModelSerializer):
|
||||||
|
"""Serializer for WebAuthn authenticator devices"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = WebAuthnDevice
|
||||||
|
fields = [
|
||||||
|
"name",
|
||||||
|
]
|
||||||
|
depth = 2
|
||||||
|
|
||||||
|
|
||||||
|
class WebAuthnDeviceViewSet(ModelViewSet):
|
||||||
|
"""Viewset for WebAuthn authenticator devices"""
|
||||||
|
|
||||||
|
queryset = WebAuthnDevice.objects.none()
|
||||||
|
serializer_class = WebAuthnDeviceSerializer
|
||||||
|
search_fields = ["name"]
|
||||||
|
filterset_fields = ["name"]
|
||||||
|
ordering = ["name"]
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if not self.request:
|
||||||
|
return super().get_queryset()
|
||||||
|
return WebAuthnDevice.objects.filter(user=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
class WebAuthnAdminDeviceViewSet(ReadOnlyModelViewSet):
|
||||||
|
"""Viewset for WebAuthn authenticator devices (for admins)"""
|
||||||
|
|
||||||
|
permission_classes = [IsAdminUser]
|
||||||
|
queryset = WebAuthnDevice.objects.all()
|
||||||
|
serializer_class = WebAuthnDeviceSerializer
|
||||||
|
search_fields = ["name"]
|
||||||
|
filterset_fields = ["name"]
|
||||||
|
ordering = ["name"]
|
||||||
|
|
|
@ -122,7 +122,7 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView):
|
||||||
|
|
||||||
return AuthenticatorWebAuthnChallenge(
|
return AuthenticatorWebAuthnChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-authenticator-webauthn",
|
"component": "ak-stage-authenticator-webauthn",
|
||||||
"registration": make_credential_options.registration_dict,
|
"registration": make_credential_options.registration_dict,
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class CaptchaStageView(ChallengeStageView):
|
||||||
def get_challenge(self, *args, **kwargs) -> Challenge:
|
def get_challenge(self, *args, **kwargs) -> Challenge:
|
||||||
return CaptchaChallenge(
|
return CaptchaChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-captcha",
|
"component": "ak-stage-captcha",
|
||||||
"site_key": self.executor.current_stage.public_key,
|
"site_key": self.executor.current_stage.public_key,
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ class ConsentStageView(ChallengeStageView):
|
||||||
def get_challenge(self) -> Challenge:
|
def get_challenge(self) -> Challenge:
|
||||||
challenge = ConsentChallenge(
|
challenge = ConsentChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-consent",
|
"component": "ak-stage-consent",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,7 +24,7 @@ class DummyStageView(ChallengeStageView):
|
||||||
def get_challenge(self, *args, **kwargs) -> Challenge:
|
def get_challenge(self, *args, **kwargs) -> Challenge:
|
||||||
return DummyChallenge(
|
return DummyChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "",
|
"component": "",
|
||||||
"title": self.executor.current_stage.name,
|
"title": self.executor.current_stage.name,
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ class EmailStageView(ChallengeStageView):
|
||||||
|
|
||||||
def get_challenge(self) -> Challenge:
|
def get_challenge(self) -> Challenge:
|
||||||
challenge = EmailChallenge(
|
challenge = EmailChallenge(
|
||||||
data={"type": ChallengeTypes.native, "component": "ak-stage-email"}
|
data={"type": ChallengeTypes.native.value, "component": "ak-stage-email"}
|
||||||
)
|
)
|
||||||
return challenge
|
return challenge
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ class IdentificationStageView(ChallengeStageView):
|
||||||
current_stage: IdentificationStage = self.executor.current_stage
|
current_stage: IdentificationStage = self.executor.current_stage
|
||||||
challenge = IdentificationChallenge(
|
challenge = IdentificationChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-identification",
|
"component": "ak-stage-identification",
|
||||||
"primary_action": _("Log in"),
|
"primary_action": _("Log in"),
|
||||||
"input_type": "text",
|
"input_type": "text",
|
||||||
|
|
|
@ -78,7 +78,7 @@ class PasswordStageView(ChallengeStageView):
|
||||||
def get_challenge(self) -> Challenge:
|
def get_challenge(self) -> Challenge:
|
||||||
challenge = PasswordChallenge(
|
challenge = PasswordChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-password",
|
"component": "ak-stage-password",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -164,7 +164,7 @@ class PromptStageView(ChallengeStageView):
|
||||||
fields = list(self.executor.current_stage.fields.all().order_by("order"))
|
fields = list(self.executor.current_stage.fields.all().order_by("order"))
|
||||||
challenge = PromptChallenge(
|
challenge = PromptChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.native,
|
"type": ChallengeTypes.native.value,
|
||||||
"component": "ak-stage-prompt",
|
"component": "ak-stage-prompt",
|
||||||
"fields": [PromptSerializer(field).data for field in fields],
|
"fields": [PromptSerializer(field).data for field in fields],
|
||||||
},
|
},
|
||||||
|
|
|
@ -279,6 +279,7 @@ stages:
|
||||||
displayName: Build static files for e2e
|
displayName: Build static files for e2e
|
||||||
inputs:
|
inputs:
|
||||||
script: |
|
script: |
|
||||||
|
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/src/api --additional-properties=typescriptThreePlus=true
|
||||||
cd web
|
cd web
|
||||||
npm i
|
npm i
|
||||||
npm run build
|
npm run build
|
||||||
|
|
|
@ -19,7 +19,7 @@ services:
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
server:
|
server:
|
||||||
image: beryju/authentik:${AUTHENTIK_TAG:-2021.3.3}
|
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.3.3}
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
AUTHENTIK_REDIS__HOST: redis
|
AUTHENTIK_REDIS__HOST: redis
|
||||||
|
@ -27,9 +27,11 @@ services:
|
||||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||||
|
# AUTHENTIK_ERROR_REPORTING__ENABLED: true
|
||||||
volumes:
|
volumes:
|
||||||
- ./media:/media
|
- ./media:/media
|
||||||
- ./custom-templates:/templates
|
- ./custom-templates:/templates
|
||||||
|
- geoip:/geoip
|
||||||
ports:
|
ports:
|
||||||
- 8000
|
- 8000
|
||||||
networks:
|
networks:
|
||||||
|
@ -45,7 +47,7 @@ services:
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
worker:
|
worker:
|
||||||
image: beryju/authentik:${AUTHENTIK_TAG:-2021.3.3}
|
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.3.3}
|
||||||
command: worker
|
command: worker
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
|
@ -55,14 +57,16 @@ services:
|
||||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||||
|
# AUTHENTIK_ERROR_REPORTING__ENABLED: true
|
||||||
volumes:
|
volumes:
|
||||||
- ./backups:/backups
|
- ./backups:/backups
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- ./custom-templates:/templates
|
- ./custom-templates:/templates
|
||||||
|
- geoip:/geoip
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
static:
|
static:
|
||||||
image: beryju/authentik-static:${AUTHENTIK_TAG:-2021.3.3}
|
image: ${AUTHENTIK_IMAGE_STATIC:-beryju/authentik-static}:${AUTHENTIK_TAG:-2021.3.3}
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
labels:
|
labels:
|
||||||
|
@ -91,10 +95,21 @@ services:
|
||||||
- "127.0.0.1:8080:8080"
|
- "127.0.0.1:8080:8080"
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
|
geoipupdate:
|
||||||
|
image: "maxmindinc/geoipupdate:latest"
|
||||||
|
volumes:
|
||||||
|
- "geoip:/usr/share/GeoIP"
|
||||||
|
environment:
|
||||||
|
GEOIPUPDATE_EDITION_IDS: "GeoLite2-City"
|
||||||
|
GEOIPUPDATE_FREQUENCY: "8"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
database:
|
database:
|
||||||
driver: local
|
driver: local
|
||||||
|
geoip:
|
||||||
|
driver: local
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
internal: {}
|
internal: {}
|
||||||
|
|
|
@ -22,6 +22,10 @@
|
||||||
| config.email.use_ssl | false | Enable SSL |
|
| config.email.use_ssl | false | Enable SSL |
|
||||||
| config.email.timeout | 10 | SMTP Timeout |
|
| config.email.timeout | 10 | SMTP Timeout |
|
||||||
| config.email.from | authentik@localhost | Email address authentik will send from, should have a correct @domain |
|
| config.email.from | authentik@localhost | Email address authentik will send from, should have a correct @domain |
|
||||||
|
| geoip.enabled | false | Optionally enable GeoIP |
|
||||||
|
| geoip.accountId | | GeoIP MaxMind Account ID |
|
||||||
|
| geoip.licenseKey | | GeoIP MaxMind License key |
|
||||||
|
| geoip.image | maxmindinc/geoipupdate:latest | GeoIP Updater image |
|
||||||
| backup.accessKey | | Optionally enable S3 Backup, Access Key |
|
| backup.accessKey | | Optionally enable S3 Backup, Access Key |
|
||||||
| backup.secretKey | | Optionally enable S3 Backup, Secret Key |
|
| backup.secretKey | | Optionally enable S3 Backup, Secret Key |
|
||||||
| backup.bucket | | Optionally enable S3 Backup, Bucket |
|
| backup.bucket | | Optionally enable S3 Backup, Bucket |
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
{{- if .Values.geoip.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "authentik.fullname" . }}-geoip-config
|
||||||
|
data:
|
||||||
|
GEOIPUPDATE_ACCOUNT_ID: "{{ .Values.geoip.accountId }}"
|
||||||
|
GEOIPUPDATE_LICENSE_KEY: "{{ .Values.geoip.licenseKey }}"
|
||||||
|
GEOIPUPDATE_EDITION_IDS: "GeoLite2-City"
|
||||||
|
GEOIPUPDATE_FREQUENCY: "8"
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,39 @@
|
||||||
|
{{- if .Values.geoip.enabled -}}
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "authentik.fullname" . }}-geoip
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "authentik.name" . }}
|
||||||
|
helm.sh/chart: {{ include "authentik.chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
k8s.goauthentik.io/component: geoip
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: {{ include "authentik.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
k8s.goauthentik.io/component: geoip
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "authentik.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
k8s.goauthentik.io/component: geoip
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: geoip
|
||||||
|
image: "{{ .Values.geoip.image }}"
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: {{ include "authentik.fullname" . }}-geoip-config
|
||||||
|
volumeMounts:
|
||||||
|
- name: geoip
|
||||||
|
mountPath: /usr/share/GeoIP
|
||||||
|
volumes:
|
||||||
|
- name: geoip
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "authentik.fullname" . }}-geoip
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{{- if .Values.geoip.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "authentik.fullname" . }}-geoip
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "authentik.name" . }}
|
||||||
|
helm.sh/chart: {{ include "authentik.chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,121 @@
|
||||||
|
{{- if .Values.monitoring.enabled -}}
|
||||||
|
---
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: PrometheusRule
|
||||||
|
metadata:
|
||||||
|
name: {{ include "authentik.fullname" . }}-static-rules
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "authentik.name" . }}
|
||||||
|
helm.sh/chart: {{ include "authentik.chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
groups:
|
||||||
|
- name: Aggregate request counters
|
||||||
|
rules:
|
||||||
|
- record: job:django_http_requests_before_middlewares_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_before_middlewares_total[30s])) by (job)
|
||||||
|
- record: job:django_http_requests_unknown_latency_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_unknown_latency_total[30s])) by (job)
|
||||||
|
- record: job:django_http_ajax_requests_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_ajax_requests_total[30s])) by (job)
|
||||||
|
- record: job:django_http_responses_before_middlewares_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_responses_before_middlewares_total[30s])) by (job)
|
||||||
|
- record: job:django_http_requests_unknown_latency_including_middlewares_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_unknown_latency_including_middlewares_total[30s])) by (job)
|
||||||
|
- record: job:django_http_requests_body_total_bytes:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_body_total_bytes[30s])) by (job)
|
||||||
|
- record: job:django_http_responses_streaming_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_responses_streaming_total[30s])) by (job)
|
||||||
|
- record: job:django_http_responses_body_total_bytes:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_responses_body_total_bytes[30s])) by (job)
|
||||||
|
- record: job:django_http_requests_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_total_by_method[30s])) by (job)
|
||||||
|
- record: job:django_http_requests_total_by_method:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_total_by_method[30s])) by (job,method)
|
||||||
|
- record: job:django_http_requests_total_by_transport:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_total_by_transport[30s])) by (job,transport)
|
||||||
|
- record: job:django_http_requests_total_by_view:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_total_by_view_transport_method[30s])) by (job,view)
|
||||||
|
- record: job:django_http_requests_total_by_view_transport_method:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_requests_total_by_view_transport_method[30s])) by (job,view,transport,method)
|
||||||
|
- record: job:django_http_responses_total_by_templatename:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_responses_total_by_templatename[30s])) by (job,templatename)
|
||||||
|
- record: job:django_http_responses_total_by_status:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_responses_total_by_status[30s])) by (job,status)
|
||||||
|
- record: job:django_http_responses_total_by_status_name_method:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_responses_total_by_status_name_method[30s])) by (job,status,name,method)
|
||||||
|
- record: job:django_http_responses_total_by_charset:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_responses_total_by_charset[30s])) by (job,charset)
|
||||||
|
- record: job:django_http_exceptions_total_by_type:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_exceptions_total_by_type[30s])) by (job,type)
|
||||||
|
- record: job:django_http_exceptions_total_by_view:sum_rate30s
|
||||||
|
expr: sum(rate(django_http_exceptions_total_by_view[30s])) by (job,view)
|
||||||
|
- name: Aggregate latency histograms
|
||||||
|
rules:
|
||||||
|
- record: job:django_http_requests_latency_including_middlewares_seconds:quantile_rate30s
|
||||||
|
expr: histogram_quantile(0.50, sum(rate(django_http_requests_latency_including_middlewares_seconds_bucket[30s])) by (job, le))
|
||||||
|
labels:
|
||||||
|
quantile: "50"
|
||||||
|
- record: job:django_http_requests_latency_including_middlewares_seconds:quantile_rate30s
|
||||||
|
expr: histogram_quantile(0.95, sum(rate(django_http_requests_latency_including_middlewares_seconds_bucket[30s])) by (job, le))
|
||||||
|
labels:
|
||||||
|
quantile: "95"
|
||||||
|
- record: job:django_http_requests_latency_including_middlewares_seconds:quantile_rate30s
|
||||||
|
expr: histogram_quantile(0.99, sum(rate(django_http_requests_latency_including_middlewares_seconds_bucket[30s])) by (job, le))
|
||||||
|
labels:
|
||||||
|
quantile: "99"
|
||||||
|
- record: job:django_http_requests_latency_including_middlewares_seconds:quantile_rate30s
|
||||||
|
expr: histogram_quantile(0.999, sum(rate(django_http_requests_latency_including_middlewares_seconds_bucket[30s])) by (job, le))
|
||||||
|
labels:
|
||||||
|
quantile: "99.9"
|
||||||
|
- record: job:django_http_requests_latency_seconds:quantile_rate30s
|
||||||
|
expr: histogram_quantile(0.50, sum(rate(django_http_requests_latency_seconds_bucket[30s])) by (job, le))
|
||||||
|
labels:
|
||||||
|
quantile: "50"
|
||||||
|
- record: job:django_http_requests_latency_seconds:quantile_rate30s
|
||||||
|
expr: histogram_quantile(0.95, sum(rate(django_http_requests_latency_seconds_bucket[30s])) by (job, le))
|
||||||
|
labels:
|
||||||
|
quantile: "95"
|
||||||
|
- record: job:django_http_requests_latency_seconds:quantile_rate30s
|
||||||
|
expr: histogram_quantile(0.99, sum(rate(django_http_requests_latency_seconds_bucket[30s])) by (job, le))
|
||||||
|
labels:
|
||||||
|
quantile: "99"
|
||||||
|
- record: job:django_http_requests_latency_seconds:quantile_rate30s
|
||||||
|
expr: histogram_quantile(0.999, sum(rate(django_http_requests_latency_seconds_bucket[30s])) by (job, le))
|
||||||
|
labels:
|
||||||
|
quantile: "99.9"
|
||||||
|
- name: Aggregate model operations
|
||||||
|
rules:
|
||||||
|
- record: job:django_model_inserts_total:sum_rate1m
|
||||||
|
expr: sum(rate(django_model_inserts_total[1m])) by (job, model)
|
||||||
|
- record: job:django_model_updates_total:sum_rate1m
|
||||||
|
expr: sum(rate(django_model_updates_total[1m])) by (job, model)
|
||||||
|
- record: job:django_model_deletes_total:sum_rate1m
|
||||||
|
expr: sum(rate(django_model_deletes_total[1m])) by (job, model)
|
||||||
|
- name: Aggregate database operations
|
||||||
|
rules:
|
||||||
|
- record: job:django_db_new_connections_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_db_new_connections_total[30s])) by (alias, vendor)
|
||||||
|
- record: job:django_db_new_connection_errors_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_db_new_connection_errors_total[30s])) by (alias, vendor)
|
||||||
|
- record: job:django_db_execute_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_db_execute_total[30s])) by (alias, vendor)
|
||||||
|
- record: job:django_db_execute_many_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_db_execute_many_total[30s])) by (alias, vendor)
|
||||||
|
- record: job:django_db_errors_total:sum_rate30s
|
||||||
|
expr: sum(rate(django_db_errors_total[30s])) by (alias, vendor, type)
|
||||||
|
- name: Aggregate migrations
|
||||||
|
rules:
|
||||||
|
- record: job:django_migrations_applied_total:max
|
||||||
|
expr: max(django_migrations_applied_total) by (job, connection)
|
||||||
|
- record: job:django_migrations_unapplied_total:max
|
||||||
|
expr: max(django_migrations_unapplied_total) by (job, connection)
|
||||||
|
- name: Alerts
|
||||||
|
rules:
|
||||||
|
- alert: UnappliedMigrations
|
||||||
|
expr: job:django_migrations_unapplied_total:max > 0
|
||||||
|
for: 1m
|
||||||
|
labels:
|
||||||
|
severity: testing
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{{- if .Values.monitoring.enabled -}}
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: ServiceMonitor
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "authentik.name" . }}
|
||||||
|
helm.sh/chart: {{ include "authentik.chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
name: {{ include "authentik.fullname" . }}-static-monitoring
|
||||||
|
spec:
|
||||||
|
endpoints:
|
||||||
|
- port: http
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
k8s.goauthentik.io/component: static
|
||||||
|
{{- end }}
|
|
@ -88,9 +88,17 @@ spec:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: "{{ .Release.Name }}-postgresql"
|
name: "{{ .Release.Name }}-postgresql"
|
||||||
key: "postgresql-password"
|
key: "postgresql-password"
|
||||||
|
{{ if .Values.geoip.enabled -}}
|
||||||
|
- name: AUTHENTIK_AUTHENTIK__GEOIP
|
||||||
|
value: /geoip/GeoLite2-City.mmdb
|
||||||
|
{{- end }}
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: authentik-uploads
|
- name: authentik-uploads
|
||||||
mountPath: /media
|
mountPath: /media
|
||||||
|
{{ if .Values.geoip.enabled -}}
|
||||||
|
- name: geoip
|
||||||
|
mountPath: /geoip
|
||||||
|
{{- end }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 8000
|
containerPort: 8000
|
||||||
|
@ -116,3 +124,8 @@ spec:
|
||||||
- name: authentik-uploads
|
- name: authentik-uploads
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: {{ include "authentik.fullname" . }}-uploads
|
claimName: {{ include "authentik.fullname" . }}-uploads
|
||||||
|
{{ if .Values.geoip.enabled -}}
|
||||||
|
- name: geoip
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "authentik.fullname" . }}-geoip
|
||||||
|
{{- end }}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
{{- if .Values.monitoring.enabled -}}
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: ServiceMonitor
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "authentik.name" . }}
|
||||||
|
helm.sh/chart: {{ include "authentik.chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
name: {{ include "authentik.fullname" . }}-web-monitoring
|
||||||
|
spec:
|
||||||
|
endpoints:
|
||||||
|
- basicAuth:
|
||||||
|
password:
|
||||||
|
name: {{ include "authentik.fullname" . }}-secret-key
|
||||||
|
key: SECRET_KEY
|
||||||
|
username:
|
||||||
|
name: {{ include "authentik.fullname" . }}-secret-key
|
||||||
|
key: monitoring_username
|
||||||
|
port: http
|
||||||
|
path: /metrics/
|
||||||
|
interval: 10s
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
k8s.goauthentik.io/component: web
|
||||||
|
{{- end }}
|
|
@ -68,6 +68,15 @@ spec:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: "{{ .Release.Name }}-postgresql"
|
name: "{{ .Release.Name }}-postgresql"
|
||||||
key: "postgresql-password"
|
key: "postgresql-password"
|
||||||
|
{{ if .Values.geoip.enabled -}}
|
||||||
|
- name: AUTHENTIK_AUTHENTIK__GEOIP
|
||||||
|
value: /geoip/GeoLite2-City.mmdb
|
||||||
|
{{- end }}
|
||||||
|
{{ if .Values.geoip.enabled -}}
|
||||||
|
volumeMounts:
|
||||||
|
- name: geoip
|
||||||
|
mountPath: /geoip
|
||||||
|
{{- end }}
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 150m
|
cpu: 150m
|
||||||
|
@ -75,3 +84,9 @@ spec:
|
||||||
limits:
|
limits:
|
||||||
cpu: 300m
|
cpu: 300m
|
||||||
memory: 600M
|
memory: 600M
|
||||||
|
{{ if .Values.geoip.enabled -}}
|
||||||
|
volumes:
|
||||||
|
- name: geoip
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "authentik.fullname" . }}-geoip
|
||||||
|
{{- end -}}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
image:
|
|
||||||
tag: gh-master
|
|
||||||
pullPolicy: Always
|
|
||||||
|
|
||||||
serverReplicas: 1
|
|
||||||
workerReplicas: 1
|
|
||||||
|
|
||||||
config:
|
|
||||||
# Log level used by web and worker
|
|
||||||
# Can be either debug, info, warning, error
|
|
||||||
logLevel: debug
|
|
||||||
|
|
||||||
ingress:
|
|
||||||
hosts:
|
|
||||||
- authentik.127.0.0.1.nip.io
|
|
||||||
|
|
||||||
# These values influence the bundled postgresql and redis charts, but are also used by authentik to connect
|
|
||||||
postgresql:
|
|
||||||
postgresqlPassword: EK-5jnKfjrGRm<77
|
|
||||||
|
|
||||||
redis:
|
|
||||||
password: password
|
|
|
@ -14,6 +14,9 @@ workerReplicas: 1
|
||||||
# Enable the Kubernetes integration which lets authentik deploy outposts into kubernetes
|
# Enable the Kubernetes integration which lets authentik deploy outposts into kubernetes
|
||||||
kubernetesIntegration: true
|
kubernetesIntegration: true
|
||||||
|
|
||||||
|
monitoring:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
config:
|
config:
|
||||||
# Optionally specify fixed secret_key, otherwise generated automatically
|
# Optionally specify fixed secret_key, otherwise generated automatically
|
||||||
# secretKey: _k*@6h2u2@q-dku57hhgzb7tnx*ba9wodcb^s9g0j59@=y(@_o
|
# secretKey: _k*@6h2u2@q-dku57hhgzb7tnx*ba9wodcb^s9g0j59@=y(@_o
|
||||||
|
@ -41,6 +44,13 @@ config:
|
||||||
# Email address authentik will send from, should have a correct @domain
|
# Email address authentik will send from, should have a correct @domain
|
||||||
from: authentik@localhost
|
from: authentik@localhost
|
||||||
|
|
||||||
|
# Enable MaxMind GeoIP
|
||||||
|
geoip:
|
||||||
|
enabled: false
|
||||||
|
accountId: ""
|
||||||
|
licenseKey: ""
|
||||||
|
image: maxmindinc/geoipupdate:latest
|
||||||
|
|
||||||
# Enable Database Backups to S3
|
# Enable Database Backups to S3
|
||||||
# backup:
|
# backup:
|
||||||
# accessKey: access-key
|
# accessKey: access-key
|
||||||
|
|
|
@ -33,7 +33,7 @@ stages:
|
||||||
- task: PublishPipelineArtifact@1
|
- task: PublishPipelineArtifact@1
|
||||||
inputs:
|
inputs:
|
||||||
targetPath: 'outpost/pkg/'
|
targetPath: 'outpost/pkg/'
|
||||||
artifact: 'swagger_client'
|
artifact: 'go_swagger_client'
|
||||||
publishLocation: 'pipeline'
|
publishLocation: 'pipeline'
|
||||||
- stage: lint
|
- stage: lint
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -51,7 +51,7 @@ stages:
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
inputs:
|
inputs:
|
||||||
buildType: 'current'
|
buildType: 'current'
|
||||||
artifactName: 'swagger_client'
|
artifactName: 'go_swagger_client'
|
||||||
path: "outpost/pkg/"
|
path: "outpost/pkg/"
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
inputs:
|
inputs:
|
||||||
|
@ -70,7 +70,7 @@ stages:
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
inputs:
|
inputs:
|
||||||
buildType: 'current'
|
buildType: 'current'
|
||||||
artifactName: 'swagger_client'
|
artifactName: 'go_swagger_client'
|
||||||
path: "outpost/pkg/"
|
path: "outpost/pkg/"
|
||||||
- task: Go@0
|
- task: Go@0
|
||||||
inputs:
|
inputs:
|
||||||
|
@ -89,7 +89,7 @@ stages:
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
inputs:
|
inputs:
|
||||||
buildType: 'current'
|
buildType: 'current'
|
||||||
artifactName: 'swagger_client'
|
artifactName: 'go_swagger_client'
|
||||||
path: "outpost/pkg/"
|
path: "outpost/pkg/"
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
inputs:
|
inputs:
|
||||||
|
|
|
@ -24,7 +24,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pquerna/cachecontrol v0.0.0-20200921180117-858c6e7e6b7e // indirect
|
github.com/pquerna/cachecontrol v0.0.0-20200921180117-858c6e7e6b7e // indirect
|
||||||
github.com/recws-org/recws v1.2.1
|
github.com/recws-org/recws v1.2.1
|
||||||
github.com/sirupsen/logrus v1.8.0
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/spf13/afero v1.5.1 // indirect
|
github.com/spf13/afero v1.5.1 // indirect
|
||||||
github.com/spf13/cast v1.3.1 // indirect
|
github.com/spf13/cast v1.3.1 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
|
|
|
@ -618,6 +618,8 @@ github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
|
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
|
||||||
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
|
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
|
||||||
|
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.16.0 AS builder
|
FROM golang:1.16.2 AS builder
|
||||||
|
|
||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
|
|
||||||
|
|
971
swagger.yaml
971
swagger.yaml
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,273 @@
|
||||||
|
"""test OAuth2 OpenID Provider flow"""
|
||||||
|
from json import loads
|
||||||
|
from sys import platform
|
||||||
|
from time import sleep
|
||||||
|
from unittest.case import skipUnless
|
||||||
|
|
||||||
|
from docker import DockerClient, from_env
|
||||||
|
from docker.models.containers import Container
|
||||||
|
from docker.types import Healthcheck
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support import expected_conditions as ec
|
||||||
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
|
from authentik.core.models import Application
|
||||||
|
from authentik.crypto.models import CertificateKeyPair
|
||||||
|
from authentik.flows.models import Flow
|
||||||
|
from authentik.policies.expression.models import ExpressionPolicy
|
||||||
|
from authentik.policies.models import PolicyBinding
|
||||||
|
from authentik.providers.oauth2.constants import (
|
||||||
|
SCOPE_OPENID,
|
||||||
|
SCOPE_OPENID_EMAIL,
|
||||||
|
SCOPE_OPENID_PROFILE,
|
||||||
|
)
|
||||||
|
from authentik.providers.oauth2.generators import (
|
||||||
|
generate_client_id,
|
||||||
|
generate_client_secret,
|
||||||
|
)
|
||||||
|
from authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping
|
||||||
|
from tests.e2e.utils import (
|
||||||
|
USER,
|
||||||
|
SeleniumTestCase,
|
||||||
|
apply_migration,
|
||||||
|
object_manager,
|
||||||
|
retry,
|
||||||
|
)
|
||||||
|
|
||||||
|
LOGGER = get_logger()
|
||||||
|
|
||||||
|
|
||||||
|
@skipUnless(platform.startswith("linux"), "requires local docker")
|
||||||
|
class TestProviderOAuth2OIDCImplicit(SeleniumTestCase):
|
||||||
|
"""test OAuth with OpenID Provider flow"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.client_id = generate_client_id()
|
||||||
|
self.client_secret = generate_client_secret()
|
||||||
|
self.application_slug = "test"
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
def setup_client(self) -> Container:
|
||||||
|
"""Setup client saml-sp container which we test SAML against"""
|
||||||
|
sleep(1)
|
||||||
|
client: DockerClient = from_env()
|
||||||
|
container = client.containers.run(
|
||||||
|
image="beryju/oidc-test-client",
|
||||||
|
detach=True,
|
||||||
|
network_mode="host",
|
||||||
|
auto_remove=True,
|
||||||
|
healthcheck=Healthcheck(
|
||||||
|
test=["CMD", "wget", "--spider", "http://localhost:9009/health"],
|
||||||
|
interval=5 * 100 * 1000000,
|
||||||
|
start_period=1 * 100 * 1000000,
|
||||||
|
),
|
||||||
|
environment={
|
||||||
|
"OIDC_CLIENT_ID": self.client_id,
|
||||||
|
"OIDC_CLIENT_SECRET": self.client_secret,
|
||||||
|
"OIDC_PROVIDER": f"{self.live_server_url}/application/o/{self.application_slug}/",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
while True:
|
||||||
|
container.reload()
|
||||||
|
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
|
||||||
|
if status == "healthy":
|
||||||
|
return container
|
||||||
|
LOGGER.info("Container failed healthcheck")
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
@retry()
|
||||||
|
@apply_migration("authentik_core", "0003_default_user")
|
||||||
|
@apply_migration("authentik_flows", "0008_default_flows")
|
||||||
|
@apply_migration("authentik_flows", "0010_provider_flows")
|
||||||
|
@apply_migration("authentik_crypto", "0002_create_self_signed_kp")
|
||||||
|
def test_redirect_uri_error(self):
|
||||||
|
"""test OpenID Provider flow (invalid redirect URI, check error message)"""
|
||||||
|
sleep(1)
|
||||||
|
# Bootstrap all needed objects
|
||||||
|
authorization_flow = Flow.objects.get(
|
||||||
|
slug="default-provider-authorization-implicit-consent"
|
||||||
|
)
|
||||||
|
provider = OAuth2Provider.objects.create(
|
||||||
|
name=self.application_slug,
|
||||||
|
client_type=ClientTypes.CONFIDENTIAL,
|
||||||
|
client_id=self.client_id,
|
||||||
|
client_secret=self.client_secret,
|
||||||
|
rsa_key=CertificateKeyPair.objects.first(),
|
||||||
|
redirect_uris="http://localhost:9009/",
|
||||||
|
authorization_flow=authorization_flow,
|
||||||
|
)
|
||||||
|
provider.property_mappings.set(
|
||||||
|
ScopeMapping.objects.filter(
|
||||||
|
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
provider.save()
|
||||||
|
Application.objects.create(
|
||||||
|
name=self.application_slug,
|
||||||
|
slug=self.application_slug,
|
||||||
|
provider=provider,
|
||||||
|
)
|
||||||
|
self.container = self.setup_client()
|
||||||
|
|
||||||
|
self.driver.get("http://localhost:9009/implicit/")
|
||||||
|
sleep(2)
|
||||||
|
self.assertEqual(
|
||||||
|
self.driver.find_element(By.CLASS_NAME, "pf-c-title").text,
|
||||||
|
"Redirect URI Error",
|
||||||
|
)
|
||||||
|
|
||||||
|
@retry()
|
||||||
|
@apply_migration("authentik_core", "0003_default_user")
|
||||||
|
@apply_migration("authentik_flows", "0008_default_flows")
|
||||||
|
@apply_migration("authentik_flows", "0010_provider_flows")
|
||||||
|
@apply_migration("authentik_crypto", "0002_create_self_signed_kp")
|
||||||
|
@object_manager
|
||||||
|
def test_authorization_consent_implied(self):
|
||||||
|
"""test OpenID Provider flow (default authorization flow with implied consent)"""
|
||||||
|
sleep(1)
|
||||||
|
# Bootstrap all needed objects
|
||||||
|
authorization_flow = Flow.objects.get(
|
||||||
|
slug="default-provider-authorization-implicit-consent"
|
||||||
|
)
|
||||||
|
provider = OAuth2Provider.objects.create(
|
||||||
|
name=self.application_slug,
|
||||||
|
client_type=ClientTypes.CONFIDENTIAL,
|
||||||
|
client_id=self.client_id,
|
||||||
|
client_secret=self.client_secret,
|
||||||
|
rsa_key=CertificateKeyPair.objects.first(),
|
||||||
|
redirect_uris="http://localhost:9009/implicit/",
|
||||||
|
authorization_flow=authorization_flow,
|
||||||
|
)
|
||||||
|
provider.property_mappings.set(
|
||||||
|
ScopeMapping.objects.filter(
|
||||||
|
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
provider.save()
|
||||||
|
Application.objects.create(
|
||||||
|
name=self.application_slug,
|
||||||
|
slug=self.application_slug,
|
||||||
|
provider=provider,
|
||||||
|
)
|
||||||
|
self.container = self.setup_client()
|
||||||
|
|
||||||
|
self.driver.get("http://localhost:9009/implicit/")
|
||||||
|
self.login()
|
||||||
|
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "pre")))
|
||||||
|
sleep(1)
|
||||||
|
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
|
||||||
|
print(body)
|
||||||
|
self.assertEqual(body["profile"]["nickname"], USER().username)
|
||||||
|
self.assertEqual(body["profile"]["name"], USER().name)
|
||||||
|
self.assertEqual(body["profile"]["email"], USER().email)
|
||||||
|
|
||||||
|
@retry()
|
||||||
|
@apply_migration("authentik_core", "0003_default_user")
|
||||||
|
@apply_migration("authentik_flows", "0008_default_flows")
|
||||||
|
@apply_migration("authentik_flows", "0010_provider_flows")
|
||||||
|
@apply_migration("authentik_crypto", "0002_create_self_signed_kp")
|
||||||
|
@object_manager
|
||||||
|
def test_authorization_consent_explicit(self):
|
||||||
|
"""test OpenID Provider flow (default authorization flow with explicit consent)"""
|
||||||
|
sleep(1)
|
||||||
|
# Bootstrap all needed objects
|
||||||
|
authorization_flow = Flow.objects.get(
|
||||||
|
slug="default-provider-authorization-explicit-consent"
|
||||||
|
)
|
||||||
|
provider = OAuth2Provider.objects.create(
|
||||||
|
name=self.application_slug,
|
||||||
|
authorization_flow=authorization_flow,
|
||||||
|
client_type=ClientTypes.CONFIDENTIAL,
|
||||||
|
client_id=self.client_id,
|
||||||
|
client_secret=self.client_secret,
|
||||||
|
rsa_key=CertificateKeyPair.objects.first(),
|
||||||
|
redirect_uris="http://localhost:9009/implicit/",
|
||||||
|
)
|
||||||
|
provider.property_mappings.set(
|
||||||
|
ScopeMapping.objects.filter(
|
||||||
|
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
provider.save()
|
||||||
|
app = Application.objects.create(
|
||||||
|
name=self.application_slug,
|
||||||
|
slug=self.application_slug,
|
||||||
|
provider=provider,
|
||||||
|
)
|
||||||
|
self.container = self.setup_client()
|
||||||
|
|
||||||
|
self.driver.get("http://localhost:9009/implicit/")
|
||||||
|
self.login()
|
||||||
|
|
||||||
|
self.wait.until(
|
||||||
|
ec.presence_of_element_located((By.CSS_SELECTOR, "ak-flow-executor"))
|
||||||
|
)
|
||||||
|
|
||||||
|
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||||
|
consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor)
|
||||||
|
|
||||||
|
self.assertIn(
|
||||||
|
app.name,
|
||||||
|
consent_stage.find_element(By.CSS_SELECTOR, "#header-text").text,
|
||||||
|
)
|
||||||
|
consent_stage.find_element(
|
||||||
|
By.CSS_SELECTOR,
|
||||||
|
("[type=submit]"),
|
||||||
|
).click()
|
||||||
|
|
||||||
|
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "pre")))
|
||||||
|
sleep(1)
|
||||||
|
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
|
||||||
|
|
||||||
|
self.assertEqual(body["profile"]["nickname"], USER().username)
|
||||||
|
self.assertEqual(body["profile"]["name"], USER().name)
|
||||||
|
self.assertEqual(body["profile"]["email"], USER().email)
|
||||||
|
|
||||||
|
@retry()
|
||||||
|
@apply_migration("authentik_core", "0003_default_user")
|
||||||
|
@apply_migration("authentik_flows", "0008_default_flows")
|
||||||
|
@apply_migration("authentik_flows", "0010_provider_flows")
|
||||||
|
@apply_migration("authentik_crypto", "0002_create_self_signed_kp")
|
||||||
|
def test_authorization_denied(self):
|
||||||
|
"""test OpenID Provider flow (default authorization with access deny)"""
|
||||||
|
sleep(1)
|
||||||
|
# Bootstrap all needed objects
|
||||||
|
authorization_flow = Flow.objects.get(
|
||||||
|
slug="default-provider-authorization-explicit-consent"
|
||||||
|
)
|
||||||
|
provider = OAuth2Provider.objects.create(
|
||||||
|
name=self.application_slug,
|
||||||
|
authorization_flow=authorization_flow,
|
||||||
|
client_type=ClientTypes.CONFIDENTIAL,
|
||||||
|
client_id=self.client_id,
|
||||||
|
client_secret=self.client_secret,
|
||||||
|
rsa_key=CertificateKeyPair.objects.first(),
|
||||||
|
redirect_uris="http://localhost:9009/implicit/",
|
||||||
|
)
|
||||||
|
provider.property_mappings.set(
|
||||||
|
ScopeMapping.objects.filter(
|
||||||
|
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
provider.save()
|
||||||
|
app = Application.objects.create(
|
||||||
|
name=self.application_slug,
|
||||||
|
slug=self.application_slug,
|
||||||
|
provider=provider,
|
||||||
|
)
|
||||||
|
|
||||||
|
negative_policy = ExpressionPolicy.objects.create(
|
||||||
|
name="negative-static", expression="return False"
|
||||||
|
)
|
||||||
|
PolicyBinding.objects.create(target=app, policy=negative_policy, order=0)
|
||||||
|
|
||||||
|
self.container = self.setup_client()
|
||||||
|
self.driver.get("http://localhost:9009/implicit/")
|
||||||
|
self.login()
|
||||||
|
self.wait.until(
|
||||||
|
ec.presence_of_element_located((By.CSS_SELECTOR, "header > h1"))
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
self.driver.find_element(By.CSS_SELECTOR, "header > h1").text,
|
||||||
|
"Permission denied",
|
||||||
|
)
|
|
@ -3,11 +3,13 @@ from shutil import rmtree
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
import yaml
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from docker import DockerClient, from_env
|
from docker import DockerClient, from_env
|
||||||
from docker.models.containers import Container
|
from docker.models.containers import Container
|
||||||
from docker.types.healthcheck import Healthcheck
|
from docker.types.healthcheck import Healthcheck
|
||||||
|
|
||||||
|
from authentik import __version__
|
||||||
from authentik.crypto.models import CertificateKeyPair
|
from authentik.crypto.models import CertificateKeyPair
|
||||||
from authentik.flows.models import Flow
|
from authentik.flows.models import Flow
|
||||||
from authentik.outposts.apps import AuthentikOutpostConfig
|
from authentik.outposts.apps import AuthentikOutpostConfig
|
||||||
|
@ -93,3 +95,14 @@ class OutpostDockerTests(TestCase):
|
||||||
controller = DockerController(self.outpost, self.service_connection)
|
controller = DockerController(self.outpost, self.service_connection)
|
||||||
controller.up()
|
controller.up()
|
||||||
controller.down()
|
controller.down()
|
||||||
|
|
||||||
|
def test_docker_static(self):
|
||||||
|
"""test that deployment requires update"""
|
||||||
|
controller = DockerController(self.outpost, self.service_connection)
|
||||||
|
manifest = controller.get_static_deployment()
|
||||||
|
compose = yaml.load(manifest, Loader=yaml.SafeLoader)
|
||||||
|
self.assertEqual(compose["version"], "3.5")
|
||||||
|
self.assertEqual(
|
||||||
|
compose["services"]["authentik_proxy"]["image"],
|
||||||
|
f"beryju/authentik-proxy:{__version__}",
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
"""outpost tests"""
|
||||||
|
from shutil import rmtree
|
||||||
|
from tempfile import mkdtemp
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
from django.test import TestCase
|
||||||
|
from docker import DockerClient, from_env
|
||||||
|
from docker.models.containers import Container
|
||||||
|
from docker.types.healthcheck import Healthcheck
|
||||||
|
|
||||||
|
from authentik import __version__
|
||||||
|
from authentik.crypto.models import CertificateKeyPair
|
||||||
|
from authentik.flows.models import Flow
|
||||||
|
from authentik.outposts.apps import AuthentikOutpostConfig
|
||||||
|
from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostType
|
||||||
|
from authentik.providers.proxy.controllers.docker import DockerController
|
||||||
|
from authentik.providers.proxy.models import ProxyProvider
|
||||||
|
|
||||||
|
|
||||||
|
class TestProxyDocker(TestCase):
|
||||||
|
"""Test Docker Controllers"""
|
||||||
|
|
||||||
|
def _start_container(self, ssl_folder: str) -> Container:
|
||||||
|
client: DockerClient = from_env()
|
||||||
|
container = client.containers.run(
|
||||||
|
image="library/docker:dind",
|
||||||
|
detach=True,
|
||||||
|
network_mode="host",
|
||||||
|
remove=True,
|
||||||
|
privileged=True,
|
||||||
|
healthcheck=Healthcheck(
|
||||||
|
test=["CMD", "docker", "info"],
|
||||||
|
interval=5 * 100 * 1000000,
|
||||||
|
start_period=5 * 100 * 1000000,
|
||||||
|
),
|
||||||
|
environment={"DOCKER_TLS_CERTDIR": "/ssl"},
|
||||||
|
volumes={
|
||||||
|
f"{ssl_folder}/": {
|
||||||
|
"bind": "/ssl",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
while True:
|
||||||
|
container.reload()
|
||||||
|
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
|
||||||
|
if status == "healthy":
|
||||||
|
return container
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.ssl_folder = mkdtemp()
|
||||||
|
self.container = self._start_container(self.ssl_folder)
|
||||||
|
# Ensure that local connection have been created
|
||||||
|
AuthentikOutpostConfig.init_local_connection()
|
||||||
|
self.provider: ProxyProvider = ProxyProvider.objects.create(
|
||||||
|
name="test",
|
||||||
|
internal_host="http://localhost",
|
||||||
|
external_host="http://localhost",
|
||||||
|
authorization_flow=Flow.objects.first(),
|
||||||
|
)
|
||||||
|
authentication_kp = CertificateKeyPair.objects.create(
|
||||||
|
name="docker-authentication",
|
||||||
|
certificate_data=open(f"{self.ssl_folder}/client/cert.pem").read(),
|
||||||
|
key_data=open(f"{self.ssl_folder}/client/key.pem").read(),
|
||||||
|
)
|
||||||
|
verification_kp = CertificateKeyPair.objects.create(
|
||||||
|
name="docker-verification",
|
||||||
|
certificate_data=open(f"{self.ssl_folder}/client/ca.pem").read(),
|
||||||
|
)
|
||||||
|
self.service_connection = DockerServiceConnection.objects.create(
|
||||||
|
url="https://localhost:2376",
|
||||||
|
tls_verification=verification_kp,
|
||||||
|
tls_authentication=authentication_kp,
|
||||||
|
)
|
||||||
|
self.outpost: Outpost = Outpost.objects.create(
|
||||||
|
name="test",
|
||||||
|
type=OutpostType.PROXY,
|
||||||
|
service_connection=self.service_connection,
|
||||||
|
)
|
||||||
|
self.outpost.providers.add(self.provider)
|
||||||
|
self.outpost.save()
|
||||||
|
|
||||||
|
def tearDown(self) -> None:
|
||||||
|
super().tearDown()
|
||||||
|
self.container.kill()
|
||||||
|
try:
|
||||||
|
rmtree(self.ssl_folder)
|
||||||
|
except PermissionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_docker_controller(self):
|
||||||
|
"""test that deployment requires update"""
|
||||||
|
controller = DockerController(self.outpost, self.service_connection)
|
||||||
|
controller.up()
|
||||||
|
controller.down()
|
||||||
|
|
||||||
|
def test_docker_static(self):
|
||||||
|
"""test that deployment requires update"""
|
||||||
|
controller = DockerController(self.outpost, self.service_connection)
|
||||||
|
manifest = controller.get_static_deployment()
|
||||||
|
compose = yaml.load(manifest, Loader=yaml.SafeLoader)
|
||||||
|
self.assertEqual(compose["version"], "3.5")
|
||||||
|
self.assertEqual(
|
||||||
|
compose["services"]["authentik_proxy"]["image"],
|
||||||
|
f"beryju/authentik-proxy:{__version__}",
|
||||||
|
)
|
|
@ -9,7 +9,7 @@ from authentik.providers.proxy.controllers.kubernetes import ProxyKubernetesCont
|
||||||
from authentik.providers.proxy.models import ProxyProvider
|
from authentik.providers.proxy.models import ProxyProvider
|
||||||
|
|
||||||
|
|
||||||
class TestControllers(TestCase):
|
class TestProxyKubernetes(TestCase):
|
||||||
"""Test Controllers"""
|
"""Test Controllers"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
@ -4,3 +4,8 @@ node_modules
|
||||||
dist
|
dist
|
||||||
# don't lint nyc coverage output
|
# don't lint nyc coverage output
|
||||||
coverage
|
coverage
|
||||||
|
# don't lint generated code
|
||||||
|
src/api/apis
|
||||||
|
src/api/models
|
||||||
|
src/api/index.ts
|
||||||
|
src/api/runtime.ts
|
||||||
|
|
|
@ -10,6 +10,25 @@ variables:
|
||||||
branchName: ${{ replace(variables['Build.SourceBranchName'], 'refs/heads/', '') }}
|
branchName: ${{ replace(variables['Build.SourceBranchName'], 'refs/heads/', '') }}
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
|
- stage: generate
|
||||||
|
jobs:
|
||||||
|
- job: swagger_generate
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- task: NodeTool@0
|
||||||
|
inputs:
|
||||||
|
versionSpec: '12.x'
|
||||||
|
displayName: 'Install Node.js'
|
||||||
|
- task: CmdLine@2
|
||||||
|
inputs:
|
||||||
|
script: |
|
||||||
|
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/src/api --additional-properties=typescriptThreePlus=true
|
||||||
|
- task: PublishPipelineArtifact@1
|
||||||
|
inputs:
|
||||||
|
targetPath: 'web/src/api/'
|
||||||
|
artifact: 'ts_swagger_client'
|
||||||
|
publishLocation: 'pipeline'
|
||||||
- stage: lint
|
- stage: lint
|
||||||
jobs:
|
jobs:
|
||||||
- job: eslint
|
- job: eslint
|
||||||
|
@ -20,6 +39,11 @@ stages:
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '12.x'
|
versionSpec: '12.x'
|
||||||
displayName: 'Install Node.js'
|
displayName: 'Install Node.js'
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
inputs:
|
||||||
|
buildType: 'current'
|
||||||
|
artifactName: 'ts_swagger_client'
|
||||||
|
path: "web/src/api/"
|
||||||
- task: Npm@1
|
- task: Npm@1
|
||||||
inputs:
|
inputs:
|
||||||
command: 'install'
|
command: 'install'
|
||||||
|
@ -37,6 +61,11 @@ stages:
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '12.x'
|
versionSpec: '12.x'
|
||||||
displayName: 'Install Node.js'
|
displayName: 'Install Node.js'
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
inputs:
|
||||||
|
buildType: 'current'
|
||||||
|
artifactName: 'ts_swagger_client'
|
||||||
|
path: "web/src/api/"
|
||||||
- task: Npm@1
|
- task: Npm@1
|
||||||
inputs:
|
inputs:
|
||||||
command: 'install'
|
command: 'install'
|
||||||
|
@ -56,6 +85,11 @@ stages:
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '12.x'
|
versionSpec: '12.x'
|
||||||
displayName: 'Install Node.js'
|
displayName: 'Install Node.js'
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
inputs:
|
||||||
|
buildType: 'current'
|
||||||
|
artifactName: 'ts_swagger_client'
|
||||||
|
path: "web/src/api/"
|
||||||
- task: Npm@1
|
- task: Npm@1
|
||||||
inputs:
|
inputs:
|
||||||
command: 'install'
|
command: 'install'
|
||||||
|
@ -71,6 +105,11 @@ stages:
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'ubuntu-latest'
|
vmImage: 'ubuntu-latest'
|
||||||
steps:
|
steps:
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
inputs:
|
||||||
|
buildType: 'current'
|
||||||
|
artifactName: 'ts_swagger_client'
|
||||||
|
path: "web/src/api/"
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
inputs:
|
inputs:
|
||||||
targetType: 'inline'
|
targetType: 'inline'
|
||||||
|
|
|
@ -103,9 +103,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@patternfly/patternfly": {
|
"@patternfly/patternfly": {
|
||||||
"version": "4.87.3",
|
"version": "4.90.5",
|
||||||
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.87.3.tgz",
|
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.90.5.tgz",
|
||||||
"integrity": "sha512-hDNMPa7B1zKD8LWFZO4SS5hC/N+yvuci2sAn8HJd+EIbAvbMAUkRsyZ0/XO3BG3RVtpSlgq7q8x1pAHC/FTFuA=="
|
"integrity": "sha512-Fe0C8UkzSjtacQ+fHXlFB/LHzrv/c2K4z479C6dboOgkGQE1FyB0wt1NBfxij0D++rhOy04OOYdE+Tr0JSlZKw=="
|
||||||
},
|
},
|
||||||
"@rollup/plugin-typescript": {
|
"@rollup/plugin-typescript": {
|
||||||
"version": "8.2.0",
|
"version": "8.2.0",
|
||||||
|
@ -143,27 +143,27 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/browser": {
|
"@sentry/browser": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.2.2.tgz",
|
||||||
"integrity": "sha512-OAikFZ9EimD3noxMp8tA6Cf6qJcQ2U8k5QSgTPwdx+09nZOGJzbRFteK7WWmrS93ZJdzN61lpSQbg5v+bmmfbQ==",
|
"integrity": "sha512-K5UGyEePtVPZIFMoiRafhd4Ov0M1kdozVsVKIPZrOpJyjQdPNX+fYDNL/h0nVmgOlE2S/uu4fl4mEfe/6aLShw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/core": "6.2.1",
|
"@sentry/core": "6.2.2",
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"@sentry/utils": "6.2.1",
|
"@sentry/utils": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/types": {
|
"@sentry/types": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.2.tgz",
|
||||||
"integrity": "sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA=="
|
"integrity": "sha512-Y/1sRtw3a5JU4YdNBig8lLSVJ1UdYtuge+QP1CVLcLSAbq07Ok1bvF+Z+BlNcnHqle2Fl8aKuryG5Yu86enOyQ=="
|
||||||
},
|
},
|
||||||
"@sentry/utils": {
|
"@sentry/utils": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.2.tgz",
|
||||||
"integrity": "sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==",
|
"integrity": "sha512-qaee6X6VDNZ8HeO83/veaKw0KuhDE7j1R+Yryme3PywFzsoTzutDrEQjb7gvcHAhBaAYX8IHUBHgxcFI9BxI+w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -175,48 +175,48 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/core": {
|
"@sentry/core": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.2.2.tgz",
|
||||||
"integrity": "sha512-jPqQEtafxxDtLONhCbTHh/Uq8mZRhsfbwJTSVYfPVEe/ELfFZLQK7tP6rOh7zEWKbTkE0mE6XcaoH3ZRAhgrqg==",
|
"integrity": "sha512-qqWbvvXtymfXh7N5eEvk97MCnMURuyFIgqWdVD4MQM6yIfDCy36CyGfuQ3ViHTLZGdIfEOhLL9/f4kzf1RzqBA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.2.1",
|
"@sentry/hub": "6.2.2",
|
||||||
"@sentry/minimal": "6.2.1",
|
"@sentry/minimal": "6.2.2",
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"@sentry/utils": "6.2.1",
|
"@sentry/utils": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/hub": {
|
"@sentry/hub": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.2.tgz",
|
||||||
"integrity": "sha512-pG7wCQeRpzeP6t0bT4T0X029R19dbDS3/qswF8BL6bg0AI3afjfjBAZm/fqn1Uwe/uBoMHVVdbxgJDZeQ5d4rQ==",
|
"integrity": "sha512-VR6uQGRYt6RP633FHShlSLj0LUKGVrlTeSlwCoooWM5FR9lmi6akAaweuxpG78/kZvXrAWpjX6/nuYwHKGwzGA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"@sentry/utils": "6.2.1",
|
"@sentry/utils": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/minimal": {
|
"@sentry/minimal": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.2.tgz",
|
||||||
"integrity": "sha512-wuSXB4Ayxv9rBEQ4pm7fnG4UU2ZPtPnnChoEfd4/mw1UthXSvmPFEn6O4pdo2G8fTkl8eqm6wT/Q7uIXMEmw+A==",
|
"integrity": "sha512-l0IgoGQgg1lTd4qDU8bQn25sbZBg8PwIHfuTLbGMlRr1flDXHOM1UXajWK/UKbAPelnU7M2JBSVzgl7PwjprzA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.2.1",
|
"@sentry/hub": "6.2.2",
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/types": {
|
"@sentry/types": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.2.tgz",
|
||||||
"integrity": "sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA=="
|
"integrity": "sha512-Y/1sRtw3a5JU4YdNBig8lLSVJ1UdYtuge+QP1CVLcLSAbq07Ok1bvF+Z+BlNcnHqle2Fl8aKuryG5Yu86enOyQ=="
|
||||||
},
|
},
|
||||||
"@sentry/utils": {
|
"@sentry/utils": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.2.tgz",
|
||||||
"integrity": "sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==",
|
"integrity": "sha512-qaee6X6VDNZ8HeO83/veaKw0KuhDE7j1R+Yryme3PywFzsoTzutDrEQjb7gvcHAhBaAYX8IHUBHgxcFI9BxI+w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -228,12 +228,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/hub": {
|
"@sentry/hub": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.2.tgz",
|
||||||
"integrity": "sha512-pG7wCQeRpzeP6t0bT4T0X029R19dbDS3/qswF8BL6bg0AI3afjfjBAZm/fqn1Uwe/uBoMHVVdbxgJDZeQ5d4rQ==",
|
"integrity": "sha512-VR6uQGRYt6RP633FHShlSLj0LUKGVrlTeSlwCoooWM5FR9lmi6akAaweuxpG78/kZvXrAWpjX6/nuYwHKGwzGA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"@sentry/utils": "6.2.1",
|
"@sentry/utils": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -245,12 +245,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/minimal": {
|
"@sentry/minimal": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.2.tgz",
|
||||||
"integrity": "sha512-wuSXB4Ayxv9rBEQ4pm7fnG4UU2ZPtPnnChoEfd4/mw1UthXSvmPFEn6O4pdo2G8fTkl8eqm6wT/Q7uIXMEmw+A==",
|
"integrity": "sha512-l0IgoGQgg1lTd4qDU8bQn25sbZBg8PwIHfuTLbGMlRr1flDXHOM1UXajWK/UKbAPelnU7M2JBSVzgl7PwjprzA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.2.1",
|
"@sentry/hub": "6.2.2",
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -262,14 +262,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/tracing": {
|
"@sentry/tracing": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.2.2.tgz",
|
||||||
"integrity": "sha512-bvStY1SnL08wkSeVK3j9K5rivQQJdKFCPR2VYRFOCaUoleZ6ChPUnBvxQ/E2LXc0hk/y/wo1q4r5B0dfCCY+bQ==",
|
"integrity": "sha512-mAkPoqtofNfka/u9rOVVDQPaEoTmr0AQh654g9ZqsaqsOJLKjB4FDLVNubWs90fjeKqHiYkI3ZHPak2TzHBPkw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.2.1",
|
"@sentry/hub": "6.2.2",
|
||||||
"@sentry/minimal": "6.2.1",
|
"@sentry/minimal": "6.2.2",
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"@sentry/utils": "6.2.1",
|
"@sentry/utils": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -281,16 +281,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/types": {
|
"@sentry/types": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.2.tgz",
|
||||||
"integrity": "sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA=="
|
"integrity": "sha512-Y/1sRtw3a5JU4YdNBig8lLSVJ1UdYtuge+QP1CVLcLSAbq07Ok1bvF+Z+BlNcnHqle2Fl8aKuryG5Yu86enOyQ=="
|
||||||
},
|
},
|
||||||
"@sentry/utils": {
|
"@sentry/utils": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.2.tgz",
|
||||||
"integrity": "sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==",
|
"integrity": "sha512-qaee6X6VDNZ8HeO83/veaKw0KuhDE7j1R+Yryme3PywFzsoTzutDrEQjb7gvcHAhBaAYX8IHUBHgxcFI9BxI+w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.2.1",
|
"@sentry/types": "6.2.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -310,12 +310,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/clean-css": {
|
"@types/clean-css": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.3.tgz",
|
||||||
"integrity": "sha512-xiTJn3bmDh1lA8c6iVJs4ZhHw+pcmxXlJQXOB6G1oULaak8rmarIeFKI4aTJ7849dEhaO612wgIualZfbxTJwA==",
|
"integrity": "sha512-ET0ldU/vpXecy5vO8JRIhtJWSrk1vzXdJcp3Bjf8bARZynl6vfkhEKY/A7njfNIRlmyTGuVFuqnD6I3tOGdXpQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "*"
|
"@types/node": "*",
|
||||||
|
"source-map": "^0.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/codemirror": {
|
"@types/codemirror": {
|
||||||
|
@ -404,22 +405,22 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/uglify-js": {
|
"@types/uglify-js": {
|
||||||
"version": "3.11.0",
|
"version": "3.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.0.tgz",
|
||||||
"integrity": "sha512-I0Yd8TUELTbgRHq2K65j8rnDPAzAP+DiaF/syLem7yXwYLsHZhPd+AM2iXsWmf9P2F2NlFCgl5erZPQx9IbM9Q==",
|
"integrity": "sha512-EGkrJD5Uy+Pg0NUR8uA4bJ5WMfljyad0G+784vLCNUkD+QwOJXUbBYExXfVGf7YtyzdQp3L/XMYcliB987kL5Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"source-map": "^0.6.1"
|
"source-map": "^0.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/eslint-plugin": {
|
"@typescript-eslint/eslint-plugin": {
|
||||||
"version": "4.16.1",
|
"version": "4.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.17.0.tgz",
|
||||||
"integrity": "sha512-SK777klBdlkUZpZLC1mPvyOWk9yAFCWmug13eAjVQ4/Q1LATE/NbcQL1xDHkptQkZOLnPmLUA1Y54m8dqYwnoQ==",
|
"integrity": "sha512-/fKFDcoHg8oNan39IKFOb5WmV7oWhQe1K6CDaAVfJaNWEhmfqlA24g+u1lqU5bMH7zuNasfMId4LaYWC5ijRLw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/experimental-utils": "4.16.1",
|
"@typescript-eslint/experimental-utils": "4.17.0",
|
||||||
"@typescript-eslint/scope-manager": "4.16.1",
|
"@typescript-eslint/scope-manager": "4.17.0",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
|
@ -429,112 +430,55 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/experimental-utils": {
|
"@typescript-eslint/experimental-utils": {
|
||||||
"version": "4.16.1",
|
"version": "4.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.17.0.tgz",
|
||||||
"integrity": "sha512-0Hm3LSlMYFK17jO4iY3un1Ve9x1zLNn4EM50Lia+0EV99NdbK+cn0er7HC7IvBA23mBg3P+8dUkMXy4leL33UQ==",
|
"integrity": "sha512-ZR2NIUbnIBj+LGqCFGQ9yk2EBQrpVVFOh9/Kd0Lm6gLpSAcCuLLe5lUCibKGCqyH9HPwYC0GIJce2O1i8VYmWA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/json-schema": "^7.0.3",
|
"@types/json-schema": "^7.0.3",
|
||||||
"@typescript-eslint/scope-manager": "4.16.1",
|
"@typescript-eslint/scope-manager": "4.17.0",
|
||||||
"@typescript-eslint/types": "4.16.1",
|
"@typescript-eslint/types": "4.17.0",
|
||||||
"@typescript-eslint/typescript-estree": "4.16.1",
|
"@typescript-eslint/typescript-estree": "4.17.0",
|
||||||
"eslint-scope": "^5.0.0",
|
"eslint-scope": "^5.0.0",
|
||||||
"eslint-utils": "^2.0.0"
|
"eslint-utils": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
"version": "4.16.1",
|
"version": "4.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.17.0.tgz",
|
||||||
"integrity": "sha512-/c0LEZcDL5y8RyI1zLcmZMvJrsR6SM1uetskFkoh3dvqDKVXPsXI+wFB/CbVw7WkEyyTKobC1mUNp/5y6gRvXg==",
|
"integrity": "sha512-KYdksiZQ0N1t+6qpnl6JeK9ycCFprS9xBAiIrw4gSphqONt8wydBw4BXJi3C11ywZmyHulvMaLjWsxDjUSDwAw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/scope-manager": "4.16.1",
|
"@typescript-eslint/scope-manager": "4.17.0",
|
||||||
"@typescript-eslint/types": "4.16.1",
|
"@typescript-eslint/types": "4.17.0",
|
||||||
"@typescript-eslint/typescript-estree": "4.16.1",
|
"@typescript-eslint/typescript-estree": "4.17.0",
|
||||||
"debug": "^4.1.1"
|
"debug": "^4.1.1"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/scope-manager": {
|
|
||||||
"version": "4.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz",
|
|
||||||
"integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@typescript-eslint/types": "4.16.1",
|
|
||||||
"@typescript-eslint/visitor-keys": "4.16.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@typescript-eslint/types": {
|
|
||||||
"version": "4.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz",
|
|
||||||
"integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@typescript-eslint/typescript-estree": {
|
|
||||||
"version": "4.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz",
|
|
||||||
"integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@typescript-eslint/types": "4.16.1",
|
|
||||||
"@typescript-eslint/visitor-keys": "4.16.1",
|
|
||||||
"debug": "^4.1.1",
|
|
||||||
"globby": "^11.0.1",
|
|
||||||
"is-glob": "^4.0.1",
|
|
||||||
"semver": "^7.3.2",
|
|
||||||
"tsutils": "^3.17.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@typescript-eslint/visitor-keys": {
|
|
||||||
"version": "4.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz",
|
|
||||||
"integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@typescript-eslint/types": "4.16.1",
|
|
||||||
"eslint-visitor-keys": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"globby": {
|
|
||||||
"version": "11.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
|
|
||||||
"integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"array-union": "^2.1.0",
|
|
||||||
"dir-glob": "^3.0.1",
|
|
||||||
"fast-glob": "^3.1.1",
|
|
||||||
"ignore": "^5.1.4",
|
|
||||||
"merge2": "^1.3.0",
|
|
||||||
"slash": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/scope-manager": {
|
"@typescript-eslint/scope-manager": {
|
||||||
"version": "4.16.1",
|
"version": "4.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.17.0.tgz",
|
||||||
"integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==",
|
"integrity": "sha512-OJ+CeTliuW+UZ9qgULrnGpPQ1bhrZNFpfT/Bc0pzNeyZwMik7/ykJ0JHnQ7krHanFN9wcnPK89pwn84cRUmYjw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.16.1",
|
"@typescript-eslint/types": "4.17.0",
|
||||||
"@typescript-eslint/visitor-keys": "4.16.1"
|
"@typescript-eslint/visitor-keys": "4.17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/types": {
|
"@typescript-eslint/types": {
|
||||||
"version": "4.16.1",
|
"version": "4.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.17.0.tgz",
|
||||||
"integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==",
|
"integrity": "sha512-RN5z8qYpJ+kXwnLlyzZkiJwfW2AY458Bf8WqllkondQIcN2ZxQowAToGSd9BlAUZDB5Ea8I6mqL2quGYCLT+2g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@typescript-eslint/typescript-estree": {
|
"@typescript-eslint/typescript-estree": {
|
||||||
"version": "4.16.1",
|
"version": "4.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.17.0.tgz",
|
||||||
"integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==",
|
"integrity": "sha512-lRhSFIZKUEPPWpWfwuZBH9trYIEJSI0vYsrxbvVvNyIUDoKWaklOAelsSkeh3E2VBSZiNe9BZ4E5tYBZbUczVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.16.1",
|
"@typescript-eslint/types": "4.17.0",
|
||||||
"@typescript-eslint/visitor-keys": "4.16.1",
|
"@typescript-eslint/visitor-keys": "4.17.0",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"globby": "^11.0.1",
|
"globby": "^11.0.1",
|
||||||
"is-glob": "^4.0.1",
|
"is-glob": "^4.0.1",
|
||||||
|
@ -559,12 +503,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/visitor-keys": {
|
"@typescript-eslint/visitor-keys": {
|
||||||
"version": "4.16.1",
|
"version": "4.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.17.0.tgz",
|
||||||
"integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==",
|
"integrity": "sha512-WfuMN8mm5SSqXuAr9NM+fItJ0SVVphobWYkWOwQ1odsfC014Vdxk/92t4JwS1Q6fCA/ABfCKpa3AVtpUKTNKGQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.16.1",
|
"@typescript-eslint/types": "4.17.0",
|
||||||
"eslint-visitor-keys": "^2.0.0"
|
"eslint-visitor-keys": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2280,16 +2224,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minify-html-literals": {
|
"minify-html-literals": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/minify-html-literals/-/minify-html-literals-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/minify-html-literals/-/minify-html-literals-1.3.5.tgz",
|
||||||
"integrity": "sha512-DBdi0md84vjvwmLoo9xleFV5FkhzOwfKBqcmoVFL54c9CFlSBtG9KTKEQqiwscB+acewculqys1cDnwyrYlNtg==",
|
"integrity": "sha512-p8T8ryePRR8FVfJZLVFmM53WY25FL0moCCTycUDuAu6rf9GMLwy0gNjXBGNin3Yun7Y+tIWd28axOf0t2EpAlQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/html-minifier": "^3.5.3",
|
"@types/html-minifier": "^3.5.3",
|
||||||
"clean-css": "^4.2.1",
|
"clean-css": "^4.2.1",
|
||||||
"html-minifier": "^4.0.0",
|
"html-minifier": "^4.0.0",
|
||||||
"magic-string": "^0.25.0",
|
"magic-string": "^0.25.0",
|
||||||
"parse-literals": "^1.2.0"
|
"parse-literals": "^1.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
|
@ -2489,20 +2433,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parse-literals": {
|
"parse-literals": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/parse-literals/-/parse-literals-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/parse-literals/-/parse-literals-1.2.1.tgz",
|
||||||
"integrity": "sha512-gh4zPwvFSXx9ginX8lu9MP3OPHN3VV12PXI8IXD6oMCklFqM82pfbU9e/PKf9r7oLpbqlDSDyHYSVlxxuq3Iew==",
|
"integrity": "sha512-Ml0w104Ph2wwzuRdxrg9booVWsngXbB4bZ5T2z6WyF8b5oaNkUmBiDtahi34yUIpXD8Y13JjAK6UyIyApJ73RQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"typescript": "^2.9.2 || ^3.0.0"
|
"typescript": "^2.9.2 || ^3.0.0 || ^4.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"typescript": {
|
|
||||||
"version": "3.9.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
|
|
||||||
"integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parse5": {
|
"parse5": {
|
||||||
|
@ -2717,9 +2653,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rollup": {
|
"rollup": {
|
||||||
"version": "2.40.0",
|
"version": "2.41.1",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.40.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.41.1.tgz",
|
||||||
"integrity": "sha512-WiOGAPbXoHu+TOz6hyYUxIksOwsY/21TRWoO593jgYt8mvYafYqQl+axaA8y1z2HFazNUUrsMSjahV2A6/2R9A==",
|
"integrity": "sha512-nepLFAW5W71/MWpS2Yr7r31eS7HRfYg2RXnxb6ehqN9zY42yACxKtEfb4xq8SmNfUohAzGMcyl6jkwdLOAiUbg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fsevents": "~2.3.1"
|
"fsevents": "~2.3.1"
|
||||||
}
|
}
|
||||||
|
@ -2801,12 +2737,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rollup-plugin-minify-html-literals": {
|
"rollup-plugin-minify-html-literals": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/rollup-plugin-minify-html-literals/-/rollup-plugin-minify-html-literals-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/rollup-plugin-minify-html-literals/-/rollup-plugin-minify-html-literals-1.2.6.tgz",
|
||||||
"integrity": "sha512-x4FzCnbBpYdme7MQDS3+18CvYLqakAtM/JmA3hqXplwzMeZWW3l14KU7H33RhJlHH8Klgv49hGtBRLWLfjCudw==",
|
"integrity": "sha512-JRq2fjlCTiw0zu+1Sy3ClHGCxA79dWGr4HLHWSQgd060StVW9fBVksuj8Xw/suPkNSGClJf/4xNQ1MF6JeXPaw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minify-html-literals": "^1.3.2",
|
"minify-html-literals": "^1.3.5",
|
||||||
"rollup-pluginutils": "^2.8.2"
|
"rollup-pluginutils": "^2.8.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3383,15 +3319,15 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz",
|
||||||
"integrity": "sha512-tbb+NVrLfnsJy3M59lsDgrzWIflR4d4TIUjz+heUnHZwdF7YsrMTKoRERiIvI2lvBG95dfpLxB21WZhys1bgaQ==",
|
"integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"uglify-js": {
|
"uglify-js": {
|
||||||
"version": "3.11.0",
|
"version": "3.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.0.tgz",
|
||||||
"integrity": "sha512-e1KQFRCpOxnrJsJVqDUCjURq+wXvIn7cK2sRAx9XL3HYLL9aezOP4Pb1+Y3/o693EPk111Yj2Q+IUXxcpHlygQ==",
|
"integrity": "sha512-TWYSWa9T2pPN4DIJYbU9oAjQx+5qdV5RUDxwARg8fmJZrD/V27Zj0JngW5xg1DFz42G0uDYl2XhzF6alSzD62w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"union-value": {
|
"union-value": {
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.15.2",
|
"@fortawesome/fontawesome-free": "^5.15.2",
|
||||||
"@patternfly/patternfly": "^4.87.3",
|
"@patternfly/patternfly": "^4.90.5",
|
||||||
"@sentry/browser": "^6.2.1",
|
"@sentry/browser": "^6.2.2",
|
||||||
"@sentry/tracing": "^6.2.1",
|
"@sentry/tracing": "^6.2.2",
|
||||||
"@types/chart.js": "^2.9.31",
|
"@types/chart.js": "^2.9.31",
|
||||||
"@types/codemirror": "0.0.108",
|
"@types/codemirror": "0.0.108",
|
||||||
"@types/grecaptcha": "^3.0.1",
|
"@types/grecaptcha": "^3.0.1",
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
"flowchart.js": "^1.15.0",
|
"flowchart.js": "^1.15.0",
|
||||||
"lit-element": "^2.4.0",
|
"lit-element": "^2.4.0",
|
||||||
"lit-html": "^1.3.0",
|
"lit-html": "^1.3.0",
|
||||||
"rollup": "^2.40.0",
|
"rollup": "^2.41.1",
|
||||||
"rollup-plugin-copy": "^3.4.0",
|
"rollup-plugin-copy": "^3.4.0",
|
||||||
"rollup-plugin-cssimport": "^1.0.2",
|
"rollup-plugin-cssimport": "^1.0.2",
|
||||||
"rollup-plugin-external-globals": "^0.6.1",
|
"rollup-plugin-external-globals": "^0.6.1",
|
||||||
|
@ -33,17 +33,17 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-typescript": "^8.2.0",
|
"@rollup/plugin-typescript": "^8.2.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.16.1",
|
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||||
"@typescript-eslint/parser": "^4.16.1",
|
"@typescript-eslint/parser": "^4.17.0",
|
||||||
"eslint": "^7.21.0",
|
"eslint": "^7.21.0",
|
||||||
"eslint-config-google": "^0.14.0",
|
"eslint-config-google": "^0.14.0",
|
||||||
"eslint-plugin-lit": "^1.3.0",
|
"eslint-plugin-lit": "^1.3.0",
|
||||||
"rollup-plugin-commonjs": "^10.1.0",
|
"rollup-plugin-commonjs": "^10.1.0",
|
||||||
"rollup-plugin-minify-html-literals": "^1.2.5",
|
"rollup-plugin-minify-html-literals": "^1.2.6",
|
||||||
"rollup-plugin-node-resolve": "^5.2.0",
|
"rollup-plugin-node-resolve": "^5.2.0",
|
||||||
"rollup-plugin-sourcemaps": "^0.6.3",
|
"rollup-plugin-sourcemaps": "^0.6.3",
|
||||||
"rollup-plugin-terser": "^7.0.2",
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
"ts-lit-plugin": "^1.2.1",
|
"ts-lit-plugin": "^1.2.1",
|
||||||
"typescript": "^4.2.2"
|
"typescript": "^4.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
apis/**
|
||||||
|
models/**
|
||||||
|
index.ts
|
||||||
|
runtime.ts
|
|
@ -0,0 +1,23 @@
|
||||||
|
# OpenAPI Generator Ignore
|
||||||
|
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||||
|
|
||||||
|
# Use this file to prevent files from being overwritten by the generator.
|
||||||
|
# The patterns follow closely to .gitignore or .dockerignore.
|
||||||
|
|
||||||
|
# As an example, the C# client generator defines ApiClient.cs.
|
||||||
|
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||||
|
#ApiClient.cs
|
||||||
|
|
||||||
|
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||||
|
#foo/*/qux
|
||||||
|
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||||
|
|
||||||
|
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||||
|
#foo/**/qux
|
||||||
|
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||||
|
|
||||||
|
# You can also negate patterns with an exclamation (!).
|
||||||
|
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||||
|
#docs/*.md
|
||||||
|
# Then explicitly reverse the ignore rule for a single file:
|
||||||
|
#!docs/README.md
|
|
@ -0,0 +1,167 @@
|
||||||
|
apis/AdminApi.ts
|
||||||
|
apis/CoreApi.ts
|
||||||
|
apis/CryptoApi.ts
|
||||||
|
apis/EventsApi.ts
|
||||||
|
apis/FlowsApi.ts
|
||||||
|
apis/OutpostsApi.ts
|
||||||
|
apis/PoliciesApi.ts
|
||||||
|
apis/PropertymappingsApi.ts
|
||||||
|
apis/ProvidersApi.ts
|
||||||
|
apis/RootApi.ts
|
||||||
|
apis/SourcesApi.ts
|
||||||
|
apis/StagesApi.ts
|
||||||
|
apis/index.ts
|
||||||
|
index.ts
|
||||||
|
models/Application.ts
|
||||||
|
models/AuthenticateWebAuthnStage.ts
|
||||||
|
models/AuthenticatorStaticStage.ts
|
||||||
|
models/AuthenticatorTOTPStage.ts
|
||||||
|
models/AuthenticatorValidateStage.ts
|
||||||
|
models/Cache.ts
|
||||||
|
models/CaptchaStage.ts
|
||||||
|
models/CertificateData.ts
|
||||||
|
models/CertificateKeyPair.ts
|
||||||
|
models/Challenge.ts
|
||||||
|
models/Config.ts
|
||||||
|
models/ConsentStage.ts
|
||||||
|
models/Coordinate.ts
|
||||||
|
models/DenyStage.ts
|
||||||
|
models/DockerServiceConnection.ts
|
||||||
|
models/DummyPolicy.ts
|
||||||
|
models/DummyStage.ts
|
||||||
|
models/EmailStage.ts
|
||||||
|
models/ErrorDetail.ts
|
||||||
|
models/Event.ts
|
||||||
|
models/EventMatcherPolicy.ts
|
||||||
|
models/EventTopPerUser.ts
|
||||||
|
models/ExpressionPolicy.ts
|
||||||
|
models/Flow.ts
|
||||||
|
models/FlowDiagram.ts
|
||||||
|
models/FlowStageBinding.ts
|
||||||
|
models/Group.ts
|
||||||
|
models/GroupMembershipPolicy.ts
|
||||||
|
models/HaveIBeenPwendPolicy.ts
|
||||||
|
models/IPReputation.ts
|
||||||
|
models/IdentificationStage.ts
|
||||||
|
models/InlineResponse200.ts
|
||||||
|
models/InlineResponse2001.ts
|
||||||
|
models/InlineResponse20010.ts
|
||||||
|
models/InlineResponse20011.ts
|
||||||
|
models/InlineResponse20012.ts
|
||||||
|
models/InlineResponse20013.ts
|
||||||
|
models/InlineResponse20014.ts
|
||||||
|
models/InlineResponse20015.ts
|
||||||
|
models/InlineResponse20016.ts
|
||||||
|
models/InlineResponse20017.ts
|
||||||
|
models/InlineResponse20018.ts
|
||||||
|
models/InlineResponse20019.ts
|
||||||
|
models/InlineResponse2002.ts
|
||||||
|
models/InlineResponse20020.ts
|
||||||
|
models/InlineResponse20021.ts
|
||||||
|
models/InlineResponse20022.ts
|
||||||
|
models/InlineResponse20023.ts
|
||||||
|
models/InlineResponse20024.ts
|
||||||
|
models/InlineResponse20025.ts
|
||||||
|
models/InlineResponse20026.ts
|
||||||
|
models/InlineResponse20027.ts
|
||||||
|
models/InlineResponse20028.ts
|
||||||
|
models/InlineResponse20029.ts
|
||||||
|
models/InlineResponse2003.ts
|
||||||
|
models/InlineResponse20030.ts
|
||||||
|
models/InlineResponse20031.ts
|
||||||
|
models/InlineResponse20032.ts
|
||||||
|
models/InlineResponse20033.ts
|
||||||
|
models/InlineResponse20034.ts
|
||||||
|
models/InlineResponse20035.ts
|
||||||
|
models/InlineResponse20036.ts
|
||||||
|
models/InlineResponse20037.ts
|
||||||
|
models/InlineResponse20038.ts
|
||||||
|
models/InlineResponse20039.ts
|
||||||
|
models/InlineResponse2004.ts
|
||||||
|
models/InlineResponse20040.ts
|
||||||
|
models/InlineResponse20041.ts
|
||||||
|
models/InlineResponse20042.ts
|
||||||
|
models/InlineResponse20043.ts
|
||||||
|
models/InlineResponse20044.ts
|
||||||
|
models/InlineResponse20045.ts
|
||||||
|
models/InlineResponse20046.ts
|
||||||
|
models/InlineResponse20047.ts
|
||||||
|
models/InlineResponse20048.ts
|
||||||
|
models/InlineResponse20049.ts
|
||||||
|
models/InlineResponse2005.ts
|
||||||
|
models/InlineResponse20050.ts
|
||||||
|
models/InlineResponse20051.ts
|
||||||
|
models/InlineResponse20052.ts
|
||||||
|
models/InlineResponse20053.ts
|
||||||
|
models/InlineResponse20054.ts
|
||||||
|
models/InlineResponse20055.ts
|
||||||
|
models/InlineResponse20056.ts
|
||||||
|
models/InlineResponse20057.ts
|
||||||
|
models/InlineResponse20058.ts
|
||||||
|
models/InlineResponse20059.ts
|
||||||
|
models/InlineResponse2006.ts
|
||||||
|
models/InlineResponse20060.ts
|
||||||
|
models/InlineResponse2007.ts
|
||||||
|
models/InlineResponse2008.ts
|
||||||
|
models/InlineResponse2009.ts
|
||||||
|
models/InlineResponse200Pagination.ts
|
||||||
|
models/Invitation.ts
|
||||||
|
models/InvitationStage.ts
|
||||||
|
models/KubernetesServiceConnection.ts
|
||||||
|
models/LDAPPropertyMapping.ts
|
||||||
|
models/LDAPSource.ts
|
||||||
|
models/LDAPSourceSyncStatus.ts
|
||||||
|
models/LoginMetrics.ts
|
||||||
|
models/Notification.ts
|
||||||
|
models/NotificationRule.ts
|
||||||
|
models/NotificationRuleGroup.ts
|
||||||
|
models/NotificationRuleGroupParent.ts
|
||||||
|
models/NotificationRuleTransports.ts
|
||||||
|
models/NotificationTransport.ts
|
||||||
|
models/NotificationTransportTest.ts
|
||||||
|
models/OAuth2Provider.ts
|
||||||
|
models/OAuth2ProviderSetupURLs.ts
|
||||||
|
models/OAuthSource.ts
|
||||||
|
models/OpenIDConnectConfiguration.ts
|
||||||
|
models/Outpost.ts
|
||||||
|
models/OutpostHealth.ts
|
||||||
|
models/PasswordExpiryPolicy.ts
|
||||||
|
models/PasswordPolicy.ts
|
||||||
|
models/PasswordStage.ts
|
||||||
|
models/Policy.ts
|
||||||
|
models/PolicyBinding.ts
|
||||||
|
models/PolicyBindingPolicy.ts
|
||||||
|
models/PolicyBindingUser.ts
|
||||||
|
models/PolicyBindingUserAkGroups.ts
|
||||||
|
models/PolicyBindingUserGroups.ts
|
||||||
|
models/PolicyBindingUserSources.ts
|
||||||
|
models/PolicyBindingUserUserPermissions.ts
|
||||||
|
models/Prompt.ts
|
||||||
|
models/PromptStage.ts
|
||||||
|
models/PropertyMapping.ts
|
||||||
|
models/Provider.ts
|
||||||
|
models/ProxyOutpostConfig.ts
|
||||||
|
models/ProxyProvider.ts
|
||||||
|
models/ReputationPolicy.ts
|
||||||
|
models/SAMLMetadata.ts
|
||||||
|
models/SAMLPropertyMapping.ts
|
||||||
|
models/SAMLProvider.ts
|
||||||
|
models/SAMLSource.ts
|
||||||
|
models/ScopeMapping.ts
|
||||||
|
models/ServiceConnection.ts
|
||||||
|
models/ServiceConnectionState.ts
|
||||||
|
models/Source.ts
|
||||||
|
models/Stage.ts
|
||||||
|
models/Task.ts
|
||||||
|
models/Token.ts
|
||||||
|
models/TokenView.ts
|
||||||
|
models/TypeCreate.ts
|
||||||
|
models/User.ts
|
||||||
|
models/UserDeleteStage.ts
|
||||||
|
models/UserLoginStage.ts
|
||||||
|
models/UserLogoutStage.ts
|
||||||
|
models/UserReputation.ts
|
||||||
|
models/UserWriteStage.ts
|
||||||
|
models/Version.ts
|
||||||
|
models/index.ts
|
||||||
|
runtime.ts
|
|
@ -0,0 +1 @@
|
||||||
|
5.1.0-SNAPSHOT
|
|
@ -1,32 +0,0 @@
|
||||||
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
|
|
||||||
import { Provider } from "./Providers";
|
|
||||||
|
|
||||||
export class Application {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
slug: string;
|
|
||||||
provider?: Provider;
|
|
||||||
|
|
||||||
launch_url: string;
|
|
||||||
meta_launch_url: string;
|
|
||||||
meta_icon: string;
|
|
||||||
meta_description: string;
|
|
||||||
meta_publisher: string;
|
|
||||||
policies: string[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(slug: string): Promise<Application> {
|
|
||||||
return DefaultClient.fetch<Application>(["core", "applications", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Application>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Application>>(["core", "applications"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/applications/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
|
|
||||||
|
|
||||||
export class CertificateKeyPair {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
fingerprint: string;
|
|
||||||
cert_expiry: number;
|
|
||||||
cert_subject: string;
|
|
||||||
private_key_available: boolean;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(slug: string): Promise<CertificateKeyPair> {
|
|
||||||
return DefaultClient.fetch<CertificateKeyPair>(["crypto", "certificatekeypairs", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<CertificateKeyPair>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<CertificateKeyPair>>(["crypto", "certificatekeypairs"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/crypto/certificates/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,3 @@
|
||||||
import { gettext } from "django";
|
|
||||||
import { showMessage } from "../elements/messages/MessageContainer";
|
|
||||||
import { getCookie } from "../utils";
|
|
||||||
import { NotFoundError, RequestError } from "./Error";
|
|
||||||
|
|
||||||
export const VERSION = "v2beta";
|
|
||||||
|
|
||||||
export interface QueryArguments {
|
export interface QueryArguments {
|
||||||
page?: number;
|
page?: number;
|
||||||
page_size?: number;
|
page_size?: number;
|
||||||
|
@ -13,104 +6,27 @@ export interface QueryArguments {
|
||||||
|
|
||||||
export interface BaseInheritanceModel {
|
export interface BaseInheritanceModel {
|
||||||
|
|
||||||
object_type: string;
|
objectType: string;
|
||||||
|
|
||||||
verbose_name: string;
|
verboseName: string;
|
||||||
verbose_name_plural: string;
|
verboseNamePlural: string;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Client {
|
export interface AKPagination {
|
||||||
makeUrl(url: string[], query?: QueryArguments): string {
|
|
||||||
let builtUrl = `/api/${VERSION}/${url.join("/")}/`;
|
|
||||||
if (query) {
|
|
||||||
const queryString = Object.keys(query)
|
|
||||||
.filter((k) => query[k] !== null)
|
|
||||||
// we default to a string in query[k] as we've filtered out the null above
|
|
||||||
// this is just for type-hinting
|
|
||||||
.map((k) => encodeURIComponent(k) + "=" + encodeURIComponent(query[k] || ""))
|
|
||||||
.join("&");
|
|
||||||
builtUrl += `?${queryString}`;
|
|
||||||
}
|
|
||||||
return builtUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch<T>(url: string[], query?: QueryArguments): Promise<T> {
|
|
||||||
const finalUrl = this.makeUrl(url, query);
|
|
||||||
return fetch(finalUrl)
|
|
||||||
.then((r) => {
|
|
||||||
if (r.status > 300) {
|
|
||||||
switch (r.status) {
|
|
||||||
case 404:
|
|
||||||
throw new NotFoundError(`URL ${finalUrl} not found`);
|
|
||||||
default:
|
|
||||||
throw new RequestError(r.statusText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
showMessage({
|
|
||||||
level_tag: "error",
|
|
||||||
message: gettext(`Unexpected error while fetching: ${e.toString()}`),
|
|
||||||
});
|
|
||||||
return e;
|
|
||||||
})
|
|
||||||
.then((r) => r.json())
|
|
||||||
.then((r) => <T>r);
|
|
||||||
}
|
|
||||||
|
|
||||||
private writeRequest<T>(url: string[], body: T, method: string, query?: QueryArguments): Promise<T> {
|
|
||||||
const finalUrl = this.makeUrl(url, query);
|
|
||||||
const csrftoken = getCookie("authentik_csrf");
|
|
||||||
const request = new Request(finalUrl, {
|
|
||||||
headers: {
|
|
||||||
"Accept": "application/json",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-CSRFToken": csrftoken,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return fetch(request, {
|
|
||||||
method: method,
|
|
||||||
mode: "same-origin",
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
})
|
|
||||||
.then((r) => {
|
|
||||||
if (r.status > 300) {
|
|
||||||
switch (r.status) {
|
|
||||||
case 404:
|
|
||||||
throw new NotFoundError(`URL ${finalUrl} not found`);
|
|
||||||
default:
|
|
||||||
throw new RequestError(r.statusText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
})
|
|
||||||
.then((r) => r.json())
|
|
||||||
.then((r) => <T>r);
|
|
||||||
}
|
|
||||||
|
|
||||||
update<T>(url: string[], body: T, query?: QueryArguments): Promise<T> {
|
|
||||||
return this.writeRequest(url, body, "PATCH", query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DefaultClient = new Client();
|
|
||||||
|
|
||||||
export interface PBPagination {
|
|
||||||
next?: number;
|
next?: number;
|
||||||
previous?: number;
|
previous?: number;
|
||||||
|
|
||||||
count: number;
|
count: number;
|
||||||
current: number;
|
current: number;
|
||||||
total_pages: number;
|
totalPages: number;
|
||||||
|
|
||||||
start_index: number;
|
startIndex: number;
|
||||||
end_index: number;
|
endIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AKResponse<T> {
|
export interface AKResponse<T> {
|
||||||
pagination: PBPagination;
|
pagination: AKPagination;
|
||||||
|
|
||||||
results: Array<T>;
|
results: Array<T>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,22 @@
|
||||||
import { DefaultClient } from "./Client";
|
|
||||||
import * as Sentry from "@sentry/browser";
|
import * as Sentry from "@sentry/browser";
|
||||||
import { Integrations } from "@sentry/tracing";
|
import { Integrations } from "@sentry/tracing";
|
||||||
import { VERSION } from "../constants";
|
import { VERSION } from "../constants";
|
||||||
import { SentryIgnoredError } from "../common/errors";
|
import { SentryIgnoredError } from "../common/errors";
|
||||||
|
import { Configuration } from "./runtime";
|
||||||
|
import { RootApi } from "./apis";
|
||||||
|
import { Config } from ".";
|
||||||
|
import { getCookie } from "../utils";
|
||||||
|
|
||||||
export class Config {
|
export const DEFAULT_CONFIG = new Configuration({
|
||||||
branding_logo: string;
|
basePath: "/api/v2beta",
|
||||||
branding_title: string;
|
headers: {
|
||||||
|
"X-CSRFToken": getCookie("authentik_csrf"),
|
||||||
error_reporting_enabled: boolean;
|
|
||||||
error_reporting_environment: string;
|
|
||||||
error_reporting_send_pii: boolean;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
static get(): Promise<Config> {
|
export function configureSentry(): Promise<Config> {
|
||||||
return DefaultClient.fetch<Config>(["root", "config"]).then((config) => {
|
return new RootApi(DEFAULT_CONFIG).rootConfigList().then((config) => {
|
||||||
if (config.error_reporting_enabled) {
|
if (config.errorReportingEnabled) {
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
|
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
|
||||||
release: `authentik@${VERSION}`,
|
release: `authentik@${VERSION}`,
|
||||||
|
@ -26,7 +24,7 @@ export class Config {
|
||||||
new Integrations.BrowserTracing(),
|
new Integrations.BrowserTracing(),
|
||||||
],
|
],
|
||||||
tracesSampleRate: 0.6,
|
tracesSampleRate: 0.6,
|
||||||
environment: config.error_reporting_environment,
|
environment: config.errorReportingEnvironment,
|
||||||
beforeSend(event: Sentry.Event, hint: Sentry.EventHint) {
|
beforeSend(event: Sentry.Event, hint: Sentry.EventHint) {
|
||||||
if (hint.originalException instanceof SentryIgnoredError) {
|
if (hint.originalException instanceof SentryIgnoredError) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -38,5 +36,4 @@ export class Config {
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
|
|
||||||
import { Event } from "./Events";
|
|
||||||
|
|
||||||
export class Notification {
|
|
||||||
pk: string;
|
|
||||||
severity: string;
|
|
||||||
body: string;
|
|
||||||
created: string;
|
|
||||||
event?: Event;
|
|
||||||
seen: boolean;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Notification> {
|
|
||||||
return DefaultClient.fetch<Notification>(["events", "notifications", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Notification>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Notification>>(["events", "notifications"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static markSeen(pk: string): Promise<{seen: boolean}> {
|
|
||||||
return DefaultClient.update(["events", "notifications", pk], {
|
|
||||||
"seen": true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
|
|
||||||
import { Group } from "./Groups";
|
|
||||||
|
|
||||||
export class Rule {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
transports: string[];
|
|
||||||
severity: string;
|
|
||||||
group?: Group;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Rule> {
|
|
||||||
return DefaultClient.fetch<Rule>(["events", "rules", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Rule>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Rule>>(["events", "rules"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/events/rules/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
|
|
||||||
|
|
||||||
export class Transport {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
mode: string;
|
|
||||||
mode_verbose: string;
|
|
||||||
webhook_url: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Transport> {
|
|
||||||
return DefaultClient.fetch<Transport>(["events", "transports", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Transport>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Transport>>(["events", "transports"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/events/transports/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
|
import { Event } from "./models";
|
||||||
|
|
||||||
export interface EventUser {
|
export interface EventUser {
|
||||||
pk: number;
|
pk: number;
|
||||||
|
@ -11,37 +11,7 @@ export interface EventContext {
|
||||||
[key: string]: EventContext | string | number | string[];
|
[key: string]: EventContext | string | number | string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Event {
|
export interface EventWithContext extends Event {
|
||||||
pk: string;
|
|
||||||
user: EventUser;
|
user: EventUser;
|
||||||
action: string;
|
|
||||||
app: string;
|
|
||||||
context: EventContext;
|
context: EventContext;
|
||||||
client_ip: string;
|
|
||||||
created: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Event> {
|
|
||||||
return DefaultClient.fetch<Event>(["events", "events", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Event>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Event>>(["events", "events"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// events/events/top_per_user/?filter_action=authorize_application
|
|
||||||
static topForUser(action: string): Promise<TopNEvent[]> {
|
|
||||||
return DefaultClient.fetch<TopNEvent[]>(["events", "events", "top_per_user"], {
|
|
||||||
"filter_action": action,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TopNEvent {
|
|
||||||
application: { [key: string]: string};
|
|
||||||
counted_events: number;
|
|
||||||
unique_users: number;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,4 @@
|
||||||
import { DefaultClient, AKResponse, QueryArguments, BaseInheritanceModel } from "./Client";
|
import { ChallengeTypeEnum } from "./models";
|
||||||
import { TypeCreate } from "./Providers";
|
|
||||||
|
|
||||||
export enum ChallengeTypes {
|
|
||||||
native = "native",
|
|
||||||
response = "response",
|
|
||||||
shell = "shell",
|
|
||||||
redirect = "redirect",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Error {
|
export interface Error {
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -18,11 +10,12 @@ export interface ErrorDict {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Challenge {
|
export interface Challenge {
|
||||||
type: ChallengeTypes;
|
type: ChallengeTypeEnum;
|
||||||
component?: string;
|
component?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
response_errors?: ErrorDict;
|
response_errors?: ErrorDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WithUserInfoChallenge extends Challenge {
|
export interface WithUserInfoChallenge extends Challenge {
|
||||||
pending_user: string;
|
pending_user: string;
|
||||||
pending_user_avatar: string;
|
pending_user_avatar: string;
|
||||||
|
@ -31,6 +24,7 @@ export interface WithUserInfoChallenge extends Challenge {
|
||||||
export interface ShellChallenge extends Challenge {
|
export interface ShellChallenge extends Challenge {
|
||||||
body: string;
|
body: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RedirectChallenge extends Challenge {
|
export interface RedirectChallenge extends Challenge {
|
||||||
to: string;
|
to: string;
|
||||||
}
|
}
|
||||||
|
@ -44,104 +38,3 @@ export enum FlowDesignation {
|
||||||
Recovery = "recovery",
|
Recovery = "recovery",
|
||||||
StageConfiguration = "stage_configuration",
|
StageConfiguration = "stage_configuration",
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Flow {
|
|
||||||
pk: string;
|
|
||||||
policybindingmodel_ptr_id: string;
|
|
||||||
name: string;
|
|
||||||
slug: string;
|
|
||||||
title: string;
|
|
||||||
designation: FlowDesignation;
|
|
||||||
background: string;
|
|
||||||
stages: string[];
|
|
||||||
policies: string[];
|
|
||||||
cache_count: number;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(slug: string): Promise<Flow> {
|
|
||||||
return DefaultClient.fetch<Flow>(["flows", "instances", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static diagram(slug: string): Promise<{ diagram: string }> {
|
|
||||||
return DefaultClient.fetch<{ diagram: string }>(["flows", "instances", slug, "diagram"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Flow>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Flow>>(["flows", "instances"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cached(): Promise<number> {
|
|
||||||
return DefaultClient.fetch<{ count: number }>(["flows", "instances", "cached"]).then(r => {
|
|
||||||
return r.count;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static executor(slug: string): Promise<Challenge> {
|
|
||||||
return DefaultClient.fetch(["flows", "executor", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/flows/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Stage implements BaseInheritanceModel {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
object_type: string;
|
|
||||||
verbose_name: string;
|
|
||||||
verbose_name_plural: string;
|
|
||||||
flow_set: Flow[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(slug: string): Promise<Stage> {
|
|
||||||
return DefaultClient.fetch<Stage>(["stages", "all", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Stage>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Stage>>(["stages", "all"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypes(): Promise<TypeCreate[]> {
|
|
||||||
return DefaultClient.fetch<TypeCreate[]>(["stages", "all", "types"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/stages/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FlowStageBinding {
|
|
||||||
|
|
||||||
pk: string;
|
|
||||||
policybindingmodel_ptr_id: string;
|
|
||||||
target: string;
|
|
||||||
stage: string;
|
|
||||||
stage_obj: Stage;
|
|
||||||
evaluate_on_plan: boolean;
|
|
||||||
re_evaluate_policies: boolean;
|
|
||||||
order: number;
|
|
||||||
policies: string[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(slug: string): Promise<FlowStageBinding> {
|
|
||||||
return DefaultClient.fetch<FlowStageBinding>(["flows", "bindings", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<FlowStageBinding>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<FlowStageBinding>>(["flows", "bindings"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/stages/bindings/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
|
|
||||||
import { EventContext } from "./Events";
|
|
||||||
|
|
||||||
export class Group {
|
|
||||||
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
is_superuser: boolean;
|
|
||||||
attributes: EventContext;
|
|
||||||
parent?: Group;
|
|
||||||
users: number[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Group> {
|
|
||||||
return DefaultClient.fetch<Group>(["core", "groups", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Group>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Group>>(["core", "groups"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/groups/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
|
|
||||||
import { EventContext } from "./Events";
|
|
||||||
import { User } from "./Users";
|
|
||||||
|
|
||||||
export class Invitation {
|
|
||||||
|
|
||||||
pk: string;
|
|
||||||
expires: number;
|
|
||||||
fixed_date: EventContext;
|
|
||||||
created_by: User;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Invitation> {
|
|
||||||
return DefaultClient.fetch<Invitation>(["stages", "invitation", "invitations", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Invitation>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Invitation>>(["stages", "invitation", "invitations"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/stages/invitations/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
|
|
||||||
import { Provider, TypeCreate } from "./Providers";
|
|
||||||
|
|
||||||
export interface OutpostHealth {
|
|
||||||
last_seen: number;
|
|
||||||
version: string;
|
|
||||||
version_should: string;
|
|
||||||
version_outdated: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Outpost {
|
|
||||||
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
providers: number[];
|
|
||||||
providers_obj: Provider[];
|
|
||||||
service_connection?: string;
|
|
||||||
_config: QueryArguments;
|
|
||||||
token_identifier: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Outpost> {
|
|
||||||
return DefaultClient.fetch<Outpost>(["outposts", "outposts", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Outpost>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Outpost>>(["outposts", "outposts"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static health(pk: string): Promise<OutpostHealth[]> {
|
|
||||||
return DefaultClient.fetch<OutpostHealth[]>(["outposts", "outposts", pk, "health"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/outposts/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OutpostServiceConnectionState {
|
|
||||||
version: string;
|
|
||||||
healthy: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OutpostServiceConnection {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
local: boolean;
|
|
||||||
object_type: string;
|
|
||||||
verbose_name: string;
|
|
||||||
verbose_name_plural: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<OutpostServiceConnection> {
|
|
||||||
return DefaultClient.fetch<OutpostServiceConnection>(["outposts", "service_connections", "all", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<OutpostServiceConnection>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<OutpostServiceConnection>>(["outposts", "service_connections", "all"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static state(pk: string): Promise<OutpostServiceConnectionState> {
|
|
||||||
return DefaultClient.fetch<OutpostServiceConnectionState>(["outposts", "service_connections", "all", pk, "state"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypes(): Promise<TypeCreate[]> {
|
|
||||||
return DefaultClient.fetch<TypeCreate[]>(["outposts", "service_connections", "all", "types"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/outpost_service_connections/${rest}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
import { DefaultClient, BaseInheritanceModel, AKResponse, QueryArguments } from "./Client";
|
|
||||||
import { TypeCreate } from "./Providers";
|
|
||||||
|
|
||||||
export class Policy implements BaseInheritanceModel {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
execution_logging: boolean;
|
|
||||||
object_type: string;
|
|
||||||
verbose_name: string;
|
|
||||||
verbose_name_plural: string;
|
|
||||||
bound_to: number;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Policy> {
|
|
||||||
return DefaultClient.fetch<Policy>(["policies", "all", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Policy>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Policy>>(["policies", "all"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cached(): Promise<number> {
|
|
||||||
return DefaultClient.fetch<{ count: number }>(["policies", "all", "cached"]).then(r => {
|
|
||||||
return r.count;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypes(): Promise<TypeCreate[]> {
|
|
||||||
return DefaultClient.fetch<TypeCreate[]>(["policies", "all", "types"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/policies/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
|
|
||||||
import { Group } from "./Groups";
|
|
||||||
import { Policy } from "./Policies";
|
|
||||||
import { User } from "./Users";
|
|
||||||
|
|
||||||
export class PolicyBinding {
|
|
||||||
pk: string;
|
|
||||||
policy?: Policy;
|
|
||||||
group?: Group;
|
|
||||||
user?: User;
|
|
||||||
target: string;
|
|
||||||
enabled: boolean;
|
|
||||||
order: number;
|
|
||||||
timeout: number;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<PolicyBinding> {
|
|
||||||
return DefaultClient.fetch<PolicyBinding>(["policies", "bindings", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<PolicyBinding>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<PolicyBinding>>(["policies", "bindings"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/policies/bindings/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
|
|
||||||
import { Stage } from "./Flows";
|
|
||||||
|
|
||||||
export class Prompt {
|
|
||||||
|
|
||||||
pk: string;
|
|
||||||
field_key: string;
|
|
||||||
label: string;
|
|
||||||
type: string;
|
|
||||||
required: boolean;
|
|
||||||
placeholder: string;
|
|
||||||
order: number;
|
|
||||||
promptstage_set: Stage[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<Prompt> {
|
|
||||||
return DefaultClient.fetch<Prompt>(["stages", "prompt", "prompts", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Prompt>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Prompt>>(["stages", "prompt", "prompts"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/stages_prompts/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
|
|
||||||
import { TypeCreate } from "./Providers";
|
|
||||||
|
|
||||||
export class PropertyMapping {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
expression: string;
|
|
||||||
|
|
||||||
verbose_name: string;
|
|
||||||
verbose_name_plural: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<PropertyMapping> {
|
|
||||||
return DefaultClient.fetch<PropertyMapping>(["propertymappings", "all", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<PropertyMapping>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<PropertyMapping>>(["propertymappings", "all"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypes(): Promise<TypeCreate[]> {
|
|
||||||
return DefaultClient.fetch<TypeCreate[]>(["propertymappings", "all", "types"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/property-mappings/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
import { BaseInheritanceModel, DefaultClient, AKResponse, QueryArguments } from "./Client";
|
|
||||||
|
|
||||||
export interface TypeCreate {
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
link: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Provider implements BaseInheritanceModel {
|
|
||||||
pk: number;
|
|
||||||
name: string;
|
|
||||||
authorization_flow: string;
|
|
||||||
object_type: string;
|
|
||||||
|
|
||||||
assigned_application_slug?: string;
|
|
||||||
assigned_application_name?: string;
|
|
||||||
|
|
||||||
verbose_name: string;
|
|
||||||
verbose_name_plural: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(id: number): Promise<Provider> {
|
|
||||||
return DefaultClient.fetch<Provider>(["providers", "all", id.toString()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Provider>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Provider>>(["providers", "all"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypes(): Promise<TypeCreate[]> {
|
|
||||||
return DefaultClient.fetch<TypeCreate[]>(["providers", "all", "types"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/providers/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
import { BaseInheritanceModel, DefaultClient, AKResponse, QueryArguments } from "./Client";
|
|
||||||
import { TypeCreate } from "./Providers";
|
|
||||||
|
|
||||||
export class Source implements BaseInheritanceModel {
|
|
||||||
pk: string;
|
|
||||||
name: string;
|
|
||||||
slug: string;
|
|
||||||
enabled: boolean;
|
|
||||||
authentication_flow: string;
|
|
||||||
enrollment_flow: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
object_type: string;
|
|
||||||
verbose_name: string;
|
|
||||||
verbose_name_plural: string;
|
|
||||||
|
|
||||||
static get(slug: string): Promise<Source> {
|
|
||||||
return DefaultClient.fetch<Source>(["sources", "all", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Source>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Source>>(["sources", "all"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypes(): Promise<TypeCreate[]> {
|
|
||||||
return DefaultClient.fetch<TypeCreate[]>(["sources", "all", "types"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/sources/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { DefaultClient, QueryArguments } from "./Client";
|
|
||||||
|
|
||||||
export enum TaskStatus {
|
|
||||||
SUCCESSFUL = 1,
|
|
||||||
WARNING = 2,
|
|
||||||
ERROR = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SystemTask {
|
|
||||||
|
|
||||||
task_name: string;
|
|
||||||
task_description: string;
|
|
||||||
task_finish_timestamp: number;
|
|
||||||
status: TaskStatus;
|
|
||||||
messages: string[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(task_name: string): Promise<SystemTask> {
|
|
||||||
return DefaultClient.fetch<SystemTask>(["admin", "system_tasks", task_name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<SystemTask[]> {
|
|
||||||
return DefaultClient.fetch<SystemTask[]>(["admin", "system_tasks"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static retry(task_name: string): string {
|
|
||||||
return DefaultClient.makeUrl(["admin", "system_tasks", task_name, "retry"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
import { AKResponse, DefaultClient, QueryArguments } from "./Client";
|
|
||||||
import { User } from "./Users";
|
|
||||||
|
|
||||||
export enum TokenIntent {
|
|
||||||
INTENT_VERIFICATION = "verification",
|
|
||||||
INTENT_API = "api",
|
|
||||||
INTENT_RECOVERY = "recovery",
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Token {
|
|
||||||
|
|
||||||
pk: string;
|
|
||||||
identifier: string;
|
|
||||||
intent: TokenIntent;
|
|
||||||
user: User;
|
|
||||||
description: string;
|
|
||||||
|
|
||||||
expires: number;
|
|
||||||
expiring: boolean;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<User> {
|
|
||||||
return DefaultClient.fetch<User>(["core", "tokens", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<Token>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<Token>>(["core", "tokens"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/tokens/${rest}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static userUrl(rest: string): string {
|
|
||||||
return `/-/user/tokens/${rest}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getKey(identifier: string): Promise<string> {
|
|
||||||
return DefaultClient.fetch<{ key: string }>(["core", "tokens", identifier, "view_key"]).then(
|
|
||||||
(r) => r.key
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,45 +1,11 @@
|
||||||
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
|
import { CoreApi } from "./apis";
|
||||||
|
import { DEFAULT_CONFIG } from "./Config";
|
||||||
|
import { User } from "./models";
|
||||||
|
|
||||||
let _globalMePromise: Promise<User>;
|
let _globalMePromise: Promise<User>;
|
||||||
|
export function me(): Promise<User> {
|
||||||
export class User {
|
|
||||||
pk: number;
|
|
||||||
username: string;
|
|
||||||
name: string;
|
|
||||||
is_superuser: boolean;
|
|
||||||
email: boolean;
|
|
||||||
avatar: string;
|
|
||||||
is_active: boolean;
|
|
||||||
last_login: number;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(pk: string): Promise<User> {
|
|
||||||
return DefaultClient.fetch<User>(["core", "users", pk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static list(filter?: QueryArguments): Promise<AKResponse<User>> {
|
|
||||||
return DefaultClient.fetch<AKResponse<User>>(["core", "users"], filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adminUrl(rest: string): string {
|
|
||||||
return `/administration/users/${rest}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static me(): Promise<User> {
|
|
||||||
if (!_globalMePromise) {
|
if (!_globalMePromise) {
|
||||||
_globalMePromise = DefaultClient.fetch<User>(["core", "users", "me"]);
|
_globalMePromise = new CoreApi(DEFAULT_CONFIG).coreUsersMe({});
|
||||||
}
|
}
|
||||||
return _globalMePromise;
|
return _globalMePromise;
|
||||||
}
|
|
||||||
|
|
||||||
static count(): Promise<number> {
|
|
||||||
return DefaultClient.fetch<AKResponse<User>>(["core", "users"], {
|
|
||||||
"page_size": 1
|
|
||||||
}).then(r => {
|
|
||||||
return r.pagination.count;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import { DefaultClient } from "./Client";
|
|
||||||
|
|
||||||
export class Version {
|
|
||||||
|
|
||||||
version_current: string;
|
|
||||||
version_latest: string;
|
|
||||||
outdated: boolean;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(): Promise<Version> {
|
|
||||||
return DefaultClient.fetch<Version>(["admin", "version"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
export class AdminURLManager {
|
||||||
|
|
||||||
|
static applications(rest: string): string {
|
||||||
|
return `/administration/applications/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cryptoCertificates(rest: string): string {
|
||||||
|
return `/administration/crypto/certificates/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static policies(rest: string): string {
|
||||||
|
return `/administration/policies/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static policyBindings(rest: string): string {
|
||||||
|
return `/administration/policies/bindings/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static providers(rest: string): string {
|
||||||
|
return `/administration/providers/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static propertyMappings(rest: string): string {
|
||||||
|
return `/administration/property-mappings/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static outposts(rest: string): string {
|
||||||
|
return `/administration/outposts/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static outpostServiceConnections(rest: string): string {
|
||||||
|
return `/administration/outpost_service_connections/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static flows(rest: string): string {
|
||||||
|
return `/administration/flows/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static stages(rest: string): string {
|
||||||
|
return `/administration/stages/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static stagePrompts(rest: string): string {
|
||||||
|
return `/administration/stages_prompts/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static stageInvitations(rest: string): string {
|
||||||
|
return `/administration/stages/invitations/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static stageBindings(rest: string): string {
|
||||||
|
return `/administration/stages/bindings/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sources(rest: string): string {
|
||||||
|
return `/administration/sources/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tokens(rest: string): string {
|
||||||
|
return `/administration/tokens/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static eventRules(rest: string): string {
|
||||||
|
return `/administration/events/rules/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static eventTransports(rest: string): string {
|
||||||
|
return `/administration/events/transports/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static users(rest: string): string {
|
||||||
|
return `/administration/users/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static groups(rest: string): string {
|
||||||
|
return `/administration/groups/${rest}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UserURLManager {
|
||||||
|
|
||||||
|
static tokens(rest: string): string {
|
||||||
|
return `/-/user/tokens/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AppURLManager {
|
||||||
|
|
||||||
|
static sourceSAML(slug: string, rest: string): string {
|
||||||
|
return `/source/saml/${slug}/${rest}`;
|
||||||
|
}
|
||||||
|
static providerSAML(rest: string): string {
|
||||||
|
return `/application/saml/${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
import { DefaultClient } from "../Client";
|
|
||||||
import { Provider } from "../Providers";
|
|
||||||
|
|
||||||
export interface OAuth2SetupURLs {
|
|
||||||
|
|
||||||
issuer?: string;
|
|
||||||
authorize: string;
|
|
||||||
token: string;
|
|
||||||
user_info: string;
|
|
||||||
provider_info?: string;
|
|
||||||
logout?: string;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OAuth2Provider extends Provider {
|
|
||||||
client_type: string
|
|
||||||
client_id: string;
|
|
||||||
client_secret: string;
|
|
||||||
token_validity: string;
|
|
||||||
include_claims_in_id_token: boolean;
|
|
||||||
jwt_alg: string;
|
|
||||||
rsa_key: string;
|
|
||||||
redirect_uris: string;
|
|
||||||
sub_mode: string;
|
|
||||||
issuer_mode: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(id: number): Promise<OAuth2Provider> {
|
|
||||||
return DefaultClient.fetch<OAuth2Provider>(["providers", "oauth2", id.toString()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getLaunchURls(id: number): Promise<OAuth2SetupURLs> {
|
|
||||||
return DefaultClient.fetch(["providers", "oauth2", id.toString(), "setup_urls"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static appUrl(rest: string): string {
|
|
||||||
return `/application/oauth2/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { DefaultClient } from "../Client";
|
|
||||||
import { Provider } from "../Providers";
|
|
||||||
|
|
||||||
export class ProxyProvider extends Provider {
|
|
||||||
internal_host: string;
|
|
||||||
external_host: string;
|
|
||||||
internal_host_ssl_validation: boolean
|
|
||||||
certificate?: string;
|
|
||||||
skip_path_regex: string;
|
|
||||||
basic_auth_enabled: boolean;
|
|
||||||
basic_auth_password_attribute: string;
|
|
||||||
basic_auth_user_attribute: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(id: number): Promise<ProxyProvider> {
|
|
||||||
return DefaultClient.fetch<ProxyProvider>(["providers", "proxy", id.toString()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getMetadata(id: number): Promise<{ metadata: string }> {
|
|
||||||
return DefaultClient.fetch(["providers", "proxy", id.toString(), "metadata"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static appUrl(rest: string): string {
|
|
||||||
return `/application/proxy/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { DefaultClient } from "../Client";
|
|
||||||
import { Provider } from "../Providers";
|
|
||||||
|
|
||||||
export class SAMLProvider extends Provider {
|
|
||||||
acs_url: string;
|
|
||||||
audience: string;
|
|
||||||
issuer: string;
|
|
||||||
assertion_valid_not_before: string;
|
|
||||||
assertion_valid_not_on_or_after: string;
|
|
||||||
session_valid_not_on_or_after: string;
|
|
||||||
name_id_mapping?: string;
|
|
||||||
digest_algorithm: string;
|
|
||||||
signature_algorithm: string;
|
|
||||||
signing_kp?: string;
|
|
||||||
verification_kp?: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(id: number): Promise<SAMLProvider> {
|
|
||||||
return DefaultClient.fetch<SAMLProvider>(["providers", "saml", id.toString()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getMetadata(id: number): Promise<{ metadata: string }> {
|
|
||||||
return DefaultClient.fetch(["providers", "saml", id.toString(), "metadata"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static appUrl(rest: string): string {
|
|
||||||
return `/application/saml/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
import { DefaultClient } from "../Client";
|
|
||||||
import { Source } from "../Sources";
|
|
||||||
|
|
||||||
export class LDAPSource extends Source {
|
|
||||||
server_uri: string;
|
|
||||||
bind_cn: string;
|
|
||||||
start_tls: boolean
|
|
||||||
base_dn: string;
|
|
||||||
additional_user_dn: string;
|
|
||||||
additional_group_dn: string;
|
|
||||||
user_object_filter: string;
|
|
||||||
group_object_filter: string;
|
|
||||||
group_membership_field: string;
|
|
||||||
object_uniqueness_field: string;
|
|
||||||
sync_users: boolean;
|
|
||||||
sync_users_password: boolean;
|
|
||||||
sync_groups: boolean;
|
|
||||||
sync_parent_group?: string;
|
|
||||||
property_mappings: string[];
|
|
||||||
property_mappings_group: string[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(slug: string): Promise<LDAPSource> {
|
|
||||||
return DefaultClient.fetch<LDAPSource>(["sources", "ldap", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static syncStatus(slug: string): Promise<{ last_sync?: number }> {
|
|
||||||
return DefaultClient.fetch(["sources", "ldap", slug, "sync_status"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
import { DefaultClient } from "../Client";
|
|
||||||
import { Source } from "../Sources";
|
|
||||||
|
|
||||||
export class OAuthSource extends Source {
|
|
||||||
provider_type: string;
|
|
||||||
request_token_url: string;
|
|
||||||
authorization_url: string;
|
|
||||||
access_token_url: string;
|
|
||||||
profile_url: string;
|
|
||||||
consumer_key: string;
|
|
||||||
callback_url: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(slug: string): Promise<OAuthSource> {
|
|
||||||
return DefaultClient.fetch<OAuthSource>(["sources", "oauth", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
import { DefaultClient } from "../Client";
|
|
||||||
import { Source } from "../Sources";
|
|
||||||
|
|
||||||
export class SAMLSource extends Source {
|
|
||||||
issuer: string;
|
|
||||||
sso_url: string;
|
|
||||||
slo_url: string;
|
|
||||||
allow_idp_initiated: boolean;
|
|
||||||
name_id_policy: string;
|
|
||||||
binding_type: string
|
|
||||||
signing_kp?: string;
|
|
||||||
digest_algorithm: string;
|
|
||||||
signature_algorithm: string;
|
|
||||||
temporary_user_delete_after: string;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get(slug: string): Promise<SAMLSource> {
|
|
||||||
return DefaultClient.fetch<SAMLSource>(["sources", "saml", slug]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getMetadata(slug: string): Promise<{ metadata: string }> {
|
|
||||||
return DefaultClient.fetch(["sources", "saml", slug, "metadata"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static appUrl(slug: string, rest: string): string {
|
|
||||||
return `/source/saml/${slug}/${rest}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,6 +5,12 @@ html {
|
||||||
--pf-c-nav__link--PaddingLeft: 0.5rem;
|
--pf-c-nav__link--PaddingLeft: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html > input {
|
||||||
|
position: absolute;
|
||||||
|
top: -2000px;
|
||||||
|
left: -2000px;
|
||||||
|
}
|
||||||
|
|
||||||
.pf-c-page__header {
|
.pf-c-page__header {
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +89,7 @@ select[multiple] {
|
||||||
|
|
||||||
/* ensure background on non-flow pages match */
|
/* ensure background on non-flow pages match */
|
||||||
.pf-c-background-image::before {
|
.pf-c-background-image::before {
|
||||||
background-image: url("dist/assets/images/flow_background.jpg");
|
background-image: url("/static/dist/assets/images/flow_background.jpg");
|
||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +163,7 @@ ak-message {
|
||||||
color: var(--ak-dark-foreground) !important;
|
color: var(--ak-dark-foreground) !important;
|
||||||
}
|
}
|
||||||
/* tabs, vertical */
|
/* tabs, vertical */
|
||||||
.pf-c-tabs__link {
|
.pf-c-tabs.pf-m-vertical .pf-c-tabs__link {
|
||||||
background-color: var(--ak-dark-background-light);
|
background-color: var(--ak-dark-background-light);
|
||||||
}
|
}
|
||||||
/* table, on mobile */
|
/* table, on mobile */
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue