MCPcopy Create free account
hub / github.com/couchbase/sync_gateway / UpdatePrincipal

Method UpdatePrincipal

db/users.go:45–234  ·  view source on GitHub ↗

UpdatePrincipal updates or creates a principal from a PrincipalConfig structure.

(ctx context.Context, updates *auth.PrincipalConfig, isUser bool, allowReplace bool)

Source from the content-addressed store, hash-verified

43
44// UpdatePrincipal updates or creates a principal from a PrincipalConfig structure.
45func (dbc *DatabaseContext) UpdatePrincipal(ctx context.Context, updates *auth.PrincipalConfig, isUser bool, allowReplace bool) (replaced bool, princ auth.Principal, err error) {
46 // Sanity checking
47 if !base.AllOrNoneNil(updates.JWTIssuer, updates.JWTRoles, updates.JWTChannels) {
48 return false, princ, fmt.Errorf("must either specify all OIDC properties or none")
49 }
50
51 // Get the existing principal, or if this is a POST make sure there isn't one:
52 var user auth.User
53 authenticator := dbc.Authenticator(ctx)
54
55 // Retry handling for cas failure during principal update. Limiting retry attempts
56 // to PrincipalUpdateMaxCasRetries defensively to avoid unexpected retry loops.
57 for i := 1; i <= auth.PrincipalUpdateMaxCasRetries; i++ {
58 if isUser {
59 user, err = authenticator.GetUser(*updates.Name)
60 princ = user
61 } else {
62 princ, err = authenticator.GetRole(*updates.Name)
63 }
64 if err != nil {
65 return replaced, princ, err
66 }
67
68 changed := false
69 replaced = (princ != nil)
70 if !replaced {
71 if updates.Name == nil || *updates.Name == "" {
72 return replaced, princ, fmt.Errorf("UpdatePrincipal: cannot create principal with empty name")
73 }
74 // If user/role didn't exist already, instantiate a new one:
75 if isUser {
76 isValid, reason := updates.IsPasswordValid(dbc.AllowEmptyPassword)
77 if !isValid {
78 err = base.HTTPErrorf(http.StatusBadRequest, "Error creating user: %s", reason)
79 return replaced, princ, err
80 }
81 user, err = authenticator.NewUserNoChannels(*updates.Name, "")
82 princ = user
83 } else {
84 princ, err = authenticator.NewRoleNoChannels(*updates.Name)
85 }
86 if err != nil {
87 return replaced, princ, fmt.Errorf("Error creating user/role: %w", err)
88 }
89 princ.SetCreatedAt(time.Now().UTC())
90 changed = true
91 } else if !allowReplace {
92 err = base.HTTPErrorf(http.StatusConflict, "Already exists")
93 return
94 } else if isUser && updates.Password != nil {
95 isValid, reason := updates.IsPasswordValid(dbc.AllowEmptyPassword)
96 if !isValid {
97 err = base.HTTPErrorf(http.StatusBadRequest, "Error updating user/role: %s", reason)
98 return replaced, princ, err
99 }
100 }
101
102 // Ensure the caller isn't trying to set all_channels or roles explicitly - it'll get recomputed automatically.

Callers 11

InstallPrincipalsMethod · 0.95
updatePrincipalMethod · 0.80
setUserForPublicAuthMethod · 0.80
TestUserWaiterFunction · 0.80
TestUpdatePrincipalFunction · 0.80

Calls 15

AuthenticatorMethod · 0.95
RoleNamesMethod · 0.95
EmailMethod · 0.95
SetEmailMethod · 0.95
SetPasswordMethod · 0.95
DisabledMethod · 0.95
SetDisabledMethod · 0.95
ExplicitRolesMethod · 0.95
EqualsMethod · 0.95
JWTIssuerMethod · 0.95
SetJWTIssuerMethod · 0.95

Tested by 6

TestUserWaiterFunction · 0.64
TestUpdatePrincipalFunction · 0.64