From 68efe871c7d3e7a884635158f3d0c792e8922202 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Mon, 20 Feb 2023 11:24:18 +0100 Subject: [PATCH] Centralize project filter for manager role - Remove all unnecessary frontend code for managerfilters --- api/schema.graphqls | 1 - internal/graph/generated/generated.go | 43 +------------------------ internal/graph/model/models_gen.go | 1 - internal/repository/query.go | 22 ++++++------- internal/routerConfig/routes.go | 7 +--- web/frontend/src/Jobs.root.svelte | 4 --- web/frontend/src/List.root.svelte | 15 --------- web/frontend/src/filters/Filters.svelte | 6 ---- web/frontend/src/joblist/JobList.svelte | 22 ------------- web/frontend/src/jobs.entrypoint.js | 2 -- web/frontend/src/list.entrypoint.js | 2 -- web/templates/base.tmpl | 1 - web/templates/monitoring/jobs.tmpl | 2 -- web/templates/monitoring/list.tmpl | 2 -- web/web.go | 5 ++- 15 files changed, 14 insertions(+), 121 deletions(-) diff --git a/api/schema.graphqls b/api/schema.graphqls index 04224aa..bf41eac 100644 --- a/api/schema.graphqls +++ b/api/schema.graphqls @@ -202,7 +202,6 @@ input JobFilter { arrayJobId: Int user: StringInput project: StringInput - multiProject: [String] cluster: StringInput partition: StringInput duration: IntRange diff --git a/internal/graph/generated/generated.go b/internal/graph/generated/generated.go index 4e19fa4..1710ade 100644 --- a/internal/graph/generated/generated.go +++ b/internal/graph/generated/generated.go @@ -1583,7 +1583,6 @@ input JobFilter { arrayJobId: Int user: StringInput project: StringInput - multiProject: [String] cluster: StringInput partition: StringInput duration: IntRange @@ -10390,7 +10389,7 @@ func (ec *executionContext) unmarshalInputJobFilter(ctx context.Context, obj int asMap[k] = v } - fieldsInOrder := [...]string{"tags", "jobId", "arrayJobId", "user", "project", "multiProject", "cluster", "partition", "duration", "minRunningFor", "numNodes", "numAccelerators", "numHWThreads", "startTime", "state", "flopsAnyAvg", "memBwAvg", "loadAvg", "memUsedMax"} + fieldsInOrder := [...]string{"tags", "jobId", "arrayJobId", "user", "project", "cluster", "partition", "duration", "minRunningFor", "numNodes", "numAccelerators", "numHWThreads", "startTime", "state", "flopsAnyAvg", "memBwAvg", "loadAvg", "memUsedMax"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -10437,14 +10436,6 @@ func (ec *executionContext) unmarshalInputJobFilter(ctx context.Context, obj int if err != nil { return it, err } - case "multiProject": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("multiProject")) - it.MultiProject, err = ec.unmarshalOString2ᚕᚖstring(ctx, v) - if err != nil { - return it, err - } case "cluster": var err error @@ -14591,38 +14582,6 @@ func (ec *executionContext) marshalOString2ᚕstringᚄ(ctx context.Context, sel return ret } -func (ec *executionContext) unmarshalOString2ᚕᚖstring(ctx context.Context, v interface{}) ([]*string, error) { - if v == nil { - return nil, nil - } - var vSlice []interface{} - if v != nil { - vSlice = graphql.CoerceList(v) - } - var err error - res := make([]*string, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalOString2ᚖstring(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalOString2ᚕᚖstring(ctx context.Context, sel ast.SelectionSet, v []*string) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - for i := range v { - ret[i] = ec.marshalOString2ᚖstring(ctx, sel, v[i]) - } - - return ret -} - func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { if v == nil { return nil, nil diff --git a/internal/graph/model/models_gen.go b/internal/graph/model/models_gen.go index 88a497a..cb3d901 100644 --- a/internal/graph/model/models_gen.go +++ b/internal/graph/model/models_gen.go @@ -42,7 +42,6 @@ type JobFilter struct { ArrayJobID *int `json:"arrayJobId"` User *StringInput `json:"user"` Project *StringInput `json:"project"` - MultiProject []*string `json:"multiProject"` Cluster *StringInput `json:"cluster"` Partition *StringInput `json:"partition"` Duration *schema.IntRange `json:"duration"` diff --git a/internal/repository/query.go b/internal/repository/query.go index 7e2a2e3..bcf69f6 100644 --- a/internal/repository/query.go +++ b/internal/repository/query.go @@ -101,13 +101,18 @@ func (r *JobRepository) CountJobs( func SecurityCheck(ctx context.Context, query sq.SelectBuilder) (queryOut sq.SelectBuilder, err error) { user := auth.GetUser(ctx) - if user == nil || user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleSupport, auth.RoleApi}) { + if user == nil || user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleSupport, auth.RoleApi}) { // Admin & Co. : All jobs return query, nil - } else if user.HasRole(auth.RoleManager) { // Manager (Might be doublefiltered by frontend: should not matter) - return query.Where(sq.Or{sq.Eq{"job.project": user.Projects}}), nil // Only Jobs from manages projects - } else if user.HasRole(auth.RoleUser) { // User + } else if user.HasRole(auth.RoleManager) { // Manager : Add filter for managed projects' jobs only + personal jobs + if len(user.Projects) != 0 { + return query.Where(sq.Or{sq.Eq{"job.project": user.Projects}, sq.Eq{"job.user": user.Username}}), nil + } else { + log.Infof("Manager-User '%s' has no defined projects to lookup! Query only personal jobs ...", user.Username) + return query.Where("job.user = ?", user.Username), nil + } + } else if user.HasRole(auth.RoleUser) { // User : Only personal jobs return query.Where("job.user = ?", user.Username), nil - } else { // Unauthorized + } else { // Unauthorized : Error var qnil sq.SelectBuilder return qnil, errors.New(fmt.Sprintf("User '%s' with unknown roles! [%#v]\n", user.Username, user.Roles)) } @@ -130,13 +135,6 @@ func BuildWhereClause(filter *model.JobFilter, query sq.SelectBuilder) sq.Select if filter.Project != nil { query = buildStringCondition("job.project", filter.Project, query) } - if filter.MultiProject != nil { - queryProjs := make([]string, len(filter.MultiProject)) - for i, val := range filter.MultiProject { - queryProjs[i] = *val - } - query = query.Where(sq.Or{sq.Eq{"job.project": queryProjs}}) - } if filter.Cluster != nil { query = buildStringCondition("job.cluster", filter.Cluster, query) } diff --git a/internal/routerConfig/routes.go b/internal/routerConfig/routes.go index 2c718b5..9bd7d30 100644 --- a/internal/routerConfig/routes.go +++ b/internal/routerConfig/routes.go @@ -188,9 +188,6 @@ func buildFilterPresets(query url.Values) map[string]interface{} { filterPresets["project"] = query.Get("project") filterPresets["projectMatch"] = "eq" } - if len(query["multiProject"]) != 0 { - filterPresets["multiProject"] = query["multiProject"] - } if query.Get("user") != "" { filterPresets["user"] = query.Get("user") filterPresets["userMatch"] = "eq" @@ -282,17 +279,15 @@ func SetupRoutes(router *mux.Router, version string, hash string, buildTime stri } username, authLevel := "", 0 - var projects []string if user := auth.GetUser(r.Context()); user != nil { username = user.Username - projects = user.Projects authLevel = user.GetAuthLevel() } page := web.Page{ Title: title, - User: web.User{Username: username, Projects: projects, AuthLevel: authLevel}, + User: web.User{Username: username, AuthLevel: authLevel}, Build: web.Build{Version: version, Hash: hash, Buildtime: buildTime}, Config: conf, Infos: infos, diff --git a/web/frontend/src/Jobs.root.svelte b/web/frontend/src/Jobs.root.svelte index 2d617c0..9ecaafa 100644 --- a/web/frontend/src/Jobs.root.svelte +++ b/web/frontend/src/Jobs.root.svelte @@ -14,8 +14,6 @@ const ccconfig = getContext('cc-config') export let filterPresets = {} - export let projects = [] - export let isManager = false let filters, jobList, matchedJobs = null let sorting = { field: 'startTime', order: 'DESC' }, isSortingOpen = false, isMetricsSelectionOpen = false @@ -72,8 +70,6 @@ { $stats.variables = { filter: detail.filters } - if (projectsFilter != null) { - $stats.variables.filter.push(projectsFilter) - } $stats.context.pause = false $stats.reexecute() }} /> diff --git a/web/frontend/src/filters/Filters.svelte b/web/frontend/src/filters/Filters.svelte index fa9fe0c..c8d3063 100644 --- a/web/frontend/src/filters/Filters.svelte +++ b/web/frontend/src/filters/Filters.svelte @@ -45,7 +45,6 @@ arrayJobId: filterPresets.arrayJobId || null, user: filterPresets.user || '', project: filterPresets.project || '', - multiProject: filterPresets.multiProject || [], numNodes: filterPresets.numNodes || { from: null, to: null }, numHWThreads: filterPresets.numHWThreads || { from: null, to: null }, @@ -95,8 +94,6 @@ items.push({ user: { [filters.userMatch]: filters.user } }) if (filters.project) items.push({ project: { [filters.projectMatch]: filters.project } }) - if (filters.multiProject.length != 0) - items.push({ multiProject: filters.multiProject }) for (let stat of filters.stats) items.push({ [stat.field]: { from: stat.from, to: stat.to } }) @@ -132,9 +129,6 @@ opts.push(`userMatch=${filters.userMatch}`) if (filters.project) opts.push(`project=${filters.project}`) - if (filters.multiProject.length != 0) - for (let singleProj of filters.multiProject) - opts.push(`multiProject=${singleProj}`) if (filters.projectMatch != 'contains') opts.push(`projectMatch=${filters.projectMatch}`) diff --git a/web/frontend/src/joblist/JobList.svelte b/web/frontend/src/joblist/JobList.svelte index 65fcc33..abead1a 100644 --- a/web/frontend/src/joblist/JobList.svelte +++ b/web/frontend/src/joblist/JobList.svelte @@ -23,25 +23,12 @@ export let sorting = { field: "startTime", order: "DESC" } export let matchedJobs = 0 export let metrics = ccconfig.plot_list_selectedMetrics - export let projects = [] - export let isManager let itemsPerPage = ccconfig.plot_list_jobsPerPage let page = 1 let paging = { itemsPerPage, page } let filter = [] - //Setup default filter - if (isManager == true && projects.length == 0) { - filter.push({ project: {eq: "noProjectForManager"} }) - } else if (isManager == true && projects.length == 1) { - filter.push({ project: {eq: projects[0]} }) - } else { - filter.push({ multiProject: projects }) - } - - - const jobs = operationStore(` query($filter: [JobFilter!]!, $sorting: OrderByInput!, $paging: PageRequest! ){ jobs(filter: $filter, order: $sorting, page: $paging) { @@ -81,15 +68,6 @@ filters.push({ minRunningFor }) } - // (Re-)Add Manager-Filter - if (isManager == true && projects.length == 0) { - filter.push({ project: {eq: "noProjectForManager"} }) - } else if (isManager == true && projects.length == 1) { - filter.push({ project: {eq: projects[0]} }) - } else { - filter.push({ multiProject: projects }) - } - $jobs.variables.filter = filters // console.log('filters:', ...filters.map(f => Object.entries(f)).flat(2)) } diff --git a/web/frontend/src/jobs.entrypoint.js b/web/frontend/src/jobs.entrypoint.js index 9008796..61c9796 100644 --- a/web/frontend/src/jobs.entrypoint.js +++ b/web/frontend/src/jobs.entrypoint.js @@ -5,8 +5,6 @@ new Jobs({ target: document.getElementById('svelte-app'), props: { filterPresets: filterPresets, - projects: projects, - isManager: isManager }, context: new Map([ ['cc-config', clusterCockpitConfig] diff --git a/web/frontend/src/list.entrypoint.js b/web/frontend/src/list.entrypoint.js index 068adf1..21c8f5d 100644 --- a/web/frontend/src/list.entrypoint.js +++ b/web/frontend/src/list.entrypoint.js @@ -6,8 +6,6 @@ new List({ props: { filterPresets: filterPresets, type: listType, - projects: projects, - isManager: isManager }, context: new Map([ ['cc-config', clusterCockpitConfig] diff --git a/web/templates/base.tmpl b/web/templates/base.tmpl index 6fcc5d2..f1a90c3 100644 --- a/web/templates/base.tmpl +++ b/web/templates/base.tmpl @@ -16,7 +16,6 @@ {{end}} diff --git a/web/templates/monitoring/list.tmpl b/web/templates/monitoring/list.tmpl index 21d2428..0c1994e 100644 --- a/web/templates/monitoring/list.tmpl +++ b/web/templates/monitoring/list.tmpl @@ -10,8 +10,6 @@ const listType = {{ .Infos.listType }}; const filterPresets = {{ .FilterPresets }}; const clusterCockpitConfig = {{ .Config }}; - const projects = {{ .User.Projects }}; - const isManager = {{ eq .User.AuthLevel 3 }}; {{end}} diff --git a/web/web.go b/web/web.go index caea84f..acf5bed 100644 --- a/web/web.go +++ b/web/web.go @@ -54,9 +54,8 @@ func init() { } type User struct { - Username string // Username of the currently logged in user - Projects []string // Project(s) of the user (relevant for managers only) - AuthLevel int // Level of authorization + Username string // Username of the currently logged in user + AuthLevel int // Level of authorization } type Build struct {