Merge branch 'master' into docs

This commit is contained in:
Jens Langhammer 2019-12-09 16:49:05 +01:00
commit c1e98e2f0c
36 changed files with 394 additions and 1210 deletions

2
.gitignore vendored
View file

@ -63,6 +63,7 @@ coverage.xml
*.cover
.hypothesis/
.pytest_cache/
unittest.xml
# Translations
*.mo
@ -184,7 +185,6 @@ dmypy.json
[Ii]nclude
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
pip-selfcheck.json

View file

@ -64,13 +64,13 @@ migrations:
services:
- postgres:latest
- redis:latest
# prospector:
# script:
# - prospector
# stage: test
# services:
# - postgres:latest
# - redis:latest
prospector:
script:
- prospector
stage: test
services:
- postgres:latest
- redis:latest
pylint:
script:
- pylint passbook
@ -80,9 +80,7 @@ pylint:
- redis:latest
coverage:
script:
- coverage run --concurrency=multiprocessing manage.py test
- coverage combine
- coverage report
- ./scripts/coverage.sh
stage: test
services:
- postgres:latest
@ -116,18 +114,6 @@ build-passbook-static:
services:
- postgres:latest
- redis:latest
# build-passbook-gatekeeper:
# stage: build
# image:
# name: gcr.io/kaniko-project/executor:debug
# entrypoint: [""]
# before_script:
# - echo "{\"auths\":{\"docker.beryju.org\":{\"auth\":\"$DOCKER_AUTH\"}}}" > /kaniko/.docker/config.json
# script:
# - /kaniko/executor --context $CI_PROJECT_DIR/gatekeeper --dockerfile $CI_PROJECT_DIR/gatekeeper/Dockerfile --destination docker.beryju.org/passbook/gatekeeper:latest --destination docker.beryju.org/passbook/gatekeeper:0.7.4-beta
# only:
# - tags
# - /^version/.*$/
package-helm:
image: debian:stretch-slim

View file

@ -12,7 +12,6 @@ django-cors-middleware = "*"
django-dbbackup = "*"
django-filter = "*"
django-guardian = "*"
django-ipware = "*"
django-model-utils = "*"
django-oauth-toolkit = "*"
django-oidc-provider = "*"

