mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-11-10 08:57:25 +01:00
rename api userconfig to frontend, return json on api auth error
This commit is contained in:
parent
9d4767539c
commit
3afe40083d
@ -374,7 +374,7 @@ func main() {
|
||||
securedapi := r.PathPrefix("/api").Subrouter()
|
||||
userapi := r.PathPrefix("/userapi").Subrouter()
|
||||
configapi := r.PathPrefix("/config").Subrouter()
|
||||
userconfigapi := r.PathPrefix("/userconfig").Subrouter()
|
||||
frontendapi := r.PathPrefix("/frontend").Subrouter()
|
||||
|
||||
if !config.Keys.DisableAuthentication {
|
||||
r.Handle("/login", authentication.Login(
|
||||
@ -447,15 +447,13 @@ func main() {
|
||||
// On success;
|
||||
next,
|
||||
|
||||
// On failure:
|
||||
// On failure: JSON Response
|
||||
func(rw http.ResponseWriter, r *http.Request, err error) {
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
web.RenderTemplate(rw, "login.tmpl", &web.Page{
|
||||
Title: "Authentication failed - ClusterCockpit",
|
||||
MsgType: "alert-danger",
|
||||
Message: err.Error(),
|
||||
Build: buildInfo,
|
||||
Infos: info,
|
||||
json.NewEncoder(rw).Encode(map[string]string{
|
||||
"status": http.StatusText(http.StatusUnauthorized),
|
||||
"error": err.Error(),
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -465,15 +463,13 @@ func main() {
|
||||
// On success;
|
||||
next,
|
||||
|
||||
// On failure:
|
||||
// On failure: JSON Response
|
||||
func(rw http.ResponseWriter, r *http.Request, err error) {
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
web.RenderTemplate(rw, "login.tmpl", &web.Page{
|
||||
Title: "Authentication failed - ClusterCockpit",
|
||||
MsgType: "alert-danger",
|
||||
Message: err.Error(),
|
||||
Build: buildInfo,
|
||||
Infos: info,
|
||||
json.NewEncoder(rw).Encode(map[string]string{
|
||||
"status": http.StatusText(http.StatusUnauthorized),
|
||||
"error": err.Error(),
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -483,33 +479,29 @@ func main() {
|
||||
// On success;
|
||||
next,
|
||||
|
||||
// On failure:
|
||||
// On failure: JSON Response
|
||||
func(rw http.ResponseWriter, r *http.Request, err error) {
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
web.RenderTemplate(rw, "login.tmpl", &web.Page{
|
||||
Title: "Authentication failed - ClusterCockpit",
|
||||
MsgType: "alert-danger",
|
||||
Message: err.Error(),
|
||||
Build: buildInfo,
|
||||
Infos: info,
|
||||
json.NewEncoder(rw).Encode(map[string]string{
|
||||
"status": http.StatusText(http.StatusUnauthorized),
|
||||
"error": err.Error(),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
userconfigapi.Use(func(next http.Handler) http.Handler {
|
||||
return authentication.AuthUserConfigApi(
|
||||
frontendapi.Use(func(next http.Handler) http.Handler {
|
||||
return authentication.AuthFrontendApi(
|
||||
// On success;
|
||||
next,
|
||||
|
||||
// On failure:
|
||||
// On failure: JSON Response
|
||||
func(rw http.ResponseWriter, r *http.Request, err error) {
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
web.RenderTemplate(rw, "login.tmpl", &web.Page{
|
||||
Title: "Authentication failed - ClusterCockpit",
|
||||
MsgType: "alert-danger",
|
||||
Message: err.Error(),
|
||||
Build: buildInfo,
|
||||
Infos: info,
|
||||
json.NewEncoder(rw).Encode(map[string]string{
|
||||
"status": http.StatusText(http.StatusUnauthorized),
|
||||
"error": err.Error(),
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -532,7 +524,7 @@ func main() {
|
||||
api.MountApiRoutes(securedapi)
|
||||
api.MountUserApiRoutes(userapi)
|
||||
api.MountConfigApiRoutes(configapi)
|
||||
api.MountUserConfigApiRoutes(userconfigapi)
|
||||
api.MountFrontendApiRoutes(frontendapi)
|
||||
|
||||
if config.Keys.EmbedStaticFiles {
|
||||
if i, err := os.Stat("./var/img"); err == nil {
|
||||
|
@ -106,12 +106,13 @@ func (api *RestApi) MountConfigApiRoutes(r *mux.Router) {
|
||||
}
|
||||
}
|
||||
|
||||
func (api *RestApi) MountUserConfigApiRoutes(r *mux.Router) {
|
||||
func (api *RestApi) MountFrontendApiRoutes(r *mux.Router) {
|
||||
r.StrictSlash(true)
|
||||
|
||||
if api.Authentication != nil {
|
||||
r.HandleFunc("/jwt/", api.getJWT).Methods(http.MethodGet) // Role:Admin Check in
|
||||
r.HandleFunc("/jwt/", api.getJWT).Methods(http.MethodGet)
|
||||
r.HandleFunc("/configuration/", api.updateConfiguration).Methods(http.MethodPost)
|
||||
r.HandleFunc("/jobs/metrics/{id}", api.getJobMetrics).Methods(http.MethodGet) // Fetched in Job.svelte: Needs All-User-Access-Session-Auth
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,27 +219,25 @@ func (auth *Authentication) Auth(
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
user, err := auth.JwtAuth.AuthViaJWT(rw, r)
|
||||
if err != nil {
|
||||
log.Infof("authentication failed: %s", err.Error())
|
||||
log.Infof("auth -> authentication failed: %s", err.Error())
|
||||
http.Error(rw, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
user, err = auth.AuthViaSession(rw, r)
|
||||
if err != nil {
|
||||
log.Infof("authentication failed: %s", err.Error())
|
||||
log.Infof("auth -> authentication failed: %s", err.Error())
|
||||
http.Error(rw, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
ctx := context.WithValue(r.Context(), repository.ContextUserKey, user)
|
||||
onsuccess.ServeHTTP(rw, r.WithContext(ctx))
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("authentication failed")
|
||||
log.Info("auth -> authentication failed")
|
||||
onfailure(rw, r, errors.New("unauthorized (please login first)"))
|
||||
})
|
||||
}
|
||||
@ -251,8 +249,8 @@ func (auth *Authentication) AuthApi(
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
user, err := auth.JwtAuth.AuthViaJWT(rw, r)
|
||||
if err != nil {
|
||||
log.Infof("authentication failed: %s", err.Error())
|
||||
http.Error(rw, err.Error(), http.StatusUnauthorized)
|
||||
log.Infof("auth api -> authentication failed: %s", err.Error())
|
||||
onfailure(rw, r, err)
|
||||
return
|
||||
}
|
||||
if user != nil {
|
||||
@ -270,12 +268,12 @@ func (auth *Authentication) AuthApi(
|
||||
return
|
||||
}
|
||||
default:
|
||||
log.Debug("authentication failed")
|
||||
onfailure(rw, r, errors.New("unauthorized (missing role)"))
|
||||
log.Info("auth api -> authentication failed: missing role")
|
||||
onfailure(rw, r, errors.New("unauthorized"))
|
||||
}
|
||||
}
|
||||
log.Debug("authentication failed")
|
||||
onfailure(rw, r, errors.New("unauthorized (no auth)"))
|
||||
log.Info("auth api -> authentication failed: no auth")
|
||||
onfailure(rw, r, errors.New("unauthorized"))
|
||||
})
|
||||
}
|
||||
|
||||
@ -286,8 +284,8 @@ func (auth *Authentication) AuthUserApi(
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
user, err := auth.JwtAuth.AuthViaJWT(rw, r)
|
||||
if err != nil {
|
||||
log.Infof("authentication failed: %s", err.Error())
|
||||
http.Error(rw, err.Error(), http.StatusUnauthorized)
|
||||
log.Infof("auth user api -> authentication failed: %s", err.Error())
|
||||
onfailure(rw, r, err)
|
||||
return
|
||||
}
|
||||
if user != nil {
|
||||
@ -305,12 +303,12 @@ func (auth *Authentication) AuthUserApi(
|
||||
return
|
||||
}
|
||||
default:
|
||||
log.Debug("authentication failed")
|
||||
onfailure(rw, r, errors.New("unauthorized (missing role)"))
|
||||
log.Info("auth user api -> authentication failed: missing role")
|
||||
onfailure(rw, r, errors.New("unauthorized"))
|
||||
}
|
||||
}
|
||||
log.Debug("authentication failed")
|
||||
onfailure(rw, r, errors.New("unauthorized (no auth)"))
|
||||
log.Info("auth user api -> authentication failed: no auth")
|
||||
onfailure(rw, r, errors.New("unauthorized"))
|
||||
})
|
||||
}
|
||||
|
||||
@ -321,8 +319,8 @@ func (auth *Authentication) AuthConfigApi(
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
user, err := auth.AuthViaSession(rw, r)
|
||||
if err != nil {
|
||||
log.Infof("authentication failed: %s", err.Error())
|
||||
http.Error(rw, err.Error(), http.StatusUnauthorized)
|
||||
log.Infof("auth config api -> authentication failed: %s", err.Error())
|
||||
onfailure(rw, r, err)
|
||||
return
|
||||
}
|
||||
if user != nil && user.HasRole(schema.RoleAdmin) {
|
||||
@ -330,20 +328,20 @@ func (auth *Authentication) AuthConfigApi(
|
||||
onsuccess.ServeHTTP(rw, r.WithContext(ctx))
|
||||
return
|
||||
}
|
||||
log.Debug("authentication failed")
|
||||
onfailure(rw, r, errors.New("unauthorized (no auth)"))
|
||||
log.Info("auth config api -> authentication failed: no auth")
|
||||
onfailure(rw, r, errors.New("unauthorized"))
|
||||
})
|
||||
}
|
||||
|
||||
func (auth *Authentication) AuthUserConfigApi(
|
||||
func (auth *Authentication) AuthFrontendApi(
|
||||
onsuccess http.Handler,
|
||||
onfailure func(rw http.ResponseWriter, r *http.Request, authErr error),
|
||||
) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
user, err := auth.AuthViaSession(rw, r)
|
||||
if err != nil {
|
||||
log.Infof("authentication failed: %s", err.Error())
|
||||
http.Error(rw, err.Error(), http.StatusUnauthorized)
|
||||
log.Infof("auth frontend api -> authentication failed: %s", err.Error())
|
||||
onfailure(rw, r, err)
|
||||
return
|
||||
}
|
||||
if user != nil {
|
||||
@ -351,8 +349,8 @@ func (auth *Authentication) AuthUserConfigApi(
|
||||
onsuccess.ServeHTTP(rw, r.WithContext(ctx))
|
||||
return
|
||||
}
|
||||
log.Debug("authentication failed")
|
||||
onfailure(rw, r, errors.New("unauthorized (no auth)"))
|
||||
log.Info("auth frontend api -> authentication failed: no auth")
|
||||
onfailure(rw, r, errors.New("unauthorized"))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -305,16 +305,36 @@ func (r *JobRepository) FindByIdDirect(jobId int64) (*schema.Job, error) {
|
||||
return scanJob(q.RunWith(r.stmtCache).QueryRow())
|
||||
}
|
||||
|
||||
// FindByJobId executes a SQL query to find a specific batch job.
|
||||
// The job is queried using the slurm id and the clustername.
|
||||
// It returns a pointer to a schema.Job data structure and an error variable.
|
||||
// To check if no job was found test err == sql.ErrNoRows
|
||||
func (r *JobRepository) FindByJobId(ctx context.Context, jobId int64, startTime int64, cluster string) (*schema.Job, error) {
|
||||
q := sq.Select(jobColumns...).
|
||||
From("job").
|
||||
Where("job.job_id = ?", jobId).
|
||||
Where("job.cluster = ?", cluster).
|
||||
Where("job.start_time = ?", startTime)
|
||||
|
||||
q, qerr := SecurityCheck(ctx, q)
|
||||
if qerr != nil {
|
||||
return nil, qerr
|
||||
}
|
||||
|
||||
return scanJob(q.RunWith(r.stmtCache).QueryRow())
|
||||
}
|
||||
|
||||
// IsJobOwner executes a SQL query to find a specific batch job.
|
||||
// The job is queried using the slurm id,a username and the cluster.
|
||||
// It returns a bool.
|
||||
// If job was found, user is owner: test err != sql.ErrNoRows
|
||||
func (r *JobRepository) IsJobOwner(jobId int64, user string, cluster string) bool {
|
||||
func (r *JobRepository) IsJobOwner(jobId int64, startTime int64, user string, cluster string) bool {
|
||||
q := sq.Select("id").
|
||||
From("job").
|
||||
Where("job.job_id = ?", jobId).
|
||||
Where("job.user = ?", user).
|
||||
Where("job.cluster = ?", cluster)
|
||||
Where("job.cluster = ?", cluster).
|
||||
Where("job.start_time = ?", startTime)
|
||||
|
||||
_, err := scanJob(q.RunWith(r.stmtCache).QueryRow())
|
||||
return err != sql.ErrNoRows
|
||||
|
@ -262,7 +262,7 @@
|
||||
<form
|
||||
id="colorscheme-form"
|
||||
method="post"
|
||||
action="/userconfig/configuration/"
|
||||
action="/frontend/configuration/"
|
||||
class="card-body"
|
||||
>
|
||||
<!-- Svelte 'class' directive only on DOMs directly, normal 'class="xxx"' does not work, so style-array it is. -->
|
||||
|
@ -30,7 +30,7 @@
|
||||
<form
|
||||
id="line-width-form"
|
||||
method="post"
|
||||
action="/userconfig/configuration/"
|
||||
action="/frontend/configuration/"
|
||||
class="card-body"
|
||||
on:submit|preventDefault={() =>
|
||||
updateSetting("#line-width-form", "lw")}
|
||||
@ -76,7 +76,7 @@
|
||||
<form
|
||||
id="plots-per-row-form"
|
||||
method="post"
|
||||
action="/userconfig/configuration/"
|
||||
action="/frontend/configuration/"
|
||||
class="card-body"
|
||||
on:submit|preventDefault={() =>
|
||||
updateSetting("#plots-per-row-form", "ppr")}
|
||||
@ -122,7 +122,7 @@
|
||||
<form
|
||||
id="backgrounds-form"
|
||||
method="post"
|
||||
action="/userconfig/configuration/"
|
||||
action="/frontend/configuration/"
|
||||
class="card-body"
|
||||
on:submit|preventDefault={() =>
|
||||
updateSetting("#backgrounds-form", "bg")}
|
||||
|
@ -51,7 +51,7 @@
|
||||
<form
|
||||
id="paging-form"
|
||||
method="post"
|
||||
action="/userconfig/configuration/"
|
||||
action="/frontend/configuration/"
|
||||
class="card-body"
|
||||
on:submit|preventDefault={() =>
|
||||
updateSetting("#paging-form", "pag")}
|
||||
|
@ -239,7 +239,7 @@ export async function fetchMetrics(job, metrics, scopes) {
|
||||
|
||||
try {
|
||||
let res = await fetch(
|
||||
`/api/jobs/metrics/${job.id}${query.length > 0 ? "?" : ""}${query.join(
|
||||
`/frontend/jobs/metrics/${job.id}${query.length > 0 ? "?" : ""}${query.join(
|
||||
"&"
|
||||
)}`
|
||||
);
|
||||
@ -434,7 +434,7 @@ export function transformPerNodeDataForRoofline(nodes) {
|
||||
}
|
||||
|
||||
export async function fetchJwt(username) {
|
||||
const raw = await fetch(`/userconfig/jwt/?username=${username}`);
|
||||
const raw = await fetch(`/frontend/jwt/?username=${username}`);
|
||||
|
||||
if (!raw.ok) {
|
||||
const message = `An error has occured: ${response.status}`;
|
||||
|
Loading…
Reference in New Issue
Block a user