リアクション一覧の公開をオプトインに
This commit is contained in:
		
							parent
							
								
									1bfb176667
								
							
						
					
					
						commit
						7413634734
					
				
					 9 changed files with 51 additions and 4 deletions
				
			
		|  | @ -10,7 +10,8 @@ | |||
| ## 12.x.x (unreleased) | ||||
| 
 | ||||
| ### Improvements | ||||
| - クライアント: ユーザーのリアクション一覧を見れるように | ||||
| - クライアント: 自分のリアクション一覧を見れるように | ||||
| 	- 設定により、リアクション一覧を全員に公開することも可能 | ||||
| - クライアント: ユーザー検索の精度を強化 | ||||
| - クライアント: 新しいライトテーマを追加 | ||||
| - API: ユーザーのリアクション一覧を取得する users/reactions を追加 | ||||
|  |  | |||
|  | @ -797,6 +797,8 @@ unread: "未読" | |||
| filter: "フィルタ" | ||||
| controllPanel: "コントロールパネル" | ||||
| manageAccounts: "アカウントを管理" | ||||
| makeReactionsPublic: "リアクション一覧を公開する" | ||||
| makeReactionsPublicDescription: "あなたがしたリアクション一覧を誰でも見れるようにします。" | ||||
| 
 | ||||
| _signup: | ||||
|   almostThere: "ほとんど完了です" | ||||
|  |  | |||
							
								
								
									
										14
									
								
								migration/1634486652000-user-public-reactions.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								migration/1634486652000-user-public-reactions.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| import {MigrationInterface, QueryRunner} from "typeorm"; | ||||
| 
 | ||||
