files: replace ttl with expires_at
This commit is contained in:
parent
33947012e4
commit
c8d7c664e2
@ -44,6 +44,7 @@ import MakeMagicLinksSessionNotUniqueMigration from "swaf/auth/magic_link/MakeMa
|
||||
import AddPasswordToUsersMigration from "swaf/auth/password/AddPasswordToUsersMigration";
|
||||
import DropNameFromUsers from "swaf/auth/migrations/DropNameFromUsers";
|
||||
import packageJson = require('./package.json');
|
||||
import ReplaceTtlWithExpiresAtFilesTable from "./migrations/ReplaceTtlWithExpiresAtFilesTable";
|
||||
|
||||
export default class App extends Application {
|
||||
public constructor(
|
||||
@ -69,7 +70,8 @@ export default class App extends Application {
|
||||
AddUsedToMagicLinksMigration,
|
||||
MakeMagicLinksSessionNotUniqueMigration,
|
||||
AddPasswordToUsersMigration,
|
||||
DropNameFromUsers,
|
||||
DummyMigration,
|
||||
ReplaceTtlWithExpiresAtFilesTable,
|
||||
];
|
||||
}
|
||||
|
||||
|
46
src/migrations/ReplaceTtlWithExpiresAtFilesTable.ts
Normal file
46
src/migrations/ReplaceTtlWithExpiresAtFilesTable.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import Migration from "swaf/db/Migration";
|
||||
import FileModel from "../models/FileModel";
|
||||
import {logger} from "swaf/Logger";
|
||||
|
||||
export default class ReplaceTtlWithExpiresAtFilesTable extends Migration {
|
||||
public async install(): Promise<void> {
|
||||
await this.query(`ALTER TABLE files
|
||||
ADD COLUMN expires_at DATETIME NULL`);
|
||||
|
||||
const files = await FileModel.select().get();
|
||||
for (const file of files) {
|
||||
logger.debug(file);
|
||||
if (file.created_at && typeof file.ttl === 'number' && file.ttl > 0) {
|
||||
file.expires_at = new Date(file.created_at.getTime() + file.ttl * 1000);
|
||||
}
|
||||
const callbacks: (() => Promise<void>)[] = [];
|
||||
await file.save(this.getCurrentConnection(), callback => {
|
||||
callbacks.push(callback);
|
||||
});
|
||||
for (const c of callbacks) await c();
|
||||
}
|
||||
|
||||
await this.query(`ALTER TABLE files
|
||||
DROP COLUMN ttl`);
|
||||
}
|
||||
|
||||
public async rollback(): Promise<void> {
|
||||
await this.query(`ALTER TABLE files
|
||||
ADD COLUMN ttl INT UNSIGNED NOT NULL DEFAULT 0`);
|
||||
|
||||
const files = await FileModel.select().get();
|
||||
for (const file of files) {
|
||||
if (file.created_at && file.expires_at) {
|
||||
file.ttl = Math.ceil((file.expires_at.getTime() - file.created_at.getTime()) / 1000);
|
||||
}
|
||||
const callbacks: (() => Promise<void>)[] = [];
|
||||
await file.save(this.getCurrentConnection(), callback => {
|
||||
callbacks.push(callback);
|
||||
});
|
||||
for (const c of callbacks) await c();
|
||||
}
|
||||
|
||||
await this.query(`ALTER TABLE files
|
||||
DROP COLUMN expires_at`);
|
||||
}
|
||||
}
|
@ -28,16 +28,22 @@ export default class FileModel extends Model {
|
||||
public readonly storage_path?: string = undefined;
|
||||
public readonly size?: number = undefined;
|
||||
public created_at?: Date = undefined;
|
||||
public readonly ttl?: number = undefined;
|
||||
public expires_at?: Date | null = undefined;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public ttl?: number = undefined;
|
||||
|
||||
protected init(): void {
|
||||
this.setValidation('user_id').defined().exists(User, 'id');
|
||||
this.setValidation('slug').defined().minLength(1).maxLength(259).unique(FileModel, 'slug').unique(URLRedirect, 'slug');
|
||||
this.setValidation('slug').defined().minLength(1).maxLength(259)
|
||||
.unique(this, 'slug')
|
||||
.unique(URLRedirect, 'slug');
|
||||
this.setValidation('real_name').defined().minLength(1).maxLength(259);
|
||||
this.setValidation('storage_type').defined().maxLength(64);
|
||||
this.setValidation('storage_path').defined().maxLength(1745);
|
||||
this.setValidation('size').defined().min(0);
|
||||
this.setValidation('ttl').defined().min(0).max(4294967295);
|
||||
}
|
||||
|
||||
public getURL(domain: string = config.get<string>('public_url')): string {
|
||||
@ -46,15 +52,8 @@ export default class FileModel extends Model {
|
||||
});
|
||||
}
|
||||
|
||||
public getExpirationDate(): Date | null {
|
||||
if (!this.created_at) return new Date();
|
||||
if (this.ttl === 0) return null;
|
||||
|
||||
return new Date(this.created_at.getTime() + this.getOrFail('ttl') * 1000);
|
||||
}
|
||||
|
||||
public shouldBeDeleted(): boolean {
|
||||
const expirationDate = this.getExpirationDate();
|
||||
const expirationDate = this.expires_at;
|
||||
if (!expirationDate) return false;
|
||||
return new Date().getTime() >= expirationDate.getTime();
|
||||
}
|
||||
|
@ -28,7 +28,9 @@ export default class URLRedirect extends Model {
|
||||
|
||||
protected init(): void {
|
||||
this.setValidation('user_id').defined().exists(User, 'id');
|
||||
this.setValidation('slug').defined().minLength(1).maxLength(259).unique(URLRedirect, 'slug').unique(FileModel, 'slug');
|
||||
this.setValidation('slug').defined().minLength(1).maxLength(259)
|
||||
.unique(this, 'slug')
|
||||
.unique(FileModel, 'slug');
|
||||
this.setValidation('target_url').defined().maxLength(1745).regexp(/^https?:\/\/.{3,259}?\/?/i);
|
||||
}
|
||||
|
||||
|
@ -81,8 +81,7 @@
|
||||
</td>
|
||||
<td><pre>{{ file.real_name }}</pre></td>
|
||||
<td>{{ (file.size / (1024 * 1024)).toFixed(2) }}MB</td>
|
||||
{% set expires_at = file.getExpirationDate() %}
|
||||
<td>{% if expires_at %}{{ expires_at.toISOString() }}{% else %}Never{% endif %}</td>
|
||||
<td>{% if file.expires_at %}{{ file.expires_at.toISOString() }}{% else %}Never{% endif %}</td>
|
||||
<td class="actions">
|
||||
{% if file.shouldBeDeleted() %}
|
||||
Pending deletion
|
||||
|
Loading…
Reference in New Issue
Block a user