big update in share links

This commit is contained in:
Mateusz Gruszczyński
2026-08-03 09:56:47 +02:00
parent e3ee6319b9
commit fe5d00fcdd
27 changed files with 434 additions and 176 deletions
+60 -6
View File
@@ -25,7 +25,8 @@ def query_sql(backend: str, name: str) -> str:
def main() -> None:
names = {
"SHARE_LINK_INSERT": 6,
"SHARE_LINK_INSERT": 7,
"SHARE_LINK_UPDATE": 6,
"SHARE_LINK_PERMISSION": 3,
"SHARE_LINK_SESSION_SOURCE": 3,
"SHARE_SESSION_INSERT": 5,
@@ -43,6 +44,8 @@ def main() -> None:
assert sorted(set(parameters)) == list(range(1, expected + 1)), (name, sql)
auth = read("src/auth/mod.rs")
register_response = auth[auth.index("pub struct RegisterResponse"):auth.index("pub async fn identity")]
assert "token:" not in register_response
assert ".bind(&token)" not in auth[auth.index("pub async fn create_share_link"):auth.index("pub async fn update_share_link")]
assert '"token":row.token' not in auth
assert "token: Option<String>" not in auth[auth.index("struct SharingLinkRow"):auth.index("struct ShareLinkSessionSource")]
@@ -55,10 +58,29 @@ def main() -> None:
assert 'format!("share-session-client:{client_key}")' in auth
create_link = auth[auth.index("pub async fn create_share_link"):auth.index("pub async fn update_share_link")]
assert "no-store, max-age=0" in create_link
assert '"token_hash":token_hash' in create_link
assert '"token":token' not in create_link
assert '"label":label' in create_link
create_session = auth[auth.index("pub async fn create_share_session"):auth.index("async fn share_session_permission")]
assert "existing_session_token" in create_session
assert 'source.permission == "ro"' in create_session
assert '== Some("rw")' in create_session
assert "existing_session_token" not in create_session
assert 'source.permission == "ro"' not in create_session
assert "resource_is_public_unprotected(state, kind, slug).await?" in create_session
assert create_session.index("resource_is_public_unprotected") < create_session.index("valid_share_token")
create_link = auth[auth.index("pub async fn create_share_link"):auth.index("pub async fn update_share_link")]
update_link = auth[auth.index("pub async fn update_share_link"):auth.index("pub async fn revoke_share_link")]
revoke_link = auth[auth.index("pub async fn revoke_share_link"):auth.index("fn validate_permission")]
for management_handler in (create_link, update_link, revoke_link):
assert "ensure_share_links_enabled" in management_handler
assert "Direct share links are disabled for public resources without a password." in auth
share_access = auth[auth.index("pub async fn share_access_permission"):auth.index("pub async fn share_link_permission")]
assert "resource_is_public_unprotected(state, kind, slug).await?" in share_access
sharing = auth[auth.index("pub async fn resource_sharing"):auth.index("pub async fn create_share_link")]
assert '"share_links_enabled":share_links_enabled' in sharing
assert "if share_links_enabled" in sharing
assert "Vec::new()" in sharing
privacy = auth[auth.index("pub async fn set_resource_privacy"):auth.index("pub async fn share_resource_users")]
assert "SHARE_LINK" not in privacy
assert "SHARE_SESSION" not in privacy
api = read("src/api/mod.rs")
assert "combined_token_access_level" not in api
@@ -68,7 +90,16 @@ def main() -> None:
access_tokens = read("src/api/access_tokens.rs")
assert "verify_password_access_token" in access_tokens
assert "share_access_permission" in access_tokens
assert "verify_resource_access_token" not in access_tokens
assert "workspace.password_hash.is_some()" in access_tokens
assert "pad.password_hash.is_some()" in access_tokens
database = read("src/db/mod.rs")
workspace_password = database[database.index("pub fn verify_workspace_password"):database.index("pub async fn list_notes")]
pad_password = database[database.index("pub fn verify_pad_password"):database.index("pub async fn save_pad_revision")]
assert "(None, _) => false" in workspace_password
assert "(None, _) => false" in pad_password
assert "missing_password_does_not_grant_password_access" in database
websocket = read("src/websocket/mod.rs") + read("src/websocket/pad.rs")
assert "cookie_share_session_token" in websocket
@@ -79,6 +110,9 @@ def main() -> None:
assert "access_refresh" in websocket
assert websocket.count("update=updates.recv()=>{") == 2
assert websocket.count('message:"Access expired or revoked"') >= 6
current_access = read("src/websocket/mod.rs")[read("src/websocket/mod.rs").index("async fn current_resource_access"):read("src/websocket/mod.rs").index("// Merged from note.rs")]
assert "resource_is_public_unprotected(state, kind, slug)" in current_access
assert "public_unprotected: bool" not in current_access
pages = read("src/app/pages.rs")
assert "canonical_resource_url" in pages
@@ -95,20 +129,40 @@ def main() -> None:
security = read("src/security.rs")
assert "__Host-rustpad_share_" in security
assert "HttpOnly; Secure; SameSite=Lax" in security
assert "clear_share_session_cookie" not in security
for backend in ("sqlite", "postgres", "mysql"):
sharing_list = query_sql(backend, "RESOURCE_SHARING_LINKS")
assert not re.search(r"(?:^|,)\s*(?:CAST\()?token\b", sharing_list)
legacy_migration = read(f"migrations/{backend}/0012_share_link_tokens.sql")
assert "ADD COLUMN token" not in legacy_migration
migration = read(f"migrations/{backend}/0026_share_link_sessions.sql")
assert "UPDATE resource_share_links SET token = NULL" in migration
assert "resource_share_links SET token" not in migration
assert "session_token_hash" in migration
assert "ON DELETE CASCADE" in migration
label_migration = read(f"migrations/{backend}/0027_share_link_labels.sql")
assert "ADD COLUMN label" in label_migration
home_js = read("static/js/home.js")
assert "createdLinkValues" in home_js
assert "result.token_hash" in home_js
assert "data-copy-link" in home_js
assert "The full address is not stored" in home_js
assert 'name="label"' in home_js
assert "token_hash: linkRow.dataset.linkTokenHash" in home_js
assert "Link created, displayed below and copied." in home_js
assert "data-direct-links-disabled" in home_js
assert "d.share_links_enabled !== false" in home_js
assert "Existing links are preserved and become active again" in home_js
workspace_js = read("static/js/workspace.js")
note_js = read("static/js/note-editor.js")
assert 'info.access_level === "none"' in workspace_js
assert note_js.count('info.access_level === "none"') >= 2
main_rs = read("src/main.rs")
assert "https://git.linuxiarz.pl/gru/rustpad/src/branch/master/LICENSE.md" in main_rs
app = read("src/app/mod.rs")
assert "PathOnlyMakeSpan" in app
assert "request.uri().path()" in app