summaryrefslogtreecommitdiff
path: root/packages/backend/src
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2024-12-12 17:34:29 +0000
committerHazelnoot <acomputerdog@gmail.com>2024-12-12 17:34:29 +0000
commitd18317a7c8ba7293ff6bdd056ed72aac391b453c (patch)
tree50a8b6dec32a152fa60f95b7ecf903d486631b4a /packages/backend/src
parentmerge: Fixed Emoji in usernames of profile's owner not visible in the Pages ... (diff)
parentfix WebhookTestService.ts (diff)
downloadsharkey-d18317a7c8ba7293ff6bdd056ed72aac391b453c.tar.gz
sharkey-d18317a7c8ba7293ff6bdd056ed72aac391b453c.tar.bz2
sharkey-d18317a7c8ba7293ff6bdd056ed72aac391b453c.zip
merge: Add "enable RSS" user privacy toggle (resolves #826) (!806)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/806 Closes #826 Approved-by: dakkar <dakkar@thenautilus.net> Approved-by: Marie <github@yuugi.dev>
Diffstat (limited to 'packages/backend/src')
-rw-r--r--packages/backend/src/core/SignupService.ts1
-rw-r--r--packages/backend/src/core/WebhookTestService.ts2
-rw-r--r--packages/backend/src/core/activitypub/ApRendererService.ts1
-rw-r--r--packages/backend/src/core/activitypub/misc/contexts.ts1
-rw-r--r--packages/backend/src/core/activitypub/models/ApPersonService.ts2
-rw-r--r--packages/backend/src/core/activitypub/type.ts1
-rw-r--r--packages/backend/src/core/entities/UserEntityService.ts1
-rw-r--r--packages/backend/src/models/User.ts11
-rw-r--r--packages/backend/src/models/json-schema/user.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/i/update.ts20
-rw-r--r--packages/backend/src/server/web/ClientServerService.ts1
11 files changed, 39 insertions, 6 deletions
diff --git a/packages/backend/src/core/SignupService.ts b/packages/backend/src/core/SignupService.ts
index 1b0b1e5bbd..3f0523b610 100644
--- a/packages/backend/src/core/SignupService.ts
+++ b/packages/backend/src/core/SignupService.ts
@@ -135,6 +135,7 @@ export class SignupService {
isRoot: isTheFirstUser,
approved: isTheFirstUser || (opts.approved ?? !this.meta.approvalRequiredForSignup),
signupReason: reason,
+ enableRss: false,
}));
await transactionalEntityManager.save(new MiUserKeypair({
diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts
index 4a31c1d17a..a72a82ede6 100644
--- a/packages/backend/src/core/WebhookTestService.ts
+++ b/packages/backend/src/core/WebhookTestService.ts
@@ -85,6 +85,7 @@ function generateDummyUser(override?: Partial<MiUser>): MiUser {
approved: true,
signupReason: null,
noindex: false,
+ enableRss: true,
...override,
};
}
@@ -201,6 +202,7 @@ function toPackedUserLite(user: MiUser, override?: Packed<'UserLite'>): Packed<'
isAdmin: false,
isSystem: false,
isSilenced: user.isSilenced,
+ enableRss: true,
...override,
};
}
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
index ff909778e8..57489c754f 100644
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
@@ -531,6 +531,7 @@ export class ApRendererService {
hideOnlineStatus: user.hideOnlineStatus,
noindex: user.noindex,
indexable: !user.noindex,
+ enableRss: user.enableRss,
speakAsCat: user.speakAsCat,
attachment: attachment.length ? attachment : undefined,
};
diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts
index 1c4239502e..9c2640758f 100644
--- a/packages/backend/src/core/activitypub/misc/contexts.ts
+++ b/packages/backend/src/core/activitypub/misc/contexts.ts
@@ -567,6 +567,7 @@ const extension_context_definition = {
hideOnlineStatus: 'sharkey:hideOnlineStatus',
backgroundUrl: 'sharkey:backgroundUrl',
listenbrainz: 'sharkey:listenbrainz',
+ enableRss: 'sharkey:enableRss',
// vcard
vcard: 'http://www.w3.org/2006/vcard/ns#',
} satisfies Context;
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index 2cb31b1f09..b1bd379861 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -385,6 +385,7 @@ export class ApPersonService implements OnModuleInit {
lastFetchedAt: new Date(),
name: truncate(person.name, nameLength),
noindex: (person as any).noindex ?? false,
+ enableRss: person.enableRss === true,
isLocked: person.manuallyApprovesFollowers,
movedToUri: person.movedTo,
movedAt: person.movedTo ? new Date() : null,
@@ -584,6 +585,7 @@ export class ApPersonService implements OnModuleInit {
isCat: (person as any).isCat === true,
speakAsCat: (person as any).speakAsCat != null ? (person as any).speakAsCat === true : (person as any).isCat === true,
noindex: (person as any).noindex ?? false,
+ enableRss: person.enableRss === true,
isLocked: person.manuallyApprovesFollowers,
movedToUri: person.movedTo ?? null,
alsoKnownAs: person.alsoKnownAs ?? null,
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index a0a5ae00dc..6da382e3ec 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -217,6 +217,7 @@ export interface IActor extends IObject {
'vcard:Address'?: string;
hideOnlineStatus?: boolean;
noindex?: boolean;
+ enableRss?: boolean;
listenbrainz?: string;
backgroundUrl?: string;
}
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index b1832ca0f5..8a48c8c6b4 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -539,6 +539,7 @@ export class UserEntityService implements OnModuleInit {
isBot: user.isBot,
isCat: user.isCat,
noindex: user.noindex,
+ enableRss: user.enableRss,
isSilenced: user.isSilenced || this.roleService.getUserPolicies(user.id).then(r => !r.canPublicNote),
speakAsCat: user.speakAsCat ?? false,
approved: user.approved,
diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts
index 73a44de558..35477fe009 100644
--- a/packages/backend/src/models/User.ts
+++ b/packages/backend/src/models/User.ts
@@ -311,6 +311,17 @@ export class MiUser {
})
public signupReason: string | null;
+ /**
+ * True if profile RSS feeds are enabled for this user.
+ * Enabled by default (opt-out) for existing users, to avoid breaking any existing feeds.
+ * Disabled by default (opt-in) for newly created users, for privacy.
+ */
+ @Column('boolean', {
+ name: 'enable_rss',
+ default: true,
+ })
+ public enableRss: boolean;
+
constructor(data: Partial<MiUser>) {
if (data == null) return;
diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts
index d5e847cc40..12ed1f2009 100644
--- a/packages/backend/src/models/json-schema/user.ts
+++ b/packages/backend/src/models/json-schema/user.ts
@@ -130,6 +130,10 @@ export const packedUserLiteSchema = {
type: 'boolean',
nullable: false, optional: false,
},
+ enableRss: {
+ type: 'boolean',
+ nullable: false, optional: false,
+ },
isBot: {
type: 'boolean',
nullable: false, optional: true,
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index c640caee75..c22cbe5d4b 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -187,6 +187,7 @@ export const paramDef = {
noCrawle: { type: 'boolean' },
preventAiLearning: { type: 'boolean' },
noindex: { type: 'boolean' },
+ enableRss: { type: 'boolean' },
isBot: { type: 'boolean' },
isCat: { type: 'boolean' },
speakAsCat: { type: 'boolean' },
@@ -337,6 +338,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (typeof ps.hideOnlineStatus === 'boolean') updates.hideOnlineStatus = ps.hideOnlineStatus;
if (typeof ps.publicReactions === 'boolean') profileUpdates.publicReactions = ps.publicReactions;
if (typeof ps.noindex === 'boolean') updates.noindex = ps.noindex;
+ if (typeof ps.enableRss === 'boolean') updates.enableRss = ps.enableRss;
if (typeof ps.isBot === 'boolean') updates.isBot = ps.isBot;
if (typeof ps.carefulBot === 'boolean') profileUpdates.carefulBot = ps.carefulBot;
if (typeof ps.autoAcceptFollowed === 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed;
@@ -587,12 +589,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// these two methods need to be kept in sync with
// `ApRendererService.renderPerson`
private userNeedsPublishing(oldUser: MiLocalUser, newUser: Partial<MiUser>): boolean {
- for (const field of ['avatarId', 'bannerId', 'backgroundId', 'isBot', 'username', 'name', 'isLocked', 'isExplorable', 'isCat', 'noindex', 'speakAsCat', 'movedToUri', 'alsoKnownAs', 'hideOnlineStatus'] as (keyof MiUser)[]) {
+ const basicFields: (keyof MiUser)[] = ['avatarId', 'bannerId', 'backgroundId', 'isBot', 'username', 'name', 'isLocked', 'isExplorable', 'isCat', 'noindex', 'speakAsCat', 'movedToUri', 'alsoKnownAs', 'hideOnlineStatus', 'enableRss'];
+ for (const field of basicFields) {
if ((field in newUser) && oldUser[field] !== newUser[field]) {
return true;
}
}
- for (const arrayField of ['emojis', 'tags'] as (keyof MiUser)[]) {
+
+ const arrayFields: (keyof MiUser)[] = ['emojis', 'tags'];
+ for (const arrayField of arrayFields) {
if ((arrayField in newUser) !== (arrayField in oldUser)) {
return true;
}
@@ -602,7 +607,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (!Array.isArray(oldArray) || !Array.isArray(newArray)) {
return true;
}
- if (oldArray.join("\0") !== newArray.join("\0")) {
+ if (oldArray.join('\0') !== newArray.join('\0')) {
return true;
}
}
@@ -610,12 +615,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
private profileNeedsPublishing(oldProfile: MiUserProfile, newProfile: Partial<MiUserProfile>): boolean {
- for (const field of ['description', 'followedMessage', 'birthday', 'location', 'listenbrainz'] as (keyof MiUserProfile)[]) {
+ const basicFields: (keyof MiUserProfile)[] = ['description', 'followedMessage', 'birthday', 'location', 'listenbrainz'];
+ for (const field of basicFields) {
if ((field in newProfile) && oldProfile[field] !== newProfile[field]) {
return true;
}
}
- for (const arrayField of ['fields'] as (keyof MiUserProfile)[]) {
+
+ const arrayFields: (keyof MiUserProfile)[] = ['fields'];
+ for (const arrayField of arrayFields) {
if ((arrayField in newProfile) !== (arrayField in oldProfile)) {
return true;
}
@@ -625,7 +633,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (!Array.isArray(oldArray) || !Array.isArray(newArray)) {
return true;
}
- if (oldArray.join("\0") !== newArray.join("\0")) {
+ if (oldArray.join('\0') !== newArray.join('\0')) {
return true;
}
}
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index aca98c4d37..42f9b104ff 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -510,6 +510,7 @@ export class ClientServerService {
usernameLower: username.toLowerCase(),
host: host ?? IsNull(),
isSuspended: false,
+ enableRss: true,
});
return user && await this.feedService.packFeed(user);