From c1d06c5e5a4d7172cfe693a33ca36f8c2a32a5cd Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 7 Apr 2024 12:10:20 +0200 Subject: [PATCH] fix(projects): do not return parent project id of parents where the user does not have access This caused the frontend to not show such projects, throwing errors in the process and sometimes made it hang. --- pkg/models/label_rights.go | 2 +- pkg/models/project.go | 33 ++++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/pkg/models/label_rights.go b/pkg/models/label_rights.go index 2bd3e5823..8cd0a48c3 100644 --- a/pkg/models/label_rights.go +++ b/pkg/models/label_rights.go @@ -77,7 +77,7 @@ func (l *Label) hasAccessToLabel(s *xorm.Session, a web.Auth) (has bool, maxRigh builder. Select("id"). From("tasks"). - Where(builder.In("project_id", getUserProjectsStatement(nil, u.ID, "", false).Select("l.id"))), + Where(builder.In("project_id", getUserProjectsStatement(u.ID, "", false).Select("l.id"))), ) ll := &LabelTask{} diff --git a/pkg/models/project.go b/pkg/models/project.go index 44de667ad..05df0e681 100644 --- a/pkg/models/project.go +++ b/pkg/models/project.go @@ -368,7 +368,7 @@ type projectOptions struct { getArchived bool } -func getUserProjectsStatement(parentProjectIDs []int64, userID int64, search string, getArchived bool) *builder.Builder { +func getUserProjectsStatement(userID int64, search string, getArchived bool) *builder.Builder { dialect := db.GetDialect() // Adding a 1=1 condition by default here because xorm always needs a condition and cannot handle nil conditions @@ -413,18 +413,13 @@ func getUserProjectsStatement(parentProjectIDs []int64, userID int64, search str ), ) } - projectCol := "id" - if len(parentProjectIDs) > 0 { - parentCondition = builder.In("l.parent_project_id", parentProjectIDs) - projectCol = "parent_project_id" - } return builder.Dialect(dialect). Select("l.*"). From("projects", "l"). - Join("LEFT", "team_projects tl", "tl.project_id = l."+projectCol). + Join("LEFT", "team_projects tl", "tl.project_id = l.id"). Join("LEFT", "team_members tm2", "tm2.team_id = tl.team_id"). - Join("LEFT", "users_projects ul", "ul.project_id = l."+projectCol). + Join("LEFT", "users_projects ul", "ul.project_id = l.id"). Where(builder.And( builder.Or( builder.Eq{"tm2.user_id": userID}, @@ -434,7 +429,6 @@ func getUserProjectsStatement(parentProjectIDs []int64, userID int64, search str filterCond, getArchivedCond, parentCondition, - builder.NotIn("l.id", parentProjectIDs), )). GroupBy("l.id") } @@ -442,7 +436,7 @@ func getUserProjectsStatement(parentProjectIDs []int64, userID int64, search str func getAllProjectsForUser(s *xorm.Session, userID int64, opts *projectOptions) (projects []*Project, totalCount int64, err error) { limit, start := getLimitFromPageIndex(opts.page, opts.perPage) - query := getUserProjectsStatement(nil, userID, opts.search, opts.getArchived) + query := getUserProjectsStatement(userID, opts.search, opts.getArchived) querySQLString, args, err := query.ToSQL() if err != nil { @@ -459,9 +453,26 @@ UNION ALL SELECT p.* FROM projects p INNER JOIN all_projects ap ON p.parent_project_id = ap.id` + columnStr := strings.Join([]string{ + "all_projects.id", + "all_projects.title", + "all_projects.description", + "all_projects.identifier", + "all_projects.hex_color", + "all_projects.owner_id", + "CASE WHEN np.id IS NULL THEN 0 ELSE all_projects.parent_project_id END AS parent_project_id", + "all_projects.is_archived", + "all_projects.background_file_id", + "all_projects.background_blur_hash", + "all_projects.position", + "all_projects.created", + "all_projects.updated", + }, ", ") currentProjects := []*Project{} err = s.SQL(`WITH RECURSIVE all_projects as (`+baseQuery+`) -SELECT DISTINCT * FROM all_projects ORDER BY position `+limitSQL, args...).Find(¤tProjects) +SELECT DISTINCT `+columnStr+` FROM all_projects + LEFT JOIN all_projects np on all_projects.parent_project_id = np.id +ORDER BY all_projects.position `+limitSQL, args...).Find(¤tProjects) if err != nil { return }