mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-12-25 12:59:06 +01:00
Allow making LDAP users admins
This commit is contained in:
parent
6e9a916a18
commit
e0cc17cfa9
21
api/rest.go
21
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")
|
||||
|
37
auth/auth.go
37
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()
|
||||
|
@ -47,7 +47,8 @@
|
||||
</div>
|
||||
<div class="col card" style="margin: 10px;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">All Users not Created by an LDAP Sync:</h5>
|
||||
<h5 class="card-title">Special Users</h5>
|
||||
<p>Not created by an LDAP sync and/or having a role other than <code>user</code></p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -61,7 +62,7 @@
|
||||
</thead>
|
||||
<tbody id="users-list"><tr><td colspan="4"><div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div></td></tr></tbody>
|
||||
<script>
|
||||
fetch('/api/users/?via-ldap=false')
|
||||
fetch('/api/users/?via-ldap=false¬-just-user=true')
|
||||
.then(res => res.json())
|
||||
.then(users => {
|
||||
let listElement = document.querySelector('#users-list')
|
||||
@ -105,6 +106,37 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col card" style="margin: 10px;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Add Role to User</h5>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="username" id="add-role-username"/>
|
||||
<select class="form-select" id="add-role-select">
|
||||
<option selected value="">Role...</option>
|
||||
<option value="user">User</option>
|
||||
<option value="admin">Admin</option>
|
||||
<option value="api">API</option>
|
||||
</select>
|
||||
<button class="btn btn-outline-secondary" type="button" id="add-role-button">Button</button>
|
||||
</div>
|
||||
<script>
|
||||
document.querySelector('#add-role-button').addEventListener('click', () => {
|
||||
const username = document.querySelector('#add-role-username').value, role = document.querySelector('#add-role-select').value
|
||||
if (username == "" || role == "") {
|
||||
alert('Please fill in a username and select a role.')
|
||||
return
|
||||
}
|
||||
|
||||
let formData = new FormData()
|
||||
formData.append('username', username)
|
||||
formData.append('add-role', role)
|
||||
fetch(`/api/user/${username}`, { method: 'POST', body: formData }).then(res => res.text()).then(status => alert(status))
|
||||
})
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="row">
|
||||
<div class="col card" style="margin: 10px;">
|
||||
|
Loading…
Reference in New Issue
Block a user