Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

Commit

Search's repo: on work items answers of a private repository as of one that is not there, to who may not read it

repo:
and -repo: on work items matched any linked repository by name, read or not, so a workspace member could learn a private repository's name and which items it is linked to. The linked repository now takes the same visibility check as every repository row.
G1T-Session:
ses_01m56w3nnce54skbep969amaqy
syntaqxcommitted Parent8d94448Browse files
2 files+23−40/2 viewed
+15−0
239239 assert_eq!(found(&db, "is:open label:bug", &viewer), vec![1, 2, 3]);
240240 }
241241
242+ #[test]
243+ fn repo_names_a_private_repository_only_to_who_may_read_it() {
244+ let db = filled();
245+ // A member who reads none of acme's private repositories sees every
246+ // work item, but repo: answers of acme/api as of one that is not there.
247+ let viewer = member(BasePermission::None);
248+ assert_eq!(found(&db, "crash repo:acme/api", &viewer), found(&db, "crash repo:acme/nope", &viewer));
249+ assert_eq!(found(&db, "crash -repo:acme/api", &viewer), found(&db, "crash -repo:acme/nope", &viewer));
250+ assert_eq!(found(&db, "crash -repo:acme/api", &viewer), vec![1, 2, 3]);
251+ // Given a role on it, it is there.
252+ let granted = Some(User { workspaces: vec![Membership::member("acme")], ..outsider(&["rep_api"]).unwrap() });
253+ assert_eq!(found(&db, "crash repo:acme/api", &granted), vec![2]);
254+ assert_eq!(found(&db, "crash -repo:acme/api", &granted), vec![1, 3]);
255+ }
256+
242257 fn numbers_count(db: &Connection, sql: &Sql) -> i64 {
243258 db.query_row(&sql.text, rusqlite::params_from_iter(values(&sql.params)), |row| row.get(0)).unwrap()
244259 }
+8−4
327327
328328 /// What every query of work items starts with: the visibility check (a
329329 /// member of the workspace, or a reader of the origin), then `repo:`
330−/// (any repository it is linked to), `org:` (its workspace) and
331−/// `is:public`/`is:private` (whether its origin is public).
330+/// (any repository it is linked to that the reader may see: one they may
331+/// not is answered as one that does not exist, so neither `repo:` nor
332+/// `-repo:` says a private repository is there), `org:` (its workspace)
333+/// and `is:public`/`is:private` (whether its origin is public).
332334 fn item_scope(query: &Query, reader: &Reader) -> Where {
333335 let mut out = Where::default();
334336 out.add(
336338 vec![Param::Text(reader.members_json()), Param::Text(reader.namespaces_json()), Param::Text(reader.granted_json())],
337339 );
338340 let linked = "SELECT 1 FROM repos lr WHERE (lr.namespace || '/' || lr.name) IN (SELECT value FROM json_each(?)) AND instr(i.repos, '|' || lr.repo_id || '|') > 0";
341+ let linked = format!("{linked} AND {}", clause("lr"));
342+ let named = |names: &[String]| vec![json(names), Param::Text(reader.namespaces_json()), Param::Text(reader.granted_json())];
339343 if !query.repos.include.is_empty() {
340− out.add(format!("EXISTS ({linked})"), vec![json(&query.repos.include)]);
344+ out.add(format!("EXISTS ({linked})"), named(&query.repos.include));
341345 }
342346 if !query.repos.exclude.is_empty() {
343− out.add(format!("NOT EXISTS ({linked})"), vec![json(&query.repos.exclude)]);
347+ out.add(format!("NOT EXISTS ({linked})"), named(&query.repos.exclude));
344348 }
345349 in_list(&query.owners, "i.workspace", &mut out);
346350 match query.visibility {

Comments

Sign in to comment.