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 AddPasswordToUsersMigration from "swaf/auth/password/AddPasswordToUsersMigration";
|
||||||
import DropNameFromUsers from "swaf/auth/migrations/DropNameFromUsers";
|
import DropNameFromUsers from "swaf/auth/migrations/DropNameFromUsers";
|
||||||
import packageJson = require('./package.json');
|
import packageJson = require('./package.json');
|
||||||
|
import ReplaceTtlWithExpiresAtFilesTable from "./migrations/ReplaceTtlWithExpiresAtFilesTable";
|
||||||
|
|
||||||
export default class App extends Application {
|
export default class App extends Application {
|
||||||
public constructor(
|
public constructor(
|
||||||
@ -69,7 +70,8 @@ export default class App extends Application {
|
|||||||
AddUsedToMagicLinksMigration,
|
AddUsedToMagicLinksMigration,
|
||||||
MakeMagicLinksSessionNotUniqueMigration,
|
MakeMagicLinksSessionNotUniqueMigration,
|
||||||
AddPasswordToUsersMigration,
|
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 storage_path?: string = undefined;
|
||||||
public readonly size?: number = undefined;
|
public readonly size?: number = undefined;
|
||||||
public created_at?: Date = 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 {
|
protected init(): void {
|
||||||
this.setValidation('user_id').defined().exists(User, 'id');
|
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('real_name').defined().minLength(1).maxLength(259);
|
||||||
this.setValidation('storage_type').defined().maxLength(64);
|
this.setValidation('storage_type').defined().maxLength(64);
|
||||||
this.setValidation('storage_path').defined().maxLength(1745);
|
this.setValidation('storage_path').defined().maxLength(1745);
|
||||||
this.setValidation('size').defined().min(0);
|
this.setValidation('size').defined().min(0);
|
||||||
this.setValidation('ttl').defined().min(0).max(4294967295);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getURL(domain: string = config.get<string>('public_url')): string {
|
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 {
|
public shouldBeDeleted(): boolean {
|
||||||
const expirationDate = this.getExpirationDate();
|
const expirationDate = this.expires_at;
|
||||||
if (!expirationDate) return false;
|
if (!expirationDate) return false;
|
||||||
return new Date().getTime() >= expirationDate.getTime();
|
return new Date().getTime() >= expirationDate.getTime();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,9 @@ export default class URLRedirect extends Model {
|
|||||||
|
|
||||||
protected init(): void {
|
protected init(): void {
|
||||||
this.setValidation('user_id').defined().exists(User, 'id');
|
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);
|
this.setValidation('target_url').defined().maxLength(1745).regexp(/^https?:\/\/.{3,259}?\/?/i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td><pre>{{ file.real_name }}</pre></td>
|
<td><pre>{{ file.real_name }}</pre></td>
|
||||||
<td>{{ (file.size / (1024 * 1024)).toFixed(2) }}MB</td>
|
<td>{{ (file.size / (1024 * 1024)).toFixed(2) }}MB</td>
|
||||||
{% set expires_at = file.getExpirationDate() %}
|
<td>{% if file.expires_at %}{{ file.expires_at.toISOString() }}{% else %}Never{% endif %}</td>
|
||||||
<td>{% if expires_at %}{{ expires_at.toISOString() }}{% else %}Never{% endif %}</td>
|
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
{% if file.shouldBeDeleted() %}
|
{% if file.shouldBeDeleted() %}
|
||||||
Pending deletion
|
Pending deletion
|
||||||
|
Loading…
Reference in New Issue
Block a user