Make admin quotas editable and simplify uploader storage
This commit is contained in:
15
scripts/reset-nas-transfer-data.sh
Normal file
15
scripts/reset-nas-transfer-data.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
# One-time reset for prelaunch data; preserves registered accounts and admin settings.
|
||||
set -eu
|
||||
cd "$(dirname "$0")/.."
|
||||
if [ "$(docker inspect --format '{{.State.Running}}' hop)" != false ]; then
|
||||
printf '%s\n' 'hop 프로젝트를 먼저 중지하세요. 실행 중에는 초기화할 수 없습니다.' >&2
|
||||
exit 1
|
||||
fi
|
||||
hop_reset_image=$(docker inspect --format '{{.Image}}' hop)
|
||||
hop_reset_user=$(docker inspect --format '{{.Config.User}}' hop)
|
||||
# Use the stopped container's exact database volume, image and user, with no network or app process.
|
||||
docker run --rm --network none --volumes-from hop --user "$hop_reset_user" \
|
||||
--mount "type=bind,source=$PWD/scripts/reset-transfer-records.mjs,target=/app/scripts/reset-transfer-records.mjs,readonly" \
|
||||
--env DATABASE_PATH=/data/database/hop.sqlite \
|
||||
--entrypoint node "$hop_reset_image" /app/scripts/reset-transfer-records.mjs --confirm-reset-transfer-records
|
||||
51
scripts/reset-transfer-records.mjs
Normal file
51
scripts/reset-transfer-records.mjs
Normal file
@@ -0,0 +1,51 @@
|
||||
// Offline maintenance only. The NAS wrapper checks that hop is stopped first.
|
||||
import Database from 'better-sqlite3';
|
||||
if (!process.argv.includes('--confirm-reset-transfer-records')) {
|
||||
throw Error('전송·보관 기록 초기화에는 --confirm-reset-transfer-records가 필요합니다.');
|
||||
}
|
||||
const path = process.env.DATABASE_PATH;
|
||||
if (!path || path === ':memory:') throw Error('기존 DATABASE_PATH를 지정하세요.');
|
||||
const database = new Database(path, { fileMustExist: true });
|
||||
try {
|
||||
database.pragma('foreign_keys = ON');
|
||||
database.pragma('busy_timeout = 5000');
|
||||
const tables = [
|
||||
'vault_transfers',
|
||||
'request_receipt_accounts',
|
||||
'deletion_targets',
|
||||
'deletion_operations',
|
||||
'item_access',
|
||||
'items',
|
||||
'quota_reservations',
|
||||
'file_upload_contexts',
|
||||
'files',
|
||||
'transfer_batches',
|
||||
'transfer_requests',
|
||||
'idempotency_records',
|
||||
'guest_blocks',
|
||||
'space_members',
|
||||
'connection_spaces',
|
||||
'browser_devices',
|
||||
'guest_sessions',
|
||||
];
|
||||
const existing = new Set(
|
||||
database
|
||||
.prepare("SELECT name FROM sqlite_master WHERE type = 'table'")
|
||||
.all()
|
||||
.map((row) => row.name),
|
||||
);
|
||||
const users = database.prepare('SELECT count(*) AS count FROM users').get().count;
|
||||
database.transaction(() => {
|
||||
for (const table of tables) if (existing.has(table)) database.exec(`DELETE FROM "${table}"`);
|
||||
if (database.pragma('foreign_key_check').length) throw Error('외래 키 검사 실패');
|
||||
if (database.prepare('SELECT count(*) AS count FROM users').get().count !== users)
|
||||
throw Error('계정 수 검사 실패');
|
||||
})();
|
||||
database.pragma('wal_checkpoint(TRUNCATE)');
|
||||
console.log(`전송·보관 기록 초기화 완료. 계정 ${users}개와 인증·관리 설정은 유지했습니다.`);
|
||||
console.log(
|
||||
'uploads 폴더의 내용은 삭제하지 않았습니다. 서비스가 중지된 동안 폴더 안의 내용을 비운 뒤 재배포하세요.',
|
||||
);
|
||||
} finally {
|
||||
database.close();
|
||||
}
|
||||
Reference in New Issue
Block a user