mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:27:42 +00:00
fix: add avatar url in members, user grants, session and oidc responses (#1852)
* fix: add avatar url in members, user grants, session and oidc responses * fix auth request tests
This commit is contained in:
@@ -2,9 +2,10 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/command"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"time"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
@@ -57,9 +58,11 @@ type AuthRequestRepo struct {
|
||||
type userSessionViewProvider interface {
|
||||
UserSessionByIDs(string, string) (*user_view_model.UserSessionView, error)
|
||||
UserSessionsByAgentID(string) ([]*user_view_model.UserSessionView, error)
|
||||
PrefixAvatarURL() string
|
||||
}
|
||||
type userViewProvider interface {
|
||||
UserByID(string) (*user_view_model.UserView, error)
|
||||
PrefixAvatarURL() string
|
||||
}
|
||||
|
||||
type loginPolicyViewProvider interface {
|
||||
@@ -616,6 +619,7 @@ func (repo *AuthRequestRepo) usersForUserSelection(request *domain.AuthRequest)
|
||||
DisplayName: session.DisplayName,
|
||||
UserName: session.UserName,
|
||||
LoginName: session.LoginName,
|
||||
ResourceOwner: session.ResourceOwner,
|
||||
AvatarKey: session.AvatarKey,
|
||||
UserSessionState: auth_req_model.UserSessionStateToDomain(session.State),
|
||||
SelectionPossible: request.RequestedOrgID == "" || request.RequestedOrgID == session.ResourceOwner,
|
||||
@@ -767,7 +771,7 @@ func userSessionsByUserAgentID(provider userSessionViewProvider, agentID string)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user_view_model.UserSessionsToModel(session), nil
|
||||
return user_view_model.UserSessionsToModel(session, provider.PrefixAvatarURL()), nil
|
||||
}
|
||||
|
||||
func userSessionByIDs(ctx context.Context, provider userSessionViewProvider, eventProvider userEventProvider, agentID string, user *user_model.UserView) (*user_model.UserSessionView, error) {
|
||||
@@ -781,7 +785,7 @@ func userSessionByIDs(ctx context.Context, provider userSessionViewProvider, eve
|
||||
events, err := eventProvider.UserEventsByID(ctx, user.ID, session.Sequence)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-Hse6s").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error retrieving new events")
|
||||
return user_view_model.UserSessionToModel(session), nil
|
||||
return user_view_model.UserSessionToModel(session, provider.PrefixAvatarURL()), nil
|
||||
}
|
||||
sessionCopy := *session
|
||||
for _, event := range events {
|
||||
@@ -806,7 +810,7 @@ func userSessionByIDs(ctx context.Context, provider userSessionViewProvider, eve
|
||||
eventData, err := user_view_model.UserSessionFromEvent(event)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-sdgT3").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error getting event data")
|
||||
return user_view_model.UserSessionToModel(session), nil
|
||||
return user_view_model.UserSessionToModel(session, provider.PrefixAvatarURL()), nil
|
||||
}
|
||||
if eventData.UserAgentID != agentID {
|
||||
continue
|
||||
@@ -817,7 +821,7 @@ func userSessionByIDs(ctx context.Context, provider userSessionViewProvider, eve
|
||||
err := sessionCopy.AppendEvent(event)
|
||||
logging.Log("EVENT-qbhj3").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("error appending event")
|
||||
}
|
||||
return user_view_model.UserSessionToModel(&sessionCopy), nil
|
||||
return user_view_model.UserSessionToModel(&sessionCopy, provider.PrefixAvatarURL()), nil
|
||||
}
|
||||
|
||||
func activeUserByID(ctx context.Context, userViewProvider userViewProvider, userEventProvider userEventProvider, orgViewProvider orgViewProvider, userID string) (*user_model.UserView, error) {
|
||||
@@ -856,24 +860,24 @@ func userByID(ctx context.Context, viewProvider userViewProvider, eventProvider
|
||||
events, err := eventProvider.UserEventsByID(ctx, userID, user.Sequence)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-dfg42").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error retrieving new events")
|
||||
return user_view_model.UserToModel(user), nil
|
||||
return user_view_model.UserToModel(user, viewProvider.PrefixAvatarURL()), nil
|
||||
}
|
||||
if len(events) == 0 {
|
||||
if viewErr != nil {
|
||||
return nil, viewErr
|
||||
}
|
||||
return user_view_model.UserToModel(user), viewErr
|
||||
return user_view_model.UserToModel(user, viewProvider.PrefixAvatarURL()), viewErr
|
||||
}
|
||||
userCopy := *user
|
||||
for _, event := range events {
|
||||
if err := userCopy.AppendEvent(event); err != nil {
|
||||
return user_view_model.UserToModel(user), nil
|
||||
return user_view_model.UserToModel(user, viewProvider.PrefixAvatarURL()), nil
|
||||
}
|
||||
}
|
||||
if userCopy.State == int32(user_model.UserStateDeleted) {
|
||||
return nil, errors.ThrowNotFound(nil, "EVENT-3F9so", "Errors.User.NotFound")
|
||||
}
|
||||
return user_view_model.UserToModel(&userCopy), nil
|
||||
return user_view_model.UserToModel(&userCopy, viewProvider.PrefixAvatarURL()), nil
|
||||
}
|
||||
|
||||
func linkExternalIDPs(ctx context.Context, userCommandProvider userCommandProvider, request *domain.AuthRequest) error {
|
||||
|
@@ -3,20 +3,19 @@ package eventstore
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
||||
"github.com/caos/zitadel/internal/auth_request/model"
|
||||
"github.com/caos/zitadel/internal/auth_request/repository/cache"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
org_model "github.com/caos/zitadel/internal/org/model"
|
||||
org_view_model "github.com/caos/zitadel/internal/org/repository/view/model"
|
||||
proj_view_model "github.com/caos/zitadel/internal/project/repository/view/model"
|
||||
@@ -36,6 +35,10 @@ func (m *mockViewNoUserSession) UserSessionsByAgentID(string) ([]*user_view_mode
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockViewNoUserSession) PrefixAvatarURL() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type mockViewErrUserSession struct{}
|
||||
|
||||
func (m *mockViewErrUserSession) UserSessionByIDs(string, string) (*user_view_model.UserSessionView, error) {
|
||||
@@ -46,6 +49,10 @@ func (m *mockViewErrUserSession) UserSessionsByAgentID(string) ([]*user_view_mod
|
||||
return nil, errors.ThrowInternal(nil, "id", "internal error")
|
||||
}
|
||||
|
||||
func (m *mockViewErrUserSession) PrefixAvatarURL() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type mockViewUserSession struct {
|
||||
ExternalLoginVerification time.Time
|
||||
PasswordlessVerification time.Time
|
||||
@@ -83,12 +90,20 @@ func (m *mockViewUserSession) UserSessionsByAgentID(string) ([]*user_view_model.
|
||||
return sessions, nil
|
||||
}
|
||||
|
||||
func (m *mockViewUserSession) PrefixAvatarURL() string {
|
||||
return "prefix/"
|
||||
}
|
||||
|
||||
type mockViewNoUser struct{}
|
||||
|
||||
func (m *mockViewNoUser) UserByID(string) (*user_view_model.UserView, error) {
|
||||
return nil, errors.ThrowNotFound(nil, "id", "user not found")
|
||||
}
|
||||
|
||||
func (m *mockViewNoUser) PrefixAvatarURL() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type mockEventUser struct {
|
||||
Event *es_models.Event
|
||||
}
|
||||
@@ -152,6 +167,10 @@ func (m *mockViewUser) UserByID(string) (*user_view_model.UserView, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockViewUser) PrefixAvatarURL() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type mockViewOrg struct {
|
||||
State org_model.OrgState
|
||||
}
|
||||
@@ -291,11 +310,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
UserID: "id1",
|
||||
LoginName: "loginname1",
|
||||
SelectionPossible: true,
|
||||
ResourceOwner: "orgID1",
|
||||
},
|
||||
{
|
||||
UserID: "id2",
|
||||
LoginName: "loginname2",
|
||||
SelectionPossible: true,
|
||||
ResourceOwner: "orgID2",
|
||||
},
|
||||
},
|
||||
}},
|
||||
@@ -329,11 +350,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
UserID: "id1",
|
||||
LoginName: "loginname1",
|
||||
SelectionPossible: true,
|
||||
ResourceOwner: "orgID1",
|
||||
},
|
||||
{
|
||||
UserID: "id2",
|
||||
LoginName: "loginname2",
|
||||
SelectionPossible: false,
|
||||
ResourceOwner: "orgID2",
|
||||
},
|
||||
},
|
||||
}},
|
||||
|
@@ -24,10 +24,11 @@ import (
|
||||
)
|
||||
|
||||
type UserRepo struct {
|
||||
SearchLimit uint64
|
||||
Eventstore v1.Eventstore
|
||||
View *view.View
|
||||
SystemDefaults systemdefaults.SystemDefaults
|
||||
SearchLimit uint64
|
||||
Eventstore v1.Eventstore
|
||||
View *view.View
|
||||
SystemDefaults systemdefaults.SystemDefaults
|
||||
PrefixAvatarURL string
|
||||
}
|
||||
|
||||
func (repo *UserRepo) Health(ctx context.Context) error {
|
||||
@@ -153,18 +154,18 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (*model.UserView,
|
||||
events, err := repo.getUserEvents(ctx, id, user.Sequence)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-PSoc3").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error retrieving new events")
|
||||
return usr_view_model.UserToModel(user), nil
|
||||
return usr_view_model.UserToModel(user, repo.PrefixAvatarURL), 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(user, repo.PrefixAvatarURL), nil
|
||||
}
|
||||
}
|
||||
if userCopy.State == int32(model.UserStateDeleted) {
|
||||
return nil, errors.ThrowNotFound(nil, "EVENT-vZ8us", "Errors.User.NotFound")
|
||||
}
|
||||
return usr_view_model.UserToModel(&userCopy), nil
|
||||
return usr_view_model.UserToModel(&userCopy, repo.PrefixAvatarURL), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserEventsByID(ctx context.Context, id string, sequence uint64) ([]*models.Event, error) {
|
||||
@@ -179,18 +180,18 @@ func (repo *UserRepo) UserByLoginName(ctx context.Context, loginname string) (*m
|
||||
events, err := repo.getUserEvents(ctx, user.ID, user.Sequence)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-PSoc3").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error retrieving new events")
|
||||
return usr_view_model.UserToModel(user), nil
|
||||
return usr_view_model.UserToModel(user, repo.PrefixAvatarURL), 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(user, repo.PrefixAvatarURL), nil
|
||||
}
|
||||
}
|
||||
if userCopy.State == int32(model.UserStateDeleted) {
|
||||
return nil, errors.ThrowNotFound(nil, "EVENT-vZ8us", "Errors.User.NotFound")
|
||||
}
|
||||
return usr_view_model.UserToModel(&userCopy), nil
|
||||
return usr_view_model.UserToModel(&userCopy, repo.PrefixAvatarURL), nil
|
||||
}
|
||||
func (repo *UserRepo) MyUserChanges(ctx context.Context, lastSequence uint64, limit uint64, sortAscending bool, retention time.Duration) (*model.UserChanges, error) {
|
||||
changes, err := repo.getUserChanges(ctx, authz.GetCtxData(ctx).UserID, lastSequence, limit, sortAscending, retention)
|
||||
@@ -233,7 +234,7 @@ func (repo *UserRepo) SearchUsers(ctx context.Context, request *model.UserSearch
|
||||
Offset: request.Offset,
|
||||
Limit: request.Limit,
|
||||
TotalResult: count,
|
||||
Result: usr_view_model.UsersToModel(users),
|
||||
Result: usr_view_model.UsersToModel(users, repo.PrefixAvatarURL),
|
||||
}
|
||||
if sequenceErr == nil {
|
||||
result.Sequence = sequence.CurrentSequence
|
||||
|
@@ -21,11 +21,12 @@ import (
|
||||
)
|
||||
|
||||
type UserGrantRepo struct {
|
||||
SearchLimit uint64
|
||||
View *view.View
|
||||
IamID string
|
||||
Auth authz.Config
|
||||
AuthZRepo *authz_repo.EsRepository
|
||||
SearchLimit uint64
|
||||
View *view.View
|
||||
IamID string
|
||||
Auth authz.Config
|
||||
AuthZRepo *authz_repo.EsRepository
|
||||
PrefixAvatarURL string
|
||||
}
|
||||
|
||||
func (repo *UserGrantRepo) SearchMyUserGrants(ctx context.Context, request *grant_model.UserGrantSearchRequest) (*grant_model.UserGrantSearchResponse, error) {
|
||||
@@ -44,7 +45,7 @@ func (repo *UserGrantRepo) SearchMyUserGrants(ctx context.Context, request *gran
|
||||
Offset: request.Offset,
|
||||
Limit: request.Limit,
|
||||
TotalResult: count,
|
||||
Result: model.UserGrantsToModel(grants),
|
||||
Result: model.UserGrantsToModel(grants, repo.PrefixAvatarURL),
|
||||
}
|
||||
if err == nil {
|
||||
result.Sequence = sequence.CurrentSequence
|
||||
@@ -234,7 +235,7 @@ func (repo *UserGrantRepo) UserGrantsByProjectAndUserID(projectID, userID string
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return model.UserGrantsToModel(grants), nil
|
||||
return model.UserGrantsToModel(grants, repo.PrefixAvatarURL), nil
|
||||
}
|
||||
|
||||
func (repo *UserGrantRepo) userOrg(ctxData authz.CtxData) (*grant_model.ProjectOrgSearchResponse, error) {
|
||||
|
@@ -18,7 +18,7 @@ func (repo *UserSessionRepo) GetMyUserSessions(ctx context.Context) ([]*usr_mode
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return model.UserSessionsToModel(userSessions), nil
|
||||
return model.UserSessionsToModel(userSessions, repo.View.PrefixAvatarURL()), nil
|
||||
}
|
||||
|
||||
func (repo *UserSessionRepo) ActiveUserSessionCount() int64 {
|
||||
|
@@ -2,10 +2,11 @@ package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
|
||||
"strings"
|
||||
|
||||
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"
|
||||
org_view "github.com/caos/zitadel/internal/org/repository/view"
|
||||
@@ -149,7 +150,9 @@ func (u *UserGrant) processUser(event *es_models.Event) (err error) {
|
||||
usr_es_model.UserEmailChanged,
|
||||
usr_es_model.HumanProfileChanged,
|
||||
usr_es_model.HumanEmailChanged,
|
||||
usr_es_model.MachineChanged:
|
||||
usr_es_model.MachineChanged,
|
||||
usr_es_model.HumanAvatarAdded,
|
||||
usr_es_model.HumanAvatarRemoved:
|
||||
grants, err := u.view.UserGrantsByUserID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -396,11 +399,13 @@ func (u *UserGrant) fillData(grant *view_model.UserGrantView, resourceOwner stri
|
||||
|
||||
func (u *UserGrant) fillUserData(grant *view_model.UserGrantView, user *model.UserView) {
|
||||
grant.UserName = user.UserName
|
||||
grant.UserResourceOwner = user.ResourceOwner
|
||||
if user.HumanView != nil {
|
||||
grant.FirstName = user.FirstName
|
||||
grant.LastName = user.LastName
|
||||
grant.DisplayName = user.FirstName + " " + user.LastName
|
||||
grant.Email = user.Email
|
||||
grant.AvatarKey = user.AvatarKey
|
||||
}
|
||||
if user.MachineView != nil {
|
||||
grant.DisplayName = user.MachineView.Name
|
||||
|
@@ -24,6 +24,7 @@ import (
|
||||
type Config struct {
|
||||
SearchLimit uint64
|
||||
Domain string
|
||||
APIDomain string
|
||||
Eventstore v1.Config
|
||||
AuthRequest cache.Config
|
||||
View types.SQL
|
||||
@@ -63,7 +64,9 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
|
||||
}
|
||||
idGenerator := id.SonyFlakeGenerator
|
||||
|
||||
view, err := auth_view.StartView(sqlClient, keyAlgorithm, idGenerator)
|
||||
assetsAPI := conf.APIDomain + "/assets/v1/"
|
||||
|
||||
view, err := auth_view.StartView(sqlClient, keyAlgorithm, idGenerator, assetsAPI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -78,10 +81,11 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
|
||||
locker := spooler.NewLocker(sqlClient)
|
||||
|
||||
userRepo := eventstore.UserRepo{
|
||||
SearchLimit: conf.SearchLimit,
|
||||
Eventstore: es,
|
||||
View: view,
|
||||
SystemDefaults: systemDefaults,
|
||||
SearchLimit: conf.SearchLimit,
|
||||
Eventstore: es,
|
||||
View: view,
|
||||
SystemDefaults: systemDefaults,
|
||||
PrefixAvatarURL: assetsAPI,
|
||||
}
|
||||
return &EsRepository{
|
||||
spool,
|
||||
|
@@ -10,23 +10,29 @@ import (
|
||||
)
|
||||
|
||||
type View struct {
|
||||
Db *gorm.DB
|
||||
keyAlgorithm crypto.EncryptionAlgorithm
|
||||
idGenerator id.Generator
|
||||
Db *gorm.DB
|
||||
keyAlgorithm crypto.EncryptionAlgorithm
|
||||
idGenerator id.Generator
|
||||
prefixAvatarURL string
|
||||
}
|
||||
|
||||
func StartView(sqlClient *sql.DB, keyAlgorithm crypto.EncryptionAlgorithm, idGenerator id.Generator) (*View, error) {
|
||||
func StartView(sqlClient *sql.DB, keyAlgorithm crypto.EncryptionAlgorithm, idGenerator id.Generator, prefixAvatarURL string) (*View, error) {
|
||||
gorm, err := gorm.Open("postgres", sqlClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &View{
|
||||
Db: gorm,
|
||||
keyAlgorithm: keyAlgorithm,
|
||||
idGenerator: idGenerator,
|
||||
Db: gorm,
|
||||
keyAlgorithm: keyAlgorithm,
|
||||
idGenerator: idGenerator,
|
||||
prefixAvatarURL: prefixAvatarURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *View) Health() (err error) {
|
||||
return v.Db.DB().Ping()
|
||||
}
|
||||
|
||||
func (v *View) PrefixAvatarURL() string {
|
||||
return v.prefixAvatarURL
|
||||
}
|
||||
|
Reference in New Issue
Block a user