feat: replace API token field with login flow
New auth.ts service: login() POSTs to /api/auth/token with handle + password, stores instanceUrl/handle/apiToken in AsyncStorage, password never persisted. logout() clears all credentials. loadAuthState() returns stored credentials or null. Settings screen now shows a login form (URL + handle + password) when not connected, and a connected state card with Disconnect button when logged in. km notifications toggle auto-saves without a separate Save button.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
interface LoginResult {
|
||||
ok: boolean;
|
||||
displayName?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export async function login(
|
||||
instanceUrl: string,
|
||||
handle: string,
|
||||
password: string,
|
||||
): Promise<LoginResult> {
|
||||
const url = instanceUrl.replace(/\/$/, '') + '/api/auth/token';
|
||||
try {
|
||||
const resp = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ handle, password }),
|
||||
});
|
||||
|
||||
if (!resp.ok) {
|
||||
const text = await resp.text().catch(() => '');
|
||||
return { ok: false, error: text || `HTTP ${resp.status}` };
|
||||
}
|
||||
|
||||
const data = await resp.json();
|
||||
if (!data.token) return { ok: false, error: 'No token in response' };
|
||||
|
||||
await Promise.all([
|
||||
AsyncStorage.setItem('instanceUrl', instanceUrl.trim()),
|
||||
AsyncStorage.setItem('handle', handle.trim()),
|
||||
AsyncStorage.setItem('apiToken', data.token),
|
||||
]);
|
||||
|
||||
return { ok: true, displayName: data.display_name };
|
||||
} catch (e: any) {
|
||||
return { ok: false, error: e?.message ?? 'Connection failed' };
|
||||
}
|
||||
}
|
||||
|
||||
export async function logout(): Promise<void> {
|
||||
await Promise.all([
|
||||
AsyncStorage.removeItem('instanceUrl'),
|
||||
AsyncStorage.removeItem('handle'),
|
||||
AsyncStorage.removeItem('apiToken'),
|
||||
]);
|
||||
}
|
||||
|
||||
export interface AuthState {
|
||||
instanceUrl: string;
|
||||
handle: string;
|
||||
apiToken: string;
|
||||
}
|
||||
|
||||
export async function loadAuthState(): Promise<AuthState | null> {
|
||||
const [instanceUrl, handle, apiToken] = await Promise.all([
|
||||
AsyncStorage.getItem('instanceUrl'),
|
||||
AsyncStorage.getItem('handle'),
|
||||
AsyncStorage.getItem('apiToken'),
|
||||
]);
|
||||
if (!instanceUrl || !apiToken) return null;
|
||||
return { instanceUrl, handle: handle ?? '', apiToken };
|
||||
}
|
||||
Reference in New Issue
Block a user