diff options
| author | Hazelnoot <acomputerdog@gmail.com> | 2024-12-12 17:34:29 +0000 |
|---|---|---|
| committer | Hazelnoot <acomputerdog@gmail.com> | 2024-12-12 17:34:29 +0000 |
| commit | d18317a7c8ba7293ff6bdd056ed72aac391b453c (patch) | |
| tree | 50a8b6dec32a152fa60f95b7ecf903d486631b4a /packages/backend/src | |
| parent | merge: Fixed Emoji in usernames of profile's owner not visible in the Pages ... (diff) | |
| parent | fix WebhookTestService.ts (diff) | |
| download | sharkey-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')
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); |