Compare commits

..

369 Commits

Author SHA1 Message Date
Langhammer, Jens
e70d3b6286 new release: 0.6.3-beta 2019-10-09 14:44:50 +02:00
Langhammer, Jens
17e6bc921b core(minor): fix import order 2019-10-09 14:37:40 +02:00
Langhammer, Jens
46111e7cac deploy(minor): downgrade kombu to fix redis error
https://github.com/celery/kombu/issues/1063
2019-10-09 14:32:20 +02:00
Langhammer, Jens
3b7e47dbe2 settings(minor): use cached_db for session, use localhost as domain 2019-10-09 14:30:53 +02:00
Langhammer, Jens
fff99f0e3d deploy(minor): use SERVER_TAG, fix static container 2019-10-09 14:29:44 +02:00
Langhammer, Jens
2e15b24f0a *(minor): switch has_user_settings to return Optional dataclass instead of tuple 2019-10-09 12:47:14 +02:00
Langhammer, Jens
088b9592cd core(minor): remove unused code 2019-10-08 15:04:38 +02:00
Langhammer, Jens
b1e4e32b83 providers/oidc(minor): correctly create audit entry on authz 2019-10-08 14:34:59 +02:00
Langhammer, Jens
d91a852eda factors/email(minor): start rebuilding email integration as factor 2019-10-08 14:30:17 +02:00
Langhammer, Jens
171c5b9759 factors/password(minor): remove form from core 2019-10-08 14:23:02 +02:00
Langhammer, Jens
64290b2a37 admin(minor): add view to create user 2019-10-08 11:27:19 +02:00
Langhammer, Jens
72769b8a0a lib(minor): cleanup default settings 2019-10-08 10:44:44 +02:00
Langhammer, Jens
1018309413 helm(minor): cleanup configmap, move secret_key to k8s secret 2019-10-08 10:44:25 +02:00
Jens Langhammer
6d0ecd228e new release: 0.6.2-beta 2019-10-07 21:24:56 +02:00
Jens Langhammer
40a651e66c docker(minor): ensure passbook user can write 2019-10-07 21:23:38 +02:00
Jens Langhammer
a390bb7b59 factors/otp(minor): fix old URLs 2019-10-07 21:23:25 +02:00
Jens Langhammer
245ec65cbb helm(minor): remove default postgres password 2019-10-07 21:23:15 +02:00
Langhammer, Jens
17eea4a10c new release: 0.6.1-beta 2019-10-07 18:53:04 +02:00
Langhammer, Jens
862fb0f5d2 deploy(minor): deploy more servers with more resources 2019-10-07 18:41:43 +02:00
Langhammer, Jens
ec73b53340 providers/saml(minor): fix last wrong urls names 2019-10-07 18:36:09 +02:00
Langhammer, Jens
9110f7fee3 helm(minor): fix worker not starting correctly 2019-10-07 17:41:26 +02:00
Langhammer, Jens
54cc1fdeef helm(minor): re-add volumes 2019-10-07 17:22:35 +02:00
Langhammer, Jens
8f42a7f0b4 new release: 0.6.0-beta 2019-10-07 17:18:19 +02:00
Langhammer, Jens
2c221ea819 providers/oauth(minor): fix import order 2019-10-07 17:14:52 +02:00
Langhammer, Jens
93e0441b58 helm(minor): don't directly mount configmap 2019-10-07 17:14:08 +02:00
Langhammer, Jens
7f1455cb12 helm(minor): disable redis cluster & persistence by default 2019-10-07 17:01:27 +02:00
Langhammer, Jens
59fc223a85 factors/captcha(minor): load correct keys 2019-10-07 16:58:06 +02:00
Langhammer, Jens
0a6f555c23 otp(minor): disable autocomplete for code input 2019-10-07 16:57:54 +02:00
Langhammer, Jens
6a4233d6fd providers/oauth(minor): fix urls not being mounted in the right path 2019-10-07 16:57:36 +02:00
Langhammer, Jens
15fa7e9652 ui(minor): merge menus 2019-10-07 16:50:13 +02:00
Langhammer, Jens
f2acc154cd *(minor): small refactor 2019-10-07 16:33:48 +02:00
Langhammer, Jens
d21ec6c9a5 root(minor): get rid of duplicate settings 2019-10-04 16:09:35 +02:00
Langhammer, Jens
43dd858cd5 ci(minor): fix from in dockerfile 2019-10-04 14:04:51 +02:00
Langhammer, Jens
34cbf5f702 new release: 0.5.0-beta 2019-10-04 13:55:13 +02:00
Langhammer, Jens
3c6e94b6a8 ci(minor): fix path in bumpversion config 2019-10-04 13:55:12 +02:00
Langhammer, Jens
1cd149c815 policy(minor): fix linting 2019-10-04 13:49:27 +02:00
Langhammer, Jens
4c6f562805 policy(minor): fix deadlock issue 2019-10-04 13:44:26 +02:00
Langhammer, Jens
e59c4ec1c7 root(minor): cleanup, remove unused log 2019-10-04 13:43:47 +02:00
Langhammer, Jens
1169db7530 docker(minor): move docker-related files into separate folder 2019-10-04 12:45:19 +02:00
Langhammer, Jens
1453008796 wsgi(minor): add proper request logging 2019-10-04 12:44:59 +02:00
Langhammer, Jens
2209b6d603 deploy(minor): fix robots.txt not being in the right path
fix path matching in docker compose
2019-10-04 12:01:38 +02:00
Langhammer, Jens
ccbc0384f9 deploy(minor): remove app-gw, add robots.txt 2019-10-04 11:57:41 +02:00
Langhammer, Jens
a48924c896 docker(minor): switch to debian based image so we can use wheels 2019-10-04 11:50:52 +02:00
Langhammer, Jens
dc8d8dd2b6 deploy(minor): add docker-compose file for easy testing 2019-10-04 11:50:26 +02:00
Langhammer, Jens
afca94ceb8 policy(minor): improve loading of policy subclasses 2019-10-04 10:22:06 +02:00
Langhammer, Jens
0b86231a36 *(minor): make better use of structured logging 2019-10-04 10:21:33 +02:00
Langhammer, Jens
c0df1f38b8 *(minor): remove __name__ param from get_logger 2019-10-04 10:08:53 +02:00
Langhammer, Jens
2b8fed8f4e saml_idp(minor): rewrite to use defusedxml instead of bs4 2019-10-04 09:50:25 +02:00
Langhammer, Jens
c7322a32a0 app_gw(minor): remove current implementation 2019-10-04 09:28:28 +02:00
Jens Langhammer
64b75cab84 policy(minor): add data class for policy request 2019-10-03 10:45:31 +02:00
Jens Langhammer
f58bc61999 new release: 0.4.2-beta 2019-10-02 21:05:51 +00:00
Jens Langhammer
fb8ccc0283 lint(minor): fix import order 2019-10-02 21:05:37 +00:00
Jens Langhammer
c38012f147 new release: 0.4.1-beta 2019-10-02 21:04:16 +00:00
Jens Langhammer
3676ff21c2 helm(minor): use postgres 4.2.2 2019-10-02 21:03:39 +00:00
Jens Langhammer
920e705d75 policy(minor): lookup correct policy subclass 2019-10-02 22:28:58 +02:00
Jens Langhammer
de0b137b1e policy(minor): improve error handling 2019-10-02 22:28:39 +02:00
Jens Langhammer
d44ac6e2a3 static(minor): fix build path for static image 2019-10-02 22:16:48 +02:00
Jens Langhammer
71039a4012 helm(minor): fix p2 to passbook 2019-10-02 22:16:32 +02:00
Langhammer, Jens
8745ac7932 new release: 0.4.0-beta 2019-10-01 17:01:30 +02:00
Langhammer, Jens
7f70048423 ci(minor): disable pylint since its currently broken upstream 2019-10-01 16:53:09 +02:00
Langhammer, Jens
97dbfc8885 req(minor): fix dependency issue by downgrading prospector 2019-10-01 15:54:29 +02:00
Langhammer, Jens
149ea22a93 k8s(minor): switch to uwsgi 2019-10-01 15:43:06 +02:00
Langhammer, Jens
404ed5406d k8s(minor): remove passwords from configmap 2019-10-01 15:42:55 +02:00
Langhammer, Jens
b8656858ec k8s(minor): load secrets as env vars 2019-10-01 15:42:14 +02:00
Langhammer, Jens
6b0f0e8993 deploy(minor): use 5.x postgresql chart for psql 10.x 2019-10-01 15:33:43 +02:00
Langhammer, Jens
aec1ccd88d root(minor): fix redis password not being loaded 2019-10-01 15:30:35 +02:00
Langhammer, Jens
bee5c200b6 docker(minor): fix static build failing 2019-10-01 15:30:22 +02:00
Langhammer, Jens
9d640efc88 new release: 0.3.0-beta 2019-10-01 13:50:50 +02:00
Langhammer, Jens
f0907841dd docker(minor): remove virtualenv from pipenv 2019-10-01 13:50:37 +02:00
Langhammer, Jens
2bffc12ef9 ci(minor): fix default settings so CI works 2019-10-01 13:22:38 +02:00
Langhammer, Jens
2ff9ec6522 ci(minor): fix not all packages being installed 2019-10-01 11:34:34 +02:00
Langhammer, Jens
43a54f5c54 ci(minor): install pipenv before testing 2019-10-01 11:12:59 +02:00
Langhammer, Jens
7bff2734aa lint(minor): fix all remaining pylint and prospector errors 2019-10-01 11:08:56 +02:00
Langhammer, Jens
84768c0ec6 helm(minor): remove rabbitmq 2019-10-01 10:48:55 +02:00
Langhammer, Jens
f4499a5459 *(minor): stdlib logging to structlog 2019-10-01 10:24:10 +02:00
Langhammer, Jens
b3aede5bba policy(minor): Move policy-related code to separate package 2019-10-01 10:17:39 +02:00
Langhammer, Jens
531ea1c039 build(minor): rename dockerfiles to be detected correctly 2019-09-30 18:05:42 +02:00
Langhammer, Jens
c2c5ff6912 config(minor): CONFIG.get -> CONFIG.y 2019-09-30 18:04:04 +02:00
Langhammer, Jens
9cddab8fd5 deploy(minor): switch to pipfile 2019-09-10 17:00:13 +02:00
Langhammer, Jens
06d15d8a27 new release: 0.2.8-beta 2019-07-22 17:18:07 +02:00
Langhammer, Jens
b5c711854b deploy: fix static deployment and static container 2019-07-22 17:17:53 +02:00
Langhammer, Jens
4cf6c36f34 new release: 0.2.7-beta 2019-07-22 15:54:34 +02:00
Langhammer, Jens
75a6f6c875 deploy: remove old files from bumpversion 2019-07-22 15:54:10 +02:00
Langhammer, Jens
62abe3f256 suspicious_policy: fix Request IP lookup 2019-07-22 15:46:41 +02:00
Langhammer, Jens
9296c41650 ci: add missing packaging dependency 2019-07-22 15:35:11 +02:00
Langhammer, Jens
7fb48fde6d deploy: add static deployment, add resource reservations/limits 2019-07-22 15:22:10 +02:00
Langhammer, Jens
174472bb45 all: get rid of individual requirements file, remove version from every module 2019-07-22 15:20:17 +02:00
Langhammer, Jens
17575ed921 deploy: rewrite docker files to be more stackable 2019-07-22 15:18:33 +02:00
Langhammer, Jens
b1b1a27444 client-packages: now deprecated 2019-07-22 15:17:58 +02:00
Jens Langhammer
f97a5eeefb api: *actually* fix drf dependency issue 2019-07-15 15:05:54 +00:00
Jens Langhammer
10fd96981e new release: 0.2.6-beta 2019-07-15 13:42:18 +00:00
Jens Langhammer
67e3eb549c api: fix wrong django-rest-framework dependency 2019-07-15 13:42:03 +00:00
Jens Langhammer
30a6d1f0b1 new release: 0.2.5-beta 2019-07-15 13:31:04 +00:00
Langhammer, Jens
3d1fa9f048 app_gw: Rewrite redirect responses (replace upstream location with server_name) 2019-07-09 15:28:52 +02:00
Jens Langhammer
1d2be6e68b root: fix sentry sending wrong release 2019-07-05 16:00:01 +02:00
Jens Langhammer
c21e343986 oidc_provider: fix error when creating a new provider 2019-07-05 15:59:52 +02:00
Jens Langhammer
ff37ed095c new release: 0.2.4-beta 2019-07-05 15:30:13 +02:00
Jens Langhammer
8623a2c3fc oidc_provider: fix error trying to create RSA Key before migrations are run 2019-07-05 15:27:04 +02:00
Jens Langhammer
23d277eaf1 remove oidc from OAuth2, add dedicated OIDC provider 2019-07-05 15:21:48 +02:00
Jens Langhammer
75ced59451 helm: fix syntax error 2019-07-05 15:21:12 +02:00
Jens Langhammer
bccf424c5e new release: 0.2.3-beta 2019-07-04 16:25:33 +02:00
Jens Langhammer
2f9ae40d20 client-sentry: fix 400 failing upload 2019-07-04 16:25:17 +02:00
Jens Langhammer
11e1eec3fb ci: fix new dependencies not being installed on the fly 2019-07-04 16:21:35 +02:00
Jens Langhammer
765c5633df helm: add appgw to ingress 2019-07-04 16:07:16 +02:00
Jens Langhammer
6344b1aafb helm: add deployment for appgw 2019-07-04 15:25:36 +02:00
Jens Langhammer
ed25801e6e core: revert to cherrypy for main webserver and use daphne only for app_gw 2019-07-04 15:23:05 +02:00
Jens Langhammer
4d0148193f root: migrate to new sentry instance 2019-07-03 17:35:54 +02:00
Jens Langhammer
804ae15c2e new release: 0.2.2-beta 2019-06-25 18:50:41 +02:00
Jens Langhammer
b35a9fad86 Fix linting errors with current build-base image 2019-06-25 18:50:37 +02:00
Jens Langhammer
a4f83bd28a new release: 0.2.1-beta 2019-06-25 18:25:27 +02:00
Jens Langhammer
796f83c3d0 Fix requirements file importing wrong path 2019-06-25 18:24:07 +02:00
Jens Langhammer
2099bbb713 new release: 0.2.0-beta 2019-06-25 18:16:14 +02:00
Jens Langhammer
67beba8f78 Fix wrong URLConf being loaded 2019-06-25 18:11:08 +02:00
Jens Langhammer
a798412e17 separate passbook.core into passbook.root and passbook.core
Move Main Django Project into passbook.root while passbook.core holds core functionality.

passbook.root contains main settings, ASGI & WSGI, celery and URLs.
2019-06-25 18:00:54 +02:00
Jens Langhammer
3b2c2d781f Fix typo 2019-06-25 17:59:51 +02:00
Jens Langhammer
98c844f3d6 improve OIDC compatibility 2019-06-25 17:57:25 +02:00
Jens Langhammer
2645bd0132 new release: 0.1.38-beta 2019-04-29 23:26:18 +02:00
Jens Langhammer
2c4fc56b49 Merge branch '27-rewrite-oauth-client-as-factor' into 'master'
Resolve "Rewrite OAuth Client as Factor"

Closes #27

See merge request BeryJu.org/passbook!14
2019-04-29 21:25:04 +00:00
Jens Langhammer
0ec1468058 remove unused import 2019-04-29 23:22:54 +02:00
Jens Langhammer
5d1a3043b2 create SSOLoginPolicy, which allows factors to be applied when user comes from SSO login
implement SESSIION_IS_SSO_LOGIN for OAuth Client and core MFA
2019-04-29 23:19:37 +02:00
Jens Langhammer
b46958d1f9 send session to task 2019-04-29 23:18:51 +02:00
Jens Langhammer
5daa8d5fe3 fix missing/wrong widget inputs 2019-04-29 23:16:04 +02:00
Jens Langhammer
31846f1d05 Show redirect URL in <pre> element 2019-04-29 22:32:22 +02:00
Jens Langhammer
1fac964b8b increase application close timeout 2019-04-29 22:19:26 +02:00
Jens Langhammer
dfa6ed8ac2 add help to show how SAML Property Mapping substitutes variables 2019-04-29 22:19:13 +02:00
Jens Langhammer
66fe10299e new release: 0.1.37-beta 2019-04-29 21:43:18 +02:00
Jens Langhammer
e0a3ec033f fix IDP-Initiated SAML Login 2019-04-29 21:39:41 +02:00
Jens Langhammer
7033ec0ab9 remove debug print 2019-04-29 21:39:30 +02:00
Jens Langhammer
4004579905 remove nexus_upload command 2019-04-29 21:39:16 +02:00
Jens Langhammer
9fe9e48a5c new release: 0.1.36-beta 2019-04-29 20:57:57 +02:00
Jens Langhammer
595a6c7fe6 remove guardian completely 2019-04-29 20:57:54 +02:00
Jens Langhammer
11b5860d4a new release: 0.1.35-beta 2019-04-29 20:47:32 +02:00
Jens Langhammer
9bdbff4cda fix gitlab-ci using incorrect variables for docker access 2019-04-29 20:42:24 +02:00
Jens Langhammer
e0d597eeac show cache on admin overview, add modal to clear cache, re-add logging to policy 2019-04-29 20:37:44 +02:00
Jens Langhammer
f576985cc9 remove django guardian and check application access via PolicyEngine 2019-04-29 20:07:18 +02:00
Jens Langhammer
22a6aef60b fix wrong import 2019-04-29 20:06:52 +02:00
Jens Langhammer
ec0a6e7854 new release: 0.1.34-beta 2019-04-29 19:22:20 +02:00
Jens Langhammer
6904608e6f fix clicking on administration always loading admin interface 2019-04-29 19:22:14 +02:00
Jens Langhammer
cb3732cb2b filter out connection errors for sentry 2019-04-29 19:16:49 +02:00
Jens Langhammer
57de6cbafc repo cleanup, switch to new docker registry 2019-04-29 17:05:39 +02:00
Jens Langhammer
b1dda764a9 Merge branch 'master' of git.beryju.org:BeryJu.org/passbook
# Conflicts:
#	debian/etc/passbook/config.yml
#	helm/passbook/templates/passbook-configmap.yaml
2019-04-18 11:34:13 +02:00
Jens Langhammer
5ec2102487 Merge branch '39-saml-audience-as-database-field' into 'master'
Resolve "SAML: Audience as Database field"

