mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-12-26 13:29:05 +01:00
Rework searchbar functions, add user jobtable
This commit is contained in:
parent
d0d578a1e6
commit
d6b8d711f6
@ -491,195 +491,94 @@ var ErrForbidden = errors.New("not authorized")
|
|||||||
// If query is found to be an integer (= conversion to INT datatype succeeds), skip back to parent call
|
// If query is found to be an integer (= conversion to INT datatype succeeds), skip back to parent call
|
||||||
// If nothing matches the search, `ErrNotFound` is returned.
|
// If nothing matches the search, `ErrNotFound` is returned.
|
||||||
|
|
||||||
func (r *JobRepository) FindJobnameOrUserOrProject(ctx context.Context, searchterm string) (metasnip string, username string, project string, err error) {
|
func (r *JobRepository) FindUserOrProjectOrJobname(ctx context.Context, searchterm string) (username string, project string, metasnip string, err error) {
|
||||||
user := auth.GetUser(ctx)
|
|
||||||
if _, err := strconv.Atoi(searchterm); err == nil { // Return empty on successful conversion: parent method will redirect for integer jobId
|
if _, err := strconv.Atoi(searchterm); err == nil { // Return empty on successful conversion: parent method will redirect for integer jobId
|
||||||
return "", "", "", nil
|
return "", "", "", nil
|
||||||
} else { // has to have letters
|
} else { // Has to have letters and logged-in user for other guesses
|
||||||
|
user := auth.GetUser(ctx)
|
||||||
if user != nil && user.HasNotRoles([]string{auth.RoleAdmin, auth.RoleSupport}) {
|
if user != nil {
|
||||||
err := sq.Select("job.user").Distinct().From("job").
|
// Find username in jobs (match)
|
||||||
Where("job.user = ?", searchterm).
|
uresult, _ := r.FindColumnValue(user, searchterm, "job", "user", "user", false)
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&username)
|
if uresult != "" {
|
||||||
|
return uresult, "", "", nil
|
||||||
|
}
|
||||||
|
// Find username by name (like)
|
||||||
|
nresult, _ := r.FindColumnValue(user, searchterm, "user", "username", "name", true)
|
||||||
|
if nresult != "" {
|
||||||
|
return nresult, "", "", nil
|
||||||
|
}
|
||||||
|
// Find projectId in jobs (match)
|
||||||
|
presult, _ := r.FindColumnValue(user, searchterm, "job", "project", "project", false)
|
||||||
|
if presult != "" {
|
||||||
|
return "", presult, "", nil
|
||||||
|
}
|
||||||
|
// Still no return (or not authorized for above): Try JobName
|
||||||
|
// Match Metadata, on hit, parent method redirects to jobName GQL query
|
||||||
|
err := sq.Select("job.cluster").Distinct().From("job").
|
||||||
|
Where("job.meta_data LIKE ?", "%"+searchterm+"%").
|
||||||
|
RunWith(r.stmtCache).QueryRow().Scan(&metasnip)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
return "", "", "", err
|
return "", "", "", err
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
return "", username, "", nil
|
return "", "", metasnip[0:1], nil
|
||||||
}
|
|
||||||
|
|
||||||
if username == "" { // Try with Name2Username query
|
|
||||||
errtwo := sq.Select("user.username").Distinct().From("user").
|
|
||||||
Where("user.name LIKE ?", fmt.Sprint("%"+searchterm+"%")).
|
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&username)
|
|
||||||
if errtwo != nil && errtwo != sql.ErrNoRows {
|
|
||||||
return "", "", "", errtwo
|
|
||||||
} else if errtwo == nil {
|
|
||||||
return "", username, "", nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleSupport) {
|
|
||||||
err := sq.Select("job.project").Distinct().From("job").
|
|
||||||
Where("job.project = ?", searchterm).
|
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&project)
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
return "", "", "", err
|
|
||||||
} else if err == nil {
|
|
||||||
return "", "", project, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All Authorizations: If unlabeled query not username or projectId, try for jobname: Match Metadata, on hit, parent method redirects to jobName GQL query
|
|
||||||
err := sq.Select("job.cluster").Distinct().From("job").
|
|
||||||
Where("job.meta_data LIKE ?", "%"+searchterm+"%").
|
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&metasnip)
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
return "", "", "", err
|
|
||||||
} else if err == nil {
|
|
||||||
return metasnip[0:1], "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", "", "", ErrNotFound
|
return "", "", "", ErrNotFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *JobRepository) FindUser(ctx context.Context, searchterm string) (username string, err error) {
|
func (r *JobRepository) FindColumnValue(user *auth.User, searchterm string, table string, selectColumn string, whereColumn string, isLike bool) (result string, err error) {
|
||||||
user := auth.GetUser(ctx)
|
compareStr := " = ?"
|
||||||
if user == nil || user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleSupport}) {
|
query := searchterm
|
||||||
err := sq.Select("job.user").Distinct().From("job").
|
if isLike == true {
|
||||||
Where("job.user = ?", searchterm).
|
compareStr = " LIKE ?"
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&username)
|
query = "%" + searchterm + "%"
|
||||||
|
}
|
||||||
|
if user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleSupport, auth.RoleManager}) {
|
||||||
|
err := sq.Select(table+"."+selectColumn).Distinct().From(table).
|
||||||
|
Where(table+"."+whereColumn+compareStr, query).
|
||||||
|
RunWith(r.stmtCache).QueryRow().Scan(&result)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
return "", err
|
return "", err
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
return username, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
return "", ErrNotFound
|
return "", ErrNotFound
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.Infof("Non-Admin User %s : Requested Query Username -> %s: Forbidden", user.Name, searchterm)
|
log.Infof("Non-Admin User %s : Requested Query '%s' on table '%s' : Forbidden", user.Name, query, table)
|
||||||
return "", ErrForbidden
|
return "", ErrForbidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *JobRepository) FindUserByName(ctx context.Context, searchterm string) (username string, err error) {
|
func (r *JobRepository) FindColumnValues(user *auth.User, query string, table string, selectColumn string, whereColumn string) (results []string, err error) {
|
||||||
user := auth.GetUser(ctx)
|
|
||||||
if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleSupport) {
|
|
||||||
err := sq.Select("user.username").Distinct().From("user").
|
|
||||||
Where("user.name = ?", searchterm).
|
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&username)
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
return "", err
|
|
||||||
} else if err == nil {
|
|
||||||
return username, nil
|
|
||||||
}
|
|
||||||
return "", ErrNotFound
|
|
||||||
|
|
||||||
} else {
|
|
||||||
log.Infof("Non-Admin User %s : Requested Query Name -> %s: Forbidden", user.Name, searchterm)
|
|
||||||
return "", ErrForbidden
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JobRepository) FindUsers(ctx context.Context, searchterm string) (usernames []string, err error) {
|
|
||||||
user := auth.GetUser(ctx)
|
|
||||||
emptyResult := make([]string, 0)
|
emptyResult := make([]string, 0)
|
||||||
if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleSupport) {
|
if user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleSupport, auth.RoleManager}) {
|
||||||
rows, err := sq.Select("job.user").Distinct().From("job").
|
rows, err := sq.Select(table+"."+selectColumn).Distinct().From(table).
|
||||||
Where("job.user LIKE ?", fmt.Sprint("%", searchterm, "%")).
|
Where(table+"."+whereColumn+" LIKE ?", fmt.Sprint("%", query, "%")).
|
||||||
RunWith(r.stmtCache).Query()
|
RunWith(r.stmtCache).Query()
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
return emptyResult, err
|
return emptyResult, err
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var name string
|
var result string
|
||||||
err := rows.Scan(&name)
|
err := rows.Scan(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rows.Close()
|
rows.Close()
|
||||||
log.Warnf("Error while scanning rows: %v", err)
|
log.Warnf("Error while scanning rows: %v", err)
|
||||||
return emptyResult, err
|
return emptyResult, err
|
||||||
}
|
}
|
||||||
usernames = append(usernames, name)
|
results = append(results, result)
|
||||||
}
|
}
|
||||||
return usernames, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
return emptyResult, ErrNotFound
|
return emptyResult, ErrNotFound
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.Infof("Non-Admin User %s : Requested Query Usernames -> %s: Forbidden", user.Name, searchterm)
|
log.Infof("Non-Admin User %s : Requested Query '%s' on table '%s' : Forbidden", user.Name, query, table)
|
||||||
return emptyResult, ErrForbidden
|
return emptyResult, ErrForbidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *JobRepository) FindUsersByName(ctx context.Context, searchterm string) (usernames []string, err error) {
|
|
||||||
user := auth.GetUser(ctx)
|
|
||||||
emptyResult := make([]string, 0)
|
|
||||||
if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleSupport) {
|
|
||||||
rows, err := sq.Select("user.username").Distinct().From("user").
|
|
||||||
Where("user.name LIKE ?", fmt.Sprint("%", searchterm, "%")).
|
|
||||||
RunWith(r.stmtCache).Query()
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
return emptyResult, err
|
|
||||||
} else if err == nil {
|
|
||||||
for rows.Next() {
|
|
||||||
var username string
|
|
||||||
err := rows.Scan(&username)
|
|
||||||
if err != nil {
|
|
||||||
rows.Close()
|
|
||||||
log.Warnf("Error while scanning rows: %v", err)
|
|
||||||
return emptyResult, err
|
|
||||||
}
|
|
||||||
usernames = append(usernames, username)
|
|
||||||
}
|
|
||||||
return usernames, nil
|
|
||||||
}
|
|
||||||
return emptyResult, ErrNotFound
|
|
||||||
|
|
||||||
} else {
|
|
||||||
log.Infof("Non-Admin User %s : Requested Query name -> %s: Forbidden", user.Name, searchterm)
|
|
||||||
return emptyResult, ErrForbidden
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JobRepository) FindNameByUser(ctx context.Context, searchterm string) (name string, err error) {
|
|
||||||
user := auth.GetUser(ctx)
|
|
||||||
if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleSupport) {
|
|
||||||
err := sq.Select("user.name").Distinct().From("user").
|
|
||||||
Where("user.username = ?", searchterm).
|
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&name)
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
return "", err
|
|
||||||
} else if err == nil {
|
|
||||||
return name, nil
|
|
||||||
}
|
|
||||||
return "", ErrNotFound
|
|
||||||
|
|
||||||
} else {
|
|
||||||
log.Infof("Non-Admin User %s : Requested Query Name -> %s: Forbidden", user.Name, searchterm)
|
|
||||||
return "", ErrForbidden
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JobRepository) FindProject(ctx context.Context, searchterm string) (project string, err error) {
|
|
||||||
|
|
||||||
user := auth.GetUser(ctx)
|
|
||||||
if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleSupport) {
|
|
||||||
err := sq.Select("job.project").Distinct().From("job").
|
|
||||||
Where("job.project = ?", searchterm).
|
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&project)
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
return "", err
|
|
||||||
} else if err == nil {
|
|
||||||
return project, nil
|
|
||||||
}
|
|
||||||
return "", ErrNotFound
|
|
||||||
} else {
|
|
||||||
log.Infof("Non-Admin User %s : Requested Query Project -> %s: Forbidden", user.Name, project)
|
|
||||||
return "", ErrForbidden
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JobRepository) Partitions(cluster string) ([]string, error) {
|
func (r *JobRepository) Partitions(cluster string) ([]string, error) {
|
||||||
var err error
|
var err error
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
@ -917,7 +816,8 @@ func (r *JobRepository) JobsStatistics(ctx context.Context,
|
|||||||
if col == "job.user" {
|
if col == "job.user" {
|
||||||
for id := range stats {
|
for id := range stats {
|
||||||
emptyDash := "-"
|
emptyDash := "-"
|
||||||
name, _ := r.FindNameByUser(ctx, id)
|
user := auth.GetUser(ctx)
|
||||||
|
name, _ := r.FindColumnValue(user, id, "user", "name", "username", false)
|
||||||
if name != "" {
|
if name != "" {
|
||||||
stats[id].Name = &name
|
stats[id].Name = &name
|
||||||
} else {
|
} else {
|
||||||
|
@ -312,75 +312,61 @@ func SetupRoutes(router *mux.Router, version string, hash string, buildTime stri
|
|||||||
|
|
||||||
func HandleSearchBar(rw http.ResponseWriter, r *http.Request, api *api.RestApi) {
|
func HandleSearchBar(rw http.ResponseWriter, r *http.Request, api *api.RestApi) {
|
||||||
if search := r.URL.Query().Get("searchId"); search != "" {
|
if search := r.URL.Query().Get("searchId"); search != "" {
|
||||||
|
user := auth.GetUser(r.Context())
|
||||||
splitSearch := strings.Split(search, ":")
|
splitSearch := strings.Split(search, ":")
|
||||||
|
|
||||||
if len(splitSearch) == 2 {
|
if len(splitSearch) == 2 {
|
||||||
switch strings.Trim(splitSearch[0], " ") {
|
switch strings.Trim(splitSearch[0], " ") {
|
||||||
case "jobId":
|
case "jobId":
|
||||||
http.Redirect(rw, r, "/monitoring/jobs/?jobId="+url.QueryEscape(strings.Trim(splitSearch[1], " ")), http.StatusTemporaryRedirect) // All Users: Redirect to Tablequery
|
http.Redirect(rw, r, "/monitoring/jobs/?jobId="+url.QueryEscape(strings.Trim(splitSearch[1], " ")), http.StatusTemporaryRedirect) // All Users: Redirect to Tablequery
|
||||||
return
|
|
||||||
case "jobName":
|
case "jobName":
|
||||||
http.Redirect(rw, r, "/monitoring/jobs/?jobName="+url.QueryEscape(strings.Trim(splitSearch[1], " ")), http.StatusTemporaryRedirect) // All Users: Redirect to Tablequery
|
http.Redirect(rw, r, "/monitoring/jobs/?jobName="+url.QueryEscape(strings.Trim(splitSearch[1], " ")), http.StatusTemporaryRedirect) // All Users: Redirect to Tablequery
|
||||||
return
|
|
||||||
case "projectId":
|
case "projectId":
|
||||||
project, _ := api.JobRepository.FindProject(r.Context(), strings.Trim(splitSearch[1], " ")) // Restricted: projectId
|
http.Redirect(rw, r, "/monitoring/jobs/?projectMatch=eq&project="+url.QueryEscape(strings.Trim(splitSearch[1], " ")), http.StatusTemporaryRedirect) // All Users: Redirect to Tablequery
|
||||||
if project != "" {
|
|
||||||
http.Redirect(rw, r, "/monitoring/jobs/?projectMatch=eq&project="+url.QueryEscape(project), http.StatusTemporaryRedirect)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
http.Redirect(rw, r, "/monitoring/jobs/?jobId=NotFound", http.StatusTemporaryRedirect) // Workaround to display correctly empty table
|
|
||||||
}
|
|
||||||
case "username":
|
case "username":
|
||||||
usernames, _ := api.JobRepository.FindUsers(r.Context(), strings.Trim(splitSearch[1], " ")) // Restricted: usernames
|
if user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleSupport, auth.RoleManager}) {
|
||||||
if len(usernames) == 1 {
|
http.Redirect(rw, r, "/monitoring/users/?user="+url.QueryEscape(strings.Trim(splitSearch[1], " ")), http.StatusTemporaryRedirect)
|
||||||
http.Redirect(rw, r, "/monitoring/user/"+usernames[0], http.StatusTemporaryRedirect) // One Match: Redirect to User View
|
|
||||||
return
|
|
||||||
} else if len(usernames) > 1 {
|
|
||||||
http.Redirect(rw, r, "/monitoring/users/?user="+url.QueryEscape(strings.Trim(splitSearch[1], " ")), http.StatusTemporaryRedirect) // > 1 Matches: Redirect to user table
|
|
||||||
return
|
|
||||||
} else {
|
} else {
|
||||||
http.Redirect(rw, r, "/monitoring/users/?user=NotFound", http.StatusTemporaryRedirect) // Workaround to display correctly empty table
|
http.Redirect(rw, r, "/monitoring/jobs/?", http.StatusTemporaryRedirect) // Users: Redirect to Tablequery
|
||||||
}
|
}
|
||||||
case "name":
|
case "name":
|
||||||
usernames, _ := api.JobRepository.FindUsersByName(r.Context(), strings.Trim(splitSearch[1], " ")) // Restricted: usernames queried by name
|
usernames, _ := api.JobRepository.FindColumnValues(user, strings.Trim(splitSearch[1], " "), "user", "username", "name")
|
||||||
if len(usernames) == 1 {
|
if len(usernames) != 0 {
|
||||||
http.Redirect(rw, r, "/monitoring/user/"+usernames[0], http.StatusTemporaryRedirect)
|
|
||||||
return
|
|
||||||
} else if len(usernames) > 1 {
|
|
||||||
joinedNames := strings.Join(usernames, "&user=")
|
joinedNames := strings.Join(usernames, "&user=")
|
||||||
http.Redirect(rw, r, "/monitoring/users/?user="+joinedNames, http.StatusTemporaryRedirect) // > 1 Matches: Redirect to user table
|
http.Redirect(rw, r, "/monitoring/users/?user="+joinedNames, http.StatusTemporaryRedirect)
|
||||||
return
|
|
||||||
} else {
|
} else {
|
||||||
http.Redirect(rw, r, "/monitoring/users/?user=NotFound", http.StatusTemporaryRedirect) // Workaround to display correctly empty table
|
if user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleSupport, auth.RoleManager}) {
|
||||||
|
http.Redirect(rw, r, "/monitoring/users/?user=NoUserNameFound", http.StatusTemporaryRedirect)
|
||||||
|
} else {
|
||||||
|
http.Redirect(rw, r, "/monitoring/jobs/?", http.StatusTemporaryRedirect) // Users: Redirect to Tablequery
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
http.Error(rw, "'searchId' type parameter unknown", http.StatusBadRequest)
|
log.Warnf("Searchbar type parameter '%s' unknown", strings.Trim(splitSearch[0], " "))
|
||||||
|
http.Redirect(rw, r, "/monitoring/jobs/?", http.StatusTemporaryRedirect) // Unknown: Redirect to Tablequery
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if len(splitSearch) == 1 {
|
} else if len(splitSearch) == 1 {
|
||||||
jobname, username, project, err := api.JobRepository.FindJobnameOrUserOrProject(r.Context(), strings.Trim(search, " ")) // Determine Access within
|
username, project, jobname, err := api.JobRepository.FindUserOrProjectOrJobname(r.Context(), strings.Trim(search, " "))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
log.Errorf("Error while searchbar best guess: %v", err.Error())
|
||||||
return
|
http.Redirect(rw, r, "/monitoring/jobs/?", http.StatusTemporaryRedirect) // Unknown: Redirect to Tablequery
|
||||||
}
|
}
|
||||||
|
|
||||||
if username != "" {
|
if username != "" {
|
||||||
http.Redirect(rw, r, "/monitoring/user/"+username, http.StatusTemporaryRedirect) // User: Redirect to user page
|
http.Redirect(rw, r, "/monitoring/user/"+username, http.StatusTemporaryRedirect) // User: Redirect to user page
|
||||||
return
|
|
||||||
} else if project != "" {
|
} else if project != "" {
|
||||||
http.Redirect(rw, r, "/monitoring/jobs/?projectMatch=eq&project="+url.QueryEscape(strings.Trim(search, " ")), http.StatusTemporaryRedirect) // projectId (equal)
|
http.Redirect(rw, r, "/monitoring/jobs/?projectMatch=eq&project="+url.QueryEscape(strings.Trim(search, " ")), http.StatusTemporaryRedirect) // projectId (equal)
|
||||||
return
|
|
||||||
} else if jobname != "" {
|
} else if jobname != "" {
|
||||||
http.Redirect(rw, r, "/monitoring/jobs/?jobName="+url.QueryEscape(strings.Trim(search, " ")), http.StatusTemporaryRedirect) // JobName (contains)
|
http.Redirect(rw, r, "/monitoring/jobs/?jobName="+url.QueryEscape(strings.Trim(search, " ")), http.StatusTemporaryRedirect) // JobName (contains)
|
||||||
return
|
|
||||||
} else {
|
} else {
|
||||||
http.Redirect(rw, r, "/monitoring/jobs/?jobId="+url.QueryEscape(strings.Trim(search, " ")), http.StatusTemporaryRedirect) // No Result: Probably jobId
|
http.Redirect(rw, r, "/monitoring/jobs/?jobId="+url.QueryEscape(strings.Trim(search, " ")), http.StatusTemporaryRedirect) // No Result: Probably jobId
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
http.Error(rw, "'searchId' query parameter malformed", http.StatusBadRequest)
|
log.Warnf("Searchbar query parameters malformed: %v", search)
|
||||||
|
http.Redirect(rw, r, "/monitoring/jobs/?", http.StatusTemporaryRedirect) // Unknown: Redirect to Tablequery
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,8 +10,9 @@
|
|||||||
let isOpen = false
|
let isOpen = false
|
||||||
|
|
||||||
const userviews = [
|
const userviews = [
|
||||||
{ title: 'My Jobs', href: `/monitoring/user/${username}`, icon: 'bar-chart-line-fill' },
|
{ title: 'My Jobs', href: `/monitoring/user/${username}`, icon: 'bar-chart-line-fill' },
|
||||||
{ title: 'Tags', href: '/monitoring/tags/', icon: 'tags' }
|
{ title: `Job Search`, href: '/monitoring/jobs/', icon: 'card-list' },
|
||||||
|
{ title: 'Tags', href: '/monitoring/tags/', icon: 'tags' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const managerviews = [
|
const managerviews = [
|
||||||
@ -91,9 +92,9 @@
|
|||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<form method="GET" action="/search">
|
<form method="GET" action="/search">
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<Input type="text" placeholder={(authlevel >= 4) ? "Search jobId / username" : "Search jobId"} name="searchId"/>
|
<Input type="text" placeholder={"Search 'type:<query>' ..."} name="searchId"/>
|
||||||
<Button outline type="submit"><Icon name="search"/></Button>
|
<Button outline type="submit"><Icon name="search"/></Button>
|
||||||
<InputGroupText style="cursor:help;" title={(authlevel >= 4) ? "Example: 'projectId:a100cd', Types are: jobId | jobName | projectId | username" | "name" : "Example: 'jobName:myjob', Types are jobId | jobName"}><Icon name="info-circle"/></InputGroupText>
|
<InputGroupText style="cursor:help;" title={(authlevel >= 4) ? "Example: 'projectId:a100cd', Types are: jobId | jobName | projectId | username | name" : "Example: 'jobName:myjob', Types are jobId | jobName | projectId"}><Icon name="info-circle"/></InputGroupText>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</form>
|
</form>
|
||||||
{#if username}
|
{#if username}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
const ccconfig = getContext('cc-config')
|
const ccconfig = getContext('cc-config')
|
||||||
|
|
||||||
export let filterPresets = {}
|
export let filterPresets = {}
|
||||||
|
export let authLevel
|
||||||
|
|
||||||
let filters, jobList, matchedJobs = null
|
let filters, jobList, matchedJobs = null
|
||||||
let sorting = { field: 'startTime', order: 'DESC' }, isSortingOpen = false, isMetricsSelectionOpen = false
|
let sorting = { field: 'startTime', order: 'DESC' }, isSortingOpen = false, isMetricsSelectionOpen = false
|
||||||
@ -60,7 +61,7 @@
|
|||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col xs="3" style="margin-left: auto;">
|
<Col xs="3" style="margin-left: auto;">
|
||||||
<UserOrProject on:update={({ detail }) => filters.update(detail)}/>
|
<UserOrProject bind:authLevel={authLevel} on:update={({ detail }) => filters.update(detail)}/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs="2">
|
<Col xs="2">
|
||||||
<Refresher on:reload={() => jobList.update()} />
|
<Refresher on:reload={() => jobList.update()} />
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
export let user = ''
|
export let user = ''
|
||||||
export let project = ''
|
export let project = ''
|
||||||
|
export let authLevel
|
||||||
let mode = 'user', term = ''
|
let mode = 'user', term = ''
|
||||||
const throttle = 500
|
const throttle = 500
|
||||||
|
|
||||||
@ -22,30 +23,53 @@
|
|||||||
|
|
||||||
let timeoutId = null
|
let timeoutId = null
|
||||||
function termChanged(sleep = throttle) {
|
function termChanged(sleep = throttle) {
|
||||||
if (mode == 'user')
|
if (authLevel == 2) {
|
||||||
user = term
|
|
||||||
else
|
|
||||||
project = term
|
project = term
|
||||||
|
|
||||||
if (timeoutId != null)
|
if (timeoutId != null)
|
||||||
clearTimeout(timeoutId)
|
clearTimeout(timeoutId)
|
||||||
|
|
||||||
timeoutId = setTimeout(() => {
|
timeoutId = setTimeout(() => {
|
||||||
dispatch('update', {
|
dispatch('update', {
|
||||||
user,
|
project
|
||||||
project
|
})
|
||||||
})
|
}, sleep)
|
||||||
}, sleep)
|
} else if (authLevel >= 3) {
|
||||||
|
if (mode == 'user')
|
||||||
|
user = term
|
||||||
|
else
|
||||||
|
project = term
|
||||||
|
|
||||||
|
if (timeoutId != null)
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
dispatch('update', {
|
||||||
|
user,
|
||||||
|
project
|
||||||
|
})
|
||||||
|
}, sleep)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<InputGroup>
|
{#if authLevel == 2}
|
||||||
<select style="max-width: 175px;" class="form-select"
|
<InputGroup>
|
||||||
bind:value={mode} on:change={modeChanged}>
|
<Input
|
||||||
<option value={'user'}>Search User</option>
|
type="text" bind:value={term} on:change={() => termChanged()} on:keyup={(event) => termChanged(event.key == 'Enter' ? 0 : throttle)} placeholder='filter project...'
|
||||||
<option value={'project'}>Search Project</option>
|
/>
|
||||||
</select>
|
</InputGroup>
|
||||||
<Input
|
{:else if authLevel >= 3}
|
||||||
type="text" bind:value={term} on:change={() => termChanged()} on:keyup={(event) => termChanged(event.key == 'Enter' ? 0 : throttle)}
|
<InputGroup>
|
||||||
placeholder={mode == 'user' ? 'filter username...' : 'filter project...'} />
|
<select style="max-width: 175px;" class="form-select"
|
||||||
</InputGroup>
|
bind:value={mode} on:change={modeChanged}>
|
||||||
|
<option value={'user'}>Search User</option>
|
||||||
|
<option value={'project'}>Search Project</option>
|
||||||
|
</select>
|
||||||
|
<Input
|
||||||
|
type="text" bind:value={term} on:change={() => termChanged()} on:keyup={(event) => termChanged(event.key == 'Enter' ? 0 : throttle)}
|
||||||
|
placeholder={mode == 'user' ? 'filter username...' : 'filter project...'} />
|
||||||
|
</InputGroup>
|
||||||
|
{:else}
|
||||||
|
Unauthorized
|
||||||
|
{/if}
|
@ -5,6 +5,7 @@ new Jobs({
|
|||||||
target: document.getElementById('svelte-app'),
|
target: document.getElementById('svelte-app'),
|
||||||
props: {
|
props: {
|
||||||
filterPresets: filterPresets,
|
filterPresets: filterPresets,
|
||||||
|
authLevel: authLevel
|
||||||
},
|
},
|
||||||
context: new Map([
|
context: new Map([
|
||||||
['cc-config', clusterCockpitConfig]
|
['cc-config', clusterCockpitConfig]
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<script>
|
<script>
|
||||||
const filterPresets = {{ .FilterPresets }};
|
const filterPresets = {{ .FilterPresets }};
|
||||||
const clusterCockpitConfig = {{ .Config }};
|
const clusterCockpitConfig = {{ .Config }};
|
||||||
|
const authLevel = {{ .User.AuthLevel }};
|
||||||
</script>
|
</script>
|
||||||
<script src='/build/jobs.js'></script>
|
<script src='/build/jobs.js'></script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
Loading…
Reference in New Issue
Block a user