Description
I propose to create a new table (user_repo_units
) to summarize all permissions a user requires to access any repository; this table should be derived from all the possible permission sources (e.g. team membership, admin status, repo visibility, repo active units, etc.). Any changes in the system that modifies the user's accessibility to any repo should update said table. Then, many queries can use the table for user access checking instead of a complex set of golang-side code.
The table would have a structure like:
type UserRepoUnits struct {
UserID int64 `xorm:"pk"`
RepoID int64 `xorm:"pk INDEX"`
Type UnitType
Mode AccessMode
}
Units accessible for all users (e.g. UnitTypeCode
on public repositories) will not have a record for each user but one for the user 0
instead (may be -1
is better?). This should reduce the number of records in the table considerably.
Advantages
- Access checks would be centralized in a few functions, much easier to maintain.
- Most queries can be simplified considerably, especially for the home page.
- It will improve the performance of the more frequent actions (e.g. home page, issue list, etc), rather than the infrequent permission modifications.
- Bulk processes (like notifications) can retrieve a valid list of users with a single query instead of multiple complex steps.
- Simplified access checks means less likely to leak information inadvertently.
Usage
The table can then be used in queries. For example, to get all open issues (UnitTypeIssues
= 2) the user 1234
can see (AccessModeRead
= 1), we could do:
select issue.*
from issue
where (select max(mode) from user_repo_units
where user_repo_units.repository_id = issue.repository_id
and user_repo_units.user_id in (1234, 0)
and user_repo_units.type = 2) >= 1;
and issue.is_closed = false;
No team membership check required, no ownership or admin check required. All in the same (pretty much standardized) query.
Alternatives
- We could use a column for each unit type instead of separate records. This would reduce the number of records (and speed up the queries even more) at a little additional cost on maintainability.