zitadel/internal/api/grpc/management/user_converter.go
Fabi 7451ed58f2
feat: User metadata (#2025)
* feat: user meta data events

* feat: user meta data set tests

* feat: user meta data tests

* feat: user meta data in protos

* feat: user meta data command api

* feat: user meta data query side

* feat: proto correct order, fix handlers

* feat: proto correct order

* feat: fixes of pr comments

* feat: fixes of pr comments

* feat: value as byte array

* feat: metadata feature

* Update internal/auth/repository/eventsourcing/handler/meta_data.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/command/user_meta_data.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update proto/zitadel/metadata.proto

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update proto/zitadel/metadata.proto

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* fix: rename metadata files and table

* fix: rename meta data to metadat in protos

* Update internal/domain/metadata.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* fix: rename vars

* fix: rebiuld docs

* Update internal/iam/repository/view/metadata_view.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
2021-08-09 08:01:20 +02:00

301 lines
9.4 KiB
Go

package management
import (
"context"
"time"
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"golang.org/x/text/language"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/api/grpc/authn"
"github.com/caos/zitadel/internal/api/grpc/metadata"
"github.com/caos/zitadel/internal/api/grpc/object"
user_grpc "github.com/caos/zitadel/internal/api/grpc/user"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/eventstore/v1/models"
key_model "github.com/caos/zitadel/internal/key/model"
user_model "github.com/caos/zitadel/internal/user/model"
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
user_pb "github.com/caos/zitadel/pkg/grpc/user"
)
func ListUsersRequestToModel(ctx context.Context, req *mgmt_pb.ListUsersRequest) *user_model.UserSearchRequest {
offset, limit, asc := object.ListQueryToModel(req.Query)
req.Queries = append(req.Queries, &user_pb.SearchQuery{
Query: &user_pb.SearchQuery_ResourceOwner{
ResourceOwner: &user_pb.ResourceOwnerQuery{
OrgID: authz.GetCtxData(ctx).OrgID,
},
},
})
return &user_model.UserSearchRequest{
Offset: offset,
Limit: limit,
Asc: asc,
Queries: user_grpc.UserQueriesToModel(req.Queries),
}
}
func BulkSetMetadataToDomain(req *mgmt_pb.BulkSetUserMetadataRequest) []*domain.Metadata {
metadata := make([]*domain.Metadata, len(req.Metadata))
for i, data := range req.Metadata {
metadata[i] = &domain.Metadata{
Key: data.Key,
Value: data.Value,
}
}
return metadata
}
func ListUserMetadataToDomain(req *mgmt_pb.ListUserMetadataRequest) *domain.MetadataSearchRequest {
offset, limit, asc := object.ListQueryToModel(req.Query)
return &domain.MetadataSearchRequest{
Offset: offset,
Limit: limit,
Asc: asc,
Queries: metadata.MetadataQueriesToModel(req.Queries),
}
}
func AddHumanUserRequestToDomain(req *mgmt_pb.AddHumanUserRequest) *domain.Human {
h := &domain.Human{
Username: req.UserName,
}
preferredLanguage, err := language.Parse(req.Profile.PreferredLanguage)
logging.Log("MANAG-M029f").OnError(err).Debug("language malformed")
h.Profile = &domain.Profile{
FirstName: req.Profile.FirstName,
LastName: req.Profile.LastName,
NickName: req.Profile.NickName,
DisplayName: req.Profile.DisplayName,
PreferredLanguage: preferredLanguage,
Gender: user_grpc.GenderToDomain(req.Profile.Gender),
}
h.Email = &domain.Email{
EmailAddress: req.Email.Email,
IsEmailVerified: req.Email.IsEmailVerified,
}
if req.Phone != nil {
h.Phone = &domain.Phone{
PhoneNumber: req.Phone.Phone,
IsPhoneVerified: req.Phone.IsPhoneVerified,
}
}
if req.InitialPassword != "" {
h.Password = &domain.Password{SecretString: req.InitialPassword, ChangeRequired: true}
}
return h
}
func ImportHumanUserRequestToDomain(req *mgmt_pb.ImportHumanUserRequest) (human *domain.Human, passwordless bool) {
human = &domain.Human{
Username: req.UserName,
}
preferredLanguage, err := language.Parse(req.Profile.PreferredLanguage)
logging.Log("MANAG-3GUFJ").OnError(err).Debug("language malformed")
human.Profile = &domain.Profile{
FirstName: req.Profile.FirstName,
LastName: req.Profile.LastName,
NickName: req.Profile.NickName,
DisplayName: req.Profile.DisplayName,
PreferredLanguage: preferredLanguage,
Gender: user_grpc.GenderToDomain(req.Profile.Gender),
}
human.Email = &domain.Email{
EmailAddress: req.Email.Email,
IsEmailVerified: req.Email.IsEmailVerified,
}
if req.Phone != nil {
human.Phone = &domain.Phone{
PhoneNumber: req.Phone.Phone,
IsPhoneVerified: req.Phone.IsPhoneVerified,
}
}
if req.Password != "" {
human.Password = &domain.Password{SecretString: req.Password}
human.Password.ChangeRequired = req.PasswordChangeRequired
}
return human, req.RequestPasswordlessRegistration
}
func AddMachineUserRequestToDomain(req *mgmt_pb.AddMachineUserRequest) *domain.Machine {
return &domain.Machine{
Username: req.UserName,
Name: req.Name,
Description: req.Description,
}
}
func UpdateHumanProfileRequestToDomain(req *mgmt_pb.UpdateHumanProfileRequest) *domain.Profile {
preferredLanguage, err := language.Parse(req.PreferredLanguage)
logging.Log("MANAG-GPcYv").OnError(err).Debug("language malformed")
return &domain.Profile{
ObjectRoot: models.ObjectRoot{AggregateID: req.UserId},
FirstName: req.FirstName,
LastName: req.LastName,
NickName: req.NickName,
DisplayName: req.DisplayName,
PreferredLanguage: preferredLanguage,
Gender: user_grpc.GenderToDomain(req.Gender),
}
}
func UpdateHumanEmailRequestToDomain(ctx context.Context, req *mgmt_pb.UpdateHumanEmailRequest) *domain.Email {
return &domain.Email{
ObjectRoot: models.ObjectRoot{
AggregateID: req.UserId,
ResourceOwner: authz.GetCtxData(ctx).OrgID,
},
EmailAddress: req.Email,
IsEmailVerified: req.IsEmailVerified,
}
}
func UpdateHumanPhoneRequestToDomain(req *mgmt_pb.UpdateHumanPhoneRequest) *domain.Phone {
return &domain.Phone{
ObjectRoot: models.ObjectRoot{AggregateID: req.UserId},
PhoneNumber: req.Phone,
IsPhoneVerified: req.IsPhoneVerified,
}
}
func notifyTypeToDomain(state mgmt_pb.SendHumanResetPasswordNotificationRequest_Type) domain.NotificationType {
switch state {
case mgmt_pb.SendHumanResetPasswordNotificationRequest_TYPE_EMAIL:
return domain.NotificationTypeEmail
case mgmt_pb.SendHumanResetPasswordNotificationRequest_TYPE_SMS:
return domain.NotificationTypeSms
default:
return domain.NotificationTypeEmail
}
}
func UpdateMachineRequestToDomain(ctx context.Context, req *mgmt_pb.UpdateMachineRequest) *domain.Machine {
return &domain.Machine{
ObjectRoot: models.ObjectRoot{
AggregateID: req.UserId,
ResourceOwner: authz.GetCtxData(ctx).OrgID,
},
Name: req.Name,
Description: req.Description,
}
}
func ListMachineKeysRequestToModel(req *mgmt_pb.ListMachineKeysRequest) *key_model.AuthNKeySearchRequest {
offset, limit, asc := object.ListQueryToModel(req.Query)
return &key_model.AuthNKeySearchRequest{
Offset: offset,
Limit: limit,
Asc: asc,
Queries: []*key_model.AuthNKeySearchQuery{
{
Key: key_model.AuthNKeyObjectType,
Method: domain.SearchMethodEquals,
Value: key_model.AuthNKeyObjectTypeUser,
}, {
Key: key_model.AuthNKeyObjectID,
Method: domain.SearchMethodEquals,
Value: req.UserId,
},
},
}
}
func AddMachineKeyRequestToDomain(req *mgmt_pb.AddMachineKeyRequest) *domain.MachineKey {
expDate := time.Time{}
if req.ExpirationDate != nil {
var err error
expDate, err = ptypes.Timestamp(req.ExpirationDate)
logging.Log("MANAG-iNshR").OnError(err).Debug("unable to parse expiration date")
}
return &domain.MachineKey{
ObjectRoot: models.ObjectRoot{
AggregateID: req.UserId,
},
ExpirationDate: expDate,
Type: authn.KeyTypeToDomain(req.Type),
}
}
func RemoveHumanLinkedIDPRequestToDomain(ctx context.Context, req *mgmt_pb.RemoveHumanLinkedIDPRequest) *domain.ExternalIDP {
return &domain.ExternalIDP{
ObjectRoot: models.ObjectRoot{
AggregateID: req.UserId,
ResourceOwner: authz.GetCtxData(ctx).OrgID,
},
IDPConfigID: req.IdpId,
ExternalUserID: req.LinkedUserId,
}
}
func ListHumanLinkedIDPsRequestToModel(req *mgmt_pb.ListHumanLinkedIDPsRequest) *user_model.ExternalIDPSearchRequest {
offset, limit, asc := object.ListQueryToModel(req.Query)
return &user_model.ExternalIDPSearchRequest{
Offset: offset,
Limit: limit,
Asc: asc,
Queries: []*user_model.ExternalIDPSearchQuery{{Key: user_model.ExternalIDPSearchKeyUserID, Method: domain.SearchMethodEquals, Value: req.UserId}},
}
}
func ListUserMembershipsRequestToModel(req *mgmt_pb.ListUserMembershipsRequest) (*user_model.UserMembershipSearchRequest, error) {
offset, limit, asc := object.ListQueryToModel(req.Query)
queries, err := user_grpc.MembershipQueriesToModel(req.Queries)
if err != nil {
return nil, err
}
queries = append(queries, &user_model.UserMembershipSearchQuery{
Key: user_model.UserMembershipSearchKeyUserID,
Method: domain.SearchMethodEquals,
Value: req.UserId,
})
return &user_model.UserMembershipSearchRequest{
Offset: offset,
Limit: limit,
Asc: asc,
//SortingColumn: //TODO: sorting
Queries: queries,
}, nil
}
func UserMembershipViewsToDomain(memberships []*user_model.UserMembershipView) []*domain.UserMembership {
result := make([]*domain.UserMembership, len(memberships))
for i, membership := range memberships {
result[i] = &domain.UserMembership{
UserID: membership.UserID,
MemberType: MemberTypeToDomain(membership.MemberType),
AggregateID: membership.AggregateID,
ObjectID: membership.ObjectID,
Roles: membership.Roles,
DisplayName: membership.DisplayName,
CreationDate: membership.CreationDate,
ChangeDate: membership.ChangeDate,
ResourceOwner: membership.ResourceOwner,
ResourceOwnerName: membership.ResourceOwnerName,
Sequence: membership.Sequence,
}
}
return result
}
func MemberTypeToDomain(mType user_model.MemberType) domain.MemberType {
switch mType {
case user_model.MemberTypeIam:
return domain.MemberTypeIam
case user_model.MemberTypeOrganisation:
return domain.MemberTypeOrganisation
case user_model.MemberTypeProject:
return domain.MemberTypeProject
case user_model.MemberTypeProjectGrant:
return domain.MemberTypeProjectGrant
default:
return domain.MemberTypeUnspecified
}
}