mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-28 03:40:25 +01:00
fix: フォロー・フォロワーの公開状況によってはフォロー関連のチャートを表示できないように
This commit is contained in:
parent
15ae1605ec
commit
8bacd4aa27
4 changed files with 74 additions and 15 deletions
|
@ -3,19 +3,29 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { UserProfilesRepository } from '@/models/_.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { getJsonSchema } from '@/core/chart/core.js';
|
||||
import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js';
|
||||
import { schema } from '@/core/chart/charts/entities/per-user-following.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['charts', 'users', 'following'],
|
||||
|
||||
res: getJsonSchema(schema),
|
||||
|
||||
allowGet: true,
|
||||
cacheSec: 60 * 60,
|
||||
errors: {
|
||||
ffIsMarkedAsPrivate: {
|
||||
message: 'This user\'s followings and/or followers is marked as private.',
|
||||
code: 'FF_IS_MARKED_AS_PRIVATE',
|
||||
id: 'f9c54d7f-d4c2-4d3c-9a8g-a70daac86512',
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -32,10 +42,51 @@ export const paramDef = {
|
|||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
@Inject(DI.userProfilesRepository)
|
||||
private userProfilesRepository: UserProfilesRepository,
|
||||
|
||||
private roleService: RoleService,
|
||||
private userEntityService: UserEntityService,
|
||||
private perUserFollowingChart: PerUserFollowingChart,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
return await this.perUserFollowingChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.userId);
|
||||
const done = async () => {
|
||||
return await this.perUserFollowingChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.userId);
|
||||
};
|
||||
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: ps.userId });
|
||||
|
||||
if (profile.followingVisibility === 'public' && profile.followersVisibility === 'public') {
|
||||
done();
|
||||
}
|
||||
|
||||
const iAmModerator = await this.roleService.isModerator(me);
|
||||
|
||||
if (iAmModerator) {
|
||||
done();
|
||||
}
|
||||
|
||||
if (
|
||||
(profile.followingVisibility === 'private' || profile.followersVisibility === 'private') &&
|
||||
(me != null && profile.userId === me.id)
|
||||
) {
|
||||
done();
|
||||
}
|
||||
|
||||
if (
|
||||
me != null && (
|
||||
(profile.followingVisibility === 'followers' && profile.followersVisibility === 'followers') ||
|
||||
(profile.followingVisibility === 'followers' && profile.followersVisibility === 'public') ||
|
||||
(profile.followingVisibility === 'public' && profile.followersVisibility === 'followers')
|
||||
)
|
||||
) {
|
||||
const relations = await this.userEntityService.getRelation(me.id, ps.userId);
|
||||
if (relations.following) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
throw new ApiError(meta.errors.ffIsMarkedAsPrivate);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ export type ChartSrc =
|
|||
import { onMounted, ref, shallowRef, watch } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApiGet, misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip.js';
|
||||
import { chartVLine } from '@/scripts/chart-vline.js';
|
||||
|
@ -758,8 +758,10 @@ const fetchPerUserPvChart = async (): Promise<typeof chartData> => {
|
|||
};
|
||||
|
||||
const fetchPerUserFollowingChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await misskeyApiGet('charts/user/following', { userId: props.args?.user?.id, limit: props.limit, span: props.span });
|
||||
return {
|
||||
const raw = await misskeyApi('charts/user/following', { userId: props.args?.user?.id!, limit: props.limit, span: props.span }).catch(() => {
|
||||
return null;
|
||||
});
|
||||
return raw != null ? {
|
||||
series: [{
|
||||
name: 'Local',
|
||||
type: 'area',
|
||||
|
@ -769,12 +771,14 @@ const fetchPerUserFollowingChart = async (): Promise<typeof chartData> => {
|
|||
type: 'area',
|
||||
data: format(raw.remote.followings.total),
|
||||
}],
|
||||
};
|
||||
} : raw;
|
||||
};
|
||||
|
||||
const fetchPerUserFollowersChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await misskeyApiGet('charts/user/following', { userId: props.args?.user?.id, limit: props.limit, span: props.span });
|
||||
return {
|
||||
const raw = await misskeyApi('charts/user/following', { userId: props.args?.user?.id!, limit: props.limit, span: props.span }).catch(() => {
|
||||
return null;
|
||||
});
|
||||
return raw != null ? {
|
||||
series: [{
|
||||
name: 'Local',
|
||||
type: 'area',
|
||||
|
@ -784,7 +788,7 @@ const fetchPerUserFollowersChart = async (): Promise<typeof chartData> => {
|
|||
type: 'area',
|
||||
data: format(raw.remote.followers.total),
|
||||
}],
|
||||
};
|
||||
} : raw;
|
||||
};
|
||||
|
||||
const fetchPerUserDriveChart = async (): Promise<typeof chartData> => {
|
||||
|
|
|
@ -32,7 +32,7 @@ const props = defineProps<{
|
|||
user: Misskey.entities.User;
|
||||
}>();
|
||||
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
const chartEl = shallowRef<HTMLCanvasElement>();
|
||||
const legendEl = shallowRef<InstanceType<typeof MkChartLegend>>();
|
||||
const now = new Date();
|
||||
let chartInstance: Chart = null;
|
||||
|
@ -88,7 +88,7 @@ async function renderChart() {
|
|||
}, extra);
|
||||
}
|
||||
|
||||
chartInstance = new Chart(chartEl.value, {
|
||||
chartInstance = new Chart(chartEl.value!, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
datasets: [
|
||||
|
|
|
@ -14,7 +14,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #header><i class="ti ti-pencil"></i> Notes</template>
|
||||
<XNotes :user="user"/>
|
||||
</MkFoldableSection>
|
||||
<MkFoldableSection class="item">
|
||||
<MkFoldableSection
|
||||
v-if="isFollowersVisibleForMe(user) && isFollowingVisibleForMe(user)"
|
||||
class="item"
|
||||
>
|
||||
<template #header><i class="ti ti-users"></i> Following</template>
|
||||
<XFollowing :user="user"/>
|
||||
</MkFoldableSection>
|
||||
|
@ -33,9 +36,10 @@ import XNotes from './activity.notes.vue';
|
|||
import XFollowing from './activity.following.vue';
|
||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||
import MkHeatmap from '@/components/MkHeatmap.vue';
|
||||
import { isFollowersVisibleForMe, isFollowingVisibleForMe } from '@/scripts/isFfVisibleForMe.js';
|
||||
|
||||
const props = defineProps<{
|
||||
user: Misskey.entities.User;
|
||||
user: Misskey.entities.UserDetailed;
|
||||
}>();
|
||||
|
||||
</script>
|
||||
|
|
Loading…
Reference in a new issue