Skip to content

Commit

Permalink
Separate create / update / delete config of Login IDs
Browse files Browse the repository at this point in the history
ref DEV-1313
  • Loading branch information
louischan-oursky committed May 27, 2024
2 parents 7296a64 + 56641e7 commit 4683c25
Show file tree
Hide file tree
Showing 41 changed files with 529 additions and 198 deletions.
8 changes: 8 additions & 0 deletions authui/src/tailwind-light-theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,14 @@
border-color: var(--color-text-shaded-2);
}

.light-btn--destructive,
.light-btn--destructive:focus,
.light-btn--destructive:hover,
.light-btn--destructive:active {
color: var(--color-error-shaded-6);
border-color: var(--color-error-shaded-6);
}

.action-btn {
@apply border border-solid;
color: var(--color-text-unshaded);
Expand Down
36 changes: 27 additions & 9 deletions pkg/auth/handler/webapp/enter_login_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/authgear/authgear-server/pkg/auth/handler/webapp/viewmodels"
"github.com/authgear/authgear-server/pkg/auth/webapp"
"github.com/authgear/authgear-server/pkg/lib/authn/identity"
"github.com/authgear/authgear-server/pkg/lib/config"
"github.com/authgear/authgear-server/pkg/lib/interaction"
"github.com/authgear/authgear-server/pkg/lib/interaction/intents"
"github.com/authgear/authgear-server/pkg/util/httproute"
Expand All @@ -26,25 +27,41 @@ type EnterLoginIDViewModel struct {
LoginIDInputType string
IdentityID string
DisplayID string
UpdateDisabled bool
DeleteDisabled bool
}

type EnterLoginIDService interface {
Get(id string) (*identity.Info, error)
ListCandidates(userID string) ([]identity.Candidate, error)
}

func NewEnterLoginIDViewModel(r *http.Request, displayID string) EnterLoginIDViewModel {
func NewEnterLoginIDViewModel(r *http.Request, cfg *config.IdentityConfig, info *identity.Info) EnterLoginIDViewModel {
loginIDKey := r.Form.Get("q_login_id_key")
loginIDType := r.Form.Get("q_login_id_type")
loginIDInputType := r.Form.Get("q_login_id_input_type")
identityID := r.Form.Get("q_identity_id")

return EnterLoginIDViewModel{
LoginIDKey: loginIDKey,
LoginIDType: loginIDType,
LoginIDInputType: loginIDInputType,
IdentityID: identityID,
DisplayID: displayID,
if info == nil {
return EnterLoginIDViewModel{
LoginIDKey: loginIDKey,
LoginIDType: loginIDType,
LoginIDInputType: loginIDInputType,
IdentityID: identityID,
DisplayID: "",
UpdateDisabled: true,
DeleteDisabled: true,
}
} else {
return EnterLoginIDViewModel{
LoginIDKey: loginIDKey,
LoginIDType: loginIDType,
LoginIDInputType: loginIDInputType,
IdentityID: identityID,
DisplayID: info.DisplayID(),
UpdateDisabled: info.UpdateDisabled(cfg),
DeleteDisabled: info.DeleteDisabled(cfg),
}
}
}

Expand Down Expand Up @@ -83,6 +100,7 @@ type EnterLoginIDHandler struct {
AuthenticationViewModel *viewmodels.AuthenticationViewModeler
Renderer Renderer
Identities EnterLoginIDService
IdentityConfig *config.IdentityConfig
}

func (h *EnterLoginIDHandler) GetData(userID string, r *http.Request, rw http.ResponseWriter) (map[string]interface{}, error) {
Expand All @@ -98,9 +116,9 @@ func (h *EnterLoginIDHandler) GetData(userID string, r *http.Request, rw http.Re
} else if err != nil {
return nil, err
}
enterLoginIDViewModel = NewEnterLoginIDViewModel(r, idnInfo.DisplayID())
enterLoginIDViewModel = NewEnterLoginIDViewModel(r, h.IdentityConfig, idnInfo)
} else {
enterLoginIDViewModel = NewEnterLoginIDViewModel(r, "")
enterLoginIDViewModel = NewEnterLoginIDViewModel(r, h.IdentityConfig, nil)
}

candidates, err := h.Identities.ListCandidates(userID)
Expand Down
1 change: 1 addition & 0 deletions pkg/auth/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions pkg/lib/authn/identity/candidate.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ const (

CandidateKeyDisplayID = "display_id"

CandidateKeyModifyDisabled = "modify_disabled"
CandidateKeyCreateDisabled = "create_disabled"
CandidateKeyUpdateDisabled = "update_disabled"
CandidateKeyDeleteDisabled = "delete_disabled"
)

func NewOAuthCandidate(cfg oauthrelyingparty.ProviderConfig) Candidate {
Expand All @@ -37,7 +39,9 @@ func NewOAuthCandidate(cfg oauthrelyingparty.ProviderConfig) Candidate {
CandidateKeyProviderSubjectID: "",
CandidateKeyProviderAppType: string(wechat.ProviderConfig(cfg).AppType()),
CandidateKeyDisplayID: "",
CandidateKeyModifyDisabled: cfg.ModifyDisabled(),
CandidateKeyCreateDisabled: cfg.ModifyDisabled(),
CandidateKeyUpdateDisabled: cfg.ModifyDisabled(),
CandidateKeyDeleteDisabled: cfg.ModifyDisabled(),
}
}

Expand All @@ -49,7 +53,9 @@ func NewLoginIDCandidate(c *config.LoginIDKeyConfig) Candidate {
CandidateKeyLoginIDKey: c.Key,
CandidateKeyLoginIDValue: "",
CandidateKeyDisplayID: "",
CandidateKeyModifyDisabled: *c.ModifyDisabled,
CandidateKeyCreateDisabled: *c.CreateDisabled,
CandidateKeyUpdateDisabled: *c.UpdateDisabled,
CandidateKeyDeleteDisabled: *c.DeleteDisabled,
}
}

Expand Down
123 changes: 96 additions & 27 deletions pkg/lib/authn/identity/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,49 +267,118 @@ func (i *Info) PrimaryAuthenticatorTypes() []model.AuthenticatorType {
return i.Type.PrimaryAuthenticatorTypes(loginIDKeyType)
}

func (i *Info) ModifyDisabled(c *config.IdentityConfig) bool {
func (i *Info) findLoginIDConfig(c *config.IdentityConfig) (*config.LoginIDKeyConfig, bool) {
loginIDKey := i.LoginID.LoginIDKey
var keyConfig *config.LoginIDKeyConfig
var ok bool = false
for _, kc := range c.LoginID.Keys {
if kc.Key == loginIDKey {
kcc := kc
keyConfig = &kcc
ok = true
}
}
return keyConfig, ok
}

func (i *Info) findOAuthConfig(c *config.IdentityConfig) (oauthrelyingparty.ProviderConfig, bool) {
alias := i.OAuth.ProviderAlias
var providerConfig oauthrelyingparty.ProviderConfig
var ok bool = false
for _, pc := range c.OAuth.Providers {
pcAlias := pc.Alias()
if pcAlias == alias {
pcc := pc
providerConfig = pcc
ok = true
}
}
return providerConfig, ok
}

func (i *Info) CreateDisabled(c *config.IdentityConfig) bool {
switch i.Type {
case model.IdentityTypeLoginID:
loginIDKey := i.LoginID.LoginIDKey
var keyConfig *config.LoginIDKeyConfig
for _, kc := range c.LoginID.Keys {
if kc.Key == loginIDKey {
kcc := kc
keyConfig = &kcc
}
}
if keyConfig == nil {
keyConfig, ok := i.findLoginIDConfig(c)
if !ok {
return true
}
return *keyConfig.ModifyDisabled
return *keyConfig.CreateDisabled
case model.IdentityTypeOAuth:
alias := i.OAuth.ProviderAlias
var providerConfig oauthrelyingparty.ProviderConfig
for _, pc := range c.OAuth.Providers {
pcAlias := pc.Alias()
if pcAlias == alias {
pcc := pc
providerConfig = pcc
}
}
if providerConfig == nil {
providerConfig, ok := i.findOAuthConfig(c)
if !ok {
return true
}
// TODO(tung): Change to use create_disabled
return providerConfig.ModifyDisabled()
case model.IdentityTypeAnonymous:
// modify_disabled is only applicable to login_id and oauth.
// So we return false here.
return false
fallthrough
case model.IdentityTypeBiometric:
// modify_disabled is only applicable to login_id and oauth.
fallthrough
case model.IdentityTypePasskey:
fallthrough
case model.IdentityTypeSIWE:
// create_disabled is only applicable to login_id and oauth.
// So we return false here.
return false
default:
panic(fmt.Sprintf("identity: unexpected identity type: %s", i.Type))
}
}

func (i *Info) DeleteDisabled(c *config.IdentityConfig) bool {
switch i.Type {
case model.IdentityTypeLoginID:
keyConfig, ok := i.findLoginIDConfig(c)
if !ok {
return true
}
return *keyConfig.DeleteDisabled
case model.IdentityTypeOAuth:
providerConfig, ok := i.findOAuthConfig(c)
if !ok {
return true
}
// TODO(tung): Change to use delete_disabled
return providerConfig.ModifyDisabled()
case model.IdentityTypeAnonymous:
fallthrough
case model.IdentityTypeBiometric:
fallthrough
case model.IdentityTypePasskey:
// modify_disabled is only applicable to login_id and oauth.
fallthrough
case model.IdentityTypeSIWE:
// delete_disabled is only applicable to login_id and oauth.
// So we return false here.
return false
default:
panic(fmt.Sprintf("identity: unexpected identity type: %s", i.Type))
}
}

func (i *Info) UpdateDisabled(c *config.IdentityConfig) bool {
switch i.Type {
case model.IdentityTypeLoginID:
keyConfig, ok := i.findLoginIDConfig(c)
if !ok {
return true
}
return *keyConfig.UpdateDisabled
case model.IdentityTypeOAuth:
providerConfig, ok := i.findOAuthConfig(c)
if !ok {
return true
}
// TODO(tung): Change to use update_disabled
return providerConfig.ModifyDisabled()
case model.IdentityTypeAnonymous:
fallthrough
case model.IdentityTypeBiometric:
fallthrough
case model.IdentityTypePasskey:
fallthrough
case model.IdentityTypeSIWE:
// modify_disabled is only applicable to login_id and oauth.
// update_disabled is only applicable to login_id and oauth.
// So we return false here.
return false
default:
Expand Down
2 changes: 1 addition & 1 deletion pkg/lib/authn/identity/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,7 @@ func (s *Service) listLoginIDCandidates(loginIDs []*identity.LoginID) []identity
}
}
canAppend := true
if *loginIDKeyConfig.ModifyDisabled && !matched {
if *loginIDKeyConfig.DeleteDisabled && *loginIDKeyConfig.UpdateDisabled && !matched {
canAppend = false
}
if canAppend {
Expand Down
28 changes: 21 additions & 7 deletions pkg/lib/authn/identity/service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ func TestProviderListCandidates(t *testing.T) {
"provider_alias": "google",
"provider_subject_id": "",
"provider_app_type": "",
"modify_disabled": false,
"create_disabled": false,
"update_disabled": false,
"delete_disabled": false,
},
})
})
Expand All @@ -86,7 +88,9 @@ func TestProviderListCandidates(t *testing.T) {
{
Type: "email",
Key: "email",
ModifyDisabled: newBool(false),
UpdateDisabled: newBool(false),
DeleteDisabled: newBool(false),
CreateDisabled: newBool(false),
},
}

Expand All @@ -100,7 +104,9 @@ func TestProviderListCandidates(t *testing.T) {
"login_id_type": "email",
"login_id_key": "email",
"login_id_value": "",
"modify_disabled": false,
"create_disabled": false,
"update_disabled": false,
"delete_disabled": false,
},
})
})
Expand All @@ -117,7 +123,9 @@ func TestProviderListCandidates(t *testing.T) {
{
Type: "email",
Key: "email",
ModifyDisabled: newBool(false),
UpdateDisabled: newBool(false),
DeleteDisabled: newBool(false),
CreateDisabled: newBool(false),
},
}

Expand All @@ -134,7 +142,9 @@ func TestProviderListCandidates(t *testing.T) {
{
Type: "email",
Key: "email",
ModifyDisabled: newBool(false),
UpdateDisabled: newBool(false),
DeleteDisabled: newBool(false),
CreateDisabled: newBool(false),
},
}

Expand All @@ -161,7 +171,9 @@ func TestProviderListCandidates(t *testing.T) {
"login_id_type": "email",
"login_id_key": "email",
"login_id_value": "[email protected]",
"modify_disabled": false,
"create_disabled": false,
"update_disabled": false,
"delete_disabled": false,
},
})
})
Expand Down Expand Up @@ -204,7 +216,9 @@ func TestProviderListCandidates(t *testing.T) {
"provider_alias": "google",
"provider_subject_id": "[email protected]",
"provider_app_type": "",
"modify_disabled": false,
"create_disabled": false,
"update_disabled": false,
"delete_disabled": false,
},
})
})
Expand Down
Loading

0 comments on commit 4683c25

Please sign in to comment.