...

Source file src/edge-infra.dev/pkg/edge/iam/barcode/emergency.go

Documentation: edge-infra.dev/pkg/edge/iam/barcode

     1  package barcode
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"edge-infra.dev/pkg/edge/iam/apperror"
     9  	"edge-infra.dev/pkg/edge/iam/config"
    10  	"edge-infra.dev/pkg/edge/iam/device"
    11  	"edge-infra.dev/pkg/edge/iam/profile"
    12  	"edge-infra.dev/pkg/edge/iam/prometheus"
    13  	"edge-infra.dev/pkg/edge/iam/util"
    14  
    15  	"github.com/gin-gonic/gin"
    16  	"github.com/google/uuid"
    17  	"github.com/gorilla/sessions"
    18  )
    19  
    20  type emergencyBarcodeRequest struct {
    21  	Username string `form:"username"`
    22  	Reason   string `form:"reason"`
    23  }
    24  type Emergency struct {
    25  	profileStorage profile.Storage
    26  	sessionStore   sessions.Store
    27  	deviceStorage  device.Storage
    28  }
    29  
    30  func NewEmergency(router *gin.Engine, sessionStore sessions.Store, storage interface{}, _ *prometheus.Metrics) *Emergency {
    31  	emergency := &Emergency{
    32  		profileStorage: storage.(profile.Storage),
    33  		sessionStore:   sessionStore,
    34  		deviceStorage:  storage.(device.Storage),
    35  	}
    36  
    37  	router.POST("/idp/handle-emergency", util.MakeHandlerFunc(emergency.handleEBCRequest))
    38  	return emergency
    39  }
    40  
    41  func (emergency *Emergency) handleEBCRequest(c *gin.Context) error {
    42  	var form emergencyBarcodeRequest
    43  	if err := c.ShouldBind(&form); err != nil {
    44  		return apperror.NewAbortError(
    45  			fmt.Errorf("invalid emergency barcode request: %w", err),
    46  			http.StatusBadRequest)
    47  	}
    48  
    49  	form.Username = strings.ToLower(form.Username)
    50  	session, _ := emergency.sessionStore.Get(c.Request, "oauth2")
    51  	switch form.Reason {
    52  	case "11":
    53  		session.Values["reason"] = form.Reason
    54  	default:
    55  		var subject string
    56  		if config.DeviceLoginEnabled() {
    57  			acc, err := emergency.deviceStorage.GetDeviceAccount(c, form.Username)
    58  			if err != nil {
    59  				return apperror.NewAbortError(
    60  					fmt.Errorf("failed to get a device account: %w", err),
    61  					http.StatusInternalServerError)
    62  			}
    63  			if acc == nil {
    64  				// there is no profile for this subject in db
    65  				return apperror.NewAbortError(
    66  					fmt.Errorf("device account not found (devicelogin=`%v`): %w", form.Username, err),
    67  					http.StatusBadRequest)
    68  			}
    69  			subject = acc.Subject
    70  		} else {
    71  			subject = form.Username
    72  		}
    73  		userProfile, err := emergency.profileStorage.GetIdentityProfile(c, subject)
    74  		if err != nil {
    75  			return apperror.NewAbortError(
    76  				fmt.Errorf("failed to get user profile: %w", err),
    77  				http.StatusInternalServerError)
    78  		}
    79  
    80  		if userProfile == nil {
    81  			// there is no profile for this subject in db
    82  			return apperror.NewAbortError(
    83  				fmt.Errorf("user profile not found (subject=`%v`): %w", form.Username, err),
    84  				http.StatusBadRequest)
    85  		}
    86  
    87  		// set to IssueEmergencyBarcode, to being issuing EBC in continuation.
    88  		session.Values["reason"] = "10"
    89  		// set issued by in session, to ensure clarity & readability of code.
    90  		session.Values["iby"] = session.Values["alias"]
    91  		session.Values["sub"] = userProfile.Alias
    92  		// set roles of user to which EBC is being issued as ebc-rls, so we can verify permissions later.
    93  		session.Values["ebc-rls"] = userProfile.Roles
    94  
    95  		if userProfile.Alias == "" {
    96  			err := emergency.profileStorage.AddAliasToProfile(c, userProfile)
    97  			if err != nil {
    98  				return apperror.NewAbortError(
    99  					fmt.Errorf("failed to add alias to profile: %w", err),
   100  					http.StatusInternalServerError)
   101  			}
   102  		}
   103  	}
   104  
   105  	continuation := uuid.New().String()
   106  	session.Values["continuation"] = continuation
   107  
   108  	err := session.Save(c.Request, c.Writer)
   109  	if err != nil {
   110  		return apperror.NewAbortError(
   111  			fmt.Errorf("failed to save cookie session: %w", err),
   112  			http.StatusInternalServerError)
   113  	}
   114  
   115  	return util.WriteJSON(c.Writer, http.StatusOK, gin.H{
   116  		"challenge": continuation,
   117  	})
   118  }
   119  

View as plain text