Closes #39

See merge request BeryJu.org/passbook!25
2019-04-18 09:31:56 +00:00
Jens Langhammer
9f8fb7378a add audience field, switch base processor, better handle processor loading failure 2019-04-18 11:30:21 +02:00
Jens Langhammer
98cd646044 remove unneeded processors 2019-04-18 11:09:12 +02:00
Jens Langhammer
0cba1b4c45 fix SAML RancherProcessor not being loaded by default 2019-04-18 11:01:44 +02:00
Jens Langhammer
53918462b6 new release: 0.1.33-beta 2019-04-18 10:28:12 +02:00
Jens Langhammer
8a7e74b523 better release commit messages 2019-04-18 10:28:09 +02:00
Jens Langhammer
4dc7065e97 prepare 0.1.33 2019-04-18 10:25:22 +02:00
Jens Langhammer
3c93bb9f9f remove included CI file 2019-04-18 10:18:47 +02:00
Jens Langhammer
8143fae2d6 switch to custom CI base image with dependencies installed 2019-04-18 10:15:44 +02:00
Jens Langhammer
3cfe45d3cb fix broken icon for helm chart 2019-04-17 17:53:56 +02:00
Jens Langhammer
8e5c3f2f31 remove unused import 2019-04-17 17:53:45 +02:00
Jens Langhammer
5a3b2fdd49 add Rancher SAML processor 2019-04-17 17:53:15 +02:00
Jens Langhammer
e47b9f0d57 fix SAML Request not being parsed all the time 2019-04-17 17:53:05 +02:00
Jens Langhammer
146dd747f1 fix EntityID being None in SAML Metadata 2019-04-17 17:52:24 +02:00
Jens Langhammer
f2ce56063b bump version: 0.1.31-beta -> 0.1.32-beta 2019-04-17 14:27:41 +02:00
Jens Langhammer
b26f378e4c prepare 0.1.32 2019-04-17 14:27:03 +02:00
Jens Langhammer
9072b836c6 automatically add response_type if not given in OAuth Request 2019-04-17 14:25:51 +02:00
Jens Langhammer
2fa57d064e bump version: 0.1.30-beta -> 0.1.31-beta 2019-04-13 17:58:09 +02:00
Jens Langhammer
146705c60a prepare 0.1.31-beta 2019-04-13 17:58:03 +02:00
Jens Langhammer
5029a99df6 Merge branch '37-guardian' into 'master'
Resolve "Guardian"

Closes #37

See merge request BeryJu.org/passbook!23
2019-04-13 15:56:54 +00:00
Jens Langhammer
e7129d18f6 fix inconsistent migrations 2019-04-13 17:52:11 +02:00
Jens Langhammer
d2bf9f81d6 remove raven middleware 2019-04-13 17:46:51 +02:00
Jens Langhammer
30acf0660b Merge branch 'master' into 37-guardian 2019-04-13 17:43:02 +02:00
Jens Langhammer
dda41af5c8 remove logging to increase speed, add more caching to policy and rewriter 2019-04-13 17:22:03 +02:00
Jens Langhammer
9b5b03647b move actual proxying logic to separate class 2019-04-13 16:05:11 +02:00
Jens Langhammer
940b3eb943 move logging to separate thread 2019-04-13 16:04:48 +02:00
Jens Langhammer
16eb629b71 only enable sentry when not DEBUG 2019-04-11 15:30:42 +02:00
Jens Langhammer
755045b226 try to fix app_gw being null 2019-04-11 15:30:07 +02:00
Jens Langhammer
61478db94e use global urllib Pools 2019-04-11 15:29:35 +02:00
Jens Langhammer
f69f959bdb allow setting authentication_header to empty string (disabling the header) 2019-04-11 15:29:01 +02:00
Jens Langhammer
146edb45d4 bump version: 0.1.29-beta -> 0.1.30-beta 2019-04-11 14:22:34 +02:00
Jens Langhammer
045a802365 don't use context manager in web command 2019-04-11 14:22:32 +02:00
Jens Langhammer
c90d8ddcff bump version: 0.1.28-beta -> 0.1.29-beta 2019-04-11 14:03:08 +02:00
Jens Langhammer
3ff2ec929f prepare 0.1.29 2019-04-11 14:03:05 +02:00
Jens Langhammer
a3ef26b7ad Run collectstatic before coverage, use autoreload on celery worker 2019-04-11 13:54:11 +02:00
Jens Langhammer
19cd1624c1 replace cherrypy with daphne 2019-04-11 13:43:49 +02:00
Jens Langhammer
366ef352c6 switch to whitenoise for static files 2019-04-11 13:43:08 +02:00
Jens Langhammer
a9031a6abc Add libpq-dev dependency so psycopg2 build works 2019-04-11 12:44:26 +02:00
Jens Langhammer
a1a5223b58 bump version: 0.1.27-beta -> 0.1.28-beta 2019-04-11 10:48:31 +02:00
Jens Langhammer
c723b0233f prepare 0.1.28 2019-04-11 10:48:28 +02:00
Jens Langhammer
b369eb28f1 set default log level to warn, fix clean_nonces not working 2019-04-11 10:43:13 +02:00
Jens Langhammer
9b8f390e31 Merge branch '38-websocket-proxying' into 'master'
Resolve "Websocket Proxying"

Closes #38

See merge request BeryJu.org/passbook!24
2019-04-10 20:42:24 +00:00
Jens Langhammer
11630c9a74 switch kubernetes deployment to daphne server 2019-04-10 22:38:25 +02:00
Jens Langhammer
c9ac10f6f6 Implement websocket proxy 2019-04-10 19:03:42 +02:00
Jens Langhammer
04d613cb28 Move code from django-revproxy to app_gw to fix cookie bug 2019-04-10 19:03:22 +02:00
Jens Langhammer
40866f9ecd Choose upstream more cleverly 2019-04-10 18:49:33 +02:00
Jens Langhammer
d8585eb872 trigger autoreload from config files 2019-04-10 18:48:55 +02:00
Jens Langhammer
15aaeda475 remove unused import 2019-04-10 18:47:21 +02:00
Jens Langhammer
8536ef9e23 Add guardian for Application permissions 2019-04-10 18:46:33 +02:00
Jens Langhammer
35b6bb6b3f fix failing CI 2019-04-09 17:26:53 +02:00
Jens Langhammer
eaa573c715 fully remove raven and switch WSGI and logging to sentry_sdk 2019-04-05 16:11:53 +02:00
Jens Langhammer
660972e303 add ability to have non-expiring nonces, clean up expired nonces 2019-04-04 21:49:10 +02:00
Jens Langhammer
a21012bf0c switch from raven to sentry_sdk 2019-04-04 21:48:50 +02:00
Jens Langhammer
8dbafa4bda fix allauth client's formatting 2019-04-04 21:47:28 +02:00
Jens Langhammer
80049413f0 bump version: 0.1.26-beta -> 0.1.27-beta 2019-03-22 14:51:13 +01:00
Jens Langhammer
2739442d4a prepare 0.1.27 2019-03-22 14:51:09 +01:00
Jens Langhammer
c679f0a67c bump version: 0.1.25-beta -> 0.1.26-beta 2019-03-22 12:48:00 +01:00
Jens Langhammer
d9a952dd03 prepare 0.1.26 2019-03-22 12:47:57 +01:00
Jens Langhammer
9a1a0f0aa8 Merge branch '35-better-error-templates' into 'master'
Resolve "Better Error templates"

Closes #35

See merge request BeryJu.org/passbook!20
2019-03-22 11:19:42 +00:00
Jens Langhammer
4d6bb60134 add custom template views 2019-03-22 12:16:30 +01:00
Jens Langhammer
80e6d59382 Merge branch '34-parsed-url-cached' into 'master'
Resolve "InvalidUpstream: Upstream URL scheme must be either 'http' or 'https' (https://ory1-esxi-prod-1.ory1.beryju.org)."

Closes #34

See merge request BeryJu.org/passbook!19
2019-03-22 09:58:44 +00:00
Jens Langhammer
81ac951872 validate upstream in form 2019-03-22 10:55:26 +01:00
Jens Langhammer
f33e553cfd always parse url instead of once 2019-03-22 10:55:04 +01:00
Jens Langhammer
9b0240dc26 bump version: 0.1.24-beta -> 0.1.25-beta 2019-03-21 16:50:00 +01:00
Jens Langhammer
c327310392 prepare 0.1.24-beta release 2019-03-21 16:49:57 +01:00
Jens Langhammer
457375287c Merge branch '30-application-security-gateway' into 'master'
Resolve "Application Security Gateway (Reverse Proxy)"

Closes #30

See merge request BeryJu.org/passbook!17
2019-03-21 15:41:34 +00:00
Jens Langhammer
7e87bfef5b validate server_name in form 2019-03-21 16:36:38 +01:00
Jens Langhammer
a7af5268de Invalidate cache when ApplicationGateway instance is saved 2019-03-21 16:27:37 +01:00
Jens Langhammer
6d916029bb implement actual Rewriting logic 2019-03-21 16:22:07 +01:00
Jens Langhammer
81fdcbadad add compiled regex to RewriteRule 2019-03-21 16:21:51 +01:00
Jens Langhammer
ec1e25fe71 cleanup property_mapping list 2019-03-21 16:21:11 +01:00
Jens Langhammer
b5306e4a94 Redirect to login on reverse proxy 2019-03-21 15:15:01 +01:00
Jens Langhammer
801b8a1e59 prevent ZeroDivisionError 2019-03-21 15:05:04 +01:00
Jens Langhammer
3a52059793 cleanup post-migration mess 2019-03-21 15:02:33 +01:00
Jens Langhammer
10b7d99b37 Merge branch 'master' into 30-application-security-gateway
# Conflicts:
#	passbook/core/policies.py
#	passbook/core/settings.py
2019-03-21 14:58:10 +01:00
Jens Langhammer
6be8d0cbb2 Better handle policy timeouts 2019-03-21 14:53:57 +01:00
Jens Langhammer
5b8e3689ec Check for policies in app_gw 2019-03-21 14:53:47 +01:00
Jens Langhammer
25a5d8f5da Don't use LoginRequired for PermissionDenied View 2019-03-21 14:53:38 +01:00
Jens Langhammer
883d439544 add timeout field to policy to prevent stuck policies 2019-03-21 14:48:51 +01:00
Jens Langhammer
1c3b5889e5 Merge branch '33-cache-policy-results' into 'master'
Resolve "Cache Policy Results"

Closes #33

See merge request BeryJu.org/passbook!18
2019-03-21 10:40:36 +00:00
Jens Langhammer
87012b65e1 add redis as service in CI for unittests 2019-03-21 11:35:40 +01:00
Jens Langhammer
29913773a7 invalidate cache when policy is saved 2019-03-21 11:29:11 +01:00
Jens Langhammer
0bc6a4fed4 explicitly use redis db 2019-03-21 11:28:57 +01:00
Jens Langhammer
4645d8353f utilise cache in PolicyEngine 2019-03-21 11:08:32 +01:00
Jens Langhammer
260c5555fa add redis dependency back in for caching 2019-03-21 11:08:08 +01:00
Jens Langhammer
6f7b917c38 bump version: 0.1.23-beta -> 0.1.24-beta 2019-03-20 23:00:33 +01:00
Jens Langhammer
1456ee6d3e prepare 0.1.24 2019-03-20 23:00:22 +01:00
Jens Langhammer
ae3d3d0295 fix TypeError: can only concatenate list (not "str") to list 2019-03-20 22:50:09 +01:00
Jens Langhammer
c23ceacd0b initial implementation of reverse proxy, using django-revproxy from within a middleware
add new config entry "primary_domain" which is used to set the cookie domain
2019-03-20 22:42:47 +01:00
Jens Langhammer
5155204283 Merge branch '32-automatically-set-owner-field-when-creating-oauth-provider' into 'master'
Resolve "Automatically set owner field when creating OAuth Provider"

Closes #32

See merge request BeryJu.org/passbook!16
2019-03-20 21:20:54 +00:00
Jens Langhammer
5509ec9b0f Merge branch '29-oauth-provider-add-extra-info-button-to-show-urls' into 'master'
Resolve "OAuth Provider: Add extra info button to show URLs"

Closes #29

See merge request BeryJu.org/passbook!15
2019-03-20 21:17:36 +00:00
Jens Langhammer
d6f9b2e47d remove user field from form. Closes #32 2019-03-20 20:09:27 +01:00
Jens Langhammer
67aa4aef11 add modal for OAuth Providers showing the URLs 2019-03-20 20:03:28 +01:00
Jens Langhammer
9e46c8bfec bump version: 0.1.22-beta -> 0.1.23-beta 2019-03-18 20:54:31 +01:00
Jens Langhammer
1eaa9b9733 prepare 0.1.23 2019-03-18 20:54:23 +01:00
Jens Langhammer
ee05834b69 Merge branch '28-openid-connect-discovery' into 'master'
set issuer to root address instead of well-known path

Closes #28

See merge request BeryJu.org/passbook!13
2019-03-18 19:52:13 +00:00
Jens Langhammer
fccc8f4959 set issuer to root address instead of well-known path 2019-03-18 20:42:32 +01:00
Jens Langhammer
c721620f96 Merge branch '28-openid-connect-discovery' into 'master'
Resolve "OpenID Connect Discovery support"

Closes #28

