diff --git a/api/rest.go b/api/rest.go index 2478d53..83a71f3 100644 --- a/api/rest.go +++ b/api/rest.go @@ -55,6 +55,7 @@ func (api *RestApi) MountRoutes(r *mux.Router) { r.HandleFunc("/users/", api.createUser).Methods(http.MethodPost, http.MethodPut) r.HandleFunc("/users/", api.getUsers).Methods(http.MethodGet) r.HandleFunc("/users/", api.deleteUser).Methods(http.MethodDelete) + r.HandleFunc("/user/{id}", api.updateUser).Methods(http.MethodPost) r.HandleFunc("/configuration/", api.updateConfiguration).Methods(http.MethodPost) } @@ -555,7 +556,9 @@ func (api *RestApi) getUsers(rw http.ResponseWriter, r *http.Request) { return } - users, err := api.Authentication.FetchUsers(r.URL.Query().Get("via-ldap") == "true") + users, err := api.Authentication.FetchUsers( + r.URL.Query().Get("via-ldap") == "true", + r.URL.Query().Get("not-just-user") == "true") if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) return @@ -564,6 +567,22 @@ func (api *RestApi) getUsers(rw http.ResponseWriter, r *http.Request) { json.NewEncoder(rw).Encode(users) } +func (api *RestApi) updateUser(rw http.ResponseWriter, r *http.Request) { + if user := auth.GetUser(r.Context()); !user.HasRole(auth.RoleAdmin) { + http.Error(rw, "only admins are allowed to update a user", http.StatusForbidden) + return + } + + // TODO: Handle anything but roles... + newrole := r.FormValue("add-role") + if err := api.Authentication.AddRole(r.Context(), mux.Vars(r)["id"], newrole); err != nil { + http.Error(rw, err.Error(), http.StatusUnprocessableEntity) + return + } + + rw.Write([]byte("success")) +} + func (api *RestApi) updateConfiguration(rw http.ResponseWriter, r *http.Request) { rw.Header().Set("Content-Type", "text/plain") key, value := r.FormValue("key"), r.FormValue("value") diff --git a/auth/auth.go b/auth/auth.go index b49bddb..a57247d 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -174,17 +174,48 @@ func (auth *Authentication) CreateUser(username, name, password, email string, r return nil } +func (auth *Authentication) AddRole(ctx context.Context, username string, role string) error { + user, err := auth.FetchUser(username) + if err != nil { + return err + } + + if role != RoleAdmin && role != RoleApi && role != RoleUser { + return fmt.Errorf("invalid user role: %#v", role) + } + + for _, r := range user.Roles { + if r == role { + return fmt.Errorf("user %#v already has role %#v", username, role) + } + } + + roles, _ := json.Marshal(append(user.Roles, role)) + if _, err := sq.Update("user").Set("roles", roles).Where("user.username = ?", username).RunWith(auth.db).Exec(); err != nil { + return err + } + return nil +} + func (auth *Authentication) DelUser(username string) error { _, err := auth.db.Exec(`DELETE FROM user WHERE user.username = ?`, username) return err } -func (auth *Authentication) FetchUsers(viaLdap bool) ([]*User, error) { +func (auth *Authentication) FetchUsers(viaLdap, notJustUser bool) ([]*User, error) { q := sq.Select("username", "name", "email", "roles").From("user") if !viaLdap { - q = q.Where("ldap = 0") + if notJustUser { + q = q.Where("ldap = 0 OR roles != '[\"user\"]'") + } else { + q = q.Where("ldap = 0") + } } else { - q = q.Where("ldap = 1") + if notJustUser { + q = q.Where("ldap = 1 OR roles != '[\"user\"]'") + } else { + q = q.Where("ldap = 1") + } } rows, err := q.RunWith(auth.db).Query() diff --git a/templates/config.tmpl b/templates/config.tmpl index 9e44f38..adc027c 100644 --- a/templates/config.tmpl +++ b/templates/config.tmpl @@ -47,7 +47,8 @@
-
All Users not Created by an LDAP Sync:
+
Special Users
+

Not created by an LDAP sync and/or having a role other than user

@@ -61,7 +62,7 @@ + + + {{end}}
Loading...