diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-07 18:04:32 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-07 18:04:32 +0900 |
| commit | a28c515ef63a6f9c188cf0a7f544db1afa8e1331 (patch) | |
| tree | 4b207f6998e0697ab5c732c04769b069dfd054c7 /src/server | |
| parent | perf: delete-account処理を軽くする (#7958) (diff) | |
| download | misskey-a28c515ef63a6f9c188cf0a7f544db1afa8e1331.tar.gz misskey-a28c515ef63a6f9c188cf0a7f544db1afa8e1331.tar.bz2 misskey-a28c515ef63a6f9c188cf0a7f544db1afa8e1331.zip | |
feat: make possible to configure following/followers visibility (#7959)
* feat: make possible to configure following/followers visibility
* add test
* ap
* add ap test
* set Cache-Control
* hide following/followers count
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/activitypub/followers.ts | 16 | ||||
| -rw-r--r-- | src/server/activitypub/following.ts | 16 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/update.ts | 5 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/followers.ts | 30 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/following.ts | 30 | ||||
| -rw-r--r-- | src/server/web/feed.ts | 2 |
6 files changed, 92 insertions, 7 deletions
diff --git a/src/server/activitypub/followers.ts b/src/server/activitypub/followers.ts index 8b6a066bf0..baf2d23460 100644 --- a/src/server/activitypub/followers.ts +++ b/src/server/activitypub/followers.ts @@ -8,7 +8,7 @@ import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-colle import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page'; import renderFollowUser from '@/remote/activitypub/renderer/follow-user'; import { setResponseType } from '../activitypub'; -import { Users, Followings } from '@/models/index'; +import { Users, Followings, UserProfiles } from '@/models/index'; import { LessThan } from 'typeorm'; export default async (ctx: Router.RouterContext) => { @@ -38,6 +38,20 @@ export default async (ctx: Router.RouterContext) => { return; } + //#region Check ff visibility + const profile = await UserProfiles.findOneOrFail(user.id); + + if (profile.ffVisibility === 'private') { + ctx.status = 403; + ctx.set('Cache-Control', 'public, max-age=30'); + return; + } else if (profile.ffVisibility === 'followers') { + ctx.status = 403; + ctx.set('Cache-Control', 'public, max-age=30'); + return; + } + //#endregion + const limit = 10; const partOf = `${config.url}/users/${userId}/followers`; diff --git a/src/server/activitypub/following.ts b/src/server/activitypub/following.ts index 5fc5d68a9c..b9eb806c3c 100644 --- a/src/server/activitypub/following.ts +++ b/src/server/activitypub/following.ts @@ -8,7 +8,7 @@ import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-colle import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page'; import renderFollowUser from '@/remote/activitypub/renderer/follow-user'; import { setResponseType } from '../activitypub'; -import { Users, Followings } from '@/models/index'; +import { Users, Followings, UserProfiles } from '@/models/index'; import { LessThan, FindConditions } from 'typeorm'; import { Following } from '@/models/entities/following'; @@ -39,6 +39,20 @@ export default async (ctx: Router.RouterContext) => { return; } + //#region Check ff visibility + const profile = await UserProfiles.findOneOrFail(user.id); + + if (profile.ffVisibility === 'private') { + ctx.status = 403; + ctx.set('Cache-Control', 'public, max-age=30'); + return; + } else if (profile.ffVisibility === 'followers') { + ctx.status = 403; + ctx.set('Cache-Control', 'public, max-age=30'); + return; + } + //#endregion + const limit = 10; const partOf = `${config.url}/users/${userId}/following`; diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts index 3b8b1579ea..d0f201ab60 100644 --- a/src/server/api/endpoints/i/update.ts +++ b/src/server/api/endpoints/i/update.ts @@ -72,6 +72,10 @@ export const meta = { validator: $.optional.bool, }, + ffVisibility: { + validator: $.optional.str, + }, + carefulBot: { validator: $.optional.bool, }, @@ -174,6 +178,7 @@ export default define(meta, async (ps, _user, token) => { if (ps.lang !== undefined) profileUpdates.lang = ps.lang; if (ps.location !== undefined) profileUpdates.location = ps.location; if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday; + if (ps.ffVisibility !== undefined) profileUpdates.ffVisibility = ps.ffVisibility; if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId; if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId; if (ps.mutedWords !== undefined) { diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts index e54b6078ee..6d042a2861 100644 --- a/src/server/api/endpoints/users/followers.ts +++ b/src/server/api/endpoints/users/followers.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import define from '../../define'; import { ApiError } from '../../error'; -import { Users, Followings } from '@/models/index'; +import { Users, Followings, UserProfiles } from '@/models/index'; import { makePaginationQuery } from '../../common/make-pagination-query'; import { toPunyNullable } from '@/misc/convert-host'; @@ -53,7 +53,13 @@ export const meta = { message: 'No such user.', code: 'NO_SUCH_USER', id: '27fa5435-88ab-43de-9360-387de88727cd' - } + }, + + forbidden: { + message: 'Forbidden.', + code: 'FORBIDDEN', + id: '3c6a84db-d619-26af-ca14-06232a21df8a' + }, } }; @@ -66,6 +72,26 @@ export default define(meta, async (ps, me) => { throw new ApiError(meta.errors.noSuchUser); } + const profile = await UserProfiles.findOneOrFail(user.id); + + if (profile.ffVisibility === 'private') { + if (me == null || (me.id !== user.id)) { + throw new ApiError(meta.errors.forbidden); + } + } else if (profile.ffVisibility === 'followers') { + if (me == null) { + throw new ApiError(meta.errors.forbidden); + } else if (me.id !== user.id) { + const following = await Followings.findOne({ + followeeId: user.id, + followerId: me.id, + }); + if (following == null) { + throw new ApiError(meta.errors.forbidden); + } + } + } + const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId) .andWhere(`following.followeeId = :userId`, { userId: user.id }) .innerJoinAndSelect('following.follower', 'follower'); diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts index f2ef7f47e1..1033117ef8 100644 --- a/src/server/api/endpoints/users/following.ts +++ b/src/server/api/endpoints/users/following.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import define from '../../define'; import { ApiError } from '../../error'; -import { Users, Followings } from '@/models/index'; +import { Users, Followings, UserProfiles } from '@/models/index'; import { makePaginationQuery } from '../../common/make-pagination-query'; import { toPunyNullable } from '@/misc/convert-host'; @@ -53,7 +53,13 @@ export const meta = { message: 'No such user.', code: 'NO_SUCH_USER', id: '63e4aba4-4156-4e53-be25-c9559e42d71b' - } + }, + + forbidden: { + message: 'Forbidden.', + code: 'FORBIDDEN', + id: 'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba' + }, } }; @@ -66,6 +72,26 @@ export default define(meta, async (ps, me) => { throw new ApiError(meta.errors.noSuchUser); } + const profile = await UserProfiles.findOneOrFail(user.id); + + if (profile.ffVisibility === 'private') { + if (me == null || (me.id !== user.id)) { + throw new ApiError(meta.errors.forbidden); + } + } else if (profile.ffVisibility === 'followers') { + if (me == null) { + throw new ApiError(meta.errors.forbidden); + } else if (me.id !== user.id) { + const following = await Followings.findOne({ + followeeId: user.id, + followerId: me.id, + }); + if (following == null) { + throw new ApiError(meta.errors.forbidden); + } + } + } + const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId) .andWhere(`following.followerId = :userId`, { userId: user.id }) .innerJoinAndSelect('following.followee', 'followee'); diff --git a/src/server/web/feed.ts b/src/server/web/feed.ts index 4b6de517b7..1d4c47dafb 100644 --- a/src/server/web/feed.ts +++ b/src/server/web/feed.ts @@ -27,7 +27,7 @@ export default async function(user: User) { title: `${author.name} (@${user.username}@${config.host})`, updated: notes[0].createdAt, generator: 'Misskey', - description: `${user.notesCount} Notes, ${user.followingCount} Following, ${user.followersCount} Followers${profile.description ? ` · ${profile.description}` : ''}`, + description: `${user.notesCount} Notes, ${profile.ffVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.ffVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`, link: author.link, image: user.avatarUrl ? user.avatarUrl : undefined, feedLinks: { |