See merge request BeryJu.org/passbook!12
2019-03-18 19:42:08 +00:00
Jens Langhammer
c9f73d718e start implementing openid connect discovery 2019-03-18 20:35:11 +01:00
Jens Langhammer
bfa58be721 bump version: 0.1.21-beta -> 0.1.22-beta 2019-03-14 21:22:15 +01:00
Jens Langhammer
4bb602149e perapre 0.1.22 2019-03-14 21:20:55 +01:00
Jens Langhammer
81ab9092fc Fix OAuth Client's disconnect view having invalid URL names 2019-03-14 21:19:14 +01:00
Jens Langhammer
29d5962c4c add Azure AD Source 2019-03-14 21:18:55 +01:00
Jens Langhammer
5c75339946 point to correct icons 2019-03-14 21:18:13 +01:00
Jens Langhammer
4774d9a46c fix delete form not working 2019-03-14 21:17:41 +01:00
Jens Langhammer
dbe16ba4fd fix layout when on mobile viewport and scrolling 2019-03-14 21:17:28 +01:00
Jens Langhammer
6972cf00a0 move icons to single folder, cleanup 2019-03-14 21:17:07 +01:00
Jens Langhammer
0445be9712 fix missing debug template 2019-03-14 21:16:27 +01:00
Jens Langhammer
89dbdd9585 bump version: 0.1.20-beta -> 0.1.21-beta 2019-03-14 18:08:02 +01:00
Jens Langhammer
da88ce7150 prepare 0.1.21 2019-03-14 18:02:13 +01:00
Jens Langhammer
5f50fcfcf5 detect HTTPS from reverse proxy 2019-03-14 18:01:41 +01:00
Jens Langhammer
96be087221 add request debug view 2019-03-14 18:01:27 +01:00
Jens Langhammer
a53a269a8c bump version: 0.1.19-beta -> 0.1.20-beta 2019-03-13 16:51:43 +01:00
Jens Langhammer
59565a5286 prepare 0.1.20 2019-03-13 16:51:38 +01:00
Jens Langhammer
ae3c092238 add user settings for Sources 2019-03-13 16:49:30 +01:00
Jens Langhammer
e98e5e4e3e fix GitHub Pretend again 2019-03-13 15:52:05 +01:00
Jens Langhammer
d50c7ec8d4 bump version: 0.1.18-beta -> 0.1.19-beta 2019-03-13 15:16:48 +01:00
Jens Langhammer
c0fdf377d1 prepare 0.1.18 2019-03-13 15:14:36 +01:00
Jens Langhammer
70c11c8988 fix GitHub Pretend throwing a 500 error 2019-03-13 15:12:13 +01:00
Jens Langhammer
67b19becc1 fix API Call for sentry-client, add missing template 2019-03-13 14:27:34 +01:00
Jens Langhammer
ae64024ef4 bump version: 0.1.17-beta -> 0.1.18-beta 2019-03-13 11:31:05 +01:00
Jens Langhammer
e6571826cb adjust versions for client packages, auto build client-packages 2019-03-12 17:30:57 +01:00
Jens Langhammer
c621e61978 fix included yaml file 2019-03-12 17:19:13 +01:00
Jens Langhammer
3626fa4b98 add sentry client 2019-03-12 17:18:08 +01:00
Jens Langhammer
01b0eb159a fix Server Error when downloading metadata 2019-03-12 17:08:53 +01:00
Jens Langhammer
63aa48d981 bump version: 0.1.16-beta -> 0.1.17-beta 2019-03-12 15:55:18 +01:00
Jens Langhammer
2e0ba05d55 prepare 0.1.17 2019-03-12 15:55:14 +01:00
Jens Langhammer
b2ac57bb67 switch to vertical navigation 2019-03-12 13:35:09 +01:00
Jens Langhammer
4c22e5c2c8 don't use celery heartbeat, use TCP keepalive instead 2019-03-12 13:34:54 +01:00
Jens Langhammer
4a7b0ec8a9 remove Application.user_is_authorized 2019-03-12 10:56:01 +01:00
Jens Langhammer
330118249e bump version: 0.1.15-beta -> 0.1.16-beta 2019-03-11 21:35:11 +01:00
Jens Langhammer
8d4dabde02 finalize RabbitMQ replacement, update debian package, remove redis tgz 2019-03-11 21:35:06 +01:00
Jens Langhammer
cf7323c41b bump version: 0.1.14-beta -> 0.1.15-beta 2019-03-11 21:01:18 +01:00
Jens Langhammer
edd856df7d redis -> rabbitmq 2019-03-11 20:46:19 +01:00
Jens Langhammer
5e35859db6 bump version: 0.1.13-beta -> 0.1.14-beta 2019-03-11 11:44:34 +01:00
Jens Langhammer
acabb2df54 fix unittests 2019-03-11 11:44:12 +01:00
Jens Langhammer
e6376a05f7 bump version: 0.1.12-beta -> 0.1.13-beta 2019-03-11 11:31:12 +01:00
Jens Langhammer
1f45aff7ad prepare 0.1.13 2019-03-11 11:31:06 +01:00
Jens Langhammer
e1f1f617b6 fix UserChangePasswordView not requiring Login 2019-03-11 11:25:59 +01:00
Jens Langhammer
2690675dca allow custom email server for helm installs 2019-03-11 11:03:25 +01:00
Jens Langhammer
7529b51358 Fix DoesNotExist error when running PolicyEngine against None user 2019-03-11 10:52:50 +01:00
Jens Langhammer
c394066d99 bump version: 0.1.11-beta -> 0.1.12-beta 2019-03-11 09:51:00 +01:00
Jens Langhammer
9c585032ef prepare 0.1.12-beta 2019-03-11 09:50:57 +01:00
Jens Langhammer
d408031304 fix OAuth Authorization View not requiring authentication 2019-03-11 09:48:36 +01:00
Jens Langhammer
c47bc11ec0 disable automatic k8s deployment for now 2019-03-11 09:47:06 +01:00
Jens Langhammer
1deb094afe install updated helm release from local folder 2019-03-10 21:47:22 +01:00
Jens Langhammer
501fed1922 rewrite PasswordFactor to use backends setting instead of trying all backends 2019-03-10 21:47:08 +01:00
Jens Langhammer
ad8125ac1c bump version: 0.1.10-beta -> 0.1.11-beta 2019-03-10 19:56:30 +01:00
Jens Langhammer
b42a551fb2 prepare 0.1.11 2019-03-10 19:56:27 +01:00
Jens Langhammer
3256be23df Merge branch '23-groups' into 'master'
Resolve "Group Management"

Closes #23

See merge request BeryJu.org/passbook!9
2019-03-10 18:49:01 +00:00
Jens Langhammer
f7c0c0146a add LDAP Group Membership Policy 2019-03-10 19:45:16 +01:00
Jens Langhammer
e4baf8c21e Add Group Member policy 2019-03-10 19:32:18 +01:00
Jens Langhammer
364f040b36 always use FilteredSelectMultiple for many-to-many fields 2019-03-10 18:34:09 +01:00
Jens Langhammer
2b8c2b2346 use Django's Admin FilteredSelectMultiple for Group Membership 2019-03-10 18:06:06 +01:00
Jens Langhammer
5f861189e4 Merge branch 'master' into 23-groups
# Conflicts:
#	passbook/admin/templates/administration/base.html
2019-03-10 17:13:29 +01:00
Jens Langhammer
5e11b6687e automatically deploy after release 2019-03-10 17:08:33 +01:00
Jens Langhammer
c4b429825d fix helm labels being on deployments and not pods 2019-03-10 16:39:41 +01:00
Jens Langhammer
eebbae0677 bump version: 0.1.9-beta -> 0.1.10-beta 2019-03-10 15:54:50 +01:00
Jens Langhammer
42b30f4507 prepare 0.1.10 release 2019-03-10 15:53:38 +01:00
Jens Langhammer
0e425418df better show loading state when testing a policy 2019-03-10 15:46:49 +01:00
Jens Langhammer
7fe0300b86 Fix button on policy test page 2019-03-10 15:36:49 +01:00
Jens Langhammer
c012c6be5c fix k8s service routing http traffic to workers 2019-03-10 15:34:24 +01:00
Jens Langhammer
a5dc193cfd bump version: 0.1.8-beta -> 0.1.9-beta 2019-03-10 12:17:48 +01:00
Jens Langhammer
7507ad2620 Merge branch '24-impersonate' into 'master'
Resolve "Impersonate user"

Closes #24

See merge request BeryJu.org/passbook!11
2019-03-10 01:47:29 +00:00
Jens Langhammer
f1291fec8d add impersonation middleware, add to templates 2019-03-10 02:41:31 +01:00
Jens Langhammer
37aeeea239 slightly refactor Factor View, add more unittests 2019-03-10 02:08:09 +01:00
Jens Langhammer
0fa1fc86da add more Verbosity to PolicyEngine, rewrite SAML Authorisation check 2019-03-10 02:07:48 +01:00
Jens Langhammer
c3034ab9ac consistently using PolicyEngine 2019-03-10 02:07:18 +01:00
Jens Langhammer
76694e037a bump version: 0.1.7-beta -> 0.1.8-beta 2019-03-08 21:43:35 +01:00
Jens Langhammer
787db41cc3 prepare for 0.1.7 2019-03-08 21:43:33 +01:00
Jens Langhammer
74da3df7cd bump version: 0.1.6-beta -> 0.1.7-beta 2019-03-08 21:37:59 +01:00
Jens Langhammer
a6e435bd70 prepare debian changelog for 0.1.6 2019-03-08 21:37:55 +01:00
Jens Langhammer
c313b496aa Improve access control for saml 2019-03-08 21:30:16 +01:00
Jens Langhammer
a7eaa74191 fix MATCH_EXACT not working as intended 2019-03-08 21:20:38 +01:00
Jens Langhammer
11ecdc4fcf bump version: 0.1.5-beta -> 0.1.6-beta 2019-03-08 20:39:27 +01:00
Jens Langhammer
2f7781b67a fix captcha factor not loading keys from Factor class 2019-03-08 20:08:28 +01:00
Jens Langhammer
296d4f691a add passing property to PolicyEngine 2019-03-08 19:49:53 +01:00
Jens Langhammer
64033031b1 remove audit's login attempt 2019-03-08 19:45:50 +01:00
Jens Langhammer
9daff7608d fix password not getting set on user import 2019-03-08 19:45:41 +01:00
Jens Langhammer
0a4af80b9b fix static files missing for debian package 2019-03-08 16:41:52 +01:00
Jens Langhammer
a54adb05c4 bump version: 0.1.4-beta -> 0.1.5-beta 2019-03-08 16:03:52 +01:00
Jens Langhammer
43a389e596 Merge branch '22-custom-property-mapping' into 'master'
Resolve "Custom Property Mapping"

Closes #22

See merge request BeryJu.org/passbook!8
2019-03-08 15:03:08 +00:00
Jens Langhammer
2d7e8f1b50 add group administration 2019-03-08 15:49:45 +01:00
Jens Langhammer
cf11f6b121 format data before inserting it 2019-03-08 15:16:25 +01:00
Jens Langhammer
6dcdf7bcce add custom DynamicArrayField to better handle arrays 2019-03-08 15:11:01 +01:00
Jens Langhammer
56d872af15 add PropertyMapping Model, add Subclass for SAML, test with AWS 2019-03-08 12:47:50 +01:00
Jens Langhammer
ca663d16fc fix debian build (again) 2019-03-07 20:58:18 +01:00
Jens Langhammer
e05c18b19b implicitly add kubernetes-healthcheck-host in helm configmap 2019-03-07 17:11:55 +01:00
Jens Langhammer
a7b86e46bc bump version: 0.1.3-beta -> 0.1.4-beta 2019-03-07 16:24:09 +01:00
Jens Langhammer
84f56674c2 prepare 0.1.4 2019-03-07 16:24:07 +01:00
Jens Langhammer
02ab177c6d install python3-venv for debian build 2019-03-07 16:23:42 +01:00
Jens Langhammer
1232c487e9 bump version: 0.1.2-beta -> 0.1.3-beta 2019-03-07 16:13:05 +01:00
Jens Langhammer
ef0a2bfbe8 Merge branch '11-debian-packaging' into 'master'
add debian package files

Closes #11

See merge request BeryJu.org/passbook!7
2019-03-07 15:06:33 +00:00
Jens Langhammer
05242a11ad add debian package files 2019-03-07 16:01:31 +01:00
Jens Langhammer
4593ad7bcc load AWS processor by default on helm 2019-03-07 14:49:06 +01:00
Jens Langhammer
d7fd5a7fa6 Fix redis dependency being too old 2019-03-07 14:39:00 +01:00
Jens Langhammer
4439378fd4 bump version: 0.1.1-beta -> 0.1.2-beta 2019-03-07 14:14:51 +01:00
Jens Langhammer
acf65eafdd make naming of Providers more consistent 2019-03-07 14:14:49 +01:00
Jens Langhammer
c2ebff55ef fix IDP-initiated login not working 2019-03-07 14:10:06 +01:00
Jens Langhammer
99c82676b6 Add some more failsafe for administration 2019-03-07 14:09:52 +01:00
Jens Langhammer
4991e9b825 Merge branch '1-suspicious-request' into 'master'
fix broken E-Mail templatetag

Closes #1

See merge request BeryJu.org/passbook!5
2019-03-03 20:18:23 +00:00
Jens Langhammer
612f95c3ba fix broken E-Mail templatetag 2019-03-03 21:05:17 +01:00
Jens Langhammer
cd91d5ca15 Merge branch '1-suspicious-request' into 'master'
Resolve "Suspicious request detector (many invalid logins from one IP, many attempts on one username, etc)"

Closes #1

See merge request BeryJu.org/passbook!3
2019-03-03 20:04:56 +00:00
Jens Langhammer
cbbbb5dc08 Merge branch '20-sentry' into 'master'
Resolve "Sentry Error Tracking"

Closes #20

See merge request BeryJu.org/passbook!4
2019-03-03 19:58:18 +00:00
Jens Langhammer
c1640b9411 fix prospector/isort errors 2019-03-03 20:54:23 +01:00
Jens Langhammer
a4842c1f95 add sentry configuration 2019-03-03 20:48:31 +01:00
Jens Langhammer
a4707ddc54 fix failing unittests 2019-03-03 20:34:00 +01:00
Jens Langhammer
fb82d56307 create suspicious request detector and policy, add request to policy engine 2019-03-03 20:26:25 +01:00
Jens Langhammer
1a1005f80d remove audit's LoginAttempt 2019-03-03 20:13:54 +01:00
Jens Langhammer
e86cae6cac Merge branch '18-password-expiry' into 'master'
Resolve "Password Expiry"

Closes #18

See merge request BeryJu.org/passbook!2
2019-03-03 16:53:31 +00:00
Jens Langhammer
0b282f45e0 fix pylint messages 2019-03-03 17:45:20 +01:00
Jens Langhammer
791e88ffc1 Fix negate on FieldMatcherPolicy 2019-03-03 17:21:58 +01:00
Jens Langhammer
7bd3c4bccf Better handle Policy.action and Policy.negate 2019-03-03 17:12:53 +01:00
Jens Langhammer
722e2e4050 Show warning when un-attached policies exist 2019-03-03 17:12:35 +01:00
Jens Langhammer
c7fc444c95 add password policy 2019-03-03 17:12:05 +01:00
Jens Langhammer
20ad062814 Log SAML Authorization actions 2019-03-03 00:34:34 +01:00
Jens Langhammer
fcb5d36e07 cleanup SAML urls 2019-03-03 00:07:40 +01:00
Jens Langhammer
9b131b619f Show warning message when no Factor exists 2019-03-02 23:54:40 +01:00
Jens Langhammer
54427f7c68 use HTML5 autocomplete values to better handle password managers 2019-03-02 23:19:58 +01:00
Jens Langhammer
35eef9c28d improve worker warning 2019-03-02 22:41:25 +01:00
Jens Langhammer
e88a82553d use separate Form for Admin user editing (allow is_staff and is_active) 2019-03-02 22:41:14 +01:00
Jens Langhammer
01a9520140 add import_users script to import users from CSV with already hashed passwords 2019-03-02 22:40:47 +01:00
Jens Langhammer
46667615c3 switch releases to beta 2019-02-27 17:47:41 +01:00
Jens Langhammer
c6721a83a4 bump version: 0.1.1-alpha -> 0.1.1-beta 2019-02-27 17:45:10 +01:00
Jens Langhammer
46866e8ef0 bump version: 0.1.0-beta -> 0.1.1-alpha 2019-02-27 17:43:28 +01:00
Jens Langhammer
4a49681127 Fix docker build failing 2019-02-27 17:43:24 +01:00
Jens Langhammer
4c3fced4e9 bump version: 0.1.0-alpha -> 0.1.0-beta 2019-02-27 16:45:52 +01:00
Jens Langhammer
172347d90f bump version: 0.0.13-alpha -> 0.1.0-alpha 2019-02-27 16:42:52 +01:00
476 changed files with 7256 additions and 3577 deletions

View File

@@ -1,14 +1,15 @@
[bumpversion]
current_version = 0.0.13-alpha
current_version = 0.6.3-beta
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)
serialize = {major}.{minor}.{patch}-{release}
message = bump version: {current_version} -> {new_version}
message = new release: {new_version}
tag_name = version/{new_version}
[bumpversion:part:release]
optional_value = stable
first_value = beta
values =
alpha
beta
@@ -22,25 +23,5 @@ values =
[bumpversion:file:passbook/__init__.py]
[bumpversion:file:passbook/api/__init__.py]
[bumpversion:file:passbook/core/__init__.py]
[bumpversion:file:passbook/admin/__init__.py]
[bumpversion:file:passbook/captcha_factor/__init__.py]
[bumpversion:file:passbook/oauth_client/__init__.py]
[bumpversion:file:passbook/ldap/__init__.py]
[bumpversion:file:passbook/lib/__init__.py]
[bumpversion:file:passbook/saml_idp/__init__.py]
[bumpversion:file:passbook/audit/__init__.py]
[bumpversion:file:passbook/oauth_provider/__init__.py]
[bumpversion:file:passbook/otp/__init__.py]
[bumpversion:file:docker/nginx.conf]

View File

@@ -1,12 +1,10 @@
[run]
source = passbook
omit =
env/
*/wsgi.py
manage.py
*/migrations/*
*/apps.py
passbook/management/commands/nexus_upload.py
passbook/management/commands/web.py
passbook/management/commands/worker.py
docs/

View File

@@ -2,3 +2,4 @@ env
helm
passbook-ui
static
*.env.yml

View File

@@ -9,3 +9,6 @@ insert_final_newline = true
[html]
indent_size = 2
[yaml]
indent_size = 2

1
.gitignore vendored
View File

@@ -191,3 +191,4 @@ pip-selfcheck.json
# End of https://www.gitignore.io/api/python,django
/static/
local.env.yml
.vscode/

View File

