mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-12-26 13:29:05 +01:00
Add API call for frontend to fetch list of valid roles from backend
- only relevant for admin config (addUser, editRole) - admin only (double-checked)
This commit is contained in:
parent
7d4f4ab2c8
commit
7fb94c33cf
@ -76,6 +76,7 @@ func (api *RestApi) MountRoutes(r *mux.Router) {
|
|||||||
|
|
||||||
if api.Authentication != nil {
|
if api.Authentication != nil {
|
||||||
r.HandleFunc("/jwt/", api.getJWT).Methods(http.MethodGet)
|
r.HandleFunc("/jwt/", api.getJWT).Methods(http.MethodGet)
|
||||||
|
r.HandleFunc("/roles/", api.getRoles).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/users/", api.createUser).Methods(http.MethodPost, http.MethodPut)
|
r.HandleFunc("/users/", api.createUser).Methods(http.MethodPost, http.MethodPut)
|
||||||
r.HandleFunc("/users/", api.getUsers).Methods(http.MethodGet)
|
r.HandleFunc("/users/", api.getUsers).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/users/", api.deleteUser).Methods(http.MethodDelete)
|
r.HandleFunc("/users/", api.deleteUser).Methods(http.MethodDelete)
|
||||||
@ -880,6 +881,22 @@ func (api *RestApi) getUsers(rw http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(rw).Encode(users)
|
json.NewEncoder(rw).Encode(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *RestApi) getRoles(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
user := auth.GetUser(r.Context())
|
||||||
|
if (!user.HasRole(auth.RoleAdmin)) {
|
||||||
|
http.Error(rw, "only admins are allowed to fetch a list of roles", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
roles, err := auth.GetValidRoles(user)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
json.NewEncoder(rw).Encode(roles)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *RestApi) updateUser(rw http.ResponseWriter, r *http.Request) {
|
func (api *RestApi) updateUser(rw http.ResponseWriter, r *http.Request) {
|
||||||
if user := auth.GetUser(r.Context()); !user.HasRole(auth.RoleAdmin) {
|
if user := auth.GetUser(r.Context()); !user.HasRole(auth.RoleAdmin) {
|
||||||
http.Error(rw, "only admins are allowed to update a user", http.StatusForbidden)
|
http.Error(rw, "only admins are allowed to update a user", http.StatusForbidden)
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/ClusterCockpit/cc-backend/pkg/log"
|
"github.com/ClusterCockpit/cc-backend/pkg/log"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
@ -139,6 +140,15 @@ func IsValidRole(role string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetValidRoles(user *User) ([5]string, error) {
|
||||||
|
var vals [5]string
|
||||||
|
if (!user.HasRole(RoleAdmin)) {
|
||||||
|
return vals, fmt.Errorf("%#v: only admins are allowed to fetch a list of roles", user.Username)
|
||||||
|
} else {
|
||||||
|
return validRoles, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GetUser(ctx context.Context) *User {
|
func GetUser(ctx context.Context) *User {
|
||||||
x := ctx.Value(ContextUserKey)
|
x := ctx.Value(ContextUserKey)
|
||||||
if x == nil {
|
if x == nil {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
import Options from './admin/Options.svelte'
|
import Options from './admin/Options.svelte'
|
||||||
|
|
||||||
let users = []
|
let users = []
|
||||||
|
let roles = []
|
||||||
|
|
||||||
function getUserList() {
|
function getUserList() {
|
||||||
fetch('/api/users/?via-ldap=false¬-just-user=true')
|
fetch('/api/users/?via-ldap=false¬-just-user=true')
|
||||||
@ -17,19 +18,32 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => getUserList())
|
function getValidRoles() {
|
||||||
|
fetch('/api/roles/')
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(rolesRaw => {
|
||||||
|
roles = rolesRaw
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function initAdmin() {
|
||||||
|
getUserList()
|
||||||
|
getValidRoles()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => initAdmin())
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Row cols={2} class="p-2 g-2" >
|
<Row cols={2} class="p-2 g-2" >
|
||||||
<Col class="mb-1">
|
<Col class="mb-1">
|
||||||
<AddUser on:reload={getUserList}/>
|
<AddUser roles={roles} on:reload={getUserList}/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col class="mb-1">
|
<Col class="mb-1">
|
||||||
<ShowUsers on:reload={getUserList} bind:users={users}/>
|
<ShowUsers on:reload={getUserList} bind:users={users}/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col>
|
<Col>
|
||||||
<EditRole on:reload={getUserList}/>
|
<EditRole roles={roles} on:reload={getUserList}/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col>
|
<Col>
|
||||||
<EditProject on:reload={getUserList}/>
|
<EditProject on:reload={getUserList}/>
|
||||||
|
@ -7,6 +7,15 @@
|
|||||||
|
|
||||||
let message = {msg: '', color: '#d63384'}
|
let message = {msg: '', color: '#d63384'}
|
||||||
let displayMessage = false
|
let displayMessage = false
|
||||||
|
let roleLabel = {
|
||||||
|
api: 'API',
|
||||||
|
user: 'User (regular user, same as if created via LDAP sync.)',
|
||||||
|
manager: 'Manager',
|
||||||
|
support: 'Support',
|
||||||
|
admin: 'Admin'
|
||||||
|
}
|
||||||
|
|
||||||
|
export let roles = []
|
||||||
|
|
||||||
async function handleUserSubmit() {
|
async function handleUserSubmit() {
|
||||||
let form = document.querySelector('#create-user-form')
|
let form = document.querySelector('#create-user-form')
|
||||||
@ -73,26 +82,19 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<p>Role:</p>
|
<p>Role:</p>
|
||||||
|
{#each roles as role, i}
|
||||||
|
{#if i == 0}
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="user" name="role" value="user" checked/>
|
<input type="radio" id={role} name="role" value={role} checked/>
|
||||||
<label for="user">User (regular user, same as if created via LDAP sync.)</label>
|
<label for={role}>{roleLabel[role]}</label>
|
||||||
</div>
|
</div>
|
||||||
|
{:else}
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" id="api" name="role" value="api"/>
|
<input type="radio" id={role} name="role" value={role}/>
|
||||||
<label for="api">API</label>
|
<label for={role}>{roleLabel[role]}</label>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="radio" id="manager" name="role" value="manager"/>
|
|
||||||
<label for="manager">Manager</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="radio" id="support" name="role" value="support"/>
|
|
||||||
<label for="support">Support</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="radio" id="admin" name="role" value="admin"/>
|
|
||||||
<label for="admin">Admin</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<p style="display: flex; align-items: center;">
|
<p style="display: flex; align-items: center;">
|
||||||
<Button type="submit" color="primary">Submit</Button>
|
<Button type="submit" color="primary">Submit</Button>
|
||||||
|
@ -8,6 +8,15 @@
|
|||||||
let message = {msg: '', color: '#d63384'}
|
let message = {msg: '', color: '#d63384'}
|
||||||
let displayMessage = false
|
let displayMessage = false
|
||||||
|
|
||||||
|
export let roles = []
|
||||||
|
let roleLabel = {
|
||||||
|
api: 'API',
|
||||||
|
user: 'User',
|
||||||
|
manager: 'Manager',
|
||||||
|
support: 'Support',
|
||||||
|
admin: 'Admin'
|
||||||
|
}
|
||||||
|
|
||||||
async function handleAddRole() {
|
async function handleAddRole() {
|
||||||
const username = document.querySelector('#role-username').value
|
const username = document.querySelector('#role-username').value
|
||||||
const role = document.querySelector('#role-select').value
|
const role = document.querySelector('#role-select').value
|
||||||
@ -86,11 +95,9 @@
|
|||||||
<input type="text" class="form-control" placeholder="username" id="role-username"/>
|
<input type="text" class="form-control" placeholder="username" id="role-username"/>
|
||||||
<select class="form-select" id="role-select">
|
<select class="form-select" id="role-select">
|
||||||
<option selected value="">Role...</option>
|
<option selected value="">Role...</option>
|
||||||
<option value="user">User</option>
|
{#each roles as role}
|
||||||
<option value="manager">Manager</option>
|
<option value={role}>{roleLabel[role]}</option>
|
||||||
<option value="support">Support</option>
|
{/each}
|
||||||
<option value="admin">Admin</option>
|
|
||||||
<option value="api">API</option>
|
|
||||||
</select>
|
</select>
|
||||||
<!-- PreventDefault on Sveltestrap-Button more complex to achieve than just use good ol' html button -->
|
<!-- PreventDefault on Sveltestrap-Button more complex to achieve than just use good ol' html button -->
|
||||||
<!-- see: https://stackoverflow.com/questions/69630422/svelte-how-to-use-event-modifiers-in-my-own-components -->
|
<!-- see: https://stackoverflow.com/questions/69630422/svelte-how-to-use-event-modifiers-in-my-own-components -->
|
||||||
|
Loading…
Reference in New Issue
Block a user