Skip to content

Commit

Permalink
Update display name
Browse files Browse the repository at this point in the history
  • Loading branch information
boreq committed Jul 11, 2021
1 parent 7422a44 commit 9ec27e2
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 21 deletions.
6 changes: 6 additions & 0 deletions adapters/auth/dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "time"
type persistedUser struct {
UUID string `json:"uuid"`
Username string `json:"username"`
DisplayName string `json:"displayName"`
Password []byte `json:"password"`
Administrator bool `json:"administrator"`
Created time.Time `json:"created"`
Expand All @@ -16,3 +17,8 @@ type persistedSession struct {
Token string `json:"token"`
LastSeen time.Time `json:"lastSeen"`
}

type persistedInvitation struct {
Token string `json:"token"`
Created time.Time `json:"created"`
}
22 changes: 18 additions & 4 deletions adapters/auth/repository_invitations.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package auth
import (
"encoding/json"

"github.com/boreq/errors"
"github.com/boreq/velo/application/auth"
"github.com/boreq/velo/logging"
"github.com/boreq/errors"
bolt "go.etcd.io/bbolt"
)

Expand All @@ -32,7 +32,7 @@ func NewInvitationRepository(tx *bolt.Tx) (*InvitationRepository, error) {
}

func (r *InvitationRepository) Put(invitation auth.Invitation) error {
j, err := json.Marshal(invitation)
j, err := json.Marshal(r.toPersisted(invitation))
if err != nil {
return errors.Wrap(err, "marshaling to json failed")
}
Expand All @@ -54,12 +54,12 @@ func (r *InvitationRepository) Get(token auth.InvitationToken) (*auth.Invitation
return nil, auth.ErrNotFound
}

invitation := &auth.Invitation{}
invitation := &persistedInvitation{}
if err := json.Unmarshal(j, invitation); err != nil {
return nil, errors.Wrap(err, "json unmarshal failed")
}

return invitation, nil
return r.fromPersisted(*invitation), nil
}

func (r *InvitationRepository) Remove(token auth.InvitationToken) error {
Expand All @@ -69,3 +69,17 @@ func (r *InvitationRepository) Remove(token auth.InvitationToken) error {
}
return b.Delete([]byte(token))
}

func (r *InvitationRepository) toPersisted(i auth.Invitation) persistedInvitation {
return persistedInvitation{
Token: string(i.Token),
Created: i.Created,
}
}

func (r *InvitationRepository) fromPersisted(i persistedInvitation) *auth.Invitation {
return &auth.Invitation{
Token: auth.InvitationToken(i.Token),
Created: i.Created,
}
}
2 changes: 2 additions & 0 deletions adapters/auth/repository_users.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ func (r *UserRepository) toPersisted(user auth.User) persistedUser {
return persistedUser{
UUID: user.UUID.String(),
Username: user.Username,
DisplayName: user.DisplayName,
Password: user.Password,
Administrator: user.Administrator,
Created: user.Created,
Expand All @@ -188,6 +189,7 @@ func (r *UserRepository) fromPersisted(user persistedUser) (*auth.User, error) {
return &auth.User{
UUID: uuid,
Username: user.Username,
DisplayName: user.DisplayName,
Password: user.Password,
Administrator: user.Administrator,
Created: user.Created,
Expand Down
25 changes: 14 additions & 11 deletions application/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,24 @@ type InvitationToken string
type PasswordHash []byte

type User struct {
UUID auth.UserUUID `json:"uuid"`
Username string `json:"username"`
Password PasswordHash `json:"password"`
Administrator bool `json:"administrator"`
Created time.Time `json:"created"`
LastSeen time.Time `json:"lastSeen"`
Sessions []Session `json:"sessions"`
UUID auth.UserUUID
Username string
DisplayName string
Password PasswordHash
Administrator bool
Created time.Time
LastSeen time.Time
Sessions []Session
}

type Session struct {
Token AccessToken `json:"token"`
LastSeen time.Time `json:"lastSeen"`
Token AccessToken
LastSeen time.Time
}

type Invitation struct {
Token InvitationToken `json:"invitation"`
Created time.Time `json:"created"`
Token InvitationToken
Created time.Time
}

type TransactionProvider interface {
Expand All @@ -111,6 +112,7 @@ type Auth struct {
Remove *RemoveHandler
SetPassword *SetPasswordHandler
GetUser *GetUserHandler
UpdateProfile *UpdateProfileHandler
}

func toReadUsers(users []User) []auth.ReadUser {
Expand All @@ -125,6 +127,7 @@ func toReadUser(user User) auth.ReadUser {
rv := auth.ReadUser{
UUID: user.UUID,
Username: user.Username,
DisplayName: user.DisplayName,
Administrator: user.Administrator,
Created: user.Created,
LastSeen: user.LastSeen,
Expand Down
1 change: 1 addition & 0 deletions application/auth/handler_register.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func (h *RegisterHandler) Execute(cmd Register) error {
u := User{
UUID: userUUID,
Username: cmd.Username.String(),
DisplayName: cmd.Username.String(),
Password: passwordHash,
Administrator: false,
Created: time.Now(),
Expand Down
1 change: 1 addition & 0 deletions application/auth/handler_register_initial.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func (h *RegisterInitialHandler) Execute(cmd RegisterInitial) error {
u := User{
UUID: userUUID,
Username: cmd.Username.String(),
DisplayName: cmd.Username.String(),
Password: passwordHash,
Administrator: true,
Created: time.Now(),
Expand Down
53 changes: 53 additions & 0 deletions application/auth/handler_update_profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package auth

import (
"github.com/boreq/errors"
"github.com/boreq/velo/domain/auth"
"github.com/boreq/velo/domain/permissions"
)

var ErrUpdatingProfileForbidden = errors.New("this user can not update this profile")

type UpdateProfile struct {
Username string
DisplayName auth.ValidatedDisplayName
AsUser *auth.ReadUser
}

type UpdateProfileHandler struct {
transactionProvider TransactionProvider
}

func NewUpdateProfileHandler(
transactionProvider TransactionProvider,
) *UpdateProfileHandler {
return &UpdateProfileHandler{
transactionProvider: transactionProvider,
}
}

func (h *UpdateProfileHandler) Execute(cmd UpdateProfile) error {
if cmd.DisplayName.IsZero() {
return errors.New("zero value of display name")
}

return h.transactionProvider.Write(func(r *TransactableRepositories) error {
u, err := r.Users.Get(cmd.Username)
if err != nil {
return errors.Wrap(err, "could not get the user")
}

ok, err := permissions.CanUpdateProfile(toReadUser(*u), cmd.AsUser)
if err != nil {
return errors.Wrap(err, "permission check failed")
}

if !ok {
return ErrUpdatingProfileForbidden
}

u.DisplayName = cmd.DisplayName.String()

return r.Users.Put(*u)
})
}
6 changes: 4 additions & 2 deletions application/tracker/tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ type Activity struct {
}

type User struct {
Username string
Username string
DisplayName string
}

type ActivityIterator interface {
Expand Down Expand Up @@ -110,7 +111,8 @@ type TransactableRepositories struct {

func toUser(user *appAuth.User) *User {
return &User{
Username: user.Username,
Username: user.Username,
DisplayName: user.DisplayName,
}
}

Expand Down
40 changes: 40 additions & 0 deletions domain/auth/display_name.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package auth

import (
"errors"
"fmt"
)

const maxDisplayNameLen = 100

type ValidatedDisplayName struct {
displayName string
}

func NewValidatedDisplayName(displayName string) (ValidatedDisplayName, error) {
if displayName == "" {
return ValidatedDisplayName{}, errors.New("display name can't be empty")
}

if len(displayName) > maxDisplayNameLen {
return ValidatedDisplayName{}, fmt.Errorf("display name length can't exceed %d characters", maxDisplayNameLen)
}

return ValidatedDisplayName{displayName}, nil
}

func MustNewValidatedDisplayName(displayName string) ValidatedDisplayName {
v, err := NewValidatedDisplayName(displayName)
if err != nil {
panic(err)
}
return v
}

func (u ValidatedDisplayName) String() string {
return u.displayName
}

func (u ValidatedDisplayName) IsZero() bool {
return u == ValidatedDisplayName{}
}
1 change: 1 addition & 0 deletions domain/auth/read_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
type ReadUser struct {
UUID UserUUID
Username string
DisplayName string
Administrator bool
Created time.Time
LastSeen time.Time
Expand Down
4 changes: 4 additions & 0 deletions domain/permissions/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ func CanListPrivacyZones(userUUID auth.UserUUID, user *auth.ReadUser) bool {
func CanDeletePrivacyZone(privacyZone *domain.PrivacyZone, user *auth.ReadUser) (bool, error) {
return user != nil && privacyZone.UserUUID() == user.UUID, nil
}

func CanUpdateProfile(user auth.ReadUser, as *auth.ReadUser) (bool, error) {
return as != nil && as.UUID == user.UUID, nil
}
Loading

0 comments on commit 9ec27e2

Please sign in to comment.