implement avatar backend functionality
This commit is contained in:
@@ -7,6 +7,7 @@ type Human struct {
|
||||
Email string
|
||||
EmailPrefix string
|
||||
EmailNotificationsEnabled bool
|
||||
AvatarObjectID *string
|
||||
LastEmailNotificationSentAt *time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ type repository interface {
|
||||
listAll(ctx context.Context) ([]*Human, error)
|
||||
updateEmailNotificationsEnabled(ctx context.Context, id string, enabled bool) error
|
||||
updateLastEmailNotificationSentAt(ctx context.Context, id string, t time.Time) error
|
||||
updateAvatarObjectID(ctx context.Context, id string, objectID *string) error
|
||||
}
|
||||
|
||||
type repositoryImpl struct {
|
||||
@@ -50,9 +51,9 @@ func newRepository(pool *pgxpool.Pool) repository {
|
||||
func (r *repositoryImpl) getByEmail(ctx context.Context, email string) (*Human, error) {
|
||||
var h Human
|
||||
err := r.pool.QueryRow(ctx,
|
||||
`SELECT id, email, email_notifications_enabled, last_email_notification_sent_at, created_at FROM humans WHERE email = $1`,
|
||||
`SELECT id, email, email_notifications_enabled, last_email_notification_sent_at, created_at, avatar_object_id FROM humans WHERE email = $1`,
|
||||
email,
|
||||
).Scan(&h.ID, &h.Email, &h.EmailNotificationsEnabled, &h.LastEmailNotificationSentAt, &h.CreatedAt)
|
||||
).Scan(&h.ID, &h.Email, &h.EmailNotificationsEnabled, &h.LastEmailNotificationSentAt, &h.CreatedAt, &h.AvatarObjectID)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, errNotFound
|
||||
@@ -66,9 +67,9 @@ func (r *repositoryImpl) getByEmail(ctx context.Context, email string) (*Human,
|
||||
func (r *repositoryImpl) getByID(ctx context.Context, id string) (*Human, error) {
|
||||
var h Human
|
||||
err := r.pool.QueryRow(ctx,
|
||||
`SELECT id, email, email_notifications_enabled, last_email_notification_sent_at, created_at FROM humans WHERE id = $1`,
|
||||
`SELECT id, email, email_notifications_enabled, last_email_notification_sent_at, created_at, avatar_object_id FROM humans WHERE id = $1`,
|
||||
id,
|
||||
).Scan(&h.ID, &h.Email, &h.EmailNotificationsEnabled, &h.LastEmailNotificationSentAt, &h.CreatedAt)
|
||||
).Scan(&h.ID, &h.Email, &h.EmailNotificationsEnabled, &h.LastEmailNotificationSentAt, &h.CreatedAt, &h.AvatarObjectID)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, errNotFound
|
||||
@@ -113,7 +114,7 @@ func (r *repositoryImpl) exists(ctx context.Context, email string) (bool, error)
|
||||
|
||||
func (r *repositoryImpl) listAll(ctx context.Context) ([]*Human, error) {
|
||||
rows, err := r.pool.Query(ctx,
|
||||
`SELECT id, email, email_notifications_enabled, last_email_notification_sent_at, created_at FROM humans`,
|
||||
`SELECT id, email, email_notifications_enabled, last_email_notification_sent_at, created_at, avatar_object_id FROM humans`,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -123,7 +124,7 @@ func (r *repositoryImpl) listAll(ctx context.Context) ([]*Human, error) {
|
||||
var humans []*Human
|
||||
for rows.Next() {
|
||||
var h Human
|
||||
if err := rows.Scan(&h.ID, &h.Email, &h.EmailNotificationsEnabled, &h.LastEmailNotificationSentAt, &h.CreatedAt); err != nil {
|
||||
if err := rows.Scan(&h.ID, &h.Email, &h.EmailNotificationsEnabled, &h.LastEmailNotificationSentAt, &h.CreatedAt, &h.AvatarObjectID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.EmailPrefix = emailPrefix(h.Email)
|
||||
@@ -159,3 +160,17 @@ func (r *repositoryImpl) updateLastEmailNotificationSentAt(ctx context.Context,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *repositoryImpl) updateAvatarObjectID(ctx context.Context, id string, objectID *string) error {
|
||||
result, err := r.pool.Exec(ctx,
|
||||
`UPDATE humans SET avatar_object_id = $2 WHERE id = $1`,
|
||||
id, objectID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if result.RowsAffected() == 0 {
|
||||
return errNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,7 +11,10 @@ import (
|
||||
|
||||
//go:generate go tool mockgen -source ./service.go -destination ./mocks/service.go
|
||||
|
||||
var ErrNotFound = errors.New("human not found")
|
||||
var (
|
||||
ErrNotFound = errors.New("human not found")
|
||||
ErrInvalidParam = errors.New("invalid param")
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
GetOrCreateByEmail(ctx context.Context, email string) (*Human, error)
|
||||
@@ -22,6 +25,8 @@ type Service interface {
|
||||
ListAll(ctx context.Context) ([]*Human, error)
|
||||
UpdateEmailNotificationsEnabled(ctx context.Context, id string, enabled bool) error
|
||||
UpdateLastEmailNotificationSentAt(ctx context.Context, id string, t time.Time) error
|
||||
UpdateAvatar(ctx context.Context, id string, objectID string) error
|
||||
DeleteAvatar(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
type serviceImpl struct {
|
||||
@@ -88,3 +93,22 @@ func (s *serviceImpl) UpdateLastEmailNotificationSentAt(ctx context.Context, id
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *serviceImpl) UpdateAvatar(ctx context.Context, id string, objectID string) error {
|
||||
if objectID == "" {
|
||||
return ErrInvalidParam
|
||||
}
|
||||
err := s.repo.updateAvatarObjectID(ctx, id, utils.CreateOptionalString(objectID))
|
||||
if errors.Is(err, errNotFound) {
|
||||
return ErrNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *serviceImpl) DeleteAvatar(ctx context.Context, id string) error {
|
||||
err := s.repo.updateAvatarObjectID(ctx, id, nil)
|
||||
if errors.Is(err, errNotFound) {
|
||||
return ErrNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -56,4 +56,19 @@ func TestHumanService(t *testing.T) {
|
||||
assert.NotEqual(t, createdHuman.ID, anotherHuman.ID)
|
||||
assert.Equal(t, "[email protected]", anotherHuman.Email)
|
||||
assert.Equal(t, "another", anotherHuman.EmailPrefix)
|
||||
|
||||
// Test avatar handling
|
||||
objectID := "obj_xxx"
|
||||
err = svc.UpdateAvatar(ctx, anotherHuman.ID, objectID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
anotherHuman, err = svc.GetByID(ctx, anotherHuman.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, objectID, *anotherHuman.AvatarObjectID)
|
||||
|
||||
err = svc.DeleteAvatar(ctx, anotherHuman.ID)
|
||||
assert.NoError(t, err)
|
||||
anotherHuman, err = svc.GetByID(ctx, anotherHuman.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, anotherHuman.AvatarObjectID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user