mirror of
https://github.com/zitadel/zitadel.git
synced 2025-05-22 10:38:19 +00:00
feat: fixes (#228)
* feat: user login names * fix: user login names * fix: generate login name
This commit is contained in:
parent
f2cdae9ea3
commit
6fa62ccd0a
@ -2,11 +2,13 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/sdk"
|
||||
org_model "github.com/caos/zitadel/internal/org/model"
|
||||
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
||||
usr_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
||||
@ -63,7 +65,11 @@ func (repo *UserRepo) Register(ctx context.Context, registerUser *model.User, or
|
||||
}
|
||||
|
||||
func (repo *UserRepo) MyProfile(ctx context.Context) (*model.Profile, error) {
|
||||
return repo.UserEvents.ProfileByID(ctx, auth.GetCtxData(ctx).UserID)
|
||||
user, err := repo.UserByID(ctx, auth.GetCtxData(ctx).UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.GetProfile(), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeMyProfile(ctx context.Context, profile *model.Profile) (*model.Profile, error) {
|
||||
@ -74,7 +80,11 @@ func (repo *UserRepo) ChangeMyProfile(ctx context.Context, profile *model.Profil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) MyEmail(ctx context.Context) (*model.Email, error) {
|
||||
return repo.UserEvents.EmailByID(ctx, auth.GetCtxData(ctx).UserID)
|
||||
user, err := repo.UserByID(ctx, auth.GetCtxData(ctx).UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.GetEmail(), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeMyEmail(ctx context.Context, email *model.Email) (*model.Email, error) {
|
||||
@ -101,7 +111,11 @@ func (repo *UserRepo) ResendMyEmailVerificationMail(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (repo *UserRepo) MyPhone(ctx context.Context) (*model.Phone, error) {
|
||||
return repo.UserEvents.PhoneByID(ctx, auth.GetCtxData(ctx).UserID)
|
||||
user, err := repo.UserByID(ctx, auth.GetCtxData(ctx).UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.GetPhone(), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeMyPhone(ctx context.Context, phone *model.Phone) (*model.Phone, error) {
|
||||
@ -120,7 +134,11 @@ func (repo *UserRepo) ResendMyPhoneVerificationCode(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (repo *UserRepo) MyAddress(ctx context.Context) (*model.Address, error) {
|
||||
return repo.UserEvents.AddressByID(ctx, auth.GetCtxData(ctx).UserID)
|
||||
user, err := repo.UserByID(ctx, auth.GetCtxData(ctx).UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.GetAddress(), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeMyAddress(ctx context.Context, address *model.Address) (*model.Address, error) {
|
||||
@ -205,8 +223,23 @@ func (repo *UserRepo) SignOut(ctx context.Context, agentID, userID string) error
|
||||
return repo.UserEvents.SignOut(ctx, agentID, userID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, userID string) (*model.User, error) {
|
||||
return repo.UserEvents.UserByID(ctx, userID)
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, id string) (*model.UserView, error) {
|
||||
user, err := repo.View.UserByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := repo.UserEvents.UserEventsByID(ctx, id, user.Sequence)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-PSoc3").WithError(err).Debug("error retrieving new events")
|
||||
return usr_view_model.UserToModel(user), nil
|
||||
}
|
||||
userCopy := *user
|
||||
for _, event := range events {
|
||||
if err := userCopy.AppendEvent(event); err != nil {
|
||||
return usr_view_model.UserToModel(user), nil
|
||||
}
|
||||
}
|
||||
return usr_view_model.UserToModel(&userCopy), nil
|
||||
}
|
||||
|
||||
func checkIDs(ctx context.Context, obj es_models.ObjectRoot) error {
|
||||
|
@ -101,23 +101,11 @@ func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user.LoginNames = getLoginNames(policy, user.UserName, org.Domains)
|
||||
user.SetLoginNames(policy, org.Domains)
|
||||
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLoginNames(policy *org_model.OrgIamPolicy, userName string, domains []*org_model.OrgDomain) []string {
|
||||
loginNames := make([]string, 0)
|
||||
if !policy.UserLoginMustBeDomain {
|
||||
return []string{userName}
|
||||
}
|
||||
for _, d := range domains {
|
||||
if d.Verified {
|
||||
loginNames = append(loginNames, userName+"@"+d.Domain)
|
||||
}
|
||||
}
|
||||
return loginNames
|
||||
}
|
||||
|
||||
func (u *User) ProcessOrg(event *models.Event) (err error) {
|
||||
switch event.Type {
|
||||
case org_es_model.OrgDomainVerified,
|
||||
@ -126,6 +114,8 @@ func (u *User) ProcessOrg(event *models.Event) (err error) {
|
||||
org_es_model.OrgIamPolicyChanged,
|
||||
org_es_model.OrgIamPolicyRemoved:
|
||||
return u.fillLoginNamesOnOrgUsers(event)
|
||||
case org_es_model.OrgDomainPrimarySet:
|
||||
return u.fillPreferredLoginNamesOnOrgUsers(event)
|
||||
default:
|
||||
return u.view.ProcessedUserSequence(event.Sequence)
|
||||
}
|
||||
@ -134,6 +124,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
|
||||
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
|
||||
if err != nil {
|
||||
@ -148,7 +139,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
|
||||
return err
|
||||
}
|
||||
for _, user := range users {
|
||||
user.LoginNames = getLoginNames(policy, user.UserName, org.Domains)
|
||||
user.SetLoginNames(policy, org.Domains)
|
||||
err := u.view.PutUser(user, event.Sequence)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -157,6 +148,32 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
|
||||
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
policy, err := u.orgEvents.GetOrgIamPolicy(context.Background(), event.ResourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !policy.UserLoginMustBeDomain {
|
||||
return nil
|
||||
}
|
||||
users, err := u.view.UsersByOrgID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, user := range users {
|
||||
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain)
|
||||
err := u.view.PutUser(user, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *User) OnError(event *models.Event, err error) error {
|
||||
logging.LogWithFields("SPOOL-is8wa", "id", event.AggregateID).WithError(err).Warn("something went wrong in user handler")
|
||||
return spooler.HandleError(event, err, p.view.GetLatestUserFailedEvent, p.view.ProcessedUserFailedEvent, p.view.ProcessedUserSequence, p.errorCountUntilSkip)
|
||||
|
@ -25,7 +25,7 @@ type UserRepository interface {
|
||||
|
||||
SignOut(ctx context.Context, agentID, userID string) error
|
||||
|
||||
UserByID(ctx context.Context, userID string) (*model.User, error)
|
||||
UserByID(ctx context.Context, userID string) (*model.UserView, error)
|
||||
}
|
||||
|
||||
type myUserRepo interface {
|
||||
|
@ -2,6 +2,7 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
"github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
|
||||
@ -20,8 +21,23 @@ type UserRepo struct {
|
||||
View *view.View
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, id string) (project *usr_model.User, err error) {
|
||||
return repo.UserEvents.UserByID(ctx, id)
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, id string) (*usr_model.UserView, error) {
|
||||
user, err := repo.View.UserByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := repo.UserEvents.UserEventsByID(ctx, id, user.Sequence)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-PSoc3").WithError(err).Debug("error retrieving new events")
|
||||
return model.UserToModel(user), nil
|
||||
}
|
||||
userCopy := *user
|
||||
for _, event := range events {
|
||||
if err := userCopy.AppendEvent(event); err != nil {
|
||||
return model.UserToModel(user), nil
|
||||
}
|
||||
}
|
||||
return model.UserToModel(&userCopy), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) CreateUser(ctx context.Context, user *usr_model.User) (*usr_model.User, error) {
|
||||
@ -119,7 +135,11 @@ func (repo *UserRepo) RequestSetPassword(ctx context.Context, id string, notifyT
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ProfileByID(ctx context.Context, userID string) (*usr_model.Profile, error) {
|
||||
return repo.UserEvents.ProfileByID(ctx, userID)
|
||||
user, err := repo.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.GetProfile(), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeProfile(ctx context.Context, profile *usr_model.Profile) (*usr_model.Profile, error) {
|
||||
@ -127,7 +147,11 @@ func (repo *UserRepo) ChangeProfile(ctx context.Context, profile *usr_model.Prof
|
||||
}
|
||||
|
||||
func (repo *UserRepo) EmailByID(ctx context.Context, userID string) (*usr_model.Email, error) {
|
||||
return repo.UserEvents.EmailByID(ctx, userID)
|
||||
user, err := repo.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.GetEmail(), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeEmail(ctx context.Context, email *usr_model.Email) (*usr_model.Email, error) {
|
||||
@ -139,7 +163,11 @@ func (repo *UserRepo) CreateEmailVerificationCode(ctx context.Context, userID st
|
||||
}
|
||||
|
||||
func (repo *UserRepo) PhoneByID(ctx context.Context, userID string) (*usr_model.Phone, error) {
|
||||
return repo.UserEvents.PhoneByID(ctx, userID)
|
||||
user, err := repo.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.GetPhone(), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangePhone(ctx context.Context, email *usr_model.Phone) (*usr_model.Phone, error) {
|
||||
@ -151,7 +179,11 @@ func (repo *UserRepo) CreatePhoneVerificationCode(ctx context.Context, userID st
|
||||
}
|
||||
|
||||
func (repo *UserRepo) AddressByID(ctx context.Context, userID string) (*usr_model.Address, error) {
|
||||
return repo.UserEvents.AddressByID(ctx, userID)
|
||||
user, err := repo.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.GetAddress(), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeAddress(ctx context.Context, address *usr_model.Address) (*usr_model.Address, error) {
|
||||
|
@ -39,7 +39,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev
|
||||
&ProjectMember{handler: handler{view, bulkLimit, configs.cycleDuration("ProjectMember"), errorCount}, userEvents: repos.UserEvents},
|
||||
&ProjectGrantMember{handler: handler{view, bulkLimit, configs.cycleDuration("ProjectGrantMember"), errorCount}, userEvents: repos.UserEvents},
|
||||
&Application{handler: handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount}, projectEvents: repos.ProjectEvents},
|
||||
&User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, eventstore: eventstore},
|
||||
&User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, eventstore: eventstore, orgEvents: repos.OrgEvents},
|
||||
&UserGrant{handler: handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount}, projectEvents: repos.ProjectEvents, userEvents: repos.UserEvents, orgEvents: repos.OrgEvents},
|
||||
&Org{handler: handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount}},
|
||||
&OrgMember{handler: handler{view, bulkLimit, configs.cycleDuration("OrgMember"), errorCount}, userEvents: repos.UserEvents},
|
||||
|
@ -1,6 +1,11 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
org_model "github.com/caos/zitadel/internal/org/model"
|
||||
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
||||
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
"time"
|
||||
|
||||
@ -9,13 +14,13 @@ import (
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/spooler"
|
||||
"github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
handler
|
||||
eventstore eventstore.Eventstore
|
||||
orgEvents *org_events.OrgEventstore
|
||||
}
|
||||
|
||||
const (
|
||||
@ -33,15 +38,29 @@ func (p *User) EventQuery() (*models.SearchQuery, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return eventsourcing.UserQuery(sequence), nil
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(es_model.UserAggregate, org_es_model.OrgAggregate).
|
||||
LatestSequenceFilter(sequence), nil
|
||||
}
|
||||
|
||||
func (p *User) Process(event *models.Event) (err error) {
|
||||
func (u *User) Process(event *models.Event) (err error) {
|
||||
switch event.AggregateType {
|
||||
case es_model.UserAggregate:
|
||||
return u.ProcessUser(event)
|
||||
case org_es_model.OrgAggregate:
|
||||
return u.ProcessOrg(event)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p *User) ProcessUser(event *models.Event) (err error) {
|
||||
user := new(view_model.UserView)
|
||||
switch event.Type {
|
||||
case es_model.UserAdded,
|
||||
es_model.UserRegistered:
|
||||
user.AppendEvent(event)
|
||||
p.fillLoginNames(user)
|
||||
case es_model.UserProfileChanged,
|
||||
es_model.UserEmailChanged,
|
||||
es_model.UserEmailVerified,
|
||||
@ -68,7 +87,89 @@ func (p *User) Process(event *models.Event) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.view.PutUser(user)
|
||||
return p.view.PutUser(user, user.Sequence)
|
||||
}
|
||||
|
||||
func (u *User) ProcessOrg(event *models.Event) (err error) {
|
||||
switch event.Type {
|
||||
case org_es_model.OrgDomainVerified,
|
||||
org_es_model.OrgDomainRemoved,
|
||||
org_es_model.OrgIamPolicyAdded,
|
||||
org_es_model.OrgIamPolicyChanged,
|
||||
org_es_model.OrgIamPolicyRemoved:
|
||||
return u.fillLoginNamesOnOrgUsers(event)
|
||||
case org_es_model.OrgDomainPrimarySet:
|
||||
return u.fillPreferredLoginNamesOnOrgUsers(event)
|
||||
default:
|
||||
return u.view.ProcessedUserSequence(event.Sequence)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
|
||||
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
policy, err := u.orgEvents.GetOrgIamPolicy(context.Background(), event.ResourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
users, err := u.view.UsersByOrgID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, user := range users {
|
||||
user.SetLoginNames(policy, org.Domains)
|
||||
err := u.view.PutUser(user, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
|
||||
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
policy, err := u.orgEvents.GetOrgIamPolicy(context.Background(), event.ResourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !policy.UserLoginMustBeDomain {
|
||||
return nil
|
||||
}
|
||||
users, err := u.view.UsersByOrgID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, user := range users {
|
||||
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain)
|
||||
err := u.view.PutUser(user, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
|
||||
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(user.ResourceOwner))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
policy, err := u.orgEvents.GetOrgIamPolicy(context.Background(), user.ResourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user.SetLoginNames(policy, org.Domains)
|
||||
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *User) OnError(event *models.Event, err error) error {
|
||||
|
@ -23,6 +23,10 @@ func (v *View) GetGlobalUserByEmail(email string) (*model.UserView, error) {
|
||||
return view.GetGlobalUserByEmail(v.Db, userTable, email)
|
||||
}
|
||||
|
||||
func (v *View) UsersByOrgID(orgID string) ([]*model.UserView, error) {
|
||||
return view.UsersByOrgID(v.Db, userTable, orgID)
|
||||
}
|
||||
|
||||
func (v *View) IsUserUnique(userName, email string) (bool, error) {
|
||||
return view.IsUserUnique(v.Db, userTable, userName, email)
|
||||
}
|
||||
@ -31,12 +35,15 @@ func (v *View) UserMfas(userID string) ([]*usr_model.MultiFactor, error) {
|
||||
return view.UserMfas(v.Db, userTable, userID)
|
||||
}
|
||||
|
||||
func (v *View) PutUser(user *model.UserView) error {
|
||||
func (v *View) PutUser(user *model.UserView, sequence uint64) error {
|
||||
err := view.PutUser(v.Db, userTable, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedUserSequence(user.Sequence)
|
||||
if sequence != 0 {
|
||||
return v.ProcessedUserSequence(sequence)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteUser(userID string, eventSequence uint64) error {
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type UserRepository interface {
|
||||
UserByID(ctx context.Context, id string) (*model.User, error)
|
||||
UserByID(ctx context.Context, id string) (*model.UserView, error)
|
||||
CreateUser(ctx context.Context, user *model.User) (*model.User, error)
|
||||
RegisterUser(ctx context.Context, user *model.User, resourceOwner string) (*model.User, error)
|
||||
DeactivateUser(ctx context.Context, id string) (*model.User, error)
|
||||
|
@ -2,8 +2,8 @@ package model
|
||||
|
||||
import (
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"strings"
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Org struct {
|
||||
@ -57,6 +57,15 @@ func (o *Org) ContainsDomain(domain *OrgDomain) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Org) GetPrimaryDomain() *OrgDomain {
|
||||
for _, d := range o.Domains {
|
||||
if d.Primary {
|
||||
return d
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Org) ContainsMember(userID string) bool {
|
||||
for _, member := range o.Members {
|
||||
if member.UserID == userID {
|
||||
|
@ -8,13 +8,15 @@ import (
|
||||
type Profile struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
UserName string
|
||||
FirstName string
|
||||
LastName string
|
||||
NickName string
|
||||
DisplayName string
|
||||
PreferredLanguage language.Tag
|
||||
Gender Gender
|
||||
UserName string
|
||||
FirstName string
|
||||
LastName string
|
||||
NickName string
|
||||
DisplayName string
|
||||
PreferredLanguage language.Tag
|
||||
Gender Gender
|
||||
PreferredLoginName string
|
||||
LoginNames []string
|
||||
}
|
||||
|
||||
func (p *Profile) IsValid() bool {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"golang.org/x/text/language"
|
||||
"time"
|
||||
|
||||
req_model "github.com/caos/zitadel/internal/auth_request/model"
|
||||
@ -18,6 +20,7 @@ type UserView struct {
|
||||
PasswordChanged time.Time
|
||||
LastLogin time.Time
|
||||
UserName string
|
||||
PreferredLoginName string
|
||||
LoginNames []string
|
||||
FirstName string
|
||||
LastName string
|
||||
@ -121,3 +124,69 @@ func (u *UserView) MfaTypesAllowed(level req_model.MfaLevel) []req_model.MfaType
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
func (u *UserView) GetProfile() *Profile {
|
||||
return &Profile{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: u.ID,
|
||||
Sequence: u.Sequence,
|
||||
ResourceOwner: u.ResourceOwner,
|
||||
CreationDate: u.CreationDate,
|
||||
ChangeDate: u.ChangeDate,
|
||||
},
|
||||
UserName: u.UserName,
|
||||
FirstName: u.FirstName,
|
||||
LastName: u.LastName,
|
||||
NickName: u.NickName,
|
||||
DisplayName: u.DisplayName,
|
||||
PreferredLanguage: language.Make(u.PreferredLanguage),
|
||||
Gender: u.Gender,
|
||||
PreferredLoginName: u.PreferredLoginName,
|
||||
LoginNames: u.LoginNames,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserView) GetPhone() *Phone {
|
||||
return &Phone{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: u.ID,
|
||||
Sequence: u.Sequence,
|
||||
ResourceOwner: u.ResourceOwner,
|
||||
CreationDate: u.CreationDate,
|
||||
ChangeDate: u.ChangeDate,
|
||||
},
|
||||
PhoneNumber: u.Phone,
|
||||
IsPhoneVerified: u.IsPhoneVerified,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserView) GetEmail() *Email {
|
||||
return &Email{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: u.ID,
|
||||
Sequence: u.Sequence,
|
||||
ResourceOwner: u.ResourceOwner,
|
||||
CreationDate: u.CreationDate,
|
||||
ChangeDate: u.ChangeDate,
|
||||
},
|
||||
EmailAddress: u.Email,
|
||||
IsEmailVerified: u.IsEmailVerified,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserView) GetAddress() *Address {
|
||||
return &Address{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: u.ID,
|
||||
Sequence: u.Sequence,
|
||||
ResourceOwner: u.ResourceOwner,
|
||||
CreationDate: u.CreationDate,
|
||||
ChangeDate: u.ChangeDate,
|
||||
},
|
||||
Country: u.Country,
|
||||
Locality: u.Locality,
|
||||
PostalCode: u.PostalCode,
|
||||
Region: u.Region,
|
||||
StreetAddress: u.StreetAddress,
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,9 @@ func (es *UserEventstore) UserEventsByID(ctx context.Context, id string, sequenc
|
||||
|
||||
func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model.User, pwPolicy *policy_model.PasswordComplexityPolicy, orgIamPolicy *org_model.OrgIamPolicy, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
||||
err := user.CheckOrgIamPolicy(orgIamPolicy)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !user.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "User is invalid")
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
org_model "github.com/caos/zitadel/internal/org/model"
|
||||
"github.com/lib/pq"
|
||||
"time"
|
||||
|
||||
@ -39,6 +40,7 @@ type UserView struct {
|
||||
LastLogin time.Time `json:"-" gorm:"column:last_login"`
|
||||
UserName string `json:"userName" gorm:"column:user_name"`
|
||||
LoginNames pq.StringArray `json:"-" gorm:"column:login_names"`
|
||||
PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"`
|
||||
FirstName string `json:"firstName" gorm:"column:first_name"`
|
||||
LastName string `json:"lastName" gorm:"column:last_name"`
|
||||
NickName string `json:"nickName" gorm:"column:nick_name"`
|
||||
@ -74,6 +76,7 @@ func UserFromModel(user *model.UserView) *UserView {
|
||||
LastLogin: user.LastLogin,
|
||||
UserName: user.UserName,
|
||||
LoginNames: user.LoginNames,
|
||||
PreferredLoginName: user.PreferredLoginName,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
NickName: user.NickName,
|
||||
@ -108,6 +111,8 @@ func UserToModel(user *UserView) *model.UserView {
|
||||
PasswordChangeRequired: user.PasswordChangeRequired,
|
||||
PasswordChanged: user.PasswordChanged,
|
||||
LastLogin: user.LastLogin,
|
||||
PreferredLoginName: user.PreferredLoginName,
|
||||
LoginNames: user.LoginNames,
|
||||
UserName: user.UserName,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
@ -140,6 +145,24 @@ func UsersToModel(users []*UserView) []*model.UserView {
|
||||
return result
|
||||
}
|
||||
|
||||
func (u *UserView) GenerateLoginName(domain string) string {
|
||||
return u.UserName + "@" + domain
|
||||
}
|
||||
|
||||
func (u *UserView) SetLoginNames(policy *org_model.OrgIamPolicy, domains []*org_model.OrgDomain) {
|
||||
loginNames := make([]string, 0)
|
||||
if !policy.UserLoginMustBeDomain {
|
||||
u.LoginNames = []string{u.UserName}
|
||||
return
|
||||
}
|
||||
for _, d := range domains {
|
||||
if d.Verified {
|
||||
loginNames = append(loginNames, u.GenerateLoginName(d.Domain))
|
||||
}
|
||||
}
|
||||
u.LoginNames = loginNames
|
||||
}
|
||||
|
||||
func (u *UserView) AppendEvent(event *models.Event) (err error) {
|
||||
u.ChangeDate = event.CreationDate
|
||||
u.Sequence = event.Sequence
|
||||
|
6
migrations/cockroach/V1.18__user_view.sql
Normal file
6
migrations/cockroach/V1.18__user_view.sql
Normal file
@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE auth.users ADD COLUMN preferred_login_name TEXT;
|
||||
ALTER TABLE management.users ADD COLUMN preferred_login_name TEXT;
|
||||
|
||||
COMMIT;
|
File diff suppressed because it is too large
Load Diff
@ -145,7 +145,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1UserAddress"
|
||||
"$ref": "#/definitions/v1UserAddressView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -185,7 +185,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1UserEmail"
|
||||
"$ref": "#/definitions/v1UserEmailView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -387,7 +387,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1UserPhone"
|
||||
"$ref": "#/definitions/v1UserPhoneView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -480,7 +480,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1UserProfile"
|
||||
"$ref": "#/definitions/v1UserProfileView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -872,6 +872,41 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserAddressView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"country": {
|
||||
"type": "string"
|
||||
},
|
||||
"locality": {
|
||||
"type": "string"
|
||||
},
|
||||
"postal_code": {
|
||||
"type": "string"
|
||||
},
|
||||
"region": {
|
||||
"type": "string"
|
||||
},
|
||||
"street_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserEmail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -899,6 +934,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserEmailView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"isEmailVerified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserGrantSearchKey": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@ -1021,6 +1083,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserPhoneView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"is_phone_verified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserProfile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -1062,6 +1151,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserProfileView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"nick_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"preferred_language": {
|
||||
"type": "string"
|
||||
},
|
||||
"gender": {
|
||||
"$ref": "#/definitions/v1Gender"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"login_names": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"preferred_login_name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserSessionState": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
@ -8,36 +8,36 @@ import (
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
func (s *Server) GetMyUserProfile(ctx context.Context, _ *empty.Empty) (*UserProfile, error) {
|
||||
func (s *Server) GetMyUserProfile(ctx context.Context, _ *empty.Empty) (*UserProfileView, error) {
|
||||
profile, err := s.repo.MyProfile(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return profileFromModel(profile), nil
|
||||
return profileViewFromModel(profile), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetMyUserEmail(ctx context.Context, _ *empty.Empty) (*UserEmail, error) {
|
||||
func (s *Server) GetMyUserEmail(ctx context.Context, _ *empty.Empty) (*UserEmailView, error) {
|
||||
email, err := s.repo.MyEmail(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return emailFromModel(email), nil
|
||||
return emailViewFromModel(email), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetMyUserPhone(ctx context.Context, _ *empty.Empty) (*UserPhone, error) {
|
||||
func (s *Server) GetMyUserPhone(ctx context.Context, _ *empty.Empty) (*UserPhoneView, error) {
|
||||
phone, err := s.repo.MyPhone(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return phoneFromModel(phone), nil
|
||||
return phoneViewFromModel(phone), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetMyUserAddress(ctx context.Context, _ *empty.Empty) (*UserAddress, error) {
|
||||
func (s *Server) GetMyUserAddress(ctx context.Context, _ *empty.Empty) (*UserAddressView, error) {
|
||||
address, err := s.repo.MyAddress(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return addressFromModel(address), nil
|
||||
return addressViewFromModel(address), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetMyMfas(ctx context.Context, _ *empty.Empty) (*MultiFactors, error) {
|
||||
|
@ -33,6 +33,30 @@ func profileFromModel(profile *usr_model.Profile) *UserProfile {
|
||||
}
|
||||
}
|
||||
|
||||
func profileViewFromModel(profile *usr_model.Profile) *UserProfileView {
|
||||
creationDate, err := ptypes.TimestampProto(profile.CreationDate)
|
||||
logging.Log("GRPC-s9iKs").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(profile.ChangeDate)
|
||||
logging.Log("GRPC-9sujE").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserProfileView{
|
||||
Id: profile.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: profile.Sequence,
|
||||
UserName: profile.UserName,
|
||||
FirstName: profile.FirstName,
|
||||
LastName: profile.LastName,
|
||||
DisplayName: profile.DisplayName,
|
||||
NickName: profile.NickName,
|
||||
PreferredLanguage: profile.PreferredLanguage.String(),
|
||||
Gender: genderFromModel(profile.Gender),
|
||||
LoginNames: profile.LoginNames,
|
||||
PreferredLoginName: profile.PreferredLoginName,
|
||||
}
|
||||
}
|
||||
|
||||
func updateProfileToModel(ctx context.Context, u *UpdateUserProfileRequest) *usr_model.Profile {
|
||||
preferredLanguage, err := language.Parse(u.PreferredLanguage)
|
||||
logging.Log("GRPC-lk73L").OnError(err).Debug("language malformed")
|
||||
@ -65,6 +89,23 @@ func emailFromModel(email *usr_model.Email) *UserEmail {
|
||||
}
|
||||
}
|
||||
|
||||
func emailViewFromModel(email *usr_model.Email) *UserEmailView {
|
||||
creationDate, err := ptypes.TimestampProto(email.CreationDate)
|
||||
logging.Log("GRPC-LSp8s").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(email.ChangeDate)
|
||||
logging.Log("GRPC-6szJe").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserEmailView{
|
||||
Id: email.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: email.Sequence,
|
||||
Email: email.EmailAddress,
|
||||
IsEmailVerified: email.IsEmailVerified,
|
||||
}
|
||||
}
|
||||
|
||||
func updateEmailToModel(ctx context.Context, e *UpdateUserEmailRequest) *usr_model.Email {
|
||||
return &usr_model.Email{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: auth.GetCtxData(ctx).UserID},
|
||||
@ -89,6 +130,23 @@ func phoneFromModel(phone *usr_model.Phone) *UserPhone {
|
||||
}
|
||||
}
|
||||
|
||||
func phoneViewFromModel(phone *usr_model.Phone) *UserPhoneView {
|
||||
creationDate, err := ptypes.TimestampProto(phone.CreationDate)
|
||||
logging.Log("GRPC-s5zJS").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(phone.ChangeDate)
|
||||
logging.Log("GRPC-s9kLe").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserPhoneView{
|
||||
Id: phone.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: phone.Sequence,
|
||||
Phone: phone.PhoneNumber,
|
||||
IsPhoneVerified: phone.IsPhoneVerified,
|
||||
}
|
||||
}
|
||||
|
||||
func updatePhoneToModel(ctx context.Context, e *UpdateUserPhoneRequest) *usr_model.Phone {
|
||||
return &usr_model.Phone{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: auth.GetCtxData(ctx).UserID},
|
||||
@ -116,6 +174,26 @@ func addressFromModel(address *usr_model.Address) *UserAddress {
|
||||
}
|
||||
}
|
||||
|
||||
func addressViewFromModel(address *usr_model.Address) *UserAddressView {
|
||||
creationDate, err := ptypes.TimestampProto(address.CreationDate)
|
||||
logging.Log("GRPC-sk4fS").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(address.ChangeDate)
|
||||
logging.Log("GRPC-9siEs").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserAddressView{
|
||||
Id: address.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: address.Sequence,
|
||||
Country: address.Country,
|
||||
StreetAddress: address.StreetAddress,
|
||||
Region: address.Region,
|
||||
PostalCode: address.PostalCode,
|
||||
Locality: address.Locality,
|
||||
}
|
||||
}
|
||||
|
||||
func updateAddressToModel(ctx context.Context, address *UpdateUserAddressRequest) *usr_model.Address {
|
||||
return &usr_model.Address{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: auth.GetCtxData(ctx).UserID},
|
||||
|
@ -46,18 +46,12 @@ func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID string, sc
|
||||
for _, scope := range scopes {
|
||||
switch scope {
|
||||
case scopeOpenID:
|
||||
userInfo.Subject = user.AggregateID
|
||||
userInfo.Subject = user.ID
|
||||
case scopeEmail:
|
||||
if user.Email == nil {
|
||||
continue
|
||||
}
|
||||
userInfo.Email = user.EmailAddress
|
||||
userInfo.Email = user.Email
|
||||
userInfo.EmailVerified = user.IsEmailVerified
|
||||
case scopeProfile:
|
||||
if user.Profile == nil {
|
||||
continue
|
||||
}
|
||||
userInfo.Name = user.FirstName + " " + user.LastName
|
||||
userInfo.Name = user.DisplayName
|
||||
userInfo.FamilyName = user.LastName
|
||||
userInfo.GivenName = user.FirstName
|
||||
userInfo.Nickname = user.NickName
|
||||
@ -65,15 +59,9 @@ func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID string, sc
|
||||
userInfo.UpdatedAt = user.ChangeDate
|
||||
userInfo.Gender = oidc.Gender(getGender(user.Gender))
|
||||
case scopePhone:
|
||||
if user.Phone == nil {
|
||||
continue
|
||||
}
|
||||
userInfo.PhoneNumber = user.PhoneNumber
|
||||
userInfo.PhoneNumber = user.Phone
|
||||
userInfo.PhoneNumberVerified = user.IsPhoneVerified
|
||||
case scopeAddress:
|
||||
if user.Address == nil {
|
||||
continue
|
||||
}
|
||||
userInfo.Address.StreetAddress = user.StreetAddress
|
||||
userInfo.Address.Locality = user.Locality
|
||||
userInfo.Address.Region = user.Region
|
||||
|
@ -62,7 +62,7 @@ service AuthService {
|
||||
}
|
||||
|
||||
//User
|
||||
rpc GetMyUserProfile(google.protobuf.Empty) returns (UserProfile) {
|
||||
rpc GetMyUserProfile(google.protobuf.Empty) returns (UserProfileView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/me/profile"
|
||||
};
|
||||
@ -83,7 +83,7 @@ service AuthService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetMyUserEmail(google.protobuf.Empty) returns (UserEmail) {
|
||||
rpc GetMyUserEmail(google.protobuf.Empty) returns (UserEmailView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/me/email"
|
||||
};
|
||||
@ -126,7 +126,7 @@ service AuthService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetMyUserPhone(google.protobuf.Empty) returns (UserPhone) {
|
||||
rpc GetMyUserPhone(google.protobuf.Empty) returns (UserPhoneView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/me/phone"
|
||||
};
|
||||
@ -169,7 +169,7 @@ service AuthService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetMyUserAddress(google.protobuf.Empty) returns (UserAddress) {
|
||||
rpc GetMyUserAddress(google.protobuf.Empty) returns (UserAddressView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/me/address"
|
||||
};
|
||||
@ -326,6 +326,8 @@ message User {
|
||||
string street_address = 23;
|
||||
bool password_change_required = 24;
|
||||
uint64 sequence = 25;
|
||||
repeated string login_names = 26;
|
||||
string preferred_login_name = 27;
|
||||
}
|
||||
|
||||
enum UserState {
|
||||
@ -359,6 +361,22 @@ message UserProfile {
|
||||
google.protobuf.Timestamp change_date = 11;
|
||||
}
|
||||
|
||||
message UserProfileView {
|
||||
string id = 1;
|
||||
string user_name = 2;
|
||||
string first_name = 3;
|
||||
string last_name = 4;
|
||||
string nick_name = 5;
|
||||
string display_name = 6;
|
||||
string preferred_language = 7;
|
||||
Gender gender = 8;
|
||||
uint64 sequence = 9;
|
||||
google.protobuf.Timestamp creation_date = 10;
|
||||
google.protobuf.Timestamp change_date = 11;
|
||||
repeated string login_names = 12;
|
||||
string preferred_login_name = 13;
|
||||
}
|
||||
|
||||
message UpdateUserProfileRequest {
|
||||
string first_name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string last_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
@ -377,6 +395,15 @@ message UserEmail {
|
||||
google.protobuf.Timestamp change_date = 6;
|
||||
}
|
||||
|
||||
message UserEmailView {
|
||||
string id = 1;
|
||||
string email = 2;
|
||||
bool isEmailVerified = 3;
|
||||
uint64 sequence = 4;
|
||||
google.protobuf.Timestamp creation_date = 5;
|
||||
google.protobuf.Timestamp change_date = 6;
|
||||
}
|
||||
|
||||
message VerifyMyUserEmailRequest {
|
||||
string code = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
}
|
||||
@ -399,6 +426,15 @@ message UserPhone {
|
||||
google.protobuf.Timestamp change_date = 6;
|
||||
}
|
||||
|
||||
message UserPhoneView {
|
||||
string id = 1;
|
||||
string phone = 2;
|
||||
bool is_phone_verified = 3;
|
||||
uint64 sequence = 4;
|
||||
google.protobuf.Timestamp creation_date = 5;
|
||||
google.protobuf.Timestamp change_date = 6;
|
||||
}
|
||||
|
||||
message UpdateUserPhoneRequest {
|
||||
string phone = 1 [(validate.rules).string = {min_len: 1, max_len: 20}];
|
||||
}
|
||||
@ -419,6 +455,18 @@ message UserAddress {
|
||||
google.protobuf.Timestamp change_date = 9;
|
||||
}
|
||||
|
||||
message UserAddressView {
|
||||
string id = 1;
|
||||
string country = 2;
|
||||
string locality = 3;
|
||||
string postal_code = 4;
|
||||
string region = 5;
|
||||
string street_address = 6;
|
||||
uint64 sequence = 7;
|
||||
google.protobuf.Timestamp creation_date = 8;
|
||||
google.protobuf.Timestamp change_date = 9;
|
||||
}
|
||||
|
||||
message UpdateUserAddressRequest {
|
||||
string country = 1 [(validate.rules).string = {max_len: 200}];
|
||||
string locality = 2 [(validate.rules).string = {max_len: 200}];
|
||||
|
@ -3,7 +3,6 @@ package grpc
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
@ -38,9 +37,6 @@ func (s *Server) UpdateApplication(ctx context.Context, in *ApplicationUpdate) (
|
||||
return appFromModel(app), nil
|
||||
}
|
||||
func (s *Server) DeactivateApplication(ctx context.Context, in *ApplicationID) (*Application, error) {
|
||||
if s.IsZitadel(ctx, in.ProjectId) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSped", "Zitadel Project Applications should not be deactivated")
|
||||
}
|
||||
app, err := s.project.DeactivateApplication(ctx, in.ProjectId, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -56,17 +52,11 @@ func (s *Server) ReactivateApplication(ctx context.Context, in *ApplicationID) (
|
||||
}
|
||||
|
||||
func (s *Server) RemoveApplication(ctx context.Context, in *ApplicationID) (*empty.Empty, error) {
|
||||
if s.IsZitadel(ctx, in.ProjectId) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpee", "Zitadel Project Applications should not be removed")
|
||||
}
|
||||
err := s.project.RemoveApplication(ctx, in.ProjectId, in.Id)
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
|
||||
func (s *Server) UpdateApplicationOIDCConfig(ctx context.Context, in *OIDCConfigUpdate) (*OIDCConfig, error) {
|
||||
if s.IsZitadel(ctx, in.ProjectId) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpee", "Zitadel Project Applications OIdc Config should not be changed")
|
||||
}
|
||||
config, err := s.project.ChangeOIDCConfig(ctx, oidcConfigUpdateToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -75,9 +65,6 @@ func (s *Server) UpdateApplicationOIDCConfig(ctx context.Context, in *OIDCConfig
|
||||
}
|
||||
|
||||
func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, in *ApplicationID) (*ClientSecret, error) {
|
||||
if s.IsZitadel(ctx, in.ProjectId) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-Lps4d", "Zitadel Project Applications OIdc Config should not be changed")
|
||||
}
|
||||
config, err := s.project.ChangeOIDConfigSecret(ctx, in.ProjectId, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
14
pkg/management/api/grpc/iam.go
Normal file
14
pkg/management/api/grpc/iam.go
Normal file
@ -0,0 +1,14 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) GetIam(ctx context.Context, _ *empty.Empty) (*Iam, error) {
|
||||
iam, err := s.iam.IamByID(ctx, s.systemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iamFromModel(iam), nil
|
||||
}
|
14
pkg/management/api/grpc/iam_converter.go
Normal file
14
pkg/management/api/grpc/iam_converter.go
Normal file
@ -0,0 +1,14 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
)
|
||||
|
||||
func iamFromModel(iam *iam_model.Iam) *Iam {
|
||||
return &Iam{
|
||||
IamProjectId: iam.IamProjectID,
|
||||
GlobalOrgId: iam.GlobalOrgID,
|
||||
SetUpDone: iam.SetUpDone,
|
||||
SetUpStarted: iam.SetUpStarted,
|
||||
}
|
||||
}
|
@ -15,6 +15,11 @@ import (
|
||||
|
||||
var ManagementService_AuthMethods = utils_auth.MethodMapping{
|
||||
|
||||
"/caos.zitadel.management.api.v1.ManagementService/GetIam": utils_auth.Option{
|
||||
Permission: "authenticated",
|
||||
CheckParam: "",
|
||||
},
|
||||
|
||||
"/caos.zitadel.management.api.v1.ManagementService/GetUserByID": utils_auth.Option{
|
||||
Permission: "user.read",
|
||||
CheckParam: "",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,15 @@ func request_ManagementService_Validate_0(ctx context.Context, marshaler runtime
|
||||
|
||||
}
|
||||
|
||||
func request_ManagementService_GetIam_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.GetIam(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_ManagementService_GetUserByID_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq UserID
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -3760,6 +3769,26 @@ func RegisterManagementServiceHandlerClient(ctx context.Context, mux *runtime.Se
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_ManagementService_GetIam_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_ManagementService_GetIam_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_ManagementService_GetIam_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_ManagementService_GetUserByID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@ -5950,6 +5979,8 @@ var (
|
||||
|
||||
pattern_ManagementService_Validate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"validate"}, ""))
|
||||
|
||||
pattern_ManagementService_GetIam_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"iam"}, ""))
|
||||
|
||||
pattern_ManagementService_GetUserByID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"users", "id"}, ""))
|
||||
|
||||
pattern_ManagementService_GetUserByEmailGlobal_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 2}, []string{"global", "users", "email"}, ""))
|
||||
@ -6176,6 +6207,8 @@ var (
|
||||
|
||||
forward_ManagementService_Validate_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_GetIam_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_GetUserByID_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ManagementService_GetUserByEmailGlobal_0 = runtime.ForwardResponseMessage
|
||||
|
@ -209,6 +209,23 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/iam": {
|
||||
"get": {
|
||||
"summary": "IAM",
|
||||
"operationId": "GetIam",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1Iam"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"ManagementService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/orgs/me/domains": {
|
||||
"post": {
|
||||
"operationId": "AddMyOrgDomain",
|
||||
@ -2663,7 +2680,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1User"
|
||||
"$ref": "#/definitions/v1UserView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2904,7 +2921,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1UserAddress"
|
||||
"$ref": "#/definitions/v1UserAddressView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3003,7 +3020,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1UserEmail"
|
||||
"$ref": "#/definitions/v1UserEmailView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3115,7 +3132,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1UserPhone"
|
||||
"$ref": "#/definitions/v1UserPhoneView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3202,7 +3219,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1UserProfile"
|
||||
"$ref": "#/definitions/v1UserProfileView"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3959,6 +3976,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1Iam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"global_org_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"iam_project_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"set_up_done": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"set_up_started": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1MFAState": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@ -5960,6 +5996,41 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserAddressView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"country": {
|
||||
"type": "string"
|
||||
},
|
||||
"locality": {
|
||||
"type": "string"
|
||||
},
|
||||
"postal_code": {
|
||||
"type": "string"
|
||||
},
|
||||
"region": {
|
||||
"type": "string"
|
||||
},
|
||||
"street_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserEmail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -5987,6 +6058,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserEmailView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"is_email_verified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserGrant": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -6242,6 +6340,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserPhoneView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"is_phone_verified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserProfile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -6283,6 +6408,56 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserProfileView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"nick_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"preferred_language": {
|
||||
"type": "string"
|
||||
},
|
||||
"gender": {
|
||||
"$ref": "#/definitions/v1Gender"
|
||||
},
|
||||
"user_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"change_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"login_names": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"preferred_login_name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1UserSearchKey": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@ -6454,6 +6629,15 @@
|
||||
},
|
||||
"resource_owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"login_names": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"preferred_login_name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"github.com/caos/zitadel/internal/api"
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
grpc_util "github.com/caos/zitadel/internal/api/grpc"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
@ -18,9 +17,6 @@ func (s *Server) CreateProject(ctx context.Context, in *ProjectCreateRequest) (*
|
||||
return projectFromModel(project), nil
|
||||
}
|
||||
func (s *Server) UpdateProject(ctx context.Context, in *ProjectUpdateRequest) (*Project, error) {
|
||||
if s.IsZitadel(ctx, in.Id) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-SFH8d", "Zitadel Project should not be updated")
|
||||
}
|
||||
project, err := s.project.UpdateProject(ctx, projectUpdateToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -28,9 +24,6 @@ func (s *Server) UpdateProject(ctx context.Context, in *ProjectUpdateRequest) (*
|
||||
return projectFromModel(project), nil
|
||||
}
|
||||
func (s *Server) DeactivateProject(ctx context.Context, in *ProjectID) (*Project, error) {
|
||||
if s.IsZitadel(ctx, in.Id) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-PS9cs", "Zitadel Project should not be deactivated")
|
||||
}
|
||||
project, err := s.project.DeactivateProject(ctx, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -38,9 +31,6 @@ func (s *Server) DeactivateProject(ctx context.Context, in *ProjectID) (*Project
|
||||
return projectFromModel(project), nil
|
||||
}
|
||||
func (s *Server) ReactivateProject(ctx context.Context, in *ProjectID) (*Project, error) {
|
||||
if s.IsZitadel(ctx, in.Id) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpe2", "Zitadel Project should not be reactivated")
|
||||
}
|
||||
project, err := s.project.ReactivateProject(ctx, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -85,9 +75,6 @@ func (s *Server) GetGrantedProjectByID(ctx context.Context, in *ProjectGrantID)
|
||||
}
|
||||
|
||||
func (s *Server) AddProjectRole(ctx context.Context, in *ProjectRoleAdd) (*ProjectRole, error) {
|
||||
if s.IsZitadel(ctx, in.Id) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-PS9cs", "Zitadel Project should not get new role")
|
||||
}
|
||||
role, err := s.project.AddProjectRole(ctx, projectRoleAddToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -95,9 +82,6 @@ func (s *Server) AddProjectRole(ctx context.Context, in *ProjectRoleAdd) (*Proje
|
||||
return projectRoleFromModel(role), nil
|
||||
}
|
||||
func (s *Server) ChangeProjectRole(ctx context.Context, in *ProjectRoleChange) (*ProjectRole, error) {
|
||||
if s.IsZitadel(ctx, in.Id) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LASj8", "Zitadel Project should not change roles")
|
||||
}
|
||||
role, err := s.project.ChangeProjectRole(ctx, projectRoleChangeToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -106,9 +90,6 @@ func (s *Server) ChangeProjectRole(ctx context.Context, in *ProjectRoleChange) (
|
||||
}
|
||||
|
||||
func (s *Server) RemoveProjectRole(ctx context.Context, in *ProjectRoleRemove) (*empty.Empty, error) {
|
||||
if s.IsZitadel(ctx, in.Id) {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-Psn7s", "do not remove roles from Zitadel Project")
|
||||
}
|
||||
err := s.project.RemoveProjectRole(ctx, in.Id, in.Key)
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
@ -131,14 +112,3 @@ func (s *Server) ProjectChanges(ctx context.Context, changesRequest *ChangeReque
|
||||
}
|
||||
return projectChangesToResponse(response, changesRequest.GetSequenceOffset(), changesRequest.GetLimit()), nil
|
||||
}
|
||||
|
||||
func (s *Server) IsZitadel(ctx context.Context, projectID string) bool {
|
||||
iam, err := s.iam.IamByID(ctx, s.systemDefaults.IamID)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if iam.IamProjectID == projectID {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -9,12 +9,12 @@ import (
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) GetUserByID(ctx context.Context, id *UserID) (*User, error) {
|
||||
func (s *Server) GetUserByID(ctx context.Context, id *UserID) (*UserView, error) {
|
||||
user, err := s.user.UserByID(ctx, id.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return userFromModel(user), nil
|
||||
return userViewFromModel(user), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetUserByEmailGlobal(ctx context.Context, email *UserEmailID) (*UserView, error) {
|
||||
@ -96,12 +96,12 @@ func (s *Server) DeleteUser(ctx context.Context, in *UserID) (*empty.Empty, erro
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-as4fg", "Not implemented")
|
||||
}
|
||||
|
||||
func (s *Server) GetUserProfile(ctx context.Context, in *UserID) (*UserProfile, error) {
|
||||
func (s *Server) GetUserProfile(ctx context.Context, in *UserID) (*UserProfileView, error) {
|
||||
profile, err := s.user.ProfileByID(ctx, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return profileFromModel(profile), nil
|
||||
return profileViewFromModel(profile), nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateUserProfile(ctx context.Context, request *UpdateUserProfileRequest) (*UserProfile, error) {
|
||||
@ -112,12 +112,12 @@ func (s *Server) UpdateUserProfile(ctx context.Context, request *UpdateUserProfi
|
||||
return profileFromModel(profile), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetUserEmail(ctx context.Context, in *UserID) (*UserEmail, error) {
|
||||
func (s *Server) GetUserEmail(ctx context.Context, in *UserID) (*UserEmailView, error) {
|
||||
email, err := s.user.EmailByID(ctx, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return emailFromModel(email), nil
|
||||
return emailViewFromModel(email), nil
|
||||
}
|
||||
|
||||
func (s *Server) ChangeUserEmail(ctx context.Context, request *UpdateUserEmailRequest) (*UserEmail, error) {
|
||||
@ -133,12 +133,12 @@ func (s *Server) ResendEmailVerificationMail(ctx context.Context, in *UserID) (*
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
|
||||
func (s *Server) GetUserPhone(ctx context.Context, in *UserID) (*UserPhone, error) {
|
||||
func (s *Server) GetUserPhone(ctx context.Context, in *UserID) (*UserPhoneView, error) {
|
||||
phone, err := s.user.PhoneByID(ctx, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return phoneFromModel(phone), nil
|
||||
return phoneViewFromModel(phone), nil
|
||||
}
|
||||
|
||||
func (s *Server) ChangeUserPhone(ctx context.Context, request *UpdateUserPhoneRequest) (*UserPhone, error) {
|
||||
@ -154,12 +154,12 @@ func (s *Server) ResendPhoneVerificationCode(ctx context.Context, in *UserID) (*
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
|
||||
func (s *Server) GetUserAddress(ctx context.Context, in *UserID) (*UserAddress, error) {
|
||||
func (s *Server) GetUserAddress(ctx context.Context, in *UserID) (*UserAddressView, error) {
|
||||
address, err := s.user.AddressByID(ctx, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return addressFromModel(address), nil
|
||||
return addressViewFromModel(address), nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateUserAddress(ctx context.Context, request *UpdateUserAddressRequest) (*UserAddress, error) {
|
||||
|
@ -160,6 +160,30 @@ func profileFromModel(profile *usr_model.Profile) *UserProfile {
|
||||
}
|
||||
}
|
||||
|
||||
func profileViewFromModel(profile *usr_model.Profile) *UserProfileView {
|
||||
creationDate, err := ptypes.TimestampProto(profile.CreationDate)
|
||||
logging.Log("GRPC-sk8sk").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(profile.ChangeDate)
|
||||
logging.Log("GRPC-s30Ks'").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserProfileView{
|
||||
Id: profile.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: profile.Sequence,
|
||||
UserName: profile.UserName,
|
||||
FirstName: profile.FirstName,
|
||||
LastName: profile.LastName,
|
||||
DisplayName: profile.DisplayName,
|
||||
NickName: profile.NickName,
|
||||
PreferredLanguage: profile.PreferredLanguage.String(),
|
||||
Gender: genderFromModel(profile.Gender),
|
||||
LoginNames: profile.LoginNames,
|
||||
PreferredLoginName: profile.PreferredLoginName,
|
||||
}
|
||||
}
|
||||
|
||||
func updateProfileToModel(u *UpdateUserProfileRequest) *usr_model.Profile {
|
||||
preferredLanguage, err := language.Parse(u.PreferredLanguage)
|
||||
logging.Log("GRPC-d8k2s").OnError(err).Debug("language malformed")
|
||||
@ -192,6 +216,23 @@ func emailFromModel(email *usr_model.Email) *UserEmail {
|
||||
}
|
||||
}
|
||||
|
||||
func emailViewFromModel(email *usr_model.Email) *UserEmailView {
|
||||
creationDate, err := ptypes.TimestampProto(email.CreationDate)
|
||||
logging.Log("GRPC-sKefs").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(email.ChangeDate)
|
||||
logging.Log("GRPC-0isjD").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserEmailView{
|
||||
Id: email.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: email.Sequence,
|
||||
Email: email.EmailAddress,
|
||||
IsEmailVerified: email.IsEmailVerified,
|
||||
}
|
||||
}
|
||||
|
||||
func updateEmailToModel(e *UpdateUserEmailRequest) *usr_model.Email {
|
||||
return &usr_model.Email{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: e.Id},
|
||||
@ -217,6 +258,22 @@ func phoneFromModel(phone *usr_model.Phone) *UserPhone {
|
||||
}
|
||||
}
|
||||
|
||||
func phoneViewFromModel(phone *usr_model.Phone) *UserPhoneView {
|
||||
creationDate, err := ptypes.TimestampProto(phone.CreationDate)
|
||||
logging.Log("GRPC-6gSj").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(phone.ChangeDate)
|
||||
logging.Log("GRPC-lKs8f").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserPhoneView{
|
||||
Id: phone.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: phone.Sequence,
|
||||
Phone: phone.PhoneNumber,
|
||||
IsPhoneVerified: phone.IsPhoneVerified,
|
||||
}
|
||||
}
|
||||
func updatePhoneToModel(e *UpdateUserPhoneRequest) *usr_model.Phone {
|
||||
return &usr_model.Phone{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: e.Id},
|
||||
@ -245,6 +302,26 @@ func addressFromModel(address *usr_model.Address) *UserAddress {
|
||||
}
|
||||
}
|
||||
|
||||
func addressViewFromModel(address *usr_model.Address) *UserAddressView {
|
||||
creationDate, err := ptypes.TimestampProto(address.CreationDate)
|
||||
logging.Log("GRPC-67stC").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(address.ChangeDate)
|
||||
logging.Log("GRPC-0jSfs").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserAddressView{
|
||||
Id: address.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Sequence: address.Sequence,
|
||||
Country: address.Country,
|
||||
StreetAddress: address.StreetAddress,
|
||||
Region: address.Region,
|
||||
PostalCode: address.PostalCode,
|
||||
Locality: address.Locality,
|
||||
}
|
||||
}
|
||||
|
||||
func updateAddressToModel(address *UpdateUserAddressRequest) *usr_model.Address {
|
||||
return &usr_model.Address{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: address.Id},
|
||||
@ -287,27 +364,29 @@ func userViewFromModel(user *usr_model.UserView) *UserView {
|
||||
logging.Log("GRPC-dl9ws").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &UserView{
|
||||
Id: user.ID,
|
||||
State: userStateFromModel(user.State),
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
LastLogin: lastLogin,
|
||||
PasswordChanged: passwordChanged,
|
||||
Sequence: user.Sequence,
|
||||
ResourceOwner: user.ResourceOwner,
|
||||
UserName: user.UserName,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
NickName: user.NickName,
|
||||
Email: user.Email,
|
||||
IsEmailVerified: user.IsEmailVerified,
|
||||
Phone: user.Phone,
|
||||
IsPhoneVerified: user.IsPhoneVerified,
|
||||
Country: user.Country,
|
||||
Locality: user.Locality,
|
||||
Region: user.Region,
|
||||
PostalCode: user.PostalCode,
|
||||
StreetAddress: user.StreetAddress,
|
||||
Id: user.ID,
|
||||
State: userStateFromModel(user.State),
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
LastLogin: lastLogin,
|
||||
PasswordChanged: passwordChanged,
|
||||
Sequence: user.Sequence,
|
||||
ResourceOwner: user.ResourceOwner,
|
||||
UserName: user.UserName,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
NickName: user.NickName,
|
||||
Email: user.Email,
|
||||
IsEmailVerified: user.IsEmailVerified,
|
||||
Phone: user.Phone,
|
||||
IsPhoneVerified: user.IsPhoneVerified,
|
||||
Country: user.Country,
|
||||
Locality: user.Locality,
|
||||
Region: user.Region,
|
||||
PostalCode: user.PostalCode,
|
||||
StreetAddress: user.StreetAddress,
|
||||
LoginNames: user.LoginNames,
|
||||
PreferredLoginName: user.PreferredLoginName,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,19 @@ service ManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
//IAM
|
||||
rpc GetIam(google.protobuf.Empty) returns (Iam) {
|
||||
option (google.api.http) = {
|
||||
get: "/iam"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "authenticated"
|
||||
};
|
||||
}
|
||||
|
||||
//USER
|
||||
rpc GetUserByID(UserID) returns (User) {
|
||||
rpc GetUserByID(UserID) returns (UserView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/{id}"
|
||||
};
|
||||
@ -199,7 +210,7 @@ service ManagementService {
|
||||
}
|
||||
|
||||
//USER_PROFILE
|
||||
rpc GetUserProfile(UserID) returns (UserProfile) {
|
||||
rpc GetUserProfile(UserID) returns (UserProfileView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/{id}/profile"
|
||||
};
|
||||
@ -221,7 +232,7 @@ service ManagementService {
|
||||
}
|
||||
|
||||
//USER_EMAIL
|
||||
rpc GetUserEmail(UserID) returns (UserEmail) {
|
||||
rpc GetUserEmail(UserID) returns (UserEmailView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/{id}/email"
|
||||
};
|
||||
@ -254,7 +265,7 @@ service ManagementService {
|
||||
}
|
||||
|
||||
//USER_PHONE
|
||||
rpc GetUserPhone(UserID) returns (UserPhone) {
|
||||
rpc GetUserPhone(UserID) returns (UserPhoneView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/{id}/phone"
|
||||
};
|
||||
@ -287,7 +298,7 @@ service ManagementService {
|
||||
}
|
||||
|
||||
//USER_ADDRESS
|
||||
rpc GetUserAddress(UserID) returns (UserAddress) {
|
||||
rpc GetUserAddress(UserID) returns (UserAddressView) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/{id}/address"
|
||||
};
|
||||
@ -1266,6 +1277,13 @@ service ManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
message Iam {
|
||||
string global_org_id = 1;
|
||||
string iam_project_id = 2;
|
||||
bool set_up_done = 3;
|
||||
bool set_up_started = 4;
|
||||
}
|
||||
|
||||
message ChangeRequest {
|
||||
string id = 1;
|
||||
string sec_id = 2;
|
||||
@ -1399,6 +1417,8 @@ message UserView {
|
||||
string street_address = 22;
|
||||
uint64 sequence = 23;
|
||||
string resource_owner = 24;
|
||||
repeated string login_names = 25;
|
||||
string preferred_login_name = 27;
|
||||
}
|
||||
|
||||
message UserSearchRequest {
|
||||
@ -1456,6 +1476,22 @@ message UserProfile {
|
||||
google.protobuf.Timestamp change_date = 11;
|
||||
}
|
||||
|
||||
message UserProfileView {
|
||||
string id = 1;
|
||||
string first_name = 2;
|
||||
string last_name = 3;
|
||||
string nick_name = 4;
|
||||
string display_name = 5;
|
||||
string preferred_language = 6;
|
||||
Gender gender = 7;
|
||||
string user_name = 8;
|
||||
uint64 sequence = 9;
|
||||
google.protobuf.Timestamp creation_date = 10;
|
||||
google.protobuf.Timestamp change_date = 11;
|
||||
repeated string login_names = 12;
|
||||
string preferred_login_name = 27;
|
||||
}
|
||||
|
||||
message UpdateUserProfileRequest {
|
||||
string id = 1;
|
||||
string first_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
@ -1475,6 +1511,15 @@ message UserEmail {
|
||||
google.protobuf.Timestamp change_date = 6;
|
||||
}
|
||||
|
||||
message UserEmailView {
|
||||
string id = 1;
|
||||
string email = 2;
|
||||
bool is_email_verified = 3;
|
||||
uint64 sequence = 4;
|
||||
google.protobuf.Timestamp creation_date = 5;
|
||||
google.protobuf.Timestamp change_date = 6;
|
||||
}
|
||||
|
||||
message UpdateUserEmailRequest {
|
||||
string id = 1;
|
||||
string email = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
@ -1490,6 +1535,15 @@ message UserPhone {
|
||||
google.protobuf.Timestamp change_date = 7;
|
||||
}
|
||||
|
||||
message UserPhoneView {
|
||||
string id = 1;
|
||||
string phone = 2;
|
||||
bool is_phone_verified = 3;
|
||||
uint64 sequence = 5;
|
||||
google.protobuf.Timestamp creation_date = 6;
|
||||
google.protobuf.Timestamp change_date = 7;
|
||||
}
|
||||
|
||||
message UpdateUserPhoneRequest {
|
||||
string id = 1;
|
||||
string phone = 2 [(validate.rules).string = {min_len: 1, max_len: 20}];
|
||||
@ -1508,6 +1562,18 @@ message UserAddress {
|
||||
google.protobuf.Timestamp change_date = 9;
|
||||
}
|
||||
|
||||
message UserAddressView {
|
||||
string id = 1;
|
||||
string country = 2;
|
||||
string locality = 3;
|
||||
string postal_code = 4;
|
||||
string region = 5;
|
||||
string street_address = 6;
|
||||
uint64 sequence = 7;
|
||||
google.protobuf.Timestamp creation_date = 8;
|
||||
google.protobuf.Timestamp change_date = 9;
|
||||
}
|
||||
|
||||
message UpdateUserAddressRequest {
|
||||
string id = 1;
|
||||
string country = 2 [(validate.rules).string = {max_len: 200}];
|
||||
|
Loading…
x
Reference in New Issue
Block a user