zou 0.20.82__py3-none-any.whl → 0.20.83__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zou/__init__.py +1 -1
- zou/app/blueprints/assets/resources.py +1060 -153
- zou/app/blueprints/auth/resources.py +368 -238
- zou/app/blueprints/breakdown/resources.py +584 -94
- zou/app/blueprints/chats/resources.py +176 -37
- zou/app/blueprints/comments/resources.py +387 -125
- zou/app/blueprints/concepts/resources.py +428 -63
- zou/app/blueprints/departments/resources.py +302 -68
- zou/app/blueprints/edits/resources.py +651 -81
- zou/app/blueprints/entities/resources.py +104 -39
- zou/app/blueprints/events/resources.py +96 -8
- zou/app/blueprints/index/resources.py +49 -42
- zou/app/blueprints/news/resources.py +45 -27
- zou/app/blueprints/user/resources.py +1808 -215
- zou/app/swagger.py +100 -27
- {zou-0.20.82.dist-info → zou-0.20.83.dist-info}/METADATA +1 -1
- {zou-0.20.82.dist-info → zou-0.20.83.dist-info}/RECORD +21 -21
- {zou-0.20.82.dist-info → zou-0.20.83.dist-info}/WHEEL +0 -0
- {zou-0.20.82.dist-info → zou-0.20.83.dist-info}/entry_points.txt +0 -0
- {zou-0.20.82.dist-info → zou-0.20.83.dist-info}/licenses/LICENSE +0 -0
- {zou-0.20.82.dist-info → zou-0.20.83.dist-info}/top_level.txt +0 -0
|
@@ -29,7 +29,7 @@ from zou.app.services import (
|
|
|
29
29
|
persons_service,
|
|
30
30
|
auth_service,
|
|
31
31
|
events_service,
|
|
32
|
-
templates_service
|
|
32
|
+
templates_service,
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
from zou.app.utils.flask import is_from_browser
|
|
@@ -58,20 +58,15 @@ from zou.app.services.exception import (
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
class AuthenticatedResource(Resource):
|
|
61
|
-
"""
|
|
62
|
-
Returns information if the user is authenticated else it returns a 401
|
|
63
|
-
response.
|
|
64
|
-
It can be used by third party tools, especially browser frontend, to know
|
|
65
|
-
if current user is still logged in.
|
|
66
|
-
"""
|
|
67
61
|
|
|
68
62
|
@jwt_required()
|
|
69
63
|
def get(self):
|
|
70
64
|
"""
|
|
71
|
-
|
|
72
|
-
response.
|
|
65
|
+
Check authentication status
|
|
73
66
|
---
|
|
74
|
-
description:
|
|
67
|
+
description: Returns information if the user is authenticated.
|
|
68
|
+
It can be used by third party tools, especially browser frontend,
|
|
69
|
+
to know if current user is still logged in.
|
|
75
70
|
tags:
|
|
76
71
|
- Authentication
|
|
77
72
|
responses:
|
|
@@ -92,25 +87,19 @@ class AuthenticatedResource(Resource):
|
|
|
92
87
|
|
|
93
88
|
|
|
94
89
|
class LogoutResource(Resource):
|
|
95
|
-
"""
|
|
96
|
-
Log user out by revoking his auth tokens. Once log out, current user
|
|
97
|
-
cannot access to API anymore.
|
|
98
|
-
"""
|
|
99
90
|
|
|
100
91
|
@jwt_required()
|
|
101
92
|
@permissions.require_person
|
|
102
93
|
def get(self):
|
|
103
94
|
"""
|
|
104
|
-
|
|
95
|
+
Logout user
|
|
105
96
|
---
|
|
106
|
-
description: Once logged out, current user cannot access the API anymore.
|
|
97
|
+
description: Log user out by revoking auth tokens. Once logged out, current user cannot access the API anymore.
|
|
107
98
|
tags:
|
|
108
99
|
- Authentication
|
|
109
100
|
responses:
|
|
110
101
|
200:
|
|
111
102
|
description: Logout successful
|
|
112
|
-
500:
|
|
113
|
-
description: Access token not found
|
|
114
103
|
"""
|
|
115
104
|
try:
|
|
116
105
|
auth_service.logout(get_jwt()["jti"])
|
|
@@ -131,49 +120,61 @@ class LogoutResource(Resource):
|
|
|
131
120
|
|
|
132
121
|
|
|
133
122
|
class LoginResource(Resource, ArgsMixin):
|
|
134
|
-
"""
|
|
135
|
-
Log in user by creating and registering auth tokens. Login is based
|
|
136
|
-
on email and password. If no user match given email and a destkop ID,
|
|
137
|
-
it looks in matching the desktop ID with the one stored in database. It is
|
|
138
|
-
useful for clients that run on desktop tools and that don't know user
|
|
139
|
-
email.
|
|
140
|
-
"""
|
|
141
123
|
|
|
142
124
|
def post(self):
|
|
143
125
|
"""
|
|
144
|
-
|
|
126
|
+
Login user
|
|
145
127
|
---
|
|
146
|
-
description:
|
|
147
|
-
|
|
148
|
-
|
|
128
|
+
description: Log in user by creating and registering auth tokens.
|
|
129
|
+
Login is based on email and password. If no user matches given email
|
|
130
|
+
It fallbacks to a desktop ID. It is useful for desktop tools that
|
|
131
|
+
don't know user email.
|
|
132
|
+
It is also possible to login with TOTP, Email OTP, FIDO and recovery
|
|
133
|
+
code.
|
|
149
134
|
tags:
|
|
150
135
|
- Authentication
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
136
|
+
requestBody:
|
|
137
|
+
required: true
|
|
138
|
+
content:
|
|
139
|
+
application/json:
|
|
140
|
+
schema:
|
|
141
|
+
type: object
|
|
142
|
+
properties:
|
|
143
|
+
email:
|
|
144
|
+
type: string
|
|
145
|
+
format: email
|
|
146
|
+
example: admin@example.com
|
|
147
|
+
description: User email address
|
|
148
|
+
password:
|
|
149
|
+
type: string
|
|
150
|
+
format: password
|
|
151
|
+
example: mysecretpassword
|
|
152
|
+
description: User password
|
|
153
|
+
required: true
|
|
154
|
+
totp:
|
|
155
|
+
type: string
|
|
156
|
+
example: 123456
|
|
157
|
+
description: TOTP verification code for two-factor authentication
|
|
158
|
+
required: false
|
|
159
|
+
email_otp:
|
|
160
|
+
type: string
|
|
161
|
+
example: 123456
|
|
162
|
+
description: Email OTP verification code for two-factor authentication
|
|
163
|
+
fido_authentication_response:
|
|
164
|
+
type: object
|
|
165
|
+
description: FIDO authentication response for WebAuth
|
|
166
|
+
recovery_code:
|
|
167
|
+
type: string
|
|
168
|
+
example: ABCD-EFGH-IJKL-MNOP
|
|
169
|
+
description: Recovery code for two-factor authentication
|
|
170
|
+
required:
|
|
171
|
+
- email
|
|
172
|
+
- password
|
|
170
173
|
responses:
|
|
171
174
|
200:
|
|
172
175
|
description: Login successful
|
|
173
176
|
400:
|
|
174
177
|
description: Login failed
|
|
175
|
-
500:
|
|
176
|
-
description: Database not reachable
|
|
177
178
|
"""
|
|
178
179
|
(
|
|
179
180
|
email,
|
|
@@ -372,9 +373,10 @@ class RefreshTokenResource(Resource):
|
|
|
372
373
|
@permissions.require_person
|
|
373
374
|
def get(self):
|
|
374
375
|
"""
|
|
375
|
-
|
|
376
|
+
Refresh access token
|
|
376
377
|
---
|
|
377
|
-
description:
|
|
378
|
+
description: Tokens are considered outdated every two weeks.
|
|
379
|
+
This route allows to extend their lifetime before they get outdated.
|
|
378
380
|
tags:
|
|
379
381
|
- Authentication
|
|
380
382
|
responses:
|
|
@@ -403,35 +405,43 @@ class RegistrationResource(Resource, ArgsMixin):
|
|
|
403
405
|
|
|
404
406
|
def post(self):
|
|
405
407
|
"""
|
|
406
|
-
|
|
408
|
+
Register new user
|
|
407
409
|
---
|
|
410
|
+
description: Allow a user to register himself to the service.
|
|
408
411
|
tags:
|
|
409
412
|
- Authentication
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
413
|
+
requestBody:
|
|
414
|
+
required: true
|
|
415
|
+
content:
|
|
416
|
+
application/json:
|
|
417
|
+
schema:
|
|
418
|
+
type: object
|
|
419
|
+
properties:
|
|
420
|
+
email:
|
|
421
|
+
type: string
|
|
422
|
+
format: email
|
|
423
|
+
example: admin@example.com
|
|
424
|
+
description: User email address
|
|
425
|
+
password:
|
|
426
|
+
type: string
|
|
427
|
+
format: password
|
|
428
|
+
description: User password
|
|
429
|
+
password_2:
|
|
430
|
+
type: string
|
|
431
|
+
format: password
|
|
432
|
+
description: Password confirmation
|
|
433
|
+
first_name:
|
|
434
|
+
type: string
|
|
435
|
+
description: User first name
|
|
436
|
+
last_name:
|
|
437
|
+
type: string
|
|
438
|
+
description: User last name
|
|
439
|
+
required:
|
|
440
|
+
- email
|
|
441
|
+
- password
|
|
442
|
+
- password_2
|
|
443
|
+
- first_name
|
|
444
|
+
- last_name
|
|
435
445
|
responses:
|
|
436
446
|
201:
|
|
437
447
|
description: Registration successful
|
|
@@ -508,42 +518,41 @@ class RegistrationResource(Resource, ArgsMixin):
|
|
|
508
518
|
|
|
509
519
|
|
|
510
520
|
class ChangePasswordResource(Resource, ArgsMixin):
|
|
511
|
-
"""
|
|
512
|
-
Allow the user to change his password. Prior to modify the password,
|
|
513
|
-
it requires to give the current password (to make sure the user changing
|
|
514
|
-
the password is not someone who stealed the session).
|
|
515
|
-
The new password requires a confirmation to ensure that the user didn't
|
|
516
|
-
make mistake by typing his new password.
|
|
517
|
-
"""
|
|
518
521
|
|
|
519
522
|
@jwt_required()
|
|
520
523
|
@permissions.require_person
|
|
521
524
|
def post(self):
|
|
522
525
|
"""
|
|
523
|
-
|
|
526
|
+
Change user password
|
|
524
527
|
---
|
|
525
|
-
description:
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
make a mistake by typing his new password.
|
|
528
|
+
description: Allow the user to change his password. Requires current
|
|
529
|
+
password for verification and password confirmation to ensure
|
|
530
|
+
accuracy.
|
|
529
531
|
tags:
|
|
530
532
|
- Authentication
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
533
|
+
requestBody:
|
|
534
|
+
required: true
|
|
535
|
+
content:
|
|
536
|
+
application/json:
|
|
537
|
+
schema:
|
|
538
|
+
type: object
|
|
539
|
+
properties:
|
|
540
|
+
old_password:
|
|
541
|
+
type: string
|
|
542
|
+
format: password
|
|
543
|
+
description: Current password
|
|
544
|
+
password:
|
|
545
|
+
type: string
|
|
546
|
+
format: password
|
|
547
|
+
description: New password
|
|
548
|
+
password_2:
|
|
549
|
+
type: string
|
|
550
|
+
format: password
|
|
551
|
+
description: New password confirmation
|
|
552
|
+
required:
|
|
553
|
+
- old_password
|
|
554
|
+
- password
|
|
555
|
+
- password_2
|
|
547
556
|
responses:
|
|
548
557
|
200:
|
|
549
558
|
description: Password changed
|
|
@@ -625,42 +634,45 @@ Your IP when you have changed your password is: {person_IP}.
|
|
|
625
634
|
|
|
626
635
|
|
|
627
636
|
class ResetPasswordResource(Resource, ArgsMixin):
|
|
628
|
-
"""
|
|
629
|
-
Resource to allow a user to change his password when he forgets it.
|
|
630
|
-
It uses a classic scheme: a token is sent by email to the user. Then
|
|
631
|
-
he can change his password.
|
|
632
|
-
"""
|
|
633
637
|
|
|
634
638
|
def put(self):
|
|
635
639
|
"""
|
|
636
|
-
|
|
640
|
+
Reset password with token
|
|
637
641
|
---
|
|
638
|
-
description:
|
|
639
|
-
|
|
642
|
+
description: Allow a user to change his password when he forgets it.
|
|
643
|
+
It uses a token sent by email to the user to verify it is the user
|
|
644
|
+
who requested the password reset.
|
|
640
645
|
tags:
|
|
641
646
|
- Authentication
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
647
|
+
requestBody:
|
|
648
|
+
required: true
|
|
649
|
+
content:
|
|
650
|
+
application/json:
|
|
651
|
+
schema:
|
|
652
|
+
type: object
|
|
653
|
+
properties:
|
|
654
|
+
email:
|
|
655
|
+
type: string
|
|
656
|
+
format: email
|
|
657
|
+
example: admin@example.com
|
|
658
|
+
description: User email address
|
|
659
|
+
token:
|
|
660
|
+
type: string
|
|
661
|
+
format: JWT token
|
|
662
|
+
description: Password reset token
|
|
663
|
+
password:
|
|
664
|
+
type: string
|
|
665
|
+
format: password
|
|
666
|
+
description: New password
|
|
667
|
+
password2:
|
|
668
|
+
type: string
|
|
669
|
+
format: password
|
|
670
|
+
description: New password confirmation
|
|
671
|
+
required:
|
|
672
|
+
- email
|
|
673
|
+
- token
|
|
674
|
+
- password
|
|
675
|
+
- password2
|
|
664
676
|
responses:
|
|
665
677
|
200:
|
|
666
678
|
description: Password reset
|
|
@@ -712,19 +724,26 @@ class ResetPasswordResource(Resource, ArgsMixin):
|
|
|
712
724
|
|
|
713
725
|
def post(self):
|
|
714
726
|
"""
|
|
715
|
-
|
|
727
|
+
Request password reset
|
|
716
728
|
---
|
|
717
|
-
description:
|
|
718
|
-
|
|
729
|
+
description: Send a password reset token by email to the user.
|
|
730
|
+
It uses a classic scheme where a token is sent by email.
|
|
719
731
|
tags:
|
|
720
732
|
- Authentication
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
733
|
+
requestBody:
|
|
734
|
+
required: true
|
|
735
|
+
content:
|
|
736
|
+
application/json:
|
|
737
|
+
schema:
|
|
738
|
+
type: object
|
|
739
|
+
properties:
|
|
740
|
+
email:
|
|
741
|
+
type: string
|
|
742
|
+
format: email
|
|
743
|
+
example: admin@example.com
|
|
744
|
+
description: User email address
|
|
745
|
+
required:
|
|
746
|
+
- email
|
|
728
747
|
responses:
|
|
729
748
|
200:
|
|
730
749
|
description: Reset token sent
|
|
@@ -789,26 +808,22 @@ The IP of the person who requested this is: {person_IP}.
|
|
|
789
808
|
|
|
790
809
|
|
|
791
810
|
class TOTPResource(Resource, ArgsMixin):
|
|
792
|
-
"""
|
|
793
|
-
Resource to allow a user to enable/disable TOTP.
|
|
794
|
-
"""
|
|
795
811
|
|
|
796
812
|
@jwt_required()
|
|
797
813
|
@permissions.require_person
|
|
798
814
|
def put(self):
|
|
799
815
|
"""
|
|
800
|
-
|
|
816
|
+
Pre-enable TOTP
|
|
801
817
|
---
|
|
802
|
-
description:
|
|
818
|
+
description: Prepare TOTP (Time-based One-Time Password) for enabling.
|
|
819
|
+
It returns provisioning URI and secret for authenticator app setup.
|
|
803
820
|
tags:
|
|
804
821
|
- Authentication
|
|
805
822
|
responses:
|
|
806
823
|
200:
|
|
807
|
-
description: TOTP enabled
|
|
824
|
+
description: TOTP pre-enabled
|
|
808
825
|
400:
|
|
809
|
-
description:
|
|
810
|
-
Wrong or expired token
|
|
811
|
-
Inactive user
|
|
826
|
+
description: TOTP already enabled
|
|
812
827
|
"""
|
|
813
828
|
try:
|
|
814
829
|
totp_provisionning_uri, totp_secret = auth_service.pre_enable_totp(
|
|
@@ -828,18 +843,29 @@ class TOTPResource(Resource, ArgsMixin):
|
|
|
828
843
|
@permissions.require_person
|
|
829
844
|
def post(self):
|
|
830
845
|
"""
|
|
831
|
-
|
|
846
|
+
Enable TOTP
|
|
832
847
|
---
|
|
833
|
-
description:
|
|
848
|
+
description: Enable TOTP (Time-based One-Time Password) authentication.
|
|
849
|
+
It requires verification code from authenticator app.
|
|
834
850
|
tags:
|
|
835
851
|
- Authentication
|
|
852
|
+
requestBody:
|
|
853
|
+
required: true
|
|
854
|
+
content:
|
|
855
|
+
application/json:
|
|
856
|
+
schema:
|
|
857
|
+
type: object
|
|
858
|
+
properties:
|
|
859
|
+
totp:
|
|
860
|
+
type: string
|
|
861
|
+
description: TOTP verification code from authenticator app
|
|
862
|
+
required:
|
|
863
|
+
- totp
|
|
836
864
|
responses:
|
|
837
865
|
200:
|
|
838
866
|
description: TOTP enabled
|
|
839
867
|
400:
|
|
840
|
-
description:
|
|
841
|
-
Wrong or expired token
|
|
842
|
-
Inactive user
|
|
868
|
+
description: TOTP already enabled or verification failed
|
|
843
869
|
"""
|
|
844
870
|
args = self.get_args([("totp", "", True)])
|
|
845
871
|
|
|
@@ -867,16 +893,36 @@ class TOTPResource(Resource, ArgsMixin):
|
|
|
867
893
|
@permissions.require_person
|
|
868
894
|
def delete(self):
|
|
869
895
|
"""
|
|
870
|
-
|
|
896
|
+
Disable TOTP
|
|
871
897
|
---
|
|
872
|
-
description:
|
|
898
|
+
description: Disable TOTP (Time-based One-Time Password) authentication.
|
|
899
|
+
It requires two-factor authentication verification.
|
|
873
900
|
tags:
|
|
874
901
|
- Authentication
|
|
902
|
+
requestBody:
|
|
903
|
+
required: true
|
|
904
|
+
content:
|
|
905
|
+
application/json:
|
|
906
|
+
schema:
|
|
907
|
+
type: object
|
|
908
|
+
properties:
|
|
909
|
+
totp:
|
|
910
|
+
type: string
|
|
911
|
+
description: TOTP verification code
|
|
912
|
+
email_otp:
|
|
913
|
+
type: string
|
|
914
|
+
description: Email OTP verification code
|
|
915
|
+
fido_authentication_response:
|
|
916
|
+
type: object
|
|
917
|
+
description: FIDO authentication response
|
|
918
|
+
recovery_code:
|
|
919
|
+
type: string
|
|
920
|
+
description: Recovery code for two-factor authentication
|
|
875
921
|
responses:
|
|
876
922
|
200:
|
|
877
923
|
description: TOTP disabled
|
|
878
924
|
400:
|
|
879
|
-
description: TOTP not enabled
|
|
925
|
+
description: TOTP not enabled or verification failed
|
|
880
926
|
"""
|
|
881
927
|
args = self.get_args(
|
|
882
928
|
[
|
|
@@ -920,25 +966,27 @@ class TOTPResource(Resource, ArgsMixin):
|
|
|
920
966
|
|
|
921
967
|
|
|
922
968
|
class EmailOTPResource(Resource, ArgsMixin):
|
|
923
|
-
"""
|
|
924
|
-
Resource to allow a user to enable/disable OTP by email or to send an OTP
|
|
925
|
-
by email.
|
|
926
|
-
"""
|
|
927
969
|
|
|
928
970
|
def get(self):
|
|
929
971
|
"""
|
|
930
|
-
|
|
972
|
+
Send email OTP
|
|
931
973
|
---
|
|
932
|
-
description:
|
|
974
|
+
description: Send a one-time password by email to the user for
|
|
975
|
+
authentication.
|
|
933
976
|
tags:
|
|
934
977
|
- Authentication
|
|
978
|
+
parameters:
|
|
979
|
+
- in: query
|
|
980
|
+
name: email
|
|
981
|
+
required: True
|
|
982
|
+
type: string
|
|
983
|
+
format: email
|
|
984
|
+
description: User email address
|
|
935
985
|
responses:
|
|
936
986
|
200:
|
|
937
987
|
description: OTP by email sent
|
|
938
988
|
400:
|
|
939
|
-
description:
|
|
940
|
-
Wrong or expired token
|
|
941
|
-
Inactive user
|
|
989
|
+
description: OTP by email not enabled
|
|
942
990
|
"""
|
|
943
991
|
args = self.get_args(
|
|
944
992
|
[
|
|
@@ -973,18 +1021,17 @@ class EmailOTPResource(Resource, ArgsMixin):
|
|
|
973
1021
|
@permissions.require_person
|
|
974
1022
|
def put(self):
|
|
975
1023
|
"""
|
|
976
|
-
|
|
1024
|
+
Pre-enable email OTP
|
|
977
1025
|
---
|
|
978
|
-
description:
|
|
1026
|
+
description: Prepare email OTP (One-Time Password) for enabling.
|
|
1027
|
+
It sets up email-based two-factor authentication.
|
|
979
1028
|
tags:
|
|
980
1029
|
- Authentication
|
|
981
1030
|
responses:
|
|
982
1031
|
200:
|
|
983
|
-
description: OTP
|
|
1032
|
+
description: Email OTP pre-enabled
|
|
984
1033
|
400:
|
|
985
|
-
description:
|
|
986
|
-
Wrong or expired token
|
|
987
|
-
Inactive user
|
|
1034
|
+
description: Email OTP already enabled
|
|
988
1035
|
"""
|
|
989
1036
|
try:
|
|
990
1037
|
auth_service.pre_enable_email_otp(
|
|
@@ -1001,18 +1048,29 @@ class EmailOTPResource(Resource, ArgsMixin):
|
|
|
1001
1048
|
@permissions.require_person
|
|
1002
1049
|
def post(self):
|
|
1003
1050
|
"""
|
|
1004
|
-
|
|
1051
|
+
Enable email OTP
|
|
1005
1052
|
---
|
|
1006
|
-
description:
|
|
1053
|
+
description: Enable email OTP (One-Time Password) authentication.
|
|
1054
|
+
It requires verification code sent to email.
|
|
1007
1055
|
tags:
|
|
1008
1056
|
- Authentication
|
|
1057
|
+
requestBody:
|
|
1058
|
+
required: true
|
|
1059
|
+
content:
|
|
1060
|
+
application/json:
|
|
1061
|
+
schema:
|
|
1062
|
+
type: object
|
|
1063
|
+
properties:
|
|
1064
|
+
email_otp:
|
|
1065
|
+
type: string
|
|
1066
|
+
description: Email OTP verification code
|
|
1067
|
+
required:
|
|
1068
|
+
- email_otp
|
|
1009
1069
|
responses:
|
|
1010
1070
|
200:
|
|
1011
|
-
description: OTP
|
|
1071
|
+
description: Email OTP enabled
|
|
1012
1072
|
400:
|
|
1013
|
-
description:
|
|
1014
|
-
Wrong or expired token
|
|
1015
|
-
Inactive user
|
|
1073
|
+
description: Email OTP already enabled or verification failed
|
|
1016
1074
|
"""
|
|
1017
1075
|
args = self.get_args([("email_otp", "", True)])
|
|
1018
1076
|
|
|
@@ -1041,19 +1099,36 @@ class EmailOTPResource(Resource, ArgsMixin):
|
|
|
1041
1099
|
@permissions.require_person
|
|
1042
1100
|
def delete(self):
|
|
1043
1101
|
"""
|
|
1044
|
-
|
|
1102
|
+
Disable email OTP
|
|
1045
1103
|
---
|
|
1046
|
-
description:
|
|
1104
|
+
description: Disable email OTP (One-Time Password) authentication.
|
|
1105
|
+
It requires two-factor authentication verification.
|
|
1047
1106
|
tags:
|
|
1048
1107
|
- Authentication
|
|
1108
|
+
requestBody:
|
|
1109
|
+
required: true
|
|
1110
|
+
content:
|
|
1111
|
+
application/json:
|
|
1112
|
+
schema:
|
|
1113
|
+
type: object
|
|
1114
|
+
properties:
|
|
1115
|
+
totp:
|
|
1116
|
+
type: string
|
|
1117
|
+
description: TOTP verification code
|
|
1118
|
+
email_otp:
|
|
1119
|
+
type: string
|
|
1120
|
+
description: Email OTP verification code
|
|
1121
|
+
fido_authentication_response:
|
|
1122
|
+
type: object
|
|
1123
|
+
description: FIDO authentication response
|
|
1124
|
+
recovery_code:
|
|
1125
|
+
type: string
|
|
1126
|
+
description: Recovery code for two-factor authentication
|
|
1049
1127
|
responses:
|
|
1050
1128
|
200:
|
|
1051
|
-
description: OTP
|
|
1129
|
+
description: Email OTP disabled
|
|
1052
1130
|
400:
|
|
1053
|
-
description:
|
|
1054
|
-
Wrong or expired token.
|
|
1055
|
-
Inactive user.
|
|
1056
|
-
Wrong 2FA.
|
|
1131
|
+
description: Email OTP not enabled or verification failed
|
|
1057
1132
|
"""
|
|
1058
1133
|
args = self.get_args(
|
|
1059
1134
|
[
|
|
@@ -1104,16 +1179,24 @@ class FIDOResource(Resource, ArgsMixin):
|
|
|
1104
1179
|
|
|
1105
1180
|
def get(self):
|
|
1106
1181
|
"""
|
|
1107
|
-
|
|
1182
|
+
Get FIDO challenge
|
|
1108
1183
|
---
|
|
1109
|
-
description:
|
|
1184
|
+
description: Get a challenge for FIDO device authentication.
|
|
1185
|
+
It is used for WebAuthn authentication flow.
|
|
1110
1186
|
tags:
|
|
1111
1187
|
- Authentication
|
|
1188
|
+
parameters:
|
|
1189
|
+
- in: query
|
|
1190
|
+
name: email
|
|
1191
|
+
required: True
|
|
1192
|
+
type: string
|
|
1193
|
+
format: email
|
|
1194
|
+
description: User email address
|
|
1112
1195
|
responses:
|
|
1113
1196
|
200:
|
|
1114
|
-
description:
|
|
1197
|
+
description: FIDO challenge generated
|
|
1115
1198
|
400:
|
|
1116
|
-
description:
|
|
1199
|
+
description: FIDO not enabled
|
|
1117
1200
|
"""
|
|
1118
1201
|
args = self.get_args(
|
|
1119
1202
|
[
|
|
@@ -1147,18 +1230,17 @@ class FIDOResource(Resource, ArgsMixin):
|
|
|
1147
1230
|
@permissions.require_person
|
|
1148
1231
|
def put(self):
|
|
1149
1232
|
"""
|
|
1150
|
-
|
|
1233
|
+
Pre-register FIDO device
|
|
1151
1234
|
---
|
|
1152
|
-
description:
|
|
1235
|
+
description: Prepare FIDO device for registration.
|
|
1236
|
+
It returns registration options for WebAuthn.
|
|
1153
1237
|
tags:
|
|
1154
1238
|
- Authentication
|
|
1155
1239
|
responses:
|
|
1156
1240
|
200:
|
|
1157
|
-
description: FIDO device pre-registered
|
|
1241
|
+
description: FIDO device pre-registered data
|
|
1158
1242
|
400:
|
|
1159
|
-
description: Invalid
|
|
1160
|
-
Wrong or expired token
|
|
1161
|
-
Inactive user
|
|
1243
|
+
description: Invalid request
|
|
1162
1244
|
"""
|
|
1163
1245
|
return auth_service.pre_register_fido(
|
|
1164
1246
|
persons_service.get_current_user()["id"]
|
|
@@ -1168,18 +1250,33 @@ class FIDOResource(Resource, ArgsMixin):
|
|
|
1168
1250
|
@jwt_required()
|
|
1169
1251
|
def post(self):
|
|
1170
1252
|
"""
|
|
1171
|
-
|
|
1253
|
+
Register FIDO device
|
|
1172
1254
|
---
|
|
1173
|
-
description:
|
|
1255
|
+
description: Register a FIDO device for WebAuthn authentication.
|
|
1256
|
+
It requires registration response from the device.
|
|
1174
1257
|
tags:
|
|
1175
1258
|
- Authentication
|
|
1259
|
+
requestBody:
|
|
1260
|
+
required: true
|
|
1261
|
+
content:
|
|
1262
|
+
application/json:
|
|
1263
|
+
schema:
|
|
1264
|
+
type: object
|
|
1265
|
+
properties:
|
|
1266
|
+
registration_response:
|
|
1267
|
+
type: object
|
|
1268
|
+
description: FIDO device registration response
|
|
1269
|
+
device_name:
|
|
1270
|
+
type: string
|
|
1271
|
+
description: Name for the FIDO device
|
|
1272
|
+
required:
|
|
1273
|
+
- registration_response
|
|
1274
|
+
- device_name
|
|
1176
1275
|
responses:
|
|
1177
1276
|
200:
|
|
1178
|
-
description: FIDO device registered
|
|
1277
|
+
description: FIDO device registered
|
|
1179
1278
|
400:
|
|
1180
|
-
description:
|
|
1181
|
-
Wrong or expired token
|
|
1182
|
-
Inactive user
|
|
1279
|
+
description: Registration failed or no preregistration
|
|
1183
1280
|
"""
|
|
1184
1281
|
try:
|
|
1185
1282
|
args = self.get_args(
|
|
@@ -1213,19 +1310,41 @@ class FIDOResource(Resource, ArgsMixin):
|
|
|
1213
1310
|
@permissions.require_person
|
|
1214
1311
|
def delete(self):
|
|
1215
1312
|
"""
|
|
1216
|
-
|
|
1313
|
+
Unregister FIDO device
|
|
1217
1314
|
---
|
|
1218
|
-
description:
|
|
1315
|
+
description: Unregister a FIDO device from WebAuthn authentication.
|
|
1316
|
+
It requires two-factor authentication verification.
|
|
1219
1317
|
tags:
|
|
1220
1318
|
- Authentication
|
|
1319
|
+
requestBody:
|
|
1320
|
+
required: true
|
|
1321
|
+
content:
|
|
1322
|
+
application/json:
|
|
1323
|
+
schema:
|
|
1324
|
+
type: object
|
|
1325
|
+
properties:
|
|
1326
|
+
totp:
|
|
1327
|
+
type: string
|
|
1328
|
+
description: TOTP verification code
|
|
1329
|
+
email_otp:
|
|
1330
|
+
type: string
|
|
1331
|
+
description: Email OTP verification code
|
|
1332
|
+
fido_authentication_response:
|
|
1333
|
+
type: object
|
|
1334
|
+
description: FIDO authentication response
|
|
1335
|
+
recovery_code:
|
|
1336
|
+
type: string
|
|
1337
|
+
description: Recovery code for two-factor authentication
|
|
1338
|
+
device_name:
|
|
1339
|
+
type: string
|
|
1340
|
+
description: Name of the FIDO device to unregister
|
|
1341
|
+
required:
|
|
1342
|
+
- device_name
|
|
1221
1343
|
responses:
|
|
1222
1344
|
200:
|
|
1223
|
-
description: FIDO device unregistered
|
|
1345
|
+
description: FIDO device unregistered
|
|
1224
1346
|
400:
|
|
1225
|
-
description:
|
|
1226
|
-
Wrong or expired token
|
|
1227
|
-
Inactive user
|
|
1228
|
-
Wrong 2FA
|
|
1347
|
+
description: FIDO not enabled or verification failed
|
|
1229
1348
|
"""
|
|
1230
1349
|
args = self.get_args(
|
|
1231
1350
|
[
|
|
@@ -1270,26 +1389,41 @@ class FIDOResource(Resource, ArgsMixin):
|
|
|
1270
1389
|
|
|
1271
1390
|
|
|
1272
1391
|
class RecoveryCodesResource(Resource, ArgsMixin):
|
|
1273
|
-
"""
|
|
1274
|
-
Resource to allow a user to generate new recovery codes.
|
|
1275
|
-
"""
|
|
1276
1392
|
|
|
1277
1393
|
@jwt_required()
|
|
1278
1394
|
@permissions.require_person
|
|
1279
1395
|
def put(self):
|
|
1280
1396
|
"""
|
|
1281
|
-
|
|
1397
|
+
Generate recovery codes
|
|
1282
1398
|
---
|
|
1283
|
-
description:
|
|
1399
|
+
description: Generate new recovery codes for two-factor authentication.
|
|
1400
|
+
It requires two-factor authentication verification.
|
|
1284
1401
|
tags:
|
|
1285
1402
|
- Authentication
|
|
1403
|
+
requestBody:
|
|
1404
|
+
required: true
|
|
1405
|
+
content:
|
|
1406
|
+
application/json:
|
|
1407
|
+
schema:
|
|
1408
|
+
type: object
|
|
1409
|
+
properties:
|
|
1410
|
+
totp:
|
|
1411
|
+
type: string
|
|
1412
|
+
description: TOTP verification code
|
|
1413
|
+
email_otp:
|
|
1414
|
+
type: string
|
|
1415
|
+
description: Email OTP verification code
|
|
1416
|
+
fido_authentication_response:
|
|
1417
|
+
type: object
|
|
1418
|
+
description: FIDO authentication response
|
|
1419
|
+
recovery_code:
|
|
1420
|
+
type: string
|
|
1421
|
+
description: Recovery code for two-factor authentication
|
|
1286
1422
|
responses:
|
|
1287
1423
|
200:
|
|
1288
|
-
description:
|
|
1424
|
+
description: New recovery codes generated
|
|
1289
1425
|
400:
|
|
1290
|
-
description:
|
|
1291
|
-
Wrong or expired token
|
|
1292
|
-
Inactive user
|
|
1426
|
+
description: No two-factor authentication enabled or verification failed
|
|
1293
1427
|
"""
|
|
1294
1428
|
args = self.get_args(
|
|
1295
1429
|
[
|
|
@@ -1338,22 +1472,20 @@ class RecoveryCodesResource(Resource, ArgsMixin):
|
|
|
1338
1472
|
|
|
1339
1473
|
|
|
1340
1474
|
class SAMLSSOResource(Resource, ArgsMixin):
|
|
1341
|
-
"""
|
|
1342
|
-
Resource to allow a user to login with SAML SSO.
|
|
1343
|
-
"""
|
|
1344
|
-
|
|
1345
1475
|
def post(self):
|
|
1346
1476
|
"""
|
|
1347
|
-
|
|
1477
|
+
SAML SSO login
|
|
1348
1478
|
---
|
|
1349
|
-
description:
|
|
1479
|
+
description: Handle SAML SSO login response. Processes authentication
|
|
1480
|
+
response from SAML identity provider and creates a new user if they
|
|
1481
|
+
don't exist.
|
|
1350
1482
|
tags:
|
|
1351
1483
|
- Authentication
|
|
1352
1484
|
responses:
|
|
1353
1485
|
302:
|
|
1354
|
-
description: Login successful, redirect to
|
|
1486
|
+
description: Login successful, redirect to home page
|
|
1355
1487
|
400:
|
|
1356
|
-
description:
|
|
1488
|
+
description: SAML not enabled or wrong parameter
|
|
1357
1489
|
"""
|
|
1358
1490
|
if not config.SAML_ENABLED:
|
|
1359
1491
|
return {"error": "SAML is not enabled."}, 400
|
|
@@ -1429,22 +1561,20 @@ class SAMLSSOResource(Resource, ArgsMixin):
|
|
|
1429
1561
|
|
|
1430
1562
|
|
|
1431
1563
|
class SAMLLoginResource(Resource, ArgsMixin):
|
|
1432
|
-
"""
|
|
1433
|
-
Resource to allow a user to login with SAML SSO.
|
|
1434
|
-
"""
|
|
1435
1564
|
|
|
1436
1565
|
def get(self):
|
|
1437
1566
|
"""
|
|
1438
|
-
|
|
1567
|
+
SAML SSO login redirect
|
|
1439
1568
|
---
|
|
1440
|
-
description:
|
|
1569
|
+
description: Initiate SAML SSO login by redirecting to SAML identity
|
|
1570
|
+
provider.
|
|
1441
1571
|
tags:
|
|
1442
1572
|
- Authentication
|
|
1443
1573
|
responses:
|
|
1444
1574
|
302:
|
|
1445
|
-
description: Redirect to
|
|
1575
|
+
description: Redirect to SAML identity provider
|
|
1446
1576
|
400:
|
|
1447
|
-
description:
|
|
1577
|
+
description: SAML not enabled or wrong parameter
|
|
1448
1578
|
"""
|
|
1449
1579
|
if not config.SAML_ENABLED:
|
|
1450
1580
|
return {"error": "SAML is not enabled."}, 400
|