@@ -1,139 +1,135 @@
# Global Variables
before_script:
- "python3 -m pip install -U virtualenv"
- "virtualenv env"
- "source env/bin/activate"
- "pip3 install -U -r requirements-dev.txt"
stages:
- build-base-image
- build-dev-image
- test
- build
- docs
image: python:3.6
services:
- postgres:latest
- package
image: docker.beryju.org/passbook/dev:latest
variables:
POSTGRES_DB: passbook
POSTGRES_USER: passbook
POSTGRES_PASSWORD: 'EK-5jnKfjrGRm<77'
POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77"
before_script:
- pip install pipenv
# Ensure all dependencies are installed, even those not included in passbook/dev
# According to pipenv docs, -d outputs all packages, however it actually does not
- pipenv lock -r > requirements-all.txt
- pipenv lock -rd >> requirements-all.txt
- pip install -r requirements-all.txt
create-base-image:
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 --dockerfile $CI_PROJECT_DIR/base.Dockerfile --destination docker.beryju.org/passbook/base:latest --destination docker.beryju.org/passbook/base:0.6.3-beta
stage: build-base-image
only:
refs:
- tags
- /^version/.*$/
build-dev-image:
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 --dockerfile $CI_PROJECT_DIR/dev.Dockerfile --destination docker.beryju.org/passbook/dev:latest --destination docker.beryju.org/passbook/dev:0.6.3-beta
stage: build-dev-image
only:
refs:
- tags
- /^version/.*$/
include:
- /allauth/.gitlab-ci.yml
isort:
script:
- isort -c -sg env
stage: test
services:
- postgres:latest
- redis:latest
migrations:
script:
- python manage.py migrate
stage: test
prospector:
script:
- prospector
stage: test
pylint:
script:
- pylint passbook
stage: test
services:
- postgres:latest
- redis:latest
# prospector:
# script:
# - prospector
# stage: test
# services:
# - postgres:latest
# - redis:latest
# pylint:
# script:
# - pylint passbook
# stage: test
# services:
# - postgres:latest
# - redis:latest
coverage:
script:
- coverage run manage.py test
- coverage report
- coverage html
stage: test
bandit:
script:
- bandit -r passbook
stage: test
services:
- postgres:latest
- redis:latest
package-docker:
build-passbook-server:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
before_script:
- echo "{\"auths\":{\"docker.$NEXUS_URL\":{\"auth\":\"$NEXUS_AUTH\"}}}" > /kaniko/.docker/config.json
- echo "{\"auths\":{\"docker.beryju.org\":{\"auth\":\"$DOCKER_AUTH\"}}}" > /kaniko/.docker/config.json
script:
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination docker.pkg.beryju.org/passbook:latest --destination docker.pkg.beryju.org/passbook:0.0.13-alpha
stage: build
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination docker.beryju.org/passbook/server:latest --destination docker.beryju.org/passbook/server:0.6.3-beta
only:
- tags
- /^version/.*$/
package-helm:
build-passbook-static:
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:
- curl https://raw.githubusercontent.com/helm/helm/master/scripts/get | bash
- helm init --client-only
- helm package helm/passbook
- ./manage.py nexus_upload --method put --url $NEXUS_URL --auth $NEXUS_AUTH --repo helm *.tgz
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/static.Dockerfile --destination docker.beryju.org/passbook/static:latest --destination docker.beryju.org/passbook/static:0.6.3-beta
only:
- tags
- /^version/.*$/
# package-3.5:
# before_script:
# - apt update
# - apt install -y build-essential debhelper devscripts equivs python3 python3-pip
# - cp debian/control-3.5 debian/control
# - mk-build-deps debian/control
# - apt install ./*build-deps*deb -f -y
# - "python3 -m pip install -U virtualenv"
# - "virtualenv env"
# - "source env/bin/activate"
# - "pip3 install -U -r requirements.txt -r requirements-dev.txt"
# image: debian
# script:
# - debuild -us -uc
# - cp ../passbook*.deb .
# - python manage.py nexus_upload
# artifacts:
# paths:
# - passbook-python3.5*deb
# expire_in: 2 days
# stage: build
# only:
# - tags
# - /^debian/.*$/
# package-3.6:
# before_script:
# - apt update
# - apt install -y build-essential debhelper devscripts equivs python3 python3-pip
# - cp debian/control-3.6 debian/control
# - mk-build-deps debian/control
# - apt install ./*build-deps*deb -f -y
# - "python3 -m pip install -U virtualenv"
# - "virtualenv env"
# - "source env/bin/activate"
# - "pip3 install -U -r requirements.txt -r requirements-dev.txt"
# image: debian:buster
# script:
# - debuild -us -uc
# - cp ../passbook*.deb .
# - python manage.py nexus_upload
# artifacts:
# paths:
# - passbook-python3.6*deb
# expire_in: 2 days
# stage: build
# only:
# - tags
# - /^debian/.*$r
# running collectstatic fully initialises django, hence we need that databases
services:
- postgres:latest
- redis:latest
# docs:
# stage: docs
# only:
# - master
# - tags
# - /^debian/.*$/
# environment:
# name: docs
# url: "https://passbook.beryju.org/docs/"
# script:
# - apt update
# - apt install -y rsync
# - "mkdir ~/.ssh"
# - "cp .gitlab/known_hosts ~/.ssh/"
# - "pip3 install -U -r requirements-docs.txt"
# - "eval $(ssh-agent -s)"
# - "echo \"${CI_SSH_PRIVATE}\" | ssh-add -"
# - mkdocs build
# - 'rsync -avh --delete web/* "beryjuorg@ory1-web-prod-1.ory1.beryju.org:passbook.beryju.org/"'
# - 'rsync -avh --delete site/* "beryjuorg@ory1-web-prod-1.ory1.beryju.org:passbook.beryju.org/docs/"'
package-helm:
image: debian:stretch-slim
stage: package
before_script:
- apt update && apt install -y curl
- curl https://raw.githubusercontent.com/helm/helm/master/scripts/get | bash
script:
- helm init --client-only
- helm dependency update helm/passbook
- helm package helm/passbook
artifacts:
paths:
- passbook-*.tgz
expire_in: 1 week
only:
- tags
- /^version/.*$/

View File

@@ -3,7 +3,6 @@ test-warnings: true
doc-warnings: false
ignore-paths:
- env
- migrations
- docs
- node_modules

View File

@@ -2,9 +2,10 @@
disable=redefined-outer-name,arguments-differ,no-self-use,cyclic-import,fixme,locally-disabled,unpacking-non-sequence,too-many-ancestors,too-many-branches,too-few-public-methods
load-plugins=pylint_django,pylint.extensions.bad_builtin
#,pylint.extensions.docparams
extension-pkg-whitelist=lxml
const-rgx=[a-zA-Z0-9_]{1,40}$
ignored-modules=django-otp
jobs=4
[SIMILARITIES]

View File

@@ -1,114 +0,0 @@
# The default ``config.py``
# flake8: noqa
def set_prefs(prefs):
"""This function is called before opening the project"""
# Specify which files and folders to ignore in the project.
# Changes to ignored resources are not added to the history and
# VCSs. Also they are not returned in `Project.get_files()`.
# Note that ``?`` and ``*`` match all characters but slashes.
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
# '.svn': matches 'pkg/.svn' and all of its children
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
'.hg', '.svn', '_svn', '.git', '.tox']
# Specifies which files should be considered python files. It is
# useful when you have scripts inside your project. Only files
# ending with ``.py`` are considered to be python files by
# default.
# prefs['python_files'] = ['*.py']
# Custom source folders: By default rope searches the project
# for finding source folders (folders that should be searched
# for finding modules). You can add paths to that list. Note
# that rope guesses project source folders correctly most of the
# time; use this if you have any problems.
# The folders should be relative to project root and use '/' for
# separating folders regardless of the platform rope is running on.
# 'src/my_source_folder' for instance.
# prefs.add('source_folders', 'src')
# You can extend python path for looking up modules
# prefs.add('python_path', '~/python/')
# Should rope save object information or not.
prefs['save_objectdb'] = True
prefs['compress_objectdb'] = False
# If `True`, rope analyzes each module when it is being saved.
prefs['automatic_soa'] = True
# The depth of calls to follow in static object analysis
prefs['soa_followed_calls'] = 0
# If `False` when running modules or unit tests "dynamic object
# analysis" is turned off. This makes them much faster.
prefs['perform_doa'] = True
# Rope can check the validity of its object DB when running.
prefs['validate_objectdb'] = True
# How many undos to hold?
prefs['max_history_items'] = 32
# Shows whether to save history across sessions.
prefs['save_history'] = True
prefs['compress_history'] = False
# Set the number spaces used for indenting. According to
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
# unit-tests use 4 spaces it is more reliable, too.
prefs['indent_size'] = 4
# Builtin and c-extension modules that are allowed to be imported
# and inspected by rope.
prefs['extension_modules'] = []
# Add all standard c-extensions to extension_modules list.
prefs['import_dynload_stdmods'] = True
# If `True` modules with syntax errors are considered to be empty.
# The default value is `False`; When `False` syntax errors raise
# `rope.base.exceptions.ModuleSyntaxError` exception.
prefs['ignore_syntax_errors'] = False
# If `True`, rope ignores unresolvable imports. Otherwise, they
# appear in the importing namespace.
prefs['ignore_bad_imports'] = False
# If `True`, rope will insert new module imports as
# `from <package> import <module>` by default.
prefs['prefer_module_from_imports'] = False
# If `True`, rope will transform a comma list of imports into
# multiple separate import statements when organizing
# imports.
prefs['split_imports'] = False
# If `True`, rope will remove all top-level import statements and
# reinsert them at the top of the module when making changes.
prefs['pull_imports_to_top'] = True
# If `True`, rope will sort imports alphabetically by module name instead
# of alphabetically by import statement, with from imports after normal
# imports.
prefs['sort_imports_alphabetically'] = False
# Location of implementation of
# rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general
# case, you don't have to change this value, unless you're an rope expert.
# Change this value to inject you own implementations of interfaces
# listed in module rope.base.oi.type_hinting.providers.interfaces
# For example, you can add you own providers for Django Models, or disable
# the search type-hinting in a class hierarchy, etc.
prefs['type_hinting_factory'] = (
'rope.base.oi.type_hinting.factory.default_type_hinting_factory')
def project_opened(project):
"""This function is called after opening the project"""
# Do whatever you like here!

Binary file not shown.

11
.vscode/settings.json vendored
View File

@@ -1,11 +0,0 @@
{
"python.pythonPath": "env/bin/python",
"editor.tabSize": 4,
"[html]": {
"editor.tabSize": 2
},
"cSpell.words": [
"SAML",
"passbook"
]
}

View File

@@ -1,28 +1,10 @@
FROM python:3.6-slim-stretch as build
FROM docker.beryju.org/passbook/base:latest
COPY ./passbook/ /app/passbook
COPY ./manage.py /app/
COPY ./requirements.txt /app/
COPY ./docker/uwsgi.ini /app/
RUN chown -R passbook: /app
WORKDIR /app/
RUN mkdir /app/static/ && \
pip install -r requirements.txt && \
pip install psycopg2 && \
./manage.py collectstatic --no-input
FROM python:3.6-slim-stretch
COPY ./passbook/ /app/passbook
COPY ./manage.py /app/
COPY ./requirements.txt /app/
COPY --from=build /app/static /app/static/
WORKDIR /app/
RUN pip install -r requirements.txt && \
pip install psycopg2 && \
adduser --system --home /app/ passbook && \
chown -R passbook /app/
USER passbook

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 BeryJu.org
Copyright (c) 2019 BeryJu.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

54
Pipfile Normal file
View File

@@ -0,0 +1,54 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[packages]
celery = "*"
cherrypy = "*"
defusedxml = "*"
django = "*"
kombu = "==4.5.0"
django-cors-middleware = "*"
django-filters = "*"
django-ipware = "*"
django-model-utils = "*"
django-oauth-toolkit = "*"
django-oidc-provider = "*"
django-otp = "*"
django-recaptcha = "*"
django-redis = "*"
django-rest-framework = "*"
drf-yasg = "*"
ldap3 = "*"
lxml = "*"
markdown = "*"
oauthlib = "*"
packaging = "*"
psycopg2-binary = "*"
pycryptodome = "*"
pyyaml = "*"
qrcode = "*"
requests-oauthlib = "*"
sentry-sdk = "*"
service_identity = "*"
signxml = "*"
urllib3 = {extras = ["secure"],version = "*"}
structlog = "*"
[requires]
python_version = "3.7"
[dev-packages]
astroid = "==2.2.5"
coverage = "*"
isort = "*"
pylint = "==2.3.1"
pylint-django = "==2.0.10"
prospector = "==1.1.7"
django-debug-toolbar = "*"
bumpversion = "*"
unittest-xml-reporting = "*"
autopep8 = "*"
bandit = "*"
colorama = "*"

1072
Pipfile.lock generated Normal file

File diff suppressed because it is too large Load Diff

11
README.md Normal file
View File

@@ -0,0 +1,11 @@
# passbook
## Quick instance
```
export PASSBOOK_DOMAIN=domain.tld
docker-compose pull
docker-compose up -d
docker-compose exec server ./manage.py migrate
docker-compose exec server ./manage.py createsuperuser
```

View File

@@ -1,27 +0,0 @@
# Global Variables
before_script:
- cd allauth/
- "python3 -m pip install -U virtualenv"
- "virtualenv env"
- "source env/bin/activate"
- "pip3 install -U -r requirements-dev.txt"
stages:
- test-allauth
image: python:3.6
isort:
script:
- isort -c -sg env
stage: test-allauth
prospector:
script:
- prospector
stage: test-allauth
pylint:
script:
- pylint passbook
stage: test-allauth
bandit:
script:
- bandit -r allauth_passbook
stage: test-allauth

View File

@@ -1,35 +0,0 @@
"""passbook provider"""
from allauth.socialaccount.providers.base import ProviderAccount
from allauth.socialaccount.providers.oauth2.provider import OAuth2Provider
class PassbookAccount(ProviderAccount):
"""passbook account"""
def to_str(self):
dflt = super().to_str()
return self.account.extra_data.get('username', dflt)
class PassbookProvider(OAuth2Provider):
"""passbook provider"""
id = 'passbook'
name = 'passbook'
account_class = PassbookAccount
def extract_uid(self, data):
return str(data['sub'])
def extract_common_fields(self, data):
return {
'email': data.get('email'),
'username': data.get('preferred_username'),
'name': data.get('name'),
}
def get_default_scope(self):
return ['openid:userinfo']
provider_classes = [PassbookProvider] # noqa

View File

@@ -1,5 +0,0 @@
"""passbook provider"""
from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns
from allauth_passbook.provider import PassbookProvider
urlpatterns = default_urlpatterns(PassbookProvider)

View File

@@ -1,37 +0,0 @@
"""passbook adapter"""
import requests
from allauth.socialaccount import app_settings
from allauth.socialaccount.providers.oauth2.views import (OAuth2Adapter,
OAuth2CallbackView,
OAuth2LoginView)
from allauth_passbook.provider import PassbookProvider
class PassbookOAuth2Adapter(OAuth2Adapter):
"""passbook OAuth2 Adapter"""
provider_id = PassbookProvider.id
# pylint: disable=no-member
settings = app_settings.PROVIDERS.get(provider_id, {}) # noqa
provider_base_url = settings.get("PASSBOOK_URL", 'https://id.beryju.org')
access_token_url = '{0}/application/oauth/token/'.format(provider_base_url)
authorize_url = '{0}/application/oauth/authorize/'.format(provider_base_url)
profile_url = '{0}/api/v1/openid/'.format(
provider_base_url)
def complete_login(self, request, app, access_token, **kwargs):
headers = {
'Authorization': 'Bearer {0}'.format(access_token.token),
'Content-Type': 'application/json',
}
extra_data = requests.get(self.profile_url, headers=headers)
return self.get_provider().sociallogin_from_response(
request,
extra_data.json()
)
oauth2_login = OAuth2LoginView.adapter_view(PassbookOAuth2Adapter) # noqa
oauth2_callback = OAuth2CallbackView.adapter_view(PassbookOAuth2Adapter) # noqa

View File

@@ -1 +0,0 @@
django-allauth

View File

@@ -1,33 +0,0 @@
"""passbook allauth setup.py"""
from setuptools import setup
setup(
name='django-allauth-passbook',
version='1.0.0',
description='passbook support for django-allauth',
# long_description='\n'.join(read_simple('docs/index.md')[2:]),
long_description_content_type='text/markdown',
author='BeryJu.org',
author_email='hello@beryju.org',
packages=['allauth_passbook'],
include_package_data=True,
install_requires=['django-allauth'],
keywords='django allauth passbook',
license='MIT',
classifiers=[
'Intended Audience :: Developers',
'Topic :: Software Development :: Libraries :: Python Modules',
'Environment :: Web Environment',
'Topic :: Internet',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Framework :: Django',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Framework :: Django :: 2.1',
],
)

