|
|
|
|
@@ -95,6 +95,10 @@ pub async fn serve(addr: &str, state: AppState) -> anyhow::Result<()> {
|
|
|
|
|
// plugin will do with any of it. It puts `cmd` and `reqId` on the object and forwards it,
|
|
|
|
|
// exactly as it forwards a link code.
|
|
|
|
|
.route("/permissions/sync", post(perm_sync))
|
|
|
|
|
// Protocol 13 (D160): the whole store, owners included, in pages. The body is
|
|
|
|
|
// `{snapshotId?, page?}` and is forwarded as it is; paging is the plugin's and the
|
|
|
|
|
// website's business, never this process's, which keeps no copy of any page.
|
|
|
|
|
.route("/permissions/inventory", post(perm_inventory))
|
|
|
|
|
// Protocol 5 (R18): the plugin's own view of the game host's configuration tree. All
|
|
|
|
|
// three are correlated round trips and all three fail when the game is down, because
|
|
|
|
|
// "what is on that host's disk" has no stale answer worth giving — and, unlike a board,
|
|
|
|
|
@@ -435,6 +439,13 @@ async fn perm_sync(State(st): State<AppState>, Json(body): Json<Value>) -> Respo
|
|
|
|
|
respond(st.rpc.call(&st.game, command, &req_id).await)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// One page of the plugin's permission inventory (protocol 13). Page 0 without a `snapshotId`
|
|
|
|
|
/// starts a fresh read; any other page names the snapshot page 0 answered with. A `perm.error`
|
|
|
|
|
/// (`busy`, `stale`, `too-large`) is an answer, and arrives as a `200` like the sync's.
|
|
|
|
|
async fn perm_inventory(State(st): State<AppState>, Json(body): Json<Value>) -> Response {
|
|
|
|
|
forward_object(&st, body, "perm.inventory", "an inventory request").await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
struct ConfigPathQuery {
|
|
|
|
|
path: String,
|
|
|
|
|
@@ -1081,6 +1092,20 @@ mod tests {
|
|
|
|
|
assert!(stamp(json!(["9"]), "tally.close", "r-4").is_none());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Protocol 13: an inventory page request keeps its paging fields and cannot become a sync.
|
|
|
|
|
#[test]
|
|
|
|
|
fn an_inventory_request_cannot_choose_its_own_command() {
|
|
|
|
|
let body =
|
|
|
|
|
json!({ "cmd": "perm.sync", "reqId": "theirs", "snapshotId": "abc123", "page": 2 });
|
|
|
|
|
let stamped = stamp(body, "perm.inventory", "r-7").expect("an object is stamped");
|
|
|
|
|
|
|
|
|
|
assert_eq!(stamped["cmd"], "perm.inventory");
|
|
|
|
|
assert_eq!(stamped["reqId"], "r-7");
|
|
|
|
|
assert_eq!(stamped["snapshotId"], "abc123");
|
|
|
|
|
assert_eq!(stamped["page"], 2);
|
|
|
|
|
assert!(stamp(json!([0]), "perm.inventory", "r-8").is_none());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Protocol 12: a title set is forwarded whole. The markup inside each `text` is the module's
|
|
|
|
|
/// and the plugin's business, so it must arrive byte for byte as the website composed it.
|
|
|
|
|
#[test]
|
|
|
|
|
|