scopes: tweak tests, add translations

Lewis: May this revision serve well! <did:plc:3fwecdnvtcscjnrx2p4n7alz>
This commit is contained in:
Lewis
2026-07-25 11:08:27 +03:00
committed by Tangled
parent 25d7d24d4e
commit aca78bb8d3
10 changed files with 199 additions and 5 deletions
+4 -1
View File
@@ -177,7 +177,10 @@ async fn test_external_did_web_no_local_doc() {
async fn reserve_signing_key(client: &reqwest::Client, base: &str, did: &str) -> String {
let res = client
.post(format!("{}/xrpc/com.atproto.server.reserveSigningKey", base))
.post(format!(
"{}/xrpc/com.atproto.server.reserveSigningKey",
base
))
.json(&json!({ "did": did }))
.send()
.await
+32 -2
View File
@@ -605,6 +605,7 @@ async fn test_oauth_multiple_clients_same_user() {
("redirect_uri", "https://client1.example.com/callback"),
("code_challenge", &challenge1),
("code_challenge_method", "S256"),
("scope", "atproto repo:app.bsky.feed.post?action=create"),
])
.send()
.await
@@ -631,7 +632,7 @@ async fn test_oauth_multiple_clients_same_user() {
let consent_res = http_client
.post(format!("{}/oauth/authorize/consent", url))
.header("Content-Type", "application/json")
.json(&json!({"request_uri": request_uri1, "approved_scopes": ["atproto", "transition:generic"], "remember": false}))
.json(&json!({"request_uri": request_uri1, "approved_scopes": ["atproto", "repo:app.bsky.feed.post?action=create"], "remember": false}))
.send().await.unwrap();
let consent_body: Value = consent_res.json().await.unwrap();
location1 = consent_body["redirect_uri"].as_str().unwrap().to_string();
@@ -666,6 +667,7 @@ async fn test_oauth_multiple_clients_same_user() {
("redirect_uri", "https://client2.example.com/callback"),
("code_challenge", &challenge2),
("code_challenge_method", "S256"),
("scope", "atproto repo:app.bsky.feed.post?action=create"),
])
.send()
.await
@@ -692,7 +694,7 @@ async fn test_oauth_multiple_clients_same_user() {
let consent_res = http_client
.post(format!("{}/oauth/authorize/consent", url))
.header("Content-Type", "application/json")
.json(&json!({"request_uri": request_uri2, "approved_scopes": ["atproto", "transition:generic"], "remember": false}))
.json(&json!({"request_uri": request_uri2, "approved_scopes": ["atproto", "repo:app.bsky.feed.post?action=create"], "remember": false}))
.send().await.unwrap();
let consent_body: Value = consent_res.json().await.unwrap();
location2 = consent_body["redirect_uri"].as_str().unwrap().to_string();
@@ -763,6 +765,33 @@ async fn test_oauth_multiple_clients_same_user() {
StatusCode::OK,
"Client 2 token should work"
);
let ungranted_collection = "app.bsky.graph.follow";
let denied_res = http_client
.post(format!("{}/xrpc/com.atproto.repo.createRecord", url))
.bearer_auth(token1)
.json(&json!({
"repo": user_did,
"collection": ungranted_collection,
"record": {
"$type": ungranted_collection,
"subject": user_did,
"createdAt": Utc::now().to_rfc3339()
}
}))
.send()
.await
.unwrap();
assert_eq!(
denied_res.status(),
StatusCode::FORBIDDEN,
"Client 1 token shouldn't write outside its granted collection"
);
let denied_body: Value = denied_res.json().await.unwrap();
assert_eq!(
denied_body["error"].as_str(),
Some("InsufficientScope"),
"Write outside the granted collection should fail on scope"
);
let list_res = http_client
.get(format!("{}/xrpc/com.atproto.repo.listRecords", url))
.bearer_auth(token1)
@@ -770,6 +799,7 @@ async fn test_oauth_multiple_clients_same_user() {
.send()
.await
.unwrap();
assert_eq!(list_res.status(), StatusCode::OK, "listRecords should work");
let list_body: Value = list_res.json().await.unwrap();
let records = list_body["records"].as_array().unwrap();
assert_eq!(
+2 -1
View File
@@ -609,7 +609,8 @@
"malformed": "This bundle's name is not a valid identifier, so it cannot be granted.",
"not_a_permission_set": "This identifier does not refer to a permission bundle, so it cannot be granted.",
"malformed_lexicon": "This bundle is published incorrectly and cannot be granted.",
"empty_permissions": "This bundle does not currently grant any permissions."
"empty_permissions": "This bundle does not currently grant any permissions.",
"unknown": "This bundle cannot be granted."
},
"permTable": {
"data": "Data",
+23
View File
@@ -603,6 +603,29 @@
"permissionsRequested": "Pyydetyt oikeudet",
"required": "Vaaditaan",
"rememberChoiceLabel": "Muista valintani tälle sovellukselle",
"permissionSets": "Oikeuspaketit",
"showIncludedScopes": "Näytä sisältyvät oikeudet ({count})",
"unavailablePermissions": "Ei käytettävissä olevat oikeudet",
"unavailableLimited": "Delegoinnin rajoittama",
"unavailableFailed": "Lataus epäonnistui",
"setPartiallyLimited": "Delegointisi rajoittaa osaa tämän paketin oikeuksista. Kohta \"Ei käytettävissä olevat oikeudet\" kertoo, mitä ei sallittu.",
"setFailureReason": {
"not_found": "Pakettia ei löytynyt, joten sitä ei voi myöntää.",
"unreachable": "Paketin julkaisijaan ei saatu yhteyttä, joten sitä ei voi nyt myöntää.",
"malformed": "Paketin nimi ei ole kelvollinen tunniste, joten sitä ei voi myöntää.",
"not_a_permission_set": "Tunniste ei viittaa oikeuspakettiin, joten sitä ei voi myöntää.",
"malformed_lexicon": "Paketti on julkaistu virheellisesti, joten sitä ei voi myöntää.",
"empty_permissions": "Paketti ei myönnä tällä hetkellä yhtään oikeutta.",
"unknown": "Pakettia ei voi myöntää."
},
"permTable": {
"data": "Tiedot",
"create": "Luonti",
"update": "Päivitys",
"delete": "Poisto",
"allData": "Kaikki kokoelmat",
"apiAccess": "API-käyttö"
},
"scopes": {
"atproto": {
"name": "AT Protocol -käyttöoikeus",
+23
View File
@@ -597,6 +597,29 @@
"permissionsRequested": "Permissions demandées",
"required": "Requis",
"rememberChoiceLabel": "Se souvenir de mon choix pour cette application",
"permissionSets": "Ensembles de permissions",
"showIncludedScopes": "Afficher les permissions incluses ({count})",
"unavailablePermissions": "Permissions indisponibles",
"unavailableLimited": "Limité par la délégation",
"unavailableFailed": "Échec du chargement",
"setPartiallyLimited": "Votre délégation limite certaines permissions de cet ensemble. La section « Permissions indisponibles » indique lesquelles ont été refusées.",
"setFailureReason": {
"not_found": "Cet ensemble est introuvable et ne peut pas être accordé.",
"unreachable": "L'éditeur de cet ensemble est injoignable, il ne peut donc pas être accordé pour le moment.",
"malformed": "Le nom de cet ensemble n'est pas un identifiant valide, il ne peut donc pas être accordé.",
"not_a_permission_set": "Cet identifiant ne désigne pas un ensemble de permissions, il ne peut donc pas être accordé.",
"malformed_lexicon": "Cet ensemble est publié de façon incorrecte et ne peut pas être accordé.",
"empty_permissions": "Cet ensemble n'accorde actuellement aucune permission.",
"unknown": "Cet ensemble ne peut pas être accordé."
},
"permTable": {
"data": "Données",
"create": "Créer",
"update": "Modifier",
"delete": "Supprimer",
"allData": "Toutes les collections",
"apiAccess": "Accès API"
},
"scopes": {
"atproto": {
"name": "Accès AT Protocol",
+23
View File
@@ -603,6 +603,29 @@
"permissionsRequested": "リクエストされた権限",
"required": "必須",
"rememberChoiceLabel": "このアプリに対する選択を記憶する",
"permissionSets": "権限バンドル",
"showIncludedScopes": "含まれる権限を表示 ({count})",
"unavailablePermissions": "利用できない権限",
"unavailableLimited": "委任による制限",
"unavailableFailed": "読み込み失敗",
"setPartiallyLimited": "このバンドルの一部の権限は委任設定により制限されています。許可されなかった権限は「利用できない権限」で確認できます。",
"setFailureReason": {
"not_found": "このバンドルは見つからないため、付与できません。",
"unreachable": "バンドルの公開元に接続できないため、現在は付与できません。",
"malformed": "このバンドルの名前が有効な識別子ではないため、付与できません。",
"not_a_permission_set": "この識別子は権限バンドルを指していないため、付与できません。",
"malformed_lexicon": "このバンドルは正しく公開されていないため、付与できません。",
"empty_permissions": "このバンドルは現在、権限を付与しません。",
"unknown": "このバンドルは付与できません。"
},
"permTable": {
"data": "データ",
"create": "作成",
"update": "更新",
"delete": "削除",
"allData": "すべてのコレクション",
"apiAccess": "API アクセス"
},
"scopes": {
"atproto": {
"name": "AT Protocol アクセス",
+23
View File
@@ -603,6 +603,29 @@
"permissionsRequested": "요청된 권한",
"required": "필수",
"rememberChoiceLabel": "이 앱에 대한 선택 기억하기",
"permissionSets": "권한 번들",
"showIncludedScopes": "포함된 권한 보기 ({count})",
"unavailablePermissions": "사용할 수 없는 권한",
"unavailableLimited": "위임으로 제한됨",
"unavailableFailed": "불러오기 실패",
"setPartiallyLimited": "위임 설정이 이 번들의 일부 권한을 제한합니다. 허용되지 않은 권한은 \"사용할 수 없는 권한\" 항목에서 확인하세요.",
"setFailureReason": {
"not_found": "이 번들을 찾을 수 없어 부여할 수 없습니다.",
"unreachable": "번들 게시자에 연결할 수 없어 지금은 부여할 수 없습니다.",
"malformed": "이 번들의 이름이 유효한 식별자가 아니어서 부여할 수 없습니다.",
"not_a_permission_set": "이 식별자는 권한 번들을 가리키지 않아 부여할 수 없습니다.",
"malformed_lexicon": "이 번들이 잘못 게시되어 부여할 수 없습니다.",
"empty_permissions": "이 번들은 현재 어떤 권한도 부여하지 않습니다.",
"unknown": "이 번들은 부여할 수 없습니다."
},
"permTable": {
"data": "데이터",
"create": "생성",
"update": "수정",
"delete": "삭제",
"allData": "모든 컬렉션",
"apiAccess": "API 접근"
},
"scopes": {
"atproto": {
"name": "AT Protocol 액세스",
+23
View File
@@ -603,6 +603,29 @@
"permissionsRequested": "Begärda behörigheter",
"required": "Krävs",
"rememberChoiceLabel": "Kom ihåg mitt val för denna applikation",
"permissionSets": "Behörighetspaket",
"showIncludedScopes": "Visa inkluderade behörigheter ({count})",
"unavailablePermissions": "Otillgängliga behörigheter",
"unavailableLimited": "Begränsad av delegering",
"unavailableFailed": "Kunde inte laddas",
"setPartiallyLimited": "Din delegering begränsar vissa behörigheter i paketet. Avsnittet \"Otillgängliga behörigheter\" visar vilka som nekades.",
"setFailureReason": {
"not_found": "Paketet hittades inte och kan inte beviljas.",
"unreachable": "Paketets utgivare kunde inte nås, så paketet kan inte beviljas just nu.",
"malformed": "Paketets namn är inte en giltig identifierare, så det kan inte beviljas.",
"not_a_permission_set": "Identifieraren avser inte ett behörighetspaket, så det kan inte beviljas.",
"malformed_lexicon": "Paketet är felaktigt publicerat och kan inte beviljas.",
"empty_permissions": "Paketet beviljar för närvarande inga behörigheter.",
"unknown": "Paketet kan inte beviljas."
},
"permTable": {
"data": "Data",
"create": "Skapa",
"update": "Uppdatera",
"delete": "Radera",
"allData": "Alla samlingar",
"apiAccess": "API-åtkomst"
},
"scopes": {
"atproto": {
"name": "AT Protocol-åtkomst",
+23
View File
@@ -603,6 +603,29 @@
"permissionsRequested": "请求的权限",
"required": "必需",
"rememberChoiceLabel": "记住对此应用的授权选择",
"permissionSets": "权限包",
"showIncludedScopes": "显示包含的权限 ({count})",
"unavailablePermissions": "不可用权限",
"unavailableLimited": "受委托限制",
"unavailableFailed": "加载失败",
"setPartiallyLimited": "您的委托设置限制了此权限包中的部分权限。“不可用权限”一节列出了未被允许的权限。",
"setFailureReason": {
"not_found": "找不到此权限包,无法授予。",
"unreachable": "无法连接此权限包的发布方,目前无法授予。",
"malformed": "此权限包的名称不是有效标识符,无法授予。",
"not_a_permission_set": "此标识符并非指向权限包,无法授予。",
"malformed_lexicon": "此权限包发布有误,无法授予。",
"empty_permissions": "此权限包目前不授予任何权限。",
"unknown": "此权限包无法授予。"
},
"permTable": {
"data": "数据",
"create": "创建",
"update": "更新",
"delete": "删除",
"allData": "所有集合",
"apiAccess": "API 访问"
},
"scopes": {
"atproto": {
"name": "AT Protocol 访问",
+23 -1
View File
@@ -44,6 +44,28 @@
restricted?: boolean
}
type SetFailureReason =
| 'unreachable'
| 'not_found'
| 'malformed'
| 'not_a_permission_set'
| 'malformed_lexicon'
| 'empty_permissions'
const SET_FAILURE_LOCALE_KEYS: Record<SetFailureReason, string> = {
unreachable: 'oauth.consent.setFailureReason.unreachable',
not_found: 'oauth.consent.setFailureReason.not_found',
malformed: 'oauth.consent.setFailureReason.malformed',
not_a_permission_set: 'oauth.consent.setFailureReason.not_a_permission_set',
malformed_lexicon: 'oauth.consent.setFailureReason.malformed_lexicon',
empty_permissions: 'oauth.consent.setFailureReason.empty_permissions',
}
function setFailureLocaleKey(reason: string): string {
const known: Partial<Record<string, string>> = SET_FAILURE_LOCALE_KEYS
return known[reason] ?? 'oauth.consent.setFailureReason.unknown'
}
interface FailedSetInfo {
nsid: string
aud?: string
@@ -572,7 +594,7 @@
<div class="scope-item failed">
<div class="scope-info">
<span class="scope-name">{f.nsid}{#if f.aud} ({f.aud}){/if}</span>
<span class="scope-description">{$_(`oauth.consent.setFailureReason.${f.reason}`)}</span>
<span class="scope-description">{$_(setFailureLocaleKey(f.reason))}</span>
</div>
</div>
{/each}