feat: reject token if it's not valid

This commit is contained in:
2024-06-15 06:26:13 -04:00
parent dfd709ad1c
commit 5d528fba52
12 changed files with 368 additions and 16 deletions

View File

@@ -1,7 +1,7 @@
import { eq } from "drizzle-orm";
import { DateTime } from "luxon";
import { beforeEach, describe, expect, it } from "bun:test";
import { beforeEach, describe, expect, it, mock } from "bun:test";
import app from "~/index";
import { getTestDb } from "~/libs/test/getTestDb";
@@ -16,6 +16,9 @@ describe("requests the /token route", () => {
beforeEach(async () => {
await resetTestDb();
mock.module("src/libs/fcm/verifyFcmToken", () => ({
verifyFcmToken: () => true,
}));
});
it("should succeed", async () => {
@@ -191,4 +194,42 @@ describe("requests the /token route", () => {
expect(row).toBeUndefined();
});
it("token is invalid, should fail", async () => {
mock.module("src/libs/fcm/verifyFcmToken", () => ({
verifyFcmToken: () => false,
}));
const res = await app.request("/token", {
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
}),
body: JSON.stringify({ token: "123", deviceId: "124", username: null }),
});
expect(res.json()).resolves.toEqual({ success: false });
expect(res.status).toBe(401);
});
it("token is invalid, should not insert new entry", async () => {
mock.module("src/libs/fcm/verifyFcmToken", () => ({
verifyFcmToken: () => false,
}));
await app.request("/token", {
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
}),
body: JSON.stringify({ token: "123", deviceId: "124", username: null }),
});
const row = await db
.select()
.from(deviceTokensTable)
.where(eq(deviceTokensTable.deviceId, "124"))
.get();
expect(row).toBeUndefined();
});
});

View File

@@ -1,6 +1,11 @@
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { env } from "hono/adapter";
import mapKeys from "lodash.mapkeys";
import { Case, changeStringCase } from "~/libs/changeStringCase";
import type { AdminSdkCredentials } from "~/libs/fcm/getGoogleAuthToken";
import { verifyFcmToken } from "~/libs/fcm/verifyFcmToken";
import { readEnvVariable } from "~/libs/readEnvVariable";
import { saveToken } from "~/models/token";
import type { Env } from "~/types/env";
import {
@@ -51,8 +56,20 @@ app.openapi(route, async (c) => {
await c.req.json<typeof SaveTokenRequest._type>();
try {
const isValidToken = await verifyFcmToken(
token,
mapKeys(
readEnvVariable<AdminSdkCredentials>(c.env, "ADMIN_SDK_JSON"),
(_, key) => changeStringCase(key, Case.snake_case, Case.camelCase),
) as unknown as AdminSdkCredentials,
);
if (!isValidToken) {
return c.json(ErrorResponse, 401);
}
await saveToken(env(c, "workerd"), deviceId, token, username);
} catch (error) {
// when token already exists in the database
if (
error.code === "SQLITE_CONSTRAINT" &&
error.message.includes("device_tokens.token")