aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/routes/sb1.remote.ts
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/routes/sb1.remote.ts')
-rw-r--r--app/src/routes/sb1.remote.ts192
1 files changed, 27 insertions, 165 deletions
diff --git a/app/src/routes/sb1.remote.ts b/app/src/routes/sb1.remote.ts
index 17e1ead..d2eb0cc 100644
--- a/app/src/routes/sb1.remote.ts
+++ b/app/src/routes/sb1.remote.ts
@@ -1,181 +1,43 @@
-import { SB1_FIN_INST, SB1_ID, SB1_REDIRECT_URI, SB1_SECRET } from "$env/static/private";
-import { randomUUID } from "node:crypto";
-import { db } from "../lib/server/db";
-import { syncSession } from "../lib/server/db/schema";
+import { db } from "$lib/server/db";
+import { syncSession } from "$lib/server/db/schema";
import * as v from "valibot"
import { command, query } from "$app/server";
-import { eq } from "drizzle-orm";
-import { Temporal } from "temporal-polyfill";
+import sb1 from "$lib/server/sb1";
-export const createSb1SyncSessionAndReturnLoginUrl = command(async () => {
- return createSb1Auth()
+const init_auth_session = command(async () => {
+ return await sb1.auth.init_auth_session()
})
-async function createSb1Auth() {
- const state = randomUUID()
-
- await db.insert(syncSession).values({
- authzState: state
- })
-
- const authorizeUrl = new URL("https://api.sparebank1.no/oauth/authorize");
-
- authorizeUrl.searchParams.set("client_id", SB1_ID);
- authorizeUrl.searchParams.set("state", state);
- authorizeUrl.searchParams.set("redirect_uri", SB1_REDIRECT_URI);
- authorizeUrl.searchParams.set("finInst", SB1_FIN_INST);
- authorizeUrl.searchParams.set("response_type", "code");
-
- return authorizeUrl.toString()
-}
-
-export const getAccounts = query(async () => {
- const token = await getSb1AccessToken()
- if (!token) return undefined
- const url = new URL(
- "https://api.sparebank1.no/personal/banking/accounts",
- );
- const response = await fetch(url, {
- headers: {
- Authorization: `Bearer ${token}`
- },
- });
- if (response.ok) {
- return await response.json() as { accounts: Array<any> }
- }
- else console.error(await response.text())
+const is_ready = query(async () => {
+ return await sb1.auth.is_ready()
})
-export const getTransactions = query(v.string(), async (accountKey: string) => {
- const token = await getSb1AccessToken()
- if (token) return undefined
- const url = new URL(
- "https://api.sparebank1.no/personal/banking/transactions",
- );
- url.searchParams.set("accountKey", accountKey);
- const response = await fetch(url, {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- });
- return (await response.json()) as TransactionsResponse;
+const get_accounts = query(async () => {
+ return await sb1.data.get_accounts()
})
-async function getSb1AccessToken() {
- const entity = await db.select({
- tokens: syncSession.tokens
- }).from(syncSession)
- const { tokens } = entity[0]
- if (!tokens) return null
- const parsed = JSON.parse(tokens)
- return parsed.access_token as string
-}
+const get_transactions = query(v.string(), async (accountKey: string) => {
+ return await sb1.data.get_transactions(accountKey)
+})
-export const clearTokens = query(async () => {
+const clear_auth_session = query(async () => {
await db.delete(syncSession)
})
-export const getTokenExpires = query(async () => {
- const entity = await db.select({
- refreshTokenCreated: syncSession.refreshTokenCreated,
- accessTokenCreated: syncSession.accessTokenCreated,
- tokens: syncSession.tokens
- }).from(syncSession)
- if (!entity[0]) return undefined
- const { tokens, accessTokenCreated, refreshTokenCreated } = entity[0]
- const tokensParsed = JSON.parse(tokens ?? "")
- return {
- accessToken: {
- expires: tokensParsed?.expires_in ?? 0,
- created: Temporal.Instant.fromEpochMilliseconds(Number(accessTokenCreated))
- },
- refreshToken: {
- expires: tokensParsed?.refresh_token_expires_in ?? 0,
- created: Temporal.Instant.fromEpochMilliseconds(Number(refreshTokenCreated))
- },
- }
+const get_auth_info = query(async () => {
+ return await sb1.auth.get_auth_info()
})
-type Sb1Tokens = {
- access_token: string,
- expires_in: number,
- refresh_token_expires_in: number,
- refresh_token_absolute_expires_in: number,
- token_type: string,
- refresh_token: string
-}
-
-type TokenAction = "Empty"
-
-const auth = {
- async ready(): Promise<boolean> {
- const token = await this.tokenOrAction()
- const ping = await fetch("https://developer.sparebank1.no/helloworld/ping", {
- headers: {
- "Authorization": "Bearer " + token
- }
- })
- return ping.ok
- },
- async tokenOrAction(): Promise<TokenAction | string> {
- const entity = await db.select({
- refreshTokenCreated: syncSession.refreshTokenCreated,
- accessTokenCreated: syncSession.accessTokenCreated,
- tokens: syncSession.tokens
- }).from(syncSession)
- const { tokens, accessTokenCreated, refreshTokenCreated } = entity[0]
- if (!tokens) return "Empty"
- const json = JSON.parse(tokens) as Sb1Tokens
- if (!Object.hasOwn(json, "access_token")) return TokenAction.Empty
- return json.access_token
- },
- getAccessToken() { },
- async getRefreshToken() {
- const entity = await db.select({
- tokens: syncSession.tokens,
- id: syncSession.id
- }).from(syncSession)
-
- const { tokens, id } = entity[0]
-
- if (!tokens) return null
-
- const parsed = JSON.parse(tokens)
-
- if (!parsed.refresh_token) throw new Error("No refresh token");
-
- const fd = new URLSearchParams();
-
- fd.set("client_id", SB1_ID);
- fd.set("client_secret", SB1_SECRET);
- fd.set("refresh_token", parsed.refresh_token);
- fd.set("grant_type", "refresh_token");
-
- const res = await fetch("https://api.sparebank1.no/oauth/token", {
- headers: {
- "Content-Type": "application/x-www-form-urlencoded",
- },
- method: "post",
- body: fd,
- });
-
- const text = await res.text();
- const epoch = Temporal.Now.instant().epochMilliseconds
- await db.update(syncSession).set({ tokens: text, accessTokenCreated: epoch, refreshTokenCreated: epoch }).where(eq(syncSession.id, id))
- }
-}
-
-export const refreshSB1Token = command(async () => {
- auth.getRefreshToken()
-});
-
-export type Transaction = {
- description: string;
- amount: number;
- date: string;
- mcc: string;
-}
+const refresh_tokem = command(async () => {
+ await sb1.auth.refresh_tokem()
+})
-export type TransactionsResponse = {
- transactions: Array<Transaction>;
-}
+export {
+ refresh_tokem,
+ init_auth_session,
+ is_ready,
+ get_accounts,
+ get_transactions,
+ clear_auth_session,
+ get_auth_info,
+} \ No newline at end of file