AGC 认证续期失败不再降级成字符串
- refresh_session_inner 的非权威失败直接返回 Err(ClientAuthError),不再折成 error_message 字符串 - ClientAuthStateView 删除 error_message 字段,状态收窄为 authenticated / unauthenticated - ClientAuthRefreshView 删除 error_message 与 failed 状态,authoritative 只在未登录时为 true - read_client_auth_state 把续期失败原样透传给命令出口,不再投影出 unavailable 第三态
This commit is contained in:
@@ -49,14 +49,12 @@ const AUTH_AUTHORITY_MESSAGE: &str = "登录状态已失效,请重新登录";
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ClientAuthStateView {
|
||||
/// `authenticated` / `unauthenticated` / `unavailable`。
|
||||
/// `authenticated` / `unauthenticated`。
|
||||
pub(crate) status: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) user: Option<AuthUserPayload>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) api_base_url: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
@@ -66,18 +64,17 @@ pub(crate) struct ClientLoginCodeView {
|
||||
pub(crate) expires_in_seconds: u64,
|
||||
}
|
||||
|
||||
/// 续期结果。`stale` 表示续期期间身份已经变化,调用方不得重放旧身份请求。
|
||||
/// 续期结果。`stale` 表示续期期间身份已经变化,调用方不得重放旧身份请求;
|
||||
/// 非权威失败(网络 / 5xx / 契约异常)不在这里降级成字符串,直接以 `Err(ClientAuthError)` 返回。
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ClientAuthRefreshView {
|
||||
/// `refreshed` / `unauthenticated` / `stale` / `failed`。
|
||||
/// `refreshed` / `unauthenticated` / `stale`。
|
||||
pub(crate) status: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) user: Option<AuthUserPayload>,
|
||||
#[serde(default)]
|
||||
pub(crate) authoritative: bool,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
@@ -808,7 +805,6 @@ fn auth_state_view(
|
||||
status: status.to_string(),
|
||||
user,
|
||||
api_base_url,
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -886,7 +882,6 @@ async fn refresh_session_inner(
|
||||
status: "unauthenticated".to_string(),
|
||||
user: None,
|
||||
authoritative: true,
|
||||
error_message: None,
|
||||
});
|
||||
};
|
||||
let _guard = refresh_lock().lock().await;
|
||||
@@ -902,7 +897,6 @@ async fn refresh_session_inner(
|
||||
status: "refreshed".to_string(),
|
||||
user: Some(user),
|
||||
authoritative: false,
|
||||
error_message: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -934,15 +928,11 @@ async fn refresh_session_inner(
|
||||
status: "unauthenticated".to_string(),
|
||||
user: None,
|
||||
authoritative: true,
|
||||
error_message: None,
|
||||
});
|
||||
}
|
||||
return Ok(ClientAuthRefreshView {
|
||||
status: "failed".to_string(),
|
||||
user: None,
|
||||
authoritative: false,
|
||||
error_message: Some(error.message().to_string()),
|
||||
});
|
||||
// 非权威失败不再降级成字符串:把 typed error 原样交给命令出口,
|
||||
// 由前端 `invokeClientAuth` 转成 `ClientAuthFailure` 并按变体分流。
|
||||
return Err(error);
|
||||
}
|
||||
};
|
||||
let token: TokenResponse = serde_json::from_value(refreshed.data).map_err(|_| {
|
||||
@@ -977,7 +967,6 @@ async fn refresh_session_inner(
|
||||
status: "stale".to_string(),
|
||||
user: None,
|
||||
authoritative: false,
|
||||
error_message: None,
|
||||
});
|
||||
}
|
||||
let view = auth_state_view(
|
||||
@@ -990,7 +979,6 @@ async fn refresh_session_inner(
|
||||
status: "refreshed".to_string(),
|
||||
user: Some(user),
|
||||
authoritative: false,
|
||||
error_message: None,
|
||||
})
|
||||
}
|
||||
Ok(None) => {
|
||||
@@ -1001,7 +989,6 @@ async fn refresh_session_inner(
|
||||
status: "unauthenticated".to_string(),
|
||||
user: None,
|
||||
authoritative: true,
|
||||
error_message: None,
|
||||
})
|
||||
}
|
||||
Err(error) if error.is_authority_failure() => {
|
||||
@@ -1012,15 +999,9 @@ async fn refresh_session_inner(
|
||||
status: "unauthenticated".to_string(),
|
||||
user: None,
|
||||
authoritative: true,
|
||||
error_message: None,
|
||||
})
|
||||
}
|
||||
Err(error) => Ok(ClientAuthRefreshView {
|
||||
status: "failed".to_string(),
|
||||
user: None,
|
||||
authoritative: false,
|
||||
error_message: Some(error.message().to_string()),
|
||||
}),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1063,20 +1044,10 @@ pub(crate) async fn read_client_auth_state(
|
||||
refresh.user,
|
||||
Some(session.api_base_url),
|
||||
)),
|
||||
"stale" | "unauthenticated" => Ok(auth_state_view("unauthenticated", None, None)),
|
||||
_ => Ok(ClientAuthStateView {
|
||||
status: "unavailable".to_string(),
|
||||
user: None,
|
||||
api_base_url: Some(session.api_base_url),
|
||||
error_message: refresh.error_message,
|
||||
}),
|
||||
// `stale`(续期期间身份已变化)与 `unauthenticated` 都按未登录处理。
|
||||
_ => Ok(auth_state_view("unauthenticated", None, None)),
|
||||
},
|
||||
Err(error) => Ok(ClientAuthStateView {
|
||||
status: "unavailable".to_string(),
|
||||
user: None,
|
||||
api_base_url: Some(session.api_base_url),
|
||||
error_message: Some(error.message().to_string()),
|
||||
}),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1493,7 +1464,6 @@ mod tests {
|
||||
wechat_account: None,
|
||||
}),
|
||||
api_base_url: Some(DEVELOPMENT_ORIGIN.to_string()),
|
||||
error_message: None,
|
||||
};
|
||||
let serialized = serde_json::to_string(&view).expect("serialize auth state");
|
||||
for forbidden in [
|
||||
|
||||
Reference in New Issue
Block a user