Skip to content

Commit

Permalink
radio: simplify UserPermissions logic
Browse files Browse the repository at this point in the history
website/admin: give profile page a concrete list of permissions to render,
this way a lot of the logic is removed from the template and instead moved
into Go land.
  • Loading branch information
Wessie committed Apr 26, 2024
1 parent 86ece24 commit 31cf3b8
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 15 deletions.
31 changes: 20 additions & 11 deletions radio.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,33 @@ type UserPermissions map[UserPermission]struct{}
// Has returns true if the permissions in UserPermission allow
// access to the permission given
func (up UserPermissions) Has(perm UserPermission) bool {
if up == nil { // nil map, has no permissions ever
return false
}
_, ok := up[PermActive]
if !ok { // not an active user, no permissions ever
if !up.has(PermActive) { // not an active user
return false
}

_, ok = up[perm]
if !ok { // don't have this perm but might be dev who has access to everything
_, ok = up[PermDev]
return ok
}
return ok
return up.has(perm) || up.has(PermDev)
}

// HasExplicit returns true if the permission given is explicitly in the UserPermissions
func (up UserPermissions) HasExplicit(perm UserPermission) bool {
return up.has(perm)
}

// HasEdit returns true if the UserPermissions is allowed to edit the given permission
func (up UserPermissions) HasEdit(perm UserPermission) bool {
// devs can edit any permission
if up.has(PermDev) {
return true
}
// admins can edit every permission except for PermDev
if up.has(PermAdmin) && perm != PermDev {
return true
}
// no one else can edit permissions
return false
}

func (up UserPermissions) has(perm UserPermission) bool {
if up == nil {
return false
}
Expand Down
36 changes: 32 additions & 4 deletions website/admin/profiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,18 @@ func newProfileDJ(name string) radio.DJ {
}
}

type ProfilePermissionEntry struct {
Perm radio.UserPermission
Checked bool
Disabled bool
}

// ProfileForm defines the form we use for the profile page
type ProfileForm struct {
radio.User

// PermissionList is the list of permissions we should render
PermissionList []ProfilePermissionEntry
// IsAdmin indicates if we're setting up the admin-only form
IsAdmin bool
// IsSelf indicates if we're setting up a form for ourselves, can only
Expand Down Expand Up @@ -194,6 +202,9 @@ func (s *State) postProfile(w http.ResponseWriter, r *http.Request) (*ProfileFor
ctx := r.Context()
// current user of this session
currentUser := middleware.UserFromContext(ctx)
if currentUser == nil {
panic("admin request with no user")
}
// the user we're editing
toEdit := currentUser

Expand Down Expand Up @@ -274,6 +285,7 @@ func (s *State) postProfile(w http.ResponseWriter, r *http.Request) (*ProfileFor
// apply any permission change, only admins can change this (for now)
if currentUser.UserPermissions.Has(radio.PermAdmin) {
form.User.UserPermissions = form.newPermissions
form.PermissionList = generatePermissionList(*currentUser, form.User)
}

// update the user in the database
Expand Down Expand Up @@ -488,18 +500,34 @@ func NewProfileForm(user radio.User, r *http.Request) (*ProfileForm, error) {

func newProfileForm(user radio.User, r *http.Request) ProfileForm {
requestUser := middleware.UserFromContext(r.Context())
if requestUser == nil {
panic("admin request with no user")
}

return ProfileForm{
User: user,
IsAdmin: requestUser.UserPermissions.Has(radio.PermAdmin),
IsSelf: requestUser.Username == user.Username,
CurrentIP: template.JS(r.RemoteAddr),
User: user,
PermissionList: generatePermissionList(*requestUser, user),
IsAdmin: requestUser.UserPermissions.Has(radio.PermAdmin),
IsSelf: requestUser.Username == user.Username,
CurrentIP: template.JS(r.RemoteAddr),
PasswordChangeForm: ProfilePasswordChangeForm{
For: user,
},
}
}

func generatePermissionList(by, other radio.User) []ProfilePermissionEntry {
var entries []ProfilePermissionEntry
for _, perm := range radio.AllUserPermissions() {
entries = append(entries, ProfilePermissionEntry{
Perm: perm,
Checked: other.UserPermissions.HasExplicit(perm),
Disabled: !by.UserPermissions.HasEdit(perm),
})
}
return entries
}

func (pf *ProfileForm) Update(form url.Values) {
if form.Has("username") {
pf.Username = form.Get("username")
Expand Down

0 comments on commit 31cf3b8

Please sign in to comment.