storkit: merge 449_bug_oauth_callback_url_ignores_port_cli_flag
This commit is contained in:
@@ -66,7 +66,12 @@ describe("App", () => {
|
|||||||
mockedApi.getAnthropicApiKeyExists.mockResolvedValue(false);
|
mockedApi.getAnthropicApiKeyExists.mockResolvedValue(false);
|
||||||
mockedApi.getAnthropicModels.mockResolvedValue([]);
|
mockedApi.getAnthropicModels.mockResolvedValue([]);
|
||||||
mockedApi.getModelPreference.mockResolvedValue(null);
|
mockedApi.getModelPreference.mockResolvedValue(null);
|
||||||
mockedApi.getOAuthStatus.mockResolvedValue({ authenticated: false, expired: false, expires_at: 0, has_refresh_token: false });
|
mockedApi.getOAuthStatus.mockResolvedValue({
|
||||||
|
authenticated: false,
|
||||||
|
expired: false,
|
||||||
|
expires_at: 0,
|
||||||
|
has_refresh_token: false,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function renderApp() {
|
async function renderApp() {
|
||||||
|
|||||||
@@ -168,7 +168,11 @@ interface ChatProps {
|
|||||||
oauthStatus?: OAuthStatus | null;
|
oauthStatus?: OAuthStatus | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Chat({ projectPath, onCloseProject, oauthStatus = null }: ChatProps) {
|
export function Chat({
|
||||||
|
projectPath,
|
||||||
|
onCloseProject,
|
||||||
|
oauthStatus = null,
|
||||||
|
}: ChatProps) {
|
||||||
const { messages, setMessages, clearMessages } = useChatHistory(projectPath);
|
const { messages, setMessages, clearMessages } = useChatHistory(projectPath);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [model, setModel] = useState("claude-code-pty");
|
const [model, setModel] = useState("claude-code-pty");
|
||||||
|
|||||||
@@ -349,7 +349,11 @@ export function ChatHeader({
|
|||||||
type="button"
|
type="button"
|
||||||
title="Authenticate with Claude via OAuth"
|
title="Authenticate with Claude via OAuth"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open("/oauth/authorize", "_blank", "noopener,noreferrer");
|
window.open(
|
||||||
|
"/oauth/authorize",
|
||||||
|
"_blank",
|
||||||
|
"noopener,noreferrer",
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
padding: "6px 12px",
|
padding: "6px 12px",
|
||||||
|
|||||||
@@ -66,7 +66,11 @@ export function SelectionScreen({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open("/oauth/authorize", "_blank", "noopener,noreferrer");
|
window.open(
|
||||||
|
"/oauth/authorize",
|
||||||
|
"_blank",
|
||||||
|
"noopener,noreferrer",
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
padding: "8px 16px",
|
padding: "8px 16px",
|
||||||
@@ -78,7 +82,9 @@ export function SelectionScreen({
|
|||||||
fontSize: "0.9em",
|
fontSize: "0.9em",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{oauthStatus.expired ? "Re-authenticate with Claude" : "Login with Claude"}
|
{oauthStatus.expired
|
||||||
|
? "Re-authenticate with Claude"
|
||||||
|
: "Login with Claude"}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<span
|
<span
|
||||||
|
|||||||
+12
-2
@@ -64,12 +64,13 @@ pub fn build_routes(
|
|||||||
ctx: AppContext,
|
ctx: AppContext,
|
||||||
whatsapp_ctx: Option<Arc<WhatsAppWebhookContext>>,
|
whatsapp_ctx: Option<Arc<WhatsAppWebhookContext>>,
|
||||||
slack_ctx: Option<Arc<SlackWebhookContext>>,
|
slack_ctx: Option<Arc<SlackWebhookContext>>,
|
||||||
|
port: u16,
|
||||||
) -> impl poem::Endpoint {
|
) -> impl poem::Endpoint {
|
||||||
let ctx_arc = std::sync::Arc::new(ctx);
|
let ctx_arc = std::sync::Arc::new(ctx);
|
||||||
|
|
||||||
let (api_service, docs_service) = build_openapi_service(ctx_arc.clone());
|
let (api_service, docs_service) = build_openapi_service(ctx_arc.clone());
|
||||||
|
|
||||||
let oauth_state = Arc::new(oauth::OAuthState::new(resolve_port()));
|
let oauth_state = Arc::new(oauth::OAuthState::new(port));
|
||||||
|
|
||||||
let mut route = Route::new()
|
let mut route = Route::new()
|
||||||
.nest("/api", api_service)
|
.nest("/api", api_service)
|
||||||
@@ -236,6 +237,15 @@ mod tests {
|
|||||||
fn build_routes_constructs_without_panic() {
|
fn build_routes_constructs_without_panic() {
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let ctx = context::AppContext::new_test(tmp.path().to_path_buf());
|
let ctx = context::AppContext::new_test(tmp.path().to_path_buf());
|
||||||
let _endpoint = build_routes(ctx, None, None);
|
let _endpoint = build_routes(ctx, None, None, 3001);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_routes_accepts_custom_port() {
|
||||||
|
// Verify build_routes compiles and runs with a non-default port,
|
||||||
|
// ensuring the port parameter flows through to OAuthState.
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = context::AppContext::new_test(tmp.path().to_path_buf());
|
||||||
|
let _endpoint = build_routes(ctx, None, None, 9999);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -423,6 +423,13 @@ mod tests {
|
|||||||
assert_eq!(state.callback_url(), "http://localhost:3001/callback");
|
assert_eq!(state.callback_url(), "http://localhost:3001/callback");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn oauth_state_callback_url_uses_given_port() {
|
||||||
|
// Ensure OAuthState::new uses the port passed to it, not a hardcoded value.
|
||||||
|
let state = OAuthState::new(9876);
|
||||||
|
assert_eq!(state.callback_url(), "http://localhost:9876/callback");
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn html_response_contains_title_and_message() {
|
async fn html_response_contains_title_and_message() {
|
||||||
let resp = html_response(StatusCode::OK, "Test Title", "Test message");
|
let resp = html_response(StatusCode::OK, "Test Title", "Test message");
|
||||||
|
|||||||
+1
-1
@@ -495,7 +495,7 @@ async fn main() -> Result<(), std::io::Error> {
|
|||||||
matrix_shutdown_tx: Some(Arc::clone(&matrix_shutdown_tx)),
|
matrix_shutdown_tx: Some(Arc::clone(&matrix_shutdown_tx)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let app = build_routes(ctx, whatsapp_ctx.clone(), slack_ctx.clone());
|
let app = build_routes(ctx, whatsapp_ctx.clone(), slack_ctx.clone(), port);
|
||||||
|
|
||||||
// Optional Matrix bot: connect to the homeserver and start listening for
|
// Optional Matrix bot: connect to the homeserver and start listening for
|
||||||
// messages if `.storkit/bot.toml` is present and enabled.
|
// messages if `.storkit/bot.toml` is present and enabled.
|
||||||
|
|||||||
Reference in New Issue
Block a user