Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cron/monthly/user-report.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const debug = debugLib('monthlyreport');
* @param {*} backerCollective
*/
const fetchUserSubscribers = async (notificationType, backerCollective) => {
const unsubscriptions = await models.Notification.findAll({
const unsubscriptions = await models.ActivitySubscription.findAll({
attributes: ['UserId'],
where: {
CollectiveId: backerCollective.id,
Expand Down
2 changes: 1 addition & 1 deletion cron/yearly/user-report.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ const getCollectives = () => {
};

const getUsers = collective => {
return models.Notification.findAll({
return models.ActivitySubscription.findAll({
where: {
channel: 'email',
CollectiveId: collective.id,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

/**
* Renames the legacy `Notifications` table to `ActivitySubscriptions` to match
* the ActivitySubscription Sequelize model (`server/models/ActivitySubscription.ts`).
*
* @type {import('sequelize-cli').Migration}
*/
module.exports = {
async up(queryInterface) {
await queryInterface.renameTable('Notifications', 'ActivitySubscriptions');
},

async down(queryInterface) {
await queryInterface.renameTable('ActivitySubscriptions', 'Notifications');
},
};
2 changes: 1 addition & 1 deletion scripts/sanitize-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ const removeConnectedAccountsTokens = () => {

// Remove all webhooks to ensure we won't ping user apps
const deleteWebhooks = () => {
return models.Notification.destroy({
return models.ActivitySubscription.destroy({
where: { channel: [channels.WEBHOOK, channels.SLACK] },
}).catch(e => console.error('There was an error removing the webhooks. Please do it manually', e));
};
Expand Down
2 changes: 1 addition & 1 deletion server/controllers/services/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const unsubscribe = async (req, res, next) => {
type = 'order.processed';
}

await models.Notification.unsubscribe(type, 'email', user.id, collective?.id);
await models.ActivitySubscription.unsubscribe(type, 'email', user.id, collective?.id);
res.send({ response: 'ok' });
} catch (e) {
next(e);
Expand Down
4 changes: 3 additions & 1 deletion server/graphql/v1/CollectiveInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ export const CollectiveInterfaceType = new GraphQLInterfaceType({
notifications: {
type: new GraphQLList(NotificationType),
description: 'List of all notifications for this collective',
deprecationReason: '2026-03-31: Please move to GraphQL v2',
args: {
limit: { type: GraphQLInt },
offset: { type: GraphQLInt },
Expand Down Expand Up @@ -1292,6 +1293,7 @@ const CollectiveFields = () => {
},
notifications: {
type: new GraphQLList(NotificationType),
deprecationReason: '2026-03-31: Please move to GraphQL v2',
args: {
limit: { type: GraphQLInt },
offset: { type: GraphQLInt },
Expand All @@ -1318,7 +1320,7 @@ const CollectiveFields = () => {
where.active = args.active;
}

return models.Notification.findAll({
return models.ActivitySubscription.findAll({
where: where,
limit: args.limit,
offset: args.offset,
Expand Down
1 change: 1 addition & 0 deletions server/graphql/v1/mutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ const mutations = {
editWebhooks: {
type: new GraphQLList(NotificationType),
description: 'Edits (by replacing) the admin-level webhooks for a collective.',
deprecationReason: '2026-03-31: Please move to GraphQL v2',
args: {
collectiveId: {
type: new GraphQLNonNull(GraphQLInt),
Expand Down
8 changes: 4 additions & 4 deletions server/graphql/v1/mutations/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export async function editWebhooks(args, req) {
}

const getAllWebhooks = async () => {
return await models.Notification.findAll({
return await models.ActivitySubscription.findAll({
where: { CollectiveId: args.collectiveId, channel: channels.WEBHOOK },
order: [['createdAt', 'ASC']],
});
Expand All @@ -46,7 +46,7 @@ export async function editWebhooks(args, req) {
// Delete old
if (toRemove.length > 0) {
promises.push(
models.Notification.destroy({
models.ActivitySubscription.destroy({
where: { id: { [Op.in]: toRemove.map(n => n.id) } },
}),
);
Expand All @@ -57,7 +57,7 @@ export async function editWebhooks(args, req) {
promises.push(
Promise.all(
toCreate.map(notification =>
models.Notification.create({
models.ActivitySubscription.create({
...pick(notification, allowedFields),
CollectiveId: args.collectiveId,
UserId: req.remoteUser.id,
Expand All @@ -72,7 +72,7 @@ export async function editWebhooks(args, req) {
if (toUpdate.length > 0) {
promises.push(
...toUpdate.map(notification => {
return models.Notification.update(pick(notification, allowedFields), {
return models.ActivitySubscription.update(pick(notification, allowedFields), {
where: { id: notification.id, CollectiveId: args.collectiveId },
});
}),
Expand Down
1 change: 1 addition & 0 deletions server/graphql/v1/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,7 @@ export const ExpenseType = new GraphQLObjectType({
export const NotificationType = new GraphQLObjectType({
name: 'NotificationType',
description: 'This represents a Notification',
deprecationReason: '2026-03-31: Please move to GraphQL v2',
fields: () => {
return {
id: {
Expand Down
2 changes: 1 addition & 1 deletion server/graphql/v2/collection/WebhookCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const WebhookCollectionResolver = async (args, req) => {

const { offset, limit } = args;

const result = await models.Notification.findAndCountAll({
const result = await models.ActivitySubscription.findAndCountAll({
where,
limit,
offset,
Expand Down
2 changes: 1 addition & 1 deletion server/graphql/v2/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const IDENTIFIER_TYPES = {
ACCOUNT: 'account',
ACCOUNTING_CATEGORY: 'accounting-category',
ACTIVITY: 'activity',
ACTIVITY_SUBSCRIPTION: 'activity-subscription',
AGREEMENT: 'agreement',
COMMENT: 'comment',
COMMENT_REACTION: 'comment-reaction',
Expand All @@ -42,7 +43,6 @@ export const IDENTIFIER_TYPES = {
UPDATE: 'update',
APPLICATION: 'application',
USER_TOKEN: 'user-token',
NOTIFICATION: 'notification',
PERSONAL_TOKEN: 'personal-token',
UPLOADED_FILE: 'uploaded-file',
USER: 'user',
Expand Down
12 changes: 6 additions & 6 deletions server/graphql/v2/input/WebhookReferenceInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { idDecode, IDENTIFIER_TYPES } from '../identifiers';
export const WebhookReferenceFields = {
id: {
type: GraphQLString,
description: `The public id identifying the webhook (ie: dgm9bnk8-0437xqry-ejpvzeol-jdayw5re, ${EntityShortIdPrefix.Notification}_xxxxxxxx)`,
description: `The public id identifying the webhook (ie: dgm9bnk8-0437xqry-ejpvzeol-jdayw5re, ${EntityShortIdPrefix.ActivitySubscription}_xxxxxxxx)`,
},
legacyId: {
type: GraphQLInt,
Expand All @@ -29,13 +29,13 @@ export const GraphQLWebhookReferenceInput = new GraphQLInputObjectType({
*/
export const fetchWebhookWithReference = async input => {
let notification;
if (isEntityPublicId(input.id, EntityShortIdPrefix.Notification)) {
notification = await models.Notification.findOne({ where: { publicId: input.id } });
if (isEntityPublicId(input.id, EntityShortIdPrefix.ActivitySubscription)) {
notification = await models.ActivitySubscription.findOne({ where: { publicId: input.id } });
} else if (input.id) {
const id = idDecode(input.id, IDENTIFIER_TYPES.NOTIFICATION);
notification = await models.Notification.findByPk(id);
const id = idDecode(input.id, IDENTIFIER_TYPES.ACTIVITY_SUBSCRIPTION);
notification = await models.ActivitySubscription.findByPk(id);
} else if (input.legacyId) {
notification = await models.Notification.findByPk(input.legacyId);
notification = await models.ActivitySubscription.findByPk(input.legacyId);
} else {
throw new Error('Please provide an id');
}
Expand Down
2 changes: 1 addition & 1 deletion server/graphql/v2/interface/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ const accountFieldsDefinition = () => ({
where['channel'] = args.channel;
}

return models.Notification.findAll({ where });
return models.ActivitySubscription.findAll({ where });
},
},
permissions: {
Expand Down
14 changes: 12 additions & 2 deletions server/graphql/v2/mutation/ActivitySubscriptionsMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,19 @@ const notificationMutations = {
args.account && (await fetchAccountWithReference(args.account, { loaders: req.loaders, throwIfMissing: true }));

if (args.active) {
return models.Notification.subscribe(args.type, Channels.EMAIL, req.remoteUser.id, collective?.id || null);
return models.ActivitySubscription.subscribe(
args.type,
Channels.EMAIL,
req.remoteUser.id,
collective?.id || null,
);
} else {
return models.Notification.unsubscribe(args.type, Channels.EMAIL, req.remoteUser.id, collective?.id || null);
return models.ActivitySubscription.unsubscribe(
args.type,
Channels.EMAIL,
req.remoteUser.id,
collective?.id || null,
);
}
},
},
Expand Down
2 changes: 1 addition & 1 deletion server/graphql/v2/mutation/WebhookMutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const createWebhook = {
CollectiveId: account.id,
};

return models.Notification.create(createParams);
return models.ActivitySubscription.create(createParams);
},
};

Expand Down
4 changes: 2 additions & 2 deletions server/graphql/v2/object/ActivitySubscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
type: new GraphQLNonNull(GraphQLString),
description: 'Unique identifier for this notification setting',
resolve(notification) {
if (isEntityMigratedToPublicId(EntityShortIdPrefix.Notification, notification.createdAt)) {
if (isEntityMigratedToPublicId(EntityShortIdPrefix.ActivitySubscription, notification.createdAt)) {
return notification.publicId;
} else {
return idEncode(notification.id, IDENTIFIER_TYPES.NOTIFICATION);

Check failure on line 23 in server/graphql/v2/object/ActivitySubscription.ts

View workflow job for this annotation

GitHub Actions / typescript

Property 'NOTIFICATION' does not exist on type '{ readonly ACCOUNT: "account"; readonly ACCOUNTING_CATEGORY: "accounting-category"; readonly ACTIVITY: "activity"; readonly ACTIVITY_SUBSCRIPTION: "activity-subscription"; readonly AGREEMENT: "agreement"; ... 28 more ...; readonly KYC_VERIFICATION: "kyc-verification"; }'.
}
},
},
publicId: {
type: new GraphQLNonNull(GraphQLString),
description: `The resource public id (ie: ${EntityShortIdPrefix.Notification}_xxxxxxxx)`,
description: `The resource public id (ie: ${EntityShortIdPrefix.ActivitySubscription}_xxxxxxxx)`,
},
channel: {
type: new GraphQLNonNull(GraphQLActivityChannel),
Expand Down
28 changes: 14 additions & 14 deletions server/graphql/v2/object/Webhook.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,42 @@ export const GraphQLWebhook = new GraphQLObjectType({
fields: () => ({
id: {
type: new GraphQLNonNull(GraphQLString),
resolve(notification) {
if (isEntityMigratedToPublicId(EntityShortIdPrefix.Notification, notification.createdAt)) {
return notification.publicId;
resolve(activitySubscription) {
if (isEntityMigratedToPublicId(EntityShortIdPrefix.ActivitySubscription, activitySubscription.createdAt)) {
return activitySubscription.publicId;
} else {
return idEncode(notification.id, 'notification');
return idEncode(activitySubscription.id, 'activitySubscription');
}
},
},
publicId: {
type: new GraphQLNonNull(GraphQLString),
description: `The resource public id (ie: ${EntityShortIdPrefix.Notification}_xxxxxxxx)`,
description: `The resource public id (ie: ${EntityShortIdPrefix.ActivitySubscription}_xxxxxxxx)`,
},
legacyId: {
type: new GraphQLNonNull(GraphQLInt),
deprecationReason: '2026-02-25: use publicId',
resolve(notification) {
return notification.id;
resolve(activitySubscription) {
return activitySubscription.id;
},
},
activityType: {
type: GraphQLActivityType,
resolve(notification) {
return notification.type;
resolve(activitySubscription) {
return activitySubscription.type;
},
},
webhookUrl: {
type: URL,
resolve(notification) {
return notification.webhookUrl;
resolve(activitySubscription) {
return activitySubscription.webhookUrl;
},
},
account: {
type: new GraphQLNonNull(GraphQLAccount),
resolve(notification, args, req) {
if (notification.CollectiveId) {
return req.loaders.Collective.byId.load(notification.CollectiveId);
resolve(activitySubscription, args, req) {
if (activitySubscription.CollectiveId) {
return req.loaders.Collective.byId.load(activitySubscription.CollectiveId);
}
},
},
Expand Down
2 changes: 1 addition & 1 deletion server/lib/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ const generateEmailFromTemplate = (

const isNotificationActive = async (template: string, data: SendMessageData) => {
if (data.user && data.user.id) {
return models.Notification.isActive(template, data.user, data.collective);
return models.ActivitySubscription.isActive(template, data.user, data.collective);
} else {
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion server/lib/import-export/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const getNextPK = async model => {
const modelsDeduplicationSchema: Record<ModelNames, { unique?: string[] }> = {
AccountingCategory: {},
Activity: {},
ActivitySubscription: {},
Agreement: {},
Application: {},
Collective: { unique: ['slug'] },
Expand All @@ -106,7 +107,6 @@ const modelsDeduplicationSchema: Record<ModelNames, { unique?: string[] }> = {
Member: {},
MemberInvitation: {},
MigrationLog: {},
Notification: {},
OAuthAuthorizationCode: {},
Order: { unique: ['totalAmount', 'currency', 'createdAt', 'quantity', 'status', 'interval', 'description'] },
PaymentMethod: { unique: ['uuid'] },
Expand Down
10 changes: 5 additions & 5 deletions server/lib/import-export/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ const PROD_SANITIZERS: { [k in ModelNames]: Sanitizer<k> } = {
Activity: async (activity, req) => ({
data: await sanitizeActivityData(req, activity),
}),
ActivitySubscription: async notification => {
if (notification.channel !== Channels.EMAIL) {
return null;
}
},
Agreement: (agreement, req) => {
if (!Agreement.canSeeAgreementsForHostCollectiveId(req.remoteUser, agreement.HostCollectiveId)) {
return null;
Expand Down Expand Up @@ -199,11 +204,6 @@ const PROD_SANITIZERS: { [k in ModelNames]: Sanitizer<k> } = {
}
}
},
Notification: async notification => {
if (notification.channel !== Channels.EMAIL) {
return null;
}
},
Order: async (order, req) => {
req.loaders.Order.byId.prime(order.id, order); // Store the order in the cache for later row resolvers
const publicDataFields = [
Expand Down
4 changes: 2 additions & 2 deletions server/lib/merge-accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ const collectiveFieldsConfig: CollectiveFieldsConfig = {
accountingCategories: { model: models.AccountingCategory, field: 'CollectiveId' },
agreements: { model: models.Agreement, field: 'CollectiveId' },
activities: { model: models.Activity, field: 'CollectiveId' },
activitySubscriptions: { model: models.ActivitySubscription, field: 'CollectiveId' },
applications: { model: models.Application, field: 'CollectiveId' },
childrenCollectives: { model: Collective, field: 'ParentCollectiveId' },
comments: { model: models.Comment, field: 'CollectiveId' },
Expand All @@ -204,7 +205,6 @@ const collectiveFieldsConfig: CollectiveFieldsConfig = {
members: { model: models.Member, field: 'MemberCollectiveId', getIdsToIgnore: getMemberIdsToIgnore },
membershipInvitations: { model: models.MemberInvitation, field: 'CollectiveId' },
memberships: { model: models.Member, field: 'CollectiveId', getIdsToIgnore: getMembershipIdsToIgnore },
notifications: { model: models.Notification, field: 'CollectiveId' },
ordersCreated: { model: models.Order, field: 'FromCollectiveId' },
ordersReceived: { model: models.Order, field: 'CollectiveId' },
paymentMethods: { model: models.PaymentMethod, field: 'CollectiveId' },
Expand Down Expand Up @@ -232,6 +232,7 @@ type UserFieldsConfig = Record<string, { model: User; field: UserField }>;
const userFieldsConfig = {
agreements: { model: models.Agreement, field: 'UserId' },
activities: { model: models.Activity, field: 'UserId' },
activitySubscriptions: { model: models.ActivitySubscription, field: 'UserId' },
applications: { model: models.Application, field: 'CreatedByUserId' },
collectives: { model: models.Collective, field: 'CreatedByUserId' },
comments: { model: models.Comment, field: 'CreatedByUserId' },
Expand All @@ -244,7 +245,6 @@ const userFieldsConfig = {
memberInvitations: { model: models.MemberInvitation, field: 'CreatedByUserId' },
members: { model: models.Member, field: 'CreatedByUserId' },
migrationLogs: { model: models.MigrationLog, field: 'CreatedByUserId' },
notifications: { model: models.Notification, field: 'UserId' },
oAuthAuthorizationCodes: { model: models.OAuthAuthorizationCode, field: 'UserId' },
orders: { model: models.Order, field: 'CreatedByUserId' },
paymentMethods: { model: models.PaymentMethod, field: 'CreatedByUserId' },
Expand Down
4 changes: 2 additions & 2 deletions server/lib/notifications/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const notify = {
}

if (!options?.skipUnsubscribedCheck) {
const unsubscribed = await models.Notification.getUnsubscribers({
const unsubscribed = await models.ActivitySubscription.getUnsubscribers({
type: activity.type,
UserId: user.id,
CollectiveId: options?.collective?.id || activity.CollectiveId,
Expand Down Expand Up @@ -110,7 +110,7 @@ export const notify = {
return;
}

const unsubscribed = await models.Notification.getUnsubscribers({
const unsubscribed = await models.ActivitySubscription.getUnsubscribers({
type: activity.type,
CollectiveId: options?.collective?.id || activity.CollectiveId,
channel: Channels.EMAIL,
Expand Down
Loading
Loading