From b7a6ccfef916aac26bc2b4df8ba366ca75d0d979 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Mon, 9 Dec 2024 09:29:42 -0500 Subject: enable hideOnlineStatus by default for new users --- packages/backend/src/models/User.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/backend/src/models') diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts index c7ecccf1cf..73a44de558 100644 --- a/packages/backend/src/models/User.ts +++ b/packages/backend/src/models/User.ts @@ -32,7 +32,7 @@ export class MiUser { public lastActiveDate: Date | null; @Column('boolean', { - default: false, + default: true, }) public hideOnlineStatus: boolean; @@ -160,7 +160,7 @@ export class MiUser { length: 128, nullable: true, }) public backgroundBlurhash: string | null; - + @Column('jsonb', { default: [], }) -- cgit v1.2.3-freya From fe37aa2ce851dfba4cb7b47ee569d20272b7f75e Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Mon, 9 Dec 2024 09:11:39 -0500 Subject: Add "enable RSS" user privacy toggle --- locales/index.d.ts | 8 ++++++++ .../backend/migration/1733748798177-add_user_enableRss.js | 13 +++++++++++++ packages/backend/src/core/SignupService.ts | 1 + packages/backend/src/core/activitypub/ApRendererService.ts | 1 + packages/backend/src/core/activitypub/misc/contexts.ts | 1 + .../backend/src/core/activitypub/models/ApPersonService.ts | 2 ++ packages/backend/src/core/activitypub/type.ts | 1 + packages/backend/src/core/entities/UserEntityService.ts | 1 + packages/backend/src/models/User.ts | 11 +++++++++++ packages/backend/src/models/json-schema/user.ts | 4 ++++ packages/backend/src/server/api/endpoints/i/update.ts | 2 ++ packages/backend/src/server/web/ClientServerService.ts | 1 + packages/frontend/src/pages/settings/privacy.vue | 6 ++++++ packages/misskey-js/src/autogen/types.ts | 2 ++ sharkey-locales/en-US.yml | 2 ++ 15 files changed, 56 insertions(+) create mode 100644 packages/backend/migration/1733748798177-add_user_enableRss.js (limited to 'packages/backend/src/models') diff --git a/locales/index.d.ts b/locales/index.d.ts index 7ab1b7f545..3ffa402598 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -10847,6 +10847,14 @@ export interface Locale extends ILocale { * Stop note search from indexing your public notes. */ "makeIndexableDescription": string; + /** + * Enable RSS feed + */ + "enableRss": string; + /** + * Generate an RSS feed containing your basic profile details and public notes. Users can subscribe to the feed without a follow request or approval. + */ + "enableRssDescription": string; /** * Require approval for new users */ diff --git a/packages/backend/migration/1733748798177-add_user_enableRss.js b/packages/backend/migration/1733748798177-add_user_enableRss.js new file mode 100644 index 0000000000..64662ca7b8 --- /dev/null +++ b/packages/backend/migration/1733748798177-add_user_enableRss.js @@ -0,0 +1,13 @@ +export class AddUserEnableRss1733748798177 { + name = 'AddUserEnableRss1733748798177' + + async up(queryRunner) { + // Disable by default, then specifically enable for all existing local users. + await queryRunner.query(`ALTER TABLE "user" ADD "enable_rss" boolean NOT NULL DEFAULT false`); + await queryRunner.query(`UPDATE "user" SET "enable_rss" = true WHERE host IS NULL;`) + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "enable_rss"`); + } +} 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/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..8420b5b129 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 = true; + constructor(data: Partial) { 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..cae2964628 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 { // 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; 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); diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue index b155d6e316..dccfb584ae 100644 --- a/packages/frontend/src/pages/settings/privacy.vue +++ b/packages/frontend/src/pages/settings/privacy.vue @@ -43,6 +43,10 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.makeExplorable }} + + {{ i18n.ts.enableRss }} + +
@@ -89,6 +93,7 @@ const isLocked = ref($i.isLocked); const autoAcceptFollowed = ref($i.autoAcceptFollowed); const noCrawle = ref($i.noCrawle); const noindex = ref($i.noindex); +const enableRss = ref($i.enableRss); const isExplorable = ref($i.isExplorable); const hideOnlineStatus = ref($i.hideOnlineStatus); const publicReactions = ref($i.publicReactions); @@ -106,6 +111,7 @@ function save() { autoAcceptFollowed: !!autoAcceptFollowed.value, noCrawle: !!noCrawle.value, noindex: !!noindex.value, + enableRss: !!enableRss.value, isExplorable: !!isExplorable.value, hideOnlineStatus: !!hideOnlineStatus.value, publicReactions: !!publicReactions.value, diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 29c2e814d2..b161698f27 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -3913,6 +3913,7 @@ export type components = { /** @default false */ isSystem?: boolean; noindex: boolean; + enableRss: boolean; isBot?: boolean; isCat?: boolean; speakAsCat?: boolean; @@ -21320,6 +21321,7 @@ export type operations = { noCrawle?: boolean; preventAiLearning?: boolean; noindex?: boolean; + enableRss?: boolean; isBot?: boolean; isCat?: boolean; speakAsCat?: boolean; diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml index f15646a156..4e462edda7 100644 --- a/sharkey-locales/en-US.yml +++ b/sharkey-locales/en-US.yml @@ -88,6 +88,8 @@ searchEngineCustomURIDescription: "The custom URI must be input in the format li searchEngineCusomURI: "Custom URI" makeIndexable: "Make public notes not indexable" makeIndexableDescription: "Stop note search from indexing your public notes." +enableRss: "Enable RSS feed" +enableRssDescription: "Generate an RSS feed containing your basic profile details and public notes. Users can subscribe to the feed without a follow request or approval." sendErrorReportsDescription: "When turned on, detailed error information will be shared with Sharkey when a problem occurs, helping to improve the quality of Sharkey.\nThis will include information such the version of your OS, what browser you're using, your activity in Sharkey, etc." noInquiryUrlWarning: "Contact URL is not set." misskeyUpdated: "Sharkey has been updated!" -- cgit v1.2.3-freya From d95ec3de5ffd36c84c84887a2a18a63a239e1f8f Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Thu, 12 Dec 2024 07:32:01 -0500 Subject: fix declaration of `User.enableRss` property --- packages/backend/src/models/User.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/backend/src/models') diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts index 8420b5b129..35477fe009 100644 --- a/packages/backend/src/models/User.ts +++ b/packages/backend/src/models/User.ts @@ -320,7 +320,7 @@ export class MiUser { name: 'enable_rss', default: true, }) - public enableRss = true; + public enableRss: boolean; constructor(data: Partial) { if (data == null) return; -- cgit v1.2.3-freya