385
Pipfile.lock generated
View file

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "716683e8e7794821723dcb671c58b3af32c061c52410148e5b5b6c8fc503c935"
"sha256": "865b57ef5ef326de114d39d8505f60f19b5f7e42a50d988ea3fc9dfc9b9371ec"
},
"pipfile-spec": 6,
"requires": {
@ -46,18 +46,18 @@
},
"boto3": {
"hashes": [
"sha256:228cea7e2b3be79e5393719641854d4000826d7a7baebede903a616b505b8e17",
"sha256:ad6d50dd5726a12c6442c23aabec0c7e09ef610834d9fbda010bade6888d7677"
"sha256:d280f2bf7dc373e8aeab296f81aadefabf8780ff8c8ad27cdc36f8f112ca95ed",
"sha256:edbf4636e700c46e49f555ac87ab48b8c385fde604528db15fc5189d5a73dc72"
],
"index": "pypi",
"version": "==1.10.13"
"version": "==1.10.33"
},
"botocore": {
"hashes": [
"sha256:33ee13a42ee1cc2391a3cd3ce12c84026db20cc76a5700d94fbe07a136d0c354",
"sha256:d1c6f01486566521b59fd5d4f6ba0adf526ed0d1807a0c0ba6604e982d014f3d"
"sha256:4861785b52b0b3f97da91613c31f8e501f12517c9c79482b44efbdb56b69aefc",
"sha256:9cc87d7906693c9c8fe862c574a1bebbe22a0475d6991e9b7251bc93cb1954d9"
],
"version": "==1.13.13"
"version": "==1.13.33"
},
"celery": {
"hashes": [
@ -69,10 +69,10 @@
},
"certifi": {
"hashes": [
"sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50",
"sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef"
"sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
"sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
],
"version": "==2019.9.11"
"version": "==2019.11.28"
},
"cffi": {
"hashes": [
@ -169,11 +169,11 @@
},
"django": {
"hashes": [
"sha256:16040e1288c6c9f68c6da2fe75ebde83c0a158f6f5d54f4c5177b0c1478c5b86",
"sha256:89c2007ca4fa5b351a51a279eccff298520783b713bf28efb89dfb81c80ea49b"
"sha256:a4ad4f6f9c6a4b7af7e2deec8d0cbff28501852e5010d6c2dc695d3d1fae7ca0",
"sha256:fa98ec9cc9bf5d72a08ebf3654a9452e761fbb8566e3f80de199cbc15477e891"
],
"index": "pypi",
"version": "==2.2.7"
"version": "==2.2.8"
},
"django-cors-middleware": {
"hashes": [
@ -206,13 +206,6 @@
"index": "pypi",
"version": "==2.1.0"
},
"django-ipware": {
"hashes": [
"sha256:a7c7a8fd019dbdc9c357e6e582f65034e897572fc79a7e467674efa8aef9d00b"
],
"index": "pypi",
"version": "==2.1.0"
},
"django-model-utils": {
"hashes": [
"sha256:3f130a262e45d73e0950d2be76af4bf4ee86804dd60e5f90afc5cd948fcfe760",
@ -237,11 +230,11 @@
},
"django-otp": {
"hashes": [
"sha256:0009211222388d8ba4a4840b6de21ff24461fd4aad6c6c194926e3091ac65f06",
"sha256:a9d39b35f7aa8eee82d6d9769d8004ec538e7d7c2f5a1c5e5525cda90d0e9b69"
"sha256:1b6025bbbd2517b7c246828b1d11c83d53567904836ae6d57bc0058f3cd18b50",
"sha256:76a698466178ce40473726ffd8c33f68d1c47f27c53f67fa4aeeb6fdde74d37b"
],
"index": "pypi",
"version": "==0.7.3"
"version": "==0.7.4"
},
"django-prometheus": {
"hashes": [
@ -276,11 +269,11 @@
},
"django-storages": {
"hashes": [
"sha256:87287b7ad2e789cd603373439994e1ac6f94d9dc2e5f8173d2a87aa3ed458bd9",
"sha256:f3b3def96493d3ccde37b864cea376472baf6e8a596504b209278801c510b807"
"sha256:0a9b7e620e969fb0797523695329ed223bf540bbfdf6cd163b061fc11dab2d1c",
"sha256:9322ab74ba6371e2e0fccc350c741686ade829e43085597b26b07ae8955a0a00"
],
"index": "pypi",
"version": "==1.7.2"
"version": "==1.8"
},
"djangorestframework": {
"hashes": [
@ -315,16 +308,16 @@
},
"eight": {
"hashes": [
"sha256:b3ceecbfeb58fe68f726a69ac4225bbff554f5436c274646b75c63b039626c9e",
"sha256:eebadb79193c9a3ed95a74f59462267f05ca41c23a804f9f0dd80e597c9a9f8e"
"sha256:0a7f0e7725f2a478a97676cf9c49266d95f922f8ed621ec314eeccb333927dc2",
"sha256:d148aa1fac6cafb5ff806ff634914b05e3f9357aa8dbd82cd7908821d7f93f43"
],
"version": "==0.4.2"
"version": "==1.0.0"
},
"future": {
"hashes": [
"sha256:e39ced1ab767b5936646cedba8bcce582398233d6a627067d4c6a454c90cfedb"
"sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
],
"version": "==0.16.0"
"version": "==0.18.2"
},
"idna": {
"hashes": [
@ -335,10 +328,11 @@
},
"importlib-metadata": {
"hashes": [
"sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26",
"sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af"
"sha256:3a8b2dfd0a2c6a3636e7c016a7e54ae04b997d30e69d5eacdca7a6c2221a1402",
"sha256:41e688146d000891f32b1669e8573c57e39e5060e7f5f647aa617cd9a9568278"
],
"version": "==0.23"
"markers": "python_version < '3.8'",
"version": "==1.2.0"
},
"inflection": {
"hashes": [
@ -368,10 +362,10 @@
},
"jsonschema": {
"hashes": [
"sha256:2fa0684276b6333ff3c0b1b27081f4b2305f0a36cf702a23db50edb141893c3f",
"sha256:94c0a13b4a0616458b42529091624e66700a17f847453e52279e35509a5b7631"
"sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163",
"sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"
],
"version": "==3.1.1"
"version": "==3.2.0"
},
"kombu": {
"hashes": [
@ -391,35 +385,35 @@
},
"lxml": {
"hashes": [
"sha256:02ca7bf899da57084041bb0f6095333e4d239948ad3169443f454add9f4e9cb4",
"sha256:096b82c5e0ea27ce9138bcbb205313343ee66a6e132f25c5ed67e2c8d960a1bc",
"sha256:0a920ff98cf1aac310470c644bc23b326402d3ef667ddafecb024e1713d485f1",
"sha256:1409b14bf83a7d729f92e2a7fbfe7ec929d4883ca071b06e95c539ceedb6497c",
"sha256:17cae1730a782858a6e2758fd20dd0ef7567916c47757b694a06ffafdec20046",
"sha256:17e3950add54c882e032527795c625929613adbd2ce5162b94667334458b5a36",
"sha256:1f4f214337f6ee5825bf90a65d04d70aab05526c08191ab888cb5149501923c5",
"sha256:2e8f77db25b0a96af679e64ff9bf9dddb27d379c9900c3272f3041c4d1327c9d",
"sha256:4dffd405390a45ecb95ab5ab1c1b847553c18b0ef8ed01e10c1c8b1a76452916",
"sha256:6b899931a5648862c7b88c795eddff7588fb585e81cecce20f8d9da16eff96e0",
"sha256:726c17f3e0d7a7200718c9a890ccfeab391c9133e363a577a44717c85c71db27",
"sha256:760c12276fee05c36f95f8040180abc7fbebb9e5011447a97cdc289b5d6ab6fc",
"sha256:796685d3969815a633827c818863ee199440696b0961e200b011d79b9394bbe7",
"sha256:891fe897b49abb7db470c55664b198b1095e4943b9f82b7dcab317a19116cd38",
"sha256:9277562f175d2334744ad297568677056861070399cec56ff06abbe2564d1232",
"sha256:a471628e20f03dcdfde00770eeaf9c77811f0c331c8805219ca7b87ac17576c5",
"sha256:a63b4fd3e2cabdcc9d918ed280bdde3e8e9641e04f3c59a2a3109644a07b9832",
"sha256:ae88588d687bd476be588010cbbe551e9c2872b816f2da8f01f6f1fda74e1ef0",
"sha256:b0b84408d4eabc6de9dd1e1e0bc63e7731e890c0b378a62443e5741cfd0ae90a",
"sha256:be78485e5d5f3684e875dab60f40cddace2f5b2a8f7fede412358ab3214c3a6f",
"sha256:c27eaed872185f047bb7f7da2d21a7d8913457678c9a100a50db6da890bc28b9",
"sha256:c7fccd08b14aa437fe096c71c645c0f9be0655a9b1a4b7cffc77bcb23b3d61d2",
"sha256:c81cb40bff373ab7a7446d6bbca0190bccc5be3448b47b51d729e37799bb5692",
"sha256:d11874b3c33ee441059464711cd365b89fa1a9cf19ae75b0c189b01fbf735b84",
"sha256:e9c028b5897901361d81a4718d1db217b716424a0283afe9d6735fe0caf70f79",
"sha256:fe489d486cd00b739be826e8c1be188ddb74c7a1ca784d93d06fda882a6a1681"
"sha256:00ac0d64949fef6b3693813fe636a2d56d97a5a49b5bbb86e4cc4cc50ebc9ea2",
"sha256:0571e607558665ed42e450d7bf0e2941d542c18e117b1ebbf0ba72f287ad841c",
"sha256:0e3f04a7615fdac0be5e18b2406529521d6dbdb0167d2a690ee328bef7807487",
"sha256:13cf89be53348d1c17b453867da68704802966c433b2bb4fa1f970daadd2ef70",
"sha256:217262fcf6a4c2e1c7cb1efa08bd9ebc432502abc6c255c4abab611e8be0d14d",
"sha256:223e544828f1955daaf4cefbb4853bc416b2ec3fd56d4f4204a8b17007c21250",
"sha256:277cb61fede2f95b9c61912fefb3d43fbd5f18bf18a14fae4911b67984486f5d",
"sha256:3213f753e8ae86c396e0e066866e64c6b04618e85c723b32ecb0909885211f74",
"sha256:4690984a4dee1033da0af6df0b7a6bde83f74e1c0c870623797cec77964de34d",
"sha256:4fcc472ef87f45c429d3b923b925704aa581f875d65bac80f8ab0c3296a63f78",
"sha256:61409bd745a265a742f2693e4600e4dbd45cc1daebe1d5fad6fcb22912d44145",
"sha256:678f1963f755c5d9f5f6968dded7b245dd1ece8cf53c1aa9d80e6734a8c7f41d",
"sha256:6c6d03549d4e2734133badb9ab1c05d9f0ef4bcd31d83e5d2b4747c85cfa21da",
"sha256:6e74d5f4d6ecd6942375c52ffcd35f4318a61a02328f6f1bd79fcb4ffedf969e",
"sha256:7b4fc7b1ecc987ca7aaf3f4f0e71bbfbd81aaabf87002558f5bc95da3a865bcd",
"sha256:7ed386a40e172ddf44c061ad74881d8622f791d9af0b6f5be20023029129bc85",
"sha256:8f54f0924d12c47a382c600c880770b5ebfc96c9fd94cf6f6bdc21caf6163ea7",
"sha256:ad9b81351fdc236bda538efa6879315448411a81186c836d4b80d6ca8217cdb9",
"sha256:bbd00e21ea17f7bcc58dccd13869d68441b32899e89cf6cfa90d624a9198ce85",
"sha256:c3c289762cc09735e2a8f8a49571d0e8b4f57ea831ea11558247b5bdea0ac4db",
"sha256:cf4650942de5e5685ad308e22bcafbccfe37c54aa7c0e30cd620c2ee5c93d336",
"sha256:cfcbc33c9c59c93776aa41ab02e55c288a042211708b72fdb518221cc803abc8",
"sha256:e301055deadfedbd80cf94f2f65ff23126b232b0d1fea28f332ce58137bcdb18",
"sha256:ebbfe24df7f7b5c6c7620702496b6419f6a9aa2fd7f005eb731cc80d7b4692b9",
"sha256:eff69ddbf3ad86375c344339371168640951c302450c5d3e9936e98d6459db06",
"sha256:f6ed60a62c5f1c44e789d2cf14009423cb1646b44a43e40a9cf6a21f077678a1"
],
"index": "pypi",
"version": "==4.4.1"
"version": "==4.4.2"
},
"markupsafe": {
"hashes": [
@ -456,10 +450,10 @@
},
"more-itertools": {
"hashes": [
"sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832",
"sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4"
"sha256:53ff73f186307d9c8ef17a9600309154a6ae27f25579e80af4db8f047ba14bc2",
"sha256:a0ea684c39bc4315ba7aae406596ef191fd84f873d2d2751f84d64e81a7a2d45"
],
"version": "==7.2.0"
"version": "==8.0.0"
},
"oauthlib": {
"hashes": [
@ -507,11 +501,13 @@
"sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e",
"sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103",
"sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6",
"sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1",
"sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9",
"sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e",
"sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f",
"sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd",
"sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8",
"sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f",
"sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4",
"sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964",
"sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"
@ -521,10 +517,10 @@
},
"pyasn1": {
"hashes": [
"sha256:62cdade8b5530f0b185e09855dd422bc05c0bbff6b72ff61381c09dac7befd8c",
"sha256:a9495356ca1d66ed197a0f72b41eb1823cf7ea8b5bd07191673e8147aecf8604"
"sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
"sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"
],
"version": "==0.4.7"
"version": "==0.4.8"
},
"pyasn1-modules": {
"hashes": [
@ -541,78 +537,78 @@
},
"pycryptodome": {
"hashes": [
"sha256:0aa49f3fa110f8dc090bad1671a768cc17d3d3bd01566641ffc0d10d0fec8d49",
"sha256:0fafd3c4fb76c6992f34bf2d074f582f388e3b8062b8ba5d65b020634cc221e6",
"sha256:17eb9bd5d30a71b0c8a832e3e9cd2b7723f99907c38dc5dd23e59e8c368a70e2",
"sha256:2776255d5c748782f095ec422d42da2eadd8392ac9de7da23db4aed4231272bd",
"sha256:3500826dc3b9a8fdb762bebe551106081a6bdecd4181a3d1bd0206e48bba8974",
"sha256:3aa0d30326dcdef24c632d5c03b8e4d379c6ae0645082b27dd69ea816bb97ecb",
"sha256:3c7769bdadcc4809508e71997008912cc6d94fd7b5b1f3ef121683ebcac71d81",
"sha256:3e8c97a38dac6dafd180b4696a522b1581dd1a8e0ea60763458be547bac97361",
"sha256:5aca5125a46e458b308b5571ce8fe36d2229f161aa7db27b3ecacded70c6aa8b",
"sha256:62beb75f0688f406946312bfef8923d8ab23f5b8013acded931413625299d317",
"sha256:7725643de3c884a9945a086670787dce637037f32c5c2df7fd602bd5967f3486",
"sha256:872191a02a0c2a3b98dc75c62b32912b220a8ae5ff6ac9e39868f903f55dd6a4",
"sha256:8c501e80960d12328d49e1d409daf426f29364a37c602f257c99509999654650",
"sha256:9512638bfef8ffc94c62751965a4733c3792104dc84771ba54ce0f80f49134df",
"sha256:962043051afa7a5ab071b0d8996dc00e564327a18566d3e574a39cb6e097b462",
"sha256:9db72b18b30902a83fa57b0d7dae4ce24f85186695e3bea0d423f1ec7c5b3fbe",
"sha256:9ffd4f0bfb5949dfa0e5cedef836364f18da0deb2fba04671607fb3b59b29112",
"sha256:a26819f693cf5fc0a2373a3e4b91c38e359cad9f00020a885b667c77f28738d5",
"sha256:a3efc575a53511c48361d933e12e07c2eb940db1afda0995285176c372ab7352",
"sha256:ababd6685b9d94729a851a0615482156afdacbeaabeea60f67961db0e975b1af",
"sha256:b0e9c8c270cd3f8c73b53139f0708f257189a00bbc898be6d3f03995e5f7edc2",
"sha256:b74173b13c221ee96b608212b9adc2c459a73d3632f04490df42e4f07e7041e6",
"sha256:bed297f75ba19cefe2d10beb4959f4f8cb62c2560a3998ad87479485098ee939",
"sha256:c639f09e8ce8ad5af9884233f952ade4b73a11b7d41d3b9bb7d4e64d9e1df164",
"sha256:c7bc308be67288af1cd44668d59e36356f0ce518337899079ddb0235bd55db79",
"sha256:cca152dcebc318833ba70499190ce17ee81b525404e2a7548c77f52b439306a7",
"sha256:d5261d22bc3a54db26f11dabcda14bbaab72080977e083d795b4b1d1b510c774",
"sha256:d81111e3da7fc9eee825ba7d8a68b3c1464f41110ef98a7280e0c7fb82c91e73",
"sha256:d95fafa899abb9f82e55ff43f423e100784312b43932514f2c05d41cbb20323e",
"sha256:de411a64d4105d4424441833bd25943208e58c846abf981bba5bbeeba88a49c3",
"sha256:e02c7b3d05b88ff1a236e49a252b2bf8444d3a1d04a056784af766c0909eba36",
"sha256:fbafe9b01b717e0bfbc83cd740ff5bf5cdd3f208815be470ea203942b899bbdf"
"sha256:042ae873baadd0c33b4d699a5c5b976ade3233a979d972f98ca82314632d868c",
"sha256:0502876279772b1384b660ccc91563d04490d562799d8e2e06b411e2d81128a9",
"sha256:2de33ed0a95855735d5a0fc0c39603314df9e78ee8bbf0baa9692fb46b3b8bbb",
"sha256:319e568baf86620b419d53063b18c216abf924875966efdfe06891b987196a45",
"sha256:4372ec7518727172e1605c0843cdc5375d4771e447b8148c787b860260aae151",
"sha256:48821950ffb9c836858d8fa09d7840b6df52eadd387a3c5acece55cb387743f9",
"sha256:4b9533d4166ca07abdd49ce9d516666b1df944997fe135d4b21ac376aa624aff",
"sha256:54456cf85130e01674d21fb1ab89ffccacb138a8ade88d72fa2b0ac898d2798b",
"sha256:56fdd0e425f1b8fd3a00b6d96351f86226674974814c50534864d0124d48871f",
"sha256:57b1b707363490c495ad0eeb38bd1b0e1697c497af25fad78d3a1ebf0477fd5b",
"sha256:5c485ed6e9718ebcaa81138fa70ace9c563d202b56a8cee119b4085b023931f5",
"sha256:63c103a22cbe9752f6ea9f1a0de129995bad91c4d03a66c67cffcf6ee0c9f1e1",
"sha256:68fab8455efcbfe87c5d75015476f9b606227ffe244d57bfd66269451706e899",
"sha256:6c2720696b10ae356040e888bde1239b8957fe18885ccf5e7b4e8dec882f0856",
"sha256:72166c2ac520a5dbd2d90208b9c279161ec0861662a621892bd52fb6ca13ab91",
"sha256:7c52308ac5b834331b2f107a490b2c27de024a229b61df4cdc5c131d563dfe98",
"sha256:87d8d85b4792ca5e730fb7a519fbc3ed976c59dcf79c5204589c59afd56b9926",
"sha256:896e9b6fd0762aa07b203c993fbbee7a1f1a4674c6886afd7bfa86f3d1be98a8",
"sha256:8a799bea3c6617736e914a2e77c409f52893d382f619f088f8a80e2e21f573c1",
"sha256:9d9945ac8375d5d8e60bd2a2e1df5882eaa315522eedf3ca868b1546dfa34eba",
"sha256:9ef966c727de942de3e41aa8462c4b7b4bca70f19af5a3f99e31376589c11aac",
"sha256:a168e73879619b467072509a223282a02c8047d932a48b74fbd498f27224aa04",
"sha256:a30f501bbb32e01a49ef9e09ca1260e5ab49bf33a257080ec553e08997acc487",
"sha256:a8ca2450394d3699c9f15ef25e8de9a24b401933716a1e39d37fa01f5fe3c58b",
"sha256:aec4d42deb836b8fb3ba32f2ba1ef0d33dd3dc9d430b1479ee7a914490d15b5e",
"sha256:b4af098f2a50f8d048ab12cabb59456585c0acf43d90ee79782d2d6d0ed59dba",
"sha256:b55c60c321ac91945c60a40ac9896ac7a3d432bb3e8c14006dfd82ad5871c331",
"sha256:c53348358408d94869059e16fba5ff3bef8c52c25b18421472aba272b9bb450f",
"sha256:cbfd97f9e060f0d30245cd29fa267a9a84de9da97559366fca0a3f7655acc63f",
"sha256:d3fe3f33ad52bf0c19ee6344b695ba44ffbfa16f3c29ca61116b48d97bd970fb",
"sha256:e3a79a30d15d9c7c284a7734036ee8abdb5ca3a6f5774d293cdc9e1358c1dc10",
"sha256:eec0689509389f19875f66ae8dedd59f982240cdab31b9f78a8dc266011df93a"
],
"index": "pypi",
"version": "==3.9.1"
"version": "==3.9.4"
},
"pycryptodomex": {
"hashes": [
"sha256:0713fc29cddb14f977887ccf3199d1a00d0b040e8c35785df20d107ad59efabc",
"sha256:110651378be063d5e0e653d107a14b511bd45c355968a32270f5b1bf8c093056",
"sha256:158428c0f337984cb3611484d9f61faea973aec624c8f88c5809ab88adab0884",
"sha256:17625d9f9442d3567b2532795c9232ed80cc1d6c91064ad48c802f3bff2b937d",
"sha256:179125d0b2bcbf5cf9ddf9fb74fe13e30d19fb1c2691cac43b8b37d74df9ddf6",
"sha256:227e660ee3835284fc6195163c467f8d21a1de51d0aa85d32157a1fc4bf16b9a",
"sha256:2f651173c4bb8de6a96493e5cc03b2838eedf4bb1cbfbe2b354e40a2f2f245fc",
"sha256:33b0e5c9ca02c099ec537138e8ffee1e4d054e49d69258062d89ddbd9f660000",
"sha256:42bead6e7dbca9328a6601ff41d25554606847d92b0fd198ca3f6c971c662c07",
"sha256:478cce6245e8ff8cda8f733ef1a1161ee6bf5aaa45312e1ace6c7b80fbc1e01f",
"sha256:4ce38cb16b6f41c4b579e3e9a9d66c36ba24192cc0518ce09313c25ae44d2d74",
"sha256:4e0bc594c61bd1db86c0060a5eb351c22a6c4c154315a52af1c8cd24c4e6a8a3",
"sha256:4e1e616d12f79f256109de14aebcee1bf7e0a78d00b3de6c9a0cf2eb2a80785c",
"sha256:5e4b459ccd6bfe55cc6b030b8983040bc8956f5757b621ae32dd0a26b0f85a91",
"sha256:61a586b0cb85bc8c60af4ddcae24928a3476c944cb37eb7b9066965bc1d4b4d8",
"sha256:643bea8898e875e54177c546f2ac704317937230379a9d295ece844c79e00cdb",
"sha256:7403d7addaaa4649777ce487832ef8421222960a10d7a95b0f2c9efd217a93e6",
"sha256:7f36378a699f201aea3e431a3c217c16e63abbe84ddb8d9bd0af9b28e3f826aa",
"sha256:9146a6cf9eeb4683cfffabc7093fd1063076185d790680596f7a2dfb40f6b4b9",
"sha256:9829d8aa2fb52646eda9041b785e9c6825fc1f1054f2254046fb7628800acb8e",
"sha256:aa18ad3da8da74cbd119a6c5460079c7357ba8775b2edbc5a78722fc1e52f881",
"sha256:ad39a8d3be6c5aad42b1ef839c49a50185618b26d5f1b555b1edd4d9d700e3b9",
"sha256:b10bb3c640d7666993d5b0aec0e5334131386eddbd200aabcc123fe07c2b8928",
"sha256:b17b2f5f65dffdeddf06bb82eb73a6aa55766322c3c45bc5032f9e3259adfdb0",
"sha256:ba5bce9e1fc21160c27015a705e80f49901f1c42aa8bf96ed1d650ce4b5311bd",
"sha256:c2b867277ef5a996b2198bec149abaeaeddbe57a77a4f6840882be382af72297",
"sha256:c43d5d7516b0dc8436aef6bf9ebb9fbeaebcbbc4cb1b6a23be4a5f843c2614e3",
"sha256:ce65a7dc9162a6e676f336e45f6602297981afa82f8e7ccc690667316c6b449b",
"sha256:d9a38c3a85dd3dc6cae43eac94b73485fd7e5a1daf74bb510d7220a8b18482d2",
"sha256:de39d7c456147755e5610177bd50cb7c89f74477d608b5ac055fed4e7c4c35c1",
"sha256:ea368b7b4f36c5524d7b47aa583db604085958b92ff6580075230c8d7c88cdbe",
"sha256:ff75fa26b7f8e1eaeba9edfc50b1d21bca913e743ce993a189b07bf483bedda0"
"sha256:0943b65fb41b7403a9def6214061fdd9ab9afd0bbc581e553c72eebe60bded36",
"sha256:0a1dbb5c4d975a4ea568fb7686550aa225d94023191fb0cca8747dc5b5d77857",
"sha256:0f43f1608518347fdcb9c8f443fa5cabedd33f94188b13e4196a3a7ba90d169c",
"sha256:11ce5fec5990e34e3981ed14897ba601c83957b577d77d395f1f8f878a179f98",
"sha256:17a09e38fdc91e4857cf5a7ce82f3c0b229c3977490f2146513e366923fc256b",
"sha256:22d970cee5c096b9123415e183ae03702b2cd4d3ba3f0ced25c4e1aba3967167",
"sha256:2a1793efcbae3a2264c5e0e492a2629eb10d895d6e5f17dbbd00eb8b489c6bda",
"sha256:30a8a148a0fe482cec1aaf942bbd0ade56ec197c14fe058b2a94318c57e1f991",
"sha256:32fbbaf964c5184d3f3e349085b0536dd28184b02e2b014fc900f58bbc126339",
"sha256:347d67faee36d449dc9632da411cc318df52959079062627f1243001b10dc227",
"sha256:45f4b4e5461a041518baabc52340c249b60833aa84cea6377dc8016a2b33c666",
"sha256:4717daec0035034b002d31c42e55431c970e3e38a78211f43990e1b7eaf19e28",
"sha256:51a1ac9e7dda81da444fed8be558a60ec88dfc73b2aa4b0efa310e87acb75838",
"sha256:53e9dcc8f14783f6300b70da325a50ac1b0a3dbaee323bd9dc3f71d409c197a1",
"sha256:5519a2ed776e193688b7ddb61ab709303f6eb7d1237081e298283c72acc44271",
"sha256:583450e8e80a0885c453211ed2bd69ceea634d8c904f23ff8687f677fe810e95",
"sha256:60f862bd2a07133585a4fc2ce2b1a8ec24746b07ac44307d22ef2b767cb03435",
"sha256:612091f1d3c84e723bec7cb855cf77576e646045744794c9a3f75ba80737762f",
"sha256:629a87b87c8203b8789ccefc7f2f2faecd2daaeb56bdd0b4e44cd89565f2db07",
"sha256:6e56ec4c8938fb388b6f250ddd5e21c15e8f25a76e0ad0e2abae9afee09e67b4",
"sha256:8e8092651844a11ec7fa534395f3dfe99256ce4edca06f128efc9d770d6e1dc1",
"sha256:8f5f260629876603e08f3ce95c8ccd9b6b83bf9a921c41409046796267f7adc5",
"sha256:9a6b74f38613f54c56bd759b411a352258f47489bbefd1d57c930a291498b35b",
"sha256:a5a13ebb52c4cd065fb673d8c94f39f30823428a4de19e1f3f828b63a8882d1e",
"sha256:a77ca778a476829876a3a70ae880073379160e4a465d057e3c4e1c79acdf1b8a",
"sha256:a9f7be3d19f79429c2118fd61bc2ec4fa095e93b56fb3a5f3009822402c4380f",
"sha256:dc15a467c4f9e4b43748ba2f97aea66f67812bfd581818284c47cadc81d4caec",
"sha256:e13cdeea23059f7577c230fd580d2c8178e67ebe10e360041abe86c33c316f1c",
"sha256:e45b85c8521bca6bdfaf57e4987743ade53e9f03529dd3adbc9524094c6d55c4",
"sha256:e87f17867b260f57c88487f943eb4d46c90532652bb37046e764842c3b66cbb1",
"sha256:ee40a5b156f6c1192bc3082e9d73d0479904433cdda83110546cd67f5a15a5be",
"sha256:ef63ffde3b267043579af8830fc97fc3b9b8a526a24e3ba23af9989d4e9e689a"
],
"version": "==3.9.1"
"version": "==3.9.4"
},
"pyjwkest": {
"hashes": [
@ -622,23 +618,23 @@
},
"pyopenssl": {
"hashes": [
"sha256:26ff56a6b5ecaf3a2a59f132681e2a80afcc76b4f902f612f518f92c2a1bf854",
"sha256:6488f1423b00f73b7ad5167885312bb0ce410d3312eb212393795b53c8caa580"
"sha256:621880965a720b8ece2f1b2f54ea2071966ab00e2970ad2ce11d596102063504",
"sha256:9a24494b2602aaf402be5c9e30a0b82d4a5c67528fe8fb475e3f3bc00dd69507"
],
"version": "==18.0.0"
"version": "==19.1.0"
},
"pyparsing": {
"hashes": [
"sha256:4acadc9a2b96c19fe00932a38ca63e601180c39a189a696abce1eaab641447e1",
"sha256:61b5ed888beab19ddccab3478910e2076a6b5a0295dffc43021890e136edf764"
"sha256:20f995ecd72f2a1f4bf6b072b63b22e2eb457836601e76d6e5dfcd75436acc1f",
"sha256:4ca62001be367f01bd3e92ecbb79070272a9d4964dce6a48a82ff0b8bc7e683a"
],
"version": "==2.4.4"
"version": "==2.4.5"
},
"pyrsistent": {
"hashes": [
"sha256:eb6545dbeb1aa69ab1fb4809bfbf5a8705e44d92ef8fc7c2361682a47c46c778"
"sha256:f3b280d030afb652f79d67c5586157c5c1355c9a58dfc7940566e28d28f3df1b"
],
"version": "==0.15.5"
"version": "==0.15.6"
},
"python-dateutil": {
"hashes": [
@ -689,22 +685,20 @@
},
"pyyaml": {
"hashes": [
"sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9",
"sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4",
"sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8",
"sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696",
"sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34",
"sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9",
"sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73",
"sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299",
"sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b",
"sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae",
"sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681",
"sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41",
"sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"
"sha256:0e7f69397d53155e55d10ff68fdfb2cf630a35e6daf65cf0bdeaf04f127c09dc",
"sha256:2e9f0b7c5914367b0916c3c104a024bb68f269a486b9d04a2e8ac6f6597b7803",
"sha256:35ace9b4147848cafac3db142795ee42deebe9d0dad885ce643928e88daebdcc",
"sha256:38a4f0d114101c58c0f3a88aeaa44d63efd588845c5a2df5290b73db8f246d15",
"sha256:483eb6a33b671408c8529106df3707270bfacb2447bf8ad856a4b4f57f6e3075",
"sha256:4b6be5edb9f6bb73680f5bf4ee08ff25416d1400fbd4535fe0069b2994da07cd",
"sha256:7f38e35c00e160db592091751d385cd7b3046d6d51f578b29943225178257b31",
"sha256:8100c896ecb361794d8bfdb9c11fce618c7cf83d624d73d5ab38aef3bc82d43f",
"sha256:c0ee8eca2c582d29c3c2ec6e2c4f703d1b7f1fb10bc72317355a746057e7346c",
"sha256:e4c015484ff0ff197564917b4b4246ca03f411b9bd7f16e02a2f586eb48b6d04",
"sha256:ebc4ed52dcc93eeebeae5cf5deb2ae4347b3a81c3fa12b0b8c976544829396a4"
],
"index": "pypi",
"version": "==5.1.2"
"version": "==5.2"
},
"qrcode": {
"hashes": [
@ -776,11 +770,11 @@
},
"sentry-sdk": {
"hashes": [
"sha256:09e1e8f00f22ea580348f83bbbd880adf40b29f1dec494a8e4b33e22f77184fb",
"sha256:ff1fa7fb85703ae9414c8b427ee73f8363232767c9cd19158f08f6e4f0b58fc7"
"sha256:a7c2c8d3f53b6b57454830cd6a4b73d272f1ba91952f59e6545b3cf885f3c22f",
"sha256:bfc486af718c268cf49ff43d6334ed4db7333ace420240b630acdd8f8a3a8f60"
],
"index": "pypi",
"version": "==0.13.2"
"version": "==0.13.4"
},
"service-identity": {
"hashes": [
@ -792,11 +786,11 @@
},
"signxml": {
"hashes": [
"sha256:70e3edbb07b89bec94d39db2cdced724c540f9258366474177c746b9f903d9c4",
"sha256:9540efcddd94e45399fa26ee2d24af43d162d55cbe3a2b36fddb394741993dd5"
"sha256:2e186c117284fe5a0c543f5bcdde68f5a2341eeae219af9eb7e512dacf4bfce7",
"sha256:7d6af724542cae915bbb9000d333a52ce495d0b3cdcb4dc590c3c4a149b079ed"
],
"index": "pypi",
"version": "==2.6.0"
"version": "==2.7.2"
},
"six": {
"hashes": [
@ -841,12 +835,12 @@
"secure"
],
"hashes": [
"sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398",
"sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86"
"sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293",
"sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"
],
"index": "pypi",
"markers": null,
"version": "==1.25.6"
"version": "==1.25.7"
},
"vine": {
"hashes": [
@ -864,6 +858,13 @@
}
},
"develop": {
"asgiref": {
"hashes": [
"sha256:7e06d934a7718bf3975acbf87780ba678957b87c7adc056f13b6215d610695a0",
"sha256:ea448f92fc35a0ef4b1508f53a04c4670255a3f33d22a81c8fc9c872036adbe5"
],
"version": "==3.2.3"
},
"astroid": {
"hashes": [
"sha256:6560e1e1749f68c64a4b5dee4e091fce798d2f0d84ebe638cf0e0585a343acf4",
@ -942,19 +943,19 @@
},
"django": {
"hashes": [
"sha256:16040e1288c6c9f68c6da2fe75ebde83c0a158f6f5d54f4c5177b0c1478c5b86",
"sha256:89c2007ca4fa5b351a51a279eccff298520783b713bf28efb89dfb81c80ea49b"
"sha256:a4ad4f6f9c6a4b7af7e2deec8d0cbff28501852e5010d6c2dc695d3d1fae7ca0",
"sha256:fa98ec9cc9bf5d72a08ebf3654a9452e761fbb8566e3f80de199cbc15477e891"
],
"index": "pypi",
"version": "==2.2.7"
"version": "==2.2.8"
},
"django-debug-toolbar": {
"hashes": [
"sha256:17c53cd6bf4e7d69902aedf9a1d26c5d3b7369b54c5718744704f27b5a72f35d",
"sha256:9a23ada2e43cd989195db3c18710b5d7451134a0d48127ab64c1d2ad81700342"
"sha256:24c157bc6c0e1648e0a6587511ecb1b007a00a354ce716950bff2de12693e7a8",
"sha256:77cfba1d6e91b9bc3d36dc7dc74a9bb80be351948db5f880f2562a0cbf20b6c5"
],
"index": "pypi",
"version": "==2.0"
"version": "==2.1"
},
"dodgy": {
"hashes": [
@ -971,10 +972,10 @@
},
"gitpython": {
"hashes": [
"sha256:3237caca1139d0a7aa072f6735f5fd2520de52195e0fa1d8b83a9b212a2498b2",
"sha256:a7d6bef0775f66ba47f25911d285bcd692ce9053837ff48a120c2b8cf3a71389"
"sha256:9c2398ffc3dcb3c40b27324b316f08a4f93ad646d5a6328cafbb871aa79f5e42",
"sha256:c155c6a2653593ccb300462f6ef533583a913e17857cfef8fc617c246b6dc245"
],
"version": "==3.0.4"
"version": "==3.0.5"
},
"isort": {
"hashes": [
@ -1019,10 +1020,10 @@
},
"pbr": {
"hashes": [
"sha256:2c8e420cd4ed4cec4e7999ee47409e876af575d4c35a45840d59e8b5f3155ab8",
"sha256:b32c8ccaac7b1a20c0ce00ce317642e6cf231cf038f9875e0280e28af5bf7ac9"
"sha256:139d2625547dbfa5fb0b81daebb39601c478c21956dc57e2e07b74450a8c506b",
"sha256:61aa52a0f18b71c5cc58232d2cf8f8d09cd67fcad60b742a60124cb8d6951488"
],
"version": "==5.4.3"
"version": "==5.4.4"
},
"pep8-naming": {
"hashes": [
@ -1103,22 +1104,20 @@
},
"pyyaml": {
"hashes": [
"sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9",
"sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4",
"sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8",
"sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696",
"sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34",
"sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9",
"sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73",
"sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299",
"sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b",
"sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae",
"sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681",
"sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41",
"sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"
"sha256:0e7f69397d53155e55d10ff68fdfb2cf630a35e6daf65cf0bdeaf04f127c09dc",
"sha256:2e9f0b7c5914367b0916c3c104a024bb68f269a486b9d04a2e8ac6f6597b7803",
"sha256:35ace9b4147848cafac3db142795ee42deebe9d0dad885ce643928e88daebdcc",
"sha256:38a4f0d114101c58c0f3a88aeaa44d63efd588845c5a2df5290b73db8f246d15",
"sha256:483eb6a33b671408c8529106df3707270bfacb2447bf8ad856a4b4f57f6e3075",
"sha256:4b6be5edb9f6bb73680f5bf4ee08ff25416d1400fbd4535fe0069b2994da07cd",
"sha256:7f38e35c00e160db592091751d385cd7b3046d6d51f578b29943225178257b31",
"sha256:8100c896ecb361794d8bfdb9c11fce618c7cf83d624d73d5ab38aef3bc82d43f",
"sha256:c0ee8eca2c582d29c3c2ec6e2c4f703d1b7f1fb10bc72317355a746057e7346c",
"sha256:e4c015484ff0ff197564917b4b4246ca03f411b9bd7f16e02a2f586eb48b6d04",
"sha256:ebc4ed52dcc93eeebeae5cf5deb2ae4347b3a81c3fa12b0b8c976544829396a4"
],
"index": "pypi",
"version": "==5.1.2"
"version": "==5.2"
},
"requirements-detector": {
"hashes": [

View file

@ -46,8 +46,8 @@ class UserUpdateView(SuccessMessageMixin, LoginRequiredMixin,
form_class = UserForm
permission_required = 'passbook_core.change_user'
context_object_name = 'object' # By default the object's name
# is user which is used by other checks
# By default the object's name is user which is used by other checks
context_object_name = 'object'
template_name = 'generic/update.html'
success_url = reverse_lazy('passbook_admin:users')
success_message = _('Successfully updated User')

View file

@ -0,0 +1,24 @@
# Generated by Django 2.2.8 on 2019-12-05 14:07
from django.db import migrations, models
import passbook.audit.models
class Migration(migrations.Migration):
dependencies = [
('passbook_audit', '0002_auto_20191028_0829'),
]
operations = [
migrations.AlterModelOptions(
name='event',
options={'verbose_name': 'Audit Event', 'verbose_name_plural': 'Audit Events'},
),
migrations.AlterField(
model_name='event',
name='action',
field=models.TextField(choices=[('LOGIN', 'login'), ('LOGIN_FAILED', 'login_failed'), ('LOGOUT', 'logout'), ('AUTHORIZE_APPLICATION', 'authorize_application'), ('SUSPICIOUS_REQUEST', 'suspicious_request'), ('SIGN_UP', 'sign_up'), ('PASSWORD_RESET', 'password_reset'), ('INVITE_CREATED', 'invitation_created'), ('INVITE_USED', 'invitation_used'), ('CUSTOM', 'custom')]),
),
]

View file

@ -0,0 +1,22 @@
# Generated by Django 2.2.8 on 2019-12-05 15:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('passbook_audit', '0003_auto_20191205_1407'),
]
operations = [
migrations.RemoveField(
model_name='event',
name='request_ip',
),
migrations.AddField(
model_name='event',
name='client_ip',
field=models.GenericIPAddressField(null=True),
),
]

View file

@ -1,75 +1,103 @@
"""passbook audit models"""
from enum import Enum
from inspect import getmodule, stack
from typing import Optional
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.contrib.postgres.fields import JSONField
from django.core.exceptions import ValidationError
from django.db import models
from django.http import HttpRequest
from django.utils.translation import gettext as _
from ipware import get_client_ip
from guardian.shortcuts import get_anonymous_user
from structlog import get_logger
from passbook.lib.models import UUIDModel
from passbook.lib.utils.http import get_client_ip
LOGGER = get_logger()
class EventAction(Enum):
"""All possible actions to save into the audit log"""
LOGIN = 'login'
LOGIN_FAILED = 'login_failed'
LOGOUT = 'logout'
AUTHORIZE_APPLICATION = 'authorize_application'
SUSPICIOUS_REQUEST = 'suspicious_request'
SIGN_UP = 'sign_up'
PASSWORD_RESET = 'password_reset' # noqa # nosec
INVITE_CREATED = 'invitation_created'
INVITE_USED = 'invitation_used'
CUSTOM = 'custom'
@staticmethod
def as_choices():
"""Generate choices of actions used for database"""
return tuple((x, y.value) for x, y in EventAction.__members__.items())
class Event(UUIDModel):
"""An individual audit log event"""
ACTION_LOGIN = 'login'
ACTION_LOGIN_FAILED = 'login_failed'
ACTION_LOGOUT = 'logout'
ACTION_AUTHORIZE_APPLICATION = 'authorize_application'
ACTION_SUSPICIOUS_REQUEST = 'suspicious_request'
ACTION_SIGN_UP = 'sign_up'
ACTION_PASSWORD_RESET = 'password_reset' # noqa # nosec
ACTION_INVITE_CREATED = 'invitation_created'
ACTION_INVITE_USED = 'invitation_used'
ACTIONS = (
(ACTION_LOGIN, ACTION_LOGIN),
(ACTION_LOGIN_FAILED, ACTION_LOGIN_FAILED),
(ACTION_LOGOUT, ACTION_LOGOUT),
(ACTION_AUTHORIZE_APPLICATION, ACTION_AUTHORIZE_APPLICATION),
(ACTION_SUSPICIOUS_REQUEST, ACTION_SUSPICIOUS_REQUEST),
(ACTION_SIGN_UP, ACTION_SIGN_UP),
(ACTION_PASSWORD_RESET, ACTION_PASSWORD_RESET),
(ACTION_INVITE_CREATED, ACTION_INVITE_CREATED),
(ACTION_INVITE_USED, ACTION_INVITE_USED),
)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)
action = models.TextField(choices=ACTIONS)
action = models.TextField(choices=EventAction.as_choices())
date = models.DateTimeField(auto_now_add=True)
app = models.TextField()
context = JSONField(default=dict, blank=True)
request_ip = models.GenericIPAddressField()
client_ip = models.GenericIPAddressField(null=True)
created = models.DateTimeField(auto_now_add=True)
@staticmethod
def create(action, request, **kwargs):
"""Create Event from arguments"""
client_ip, _ = get_client_ip(request)
if not hasattr(request, 'user'):
user = None
else:
user = request.user
if isinstance(user, AnonymousUser):
user = kwargs.get('user', None)
entry = Event.objects.create(
action=action,
user=user,
# User 255.255.255.255 as fallback if IP cannot be determined
request_ip=client_ip or '255.255.255.255',
def _get_app_from_request(request: HttpRequest) -> str:
if not isinstance(request, HttpRequest):
return ""
return request.resolver_match.app_name
@staticmethod
def new(action: EventAction,
app: Optional[str] = None,
_inspect_offset: int = 1,
**kwargs) -> 'Event':
"""Create new Event instance from arguments. Instance is NOT saved."""
if not isinstance(action, EventAction):
raise ValueError(f"action must be EventAction instance but was {type(action)}")
if not app:
app = getmodule(stack()[_inspect_offset][0]).__name__
event = Event(
action=action.value,
app=app,
context=kwargs)
LOGGER.debug("Created Audit entry", action=action,
user=user, from_ip=client_ip, context=kwargs)
return entry
LOGGER.debug("Created Audit event", action=action, context=kwargs)
return event
def from_http(self, request: HttpRequest,
user: Optional[settings.AUTH_USER_MODEL] = None) -> 'Event':
"""Add data from a Django-HttpRequest, allowing the creation of
Events independently from requests.
`user` arguments optionally overrides user from requests."""
if hasattr(request, 'user'):
if isinstance(request.user, AnonymousUser):
self.user = get_anonymous_user()
else:
self.user = request.user
if user:
self.user = user
# User 255.255.255.255 as fallback if IP cannot be determined
self.client_ip = get_client_ip(request) or '255.255.255.255'
# If there's no app set, we get it from the requests too
if not self.app:
self.app = Event._get_app_from_request(request)
self.save()
return self
def save(self, *args, **kwargs):
if not self._state.adding:
raise ValidationError("you may not edit an existing %s" % self._meta.model_name)
super().save(*args, **kwargs)
return super().save(*args, **kwargs)
class Meta:
verbose_name = _('Audit Entry')
verbose_name_plural = _('Audit Entries')
verbose_name = _('Audit Event')
verbose_name_plural = _('Audit Events')

View file

@ -2,7 +2,7 @@
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
from passbook.audit.models import Event
from passbook.audit.models import Event, EventAction
from passbook.core.signals import (invitation_created, invitation_used,
user_signed_up)
@ -10,26 +10,24 @@ from passbook.core.signals import (invitation_created, invitation_used,
@receiver(user_logged_in)
def on_user_logged_in(sender, request, user, **kwargs):
"""Log successful login"""
Event.create(Event.ACTION_LOGIN, request)
Event.new(EventAction.LOGIN).from_http(request)
@receiver(user_logged_out)
def on_user_logged_out(sender, request, user, **kwargs):
"""Log successfully logout"""
Event.create(Event.ACTION_LOGOUT, request)
Event.new(EventAction.LOGOUT).from_http(request)
@receiver(user_signed_up)
def on_user_signed_up(sender, request, user, **kwargs):
"""Log successfully signed up"""
Event.create(Event.ACTION_SIGN_UP, request)
Event.new(EventAction.SIGN_UP).from_http(request)
@receiver(invitation_created)
def on_invitation_created(sender, request, invitation, **kwargs):
"""Log Invitation creation"""
Event.create(Event.ACTION_INVITE_CREATED, request,
invitation_uuid=invitation.uuid.hex)
Event.new(EventAction.INVITE_CREATED, invitation_uuid=invitation.uuid.hex).from_http(request)
@receiver(invitation_used)
def on_invitation_used(sender, request, invitation, **kwargs):
"""Log Invitation usage"""
Event.create(Event.ACTION_INVITE_USED, request,
invitation_uuid=invitation.uuid.hex)
Event.new(EventAction.INVITE_USED, invitation_uuid=invitation.uuid.hex).from_http(request)

View file

@ -16,6 +16,7 @@ from qrcode import make
from qrcode.image.svg import SvgPathImage
from structlog import get_logger
from passbook.audit.models import Event, EventAction
from passbook.factors.otp.forms import OTPSetupForm
from passbook.factors.otp.utils import otpauth_url
from passbook.lib.boilerplate import NeverCacheMixin
@ -55,12 +56,7 @@ class DisableView(LoginRequiredMixin, View):
token.delete()
messages.success(request, 'Successfully disabled OTP')
# Create event with email notification
# Event.create(
# user=request.user,
# message=_('You disabled TOTP.'),
# current=True,
# request=request,
# send_notification=True)
Event.new(EventAction.CUSTOM, message='User disabled OTP.').from_http(request)
return redirect(reverse('passbook_factors_otp:otp-user-settings'))
class EnableView(LoginRequiredMixin, FormView):
@ -77,7 +73,7 @@ class EnableView(LoginRequiredMixin, FormView):
def get_context_data(self, **kwargs):
kwargs['config'] = CONFIG.y('passbook')
kwargs['is_login'] = True
kwargs['title'] = _('Configue OTP')
kwargs['title'] = _('Configure OTP')
kwargs['primary_action'] = _('Setup')
return super().get_context_data(**kwargs)
@ -134,14 +130,7 @@ class EnableView(LoginRequiredMixin, FormView):
self.static_device.confirmed = True
self.static_device.save()
del self.request.session[OTP_SETTING_UP_KEY]
# Create event with email notification
# TODO: Create Audit Log entry
# Event.create(
# user=self.request.user,
# message=_('You activated TOTP.'),
# current=True,
# request=self.request,
# send_notification=True)
Event.new(EventAction.CUSTOM, message='User enabled OTP.').from_http(self.request)
return redirect('passbook_factors_otp:otp-user-settings')
class QRView(NeverCacheMixin, View):

View file

@ -1,88 +0,0 @@
"""passbook Core Reflection templatetags Templatetag"""
from django import template
from structlog import get_logger
register = template.Library()
LOGGER = get_logger()
def get_key_unique(context):
"""Get a unique key for cache based on user"""
uniq = ''
if 'request' in context:
user = context.get('request').user
if user.is_authenticated:
uniq = context.get('request').user.email
else:
# This should never be reached as modlist requires admin rights
uniq = 'anon' # pragma: no cover
return uniq
# @register.simple_tag(takes_context=True)
# def sv_reflection_admin_modules(context):
# """Get a list of all modules and their admin page"""
# key = 'sv_reflection_admin_modules_%s' % get_key_unique(context)
# if not cache.get(key):
# view_list = []
# for app in get_apps():
# title = app.title_modifier(context.request)
# url = app.admin_url_name
# view_list.append({
# 'url': url,
# 'default': True if url == SupervisrAppConfig.admin_url_name else False,
# 'name': title,
# })
# sorted_list = sorted(view_list, key=lambda x: x.get('name'))
# cache.set(key, sorted_list, 1000)
# return sorted_list
# return cache.get(key) # pragma: no cover
# @register.simple_tag(takes_context=True)
# def sv_reflection_user_modules(context):
# """Get a list of modules that have custom user settings"""
# key = 'sv_reflection_user_modules_%s' % get_key_unique(context)
# if not cache.get(key):
# app_list = []
# for app in get_apps():
# if not app.name.startswith('supervisr.mod'):
# continue
# view = app.view_user_settings
# if view is not None:
# app_list.append({
# 'title': app.title_modifier(context.request),
# 'view': '%s:%s' % (app.label, view)
# })
# sorted_list = sorted(app_list, key=lambda x: x.get('title'))
# cache.set(key, sorted_list, 1000)
# return sorted_list
# return cache.get(key) # pragma: no cover
# @register.simple_tag(takes_context=True)
# def sv_reflection_navbar_modules(context):
# """Get a list of subapps for the navbar"""
# key = 'sv_reflection_navbar_modules_%s' % get_key_unique(context)
# if not cache.get(key):
# app_list = []
# for app in get_apps():
# LOGGER.debug("Considering %s for Navbar", app.label)
# title = app.title_modifier(context.request)
# if app.navbar_enabled(context.request):
# index = getattr(app, 'index', None)
# if not index:
# index = '%s:index' % app.label
# try:
# reverse(index)
# LOGGER.debug("Module %s made it with '%s'", app.name, index)
# app_list.append({
# 'label': app.label,
# 'title': title,
# 'index': index
# })
# except NoReverseMatch:
# LOGGER.debug("View '%s' not reversable, ignoring %s", index, app.name)
# sorted_list = sorted(app_list, key=lambda x: x.get('label'))
# cache.set(key, sorted_list, 1000)
# return sorted_list
# return cache.get(key) # pragma: no cover

View file

@ -1,22 +1,14 @@
"""passbook lib Templatetags"""
import glob
import os
import socket
from hashlib import md5
from importlib import import_module
from urllib.parse import urlencode, urljoin
from urllib.parse import urlencode
from django import template
from django.apps import apps
from django.conf import settings
from django.db.models import Model
from django.template.loaders.app_directories import get_app_template_dirs
from django.urls import reverse
from django.utils.html import escape
from django.utils.translation import ugettext as _
from passbook.lib.config import CONFIG
from passbook.lib.utils.reflection import path_to_class
from passbook.lib.utils.urls import is_url_absolute
register = template.Library()
@ -48,34 +40,6 @@ def fieldtype(field):
return field.__class__.__name__
@register.simple_tag
def setting(key, default=''):
"""Returns a setting from the settings.py file. If Key is blocked, return default"""
return getattr(settings, key, default)
@register.simple_tag
def hostname():
"""Return the current Host's short hostname"""
return socket.gethostname()
@register.simple_tag
def fqdn():
"""Return the current Host's FQDN."""
return socket.getfqdn()
@register.filter('pick')
def pick(cont, arg, fallback=''):
"""Iterate through arg and return first choice which is not None"""
choices = arg.split(',')
for choice in choices:
if choice in cont and cont[choice] is not None:
return cont[choice]
return fallback
@register.simple_tag(takes_context=True)
def title(context, *title):
"""Return either just branding or title - branding"""
@ -106,81 +70,12 @@ def config(path, default=''):
return CONFIG.y(path, default)
@register.simple_tag()
def media(*args):
"""Iterate through arg and return full media URL"""
urls = []
for arg in args:
urls.append(urljoin(settings.MEDIA_URL, str(arg)))
if len(urls) == 1:
return urls[0]
return urls
@register.simple_tag
def url_unpack(view, kwargs):
"""Reverses a URL with kwargs which are stored in a dict"""
return reverse(view, kwargs=kwargs)
@register.simple_tag
def template_wildcard(*args):
"""Return a list of all templates in dir"""
templates = []
for tmpl_dir in args:
for app_templates in get_app_template_dirs('templates'):
path = os.path.join(app_templates, tmpl_dir)
if os.path.isdir(path):
files = sorted(glob.glob(path + '*.html'))
for file in files:
templates.append(os.path.relpath(file, start=app_templates))
return templates
@register.simple_tag(takes_context=True)
def related_models(context, model_path):
"""Return list of models which have a Relationship to current user"""
request = context.get('request', None)
if not request:
# No Request -> no user -> return empty
return []
user = request.user
model = path_to_class(model_path)
# if not issubclass(model, UserAcquirable):
# # model_path is not actually a module
# # so we can't assume that it's usable
# return []
return model.objects.filter(users__in=[user])
@register.filter('unslug')
def unslug(_input):
"""Convert slugs back into normal strings"""
return _input.replace('-', ' ').replace('_', ' ')
@register.filter(name='css_class')
def css_class(field, css):
"""Add css class to form field"""
return field.as_widget(attrs={"class": css})
@register.simple_tag
def app_versions():
"""Return dictionary of app_name: version"""
app_versions = {}
for app in apps.get_app_configs():
ver_module = import_module(app.name)
ver = getattr(ver_module, '__version__', None)
if ver:
if not isinstance(ver, str):
ver = '.'.join([str(x) for x in ver])
app_versions[app.verbose_name] = ver
return app_versions
@register.simple_tag
def gravatar(email, size=None, rating=None):
"""

View file

@ -0,0 +1,24 @@
"""http helpers"""
from typing import Any, Dict, Optional
from django.http import HttpRequest
def _get_client_ip_from_meta(meta: Dict[str, Any]) -> Optional[str]:
"""Attempt to get the client's IP by checking common HTTP Headers.
Returns none if no IP Could be found"""
headers = (
'HTTP_X_FORWARDED_FOR',
'HTTP_X_REAL_IP',
'REMOTE_ADDR',
)
for _header in headers:
if _header in meta:
return meta.get(_header)
return None
def get_client_ip(request: HttpRequest) -> Optional[str]:
"""Attempt to get the client's IP by checking common HTTP Headers.
Returns none if no IP Could be found"""
return _get_client_ip_from_meta(request.META)

View file

@ -1,9 +1,9 @@
"""passbook reputation request policy"""
from django.db import models
from django.utils.translation import gettext as _
from ipware import get_client_ip
from passbook.core.models import Policy, User
from passbook.lib.utils.http import get_client_ip
from passbook.policies.struct import PolicyRequest, PolicyResult
@ -17,7 +17,7 @@ class ReputationPolicy(Policy):
form = 'passbook.policies.reputation.forms.ReputationPolicyForm'
def passes(self, request: PolicyRequest) -> PolicyResult:
remote_ip, _ = get_client_ip(request.http_request)
remote_ip = get_client_ip(request.http_request)
passing = True
if self.check_ip:
ip_scores = IPReputation.objects.filter(ip=remote_ip, score__lte=self.threshold)

View file

@ -1,30 +1,18 @@
"""passbook reputation request signals"""
from django.contrib.auth.signals import user_logged_in, user_login_failed
from django.dispatch import receiver
from ipware import get_client_ip
from structlog import get_logger
from passbook.core.models import User
from passbook.lib.utils.http import get_client_ip
from passbook.policies.reputation.models import IPReputation, UserReputation
LOGGER = get_logger()
def get_remote_ip(request):
"""Small wrapper of get_client_ip to catch errors"""
try:
remote_ip, _ = get_client_ip(request)
if remote_ip:
return remote_ip
if 'ip' in request:
return request['ip']
except (AttributeError, ValueError):
pass
return '255.255.255.255'
def update_score(request, username, amount):
"""Update score for IP and User"""
remote_ip = get_remote_ip(request)
remote_ip = get_client_ip(request) or '255.255.255.255.'
ip_score, _ = IPReputation.objects.update_or_create(ip=remote_ip)
ip_score.score += amount
ip_score.save()

View file

@ -1,70 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-16 18:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/oauth2_provider/authorize.html:18
msgid "SSO - Authorize External Source"
msgstr ""
#: templates/oauth2_provider/authorize.html:29
#, python-format
msgid ""
"\n"
" You're about to sign into %(remote)s\n"
" "
msgstr ""
#: templates/oauth2_provider/authorize.html:33
msgid "Application requires following permissions"
msgstr ""
#: templates/oauth2_provider/authorize.html:42
#, python-format
msgid ""
"\n"
" You are logged in as %(user)s. Not you?\n"
" "
msgstr ""
#: templates/oauth2_provider/authorize.html:45
msgid "Logout"
msgstr ""
#: templates/oauth2_provider/authorize.html:49
msgid "Continue"
msgstr ""
#: templates/oauth2_provider/authorize.html:52
msgid "Cancel"
msgstr ""
#: templates/oauth2_provider/authorize.html:59
#, python-format
msgid "Error: %(err)s"
msgstr ""
#: views/oauth2.py:49
#, python-format
msgid "You authenticated %s (via OAuth) (skipped Authz)"
msgstr ""
#: views/oauth2.py:62
#, python-format
msgid "You authenticated %s (via OAuth)"
msgstr ""

View file

@ -1,69 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-20 10:47+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: templates/oauth2_provider/authorize.html:18
msgid "SSO - Authorize External Source"
msgstr ""
#: templates/oauth2_provider/authorize.html:29
#, python-format
msgid ""
"\n"
" You're about to sign into %(remote)s\n"
" "
msgstr ""
#: templates/oauth2_provider/authorize.html:33
msgid "Application requires following permissions"
msgstr ""
#: templates/oauth2_provider/authorize.html:42
#, python-format
msgid ""
"\n"
" You are logged in as %(user)s. Not you?\n"
" "
msgstr ""
#: templates/oauth2_provider/authorize.html:45
msgid "Logout"
msgstr ""
#: templates/oauth2_provider/authorize.html:49
msgid "Continue"
msgstr ""
#: templates/oauth2_provider/authorize.html:52
msgid "Cancel"
msgstr ""
#: templates/oauth2_provider/authorize.html:59
#, python-format
msgid "Error: %(err)s"
msgstr ""
#: views/oauth2.py:49
#, python-format
msgid "You authenticated %s (via OAuth) (skipped Authz)"
msgstr ""
#: views/oauth2.py:62
#, python-format
msgid "You authenticated %s (via OAuth)"
msgstr ""

View file

@ -1,70 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-16 18:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/oauth2_provider/authorize.html:18
msgid "SSO - Authorize External Source"
msgstr ""
#: templates/oauth2_provider/authorize.html:29
#, python-format
msgid ""
"\n"
" You're about to sign into %(remote)s\n"
" "
msgstr ""
#: templates/oauth2_provider/authorize.html:33
msgid "Application requires following permissions"
msgstr ""
#: templates/oauth2_provider/authorize.html:42
#, python-format
msgid ""
"\n"
" You are logged in as %(user)s. Not you?\n"
" "
msgstr ""
#: templates/oauth2_provider/authorize.html:45
msgid "Logout"
msgstr ""
#: templates/oauth2_provider/authorize.html:49
msgid "Continue"
msgstr ""
#: templates/oauth2_provider/authorize.html:52
msgid "Cancel"
msgstr ""
#: templates/oauth2_provider/authorize.html:59
#, python-format
msgid "Error: %(err)s"
msgstr ""
#: views/oauth2.py:49
#, python-format
msgid "You authenticated %s (via OAuth) (skipped Authz)"
msgstr ""
#: views/oauth2.py:62
#, python-format
msgid "You authenticated %s (via OAuth)"
msgstr ""

View file

@ -1,70 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-16 18:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: templates/oauth2_provider/authorize.html:18
msgid "SSO - Authorize External Source"
msgstr ""
#: templates/oauth2_provider/authorize.html:29
#, python-format
msgid ""
"\n"
" You're about to sign into %(remote)s\n"
" "
msgstr ""
#: templates/oauth2_provider/authorize.html:33
msgid "Application requires following permissions"
msgstr ""
#: templates/oauth2_provider/authorize.html:42
#, python-format
msgid ""
"\n"
" You are logged in as %(user)s. Not you?\n"
" "
msgstr ""
#: templates/oauth2_provider/authorize.html:45
msgid "Logout"
msgstr ""
#: templates/oauth2_provider/authorize.html:49
msgid "Continue"
msgstr ""
#: templates/oauth2_provider/authorize.html:52
msgid "Cancel"
msgstr ""
#: templates/oauth2_provider/authorize.html:59
#, python-format
msgid "Error: %(err)s"
msgstr ""
#: views/oauth2.py:49
#, python-format
msgid "You authenticated %s (via OAuth) (skipped Authz)"
msgstr ""
#: views/oauth2.py:62
#, python-format
msgid "You authenticated %s (via OAuth)"
msgstr ""

View file

@ -8,7 +8,7 @@ from django.utils.translation import ugettext as _
from oauth2_provider.views.base import AuthorizationView
from structlog import get_logger
from passbook.audit.models import Event
from passbook.audit.models import Event, EventAction
from passbook.core.models import Application
from passbook.core.views.access import AccessMixin
from passbook.core.views.utils import LoadingView, PermissionDeniedView
@ -77,9 +77,8 @@ class PassbookAuthorizationView(AccessMixin, AuthorizationView):
def form_valid(self, form):
# User has clicked on "Authorize"
Event.create(
action=Event.ACTION_AUTHORIZE_APPLICATION,
request=self.request,
app=str(self._application))
LOGGER.debug('user %s authorized %s', self.request.user, self._application)
Event.new(EventAction.AUTHORIZE_APPLICATION,
authorized_application=self._application).from_http(self.request)
LOGGER.debug('User authorized Application',
user=self.request.user, application=self._application)
return super().form_valid(form)

View file

@ -3,7 +3,7 @@ from django.contrib import messages
from django.shortcuts import redirect
from structlog import get_logger
from passbook.audit.models import Event
from passbook.audit.models import Event, EventAction
from passbook.core.models import Application
from passbook.policies.engine import PolicyEngine
@ -28,9 +28,7 @@ def check_permissions(request, user, client):
messages.error(request, policy_message)
return redirect('passbook_providers_oauth:oauth2-permission-denied')
Event.create(
action=Event.ACTION_AUTHORIZE_APPLICATION,
request=request,
app=application.name,
skipped_authorization=False)
Event.new(EventAction.AUTHORIZE_APPLICATION,
authorized_application=application,
skipped_authorization=False).from_http(request)
return None

View file

@ -13,7 +13,7 @@ from django.views.decorators.csrf import csrf_exempt
from signxml.util import strip_pem_header
from structlog import get_logger
from passbook.audit.models import Event
from passbook.audit.models import Event, EventAction
from passbook.core.models import Application
from passbook.lib.mixins import CSRFExemptMixin
from passbook.lib.utils.template import render_to_string
@ -123,11 +123,9 @@ class LoginProcessView(AccessRequiredView):
if self.provider.application.skip_authorization:
ctx = self.provider.processor.generate_response()
# Log Application Authorization
Event.create(
action=Event.ACTION_AUTHORIZE_APPLICATION,
request=request,
app=self.provider.application.name,
skipped_authorization=True)
Event.new(EventAction.AUTHORIZE_APPLICATION,
authorized_application=self.provider.application,
skipped_authorization=True).from_http(request)
return RedirectToSPView.as_view()(
request=request,
acs_url=ctx['acs_url'],
@ -145,11 +143,9 @@ class LoginProcessView(AccessRequiredView):
# Check if user has access
if request.POST.get('ACSUrl', None):
# User accepted request
Event.create(
action=Event.ACTION_AUTHORIZE_APPLICATION,
request=request,
app=self.provider.application.name,
skipped_authorization=False)
Event.new(EventAction.AUTHORIZE_APPLICATION,
authorized_application=self.provider.application,
skipped_authorization=False).from_http(request)
return RedirectToSPView.as_view()(
request=request,
acs_url=request.POST.get('ACSUrl'),

View file

@ -108,13 +108,6 @@ GUARDIAN_MONKEY_PATCH = False
SWAGGER_SETTINGS = {
'DEFAULT_INFO': 'passbook.api.v2.urls.info',
# 'SECURITY_DEFINITIONS': {
# 'JWT': {
# 'type': 'apiKey',
# 'name': 'Authorization',
# 'in': 'header'
# }
# }
}
REST_FRAMEWORK = {

View file

@ -32,7 +32,7 @@ for _passbook_app in get_apps():
urlpatterns += [
# Administration
path('administration/django/', admin.site.urls),
path('metrics/', MetricsView.as_view(), name='metrics')
path('metrics', MetricsView.as_view(), name='metrics')
]
if settings.DEBUG:

View file

@ -12,6 +12,8 @@ from time import time
from django.core.wsgi import get_wsgi_application
from structlog import get_logger
from passbook.lib.utils.http import _get_client_ip_from_meta
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "passbook.root.settings")
class WSGILogger:
@ -44,8 +46,7 @@ class WSGILogger:
retval = self.application(environ, custom_start_response)
runtime = int((time() - start) * 10**6)
content_length = content_lengths[0] if content_lengths else 0
self.log(status_codes[0], environ, content_length,
ip_header=None, runtime=runtime)
self.log(status_codes[0], environ, content_length, runtime=runtime)
return retval
def log(self, status_code, environ, content_length, **kwargs):
@ -54,11 +55,7 @@ class WSGILogger:
"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
see http://httpd.apache.org/docs/current/mod/mod_log_config.html#formats
"""
ip_header = kwargs.get('ip_header', None)
if ip_header:
host = environ.get(ip_header, '')
else:
host = environ.get('REMOTE_ADDR', '')
host = _get_client_ip_from_meta(environ)
query_string = ''
if environ.get('QUERY_STRING') != '':
query_string = f"?{environ.get('QUERY_STRING')}"

View file

@ -1,80 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-16 18:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/mod/auth/oauth/client/settings.html:11
msgid "OAuth2"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:16
msgid "Connected Accounts"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:23
msgid "Provider"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:24
msgid "Status"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:25
msgid "Action"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:26
msgid "ID"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:48
msgid "No Providers configured!"
msgstr ""
#: views/core.py:126
#, python-format
msgid "Provider %(name)s didn't provide an E-Mail address."
msgstr ""
#: views/core.py:184 views/core.py:225
#, python-format
msgid "Successfully authenticated with %(provider)s!"
msgstr ""
#: views/core.py:192
msgid "Authentication Failed."
msgstr ""
#: views/core.py:204
#, python-format
msgid "Linked user with OAuth Provider %s"
msgstr ""
#: views/core.py:208
#, python-format
msgid "Successfully linked %(provider)s!"
msgstr ""
#: views/core.py:221
#, python-format
msgid "Authenticated user with OAuth Provider %s"
msgstr ""
#: views/core.py:247
msgid "Connection successfully deleted"
msgstr ""

View file

@ -1,79 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-20 10:47+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: templates/mod/auth/oauth/client/settings.html:11
msgid "OAuth2"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:16
msgid "Connected Accounts"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:23
msgid "Provider"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:24
msgid "Status"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:25
msgid "Action"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:26
msgid "ID"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:48
msgid "No Providers configured!"
msgstr ""
#: views/core.py:126
#, python-format
msgid "Provider %(name)s didn't provide an E-Mail address."
msgstr ""
#: views/core.py:184 views/core.py:225
#, python-format
msgid "Successfully authenticated with %(provider)s!"
msgstr ""
#: views/core.py:192
msgid "Authentication Failed."
msgstr ""
#: views/core.py:204
#, python-format
msgid "Linked user with OAuth Provider %s"
msgstr ""
#: views/core.py:208
#, python-format
msgid "Successfully linked %(provider)s!"
msgstr ""
#: views/core.py:221
#, python-format
msgid "Authenticated user with OAuth Provider %s"
msgstr ""
#: views/core.py:247
msgid "Connection successfully deleted"
msgstr ""

View file

@ -1,80 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-16 18:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/mod/auth/oauth/client/settings.html:11
msgid "OAuth2"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:16
msgid "Connected Accounts"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:23
msgid "Provider"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:24
msgid "Status"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:25
msgid "Action"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:26
msgid "ID"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:48
msgid "No Providers configured!"
msgstr ""
#: views/core.py:126
#, python-format
msgid "Provider %(name)s didn't provide an E-Mail address."
msgstr ""
#: views/core.py:184 views/core.py:225
#, python-format
msgid "Successfully authenticated with %(provider)s!"
msgstr ""
#: views/core.py:192
msgid "Authentication Failed."
msgstr ""
#: views/core.py:204
#, python-format
msgid "Linked user with OAuth Provider %s"
msgstr ""
#: views/core.py:208
#, python-format
msgid "Successfully linked %(provider)s!"
msgstr ""
#: views/core.py:221
#, python-format
msgid "Authenticated user with OAuth Provider %s"
msgstr ""
#: views/core.py:247
msgid "Connection successfully deleted"
msgstr ""

View file

@ -1,80 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-16 18:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: templates/mod/auth/oauth/client/settings.html:11
msgid "OAuth2"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:16
msgid "Connected Accounts"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:23
msgid "Provider"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:24
msgid "Status"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:25
msgid "Action"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:26
msgid "ID"
msgstr ""
#: templates/mod/auth/oauth/client/settings.html:48
msgid "No Providers configured!"
msgstr ""
#: views/core.py:126
#, python-format
msgid "Provider %(name)s didn't provide an E-Mail address."
msgstr ""
#: views/core.py:184 views/core.py:225
#, python-format
msgid "Successfully authenticated with %(provider)s!"
msgstr ""
#: views/core.py:192
msgid "Authentication Failed."
msgstr ""
#: views/core.py:204
#, python-format
msgid "Linked user with OAuth Provider %s"
msgstr ""
#: views/core.py:208
#, python-format
msgid "Successfully linked %(provider)s!"
msgstr ""
#: views/core.py:221
#, python-format
msgid "Authenticated user with OAuth Provider %s"
msgstr ""
#: views/core.py:247
msgid "Connection successfully deleted"
msgstr ""

View file

@ -11,8 +11,8 @@ from django.utils.translation import ugettext as _
from django.views.generic import RedirectView, View
from structlog import get_logger
from passbook.audit.models import Event, EventAction
from passbook.factors.view import AuthenticationView, _redirect_with_qs
from passbook.lib.utils.reflection import app
from passbook.sources.oauth.clients import get_client
from passbook.sources.oauth.models import (OAuthSource,
UserOAuthSourceConnection)
@ -180,17 +180,8 @@ class OAuthCallback(OAuthClientMixin, View):
access.user = user
access.save()
UserOAuthSourceConnection.objects.filter(pk=access.pk).update(user=user)
if app('passbook_audit'):
pass
# TODO: Create audit entry
# from passbook.audit.models import something
# something.event(user=user,)
# Event.create(
# user=user,
# message=_("Linked user with OAuth source %s" % self.source.name),
# request=self.request,
# hidden=True,
# current=False)
Event.new(EventAction.CUSTOM, message="Linked OAuth Source",
source=source).from_http(self.request)
if was_authenticated:
messages.success(self.request, _("Successfully linked %(source)s!" % {
'source': self.source.name

View file

@ -1,66 +0,0 @@
#XXX: Use svn:externals to get the same version as in saml2idp???
"""
Signing code goes here.
"""
# # python:
# import hashlib
# import string
from structlog import get_logger
# other libraries:
# this app:
# from passbook.providers.saml.utils import nice64
# from passbook.sources.saml.xml_templates import SIGNATURE, SIGNED_INFO
LOGGER = get_logger()
# def get_signature_xml(subject, reference_uri):
# """
# Returns XML Signature for subject.
# """
# private_key_file = saml2sp_settings.SAML2SP_PRIVATE_KEY_FILE
# certificate_file = saml2sp_settings.SAML2SP_CERTIFICATE_FILE
# LOGGER.debug('get_signature_xml - Begin.')
# LOGGER.debug('Using private key file: ' + private_key_file)
# LOGGER.debug('Using certificate file: ' + certificate_file)
# LOGGER.debug('Subject: ' + subject)
# # Hash the subject.
# subject_hash = hashlib.sha1()
# subject_hash.update(subject)
# subject_digest = nice64(subject_hash.digest())
# LOGGER.debug('Subject digest: ' + subject_digest)
# # Create signed_info.
# signed_info = string.Template(SIGNED_INFO).substitute({
# 'REFERENCE_URI': reference_uri,
# 'SUBJECT_DIGEST': subject_digest,
# })
# LOGGER.debug('SignedInfo XML: ' + signed_info)
# # # "Digest" the signed_info.
# # info_hash = hashlib.sha1()
# # info_hash.update(signed_info)
# # info_digest = info_hash.digest()
# # LOGGER.debug('Info digest: ' + nice64(info_digest))
# # RSA-sign the signed_info.
# private_key = M2Crypto.EVP.load_key(private_key_file)
# private_key.sign_init()
# private_key.sign_update(signed_info)
# rsa_signature = nice64(private_key.sign_final())
# LOGGER.debug('RSA Signature: ' + rsa_signature)
# # Load the certificate.
# cert_data = load_cert_data(certificate_file)
# # Put the signed_info and rsa_signature into the XML signature.
# signed_info_short = signed_info.replace('xmlns:ds="http://www.w3.org/2000/09/xmldsig#"', '')
# signature_xml = string.Template(SIGNATURE).substitute({
# 'RSA_SIGNATURE': rsa_signature,
# 'SIGNED_INFO': signed_info_short,
# 'CERTIFICATE': cert_data,
# })
# LOGGER.debug('Signature XML: ' + signature_xml)
# return signature_xml

5
scripts/coverage.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash -xe
coverage run --concurrency=multiprocessing manage.py test
coverage combine
coverage html
coverage report

5
scripts/pre-commit.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash -xe
scripts/coverage.sh
isort
pylint passbook
prospector