| 119 | @param('tfa', Types.String, true) |
| 120 | @param('authnChallenge', Types.String, true) |
| 121 | async post(domainId: string, password = '', tfa = '', authnChallenge = '') { |
| 122 | if (!this.session.sudoArgs?.method) throw new ForbiddenError(); |
| 123 | await Promise.all([ |
| 124 | this.limitRate('user_sudo', 60, 5, '{{user}}'), |
| 125 | oplog.log(this, 'user.sudo', {}), |
| 126 | ]); |
| 127 | if (this.user.authn && authnChallenge) { |
| 128 | const challenge = await token.get(authnChallenge, token.TYPE_WEBAUTHN); |
| 129 | if (challenge?.uid !== this.user._id) throw new InvalidTokenError(token.TYPE_TEXTS[token.TYPE_WEBAUTHN]); |
| 130 | if (!challenge.verified) throw new ValidationError('challenge'); |
| 131 | await token.del(authnChallenge, token.TYPE_WEBAUTHN); |
| 132 | } else if (this.user.tfa && tfa) { |
| 133 | if (!verifyTFA(this.user._tfa, tfa)) throw new InvalidTokenError('2FA'); |
| 134 | } else await this.user.checkPassword(password); |
| 135 | this.session.sudo = Date.now(); |
| 136 | if (this.session.sudoArgs.method.toLowerCase() !== 'get') { |
| 137 | this.response.template = 'user_sudo_redirect.html'; |
| 138 | this.response.body = this.session.sudoArgs; |
| 139 | } else this.response.redirect = this.session.sudoArgs.redirect; |
| 140 | this.session.sudoArgs.method = null; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | class UserTFAHandler extends Handler { |