mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
NOISSUE - Add Auth provider in profile view response (#3187)
Signed-off-by: Arvindh <arvindh91@gmail.com> Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> Co-authored-by: nyagamunene <stevenyaga2014@gmail.com>
This commit is contained in:
+4
-1
@@ -196,7 +196,10 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
errors.Contains(err, errors.ErrUsernameNotAvailable),
|
||||
errors.Contains(err, errors.ErrRouteNotAvailable),
|
||||
errors.Contains(err, errors.ErrChannelRouteNotAvailable),
|
||||
errors.Contains(err, errors.ErrDomainRouteNotAvailable):
|
||||
errors.Contains(err, errors.ErrDomainRouteNotAvailable),
|
||||
errors.Contains(err, svcerr.ErrExternalAuthProviderCouldNotChangePassword),
|
||||
errors.Contains(err, svcerr.ErrExternalAuthProviderCouldNotResetPassword),
|
||||
errors.Contains(err, svcerr.ErrExternalAuthProviderCouldNotUpdate):
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, svcerr.ErrAuthorization),
|
||||
errors.Contains(err, svcerr.ErrDomainAuthorization),
|
||||
|
||||
@@ -102,4 +102,13 @@ var (
|
||||
|
||||
// ErrUserVerificationExpired indicates user verification is expired.
|
||||
ErrUserVerificationExpired = errors.New("verification expired, please generate new verification")
|
||||
|
||||
// ErrExternalAuthProviderCouldNotUpdate indicates that users authenticated via external provider cannot update their account details directly.
|
||||
ErrExternalAuthProviderCouldNotUpdate = errors.New("account details can only be updated through your authentication provider's settings")
|
||||
|
||||
// ErrExternalAuthProviderCouldNotResetPassword indicates that password cannot be reset for users authenticated via external provider.
|
||||
ErrExternalAuthProviderCouldNotResetPassword = errors.New("password cannot be reset for users authenticated via external provider")
|
||||
|
||||
// ErrExternalAuthProviderCouldNotChangePassword indicates that password cannot be reset for users authenticated via external provider.
|
||||
ErrExternalAuthProviderCouldNotChangePassword = errors.New("password cannot be reset for users authenticated via external provider")
|
||||
)
|
||||
|
||||
@@ -575,6 +575,10 @@ func oauth2CallbackHandler(oauth oauth2.Provider, svc users.Service, tokenClient
|
||||
return
|
||||
}
|
||||
|
||||
user.AuthProvider = oauth.Name()
|
||||
if user.AuthProvider == "" {
|
||||
user.AuthProvider = "oauth"
|
||||
}
|
||||
user, err = svc.OAuthCallback(r.Context(), user)
|
||||
if err != nil {
|
||||
http.Redirect(w, r, oauth.ErrorURL()+"?error="+err.Error(), http.StatusSeeOther)
|
||||
|
||||
@@ -127,6 +127,15 @@ func Migration() *migrate.MemoryMigrationSource {
|
||||
`ALTER TABLE users RENAME CONSTRAINT clients_email_key TO clients_identity_key;`,
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: "clients_09",
|
||||
Up: []string{
|
||||
`ALTER TABLE users ADD COLUMN auth_provider VARCHAR(254);`,
|
||||
},
|
||||
Down: []string{
|
||||
`ALTER TABLE users DROP COLUMN auth_provider`,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+19
-6
@@ -34,9 +34,9 @@ func NewRepository(db postgres.Database) users.Repository {
|
||||
}
|
||||
|
||||
func (repo *userRepo) Save(ctx context.Context, c users.User) (users.User, error) {
|
||||
q := `INSERT INTO users (id, tags, email, secret, metadata, created_at, status, role, first_name, last_name, username, profile_picture)
|
||||
VALUES (:id, :tags, :email, :secret, :metadata, :created_at, :status, :role, :first_name, :last_name, :username, :profile_picture)
|
||||
RETURNING id, tags, email, metadata, created_at, status, role, first_name, last_name, username, profile_picture, verified_at`
|
||||
q := `INSERT INTO users (id, tags, email, secret, metadata, created_at, status, role, first_name, last_name, username, profile_picture, auth_provider)
|
||||
VALUES (:id, :tags, :email, :secret, :metadata, :created_at, :status, :role, :first_name, :last_name, :username, :profile_picture, :auth_provider)
|
||||
RETURNING id, tags, email, metadata, created_at, status, role, first_name, last_name, username, profile_picture, verified_at, auth_provider`
|
||||
|
||||
dbu, err := toDBUser(c)
|
||||
if err != nil {
|
||||
@@ -96,7 +96,7 @@ func (repo *userRepo) CheckSuperAdmin(ctx context.Context, adminID string) error
|
||||
}
|
||||
|
||||
func (repo *userRepo) RetrieveByID(ctx context.Context, id string) (users.User, error) {
|
||||
q := `SELECT id, tags, email, secret, metadata, created_at, updated_at, updated_by, status, role, first_name, last_name, username, profile_picture, verified_at
|
||||
q := `SELECT id, tags, email, secret, metadata, created_at, updated_at, updated_by, status, role, first_name, last_name, username, profile_picture, verified_at, auth_provider
|
||||
FROM users WHERE id = :id`
|
||||
|
||||
dbu := DBUser{
|
||||
@@ -431,7 +431,7 @@ func (repo *userRepo) RetrieveAllByIDs(ctx context.Context, pm users.Page) (user
|
||||
}
|
||||
|
||||
func (repo *userRepo) RetrieveByEmail(ctx context.Context, email string) (users.User, error) {
|
||||
q := `SELECT id, tags, email, secret, metadata, created_at, updated_at, updated_by, status, role, first_name, last_name, username, verified_at
|
||||
q := `SELECT id, tags, email, secret, metadata, created_at, updated_at, updated_by, status, role, first_name, last_name, username, verified_at, auth_provider
|
||||
FROM users WHERE email = :email AND status = :status`
|
||||
|
||||
dbu := DBUser{
|
||||
@@ -458,7 +458,7 @@ func (repo *userRepo) RetrieveByEmail(ctx context.Context, email string) (users.
|
||||
}
|
||||
|
||||
func (repo *userRepo) RetrieveByUsername(ctx context.Context, username string) (users.User, error) {
|
||||
q := `SELECT id, tags, email, secret, metadata, created_at, updated_at, updated_by, status, role, first_name, last_name, username, verified_at
|
||||
q := `SELECT id, tags, email, secret, metadata, created_at, updated_at, updated_by, status, role, first_name, last_name, username, verified_at, auth_provider
|
||||
FROM users WHERE username = :username AND status = :status`
|
||||
|
||||
dbu := DBUser{
|
||||
@@ -502,6 +502,7 @@ type DBUser struct {
|
||||
ProfilePicture sql.NullString `db:"profile_picture, omitempty"`
|
||||
Email string `db:"email,omitempty"`
|
||||
VerifiedAt sql.NullTime `db:"verified_at,omitempty"`
|
||||
AuthProvider sql.NullString `db:"auth_provider,omitempty"`
|
||||
}
|
||||
|
||||
func toDBUser(u users.User) (DBUser, error) {
|
||||
@@ -530,6 +531,11 @@ func toDBUser(u users.User) (DBUser, error) {
|
||||
verifiedAt = sql.NullTime{Time: u.VerifiedAt, Valid: true}
|
||||
}
|
||||
|
||||
var authProvider sql.NullString
|
||||
if u.AuthProvider != "" {
|
||||
authProvider = sql.NullString{String: u.AuthProvider, Valid: true}
|
||||
}
|
||||
|
||||
return DBUser{
|
||||
ID: u.ID,
|
||||
Tags: tags,
|
||||
@@ -546,6 +552,7 @@ func toDBUser(u users.User) (DBUser, error) {
|
||||
ProfilePicture: stringToNullString(u.ProfilePicture),
|
||||
Email: u.Email,
|
||||
VerifiedAt: verifiedAt,
|
||||
AuthProvider: authProvider,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -573,6 +580,11 @@ func ToUser(dbu DBUser) (users.User, error) {
|
||||
verifiedAt = dbu.VerifiedAt.Time.UTC()
|
||||
}
|
||||
|
||||
var authProvider string
|
||||
if dbu.AuthProvider.Valid {
|
||||
authProvider = dbu.AuthProvider.String
|
||||
}
|
||||
|
||||
user := users.User{
|
||||
ID: dbu.ID,
|
||||
FirstName: nullStringString(dbu.FirstName),
|
||||
@@ -590,6 +602,7 @@ func ToUser(dbu DBUser) (users.User, error) {
|
||||
Tags: tags,
|
||||
ProfilePicture: nullStringString(dbu.ProfilePicture),
|
||||
VerifiedAt: verifiedAt,
|
||||
AuthProvider: authProvider,
|
||||
}
|
||||
if dbu.Role != nil {
|
||||
user.Role = *dbu.Role
|
||||
|
||||
@@ -45,6 +45,17 @@ func TestUsersSave(t *testing.T) {
|
||||
|
||||
email := first_name + "@example.com"
|
||||
|
||||
externalUser := users.User{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
FirstName: namesgen.Generate(),
|
||||
LastName: namesgen.Generate(),
|
||||
Metadata: users.Metadata{},
|
||||
Credentials: users.Credentials{
|
||||
Username: namesgen.Generate(),
|
||||
},
|
||||
Email: namesgen.Generate() + "@example.com",
|
||||
AuthProvider: "external",
|
||||
}
|
||||
cases := []struct {
|
||||
desc string
|
||||
user users.User
|
||||
@@ -66,6 +77,12 @@ func TestUsersSave(t *testing.T) {
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "add new external user successfully",
|
||||
user: externalUser,
|
||||
err: nil,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "add user with duplicate user email",
|
||||
user: users.User{
|
||||
@@ -272,14 +289,38 @@ func TestRetrieveByID(t *testing.T) {
|
||||
_, err := repo.Save(context.Background(), user)
|
||||
require.Nil(t, err, fmt.Sprintf("failed to save users %s", user.ID))
|
||||
|
||||
externalUser := users.User{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
FirstName: namesgen.Generate(),
|
||||
LastName: namesgen.Generate(),
|
||||
Metadata: users.Metadata{},
|
||||
Credentials: users.Credentials{
|
||||
Username: namesgen.Generate(),
|
||||
},
|
||||
Email: namesgen.Generate() + "@example.com",
|
||||
AuthProvider: "external",
|
||||
}
|
||||
|
||||
_, err = repo.Save(context.Background(), externalUser)
|
||||
require.Nil(t, err, fmt.Sprintf("failed to save users %s", user.ID))
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
userID string
|
||||
user users.User
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "retrieve existing user",
|
||||
userID: user.ID,
|
||||
user: user,
|
||||
err: nil,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "retrieve existing oauth user",
|
||||
userID: externalUser.ID,
|
||||
user: externalUser,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
@@ -295,8 +336,11 @@ func TestRetrieveByID(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
_, err := repo.RetrieveByID(context.Background(), tc.userID)
|
||||
rUser, err := repo.RetrieveByID(context.Background(), tc.userID)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.err, err))
|
||||
if err == nil {
|
||||
assert.Equal(t, tc.user, rUser, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.user, rUser))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,6 +294,15 @@ func (svc service) Update(ctx context.Context, session authn.Session, id string,
|
||||
return User{}, err
|
||||
}
|
||||
}
|
||||
u, err := svc.users.RetrieveByID(ctx, id)
|
||||
if err != nil {
|
||||
return User{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
}
|
||||
if u.AuthProvider != "" {
|
||||
if usr.FirstName != nil || usr.LastName != nil || usr.ProfilePicture != nil {
|
||||
return User{}, svcerr.ErrExternalAuthProviderCouldNotUpdate
|
||||
}
|
||||
}
|
||||
updatedAt := time.Now().UTC()
|
||||
usr.UpdatedAt = &updatedAt
|
||||
usr.UpdatedBy = &session.UserID
|
||||
@@ -331,6 +340,14 @@ func (svc service) UpdateProfilePicture(ctx context.Context, session authn.Sessi
|
||||
}
|
||||
}
|
||||
|
||||
u, err := svc.users.RetrieveByID(ctx, id)
|
||||
if err != nil {
|
||||
return User{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
}
|
||||
if u.AuthProvider != "" {
|
||||
return User{}, svcerr.ErrExternalAuthProviderCouldNotUpdate
|
||||
}
|
||||
|
||||
updatedAt := time.Now().UTC()
|
||||
usr.UpdatedAt = &updatedAt
|
||||
usr.UpdatedBy = &session.UserID
|
||||
@@ -353,6 +370,9 @@ func (svc service) UpdateEmail(ctx context.Context, session authn.Session, userI
|
||||
if err != nil {
|
||||
return User{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
}
|
||||
if oldUsr.AuthProvider != "" {
|
||||
return User{}, svcerr.ErrExternalAuthProviderCouldNotUpdate
|
||||
}
|
||||
if oldUsr.Email == email {
|
||||
return User{}, fmt.Errorf("current email is same as update requested email")
|
||||
}
|
||||
@@ -377,6 +397,9 @@ func (svc service) SendPasswordReset(ctx context.Context, email string) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
}
|
||||
if user.AuthProvider != "" {
|
||||
return svcerr.ErrExternalAuthProviderCouldNotResetPassword
|
||||
}
|
||||
issueReq := &grpcTokenV1.IssueReq{
|
||||
UserId: user.ID,
|
||||
UserRole: uint32(user.Role + 1),
|
||||
@@ -395,6 +418,9 @@ func (svc service) ResetSecret(ctx context.Context, session authn.Session, secre
|
||||
if err != nil {
|
||||
return errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
}
|
||||
if u.AuthProvider != "" {
|
||||
return svcerr.ErrExternalAuthProviderCouldNotResetPassword
|
||||
}
|
||||
|
||||
secret, err = svc.hasher.Hash(secret)
|
||||
if err != nil {
|
||||
@@ -420,6 +446,9 @@ func (svc service) UpdateSecret(ctx context.Context, session authn.Session, oldS
|
||||
if err != nil {
|
||||
return User{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
}
|
||||
if dbUser.AuthProvider != "" {
|
||||
return User{}, svcerr.ErrExternalAuthProviderCouldNotChangePassword
|
||||
}
|
||||
if _, err := svc.IssueToken(ctx, dbUser.Credentials.Username, oldSecret); err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
|
||||
+131
-35
@@ -519,6 +519,8 @@ func TestUpdateUser(t *testing.T) {
|
||||
userReq users.UserReq
|
||||
session authn.Session
|
||||
updateResponse users.User
|
||||
retrieveByIDResp users.User
|
||||
retrieveByIDErr error
|
||||
token string
|
||||
updateErr error
|
||||
checkSuperAdminErr error
|
||||
@@ -530,10 +532,11 @@ func TestUpdateUser(t *testing.T) {
|
||||
userReq: users.UserReq{
|
||||
FirstName: &updateFirstName,
|
||||
},
|
||||
session: authn.Session{UserID: user1.ID},
|
||||
updateResponse: user1,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
session: authn.Session{UserID: user1.ID},
|
||||
updateResponse: user1,
|
||||
retrieveByIDResp: user1,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "update metadata successfully as normal user",
|
||||
@@ -541,10 +544,11 @@ func TestUpdateUser(t *testing.T) {
|
||||
userReq: users.UserReq{
|
||||
Metadata: &updatedMetadata,
|
||||
},
|
||||
session: authn.Session{UserID: user2.ID},
|
||||
updateResponse: user2,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
session: authn.Session{UserID: user2.ID},
|
||||
updateResponse: user2,
|
||||
retrieveByIDResp: user2,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "update user name as normal user with repo error on update",
|
||||
@@ -552,11 +556,12 @@ func TestUpdateUser(t *testing.T) {
|
||||
userReq: users.UserReq{
|
||||
FirstName: &updateFirstName,
|
||||
},
|
||||
session: authn.Session{UserID: user1.ID},
|
||||
updateResponse: users.User{},
|
||||
token: validToken,
|
||||
updateErr: errors.ErrMalformedEntity,
|
||||
err: svcerr.ErrUpdateEntity,
|
||||
session: authn.Session{UserID: user1.ID},
|
||||
updateResponse: users.User{},
|
||||
retrieveByIDResp: user1,
|
||||
token: validToken,
|
||||
updateErr: errors.ErrMalformedEntity,
|
||||
err: svcerr.ErrUpdateEntity,
|
||||
},
|
||||
{
|
||||
desc: "update user name as admin successfully",
|
||||
@@ -564,10 +569,11 @@ func TestUpdateUser(t *testing.T) {
|
||||
userReq: users.UserReq{
|
||||
FirstName: &updateFirstName,
|
||||
},
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
updateResponse: user1,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
updateResponse: user1,
|
||||
retrieveByIDResp: user1,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "update user metadata as admin successfully",
|
||||
@@ -575,10 +581,11 @@ func TestUpdateUser(t *testing.T) {
|
||||
userReq: users.UserReq{
|
||||
Metadata: &updatedMetadata,
|
||||
},
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
updateResponse: user2,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
updateResponse: user2,
|
||||
retrieveByIDResp: user2,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "update user with failed check on super admin",
|
||||
@@ -597,26 +604,88 @@ func TestUpdateUser(t *testing.T) {
|
||||
userReq: users.UserReq{
|
||||
FirstName: &updateFirstName,
|
||||
},
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
updateResponse: users.User{},
|
||||
token: validToken,
|
||||
updateErr: errors.ErrMalformedEntity,
|
||||
err: svcerr.ErrUpdateEntity,
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
updateResponse: users.User{},
|
||||
retrieveByIDResp: user1,
|
||||
token: validToken,
|
||||
updateErr: errors.ErrMalformedEntity,
|
||||
err: svcerr.ErrUpdateEntity,
|
||||
},
|
||||
{
|
||||
desc: "update user first name with external auth provider should fail",
|
||||
userID: user1.ID,
|
||||
userReq: users.UserReq{
|
||||
FirstName: &updateFirstName,
|
||||
},
|
||||
session: authn.Session{UserID: user1.ID},
|
||||
retrieveByIDResp: users.User{
|
||||
ID: user1.ID,
|
||||
AuthProvider: "google",
|
||||
},
|
||||
token: validToken,
|
||||
err: svcerr.ErrExternalAuthProviderCouldNotUpdate,
|
||||
},
|
||||
{
|
||||
desc: "update user last name with external auth provider should fail",
|
||||
userID: user1.ID,
|
||||
userReq: users.UserReq{
|
||||
LastName: &updateFirstName,
|
||||
},
|
||||
session: authn.Session{UserID: user1.ID},
|
||||
retrieveByIDResp: users.User{
|
||||
ID: user1.ID,
|
||||
AuthProvider: "google",
|
||||
},
|
||||
token: validToken,
|
||||
err: svcerr.ErrExternalAuthProviderCouldNotUpdate,
|
||||
},
|
||||
{
|
||||
desc: "update user metadata with external auth provider should succeed",
|
||||
userID: user2.ID,
|
||||
userReq: users.UserReq{
|
||||
Metadata: &updatedMetadata,
|
||||
},
|
||||
session: authn.Session{UserID: user2.ID},
|
||||
retrieveByIDResp: users.User{
|
||||
ID: user2.ID,
|
||||
AuthProvider: "google",
|
||||
Metadata: updatedMetadata,
|
||||
},
|
||||
updateResponse: users.User{
|
||||
ID: user2.ID,
|
||||
AuthProvider: "google",
|
||||
Metadata: updatedMetadata,
|
||||
},
|
||||
token: validToken,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "update user with retrieve by id error",
|
||||
userID: user1.ID,
|
||||
userReq: users.UserReq{
|
||||
FirstName: &updateFirstName,
|
||||
},
|
||||
session: authn.Session{UserID: user1.ID},
|
||||
retrieveByIDErr: repoerr.ErrNotFound,
|
||||
token: validToken,
|
||||
err: svcerr.ErrUpdateEntity,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
repoCall := cRepo.On("CheckSuperAdmin", context.Background(), mock.Anything).Return(tc.checkSuperAdminErr)
|
||||
repoCall1 := cRepo.On("Update", context.Background(), tc.userID, mock.Anything).Return(tc.updateResponse, tc.err)
|
||||
repoCall1 := cRepo.On("RetrieveByID", context.Background(), tc.userID).Return(tc.retrieveByIDResp, tc.retrieveByIDErr)
|
||||
repoCall2 := cRepo.On("Update", context.Background(), tc.userID, mock.Anything).Return(tc.updateResponse, tc.updateErr)
|
||||
updatedUser, err := svc.Update(context.Background(), tc.session, tc.userID, tc.userReq)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
assert.Equal(t, tc.updateResponse, updatedUser, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.updateResponse, updatedUser))
|
||||
if tc.err == nil {
|
||||
ok := repoCall1.Parent.AssertCalled(t, "Update", context.Background(), tc.userID, mock.Anything)
|
||||
ok := repoCall2.Parent.AssertCalled(t, "Update", context.Background(), tc.userID, mock.Anything)
|
||||
assert.True(t, ok, fmt.Sprintf("Update was not called on %s", tc.desc))
|
||||
}
|
||||
repoCall.Unset()
|
||||
repoCall1.Unset()
|
||||
repoCall2.Unset()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1010,6 +1079,8 @@ func TestUpdateProfilePicture(t *testing.T) {
|
||||
userReq users.UserReq
|
||||
session authn.Session
|
||||
updateProfilePicResponse users.User
|
||||
retrieveByIDResp users.User
|
||||
retrieveByIDErr error
|
||||
updateProfilePicErr error
|
||||
checkSuperAdminErr error
|
||||
err error
|
||||
@@ -1020,6 +1091,7 @@ func TestUpdateProfilePicture(t *testing.T) {
|
||||
userReq: users.UserReq{ProfilePicture: &updatedPicture},
|
||||
session: authn.Session{UserID: user.ID},
|
||||
updateProfilePicResponse: user,
|
||||
retrieveByIDResp: user,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
@@ -1028,15 +1100,17 @@ func TestUpdateProfilePicture(t *testing.T) {
|
||||
userReq: users.UserReq{ProfilePicture: &updatedPicture},
|
||||
session: authn.Session{UserID: user.ID},
|
||||
updateProfilePicResponse: users.User{},
|
||||
retrieveByIDResp: user,
|
||||
updateProfilePicErr: errors.ErrMalformedEntity,
|
||||
err: svcerr.ErrUpdateEntity,
|
||||
},
|
||||
{
|
||||
desc: "update profile picture as admin successfully",
|
||||
userID: user.ID,
|
||||
userReq: users.UserReq{ProfilePicture: &updatedPicture},
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
err: nil,
|
||||
desc: "update profile picture as admin successfully",
|
||||
userID: user.ID,
|
||||
userReq: users.UserReq{ProfilePicture: &updatedPicture},
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
retrieveByIDResp: user,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "update profile picture as admin with failed check on super admin",
|
||||
@@ -1052,23 +1126,45 @@ func TestUpdateProfilePicture(t *testing.T) {
|
||||
userReq: users.UserReq{ProfilePicture: &updatedPicture},
|
||||
session: authn.Session{UserID: adminID, SuperAdmin: true},
|
||||
updateProfilePicResponse: users.User{},
|
||||
retrieveByIDResp: user,
|
||||
updateProfilePicErr: errors.ErrMalformedEntity,
|
||||
err: svcerr.ErrUpdateEntity,
|
||||
},
|
||||
{
|
||||
desc: "update profile picture with external auth provider",
|
||||
userID: user.ID,
|
||||
userReq: users.UserReq{ProfilePicture: &updatedPicture},
|
||||
session: authn.Session{UserID: user.ID},
|
||||
retrieveByIDResp: users.User{
|
||||
ID: user.ID,
|
||||
AuthProvider: "google",
|
||||
},
|
||||
err: svcerr.ErrExternalAuthProviderCouldNotUpdate,
|
||||
},
|
||||
{
|
||||
desc: "update profile picture with retrieve by id error",
|
||||
userID: user.ID,
|
||||
userReq: users.UserReq{ProfilePicture: &updatedPicture},
|
||||
session: authn.Session{UserID: user.ID},
|
||||
retrieveByIDErr: repoerr.ErrNotFound,
|
||||
err: svcerr.ErrUpdateEntity,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
repoCall := cRepo.On("CheckSuperAdmin", context.Background(), mock.Anything).Return(tc.checkSuperAdminErr)
|
||||
repoCall1 := cRepo.On("Update", context.Background(), tc.userID, mock.Anything).Return(tc.updateProfilePicResponse, tc.updateProfilePicErr)
|
||||
repoCall1 := cRepo.On("RetrieveByID", context.Background(), tc.userID).Return(tc.retrieveByIDResp, tc.retrieveByIDErr)
|
||||
repoCall2 := cRepo.On("Update", context.Background(), tc.userID, mock.Anything).Return(tc.updateProfilePicResponse, tc.updateProfilePicErr)
|
||||
updatedUser, err := svc.UpdateProfilePicture(context.Background(), tc.session, tc.userID, tc.userReq)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
assert.Equal(t, tc.updateProfilePicResponse, updatedUser, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.updateProfilePicResponse, updatedUser))
|
||||
if tc.err == nil {
|
||||
ok := repoCall1.Parent.AssertCalled(t, "Update", context.Background(), tc.userID, mock.Anything)
|
||||
ok := repoCall2.Parent.AssertCalled(t, "Update", context.Background(), tc.userID, mock.Anything)
|
||||
assert.True(t, ok, fmt.Sprintf("Update was not called on %s", tc.desc))
|
||||
}
|
||||
repoCall.Unset()
|
||||
repoCall1.Unset()
|
||||
repoCall2.Unset()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ type User struct {
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
VerifiedAt time.Time `json:"verified_at,omitempty"`
|
||||
AuthProvider string `json:"auth_provider,omitempty"`
|
||||
}
|
||||
|
||||
type Credentials struct {
|
||||
|
||||
Reference in New Issue
Block a user