Skip to content
Clone

fix(repo): enforce per-repo Read authz on all read-side usecases (H2)

zhenyi committed
parent aaf1302 commit c298621 Browse files

16 files changed

+151 −70

File tree 16
Modified lib/repo/features/archive/usecase.rs View lib/repo/features/archive/usecase.rs
@@ -1,20 +1,20 @@
1use crate::actor::RepoAccess;
12use crate::error::{RepoError, RepoResult};
2use crate::features::RepoService;
3use crate::features::{authz, RepoService};
34use crate::metrics;
45
56use super::ArchiveFormatQuery;
67
78pub async fn get_archive(
8 _svc: &RepoService,
9 svc: &RepoService,
910 actor: uuid::Uuid,
10 _repo_id: uuid::Uuid,
11 repo_id: uuid::Uuid,
1112 archive_format: &str,
1213 ref_name: &str,
1314 _q: ArchiveFormatQuery,
1415) -> RepoResult<Vec<u8>> {
1516 let _timer = metrics::Timer::start(metrics::FEATURE_ARCHIVES_GET);
1617 let result: RepoResult<Vec<u8>> = async {
17 let _ = actor;
1818 match archive_format {
1919 "tarball" | "zipball" | "bundle" => {}
2020 other => {
@@ -26,6 +26,8 @@
2626 if ref_name.is_empty() {
2727 return Err(RepoError::BadRequest("ref is required".into()));
2828 }
29 let repo = authz::load_repo_by_id(svc, repo_id).await?;
30 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
2931 Err(RepoError::Internal(
3032 "archive generation requires lib/git rewire (in progress)".into(),
3133 ))
Modified lib/repo/features/branch/usecase.rs View lib/repo/features/branch/usecase.rs
@@ -37,7 +37,8 @@
3737) -> RepoResult<BranchPage> {
3838 let _timer = metrics::Timer::start(metrics::FEATURE_BRANCHES_LIST);
3939 let result: RepoResult<BranchPage> = async {
40 let _ = actor;
40 let repo = authz::load_repo_by_id(svc, repo_id).await?;
41 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
4142 let limit = q.limit.unwrap_or(svc.config.default_pagination);
4243 let offset = q.page.unwrap_or(0).saturating_mul(limit);
4344 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -78,7 +79,8 @@
7879) -> RepoResult<BranchView> {
7980 let _timer = metrics::Timer::start(metrics::FEATURE_BRANCHES_GET);
8081 let result: RepoResult<BranchView> = async {
81 let _ = actor;
82 let repo = authz::load_repo_by_id(svc, repo_id).await?;
83 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
8284 let branch = load_branch(svc, repo_id, name).await?;
8385 Ok(BranchView::from(branch))
8486 }
@@ -232,7 +234,6 @@
232234 } else {
233235 "merge".to_string()
234236 };
235 let _ = actor;
236237 Ok(MergeUpstreamResponse { merge_type })
237238 }
238239 .await;
Modified lib/repo/features/branch_protection/usecase.rs View lib/repo/features/branch_protection/usecase.rs
@@ -38,7 +38,8 @@
3838) -> RepoResult<BranchProtectionPage> {
3939 let _timer = metrics::Timer::start(metrics::FEATURE_BRANCH_PROTECTIONS_LIST);
4040 let result: RepoResult<BranchProtectionPage> = async {
41 let _ = actor;
41 let repo = authz::load_repo_by_id(svc, repo_id).await?;
42 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
4243 let limit = q.limit.unwrap_or(svc.config.default_pagination);
4344 let offset = q.page.unwrap_or(0).saturating_mul(limit);
4445 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -115,7 +116,8 @@
115116) -> RepoResult<BranchProtectionView> {
116117 let _timer = metrics::Timer::start(metrics::FEATURE_BRANCH_PROTECTIONS_GET);
117118 let result: RepoResult<BranchProtectionView> = async {
118 let _ = actor;
119 let repo = authz::load_repo_by_id(svc, repo_id).await?;
120 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
119121 let policy = load_policy(svc, repo_id, policy_id).await?;
120122 Ok(BranchProtectionView::from(policy))
121123 }
Modified lib/repo/features/collab/usecase.rs View lib/repo/features/collab/usecase.rs
@@ -40,7 +40,8 @@
4040) -> RepoResult<CollaboratorPage> {
4141 let _timer = metrics::Timer::start(metrics::FEATURE_COLLAB_LIST);
4242 let result: RepoResult<CollaboratorPage> = async {
43 let _ = actor;
43 let repo = authz::load_repo_by_id(svc, repo_id).await?;
44 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
4445 let limit = limit.unwrap_or(svc.config.default_pagination);
4546 let offset = page.unwrap_or(0).saturating_mul(limit);
4647 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -73,7 +74,8 @@
7374) -> RepoResult<bool> {
7475 let _timer = metrics::Timer::start(metrics::FEATURE_COLLAB_IS_COLLABORATOR);
7576 let result: RepoResult<bool> = async {
76 let _ = actor;
77 let repo = authz::load_repo_by_id(svc, repo_id).await?;
78 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
7779 let db = svc.db.reader();
7880 let hit = collab_entity::Entity::find()
7981 .filter(collab_entity::Column::RepoId.eq(repo_id))
@@ -160,7 +162,8 @@
160162) -> RepoResult<RepoCollaboratorPermission> {
161163 let _timer = metrics::Timer::start(metrics::FEATURE_COLLAB_GET_REPO_PERMISSIONS);
162164 let result: RepoResult<RepoCollaboratorPermission> = async {
163 let _ = actor;
165 let repo = authz::load_repo_by_id(svc, repo_id).await?;
166 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
164167 let db = svc.db.reader();
165168 let collab = collab_entity::Entity::find()
166169 .filter(collab_entity::Column::RepoId.eq(repo_id))
Modified lib/repo/features/commit_status/usecase.rs View lib/repo/features/commit_status/usecase.rs
@@ -46,7 +46,8 @@
4646) -> RepoResult<CommitStatusPage> {
4747 let _timer = metrics::Timer::start(metrics::FEATURE_COMMIT_STATUSES_LIST);
4848 let result: RepoResult<CommitStatusPage> = async {
49 let _ = actor;
49 let repo = authz::load_repo_by_id(svc, repo_id).await?;
50 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
5051 let limit = q.limit.unwrap_or(svc.config.default_pagination);
5152 let offset = q.page.unwrap_or(0).saturating_mul(limit);
5253 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -121,7 +122,8 @@
121122) -> RepoResult<CommitStatusPage> {
122123 let _timer = metrics::Timer::start(metrics::FEATURE_COMMIT_STATUSES_LIST_BY_REF);
123124 let result: RepoResult<CommitStatusPage> = async {
124 let _ = actor;
125 let repo = authz::load_repo_by_id(svc, repo_id).await?;
126 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
125127 let sha = resolve_ref(svc, repo_id, git_ref).await?;
126128 list_commit_statuses(svc, actor, repo_id, &sha, q).await
127129 }
@@ -138,7 +140,8 @@
138140) -> RepoResult<CombinedStatusView> {
139141 let _timer = metrics::Timer::start(metrics::FEATURE_COMMIT_STATUSES_COMBINED_BY_REF);
140142 let result: RepoResult<CombinedStatusView> = async {
141 let _ = actor;
143 let repo = authz::load_repo_by_id(svc, repo_id).await?;
144 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
142145 let sha = resolve_ref(svc, repo_id, git_ref).await?;
143146 let db = svc.db.reader();
144147 let items = status_entity::Entity::find()
Modified lib/repo/features/compare/usecase.rs View lib/repo/features/compare/usecase.rs
@@ -1,22 +1,24 @@
1use crate::actor::RepoAccess;
12use crate::error::{RepoError, RepoResult};
2use crate::features::RepoService;
3use crate::features::{authz, RepoService};
34use crate::metrics;
45
56use super::CompareView;
67
78pub async fn compare(
8 _svc: &RepoService,
9 svc: &RepoService,
910 actor: uuid::Uuid,
10 _repo_id: uuid::Uuid,
11 repo_id: uuid::Uuid,
1112 base: &str,
1213 head: &str,
1314) -> RepoResult<CompareView> {
1415 let _timer = metrics::Timer::start(metrics::FEATURE_COMPARE);
1516 let result: RepoResult<CompareView> = async {
16 let _ = actor;
1717 if base.is_empty() || head.is_empty() {
1818 return Err(RepoError::BadRequest("base and head are required".into()));
1919 }
20 let repo = authz::load_repo_by_id(svc, repo_id).await?;
21 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
2022 Err(RepoError::Internal(
2123 "compare requires lib/git rewire (in progress)".into(),
2224 ))
Modified lib/repo/features/contents/usecase.rs View lib/repo/features/contents/usecase.rs
@@ -11,15 +11,16 @@
1111};
1212
1313pub async fn list_contents(
14 _svc: &RepoService,
14 svc: &RepoService,
1515 actor: Uuid,
16 _repo_id: Uuid,
16 repo_id: Uuid,
1717 path: &str,
1818 _q: ContentsQuery,
1919) -> RepoResult<ContentsListResponse> {
2020 let _timer = metrics::Timer::start(metrics::FEATURE_CONTENTS_LIST);
2121 let result: RepoResult<ContentsListResponse> = async {
22 let _ = actor;
22 let repo = authz::load_repo_by_id(svc, repo_id).await?;
23 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
2324 let _ = path;
2425 Err(RepoError::Internal(
2526 "contents listing requires lib/git rewire (in progress)".into(),
@@ -31,15 +32,16 @@
3132}
3233
3334pub async fn get_contents(
34 _svc: &RepoService,
35 svc: &RepoService,
3536 actor: Uuid,
36 _repo_id: Uuid,
37 repo_id: Uuid,
3738 path: &str,
3839 _q: ContentsQuery,
3940) -> RepoResult<ContentsResponse> {
4041 let _timer = metrics::Timer::start(metrics::FEATURE_CONTENTS_GET);
4142 let result: RepoResult<ContentsResponse> = async {
42 let _ = actor;
43 let repo = authz::load_repo_by_id(svc, repo_id).await?;
44 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
4345 let _ = path;
4446 Err(RepoError::Internal(
4547 "contents read requires lib/git rewire (in progress)".into(),
Modified lib/repo/features/deploy_key/usecase.rs View lib/repo/features/deploy_key/usecase.rs
@@ -30,7 +30,8 @@
3030) -> RepoResult<DeployKeyPage> {
3131 let _timer = metrics::Timer::start(metrics::FEATURE_DEPLOY_KEYS_LIST);
3232 let result: RepoResult<DeployKeyPage> = async {
33 let _ = actor;
33 let repo = authz::load_repo_by_id(svc, repo_id).await?;
34 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
3435 let limit = q.limit.unwrap_or(svc.config.default_pagination);
3536 let offset = q.page.unwrap_or(0).saturating_mul(limit);
3637 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -69,7 +70,8 @@
6970) -> RepoResult<DeployKeyView> {
7071 let _timer = metrics::Timer::start(metrics::FEATURE_DEPLOY_KEYS_GET);
7172 let result: RepoResult<DeployKeyView> = async {
72 let _ = actor;
73 let repo = authz::load_repo_by_id(svc, repo_id).await?;
74 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
7375 let key = load_key(svc, repo_id, key_id).await?;
7476 Ok(DeployKeyView::from(key))
7577 }
Modified lib/repo/features/git_ref/usecase.rs View lib/repo/features/git_ref/usecase.rs
@@ -1,17 +1,19 @@
1use crate::actor::RepoAccess;
12use crate::error::{RepoError, RepoResult};
2use crate::features::RepoService;
3use crate::features::{authz, RepoService};
34use crate::metrics;
45
56use super::{BlobView, CommitDiffPayload, CommitView, GitRef, NoteView, TreeView};
67
78pub async fn list_git_refs(
8 _svc: &RepoService,
9 svc: &RepoService,
910 actor: uuid::Uuid,
10 _repo_id: uuid::Uuid,
11 repo_id: uuid::Uuid,
1112) -> RepoResult<Vec<GitRef>> {
1213 let _timer = metrics::Timer::start(metrics::FEATURE_GIT_REFS_LIST);
1314 let result: RepoResult<Vec<GitRef>> = async {
14 let _ = actor;
15 let repo = authz::load_repo_by_id(svc, repo_id).await?;
16 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
1517 Err(RepoError::Internal(
1618 "list refs requires lib/git rewire (in progress)".into(),
1719 ))
@@ -22,14 +24,15 @@
2224}
2325
2426pub async fn filter_git_refs(
25 _svc: &RepoService,
27 svc: &RepoService,
2628 actor: uuid::Uuid,
27 _repo_id: uuid::Uuid,
29 repo_id: uuid::Uuid,
2830 _filter: &str,
2931) -> RepoResult<Vec<GitRef>> {
3032 let _timer = metrics::Timer::start(metrics::FEATURE_GIT_REFS_FILTER);
3133 let result: RepoResult<Vec<GitRef>> = async {
32 let _ = actor;
34 let repo = authz::load_repo_by_id(svc, repo_id).await?;
35 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
3336 Err(RepoError::Internal(
3437 "filter refs requires lib/git rewire (in progress)".into(),
3538 ))
@@ -40,17 +43,18 @@
4043}
4144
4245pub async fn get_commit(
43 _svc: &RepoService,
46 svc: &RepoService,
4447 actor: uuid::Uuid,
45 _repo_id: uuid::Uuid,
48 repo_id: uuid::Uuid,
4649 sha: &str,
4750) -> RepoResult<CommitView> {
4851 let _timer = metrics::Timer::start(metrics::FEATURE_GIT_REFS_GET_COMMIT);
4952 let result: RepoResult<CommitView> = async {
50 let _ = actor;
5153 if sha.is_empty() {
5254 return Err(RepoError::BadRequest("sha is required".into()));
5355 }
56 let repo = authz::load_repo_by_id(svc, repo_id).await?;
57 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
5458 Err(RepoError::Internal(
5559 "get_commit requires lib/git rewire (in progress)".into(),
5660 ))
@@ -61,15 +65,14 @@
6165}
6266
6367pub async fn get_commit_diff_or_patch(
64 _svc: &RepoService,
68 svc: &RepoService,
6569 actor: uuid::Uuid,
66 _repo_id: uuid::Uuid,
70 repo_id: uuid::Uuid,
6771 sha: &str,
6872 diff_type: &str,
6973) -> RepoResult<CommitDiffPayload> {
7074 let _timer = metrics::Timer::start(metrics::FEATURE_GIT_REFS_GET_COMMIT_DIFF_OR_PATCH);
7175 let result: RepoResult<CommitDiffPayload> = async {
72 let _ = actor;
7376 if diff_type != "diff" && diff_type != "patch" {
7477 return Err(RepoError::BadRequest(format!(
7578 "unsupported diff format: {diff_type}"
@@ -78,6 +81,8 @@
7881 if sha.is_empty() {
7982 return Err(RepoError::BadRequest("sha is required".into()));
8083 }
84 let repo = authz::load_repo_by_id(svc, repo_id).await?;
85 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
8186 Err(RepoError::Internal(
8287 "get_commit_diff_or_patch requires lib/git rewire (in progress)".into(),
8388 ))
@@ -88,18 +93,19 @@
8893}
8994
9095pub async fn get_tree(
91 _svc: &RepoService,
96 svc: &RepoService,
9297 actor: uuid::Uuid,
93 _repo_id: uuid::Uuid,
98 repo_id: uuid::Uuid,
9499 sha: &str,
95100 _recursive: bool,
96101) -> RepoResult<TreeView> {
97102 let _timer = metrics::Timer::start(metrics::FEATURE_GIT_REFS_GET_TREE);
98103 let result: RepoResult<TreeView> = async {
99 let _ = actor;
100104 if sha.is_empty() {
101105 return Err(RepoError::BadRequest("sha is required".into()));
102106 }
107 let repo = authz::load_repo_by_id(svc, repo_id).await?;
108 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
103109 Err(RepoError::Internal(
104110 "get_tree requires lib/git rewire (in progress)".into(),
105111 ))
@@ -110,17 +116,18 @@
110116}
111117
112118pub async fn get_blob(
113 _svc: &RepoService,
119 svc: &RepoService,
114120 actor: uuid::Uuid,
115 _repo_id: uuid::Uuid,
121 repo_id: uuid::Uuid,
116122 sha: &str,
117123) -> RepoResult<BlobView> {
118124 let _timer = metrics::Timer::start(metrics::FEATURE_GIT_REFS_GET_BLOB);
119125 let result: RepoResult<BlobView> = async {
120 let _ = actor;
121126 if sha.is_empty() {
122127 return Err(RepoError::BadRequest("sha is required".into()));
123128 }
129 let repo = authz::load_repo_by_id(svc, repo_id).await?;
130 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
124131 Err(RepoError::Internal(
125132 "get_blob requires lib/git rewire (in progress)".into(),
126133 ))
@@ -131,17 +138,18 @@
131138}
132139
133140pub async fn get_note(
134 _svc: &RepoService,
141 svc: &RepoService,
135142 actor: uuid::Uuid,
136 _repo_id: uuid::Uuid,
143 repo_id: uuid::Uuid,
137144 sha: &str,
138145) -> RepoResult<NoteView> {
139146 let _timer = metrics::Timer::start(metrics::FEATURE_GIT_REFS_GET_NOTE);
140147 let result: RepoResult<NoteView> = async {
141 let _ = actor;
142148 if sha.is_empty() {
143149 return Err(RepoError::BadRequest("sha is required".into()));
144150 }
151 let repo = authz::load_repo_by_id(svc, repo_id).await?;
152 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
145153 Err(RepoError::Internal(
146154 "get_note requires lib/git rewire (in progress)".into(),
147155 ))
Modified lib/repo/features/pull_request/usecase.rs View lib/repo/features/pull_request/usecase.rs
@@ -17,8 +17,9 @@
1717use time::OffsetDateTime;
1818use uuid::Uuid;
1919
20use crate::actor::RepoAccess;
2021use crate::error::{RepoError, RepoResult};
21use crate::features::RepoService;
22use crate::features::{authz, RepoService};
2223use crate::metrics;
2324use crate::path::{git_bare_path, validate_branch_name};
2425
@@ -327,7 +328,8 @@
327328) -> RepoResult<PullRequestPage> {
328329 let _timer = metrics::Timer::start(metrics::FEATURE_PULL_REQUESTS_LIST);
329330 let result: RepoResult<PullRequestPage> = async {
330 let _ = actor;
331 let repo = authz::load_repo_by_id(svc, repo_id).await?;
332 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
331333 let limit = query.limit.unwrap_or(svc.config.default_pagination);
332334 let offset = query.page.unwrap_or(0).saturating_mul(limit);
333335 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -388,7 +390,8 @@
388390) -> RepoResult<PullRequestView> {
389391 let _timer = metrics::Timer::start(metrics::FEATURE_PULL_REQUESTS_GET);
390392 let result: RepoResult<PullRequestView> = async {
391 let _ = actor;
393 let repo = authz::load_repo_by_id(svc, repo_id).await?;
394 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
392395 let pr = load_pr(svc, repo_id, number).await?;
393396 let pr = heal_merged(svc, repo_id, &pr).await;
394397 Ok(PullRequestView::from(pr))
@@ -837,7 +840,8 @@
837840) -> RepoResult<Vec<PullRequestCommentView>> {
838841 let _timer = metrics::Timer::start(metrics::FEATURE_PULL_REQUESTS_LIST_COMMENTS);
839842 let result: RepoResult<Vec<PullRequestCommentView>> = async {
840 let _ = actor;
843 let repo = authz::load_repo_by_id(svc, repo_id).await?;
844 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
841845 let pr = load_pr(svc, repo_id, number).await?;
842846 let db = svc.db.reader();
843847 let items: Vec<PullRequestCommentView> = comment_entity::Entity::find()
@@ -910,7 +914,8 @@
910914) -> RepoResult<Vec<PullRequestReviewView>> {
911915 let _timer = metrics::Timer::start(metrics::FEATURE_PULL_REQUESTS_LIST_REVIEWS);
912916 let result: RepoResult<Vec<PullRequestReviewView>> = async {
913 let _ = actor;
917 let repo = authz::load_repo_by_id(svc, repo_id).await?;
918 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
914919 let pr = load_pr(svc, repo_id, number).await?;
915920 let db = svc.db.reader();
916921 let items: Vec<PullRequestReviewView> = review_entity::Entity::find()
@@ -936,7 +941,8 @@
936941) -> RepoResult<Vec<PullRequestEventView>> {
937942 let _timer = metrics::Timer::start(metrics::FEATURE_PULL_REQUESTS_LIST_EVENTS);
938943 let result: RepoResult<Vec<PullRequestEventView>> = async {
939 let _ = actor;
944 let repo = authz::load_repo_by_id(svc, repo_id).await?;
945 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
940946 let pr = load_pr(svc, repo_id, number).await?;
941947 let db = svc.db.reader();
942948 let items: Vec<PullRequestEventView> = event_entity::Entity::find()
Modified lib/repo/features/release/usecase.rs View lib/repo/features/release/usecase.rs
@@ -35,7 +35,8 @@
3535) -> RepoResult<ReleasePage> {
3636 let _timer = metrics::Timer::start(metrics::FEATURE_RELEASES_LIST);
3737 let result: RepoResult<ReleasePage> = async {
38 let _ = actor;
38 let repo = authz::load_repo_by_id(svc, repo_id).await?;
39 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
3940 let limit = q.limit.unwrap_or(svc.config.default_pagination);
4041 let offset = q.page.unwrap_or(0).saturating_mul(limit);
4142 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -77,7 +78,8 @@
7778) -> RepoResult<ReleaseView> {
7879 let _timer = metrics::Timer::start(metrics::FEATURE_RELEASES_GET);
7980 let result: RepoResult<ReleaseView> = async {
80 let _ = actor;
81 let repo = authz::load_repo_by_id(svc, repo_id).await?;
82 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
8183 let release = load_release(svc, repo_id, release_id).await?;
8284 Ok(ReleaseView::from(release))
8385 }
@@ -93,7 +95,8 @@
9395) -> RepoResult<ReleaseView> {
9496 let _timer = metrics::Timer::start(metrics::FEATURE_RELEASES_GET_LATEST);
9597 let result: RepoResult<ReleaseView> = async {
96 let _ = actor;
98 let repo = authz::load_repo_by_id(svc, repo_id).await?;
99 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
97100 let db = svc.db.reader();
98101 let release = release_entity::Entity::find()
99102 .filter(release_entity::Column::RepoId.eq(repo_id))
@@ -118,7 +121,8 @@
118121) -> RepoResult<ReleaseView> {
119122 let _timer = metrics::Timer::start(metrics::FEATURE_RELEASES_GET_BY_TAG);
120123 let result: RepoResult<ReleaseView> = async {
121 let _ = actor;
124 let repo = authz::load_repo_by_id(svc, repo_id).await?;
125 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
122126 let db = svc.db.reader();
123127 let release = release_entity::Entity::find()
124128 .filter(release_entity::Column::RepoId.eq(repo_id))
Modified lib/repo/features/subscriber/usecase.rs View lib/repo/features/subscriber/usecase.rs
@@ -1,8 +1,9 @@
11use db::conn::sea_orm::*;
22use db::repo::repo_watch as watch_entity;
33
4use crate::actor::RepoAccess;
45use crate::error::RepoResult;
5use crate::features::RepoService;
6use crate::features::{authz, RepoService};
67use crate::metrics;
78
89use super::{ListSubscriberQuery, SubscriberPage, SubscriberView};
@@ -15,7 +16,8 @@
1516) -> RepoResult<SubscriberPage> {
1617 let _timer = metrics::Timer::start(metrics::FEATURE_SUBSCRIBERS_LIST);
1718 let result: RepoResult<SubscriberPage> = async {
18 let _ = actor;
19 let repo = authz::load_repo_by_id(svc, repo_id).await?;
20 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
1921 let limit = q.limit.unwrap_or(svc.config.default_pagination);
2022 let offset = q.page.unwrap_or(0).saturating_mul(limit);
2123 let limit = std::cmp::min(limit, svc.config.max_pagination);
Modified lib/repo/features/sync/usecase.rs View lib/repo/features/sync/usecase.rs
@@ -18,7 +18,8 @@
1818) -> RepoResult<SyncStatus> {
1919 let _timer = metrics::Timer::start(metrics::FEATURE_SYNC_GET_STATUS);
2020 let result: RepoResult<SyncStatus> = async {
21 let _ = actor;
21 let repo = authz::load_repo_by_id(svc, repo_id).await?;
22 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
2223 let db = svc.db.reader();
2324 let branches_total = branch_entity::Entity::find()
2425 .filter(branch_entity::Column::RepoId.eq(repo_id))
Modified lib/repo/features/tag/usecase.rs View lib/repo/features/tag/usecase.rs
@@ -31,7 +31,8 @@
3131) -> RepoResult<TagPage> {
3232 let _timer = metrics::Timer::start(metrics::FEATURE_TAGS_LIST);
3333 let result: RepoResult<TagPage> = async {
34 let _ = actor;
34 let repo = authz::load_repo_by_id(svc, repo_id).await?;
35 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
3536 let limit = q.limit.unwrap_or(svc.config.default_pagination);
3637 let offset = q.page.unwrap_or(0).saturating_mul(limit);
3738 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -65,7 +66,8 @@
6566) -> RepoResult<TagView> {
6667 let _timer = metrics::Timer::start(metrics::FEATURE_TAGS_GET);
6768 let result: RepoResult<TagView> = async {
68 let _ = actor;
69 let repo = authz::load_repo_by_id(svc, repo_id).await?;
70 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
6971 let tag = load_tag(svc, repo_id, name).await?;
7072 Ok(TagView::from(tag))
7173 }
Modified lib/repo/features/tag_protection/usecase.rs View lib/repo/features/tag_protection/usecase.rs
@@ -48,7 +48,8 @@
4848) -> RepoResult<TagProtectionPage> {
4949 let _timer = metrics::Timer::start(metrics::FEATURE_TAG_PROTECTIONS_LIST);
5050 let result: RepoResult<TagProtectionPage> = async {
51 let _ = actor;
51 let repo = authz::load_repo_by_id(svc, repo_id).await?;
52 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
5253 let limit = q.limit.unwrap_or(svc.config.default_pagination);
5354 let offset = q.page.unwrap_or(0).saturating_mul(limit);
5455 let limit = std::cmp::min(limit, svc.config.max_pagination);
@@ -114,7 +115,8 @@
114115) -> RepoResult<TagProtectionView> {
115116 let _timer = metrics::Timer::start(metrics::FEATURE_TAG_PROTECTIONS_GET);
116117 let result: RepoResult<TagProtectionView> = async {
117 let _ = actor;
118 let repo = authz::load_repo_by_id(svc, repo_id).await?;
119 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
118120 let policy = load_policy(svc, repo_id, policy_id).await?;
119121 Ok(TagProtectionView::from(policy))
120122 }
Modified lib/repo/features/topic/usecase.rs View lib/repo/features/topic/usecase.rs
@@ -37,7 +37,8 @@
3737) -> RepoResult<TopicList> {
3838 let _timer = metrics::Timer::start(metrics::FEATURE_TOPICS_LIST);
3939 let result: RepoResult<TopicList> = async {
40 let _ = actor;
40 let repo = authz::load_repo_by_id(svc, repo_id).await?;
41 authz::authorize_repo(svc, actor, &repo, RepoAccess::Read).await?;
4142 let db = svc.db.reader();
4243 let links = db::repo::repo_relation_topic::Entity::find()
4344 .filter(db::repo::repo_relation_topic::Column::RepoId.eq(repo_id))
@@ -196,12 +197,50 @@
196197) -> RepoResult<TopicSearchResult> {
197198 let _timer = metrics::Timer::start(metrics::FEATURE_TOPICS_SEARCH);
198199 let result: RepoResult<TopicSearchResult> = async {
199 let _ = actor;
200 let db = svc.db.reader();
201 let visible_topic_ids: std::collections::HashSet<Uuid> = {
202 let (visible_channels, collab_repos) =
203 authz::visible_repo_scope(svc, actor).await?;
204 let mut link_query = db::repo::repo_relation_topic::Entity::find();
205 let mut cond = Condition::any();
206 if !visible_channels.is_empty() {
207 let repos_in_channels: Vec<Uuid> = db::repo::repos::Entity::find()
208 .select_only()
209 .column(db::repo::repos::Column::Id)
210 .filter(db::repo::repos::Column::ChannelId.is_in(visible_channels))
211 .into_tuple::<Uuid>()
212 .all(&db)
213 .await?;
214 if !repos_in_channels.is_empty() {
215 cond = cond.add(
216 db::repo::repo_relation_topic::Column::RepoId.is_in(repos_in_channels),
217 );
218 }
219 }
220 if !collab_repos.is_empty() {
221 cond = cond.add(
222 db::repo::repo_relation_topic::Column::RepoId.is_in(collab_repos),
223 );
224 }
225 if cond.is_empty() {
226 return Ok(TopicSearchResult { topics: vec![] });
227 }
228 link_query = link_query.filter(cond);
229 link_query
230 .all(&db)
231 .await?
232 .into_iter()
233 .map(|l| l.topic_id)
234 .collect()
235 };
236 if visible_topic_ids.is_empty() {
237 return Ok(TopicSearchResult { topics: vec![] });
238 }
200239 let limit = q.limit.unwrap_or(svc.config.default_pagination);
201240 let offset = q.page.unwrap_or(0).saturating_mul(limit);
202241 let limit = std::cmp::min(limit, svc.config.max_pagination);
203 let db = svc.db.reader();
204 let mut query = topic_entity::Entity::find();
242 let mut query = topic_entity::Entity::find()
243 .filter(topic_entity::Column::Id.is_in(visible_topic_ids));
205244 if let Some(s) = q.q.as_deref() {
206245 if !s.is_empty() {
207246 query = query.filter(topic_entity::Column::Name.contains(s));