Coverage for gws-app/gws/plugin/account/account_action.py: 0%
80 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
1"""User account action."""
3from typing import Optional, cast
5import gws
6import gws.config.util
7import gws.base.action
8import gws.lib.mime
10from . import core, helper
12gws.ext.new.action('account')
15class Config(gws.base.action.Config):
16 """User Account action. (added in 8.1)"""
17 pass
20class Props(gws.base.action.Props):
21 pass
24class MfaProps(gws.Data):
25 index: int
26 title: str
27 qrCode: str
30class OnboardingStartRequest(gws.Request):
31 tc: str
34class OnboardingStartResponse(gws.Response):
35 tc: str
38class OnboardingSavePasswordRequest(gws.Request):
39 tc: str
40 email: str
41 password1: str
42 password2: str
45class OnboardingSavePasswordResponse(gws.Response):
46 tc: str
47 ok: bool
48 complete: bool
49 completionUrl: str
50 mfaList: list[MfaProps]
53class OnboardingSaveMfaRequest(gws.Request):
54 tc: str
55 mfaIndex: Optional[int]
58class OnboardingSaveMfaResponse(gws.Response):
59 complete: bool
60 completionUrl: str
63class Object(gws.base.action.Object):
64 h: helper.Object
66 def configure(self):
67 self.h = cast(helper.Object, self.root.app.helper('account'))
69 @gws.ext.command.api('accountOnboardingStart')
70 def onboarding_start(self, req: gws.WebRequester, p: OnboardingStartRequest) -> OnboardingStartResponse:
71 account = self.get_account_by_tc(p.tc, core.Category.onboarding, core.Status.new)
72 self.h.set_status(account, core.Status.onboarding)
73 return OnboardingStartResponse(
74 tc=self.h.generate_tc(account, core.Category.onboarding)
75 )
77 @gws.ext.command.api('accountOnboardingSavePassword')
78 def onboarding_save_password(self, req: gws.WebRequester, p: OnboardingSavePasswordRequest) -> OnboardingSavePasswordResponse:
79 account = self.get_account_by_tc(p.tc, core.Category.onboarding, core.Status.onboarding)
81 p1 = p.password1
82 p2 = p.password2
84 if account.get('email') != p.email or p1 != p2 or not self.h.validate_password(p1):
85 return OnboardingSavePasswordResponse(
86 ok=False,
87 tc=self.h.generate_tc(account, core.Category.onboarding),
88 )
90 self.h.set_password(account, p1)
92 mfa = self.h.mfa_options(account)
93 if mfa:
94 mfa_secret = self.h.generate_mfa_secret(account)
95 return OnboardingSavePasswordResponse(
96 ok=True,
97 complete=False,
98 mfaList=self.mfa_props(account, mfa_secret),
99 tc=self.h.generate_tc(account, core.Category.onboarding),
100 )
102 self.h.set_status(account, core.Status.active)
103 self.h.clear_tc(account)
104 return OnboardingSavePasswordResponse(
105 ok=True,
106 complete=True,
107 completionUrl=self.h.onboardingCompletionUrl,
108 )
110 @gws.ext.command.api('accountOnboardingSaveMfa')
111 def onboarding_save_mfa(self, req: gws.WebRequester, p: OnboardingSaveMfaRequest) -> OnboardingSaveMfaResponse:
112 account = self.get_account_by_tc(p.tc, core.Category.onboarding, core.Status.onboarding)
114 self.h.set_mfa(account, p.mfaIndex)
115 self.h.set_status(account, core.Status.active)
116 self.h.clear_tc(account)
118 return OnboardingSaveMfaResponse(
119 complete=True,
120 completionUrl=self.h.onboardingCompletionUrl,
121 )
123 ##
125 def get_account_by_tc(self, tc, category, expected_status):
126 try:
127 account = self.h.get_account_by_tc(tc, category, expected_status)
128 except helper.Error as exc:
129 raise gws.ForbiddenError() from exc
131 if not account:
132 raise gws.ForbiddenError(f'account: {tc=} not found')
134 return account
136 def mfa_props(self, account: dict, mfa_secret):
137 ps = []
139 for mo in self.h.mfa_options(account):
140 ps.append(MfaProps(
141 index=mo.index,
142 title=mo.title,
143 qrCode=self.h.qr_code_for_mfa(account, mo, mfa_secret)
144 ))
146 return ps