MCPcopy Index your code
hub / github.com/coder/coder / postChangePasswordWithOneTimePasscode

Method postChangePasswordWithOneTimePasscode

coderd/userauth.go:336–457  ·  view source on GitHub ↗

Change a users password with a one-time passcode. @Summary Change password with a one-time passcode @ID change-password-with-a-one-time-passcode @Accept json @Tags Authorization @Param request body codersdk.ChangePasswordWithOneTimePasscodeRequest true "Change password request" @Success 204 @Router

(rw http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

334// @Success 204
335// @Router /api/v2/users/otp/change-password [post]
336func (api *API) postChangePasswordWithOneTimePasscode(rw http.ResponseWriter, r *http.Request) {
337 var (
338 err error
339 ctx = r.Context()
340 auditor = api.Auditor.Load()
341 logger = api.Logger.Named(userAuthLoggerName)
342 aReq, commitAudit = audit.InitRequest[database.User](rw, &audit.RequestParams{
343 Audit: *auditor,
344 Log: api.Logger,
345 Request: r,
346 Action: database.AuditActionWrite,
347 })
348 )
349 defer commitAudit()
350
351 if api.DeploymentValues.DisablePasswordAuth {
352 httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
353 Message: "Password authentication is disabled.",
354 })
355 return
356 }
357
358 var req codersdk.ChangePasswordWithOneTimePasscodeRequest
359 if !httpapi.Read(ctx, rw, r, &req) {
360 return
361 }
362
363 if err := userpassword.Validate(req.Password); err != nil {
364 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
365 Message: "Invalid password.",
366 Validations: []codersdk.ValidationError{
367 {
368 Field: "password",
369 Detail: err.Error(),
370 },
371 },
372 })
373 return
374 }
375
376 err = api.Database.InTx(func(tx database.Store) error {
377 //nolint:gocritic // In order to change a user's password, we need to get the user first - and can only do that in the system auth context.
378 user, err := tx.GetUserByEmailOrUsername(dbauthz.AsSystemRestricted(ctx), database.GetUserByEmailOrUsernameParams{
379 Email: req.Email,
380 })
381 if err != nil && !errors.Is(err, sql.ErrNoRows) {
382 logger.Error(ctx, "unable to fetch user by email", slog.F("email", req.Email), slog.Error(err))
383 return xerrors.Errorf("get user by email: %w", err)
384 }
385 // We continue if err == sql.ErrNoRows to help prevent a timing-based attack.
386 aReq.Old = user
387 aReq.UserID = user.ID
388
389 equal, err := userpassword.Compare(string(user.HashedOneTimePasscode), req.OneTimePasscode)
390 if err != nil {
391 logger.Error(ctx, "unable to compare one-time passcode", slog.Error(err))
392 return xerrors.Errorf("compare one-time passcode: %w", err)
393 }

Callers

nothing calls this directly

Calls 15

InitRequestFunction · 0.92
WriteFunction · 0.92
ReadFunction · 0.92
ValidateFunction · 0.92
AsSystemRestrictedFunction · 0.92
CompareFunction · 0.92
NowFunction · 0.92
HashFunction · 0.92
NamedMethod · 0.80
ContextMethod · 0.65
InTxMethod · 0.65

Tested by

no test coverage detected