feat: add Role (owner|admin) to the user domain, persistence model and mapper
This commit is contained in:
1 parent
162fea4afb
commit
461e93e3b5
30 files changed
+791
-48
No files matched your search
@@ -74,6 +74,10 @@ func getDb(dbName string) *gorm.DB {
|
||||
panic("Failed to migrate database: " + err.Error())
|
||||
}
|
||||
|
||||
if err := persistence.BackfillUserRoles(db); err != nil {
|
||||
panic("Failed to backfill user roles: " + err.Error())
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ type userListItem struct {
|
||||
Kind string `json:"kind"`
|
||||
Username string `json:"username"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Email string `json:"email"`
|
||||
Role string `json:"role"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
@@ -123,7 +125,7 @@ func (h *InviteHandler) ListUsers(w http.ResponseWriter, _ *http.Request) {
|
||||
items = append(items, inviteListItem{entry.ID, entry.Kind, entry.Email, entry.Status, entry.CreatedAt})
|
||||
continue
|
||||
}
|
||||
items = append(items, userListItem{entry.ID, entry.Kind, entry.Username, entry.DisplayName, entry.Status, entry.CreatedAt})
|
||||
items = append(items, userListItem{entry.ID, entry.Kind, entry.Username, entry.DisplayName, entry.Email, entry.Role, entry.Status, entry.CreatedAt})
|
||||
}
|
||||
|
||||
body, err := json.Marshal(items)
|
||||
|
||||
@@ -77,3 +77,21 @@ func RequireVerifiedUser(getUser *useCases.GetUserUseCase) func(http.Handler) ht
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func RequireOwner(getUser *useCases.GetUserUseCase) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser, ok := resolveCurrentUser(getUser, w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if currentUser.Role != user.RoleOwner {
|
||||
http.Error(w, apperr.OwnerRequiredErrorMessage, http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,5 @@ const PendingInviteErrorMessage = "There's already a pending invite for this add
|
||||
const InviteNotSentErrorMessage = "Couldn't send the invite. Try again in a moment."
|
||||
const InviteInvalidErrorMessage = "This invite link doesn't work."
|
||||
const InviteExpiredErrorMessage = "This invite has expired."
|
||||
const OwnerRequiredErrorMessage = "Only the owner can do this."
|
||||
const UsernameTakenErrorMessage = "That username is taken. Try another."
|
||||
@@ -13,6 +13,7 @@ type PublicUser struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Role user.Role `json:"role"`
|
||||
}
|
||||
|
||||
func New(u user.User) PublicUser {
|
||||
@@ -24,5 +25,6 @@ func New(u user.User) PublicUser {
|
||||
CreatedAt: u.CreatedAt,
|
||||
UpdatedAt: u.UpdatedAt,
|
||||
DisplayName: u.DisplayName,
|
||||
Role: u.Role,
|
||||
}
|
||||
}
|
||||
@@ -109,6 +109,7 @@ func NewUserRouter(container *UseCases, rateLimit config.AuthRateLimitSettings,
|
||||
r.Patch("/me", userHandler.UpdateMe)
|
||||
r.Get("/", inviteHandler.ListUsers)
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middleware.RequireOwner(container.GetUserUseCase))
|
||||
r.Use(middleware.TrustedProxyRealIP(trustedProxies))
|
||||
r.Use(middleware.NewRateLimiter(rateLimit.MaxAttempts, rateLimit.Window))
|
||||
r.Post("/invite", inviteHandler.CreateInvite)
|
||||
|
||||
Reference in new issue
Block a user