[mastodon-client] Switch to numeric notification ids

This appears to be required for push notification handling in most apps
This commit is contained in:
Laura Hausmann 2023-11-30 21:22:53 +01:00
parent 1cdf3c7097
commit c60ff90557
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
6 changed files with 37 additions and 6 deletions

View file

@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class AddNotificationMastoId1701546940248 implements MigrationInterface {
name = 'AddNotificationMastoId1701546940248'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "notification" ADD "mastoId" SERIAL NOT NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0ee0c7254e5612a8129251997e" ON "notification" ("mastoId") `);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "public"."IDX_0ee0c7254e5612a8129251997e"`);
await queryRunner.query(`ALTER TABLE "notification" DROP COLUMN "mastoId"`);
}
}

View file

@ -4,7 +4,7 @@ import {
JoinColumn, JoinColumn,
ManyToOne, ManyToOne,
Column, Column,
PrimaryColumn, PrimaryColumn, Generated,
} from "typeorm"; } from "typeorm";
import { User } from "./user.js"; import { User } from "./user.js";
import { id } from "../id.js"; import { id } from "../id.js";
@ -181,4 +181,9 @@ export class Notification {
}) })
@JoinColumn() @JoinColumn()
public appAccessToken: AccessToken | null; public appAccessToken: AccessToken | null;
@Index({ unique: true })
@Column()
@Generated("increment")
public mastoId: number;
} }

View file

@ -24,7 +24,7 @@ export class NotificationConverter {
: UserConverter.encode(localUser, ctx); : UserConverter.encode(localUser, ctx);
let result = { let result = {
id: notification.id, id: notification.mastoId.toString(),
account: account, account: account,
created_at: notification.createdAt.toISOString(), created_at: notification.createdAt.toISOString(),
type: this.encodeNotificationType(notification.type), type: this.encodeNotificationType(notification.type),

View file

@ -20,7 +20,7 @@ export function setupEndpointsNotifications(router: Router): void {
auth(true, ['read:notifications']), auth(true, ['read:notifications']),
filterContext('notifications'), filterContext('notifications'),
async (ctx) => { async (ctx) => {
const notification = await NotificationHelpers.getNotificationOr404(ctx.params.id, ctx); const notification = await NotificationHelpers.getPushNotificationOr404(Number.parseInt(ctx.params.id), ctx);
ctx.body = await NotificationConverter.encode(notification, ctx); ctx.body = await NotificationConverter.encode(notification, ctx);
} }
); );
@ -36,7 +36,7 @@ export function setupEndpointsNotifications(router: Router): void {
router.post("/v1/notifications/:id/dismiss", router.post("/v1/notifications/:id/dismiss",
auth(true, ['write:notifications']), auth(true, ['write:notifications']),
async (ctx) => { async (ctx) => {
const notification = await NotificationHelpers.getNotificationOr404(ctx.params.id, ctx); const notification = await NotificationHelpers.getPushNotificationOr404(Number.parseInt(ctx.params.id), ctx);
await NotificationHelpers.dismissNotification(notification.id, ctx); await NotificationHelpers.dismissNotification(notification.id, ctx);
ctx.body = {}; ctx.body = {};
} }

View file

@ -51,6 +51,18 @@ export class NotificationHelpers {
}); });
} }
public static async getPushNotification(id: number, ctx: MastoContext): Promise<Notification | null> {
const user = ctx.user as ILocalUser;
return Notifications.findOneBy({ mastoId: id, notifieeId: user.id });
}
public static async getPushNotificationOr404(id: number, ctx: MastoContext): Promise<Notification> {
return this.getPushNotification(id, ctx).then(p => {
if (p) return p;
throw new MastoApiError(404);
});
}
public static async dismissNotification(id: string, ctx: MastoContext): Promise<void> { public static async dismissNotification(id: string, ctx: MastoContext): Promise<void> {
const user = ctx.user as ILocalUser; const user = ctx.user as ILocalUser;
await Notifications.update({ id: id, notifieeId: user.id }, { isRead: true }); await Notifications.update({ id: id, notifieeId: user.id }, { isRead: true });

View file

@ -7,7 +7,6 @@ import { notificationTypes } from "@/types.js";
export class MastodonPushHandler { export class MastodonPushHandler {
public static async sendPushNotification(n: Notification) { public static async sendPushNotification(n: Notification) {
const id = n.id;
const userId = n.notifieeId; const userId = n.notifieeId;
const type = this.encodeType(n.type); const type = this.encodeType(n.type);
if (type === null) return; if (type === null) return;
@ -24,7 +23,7 @@ export class MastodonPushHandler {
access_token: subscription.token?.token, access_token: subscription.token?.token,
title: meta.name ?? "Iceshrimp", title: meta.name ?? "Iceshrimp",
body: "You have unread notifications", body: "You have unread notifications",
notification_id: id, notification_id: n.mastoId,
notification_type: type, notification_type: type,
}; };