forge
ExploreLog in

Tahinli/forge

public
0 watching
★ 0
4.5 KiB
1//! Router-level tests for the Security repo tab: it shows to people with Write on the repo, and
2//! only when advisories are enabled.
3
4use std::sync::Arc;
5
6use forge_core::{Role, Store, Visibility};
7use topcoat::router::request::Request;
8use topcoat::router::{Body, Router, to_bytes};
9
10use crate::auth::SESSION_COOKIE;
11
12/// The Security tab's link. The shell's settings menu also has a "Security" link, to
13/// `/settings/security`, so the text alone cannot tell the tab apart; the repo's href can.
14const SECURITY_TAB: &str = "href=\"/owner/proj/security\"";
15const CSRF: &str = "security-tab-test-csrf";
16
17struct Site {
18 router: Router,
19 store: Store,
20 _dir: tempfile::TempDir,
21}
22
23async fn site(advisories: bool) -> Site {
24 let dir = tempfile::tempdir().expect("tempdir");
25 let mut state = crate::test_support::test_state(dir.path()).await;
26 let mut config = crate::test_support::test_config(dir.path());
27 config.advisories.enabled = advisories;
28 state.config = Arc::new(config);
29 let store = state.store.clone();
30 let router = crate::test_support::app_router(state);
31 Site {
32 router,
33 store,
34 _dir: dir,
35 }
36}
37
38/// Signs `user_id` in and returns the session cookie header.
39async fn sign_in(store: &Store, user_id: &str, token: &str) -> String {
40 crate::test_support::create_session(store, user_id, token, CSRF).await;
41 format!("__Host-{SESSION_COOKIE}={token}")
42}
43
44async fn get(site: &Site, uri: &str, cookie: Option<&str>) -> (u16, String) {
45 let mut builder = Request::builder().method("GET").uri(uri);
46 if let Some(cookie) = cookie {
47 builder = builder.header("cookie", cookie);
48 }
49 let res = site
50 .router
51 .handle(builder.body(Body::from(String::new())).expect("request"))
52 .await;
53 let status = res.status().as_u16();
54 let bytes = to_bytes(res.into_body(), usize::MAX).await.expect("body");
55 (status, String::from_utf8_lossy(&bytes).into_owned())
56}
57
58/// A public repo `owner/proj`, with an owner and a plain reader who can read it.
59async fn fixture(site: &Site) -> (String, String) {
60 let owner = site
61 .store
62 .create_user("owner", None, "unused", false)
63 .await
64 .unwrap();
65 site.store
66 .create_repo(&owner.id, "proj", "", Visibility::Public, "main")
67 .await
68 .unwrap();
69 let owner_cookie = sign_in(&site.store, &owner.id, "owner-token").await;
70 let reader = site
71 .store
72 .create_user("reader", None, "unused", false)
73 .await
74 .unwrap();
75 let reader_cookie = sign_in(&site.store, &reader.id, "reader-token").await;
76 (owner_cookie, reader_cookie)
77}
78
79#[tokio::test]
80async fn security_tab_shows_to_the_owner_when_advisories_are_on() {
81 let site = site(true).await;
82 let (owner_cookie, _) = fixture(&site).await;
83 let (status, body) = get(&site, "/owner/proj/issues", Some(&owner_cookie)).await;
84 assert_eq!(status, 200);
85 assert!(
86 body.contains(SECURITY_TAB),
87 "owner should see the Security tab"
88 );
89 assert!(body.contains("/owner/proj/security"));
90}
91
92#[tokio::test]
93async fn security_tab_shows_to_write_collaborators() {
94 let site = site(true).await;
95 fixture(&site).await;
96 let writer = site
97 .store
98 .create_user("writer", None, "unused", false)
99 .await
100 .unwrap();
101 let repo = site
102 .store
103 .repo_by_owner_and_name("owner", "proj")
104 .await
105 .unwrap()
106 .expect("repo");
107 site.store
108 .set_collaborator(&repo.id, &writer.id, Role::Write)
109 .await
110 .unwrap();
111 let writer_cookie = sign_in(&site.store, &writer.id, "writer-token").await;
112 let (status, body) = get(&site, "/owner/proj/issues", Some(&writer_cookie)).await;
113 assert_eq!(status, 200);
114 assert!(
115 body.contains(SECURITY_TAB),
116 "a Write collaborator should see the tab"
117 );
118}
119
120#[tokio::test]
121async fn security_tab_is_hidden_from_readers() {
122 let site = site(true).await;
123 let (_, reader_cookie) = fixture(&site).await;
124 let (status, body) = get(&site, "/owner/proj/issues", Some(&reader_cookie)).await;
125 assert_eq!(status, 200);
126 assert!(
127 !body.contains(SECURITY_TAB),
128 "a reader must not see the tab"
129 );
130}
131
132#[tokio::test]
133async fn security_tab_is_hidden_when_advisories_are_off() {
134 let site = site(false).await;
135 let (owner_cookie, _) = fixture(&site).await;
136 let (status, body) = get(&site, "/owner/proj/issues", Some(&owner_cookie)).await;
137 assert_eq!(status, 200);
138 assert!(
139 !body.contains(SECURITY_TAB),
140 "no tab while advisories are off"
141 );
142}