...
1 package pin
2
3 import (
4 "errors"
5 "fmt"
6 "net/http"
7
8 "github.com/gin-gonic/gin"
9 "github.com/google/uuid"
10
11 "edge-infra.dev/pkg/edge/iam/apperror"
12 iamErrors "edge-infra.dev/pkg/edge/iam/errors"
13 "edge-infra.dev/pkg/edge/iam/log"
14 "edge-infra.dev/pkg/edge/iam/util"
15 )
16
17 type saveRequest struct {
18
19 Pin string `json:"pin" binding:"required,len=6"`
20 ConfirmPIN string `json:"pin_confirm" binding:"required,len=6"`
21 Action string `json:"action"`
22 }
23
24 func (pin *PIN) savePIN(c *gin.Context) error {
25 logger := log.Get(c.Request.Context()).WithName("save-pin")
26
27 req := c.Request
28 var reqBody saveRequest
29 if err := c.BindJSON(&reqBody); err != nil {
30 pin.metrics.IncSignUpRequestsTotal(signUpPin, util.Failed)
31 return apperror.NewAbortError(
32 fmt.Errorf("invalid save pin request body: %w", err),
33 http.StatusBadRequest)
34 }
35 err := req.ParseForm()
36 if err != nil {
37 return apperror.NewAbortError(
38 fmt.Errorf("failed to parse save pin request: %w", err),
39 http.StatusBadRequest)
40 }
41
42 session, _ := pin.sessionStore.Get(c.Request, "oauth2")
43 if session.Values["method"] != "federated" {
44 err := errors.New("no cloud login found in session. need strong auth to set PIN")
45 return apperror.NewAbortError(err, http.StatusForbidden)
46 }
47 sub, ok := session.Values["sub"]
48 if !ok {
49 err := errors.New("invalid session. could not find subject in the cookie session")
50 return apperror.NewAbortError(err, http.StatusUnauthorized)
51 }
52
53 subject := sub.(string)
54
55 switch reqBody.Action {
56 case "save":
57
58 err = pin.storage.SavePIN(c.Request.Context(), subject, reqBody.Pin)
59 if err != nil {
60 if err == iamErrors.ErrPINPreviouslyUsed {
61 return apperror.NewStatusError(err, http.StatusUnprocessableEntity)
62 }
63
64 return apperror.NewAbortError(
65 fmt.Errorf("failed to save pin: %w", err),
66 http.StatusInternalServerError)
67 }
68 case "cancel":
69 logger.Info(fmt.Sprintf("[%v] - 'cancel' action received, pin not set.", util.ShortOperationID(c.Request.Context())))
70 }
71
72
73 continuation := uuid.New().String()
74 session.Values["continuation"] = continuation
75
76
77 delete(session.Values, "reason")
78
79 err = session.Save(c.Request, c.Writer)
80 if err != nil {
81 return apperror.NewAbortError(
82 fmt.Errorf("failed to save cookie session: %w", err),
83 http.StatusInternalServerError)
84 }
85
86 pin.metrics.IncSignUpRequestsTotal(signUpPin, util.Succeeded)
87
88 return util.WriteJSON(c.Writer, http.StatusOK, gin.H{
89 "challenge": continuation,
90 })
91 }
92
View as plain text