Skip to content

Commit

Permalink
website: require permissions for routes
Browse files Browse the repository at this point in the history
radio: made UserPermissions.Has check for a nil map

website: added RequestID middleware
  • Loading branch information
Wessie committed Jan 31, 2024
1 parent 143987e commit 72b7ad1
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 7 deletions.
4 changes: 4 additions & 0 deletions radio.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,12 @@ type UserPermissions map[UserPermission]bool

// Has returns true if the permission given is in the UserPermissions
func (up UserPermissions) Has(perm UserPermission) bool {
if up == nil {
return false
}
_, ok := up[perm]
if !ok {
// devs have access to everything
_, ok = up[PermDev]
return ok
}
Expand Down
4 changes: 4 additions & 0 deletions website/admin/pending.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ func (s *State) PostPending(w http.ResponseWriter, r *http.Request) {
var input = pendingInput{
shared: s.shared(r),
}
if input.User == nil || !input.User.UserPermissions.Has(radio.PermPendingEdit) {
s.GetPending(w, r)
return
}

form, err := s.postPending(w, r)
if err == nil {
Expand Down
9 changes: 5 additions & 4 deletions website/admin/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ func Router(ctx context.Context, s State) chi.Router {
r.HandleFunc("/", s.GetHome)
r.Get("/profile", s.GetProfile)
r.Post("/profile", s.PostProfile)
r.Get("/pending", s.GetPending)
r.Post("/pending", s.PostPending)
r.HandleFunc("/streamer/start", s.StartStreamer)
r.HandleFunc("/streamer/stop", s.StopStreamer)
r.Get("/pending", vmiddleware.RequirePermission(radio.PermPendingView, s.GetPending))
r.Post("/pending", vmiddleware.RequirePermission(radio.PermPendingEdit, s.PostPending))
// debug handlers, might not be needed later
r.HandleFunc("/streamer/start", vmiddleware.RequirePermission(radio.PermAdmin, s.StartStreamer))
r.HandleFunc("/streamer/stop", vmiddleware.RequirePermission(radio.PermAdmin, s.StopStreamer))
})

return r
Expand Down
1 change: 1 addition & 0 deletions website/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func Execute(ctx context.Context, cfg config.Config) error {
executor := siteTemplates.Executor()

r := chi.NewRouter()
r.Use(middleware.RequestID)
// TODO(wessie): check if nginx is setup to send the correct headers for real IP
// passthrough, as it's required for request handling
r.Use(middleware.RealIP)
Expand Down
18 changes: 18 additions & 0 deletions website/middleware/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ type authentication struct {
templates *templates.Executor
}

func RequirePermission(perm radio.UserPermission, handler http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user := UserFromContext(r.Context())
if user == nil {
// no user, clearly doesn't have permission
http.Error(w, "forbidden", http.StatusForbidden)
return
}
if !user.UserPermissions.Has(perm) {
// user doesn't have required perm
http.Error(w, "forbidden", http.StatusForbidden)
return
}

handler(w, r)
}
}

// UserMiddleware adds the currently logged in radio.User to the request if available
func (a authentication) UserMiddleware(next http.Handler) http.Handler {
const op errors.Op = "admin/authentication.UserMiddleware"
Expand Down
4 changes: 1 addition & 3 deletions website/public/submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,10 @@ func (s State) PostSubmit(w http.ResponseWriter, r *http.Request) {
return s.TemplateExecutor.ExecuteTemplate(theme, "submit", "form_submit", w, form)
}
}
defer http.NewResponseController(w).Flush()

// parse and validate the form
form, err := s.postSubmit(w, r)
if err != nil {
// TODO: debug this
// for unknown reason if we send a response without reading the body the connection is
// hard-reset instead and our response goes missing, so discard the body up to our
// allowed max size and then cut off if required
Expand Down Expand Up @@ -250,7 +248,7 @@ func (s State) postSubmit(w http.ResponseWriter, r *http.Request) (SubmissionFor
// fill in extra info we don't get from the probe
song.Comment = form.Comment
song.Filename = form.OriginalFilename
song.UserIdentifier = r.RemoteAddr
song.UserIdentifier, _ = s.getIdentifier(r)
if form.Replacement != nil {
song.ReplacementID = *form.Replacement
}
Expand Down

0 comments on commit 72b7ad1

Please sign in to comment.