| export class userPublicReactions1634486652000 implements MigrationInterface { | ||||
|     name = 'userPublicReactions1634486652000' | ||||
| 
 | ||||
|     public async up(queryRunner: QueryRunner): Promise<void> { | ||||
| 			await queryRunner.query(`ALTER TABLE "user_profile" ADD "publicReactions" boolean NOT NULL DEFAULT false`); | ||||
|     } | ||||
| 
 | ||||
|     public async down(queryRunner: QueryRunner): Promise<void> { | ||||
|         await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "publicReactions"`); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -5,6 +5,10 @@ | |||
| 		<FormSwitch v-model="autoAcceptFollowed" :disabled="!isLocked" @update:modelValue="save()">{{ $ts.autoAcceptFollowed }}</FormSwitch> | ||||
| 		<template #caption>{{ $ts.lockedAccountInfo }}</template> | ||||
| 	</FormGroup> | ||||
| 	<FormSwitch v-model="publicReactions" @update:modelValue="save()"> | ||||
| 		{{ $ts.makeReactionsPublic }} | ||||
| 		<template #desc>{{ $ts.makeReactionsPublicDescription }}</template> | ||||
| 	</FormSwitch> | ||||
| 	<FormSwitch v-model="hideOnlineStatus" @update:modelValue="save()"> | ||||
| 		{{ $ts.hideOnlineStatus }} | ||||
| 		<template #desc>{{ $ts.hideOnlineStatusDescription }}</template> | ||||
|  | @ -64,6 +68,7 @@ export default defineComponent({ | |||
| 			noCrawle: false, | ||||
| 			isExplorable: false, | ||||
| 			hideOnlineStatus: false, | ||||
| 			publicReactions: false, | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -80,6 +85,7 @@ export default defineComponent({ | |||
| 		this.noCrawle = this.$i.noCrawle; | ||||
| 		this.isExplorable = this.$i.isExplorable; | ||||
| 		this.hideOnlineStatus = this.$i.hideOnlineStatus; | ||||
| 		this.publicReactions = this.$i.publicReactions; | ||||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
|  | @ -94,6 +100,7 @@ export default defineComponent({ | |||
| 				noCrawle: !!this.noCrawle, | ||||
| 				isExplorable: !!this.isExplorable, | ||||
| 				hideOnlineStatus: !!this.hideOnlineStatus, | ||||
| 				publicReactions: !!this.publicReactions, | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -270,12 +270,12 @@ export default defineComponent({ | |||
| 					title: this.$ts.overview, | ||||
| 					icon: 'fas fa-home', | ||||
| 					onClick: () => { this.$router.push('/@' + getAcct(this.user)); }, | ||||
| 				}, { | ||||
| 				}, ...(this.$i && (this.$i.id === this.user.id)) || this.user.publicReactions ? [{ | ||||
| 					active: this.page === 'reactions', | ||||
| 					title: this.$ts.reaction, | ||||
| 					icon: 'fas fa-laugh', | ||||
| 					onClick: () => { this.$router.push('/@' + getAcct(this.user) + '/reactions'); }, | ||||
| 				}, { | ||||
| 				}] : [], { | ||||
| 					active: this.page === 'clips', | ||||
| 					title: this.$ts.clips, | ||||
| 					icon: 'fas fa-paperclip', | ||||
|  |  | |||
|  | @ -75,6 +75,11 @@ export class UserProfile { | |||
| 	}) | ||||
| 	public emailNotificationTypes: string[]; | ||||
| 
 | ||||
| 	@Column('boolean', { | ||||
| 		default: false, | ||||
| 	}) | ||||
| 	public publicReactions: boolean; | ||||
| 
 | ||||
| 	@Column('varchar', { | ||||
| 		length: 128, nullable: true, | ||||
| 	}) | ||||
|  |  | |||
|  | @ -231,6 +231,7 @@ export class UserRepository extends Repository<User> { | |||
| 				}), | ||||
| 				pinnedPageId: profile!.pinnedPageId, | ||||
| 				pinnedPage: profile!.pinnedPageId ? Pages.pack(profile!.pinnedPageId, me) : null, | ||||
| 				publicReactions: profile!.publicReactions, | ||||
| 				twoFactorEnabled: profile!.twoFactorEnabled, | ||||
| 				usePasswordLessLogin: profile!.usePasswordLessLogin, | ||||
| 				securityKeys: profile!.twoFactorEnabled | ||||
|  |  | |||
|  | @ -68,6 +68,10 @@ export const meta = { | |||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		publicReactions: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		carefulBot: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
|  | @ -180,6 +184,7 @@ export default define(meta, async (ps, _user, token) => { | |||
| 	if (typeof ps.isLocked === 'boolean') updates.isLocked = ps.isLocked; | ||||
| 	if (typeof ps.isExplorable === 'boolean') updates.isExplorable = ps.isExplorable; | ||||
| 	if (typeof ps.hideOnlineStatus === 'boolean') updates.hideOnlineStatus = ps.hideOnlineStatus; | ||||
| 	if (typeof ps.publicReactions === 'boolean') profileUpdates.publicReactions = ps.publicReactions; | ||||
| 	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; | ||||
|  |  | |||
|  | @ -1,9 +1,10 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { NoteReactions } from '@/models/index'; | ||||
| import { NoteReactions, UserProfiles } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../common/make-pagination-query'; | ||||
| import { generateVisibilityQuery } from '../../common/generate-visibility-query'; | ||||
| import { ApiError } from '../../error'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['users', 'reactions'], | ||||
|  | @ -48,10 +49,21 @@ export const meta = { | |||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		reactionsNotPublic: { | ||||
| 			message: 'Reactions of the user is not public.', | ||||
| 			code: 'REACTIONS_NOT_PUBLIC', | ||||
| 			id: '673a7dd2-6924-1093-e0c0-e68456ceae5c' | ||||
| 		}, | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| 	const profile = await UserProfiles.findOneOrFail(ps.userId); | ||||
| 
 | ||||
| 	if (me == null || (me.id !== ps.userId && !profile.publicReactions)) { | ||||
| 		throw new ApiError(meta.errors.reactionsNotPublic); | ||||
| 	} | ||||
| 
 | ||||
| 	const query = makePaginationQuery(NoteReactions.createQueryBuilder('reaction'), | ||||
| 			ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) | ||||
| 		.andWhere(`reaction.userId = :userId`, { userId: ps.userId }) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue