diff --git a/locales/en-US.yml b/locales/en-US.yml index 0a996922e..dc7bb0676 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -479,6 +479,7 @@ youHaveNoGroups: "You have no groups" joinOrCreateGroup: "Get invited to a group or create your own." noHistory: "No history available" signinHistory: "Login history" +signinHistoryExpires: "Data about past login attempts is automatically deleted after 60 days to comply with privacy regulations." disableAnimatedMfm: "Disable MFM with animation" doing: "Processing..." category: "Category" diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index 83ad15322..d558ff739 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -74,7 +74,6 @@ export async function masterMain(): Promise { if (!envOption.noDaemons) { import('../daemons/server-stats.js').then(x => x.serverStats()); import('../daemons/queue-stats.js').then(x => x.queueStats()); - import('../daemons/janitor.js').then(x => x.janitor()); } } diff --git a/packages/backend/src/daemons/janitor.ts b/packages/backend/src/daemons/janitor.ts deleted file mode 100644 index 06f32814f..000000000 --- a/packages/backend/src/daemons/janitor.ts +++ /dev/null @@ -1,21 +0,0 @@ -// TODO: 消したい - -import { LessThan } from 'typeorm'; -import { AttestationChallenges } from '@/models/index.js'; - -const interval = 30 * 60 * 1000; - -/** - * Clean up database occasionally - */ -export function janitor(): void { - async function tick(): Promise { - await AttestationChallenges.delete({ - createdAt: LessThan(new Date(new Date().getTime() - 5 * 60 * 1000)), - }); - } - - tick(); - - setInterval(tick, interval); -} diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index b3a5862f0..05ad4c927 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -314,7 +314,7 @@ export default function() { removeOnComplete: true, }); - systemQueue.add('checkExpiredMutings', { + systemQueue.add('checkExpired', { }, { repeat: { cron: '*/5 * * * *' }, removeOnComplete: true, diff --git a/packages/backend/src/queue/processors/system/check-expired-mutings.ts b/packages/backend/src/queue/processors/system/check-expired-mutings.ts deleted file mode 100644 index 93840403f..000000000 --- a/packages/backend/src/queue/processors/system/check-expired-mutings.ts +++ /dev/null @@ -1,30 +0,0 @@ -import Bull from 'bull'; -import { In } from 'typeorm'; -import { Mutings } from '@/models/index.js'; -import { publishUserEvent } from '@/services/stream.js'; -import { queueLogger } from '@/queue/logger.js'; - -const logger = queueLogger.createSubLogger('check-expired-mutings'); - -export async function checkExpiredMutings(job: Bull.Job>, done: any): Promise { - logger.info('Checking expired mutings...'); - - const expired = await Mutings.createQueryBuilder('muting') - .where('muting.expiresAt IS NOT NULL') - .andWhere('muting.expiresAt < :now', { now: new Date() }) - .innerJoinAndSelect('muting.mutee', 'mutee') - .getMany(); - - if (expired.length > 0) { - await Mutings.delete({ - id: In(expired.map(m => m.id)), - }); - - for (const m of expired) { - publishUserEvent(m.muterId, 'unmute', m.mutee!); - } - } - - logger.succ('All expired mutings checked.'); - done(); -} diff --git a/packages/backend/src/queue/processors/system/check-expired.ts b/packages/backend/src/queue/processors/system/check-expired.ts new file mode 100644 index 000000000..7078d3ccb --- /dev/null +++ b/packages/backend/src/queue/processors/system/check-expired.ts @@ -0,0 +1,41 @@ +import Bull from 'bull'; +import { In, LessThan } from 'typeorm'; +import { AttestationChallenges, Mutings, Signins } from '@/models/index.js'; +import { publishUserEvent } from '@/services/stream.js'; +import { MINUTE, DAY } from '@/const.js'; +import { queueLogger } from '@/queue/logger.js'; + +const logger = queueLogger.createSubLogger('check-expired'); + +export async function checkExpired(job: Bull.Job>, done: any): Promise { + logger.info('Checking expired data...'); + + const expiredMutings = await Mutings.createQueryBuilder('muting') + .where('muting.expiresAt IS NOT NULL') + .andWhere('muting.expiresAt < :now', { now: new Date() }) + .innerJoinAndSelect('muting.mutee', 'mutee') + .getMany(); + + if (expiredMutings.length > 0) { + await Mutings.delete({ + id: In(expiredMutings.map(m => m.id)), + }); + + for (const m of expiredMutings) { + publishUserEvent(m.muterId, 'unmute', m.mutee!); + } + } + + await Signins.delete({ + // 60 days, or roughly equal to two months + createdAt: LessThan(new Date(new Date().getTime() - 60 * DAY)), + }); + + await AttestationChallenges.delete({ + createdAt: LessThan(new Date(new Date().getTime() - 5 * MINUTE)), + }); + + logger.succ('Deleted expired mutes, signins and attestation challenges.'); + + done(); +} diff --git a/packages/backend/src/queue/processors/system/index.ts b/packages/backend/src/queue/processors/system/index.ts index f90f6efaf..3651f8790 100644 --- a/packages/backend/src/queue/processors/system/index.ts +++ b/packages/backend/src/queue/processors/system/index.ts @@ -2,13 +2,13 @@ import Bull from 'bull'; import { tickCharts } from './tick-charts.js'; import { resyncCharts } from './resync-charts.js'; import { cleanCharts } from './clean-charts.js'; -import { checkExpiredMutings } from './check-expired-mutings.js'; +import { checkExpired } from './check-expired.js'; const jobs = { tickCharts, resyncCharts, cleanCharts, - checkExpiredMutings, + checkExpired, } as Record> | Bull.ProcessPromiseFunction>>; export default function(dbQueue: Bull.Queue>) { diff --git a/packages/client/src/pages/settings/security.vue b/packages/client/src/pages/settings/security.vue index 83c22864a..ca5f0f5a4 100644 --- a/packages/client/src/pages/settings/security.vue +++ b/packages/client/src/pages/settings/security.vue @@ -12,20 +12,24 @@ - - + + + +