feat: associate device id with username when logging in
This commit is contained in:
@@ -27,7 +27,7 @@ describe("requests the /token route", () => {
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "123", deviceId: "123", username: "test" }),
|
||||
body: JSON.stringify({ token: "123", deviceId: "123" }),
|
||||
});
|
||||
|
||||
expect(res.json()).resolves.toEqual({ success: true });
|
||||
@@ -41,50 +41,7 @@ describe("requests the /token route", () => {
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "123", deviceId: "123", username: "test" }),
|
||||
});
|
||||
|
||||
const row = await db
|
||||
.select()
|
||||
.from(deviceTokensTable)
|
||||
.where(eq(deviceTokensTable.deviceId, "123"))
|
||||
.get();
|
||||
|
||||
expect(row).toEqual({
|
||||
deviceId: "123",
|
||||
token: "123",
|
||||
username: "test",
|
||||
lastConnectedAt: expect.any(String),
|
||||
});
|
||||
// since SQL timestamp doesn't support milliseconds, compare to nearest second
|
||||
expect(
|
||||
+DateTime.fromSQL(row!.lastConnectedAt!, { zone: "utc" }).startOf(
|
||||
"second",
|
||||
),
|
||||
).toBeGreaterThanOrEqual(+minimumTimestamp.startOf("second"));
|
||||
});
|
||||
|
||||
it("with username as null, should succeed", async () => {
|
||||
const res = await app.request("/token", {
|
||||
method: "POST",
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "123", deviceId: "123", username: null }),
|
||||
});
|
||||
|
||||
expect(res.json()).resolves.toEqual({ success: true });
|
||||
expect(res.status).toBe(200);
|
||||
});
|
||||
|
||||
it("with username as null, db should contain entry", async () => {
|
||||
const minimumTimestamp = DateTime.now();
|
||||
await app.request("/token", {
|
||||
method: "POST",
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "123", deviceId: "123", username: null }),
|
||||
body: JSON.stringify({ token: "123", deviceId: "123" }),
|
||||
});
|
||||
|
||||
const row = await db
|
||||
@@ -117,7 +74,7 @@ describe("requests the /token route", () => {
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "124", deviceId: "123", username: null }),
|
||||
body: JSON.stringify({ token: "124", deviceId: "123" }),
|
||||
});
|
||||
|
||||
expect(res.json()).resolves.toEqual({ success: true });
|
||||
@@ -134,7 +91,7 @@ describe("requests the /token route", () => {
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "124", deviceId: "123", username: null }),
|
||||
body: JSON.stringify({ token: "124", deviceId: "123" }),
|
||||
});
|
||||
|
||||
const row = await db
|
||||
@@ -157,23 +114,6 @@ describe("requests the /token route", () => {
|
||||
).toBeGreaterThanOrEqual(+minimumTimestamp.startOf("second"));
|
||||
});
|
||||
|
||||
it("token already exists in db, should fail", async () => {
|
||||
await db
|
||||
.insert(deviceTokensTable)
|
||||
.values({ deviceId: "123", token: "123" });
|
||||
|
||||
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(412);
|
||||
});
|
||||
|
||||
it("token already exists in db, should not insert new entry", async () => {
|
||||
await db
|
||||
.insert(deviceTokensTable)
|
||||
@@ -183,7 +123,7 @@ describe("requests the /token route", () => {
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "123", deviceId: "124", username: null }),
|
||||
body: JSON.stringify({ token: "123", deviceId: "124" }),
|
||||
});
|
||||
|
||||
const row = await db
|
||||
@@ -195,64 +135,6 @@ describe("requests the /token route", () => {
|
||||
expect(row).toBeUndefined();
|
||||
});
|
||||
|
||||
it("associating a username with a token, should succeed", async () => {
|
||||
await db
|
||||
.insert(deviceTokensTable)
|
||||
.values({ deviceId: "123", token: "123" });
|
||||
|
||||
const res = await app.request("/token", {
|
||||
method: "POST",
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({
|
||||
token: "123",
|
||||
deviceId: "123",
|
||||
username: "aniplay",
|
||||
}),
|
||||
});
|
||||
|
||||
expect(res.json()).resolves.toEqual({ success: true });
|
||||
expect(res.status).toBe(200);
|
||||
});
|
||||
|
||||
it("associating a username with a token should update existing entry", async () => {
|
||||
const minimumTimestamp = DateTime.now();
|
||||
await db
|
||||
.insert(deviceTokensTable)
|
||||
.values({ deviceId: "123", token: "123" });
|
||||
await app.request("/token", {
|
||||
method: "POST",
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({
|
||||
token: "123",
|
||||
deviceId: "123",
|
||||
username: "aniplay",
|
||||
}),
|
||||
});
|
||||
|
||||
const row = await db
|
||||
.select()
|
||||
.from(deviceTokensTable)
|
||||
.where(eq(deviceTokensTable.deviceId, "123"))
|
||||
.get();
|
||||
|
||||
expect(row).toEqual({
|
||||
deviceId: "123",
|
||||
token: "123",
|
||||
username: "aniplay",
|
||||
lastConnectedAt: expect.any(String),
|
||||
});
|
||||
// since SQL timestamp doesn't support milliseconds, compare to nearest second
|
||||
expect(
|
||||
+DateTime.fromSQL(row!.lastConnectedAt!, { zone: "utc" }).startOf(
|
||||
"second",
|
||||
),
|
||||
).toBeGreaterThanOrEqual(+minimumTimestamp.startOf("second"));
|
||||
});
|
||||
|
||||
it("token is invalid, should fail", async () => {
|
||||
mock.module("src/libs/fcm/verifyFcmToken", () => ({
|
||||
verifyFcmToken: () => false,
|
||||
@@ -263,7 +145,7 @@ describe("requests the /token route", () => {
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "123", deviceId: "124", username: null }),
|
||||
body: JSON.stringify({ token: "123", deviceId: "124" }),
|
||||
});
|
||||
|
||||
expect(res.json()).resolves.toEqual({ success: false });
|
||||
@@ -279,7 +161,7 @@ describe("requests the /token route", () => {
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({ token: "123", deviceId: "124", username: null }),
|
||||
body: JSON.stringify({ token: "123", deviceId: "124" }),
|
||||
});
|
||||
|
||||
const row = await db
|
||||
|
||||
@@ -3,7 +3,6 @@ import { env } from "hono/adapter";
|
||||
import mapKeys from "lodash.mapkeys";
|
||||
|
||||
import { Case, changeStringCase } from "~/libs/changeStringCase";
|
||||
import { TokenAlreadyExistsError } from "~/libs/errors/TokenAlreadyExists";
|
||||
import type { AdminSdkCredentials } from "~/libs/fcm/getGoogleAuthToken";
|
||||
import { verifyFcmToken } from "~/libs/fcm/verifyFcmToken";
|
||||
import { readEnvVariable } from "~/libs/readEnvVariable";
|
||||
@@ -21,7 +20,6 @@ const app = new OpenAPIHono<Env>();
|
||||
const SaveTokenRequest = z.object({
|
||||
token: z.string(),
|
||||
deviceId: z.string(),
|
||||
username: z.string().nullable(),
|
||||
});
|
||||
|
||||
const SaveTokenResponse = SuccessResponseSchema();
|
||||
@@ -70,8 +68,7 @@ const route = createRoute({
|
||||
});
|
||||
|
||||
app.openapi(route, async (c) => {
|
||||
const { token, deviceId, username } =
|
||||
await c.req.json<typeof SaveTokenRequest._type>();
|
||||
const { token, deviceId } = await c.req.json<typeof SaveTokenRequest._type>();
|
||||
|
||||
try {
|
||||
const isValidToken = await verifyFcmToken(
|
||||
@@ -85,12 +82,8 @@ app.openapi(route, async (c) => {
|
||||
return c.json(ErrorResponse, 401);
|
||||
}
|
||||
|
||||
await saveToken(env(c, "workerd"), deviceId, token, username);
|
||||
await saveToken(env(c, "workerd"), deviceId, token);
|
||||
} catch (error) {
|
||||
if (error instanceof TokenAlreadyExistsError) {
|
||||
return c.json(ErrorResponse, 412);
|
||||
}
|
||||
|
||||
console.error(new Error("Failed to save token", { cause: error }));
|
||||
return c.json(ErrorResponse, 500);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user