19
base.Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
FROM python:3.7-slim-stretch
COPY ./Pipfile /app/
COPY ./Pipfile.lock /app/
WORKDIR /app/
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential && \
pip install pipenv uwsgi --no-cache-dir && \
apt-get remove -y --purge build-essential && \
apt-get autoremove -y --purge && \
rm -rf /var/lib/apt/lists/*
RUN pipenv lock -r > requirements.txt && \
pipenv --rm && \
pip install -r requirements.txt --no-cache-dir && \
adduser --system --no-create-home passbook && \
chown -R passbook /app

5
dev.Dockerfile Normal file
View File

@@ -0,0 +1,5 @@
FROM docker.beryju.org/passbook/base:latest
RUN pipenv lock --dev -r > requirements-dev.txt && \
pipenv --rm && \
pip install -r /app/requirements-dev.txt --no-cache-dir

89
docker-compose.yml Normal file
View File

@@ -0,0 +1,89 @@
---
version: '3.2'
services:
postgresql:
image: postgres
volumes:
- database:/var/lib/postgresql/data
networks:
- internal
environment:
- POSTGRES_PASSWORD=${PG_PASS:-thisisnotagoodpassword}
- POSTGRES_USER=passbook
- POSTGRES_DB=passbook
labels:
- traefik.enable=false
redis:
image: redis
networks:
- internal
labels:
- traefik.enable=false
server:
build:
context: .
image: docker.beryju.org/passbook/server:${SERVER_TAG:-latest}
command:
- uwsgi
- uwsgi.ini
environment:
- PASSBOOK_DOMAIN=${PASSBOOK_DOMAIN}
- PASSBOOK_REDIS__HOST=redis
- PASSBOOK_POSTGRESQL__HOST=postgresql
- PASSBOOK_POSTGRESQL__PASSWORD=${PG_PASS:-thisisnotagoodpassword}
ports:
- 8000
networks:
- internal
labels:
- traefik.port=8000
- traefik.docker.network=internal
- traefik.frontend.rule=PathPrefix:/
worker:
image: docker.beryju.org/passbook/server:${SERVER_TAG:-latest}
command:
- celery
- worker
- --autoscale=10,3
- -E
- -B
- -A=passbook.root.celery
networks:
- internal
labels:
- traefik.enable=false
environment:
- PASSBOOK_DOMAIN=${PASSBOOK_DOMAIN}
- PASSBOOK_REDIS__HOST=redis
- PASSBOOK_POSTGRESQL__HOST=postgresql
- PASSBOOK_POSTGRESQL__PASSWORD=${PG_PASS:-thisisnotagoodpassword}
static:
build:
context: .
dockerfile: static.Dockerfile
image: docker.beryju.org/passbook/static:latest
networks:
- internal
labels:
- traefik.frontend.rule=PathPrefix:/static, /robots.txt
- traefik.port=80
- traefik.docker.network=internal
traefik:
image: traefik:1.7
command: --api --docker
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "0.0.0.0:80:80"
- "0.0.0.0:443:443"
- "0.0.0.0:8080:8080"
networks:
- internal
volumes:
database:
driver: local
networks:
internal: {}

66
docker/nginx.conf Normal file
View File

@@ -0,0 +1,66 @@
user nginx;
worker_processes 1;
error_log stderr warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format json_combined escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"remote_user":"$remote_user",'
'"request":"$request",'
'"status": "$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"request_time":"$request_time",'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
access_log /dev/stdout json_combined;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
server {
server_name _;
gzip on;
gzip_types application/javascript image/* text/css;
gunzip on;
add_header X-passbook-Version 0.6.3-beta;
add_header Vary X-passbook-Version;
root /data/;
location /_/healthz {
return 204;
}
location ~* \.(jpg|jpeg|png|gif|ico)$ {
expires 30d;
}
location ~* \.(css|js)$ {
expires 7d;
}
}
server {
listen 8080;
location = /stub_status {
stub_status;
}
}
}

10
docker/uwsgi.ini Normal file
View File

@@ -0,0 +1,10 @@
[uwsgi]
http = 0.0.0.0:8000
chdir = /app
wsgi-file = passbook/root/wsgi.py
processes = 2
master = true
threads = 2
enable-threads = true
uid = passbook
gid = passbook

9
helm/passbook/Chart.lock Normal file
View File

@@ -0,0 +1,9 @@
dependencies:
- name: postgresql
repository: https://kubernetes-charts.storage.googleapis.com/
version: 6.3.10
- name: redis
repository: https://kubernetes-charts.storage.googleapis.com/
version: 9.2.1
digest: sha256:bdde250e1401dccdd5161e39c807f9e88b05e3e8e72e74df767a1bbb5fc39a4a
generated: "2019-10-01T10:46:06.542706+02:00"

View File

@@ -1,6 +1,6 @@
apiVersion: v1
appVersion: "0.0.13-alpha"
appVersion: "0.6.3-beta"
description: A Helm chart for passbook.
name: passbook
version: "0.0.13-alpha"
icon: https://passbook.beryju.org/images/logo.png
version: "0.6.3-beta"
icon: https://git.beryju.org/uploads/-/system/project/avatar/108/logo.png

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,9 +1,9 @@
dependencies:
- name: redis
repository: https://kubernetes-charts.storage.googleapis.com/
version: 5.1.0
- name: postgresql
repository: https://kubernetes-charts.storage.googleapis.com/
version: 3.10.1
digest: sha256:04bd136761f070e94a2ff32ff48ff87f5e07fbd451e5fd7f65551e3bd4680e5e
generated: 2019-02-08T12:08:49.090666+01:00
version: 4.2.2
- name: redis
repository: https://kubernetes-charts.storage.googleapis.com/
version: 9.2.1
digest: sha256:8782e974a1094eaeecf1d68f093ca4fb84977217b2bd38b09790a05ec289aec2
generated: "2019-10-02T21:03:25.90491153Z"

View File

@@ -1,7 +1,7 @@
dependencies:
- name: redis
version: 5.1.0
repository: https://kubernetes-charts.storage.googleapis.com/
- name: postgresql
version: 3.10.1
version: 4.2.2
repository: https://kubernetes-charts.storage.googleapis.com/
- name: redis
version: 9.2.1
repository: https://kubernetes-charts.storage.googleapis.com/

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "passbook.fullname" . }}-config
data:
config.yml: |
postgresql:
host: "{{ .Release.Name }}-postgresql"
name: "{{ .Values.postgresql.postgresqlDatabase }}"
user: postgres
redis:
host: "{{ .Release.Name }}-redis-master"
cache_db: 0
message_queue_db: 1
error_report_enabled: {{ .Values.config.error_reporting }}
domain: ".{{ .Values.ingress.hosts[0] }}"

View File

@@ -1,6 +1,5 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "passbook.fullname" . -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
@@ -30,9 +29,17 @@ spec:
- host: {{ . | quote }}
http:
paths:
- path: {{ $ingressPath }}
- path: /
backend:
serviceName: {{ $fullName }}
serviceName: {{ $fullName }}-web
servicePort: http
- path: /static/
backend:
serviceName: {{ $fullName }}-static
servicePort: http
- path: /robots.txt
backend:
serviceName: {{ $fullName }}-static
servicePort: http
{{- end }}
{{- end }}

View File

@@ -1,137 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "passbook.fullname" . }}-config
data:
config.yml: |
# Env for Docker images
databases:
default:
engine: django.db.backends.postgresql
name: {{ .Values.postgresql.postgresqlDatabase }}
user: postgres
password: {{ .Values.postgresql.postgresqlPassword }}
host: {{ .Release.Name }}-postgresql
port: ''
log:
level:
console: DEBUG
file: DEBUG
file: /dev/null
syslog:
host: 127.0.0.1
port: 514
email:
host: localhost
port: 25
user: ''
password: ''
use_tls: false
use_ssl: false
from: passbook <passbook@domain.tld>
web:
listen: 0.0.0.0
port: 8000
threads: 30
debug: false
secure_proxy_header:
HTTP_X_FORWARDED_PROTO: https
redis: ":{{ .Values.redis.password }}@{{ .Release.Name }}-redis-master"
# Error reporting, sends stacktrace to sentry.services.beryju.org
error_report_enabled: {{ .Values.config.error_reporting }}
{{- if .Values.config.secret_key }}
secret_key: {{ .Values.config.secret_key }}
{{- else }}
secret_key: {{ randAlphaNum 50 }}
{{- end }}
domains:
{{- range .Values.ingress.hosts }}
- {{ . | quote }}
{{- end }}
passbook:
sign_up:
# Enables signup, created users are stored in internal Database and created in LDAP if ldap.create_users is true
enabled: true
password_reset:
# Enable password reset, passwords are reset in internal Database and in LDAP if ldap.reset_password is true
enabled: true
# Verification the user has to provide in order to be able to reset passwords. Can be any combination of `email`, `2fa`, `security_questions`
verification:
- email
# Text used in title, on login page and multiple other places
branding: passbook
login:
# Override URL used for logo
logo_url: null
# Override URL used for Background on Login page
bg_url: null
# Optionally add a subtext, placed below logo on the login page
subtext: null
footer:
links:
# Optionally add links to the footer on the login page
# - name: test
# href: https://test
# Specify which fields can be used to authenticate. Can be any combination of `username` and `email`
uid_fields:
- username
- email
session:
remember_age: 2592000 # 60 * 60 * 24 * 30, one month
# Provider-specific settings
ldap:
# # Completely enable or disable LDAP provider
# enabled: false
# # AD Domain, used to generate `userPrincipalName`
# domain: corp.contoso.com
# # Base DN in which passbook should look for users
# base_dn: dn=corp,dn=contoso,dn=com
# # LDAP field which is used to set the django username
# username_field: sAMAccountName
# # LDAP server to connect to, can be set to `<domain_name>`
# server:
# name: corp.contoso.com
# use_tls: false
# # Bind credentials, used for account creation
# bind:
# username: Administraotr@corp.contoso.com
# password: VerySecurePassword!
# Which field from `uid_fields` maps to which LDAP Attribute
login_field_map:
username: sAMAccountName
email: mail # or userPrincipalName
user_attribute_map:
active_directory:
username: "%(sAMAccountName)s"
email: "%(mail)s"
name: "%(displayName)"
# # Create new users in LDAP upon sign-up
# create_users: true
# # Reset LDAP password when user reset their password
# reset_password: true
oauth_client:
# List of python packages with sources types to load.
types:
- passbook.oauth_client.source_types.discord
- passbook.oauth_client.source_types.facebook
- passbook.oauth_client.source_types.github
- passbook.oauth_client.source_types.google
- passbook.oauth_client.source_types.reddit
- passbook.oauth_client.source_types.supervisr
- passbook.oauth_client.source_types.twitter
saml_idp:
signing: true
autosubmit: false
issuer: passbook
assertion_valid_for: 86400
# List of python packages with provider types to load.
types:
- passbook.saml_idp.processors.generic
- passbook.saml_idp.processors.gitlab
- passbook.saml_idp.processors.nextcloud
- passbook.saml_idp.processors.salesforce
- passbook.saml_idp.processors.shibboleth
- passbook.saml_idp.processors.wordpress_orange

View File

@@ -1,66 +0,0 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "passbook.fullname" . }}-web
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
volumes:
- name: config-volume
configMap:
name: {{ include "passbook.fullname" . }}-config
containers:
- name: {{ .Chart.Name }}
image: "docker.pkg.beryju.org/passbook:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c"]
args: ["./manage.py migrate && ./manage.py web"]
ports:
- name: http
containerPort: 8000
protocol: TCP
volumeMounts:
- mountPath: /etc/passbook
name: config-volume
livenessProbe:
httpGet:
path: /
port: http
httpHeaders:
- name: Host
value: kubernetes-healthcheck-host
readinessProbe:
httpGet:
path: /
port: http
httpHeaders:
- name: Host
value: kubernetes-healthcheck-host
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}

View File

@@ -1,51 +0,0 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "passbook.fullname" . }}-worker
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
volumes:
- name: config-volume
configMap:
name: {{ include "passbook.fullname" . }}-config
containers:
- name: {{ .Chart.Name }}
image: "docker.pkg.beryju.org/passbook:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
command: ["./manage.py", "worker"]
ports:
- name: http
containerPort: 8000
protocol: TCP
volumeMounts:
- mountPath: /etc/passbook
name: config-volume
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ include "passbook.fullname" . }}-secret-key
data:
{{- if .Values.config.secret_key }}
secret_key: {{ .Values.config.secret_key | b64enc | quote }}
{{- else }}
secret_key: {{ randAlphaNum 50 | b64enc | quote}}
{{- end }}

View File

@@ -0,0 +1,55 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "passbook.fullname" . }}-static
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
selector:
matchLabels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
k8s.passbook.io/component: static
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: '9113'
field.cattle.io/workloadMetrics: '[{"path":"/metrics","port":9113,"schema":"HTTP"}]'
spec:
containers:
- name: {{ .Chart.Name }}-static
image: "docker.beryju.org/passbook/static:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
initialDelaySeconds: 10
timeoutSeconds: 5
httpGet:
path: /_/healthz
port: http
readinessProbe:
initialDelaySeconds: 10
timeoutSeconds: 5
httpGet:
path: /_/healthz
port: http
resources:
requests:
cpu: 10m
memory: 10M
limits:
cpu: 20m
memory: 20M
- name: {{ .Chart.Name }}-static-prometheus
image: nginx/nginx-prometheus-exporter:0.4.1
imagePullPolicy: IfNotPresent

View File

@@ -0,0 +1,21 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "passbook.fullname" . }}-static
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
k8s.passbook.io/component: static
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
k8s.passbook.io/component: static

View File

@@ -0,0 +1,112 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "passbook.fullname" . }}-web
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
passbook.io/component: web
spec:
volumes:
- name: config-volume
configMap:
name: {{ include "passbook.fullname" . }}-config
initContainers:
- name: passbook-database-migrations
image: "docker.beryju.org/passbook/server:{{ .Values.image.tag }}"
command:
- ./manage.py
args:
- migrate
volumeMounts:
- mountPath: /etc/passbook
name: config-volume
envFrom:
- configMapRef:
name: {{ include "passbook.fullname" . }}-config
prefix: PASSBOOK_
env:
- name: PASSBOOK_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ include "passbook.fullname" . }}-secret-key
key: secret_key
- name: PASSBOOK_REDIS__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-redis"
key: redis-password
- name: PASSBOOK_POSTGRESQL__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-postgresql"
key: postgresql-password
containers:
- name: {{ .Chart.Name }}
image: "docker.beryju.org/passbook/server:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
command:
- uwsgi
args:
- uwsgi.ini
volumeMounts:
- mountPath: /etc/passbook
name: config-volume
envFrom:
- configMapRef:
name: {{ include "passbook.fullname" . }}-config
prefix: PASSBOOK_
env:
- name: PASSBOOK_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ include "passbook.fullname" . }}-secret-key
key: secret_key
- name: PASSBOOK_REDIS__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-redis"
key: redis-password
- name: PASSBOOK_POSTGRESQL__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-postgresql"
key: postgresql-password
ports:
- name: http
containerPort: 8000
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
httpHeaders:
- name: Host
value: kubernetes-healthcheck-host
readinessProbe:
httpGet:
path: /
port: http
httpHeaders:
- name: Host
value: kubernetes-healthcheck-host
resources:
requests:
cpu: 100m
memory: 200M
limits:
cpu: 300m
memory: 350M

View File

@@ -1,7 +1,7 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "passbook.fullname" . }}
name: {{ include "passbook.fullname" . }}-web
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
@@ -17,3 +17,4 @@ spec:
selector:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
passbook.io/component: web

View File

@@ -0,0 +1,68 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "passbook.fullname" . }}-worker
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
passbook.io/component: worker
spec:
volumes:
- name: config-volume
configMap:
name: {{ include "passbook.fullname" . }}-config
containers:
- name: {{ .Chart.Name }}
image: "docker.beryju.org/passbook/server:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
command:
- celery
args:
- worker
- --autoscale=10,3
- -E
- -B
- -A=passbook.root.celery
volumeMounts:
- mountPath: /etc/passbook
name: config-volume
envFrom:
- configMapRef:
name: {{ include "passbook.fullname" . }}-config
prefix: PASSBOOK_
env:
- name: PASSBOOK_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ include "passbook.fullname" . }}-secret-key
key: secret_key
- name: PASSBOOK_REDIS__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-redis"
key: redis-password
- name: PASSBOOK_POSTGRESQL__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-postgresql"
key: postgresql-password
resources:
requests:
cpu: 150m
memory: 300M
limits:
cpu: 300m
memory: 500M

View File

@@ -1,11 +1,8 @@
# Default values for passbook.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
tag: 0.0.13-alpha
tag: 0.6.3-beta
nameOverride: ""
@@ -14,10 +11,18 @@ config:
# secret_key: _k*@6h2u2@q-dku57hhgzb7tnx*ba9wodcb^s9g0j59@=y(@_o
# Enable error reporting
error_reporting: true
email:
host: localhost
postgresql:
postgresqlDatabase: passbook
postgresqlPassword: foo
postgresqlDatabase: passbook
redis:
cluster:
enabled: false
master:
persistence:
enabled: false
service:
type: ClusterIP
@@ -31,27 +36,7 @@ ingress:
path: /
hosts:
- passbook.k8s.local
- kubernetes-healthcheck-host
defaultHost: passbook.k8s.local
tls: []
# - secretName: chart-example-tls
# hosts:
# - passbook.k8s.local
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}

View File

@@ -4,7 +4,7 @@ import os
import sys
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'passbook.core.settings')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'passbook.root.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:

View File

@@ -1,2 +1,2 @@
"""passbook"""
__version__ = '0.0.13-alpha'
__version__ = '0.6.3-beta'

View File

@@ -1,2 +0,0 @@
"""passbook admin"""
__version__ = '0.0.13-alpha'

View File

@@ -0,0 +1,17 @@
"""passbook administrative user forms"""
from django import forms
from passbook.core.models import User
class UserForm(forms.ModelForm):
"""Update User Details"""
class Meta:
model = User
fields = ['username', 'name', 'email', 'is_staff', 'is_active']
widgets = {
'name': forms.TextInput
}

View File

@@ -0,0 +1,25 @@
"""passbook admin Middleware to impersonate users"""
from passbook.core.models import User
def impersonate(get_response):
"""Middleware to impersonate users"""
def middleware(request):
"""Middleware to impersonate users"""
# User is superuser and has __impersonate ID set
if request.user.is_superuser and "__impersonate" in request.GET:
request.session['impersonate_id'] = request.GET["__impersonate"]
# user wants to stop impersonation
elif "__unimpersonate" in request.GET and 'impersonate_id' in request.session:
del request.session['impersonate_id']
# Actually impersonate user
if request.user.is_superuser and 'impersonate_id' in request.session:
request.user = User.objects.get(pk=request.session['impersonate_id'])
response = get_response(request)
return response
return middleware

View File

@@ -1,2 +0,0 @@
django-rest-framework
drf_yasg

View File

@@ -0,0 +1,5 @@
"""passbook admin settings"""
MIDDLEWARE = [
'passbook.admin.middleware.impersonate',
]

View File

@@ -4,36 +4,4 @@
{% load is_active %}
{% block nav_secondary %}
<ul class="nav navbar-nav navbar-persistent">
<li class="{% is_active 'passbook_admin:overview' %}">
<a href="{% url 'passbook_admin:overview' %}">{% trans 'Overview' %}</a>
</li>
<li class="{% is_active 'passbook_admin:applications' 'passbook_admin:application-create' 'passbook_admin:application-update' 'passbook_admin:application-delete' %}">
<a href="{% url 'passbook_admin:applications' %}">{% trans 'Applications' %}</a>
</li>
<li class="{% is_active 'passbook_admin:sources' 'passbook_admin:source-create' 'passbook_admin:source-update' 'passbook_admin:source-delete' %}">
<a href="{% url 'passbook_admin:sources' %}">{% trans 'Sources' %}</a>
</li>
<li class="{% is_active 'passbook_admin:providers' 'passbook_admin:provider-create' 'passbook_admin:provider-update' 'passbook_admin:provider-delete' %}">
<a href="{% url 'passbook_admin:providers' %}">{% trans 'Providers' %}</a>
</li>
<li class="{% is_active 'passbook_admin:factors' 'passbook_admin:factor-create' 'passbook_admin:factor-update' 'passbook_admin:factor-delete' %}">
<a href="{% url 'passbook_admin:factors' %}">{% trans 'Factors' %}</a>
</li>
<li class="{% is_active 'passbook_admin:policies' 'passbook_admin:policy-create' 'passbook_admin:policy-update' 'passbook_admin:policy-delete' 'passbook_admin:policy-test' %}">
<a href="{% url 'passbook_admin:policies' %}">{% trans 'Policies' %}</a>
</li>
<li class="{% is_active 'passbook_admin:invitations' 'passbook_admin:invitation-create' 'passbook_admin:invitation-update' 'passbook_admin:invitation-delete' 'passbook_admin:invitation-test' %}">
<a href="{% url 'passbook_admin:invitations' %}">{% trans 'Invitations' %}</a>
</li>
<li class="{% is_active 'passbook_admin:users' 'passbook_admin:user-update' 'passbook_admin:user-delete' %}">
<a href="{% url 'passbook_admin:users' %}">{% trans 'Users' %}</a>
</li>
<li class="{% is_active 'passbook_admin:audit-log' %}">
<a href="{% url 'passbook_admin:audit-log' %}">{% trans 'Audit Log' %}</a>
</li>
<li class="{% is_active_app 'admin' %}">
<a href="{% url 'admin:index' %}">{% trans 'Django' %}</a>
</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,31 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load utils %}
{% block title %}
{% title %}
{% endblock %}
{% block content %}
<div class="container">
<h1><span class="pficon-applications"></span> {% trans "Request" %}</h1>
<hr>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Key' %}</th>
<th>{% trans 'Value' %}</th>
</tr>
</thead>
<tbody>
{% for key, value in request_dict.items %}
<tr>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@@ -0,0 +1,45 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load utils %}
{% block title %}
{% title %}
{% endblock %}
{% block content %}
<div class="container">
<h1><span class="pficon-users"></span> {% trans "Groups" %}</h1>
<span>{% trans "Group users together and give them permissions based on the membership." %}</span>
<hr>
<a href="{% url 'passbook_admin:group-create' %}?back={{ request.get_full_path }}" class="btn btn-primary">
{% trans 'Create...' %}
</a>
<hr>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Parent' %}</th>
<th>{% trans 'Members' %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for group in object_list %}
<tr>
<td>{{ group.name }}</td>
<td>{{ group.parent }}</td>
<td>{{ group.user_set.all|length }}</td>
<td>
<a class="btn btn-default btn-sm"
href="{% url 'passbook_admin:group-update' pk=group.uuid %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a>
<a class="btn btn-default btn-sm"
href="{% url 'passbook_admin:group-delete' pk=group.uuid %}?back={{ request.get_full_path }}">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@@ -1,83 +0,0 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load static %}
{% load utils %}
{% block head %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'css/bootstrap-treeview.min.css'%}">
{% endblock %}
{% block scripts %}
{{ block.super }}
<script src="{% static 'js/bootstrap-treeview.min.js' %}"></script>
<script>
var cleanupData = function (obj) {
return {
text: obj.name,
href: '?group=' + obj.uuid,
nodes: obj.children.map(cleanupData),
};
}
$(function() {
var apiUrl = "{% url 'passbook_admin:group-list' %}?format=json";
$.ajax({
url: apiUrl,
}).done(function(data) {
$('#treeview1').treeview({
collapseIcon: "fa fa-angle-down",
data: data.map(cleanupData),
expandIcon: "fa fa-angle-right",
nodeIcon: "fa pficon-users",
showBorder: true,
enableLinks: true,
onNodeSelected: function (event, node) {
window.location.href = node.href;
}
});
});
});
</script>
{% endblock %}
{% block title %}
{% title %}
{% endblock %}
{% block content %}
<div class="col-md-3">
<div id="treeview1" class="treeview">
</div>
</div>
<div class="col-md-9">
<h1>{% trans "Invitations" %}</h1>
<a href="{% url 'passbook_admin:invitation-create' %}" class="btn btn-primary">
{% trans 'Create...' %}
</a>
<hr>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Expiry' %}</th>
<th>{% trans 'Link' %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for invitation in object_list %}
<tr>
<td>{{ invitation.expires|default:"Never" }}</td>
<td>
<pre>{{ invitation.link }}</pre>
</td>
<td>
<a class="btn btn-default btn-sm" href="{% url 'passbook_admin:invitation-delete' pk=invitation.uuid %}?back={{ request.get_full_path }}">{%
trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@@ -76,9 +76,13 @@
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
<span class="card-pf-aggregate-status-notification">
<a href="{% url 'passbook_admin:factors' %}">
<span class="pficon pficon-ok"></span>{{ factor_count }}
</a>
{% if factor_count < 1 %}
<span class="pficon-error-circle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'No Factors configured. No Users will be able to login.' %}"></span>
{{ factor_count }}
{% else %}
<span class="pficon pficon-ok"></span>{{ factor_count }}
{% endif %}
</span>
</p>
</div>
@@ -95,9 +99,13 @@
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
<span class="card-pf-aggregate-status-notification">
<a href="{% url 'passbook_admin:policies' %}">
<span class="pficon pficon-ok"></span>{{ policy_count }}
</a>
{% if policies_without_attachment > 0 %}
<span class="pficon-warning-triangle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'Policies without attachment exist.' %}"></span>
{{ policy_count }}
{% else %}
<span class="pficon pficon-ok"></span>{{ policy_count }}
{% endif %}
</span>
</p>
</div>
@@ -144,10 +152,8 @@
<div class="col-xs-6 col-sm-2 col-md-2">
<div class="card-pf card-pf-accented card-pf-aggregate-status">
<h2 class="card-pf-title">
<a href="#">
<span class="pficon-bundle"></span>
<span class="card-pf-aggregate-status-count"></span> {% trans 'Version' %}
</a>
<span class="pficon-bundle"></span>
<span class="card-pf-aggregate-status-count"></span> {% trans 'Version' %}
</h2>
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
@@ -173,8 +179,8 @@
<span class="card-pf-aggregate-status-notification">
<a href="#">
{% if worker_count < 1%}
<span class="pficon-error-circle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'No workers connected. Policies may not work.' %}"></span> {{ worker_count }}
<span class="pficon-warning-triangle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'No workers connected.' %}"></span> {{ worker_count }}
{% else %}
<span class="pficon pficon-ok"></span>{{ worker_count }}
{% endif %}
@@ -184,5 +190,59 @@
</div>
</div>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<div class="card-pf card-pf-accented card-pf-aggregate-status">
<h2 class="card-pf-title">
<span class="pficon-server"></span>
<span class="card-pf-aggregate-status-count"></span> {% trans 'Cached Policies' %}
</h2>
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
<span class="card-pf-aggregate-status-notification">
<a href="#" data-toggle="modal" data-target="#clearCacheMOdal">
{% if cached_policies < 1 %}
<span class="pficon-warning-triangle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'No policies cached. Users may experience slow response times.' %}"></span> {{ cached_policies }}
{% else %}
<span class="pficon pficon-ok"></span>{{ cached_policies }}
{% endif %}
</a>
</span>
</p>
</div>
</div>
</div>
</div>
<div class="modal fade" id="clearCacheMOdal" tabindex="-1" role="dialog" aria-labelledby="clearCacheMOdalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<span class="pficon pficon-close"></span>
</button>
<h4 class="modal-title" id="clearCacheMOdalLabel">{% trans 'Clear Cache' %}</h4>
</div>
<div class="modal-body">
<form method="post" id="clearForm">
{% csrf_token %}
<input type="hidden" name="clear">
<p>
{% blocktrans %}
Are you sure you want to clear the cache? This includes all user sessions and all cached Policy results.
{% endblocktrans %}
</p>
<h3>
{% blocktrans %}
This will also log you out.
{% endblocktrans %}
</h3>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button form="clearForm" type="submit" type="button" class="btn btn-danger">{% trans 'Clear' %}</button>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -28,6 +28,7 @@
<table class="table table-striped table-bordered">
<thead>
<tr>
<th></th>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Type' %}</th>
<th></th>
@@ -35,7 +36,14 @@
</thead>
<tbody>
{% for policy in object_list %}
<tr>
<tr {% if not policy.policymodel_set.exists %} class="warning" {% endif %}>
<th>
{% if not policy.policymodel_set.exists %}
<span class="pficon-warning-triangle-o" data-toggle="tooltip" data-placement="right" title="{% trans 'Warning: Policy is not assigned.' %}"></span>
{% else %}
<span class="pficon-ok" data-toggle="tooltip" data-placement="right" title="{% blocktrans with objects=policy.policymodel_set.all|join:', ' %}Assigned to objects {{ objects }}{% endblocktrans %}"></span>
{% endif %}
</th>
<td>{{ policy.name }}</td>
<td>{{ policy|verbose_name }}</td>
<td>

View File

@@ -5,3 +5,22 @@
{% block above_form %}
<h1>{% blocktrans with policy=policy %}Test policy {{ policy }}{% endblocktrans %}</h1>
{% endblock %}
{% block action %}
{% trans 'Test' %}
{% endblock %}
{% block beneath_form %}
<p class="loading" style="display: none;">
<span class="spinner spinner-xs spinner-inline"></span> {% trans 'Processing, please wait...' %}
</p>
{% endblock %}
{% block scripts %}
{{ block.super }}
<script>
$('form').on('submit', function () {
$('p.loading').show();
})
</script>
{% endblock %}

View File

@@ -0,0 +1,52 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load utils %}
{% block title %}
{% title %}
{% endblock %}
{% block content %}
<div class="container">
<h1><span class="fa fa-table"></span> {% trans "Property Mappings" %}</h1>
<span>{% trans "Property Mappings allow you expose provider-specific attributes." %}</span>
<hr>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" id="createDropdown" data-toggle="dropdown">
{% trans 'Create...' %}
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="createDropdown">
{% for type, name in types.items %}
<li role="presentation"><a role="menuitem" tabindex="-1"
href="{% url 'passbook_admin:property-mapping-create' %}?type={{ type }}&back={{ request.get_full_path }}">{{ name }}</a></li>
{% endfor %}
</ul>
</div>
<hr>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Type' %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for property_mapping in object_list %}
<tr>
<td>{{ property_mapping.name }}</td>
<td>{{ property_mapping|verbose_name }}</td>
<td>
<a class="btn btn-default btn-sm"
href="{% url 'passbook_admin:property-mapping-update' pk=property_mapping.pk %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a>
<a class="btn btn-default btn-sm"
href="{% url 'passbook_admin:property-mapping-delete' pk=property_mapping.pk %}?back={{ request.get_full_path }}">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@@ -57,6 +57,10 @@
<a class="btn btn-default btn-sm"
href="{{ href }}?back={{ request.get_full_path }}">{% trans name %}</a>
{% endfor %}
{% get_htmls provider as htmls %}
{% for html in htmls %}
{{ html|safe }}
{% endfor %}
</td>
</tr>
{% endfor %}

View File

@@ -36,7 +36,7 @@
<tr>
<td>{{ source.name }}</td>
<td>{{ source|fieldtype }}</td>
<td>{{ source.additional_info }}</td>
<td>{{ source.additional_info|safe }}</td>
<td>
<a class="btn btn-default btn-sm"
href="{% url 'passbook_admin:source-update' pk=source.uuid %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a>

View File

@@ -7,6 +7,10 @@
<div class="container">
<h1><span class="pficon-users"></span> {% trans "Users" %}</h1>
<hr>
<a href="{% url 'passbook_admin:user-create' %}?back={{ request.get_full_path }}" class="btn btn-primary">
{% trans 'Create...' %}
</a>
<hr>
<table class="table table-striped table-bordered">
<thead>
<tr>
@@ -31,6 +35,8 @@
href="{% url 'passbook_admin:user-delete' pk=user.pk %}?back={{ request.get_full_path }}">{% trans 'Delete' %}</a>
<a class="btn btn-default btn-sm"
href="{% url 'passbook_admin:user-password-reset' pk=user.pk %}?back={{ request.get_full_path }}">{% trans 'Reset Password' %}</a>
<a class="btn btn-default btn-sm"
href="{% url 'passbook_core:overview' %}?__impersonate={{ user.pk }}">{% trans 'Impersonate' %}</a>
</td>
</tr>
{% endfor %}

View File

@@ -2,6 +2,21 @@
{% load i18n %}
{% load utils %}
{% load static %}
{% block head %}
{{ block.super }}
{{ form.media.css }}
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/actions.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/urlify.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/prepopulate.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/SelectBox.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/SelectFilter2.js' %}"></script>
{% endblock %}
{% block content %}
<div class="container">
@@ -14,5 +29,12 @@
<input type="submit" class="btn btn-primary" value="{% block action %}{% endblock %}" />
</form>
</div>
{% block beneath_form %}
{% endblock %}
</div>
{% endblock %}
{% block scripts %}
{{ block.super }}
{{ form.media.js }}
{% endblock %}

View File

@@ -1,12 +1,14 @@
"""passbook admin templatetags"""
import inspect
from logging import getLogger
from django import template
from django.db.models import Model
from structlog import get_logger
from passbook.lib.utils.template import render_to_string
register = template.Library()
LOGGER = getLogger(__name__)
LOGGER = get_logger()
@register.simple_tag()
def get_links(model_instance):
@@ -29,3 +31,24 @@ def get_links(model_instance):
pass
return links
@register.simple_tag(takes_context=True)
def get_htmls(context, model_instance):
"""Find all html_ methods on an object instance, run them and return as dict"""
prefix = 'html_'
htmls = []
if not isinstance(model_instance, Model):
LOGGER.warning("Model %s is not instance of Model", model_instance)
return htmls
try:
for name, method in inspect.getmembers(model_instance, predicate=inspect.ismethod):
if name.startswith(prefix):
template, _context = method(context.get('request'))
htmls.append(render_to_string(template, _context))
except NotImplementedError:
pass
return htmls

View File

@@ -1,9 +1,9 @@
"""passbook URL Configuration"""
from django.urls import include, path
from passbook.admin.views import (applications, audit, factors, groups,
invitations, overview, policy, providers,
sources, users)
from passbook.admin.views import (applications, audit, debug, factors, groups,
invitations, overview, policy,
property_mapping, providers, sources, users)
urlpatterns = [
path('', overview.AdministrationOverviewView.as_view(), name='overview'),
@@ -43,6 +43,15 @@ urlpatterns = [
factors.FactorUpdateView.as_view(), name='factor-update'),
path('factors/<uuid:pk>/delete/',
factors.FactorDeleteView.as_view(), name='factor-delete'),
# Factors
path('property-mappings/', property_mapping.PropertyMappingListView.as_view(),
name='property-mappings'),
path('property-mappings/create/',
property_mapping.PropertyMappingCreateView.as_view(), name='property-mapping-create'),
path('property-mappings/<uuid:pk>/update/',
property_mapping.PropertyMappingUpdateView.as_view(), name='property-mapping-update'),
path('property-mappings/<uuid:pk>/delete/',
property_mapping.PropertyMappingDeleteView.as_view(), name='property-mapping-delete'),
# Invitations
path('invitations/', invitations.InvitationListView.as_view(), name='invitations'),
path('invitations/create/',
@@ -52,16 +61,24 @@ urlpatterns = [
# Users
path('users/', users.UserListView.as_view(),
name='users'),
path('users/create/', users.UserCreateView.as_view(), name='user-create'),
path('users/<int:pk>/update/',
users.UserUpdateView.as_view(), name='user-update'),
path('users/<int:pk>/delete/',
users.UserDeleteView.as_view(), name='user-delete'),
path('users/<int:pk>/reset/',
users.UserPasswordResetView.as_view(), name='user-password-reset'),
# Groups
path('group/', groups.GroupListView.as_view(), name='group'),
path('group/create/', groups.GroupCreateView.as_view(), name='group-create'),
path('group/<uuid:pk>/update/', groups.GroupUpdateView.as_view(), name='group-update'),
path('group/<uuid:pk>/delete/', groups.GroupDeleteView.as_view(), name='group-delete'),
# Audit Log
path('audit/', audit.AuditEntryListView.as_view(), name='audit-log'),
# Groups
path('groups/', groups.GroupListView.as_view(), name='groups'),
# API
path('api/', include('passbook.admin.api.urls'))
path('api/', include('passbook.admin.api.urls')),
# Debug
path('debug/request/', debug.DebugRequestView.as_view(), name='debug-request'),
]

View File

@@ -0,0 +1,17 @@
"""passbook administration debug views"""
from django.views.generic import TemplateView
from passbook.admin.mixins import AdminRequiredMixin
class DebugRequestView(AdminRequiredMixin, TemplateView):
"""Show debug info about request"""
template_name = 'administration/debug/request.html'
def get_context_data(self, **kwargs):
kwargs['request_dict'] = {}
for key in dir(self.request):
kwargs['request_dict'][key] = getattr(self.request, key)
return super().get_context_data(**kwargs)

View File

@@ -1,12 +1,57 @@
"""passbook Group administration"""
from django.views.generic import ListView
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.utils.translation import ugettext as _
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
from passbook.admin.mixins import AdminRequiredMixin
from passbook.core.forms.groups import GroupForm
from passbook.core.models import Group
class GroupListView(AdminRequiredMixin, ListView):
"""Show list of all invitations"""
"""Show list of all groups"""
model = Group
template_name = 'administration/groups/list.html'
ordering = 'name'
template_name = 'administration/group/list.html'
class GroupCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
"""Create new Group"""
form_class = GroupForm
template_name = 'generic/create.html'
success_url = reverse_lazy('passbook_admin:groups')
success_message = _('Successfully created Group')
def get_context_data(self, **kwargs):
kwargs['type'] = 'Group'
return super().get_context_data(**kwargs)
class GroupUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView):
"""Update group"""
model = Group
form_class = GroupForm
template_name = 'generic/update.html'
success_url = reverse_lazy('passbook_admin:groups')
success_message = _('Successfully updated Group')
class GroupDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView):
"""Delete group"""
model = Group
template_name = 'generic/delete.html'
success_url = reverse_lazy('passbook_admin:groups')
success_message = _('Successfully deleted Group')
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs)

View File

@@ -1,11 +1,13 @@
"""passbook administration overview"""
from django.core.cache import cache
from django.shortcuts import redirect, reverse
from django.views.generic import TemplateView
from passbook import __version__
from passbook.admin.mixins import AdminRequiredMixin
from passbook.core import __version__
from passbook.core.celery import CELERY_APP
from passbook.core.models import (Application, Factor, Invitation, Policy,
Provider, Source, User)
from passbook.root.celery import CELERY_APP
class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
@@ -13,6 +15,13 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
template_name = 'administration/overview.html'
def post(self, *args, **kwargs):
"""Handle post (clear cache from modal)"""
if 'clear' in self.request.POST:
cache.clear()
return redirect(reverse('passbook_core:auth-login'))
return self.get(*args, **kwargs)
def get_context_data(self, **kwargs):
kwargs['application_count'] = len(Application.objects.all())
kwargs['policy_count'] = len(Policy.objects.all())
@@ -24,4 +33,6 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
kwargs['version'] = __version__
kwargs['worker_count'] = len(CELERY_APP.control.ping(timeout=0.5))
kwargs['providers_without_application'] = Provider.objects.filter(application=None)
kwargs['policies_without_attachment'] = len(Policy.objects.filter(policymodel__isnull=True))
kwargs['cached_policies'] = len(cache.keys('policy_*'))
return super().get_context_data(**kwargs)

View File

@@ -12,6 +12,7 @@ from passbook.admin.forms.policies import PolicyTestForm
from passbook.admin.mixins import AdminRequiredMixin
from passbook.core.models import Policy
from passbook.lib.utils.reflection import path_to_class
from passbook.policies.engine import PolicyEngine
class PolicyListView(AdminRequiredMixin, ListView):
@@ -100,7 +101,9 @@ class PolicyTestView(AdminRequiredMixin, DetailView, FormView):
def form_valid(self, form):
policy = self.get_object()
user = form.cleaned_data.get('user')
result = policy.passes(user)
policy_engine = PolicyEngine([policy])
policy_engine.for_user(user).with_request(self.request).build()
result = policy_engine.passing
if result:
messages.success(self.request, _('User successfully passed policy.'))
else:

View File

@@ -0,0 +1,90 @@
"""passbook PropertyMapping administration"""
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.http import Http404
from django.urls import reverse_lazy
from django.utils.translation import ugettext as _
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
from passbook.admin.mixins import AdminRequiredMixin
from passbook.core.models import PropertyMapping
from passbook.lib.utils.reflection import path_to_class
def all_subclasses(cls):
"""Recursively return all subclassess of cls"""
return set(cls.__subclasses__()).union(
[s for c in cls.__subclasses__() for s in all_subclasses(c)])
class PropertyMappingListView(AdminRequiredMixin, ListView):
"""Show list of all property_mappings"""
model = PropertyMapping
template_name = 'administration/property_mapping/list.html'
ordering = 'name'
def get_context_data(self, **kwargs):
kwargs['types'] = {
x.__name__: x._meta.verbose_name for x in all_subclasses(PropertyMapping)}
return super().get_context_data(**kwargs)
def get_queryset(self):
return super().get_queryset().select_subclasses()
class PropertyMappingCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
"""Create new PropertyMapping"""
template_name = 'generic/create.html'
success_url = reverse_lazy('passbook_admin:property-mappings')
success_message = _('Successfully created Property Mapping')
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
property_mapping_type = self.request.GET.get('type')
model = next(x for x in all_subclasses(PropertyMapping)
if x.__name__ == property_mapping_type)
kwargs['type'] = model._meta.verbose_name
return kwargs
def get_form_class(self):
property_mapping_type = self.request.GET.get('type')
model = next(x for x in all_subclasses(PropertyMapping)
if x.__name__ == property_mapping_type)
if not model:
raise Http404
return path_to_class(model.form)
class PropertyMappingUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView):
"""Update property_mapping"""
model = PropertyMapping
template_name = 'generic/update.html'
success_url = reverse_lazy('passbook_admin:property-mappings')
success_message = _('Successfully updated Property Mapping')
def get_form_class(self):
form_class_path = self.get_object().form
form_class = path_to_class(form_class_path)
return form_class
def get_object(self, queryset=None):
return PropertyMapping.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()
class PropertyMappingDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView):
"""Delete property_mapping"""
model = PropertyMapping
template_name = 'generic/delete.html'
success_url = reverse_lazy('passbook_admin:property-mappings')
success_message = _('Successfully deleted Property Mapping')
def get_object(self, queryset=None):
return PropertyMapping.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs)

View File

@@ -5,10 +5,10 @@ from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse, reverse_lazy
from django.utils.translation import ugettext as _
from django.views import View
from django.views.generic import DeleteView, ListView, UpdateView
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
from passbook.admin.forms.users import UserForm
from passbook.admin.mixins import AdminRequiredMixin
from passbook.core.forms.users import UserDetailForm
from passbook.core.models import Nonce, User
@@ -19,11 +19,22 @@ class UserListView(AdminRequiredMixin, ListView):
template_name = 'administration/user/list.html'
class UserCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
"""Create user"""
model = User
form_class = UserForm
template_name = 'generic/create.html'
success_url = reverse_lazy('passbook_admin:users')
success_message = _('Successfully created User')
class UserUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView):
"""Update user"""
model = User
form_class = UserDetailForm
form_class = UserForm
template_name = 'generic/update.html'
success_url = reverse_lazy('passbook_admin:users')

View File

@@ -1,2 +0,0 @@
"""passbook api"""
__version__ = '0.0.13-alpha'

View File

@@ -1,3 +0,0 @@
django-rest-framework
drf_yasg
django-filters

View File

@@ -1,2 +0,0 @@
"""passbook audit Header"""
__version__ = '0.0.13-alpha'

View File

@@ -1,7 +1,8 @@
# Generated by Django 2.1.7 on 2019-02-16 09:13
# Generated by Django 2.2.6 on 2019-10-07 14:07
import uuid
import django.contrib.postgres.fields.jsonb
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
@@ -23,7 +24,7 @@ class Migration(migrations.Migration):
('action', 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'), ('invitation_created', 'invitation_created'), ('invitation_used', 'invitation_used')])),
('date', models.DateTimeField(auto_now_add=True)),
('app', models.TextField()),
('_context', models.TextField()),
('context', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('request_ip', models.GenericIPAddressField()),
('created', models.DateTimeField(auto_now_add=True)),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
@@ -33,19 +34,4 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Audit Entries',
},
),
migrations.CreateModel(
name='LoginAttempt',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateField(auto_now_add=True)),
('last_updated', models.DateTimeField(auto_now=True)),
('target_uid', models.CharField(max_length=254)),
('request_ip', models.GenericIPAddressField()),
('attempts', models.IntegerField(default=1)),
],
),
migrations.AlterUniqueTogether(
name='loginattempt',
unique_together={('target_uid', 'request_ip', 'created')},
),
]

View File

@@ -1,18 +0,0 @@
# Generated by Django 2.1.7 on 2019-02-21 12:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('passbook_audit', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='loginattempt',
name='created',
field=models.DateTimeField(auto_now_add=True),
),
]

View File

@@ -1,23 +0,0 @@
# Generated by Django 2.1.7 on 2019-02-21 12:40
import django.contrib.postgres.fields.jsonb
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('passbook_audit', '0002_auto_20190221_1201'),
]
operations = [
migrations.RemoveField(
model_name='auditentry',
name='_context',
),
migrations.AddField(
model_name='auditentry',
name='context',
field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict),
),
]

View File

@@ -1,19 +1,16 @@
"""passbook audit models"""
from datetime import timedelta
from logging import getLogger
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.utils import timezone
from django.utils.translation import gettext as _
from ipware import get_client_ip
from structlog import get_logger
from passbook.lib.models import CreatedUpdatedModel, UUIDModel
from passbook.lib.models import UUIDModel
LOGGER = getLogger(__name__)
LOGGER = get_logger()
class AuditEntry(UUIDModel):
"""An individual audit log entry"""
@@ -24,7 +21,7 @@ class AuditEntry(UUIDModel):
ACTION_AUTHORIZE_APPLICATION = 'authorize_application'
ACTION_SUSPICIOUS_REQUEST = 'suspicious_request'
ACTION_SIGN_UP = 'sign_up'
ACTION_PASSWORD_RESET = 'password_reset' # noqa
ACTION_PASSWORD_RESET = 'password_reset' # noqa # nosec
ACTION_INVITE_CREATED = 'invitation_created'
ACTION_INVITE_USED = 'invitation_used'
ACTIONS = (
@@ -75,43 +72,3 @@ class AuditEntry(UUIDModel):
verbose_name = _('Audit Entry')
verbose_name_plural = _('Audit Entries')
class LoginAttempt(CreatedUpdatedModel):
"""Track failed login-attempts"""
target_uid = models.CharField(max_length=254)
request_ip = models.GenericIPAddressField()
attempts = models.IntegerField(default=1)
@staticmethod
def attempt(target_uid, request):
"""Helper function to create attempt or count up existing one"""
if not target_uid:
return
client_ip, _ = get_client_ip(request)
# Since we can only use 254 chars for target_uid, truncate target_uid.
target_uid = target_uid[:254]
time_threshold = timezone.now() - timedelta(minutes=10)
existing_attempts = LoginAttempt.objects.filter(
target_uid=target_uid,
request_ip=client_ip,
last_updated__gt=time_threshold).order_by('created')
if existing_attempts.exists():
attempt = existing_attempts.first()
attempt.attempts += 1
attempt.save()
LOGGER.debug("Increased attempts on %s", attempt)
else:
attempt = LoginAttempt.objects.create(
target_uid=target_uid,
request_ip=client_ip)
LOGGER.debug("Created new attempt %s", attempt)
def __str__(self):
return "LoginAttempt to %s from %s (x%d)" % (self.target_uid,
self.request_ip, self.attempts)
class Meta:
unique_together = (('target_uid', 'request_ip', 'created'),)

View File

@@ -1 +0,0 @@
django-ipware

View File

@@ -1,9 +1,8 @@
"""passbook audit signal listener"""
from django.contrib.auth.signals import (user_logged_in, user_logged_out,
user_login_failed)
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
from passbook.audit.models import AuditEntry, LoginAttempt
from passbook.audit.models import AuditEntry
from passbook.core.signals import (invitation_created, invitation_used,
user_signed_up)
@@ -34,8 +33,3 @@ def on_invitation_used(sender, request, invitation, **kwargs):
"""Log Invitation usage"""
AuditEntry.create(AuditEntry.ACTION_INVITE_USED, request,
invitation_uuid=invitation.uuid.hex)
@receiver(user_login_failed)
def on_user_login_failed(sender, request, credentials, **kwargs):
"""Log failed login attempt"""
LoginAttempt.attempt(target_uid=credentials.get('username'), request=request)

View File

@@ -1,2 +0,0 @@
"""passbook captcha_factor Header"""
__version__ = '0.0.13-alpha'

View File

@@ -1,10 +0,0 @@
"""passbook captcha app"""
from django.apps import AppConfig
class PassbookCaptchaFactorConfig(AppConfig):
"""passbook captcha app"""
name = 'passbook.captcha_factor'
label = 'passbook_captcha_factor'
verbose_name = 'passbook Captcha'

View File

@@ -1,15 +0,0 @@
"""passbook captcha factor"""
from django.views.generic import FormView
from passbook.captcha_factor.forms import CaptchaForm
from passbook.core.auth.factor import AuthenticationFactor
class CaptchaFactor(FormView, AuthenticationFactor):
"""Simple captcha checker, logic is handeled in django-captcha module"""
form_class = CaptchaForm
def form_valid(self, form):
return self.authenticator.user_ok()

View File

@@ -1 +0,0 @@
django-recaptcha

View File

@@ -1,2 +0,0 @@
"""passbook core"""
__version__ = '0.0.13-alpha'

View File

@@ -1,12 +1,6 @@
"""passbook core app config"""
from importlib import import_module
from logging import getLogger
from django.apps import AppConfig
from passbook.lib.config import CONFIG
LOGGER = getLogger(__name__)
class PassbookCoreConfig(AppConfig):
"""passbook core app config"""
@@ -14,13 +8,4 @@ class PassbookCoreConfig(AppConfig):
name = 'passbook.core'
label = 'passbook_core'
verbose_name = 'passbook Core'
def ready(self):
import_module('passbook.core.policies')
factors_to_load = CONFIG.y('passbook.factors', [])
for factors_to_load in factors_to_load:
try:
import_module(factors_to_load)
LOGGER.info("Loaded %s", factors_to_load)
except ImportError as exc:
LOGGER.debug(exc)
mountpoint = ''

View File

@@ -1,76 +0,0 @@
"""passbook multi-factor authentication engine"""
from logging import getLogger
from django.contrib import messages
from django.contrib.auth import authenticate
from django.core.exceptions import PermissionDenied
from django.forms.utils import ErrorList
from django.shortcuts import redirect, reverse
from django.utils.translation import gettext as _
from django.views.generic import FormView
from passbook.core.auth.factor import AuthenticationFactor
from passbook.core.auth.view import AuthenticationView
from passbook.core.forms.authentication import PasswordFactorForm
from passbook.core.models import Nonce
from passbook.core.tasks import send_email
from passbook.lib.config import CONFIG
LOGGER = getLogger(__name__)
class PasswordFactor(FormView, AuthenticationFactor):
"""Authentication factor which authenticates against django's AuthBackend"""
form_class = PasswordFactorForm
template_name = 'login/factors/backend.html'
def get_context_data(self, **kwargs):
kwargs['show_password_forget_notice'] = CONFIG.y('passbook.password_reset.enabled')
return super().get_context_data(**kwargs)
def get(self, request, *args, **kwargs):
if 'password-forgotten' in request.GET:
nonce = Nonce.objects.create(user=self.pending_user)
LOGGER.debug("DEBUG %s", str(nonce.uuid))
# Send mail to user
send_email.delay(self.pending_user.email, _('Forgotten password'),
'email/account_password_reset.html', {
'url': self.request.build_absolute_uri(
reverse('passbook_core:passbook_core:auth-password-reset',
kwargs={
'nonce': nonce.uuid
})
)
})
self.authenticator.cleanup()
messages.success(request, _('Check your E-Mails for a password reset link.'))
return redirect('passbook_core:auth-login')
return super().get(request, *args, **kwargs)
def form_valid(self, form):
"""Authenticate against django's authentication backend"""
uid_fields = CONFIG.y('passbook.uid_fields')
kwargs = {
'password': form.cleaned_data.get('password'),
}
for uid_field in uid_fields:
kwargs[uid_field] = getattr(self.authenticator.pending_user, uid_field)
try:
user = authenticate(self.request, **kwargs)
if user:
# User instance returned from authenticate() has .backend property set
self.authenticator.pending_user = user
self.request.session[AuthenticationView.SESSION_USER_BACKEND] = user.backend
return self.authenticator.user_ok()
# No user was found -> invalid credentials
LOGGER.debug("Invalid credentials")
# Manually inject error into form
# pylint: disable=protected-access
errors = form._errors.setdefault("password", ErrorList())
errors.append(_("Invalid password"))
return self.form_invalid(form)
except PermissionDenied:
# User was found, but permission was denied (i.e. user is not active)
LOGGER.debug("Denied access to %s", kwargs)
return self.authenticator.user_invalid()

View File

@@ -1,5 +1,6 @@
"""passbook Core Application forms"""
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.utils.translation import gettext_lazy as _
from passbook.core.models import Application, Provider
@@ -15,11 +16,12 @@ class ApplicationForm(forms.ModelForm):
model = Application
fields = ['name', 'slug', 'launch_url', 'icon_url',
'policies', 'provider', 'skip_authorization']
'provider', 'policies', 'skip_authorization']
widgets = {
'name': forms.TextInput(),
'launch_url': forms.TextInput(),
'icon_url': forms.TextInput(),
'policies': FilteredSelectMultiple(_('policies'), False)
}
labels = {
'launch_url': _('Launch URL'),

View File

@@ -1,16 +1,15 @@
"""passbook core authentication forms"""
from logging import getLogger
from django import forms
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.utils.translation import gettext_lazy as _
from structlog import get_logger
from passbook.core.models import User
from passbook.lib.config import CONFIG
from passbook.lib.utils.ui import human_list
LOGGER = getLogger(__name__)
LOGGER = get_logger()
class LoginForm(forms.Form):
"""Allow users to login"""
@@ -81,15 +80,4 @@ class SignUpForm(forms.Form):
password_repeat = self.cleaned_data.get('password_repeat')
if password != password_repeat:
raise ValidationError(_("Passwords don't match"))
# TODO: Password policy? Via Plugin? via Policy?
# return check_password(self)
return self.cleaned_data.get('password_repeat')
class PasswordFactorForm(forms.Form):
"""Password authentication form"""
password = forms.CharField(widget=forms.PasswordInput(attrs={
'placeholder': _('Password'),
'autofocus': 'autofocus'
}))

View File

@@ -1,30 +0,0 @@
"""passbook administration forms"""
from django import forms
from passbook.core.models import DummyFactor, PasswordFactor
GENERAL_FIELDS = ['name', 'slug', 'order', 'policies', 'enabled']
class PasswordFactorForm(forms.ModelForm):
"""Form to create/edit Password Factors"""
class Meta:
model = PasswordFactor
fields = GENERAL_FIELDS + ['backends', 'password_policies']
widgets = {
'name': forms.TextInput(),
'order': forms.NumberInput(),
}
class DummyFactorForm(forms.ModelForm):
"""Form to create/edit Dummy Factor"""
class Meta:
model = DummyFactor
fields = GENERAL_FIELDS
widgets = {
'name': forms.TextInput(),
'order': forms.NumberInput(),
}

View File

@@ -0,0 +1,32 @@
"""passbook Core Group forms"""
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
from passbook.core.models import Group, User
class GroupForm(forms.ModelForm):
"""Group Form"""
members = forms.ModelMultipleChoiceField(
User.objects.all(), required=False, widget=FilteredSelectMultiple('users', False))
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.pk:
self.initial['members'] = self.instance.user_set.values_list('pk', flat=True)
def save(self, *args, **kwargs):
instance = super().save(*args, **kwargs)
if instance.pk:
instance.user_set.clear()
instance.user_set.add(*self.cleaned_data['members'])
return instance
class Meta:
model = Group
fields = ['name', 'parent', 'members', 'tags']
widgets = {
'name': forms.TextInput(),
}

View File

@@ -3,39 +3,8 @@
from django import forms
from django.utils.translation import gettext as _
from passbook.core.models import (DebugPolicy, FieldMatcherPolicy,
PasswordPolicy, WebhookPolicy)
GENERAL_FIELDS = ['name', 'action', 'negate', 'order', ]
class FieldMatcherPolicyForm(forms.ModelForm):
"""FieldMatcherPolicy Form"""
class Meta:
model = FieldMatcherPolicy
fields = GENERAL_FIELDS + ['user_field', 'match_action', 'value', ]
widgets = {
'name': forms.TextInput(),
'value': forms.TextInput(),
}
class WebhookPolicyForm(forms.ModelForm):
"""WebhookPolicyForm Form"""
class Meta:
model = WebhookPolicy
fields = GENERAL_FIELDS + ['url', 'method', 'json_body', 'json_headers',
'result_jsonpath', 'result_json_value', ]
widgets = {
'name': forms.TextInput(),
'json_body': forms.TextInput(),
'json_headers': forms.TextInput(),
'result_jsonpath': forms.TextInput(),
'result_json_value': forms.TextInput(),
}
from passbook.core.models import DebugPolicy
from passbook.policies.forms import GENERAL_FIELDS
class DebugPolicyForm(forms.ModelForm):
@@ -51,25 +20,3 @@ class DebugPolicyForm(forms.ModelForm):
labels = {
'result': _('Allow user')
}
class PasswordPolicyForm(forms.ModelForm):
"""PasswordPolicy Form"""
class Meta:
model = PasswordPolicy
fields = GENERAL_FIELDS + ['amount_uppercase', 'amount_lowercase',
'amount_symbols', 'length_min', 'symbol_charset',
'error_message']
widgets = {
'name': forms.TextInput(),
'symbol_charset': forms.TextInput(),
'error_message': forms.TextInput(),
}
labels = {
'amount_uppercase': _('Minimum amount of Uppercase Characters'),
'amount_lowercase': _('Minimum amount of Lowercase Characters'),
'amount_symbols': _('Minimum amount of Symbols Characters'),
'length_min': _('Minimum Length'),
}

View File

@@ -22,10 +22,14 @@ class PasswordChangeForm(forms.Form):
"""Form to update password"""
password = forms.CharField(label=_('Password'),
widget=forms.PasswordInput(attrs={'placeholder': _('New Password')}))
widget=forms.PasswordInput(attrs={
'placeholder': _('New Password'),
'autocomplete': 'new-password'
}))
password_repeat = forms.CharField(label=_('Repeat Password'),
widget=forms.PasswordInput(attrs={
'placeholder': _('Repeat Password')
'placeholder': _('Repeat Password'),
'autocomplete': 'new-password'
}))
def clean_password_repeat(self):
@@ -34,5 +38,4 @@ class PasswordChangeForm(forms.Form):
password_repeat = self.cleaned_data.get('password_repeat')
if password != password_repeat:
raise ValidationError(_("Passwords don't match"))
# TODO: Password policy check
return self.cleaned_data.get('password_repeat')

View File

@@ -1,63 +0,0 @@
"""passbook nexus_upload management command"""
from base64 import b64decode
import requests
from django.core.management.base import BaseCommand
class Command(BaseCommand):
"""Upload debian package to nexus repository"""
url = None
user = None
password = None
def add_arguments(self, parser):
parser.add_argument(
'--repo',
action='store',
help='Repository to upload to',
required=True)
parser.add_argument(
'--url',
action='store',
help='Nexus root URL',
required=True)
parser.add_argument(
'--auth',
action='store',
help='base64-encoded string of username:password',
required=True)
parser.add_argument(
'--method',
action='store',
nargs='?',
const='post',
choices=['post', 'put'],
help=('Method used for uploading files to nexus. '
'Apt repositories use post, Helm uses put.'),
required=True)
# Positional arguments
parser.add_argument('file', nargs='+', type=str)
def handle(self, *args, **options):
"""Upload debian package to nexus repository"""
auth = tuple(b64decode(options.get('auth')).decode('utf-8').split(':', 1))
responses = {}
url = 'https://%(url)s/repository/%(repo)s/' % options
method = options.get('method')
exit_code = 0
for file in options.get('file'):
if method == 'post':
responses[file] = requests.post(url, data=open(file, mode='rb'), auth=auth)
else:
responses[file] = requests.put(url+file, data=open(file, mode='rb'), auth=auth)
self.stdout.write('Upload results:\n')
sep = '-' * 60
self.stdout.write('%s\n' % sep)
for path, response in responses.items():
self.stdout.write('%-55s: %d\n' % (path, response.status_code))
if response.status_code >= 400:
exit_code = 1
self.stdout.write('%s\n' % sep)
exit(exit_code)

View File

@@ -1,34 +0,0 @@
"""passbook Webserver management command"""
from logging import getLogger
import cherrypy
from django.conf import settings
from django.core.management.base import BaseCommand
from passbook.core.wsgi import application
LOGGER = getLogger(__name__)
class Command(BaseCommand):
"""Run CherryPy webserver"""
def handle(self, *args, **options):
"""passbook cherrypy server"""
config = settings.CHERRYPY_SERVER
config.update(**options)
cherrypy.config.update(config)
cherrypy.tree.graft(application, '/')
# Mount NullObject to serve static files
cherrypy.tree.mount(None, '/static', config={
'/': {
'tools.staticdir.on': True,
'tools.staticdir.dir': settings.STATIC_ROOT,
'tools.expires.on': True,
'tools.expires.secs': 86400,
'tools.gzip.on': True,
}
})
cherrypy.engine.start()
cherrypy.engine.block()

View File

@@ -1,17 +0,0 @@
"""passbook Worker management command"""
from logging import getLogger
from django.core.management.base import BaseCommand
from passbook.core.celery import CELERY_APP
LOGGER = getLogger(__name__)
class Command(BaseCommand):
"""Run Celery Worker"""
def handle(self, *args, **options):
"""celery worker"""
CELERY_APP.worker_main(['worker', '--autoscale=10,3', '-E'])

View File

@@ -1,21 +1,24 @@
# Generated by Django 2.1.7 on 2019-02-16 09:10
# Generated by Django 2.2.6 on 2019-10-07 14:06
import uuid
import django.contrib.auth.models
import django.contrib.auth.validators
import django.contrib.postgres.fields.jsonb
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
import passbook.core.models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0009_alter_user_last_name_max_length'),
('auth', '0011_update_proxy_permissions'),
]
operations = [
@@ -34,6 +37,8 @@ class Migration(migrations.Migration):
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False)),
('name', models.TextField()),
('password_change_date', models.DateTimeField(auto_now_add=True)),
],
options={
'verbose_name': 'user',
@@ -44,39 +49,17 @@ class Migration(migrations.Migration):
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.CreateModel(
name='Group',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('name', models.CharField(max_length=80, verbose_name='name')),
('extra_data', models.TextField(blank=True)),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='passbook_core.Group')),
],
),
migrations.CreateModel(
name='Invitation',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('expires', models.DateTimeField(blank=True, default=None, null=True)),
('fixed_username', models.TextField(blank=True, default=None)),
('fixed_email', models.TextField(blank=True, default=None)),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Invitation',
'verbose_name_plural': 'Invitations',
},
),
migrations.CreateModel(
name='Policy',
fields=[
('created', models.DateField(auto_now_add=True)),
('created', models.DateTimeField(auto_now_add=True)),
('last_updated', models.DateTimeField(auto_now=True)),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('name', models.TextField(blank=True, null=True)),
('action', models.CharField(choices=[('allow', 'allow'), ('deny', 'deny')], max_length=20)),
('negate', models.BooleanField(default=False)),
('order', models.IntegerField(default=0)),
('timeout', models.IntegerField(default=30)),
],
options={
'abstract': False,
@@ -85,28 +68,136 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='PolicyModel',
fields=[
('created', models.DateField(auto_now_add=True)),
('created', models.DateTimeField(auto_now_add=True)),
('last_updated', models.DateTimeField(auto_now=True)),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('policies', models.ManyToManyField(blank=True, to='passbook_core.Policy')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='PropertyMapping',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('name', models.TextField()),
],
options={
'verbose_name': 'Property Mapping',
'verbose_name_plural': 'Property Mappings',
},
),
migrations.CreateModel(
name='DebugPolicy',
fields=[
('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
('result', models.BooleanField(default=False)),
('wait_min', models.IntegerField(default=5)),
('wait_max', models.IntegerField(default=30)),
],
options={
'verbose_name': 'Debug Policy',
'verbose_name_plural': 'Debug Policies',
},
bases=('passbook_core.policy',),
),
migrations.CreateModel(
name='Factor',
fields=[
('policymodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.PolicyModel')),
('name', models.TextField()),
('slug', models.SlugField(unique=True)),
('order', models.IntegerField()),
('enabled', models.BooleanField(default=True)),
],
options={
'abstract': False,
},
bases=('passbook_core.policymodel',),
),
migrations.CreateModel(
name='Source',
fields=[
('policymodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.PolicyModel')),
('name', models.TextField()),
('slug', models.SlugField()),
('enabled', models.BooleanField(default=True)),
],
options={
'abstract': False,
},
bases=('passbook_core.policymodel',),
),
migrations.CreateModel(
name='Provider',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('property_mappings', models.ManyToManyField(blank=True, default=None, to='passbook_core.PropertyMapping')),
],
),
migrations.CreateModel(
name='Nonce',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('expires', models.DateTimeField(default=passbook.core.models.default_nonce_duration)),
('expiring', models.BooleanField(default=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Nonce',
'verbose_name_plural': 'Nonces',
},
),
migrations.CreateModel(
name='Invitation',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('expires', models.DateTimeField(blank=True, default=None, null=True)),
('fixed_username', models.TextField(blank=True, default=None)),
('fixed_email', models.TextField(blank=True, default=None)),
('needs_confirmation', models.BooleanField(default=True)),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Invitation',
'verbose_name_plural': 'Invitations',
},
),
migrations.CreateModel(
name='Group',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('name', models.CharField(max_length=80, verbose_name='name')),
('tags', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='passbook_core.Group')),
],
options={
'unique_together': {('name', 'parent')},
},
),
migrations.AddField(
model_name='user',
name='groups',
field=models.ManyToManyField(to='passbook_core.Group'),
),
migrations.AddField(
model_name='user',
name='user_permissions',
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
),
migrations.CreateModel(
name='UserSourceConnection',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateField(auto_now_add=True)),
('created', models.DateTimeField(auto_now_add=True)),
('last_updated', models.DateTimeField(auto_now=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('source', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='passbook_core.Source')),
],
options={
'unique_together': {('user', 'source')},
},
),
migrations.CreateModel(
name='Application',
@@ -124,131 +215,9 @@ class Migration(migrations.Migration):
},
bases=('passbook_core.policymodel',),
),
migrations.CreateModel(
name='DebugPolicy',
fields=[
('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
('result', models.BooleanField(default=False)),
('wait_min', models.IntegerField(default=5)),
('wait_max', models.IntegerField(default=30)),
],
options={
'verbose_name': 'Debug Policy',
'verbose_name_plural': 'Debug Policys',
},
bases=('passbook_core.policy',),
),
migrations.CreateModel(
name='Factor',
fields=[
('policymodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.PolicyModel')),
('name', models.TextField()),
('slug', models.SlugField(unique=True)),
('order', models.IntegerField()),
('type', models.TextField(unique=True)),
('enabled', models.BooleanField(default=True)),
],
options={
'abstract': False,
},
bases=('passbook_core.policymodel',),
),
migrations.CreateModel(
name='FieldMatcherPolicy',
fields=[
('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
('user_field', models.TextField(choices=[('username', 'Username'), ('first_name', 'First Name'), ('last_name', 'Last Name'), ('email', 'E-Mail'), ('is_staff', 'Is staff'), ('is_active', 'Is active'), ('data_joined', 'Date joined')])),
('match_action', models.CharField(choices=[('startswith', 'Starts with'), ('endswith', 'Ends with'), ('endswith', 'Contains'), ('regexp', 'Regexp'), ('exact', 'Exact')], max_length=50)),
('value', models.TextField()),
],
options={
'verbose_name': 'Field matcher Policy',
'verbose_name_plural': 'Field matcher Policys',
},
bases=('passbook_core.policy',),
),
migrations.CreateModel(
name='PasswordPolicyPolicy',
fields=[
('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
('amount_uppercase', models.IntegerField(default=0)),
('amount_lowercase', models.IntegerField(default=0)),
('amount_symbols', models.IntegerField(default=0)),
('length_min', models.IntegerField(default=0)),
('symbol_charset', models.TextField(default='!\\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ ')),
],
options={
'verbose_name': 'Password Policy Policy',
'verbose_name_plural': 'Password Policy Policys',
},
bases=('passbook_core.policy',),
),
migrations.CreateModel(
name='Source',
fields=[
('policymodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.PolicyModel')),
('name', models.TextField()),
('slug', models.SlugField()),
('enabled', models.BooleanField(default=True)),
],
options={
'abstract': False,
},
bases=('passbook_core.policymodel',),
),
migrations.CreateModel(
name='WebhookPolicy',
fields=[
('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
('url', models.URLField()),
('method', models.CharField(choices=[('GET', 'GET'), ('POST', 'POST'), ('PATCH', 'PATCH'), ('DELETE', 'DELETE'), ('PUT', 'PUT')], max_length=10)),
('json_body', models.TextField()),
('json_headers', models.TextField()),
('result_jsonpath', models.TextField()),
('result_json_value', models.TextField()),
],
options={
'verbose_name': 'Webhook Policy',
'verbose_name_plural': 'Webhook Policys',
},
bases=('passbook_core.policy',),
),
migrations.AddField(
model_name='policymodel',
name='policies',
field=models.ManyToManyField(blank=True, to='passbook_core.Policy'),
),
migrations.AddField(
model_name='user',
name='groups',
field=models.ManyToManyField(to='passbook_core.Group'),
),
migrations.AddField(
model_name='user',
name='user_permissions',
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
),
migrations.AddField(
model_name='usersourceconnection',
name='source',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='passbook_core.Source'),
),
migrations.AlterUniqueTogether(
name='group',
unique_together={('name', 'parent')},
),
migrations.AddField(
model_name='user',
name='applications',
field=models.ManyToManyField(to='passbook_core.Application'),
),
migrations.AddField(
model_name='user',
name='sources',
field=models.ManyToManyField(through='passbook_core.UserSourceConnection', to='passbook_core.Source'),
),
migrations.AlterUniqueTogether(
name='usersourceconnection',
unique_together={('user', 'source')},
),
]

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