✨ — Add support for Swift object storage
- Swift support - script to upload the existing files to Swift
This commit is contained in:
parent
17600fd679
commit
8d6f1032f0
|
@ -58,6 +58,8 @@ variables:
|
||||||
services:
|
services:
|
||||||
- name: rroemhild/test-openldap
|
- name: rroemhild/test-openldap
|
||||||
alias: rroemhild-test-openldap
|
alias: rroemhild-test-openldap
|
||||||
|
- name: swiftstack/picoswiftstack
|
||||||
|
alias: swiftstack-picoswiftstack
|
||||||
.pg_template: &pg_definition
|
.pg_template: &pg_definition
|
||||||
<<: *tests_template
|
<<: *tests_template
|
||||||
needs:
|
needs:
|
||||||
|
@ -67,6 +69,8 @@ variables:
|
||||||
alias: postgres
|
alias: postgres
|
||||||
- name: rroemhild/test-openldap
|
- name: rroemhild/test-openldap
|
||||||
alias: rroemhild-test-openldap
|
alias: rroemhild-test-openldap
|
||||||
|
- name: swiftstack/picoswiftstack
|
||||||
|
alias: swiftstack-picoswiftstack
|
||||||
.mysql_template: &mysql_definition
|
.mysql_template: &mysql_definition
|
||||||
<<: *tests_template
|
<<: *tests_template
|
||||||
needs:
|
needs:
|
||||||
|
@ -76,6 +80,8 @@ variables:
|
||||||
alias: mariadb
|
alias: mariadb
|
||||||
- name: rroemhild/test-openldap
|
- name: rroemhild/test-openldap
|
||||||
alias: rroemhild-test-openldap
|
alias: rroemhild-test-openldap
|
||||||
|
- name: swiftstack/picoswiftstack
|
||||||
|
alias: swiftstack-picoswiftstack
|
||||||
|
|
||||||
### Publish tag changelog and create a toot
|
### Publish tag changelog and create a toot
|
||||||
##
|
##
|
||||||
|
|
|
@ -5,6 +5,7 @@ Revision history for Lufi
|
||||||
- Use Weblate instead of Zanata for translations (https://weblate.framasoft.org/projects/lufi/development/)
|
- Use Weblate instead of Zanata for translations (https://weblate.framasoft.org/projects/lufi/development/)
|
||||||
- Add config API endpoint (#183)
|
- Add config API endpoint (#183)
|
||||||
- Show latest tag and commit of the instance in about page and config API endpoint (#174)
|
- Show latest tag and commit of the instance in about page and config API endpoint (#174)
|
||||||
|
- Add support for Swift object storage
|
||||||
|
|
||||||
0.04.6 2019-11-07
|
0.04.6 2019-11-07
|
||||||
- Now can send large files (>2Gio) while using a DB other than SQLite (#165)
|
- Now can send large files (>2Gio) while using a DB other than SQLite (#165)
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -30,6 +30,14 @@ ldap:
|
||||||
|
|
||||||
ldapdev: ldap dev
|
ldapdev: ldap dev
|
||||||
|
|
||||||
|
swift:
|
||||||
|
sudo docker run -d --rm -p 8080:8080 --hostname="picoswiftstack" --name="picoswiftstack" swiftstack/picoswiftstack; exit 0
|
||||||
|
@echo "Sleeping 20 seconds to let picoswiftstack start"
|
||||||
|
@sleep 20
|
||||||
|
sudo docker exec picoswiftstack get_auth
|
||||||
|
|
||||||
|
swiftdev: swift dev
|
||||||
|
|
||||||
devlog:
|
devlog:
|
||||||
multitail log/development.log
|
multitail log/development.log
|
||||||
|
|
||||||
|
|
12
cpanfile
12
cpanfile
|
@ -6,9 +6,9 @@ requires 'Mojolicious::Plugin::Mail';
|
||||||
requires 'Mojolicious::Plugin::GzipStatic';
|
requires 'Mojolicious::Plugin::GzipStatic';
|
||||||
requires 'Mojolicious::Plugin::StaticCache';
|
requires 'Mojolicious::Plugin::StaticCache';
|
||||||
requires 'Mojolicious::Plugin::CSPHeader', '>= 0.06';
|
requires 'Mojolicious::Plugin::CSPHeader', '>= 0.06';
|
||||||
requires 'Mojolicious::Plugin::FiatTux::Helpers', '== 0.10', url => 'https://framagit.org/fiat-tux/mojolicious/mojolicious-plugin-fiattux-helpers/-/archive/0.10/mojolicious-plugin-fiattux-helpers-0.10.tar.gz';
|
requires 'Mojolicious::Plugin::FiatTux::Helpers', '== 0.12', url => 'https://framagit.org/fiat-tux/mojolicious/fiat-tux/mojolicious-plugin-fiattux-helpers/-/archive/0.12/mojolicious-plugin-fiattux-helpers-0.12.tar.gz';
|
||||||
requires 'Mojolicious::Plugin::FiatTux::GrantAccess', '== 0.06', url => 'https://framagit.org/fiat-tux/mojolicious/mojolicious-plugin-fiattux-grantaccess/-/archive/0.06/mojolicious-plugin-fiattux-grantaccess-0.06.tar.gz';
|
requires 'Mojolicious::Plugin::FiatTux::GrantAccess', '== 0.07', url => 'https://framagit.org/fiat-tux/mojolicious/fiat-tux/mojolicious-plugin-fiattux-grantaccess/-/archive/0.07/mojolicious-plugin-fiattux-grantaccess-0.07.tar.gz';
|
||||||
requires 'Mojolicious::Plugin::FiatTux::Themes', '== 0.02', url => 'https://framagit.org/fiat-tux/mojolicious/mojolicious-plugin-fiattux-themes/-/archive/0.02/mojolicious-plugin-fiattux-themes-0.02.tar.gz';
|
requires 'Mojolicious::Plugin::FiatTux::Themes', '== 0.02', url => 'https://framagit.org/fiat-tux/mojolicious/fiat-tux/mojolicious-plugin-fiattux-themes/-/archive/0.02/mojolicious-plugin-fiattux-themes-0.02.tar.gz';
|
||||||
requires 'Filesys::DiskUsage';
|
requires 'Filesys::DiskUsage';
|
||||||
requires 'Switch';
|
requires 'Switch';
|
||||||
requires 'Locale::Maketext';
|
requires 'Locale::Maketext';
|
||||||
|
@ -55,3 +55,9 @@ feature 'mysql', 'MySQL support' => sub {
|
||||||
requires 'Mojo::mysql';
|
requires 'Mojo::mysql';
|
||||||
requires 'Mojolicious::Plugin::PgURLHelper';
|
requires 'Mojolicious::Plugin::PgURLHelper';
|
||||||
};
|
};
|
||||||
|
feature 'swift-storage', 'Openstack Swift object storage support' => sub {
|
||||||
|
requires 'Net::OpenStack::Swift';
|
||||||
|
};
|
||||||
|
feature 'test' => sub {
|
||||||
|
requires 'Devel::Cover';
|
||||||
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
11
lib/Lufi.pm
11
lib/Lufi.pm
|
@ -66,6 +66,11 @@ sub startup {
|
||||||
# Helpers
|
# Helpers
|
||||||
$self->plugin('Lufi::Plugin::Helpers');
|
$self->plugin('Lufi::Plugin::Helpers');
|
||||||
|
|
||||||
|
# Now helpers has been loaded, time to check Swift container
|
||||||
|
if ($config->{swift}) {
|
||||||
|
$self->check_swift_container();
|
||||||
|
}
|
||||||
|
|
||||||
# Recurrent task
|
# Recurrent task
|
||||||
Mojo::IOLoop->recurring(2 => sub {
|
Mojo::IOLoop->recurring(2 => sub {
|
||||||
my $loop = shift;
|
my $loop = shift;
|
||||||
|
@ -74,8 +79,10 @@ sub startup {
|
||||||
});
|
});
|
||||||
|
|
||||||
# Create directory if needed
|
# Create directory if needed
|
||||||
mkdir($self->config('upload_dir'), 0700) unless (-d $self->config('upload_dir'));
|
if (!defined($config->{swift})) {
|
||||||
die ('The upload directory ('.$self->config('upload_dir').') is not writable') unless (-w $self->config('upload_dir'));
|
mkdir($self->config('upload_dir'), 0700) unless (-d $self->config('upload_dir'));
|
||||||
|
die ('The upload directory ('.$self->config('upload_dir').') is not writable') unless (-w $self->config('upload_dir'));
|
||||||
|
}
|
||||||
|
|
||||||
# Configure sessions
|
# Configure sessions
|
||||||
my $sessions = Mojolicious::Sessions->new;
|
my $sessions = Mojolicious::Sessions->new;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package Lufi::Command::copyFilesToSwift;
|
||||||
|
use Mojo::Base 'Mojolicious::Command';
|
||||||
|
use File::Spec;
|
||||||
|
use Term::ProgressBar;
|
||||||
|
|
||||||
|
has description => 'Copy files from filesystem to Swift object storage';
|
||||||
|
has usage => sub { shift->extract_usage };
|
||||||
|
|
||||||
|
sub run {
|
||||||
|
my $c = shift;
|
||||||
|
|
||||||
|
if ($c->app->config('swift')) {
|
||||||
|
$c->app->check_swift_container();
|
||||||
|
my @dirs = glob(File::Spec->catdir($c->app->config('upload_dir'), '*'));
|
||||||
|
|
||||||
|
say sprintf('%d folders to upload to Swift (can\'t say how many files, or the total size, sorry). This can take some time.', scalar(@dirs));
|
||||||
|
print 'Do you want to continue? [Y/n] ';
|
||||||
|
my $confirm = <STDIN>;
|
||||||
|
|
||||||
|
if ($confirm =~ m/yes|y/i) {
|
||||||
|
my $progress = Term::ProgressBar->new({ count => scalar(@dirs), ETA => 'linear', name => 'Copying to Swift'});
|
||||||
|
for my $dir (@dirs) {
|
||||||
|
my @files = glob(File::Spec->catfile($dir, '*'));
|
||||||
|
for my $file (@files) {
|
||||||
|
my ($volume, $directories, $filename) = File::Spec->splitpath($file);
|
||||||
|
my @file_dirs = File::Spec->splitdir($directories);
|
||||||
|
my $short = ($file_dirs[-1] ne '') ? $file_dirs[-1] : $file_dirs[-2];
|
||||||
|
my $path = File::Spec->catfile($short, $filename);
|
||||||
|
|
||||||
|
open my $fh, '<', $file or die sprintf('Unable to open file %s: %s', $file, $!);
|
||||||
|
|
||||||
|
$c->app->swift->put_object(
|
||||||
|
container_name => $c->app->config('swift')->{container},
|
||||||
|
object_name => $path,
|
||||||
|
content_length => -s $file,
|
||||||
|
content => $fh
|
||||||
|
);
|
||||||
|
close $fh;
|
||||||
|
}
|
||||||
|
$progress->update();
|
||||||
|
}
|
||||||
|
say sprintf('The copy to Swift object storage has ended. You can test Lufi, then delete `%s` directory', $c->app->config('upload_dir'));
|
||||||
|
} else {
|
||||||
|
say 'You want to stop. No problem.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
say 'You didn\'t configure `swift` in your config file. Exiting.';
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
=encoding utf8
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Lufi::Command::copyFilesToSwift Copy files from filesystem to Swift object storage
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
Usage: script/lufi copyFilesToSwift
|
||||||
|
|
||||||
|
This command needs you to:
|
||||||
|
- set `upload_dir` in your config file (otherwise, it will use the default path, `files` to copy files from)
|
||||||
|
- configure `swift` with correct informations in your config file
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
1;
|
|
@ -1,5 +1,6 @@
|
||||||
package Lufi::Command::sqliteToOtherDB;
|
package Lufi::Command::sqliteToOtherDB;
|
||||||
use Mojo::Base 'Mojolicious::Command';
|
use Mojo::Base 'Mojolicious::Command';
|
||||||
|
use Lufi::DB::BreakingChange;
|
||||||
use Lufi::DB::File;
|
use Lufi::DB::File;
|
||||||
use Lufi::DB::Slice;
|
use Lufi::DB::Slice;
|
||||||
use Lufi::DB::Invitation;
|
use Lufi::DB::Invitation;
|
||||||
|
@ -9,7 +10,7 @@ use Term::ProgressBar;
|
||||||
use Lufi::DefaultConfig qw($default_config);
|
use Lufi::DefaultConfig qw($default_config);
|
||||||
|
|
||||||
has description => 'Migrate the records from a SQLite db to the currently configured database';
|
has description => 'Migrate the records from a SQLite db to the currently configured database';
|
||||||
has usage => sub { shift->extract_usage };
|
has usage => sub { shift->extract_usage };
|
||||||
|
|
||||||
sub run {
|
sub run {
|
||||||
my $c = shift;
|
my $c = shift;
|
||||||
|
@ -36,8 +37,9 @@ sub run {
|
||||||
my $files = $sqlite->db->select('files', undef)->hashes;
|
my $files = $sqlite->db->select('files', undef)->hashes;
|
||||||
my $slices = $sqlite->db->select('slices', undef)->hashes;
|
my $slices = $sqlite->db->select('slices', undef)->hashes;
|
||||||
my $invitations = $sqlite->db->select('invitations', undef)->hashes;
|
my $invitations = $sqlite->db->select('invitations', undef)->hashes;
|
||||||
|
my $changes = $sqlite->db->select('breakingchanges', undef)->hashes;
|
||||||
|
|
||||||
my $progress = Term::ProgressBar->new({count => $files->size + $slices->size + $invitations->size});
|
my $progress = Term::ProgressBar->new({count => $files->size + $slices->size + $invitations->size + $changes->size});
|
||||||
|
|
||||||
$files->each(sub {
|
$files->each(sub {
|
||||||
my ($file, $num) = @_;
|
my ($file, $num) = @_;
|
||||||
|
@ -69,7 +71,6 @@ sub run {
|
||||||
Lufi::DB::Slice->new(app => $c->app)
|
Lufi::DB::Slice->new(app => $c->app)
|
||||||
->short($slice->{short})
|
->short($slice->{short})
|
||||||
->j($slice->{j})
|
->j($slice->{j})
|
||||||
->path($slice->{path})
|
|
||||||
->write();
|
->write();
|
||||||
|
|
||||||
$progress->update();
|
$progress->update();
|
||||||
|
@ -92,13 +93,22 @@ sub run {
|
||||||
->write();
|
->write();
|
||||||
$progress->update();
|
$progress->update();
|
||||||
});
|
});
|
||||||
|
$changes->each(sub {
|
||||||
|
my ($change, $num) = @_;
|
||||||
|
|
||||||
|
Lufi::DB::BreakingChange->new(app => $c->app)
|
||||||
|
->change($change->{change})
|
||||||
|
->ack($change->{ack})
|
||||||
|
->write();
|
||||||
|
$progress->update();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
=encoding utf8
|
=encoding utf8
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
Lufi::Command::cron::sqliteToOtherDB Migrate the records from a SQLite db to the currently configured database
|
Lufi::Command::sqliteToOtherDB Migrate the records from a SQLite db to the currently configured database
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
package Lufi::Command::theme;
|
package Lufi::Command::theme;
|
||||||
use Mojo::Base 'Mojolicious::Commands';
|
use Mojo::Base 'Mojolicious::Commands';
|
||||||
use FindBin qw($Bin);
|
use FindBin qw($Bin);
|
||||||
use File::Spec qw(catfile cat dir);
|
use File::Spec qw(catfile catdir);
|
||||||
use File::Path qw(make_path);
|
use File::Path qw(make_path);
|
||||||
|
|
||||||
has description => 'Create new theme skeleton.';
|
has description => 'Create new theme skeleton.';
|
||||||
|
|
|
@ -100,7 +100,8 @@ sub upload {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# Check that we have enough space (multiplying by 2 since it's encrypted, it takes more place that the original file)
|
# Check that we have enough space (multiplying by 2 since it's encrypted, it takes more place that the original file)
|
||||||
if ($json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) {
|
# Only check if using filesystem, not Swift storage
|
||||||
|
if (!defined($c->config('swift')) && $json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) {
|
||||||
$stop = 1;
|
$stop = 1;
|
||||||
return $ws->send(decode('UTF-8', encode_json(
|
return $ws->send(decode('UTF-8', encode_json(
|
||||||
{
|
{
|
||||||
|
@ -190,19 +191,12 @@ sub upload {
|
||||||
# If we already have a part, it's a resend because the websocket has been broken
|
# If we already have a part, it's a resend because the websocket has been broken
|
||||||
# In this case, we don't need to rewrite the file
|
# In this case, we don't need to rewrite the file
|
||||||
unless ($f->slices->grep(sub { $_->j == $json->{part} })->size) {
|
unless ($f->slices->grep(sub { $_->j == $json->{part} })->size) {
|
||||||
# Create directory
|
|
||||||
my $dir = catdir($c->config('upload_dir'), $f->short);
|
|
||||||
mkdir($dir, 0700) unless (-d $dir);
|
|
||||||
|
|
||||||
# Create slice file
|
# Create slice file
|
||||||
my $file = catfile($dir, $json->{part}.'.part');
|
|
||||||
my $s = Lufi::DB::Slice->new(
|
my $s = Lufi::DB::Slice->new(
|
||||||
app => $c->app,
|
app => $c->app,
|
||||||
short => $f->short,
|
short => $f->short,
|
||||||
j => $json->{part},
|
j => $json->{part}
|
||||||
path => $file
|
)->store($text);
|
||||||
);
|
|
||||||
Mojo::File->new($file)->spurt($text);
|
|
||||||
push @{$f->slices}, $s;
|
push @{$f->slices}, $s;
|
||||||
$s->write;
|
$s->write;
|
||||||
|
|
||||||
|
@ -327,7 +321,7 @@ sub download {
|
||||||
|
|
||||||
# Get the slice
|
# Get the slice
|
||||||
my $e = $f->slices->[$num];
|
my $e = $f->slices->[$num];
|
||||||
my $text = Mojo::File->new($e->path)->slurp;
|
my $text = $e->retrieve();
|
||||||
|
|
||||||
my ($json2) = split('XXMOJOXX', $text, 2);
|
my ($json2) = split('XXMOJOXX', $text, 2);
|
||||||
$json2 = decode 'UTF-8', $json2;
|
$json2 = decode 'UTF-8', $json2;
|
||||||
|
|
|
@ -148,13 +148,37 @@ sub delete {
|
||||||
|
|
||||||
$c->slices->each(sub {
|
$c->slices->each(sub {
|
||||||
my ($e, $num) = @_;
|
my ($e, $num) = @_;
|
||||||
unlink $e->path;
|
$e->delete_file();
|
||||||
});
|
});
|
||||||
rmdir Mojo::File->new($c->app->config('upload_dir'), $c->short);
|
$c->delete_path
|
||||||
$c->deleted(1);
|
->deleted(1)
|
||||||
|
->write;
|
||||||
|
|
||||||
$c->write;
|
return $c;
|
||||||
|
}
|
||||||
|
|
||||||
|
=head2 delete_path
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
=item B<Usage> : C<$c-E<gt>delete_path()>
|
||||||
|
|
||||||
|
=item B<Arguments> : none
|
||||||
|
|
||||||
|
=item B<Purpose> : delete the directory of the slices on filesystem or Swift object storage
|
||||||
|
|
||||||
|
=item B<Returns> : the db accessor object
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub delete_path {
|
||||||
|
my $c = shift;
|
||||||
|
|
||||||
|
if (!defined($c->app->config('swift'))) {
|
||||||
|
rmdir Mojo::File->new($c->app->config('upload_dir'), $c->short);
|
||||||
|
}
|
||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||||
package Lufi::DB::Slice;
|
package Lufi::DB::Slice;
|
||||||
use Mojo::Base -base;
|
use Mojo::Base -base;
|
||||||
|
use Encode 'encode';
|
||||||
|
use File::Spec::Functions;
|
||||||
use Mojo::Collection 'c';
|
use Mojo::Collection 'c';
|
||||||
|
|
||||||
has 'short';
|
has 'short';
|
||||||
has 'j';
|
has 'j';
|
||||||
has 'path';
|
|
||||||
has 'record' => 0;
|
has 'record' => 0;
|
||||||
has 'app';
|
has 'app';
|
||||||
|
|
||||||
|
=encoding utf8
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
Lufi::DB::Slice - DB abstraction layer for Lufi file
|
Lufi::DB::Slice - DB abstraction layer for Lufi file
|
||||||
|
@ -28,8 +31,6 @@ Have a look at Lufi::DB::Slice::SQLite's code: it's simple and may be more under
|
||||||
|
|
||||||
=item B<j> : integer
|
=item B<j> : integer
|
||||||
|
|
||||||
=item B<path> : string
|
|
||||||
|
|
||||||
=item B<app> : A mojolicious object
|
=item B<app> : A mojolicious object
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
@ -96,15 +97,121 @@ sub write {
|
||||||
my $c = shift;
|
my $c = shift;
|
||||||
|
|
||||||
if ($c->record) {
|
if ($c->record) {
|
||||||
$c->app->dbi->db->query('UPDATE slices SET short = ?, j = ?, path = ? WHERE short = ? AND j = ?', $c->short, $c->j, $c->path, $c->short, $c->j);
|
$c->app->dbi->db->query('UPDATE slices SET short = ?, j = ? WHERE short = ? AND j = ?', $c->short, $c->j, $c->short, $c->j);
|
||||||
} else {
|
} else {
|
||||||
$c->app->dbi->db->query('INSERT INTO slices (short, j, path) VALUES (?, ?, ?)', $c->short, $c->j, $c->path);
|
$c->app->dbi->db->query('INSERT INTO slices (short, j) VALUES (?, ?)', $c->short, $c->j);
|
||||||
$c->record(1);
|
$c->record(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=head2 store
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
=item B<Usage> : C<$c-E<gt>store($text)>
|
||||||
|
|
||||||
|
=item B<Arguments> : a scalar value
|
||||||
|
|
||||||
|
=item B<Purpose> : will store the content to the object's path, either on filesystem or on Swift object storage
|
||||||
|
|
||||||
|
=item B<Returns> : the db accessor object
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub store {
|
||||||
|
my $c = shift;
|
||||||
|
my $text = shift;
|
||||||
|
|
||||||
|
if ($c->app->config('swift')) {
|
||||||
|
$c->app->swift->put_object(
|
||||||
|
container_name => $c->app->config('swift')->{container},
|
||||||
|
object_name => $c->get_path(),
|
||||||
|
content_length => length(Encode::encode_utf8($text)),
|
||||||
|
content => $text
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
# Create directory
|
||||||
|
my $dir = catfile($c->app->config('upload_dir'), $c->short);
|
||||||
|
mkdir($dir, 0700) unless (-d $dir);
|
||||||
|
|
||||||
|
# Write file
|
||||||
|
my $file = catfile($c->app->config('upload_dir'), $c->get_path());
|
||||||
|
Mojo::File->new($file)->spurt($text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $c;
|
||||||
|
}
|
||||||
|
|
||||||
|
=head2 retrieve
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
=item B<Usage> : C<$c-E<gt>retrieve>
|
||||||
|
|
||||||
|
=item B<Arguments> : none
|
||||||
|
|
||||||
|
=item B<Purpose> : get file from storage, either filesystem or Swift object storage
|
||||||
|
|
||||||
|
=item B<Returns> : the data from the file
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub retrieve {
|
||||||
|
my $c = shift;
|
||||||
|
my $upload = shift;
|
||||||
|
|
||||||
|
if ($c->app->config('swift')) {
|
||||||
|
my $file;
|
||||||
|
$c->app->swift->get_object(
|
||||||
|
container_name => $c->app->config('swift')->{container},
|
||||||
|
object_name => $c->get_path(),
|
||||||
|
write_code => sub {
|
||||||
|
my ($status, $message, $headers, $chunk) = @_;
|
||||||
|
$file .= $chunk;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return $file;
|
||||||
|
} else {
|
||||||
|
my $file = catfile($c->app->config('upload_dir'), $c->get_path());
|
||||||
|
return Mojo::File->new($file)->slurp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
=head2 delete_file
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
=item B<Usage> : C<$c-E<gt>delete_file()>
|
||||||
|
|
||||||
|
=item B<Arguments> : none
|
||||||
|
|
||||||
|
=item B<Purpose> : delete the file on filesystem or Swift object storage
|
||||||
|
|
||||||
|
=item B<Returns> : the db accessor object
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub delete_file {
|
||||||
|
my $c = shift;
|
||||||
|
|
||||||
|
if ($c->app->config('swift')) {
|
||||||
|
$c->app->swift->delete_object({
|
||||||
|
container_name => $c->app->config('swift')->{container},
|
||||||
|
object_name => $c->get_path()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
my $file = catfile($c->app->config('upload_dir'), $c->get_path());
|
||||||
|
unlink $file or warn sprintf('Could not unlink %s: %s', $file, $!);
|
||||||
|
}
|
||||||
|
return $c;
|
||||||
|
}
|
||||||
=head2 get_slices_of_file
|
=head2 get_slices_of_file
|
||||||
|
|
||||||
=over 1
|
=over 1
|
||||||
|
@ -147,7 +254,7 @@ sub get_slices_of_file {
|
||||||
|
|
||||||
=item B<Arguments> : none
|
=item B<Arguments> : none
|
||||||
|
|
||||||
=item B<Purpose> : delete all file records from database unconditionnally
|
=item B<Purpose> : delete all slices records from database unconditionnally
|
||||||
|
|
||||||
=item B<Returns> : nothing
|
=item B<Returns> : nothing
|
||||||
|
|
||||||
|
@ -161,6 +268,50 @@ sub delete_all {
|
||||||
$c->app->dbi->db->delete('slices');
|
$c->app->dbi->db->delete('slices');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=head2 path
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
=item B<Usage> : C<$c-E<gt>path()>
|
||||||
|
|
||||||
|
=item B<Arguments> : non
|
||||||
|
|
||||||
|
=item B<Purpose> : format the path of the file, relative to the directory of the Swift object storage
|
||||||
|
|
||||||
|
=item B<Returns> : the path of the file
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub get_path {
|
||||||
|
my $c = shift;
|
||||||
|
|
||||||
|
return catfile($c->short, sprintf('%d.part', $c->j));
|
||||||
|
}
|
||||||
|
|
||||||
|
=head2 count
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
=item B<Usage> : C<$c-E<gt>count()>
|
||||||
|
|
||||||
|
=item B<Arguments> : none
|
||||||
|
|
||||||
|
=item B<Purpose> : get count of slices records from database
|
||||||
|
|
||||||
|
=item B<Returns> : integer
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub count {
|
||||||
|
my $c = shift;
|
||||||
|
|
||||||
|
return $c->app->dbi->db->query('SELECT count(*) AS count FROM slices')->hashes->first->{count};
|
||||||
|
}
|
||||||
|
|
||||||
=head2 _slurp
|
=head2 _slurp
|
||||||
|
|
||||||
=over 1
|
=over 1
|
||||||
|
@ -195,7 +346,6 @@ sub _slurp {
|
||||||
if ($slice) {
|
if ($slice) {
|
||||||
$c->short($slice->{short});
|
$c->short($slice->{short});
|
||||||
$c->j($slice->{j});
|
$c->j($slice->{j});
|
||||||
$c->path($slice->{path});
|
|
||||||
|
|
||||||
$c->record(1);
|
$c->record(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ sub new {
|
||||||
|
|
||||||
$c = $c->SUPER::new(@_);
|
$c = $c->SUPER::new(@_);
|
||||||
|
|
||||||
|
$c = $c->_slurp if defined $c->record;
|
||||||
|
|
||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ sub new {
|
||||||
|
|
||||||
$c = $c->SUPER::new(@_);
|
$c = $c->SUPER::new(@_);
|
||||||
|
|
||||||
|
$c = $c->_slurp if defined $c->record;
|
||||||
|
|
||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@ sub startup {
|
||||||
# Compress static assets
|
# Compress static assets
|
||||||
$self->plugin('GzipStatic');
|
$self->plugin('GzipStatic');
|
||||||
|
|
||||||
|
# Fiat Tux helpers
|
||||||
|
$self->plugin('FiatTux::Helpers');
|
||||||
|
|
||||||
# Headers
|
# Headers
|
||||||
$self->plugin('Lufi::Plugin::Headers');
|
$self->plugin('Lufi::Plugin::Headers');
|
||||||
|
|
||||||
|
|
|
@ -99,14 +99,25 @@
|
||||||
# Array of authorized domains for API calls.
|
# Array of authorized domains for API calls.
|
||||||
# If you want to authorize everyone to use the API: ['*']
|
# If you want to authorize everyone to use the API: ['*']
|
||||||
# optional, no domains allowed by default
|
# optional, no domains allowed by default
|
||||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||||
|
|
||||||
# Define a path to the upload directory, where the uploaded files will be stored
|
# Define a path to the upload directory, where the uploaded files will be stored
|
||||||
# You can define it relative to lufi directory or set an absolute path
|
# You can define it relative to lufi directory or set an absolute path
|
||||||
# Remember that it has to be in a directory writable by Lufi user
|
# Remember that it has to be in a directory writable by Lufi user
|
||||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
|
||||||
# optional, default is 'files'
|
# optional, default is 'files'
|
||||||
#upload_dir => 'files',
|
#upload_dir => 'files',
|
||||||
|
|
||||||
|
# You can store files on Swift object storage (https://en.wikipedia.org/wiki/OpenStack#Swift) instead of filesystem
|
||||||
|
# Please read https://metacpan.org/pod/Net::OpenStack::Swift#SYNOPSIS to know how to configure this setting
|
||||||
|
# IMPORTANT: add a `container` key in it, to let Lufi know which container to use. This is not a regular Net::OpenStack::Swift setting, but Lufi need it.
|
||||||
|
# optional, no default
|
||||||
|
#swift => {
|
||||||
|
# auth_url => 'https://auth-endpoint-url/v2.0',
|
||||||
|
# user => 'userid',
|
||||||
|
# password => 'password',
|
||||||
|
# tenant_name => 'project_id',
|
||||||
|
# container => 'lufi'
|
||||||
|
#},
|
||||||
|
|
||||||
# Allow to add a password on files, asked before allowing to download files
|
# Allow to add a password on files, asked before allowing to download files
|
||||||
# optional, default is 0
|
# optional, default is 0
|
||||||
|
|
50
t/mysql.conf
50
t/mysql.conf
|
@ -32,6 +32,10 @@
|
||||||
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
||||||
#secrets => ['fdjsofjoihrei'],
|
#secrets => ['fdjsofjoihrei'],
|
||||||
|
|
||||||
|
# Name of the instance, displayed next to the logo
|
||||||
|
# optional, default is Lufi
|
||||||
|
#instance_name => 'Lufi',
|
||||||
|
|
||||||
# Choose a theme. See the available themes in `themes` directory
|
# Choose a theme. See the available themes in `themes` directory
|
||||||
# Optional, default is 'default'
|
# Optional, default is 'default'
|
||||||
#theme => 'default',
|
#theme => 'default',
|
||||||
|
@ -97,10 +101,6 @@
|
||||||
# optional, no domains allowed by default
|
# optional, no domains allowed by default
|
||||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||||
|
|
||||||
# If set, the shortened URLs will use this domain
|
|
||||||
# optional
|
|
||||||
#fixed_domain => 'example.org',
|
|
||||||
|
|
||||||
# Define a path to the upload directory, where the uploaded files will be stored
|
# Define a path to the upload directory, where the uploaded files will be stored
|
||||||
# You can define it relative to lufi directory or set an absolute path
|
# You can define it relative to lufi directory or set an absolute path
|
||||||
# Remember that it has to be in a directory writable by Lufi user
|
# Remember that it has to be in a directory writable by Lufi user
|
||||||
|
@ -108,6 +108,12 @@
|
||||||
# optional, default is 'files'
|
# optional, default is 'files'
|
||||||
#upload_dir => 'files',
|
#upload_dir => 'files',
|
||||||
|
|
||||||
|
# You can store files on Swift object storage (https://en.wikipedia.org/wiki/OpenStack#Swift) instead of filesystem
|
||||||
|
# Please read https://metacpan.org/pod/Net::OpenStack::Swift#SYNOPSIS to know how to configure this setting
|
||||||
|
# IMPORTANT: add a `container` key in it, to let Lufi know which container to use. This is not a regular Net::OpenStack::Swift setting, but Lufi need it.
|
||||||
|
# optional, no default
|
||||||
|
#swift => { auth_url => 'http://swiftstack-picoswiftstack:8080/auth/v1.0', user => 'test', password => 'test', container => 'lufi', auth_version => '1.0' },
|
||||||
|
|
||||||
# Allow to add a password on files, asked before allowing to download files
|
# Allow to add a password on files, asked before allowing to download files
|
||||||
# optional, default is 0
|
# optional, default is 0
|
||||||
allow_pwd_on_files => 1,
|
allow_pwd_on_files => 1,
|
||||||
|
@ -228,11 +234,47 @@
|
||||||
#
|
#
|
||||||
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
||||||
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
||||||
|
# optional, no default
|
||||||
#ldap_map_attr => {
|
#ldap_map_attr => {
|
||||||
# displayname => 'cn',
|
# displayname => 'cn',
|
||||||
# mail => 'mail'
|
# mail => 'mail'
|
||||||
#},
|
#},
|
||||||
|
|
||||||
|
# When using LDAP authentication, LDAP users can invite people (by mail) to use Lufi to send them files without
|
||||||
|
# being authenticated.
|
||||||
|
# This is where you configure the behavior of the invitations.
|
||||||
|
# You may need to fetch some attributes from LDAP to use some invitations settings. See `ldap_map_attr` above.
|
||||||
|
# optional, no default
|
||||||
|
#invitations => {
|
||||||
|
# # The name of the key set in `ldap_map_attr` (above) that corresponds to the mail of the LDAP user
|
||||||
|
# # optional, default is `mail`
|
||||||
|
# mail_attr => 'mail',
|
||||||
|
# # The `From` header of invitation mail can be the mail of the LDAP user
|
||||||
|
# # Be sure to have a mail system that will correctly send the mail from your users! (DKIM, SPF…)
|
||||||
|
# # To enable this feature, set it to 1
|
||||||
|
# # optional, disabled by default
|
||||||
|
# send_invitation_with_ldap_user_mail => 1,
|
||||||
|
# # The user is able to set an expiration delay for the invitation.
|
||||||
|
# # This expiration delay can’t be more than this setting (in days).
|
||||||
|
# # optional, default is 30 days
|
||||||
|
# max_invitation_expiration_delay => 30,
|
||||||
|
# # Once the guest has submitted his files, he has an additional period of time to submit forgotten files.
|
||||||
|
# # You can set that additional period of time in minutes here.
|
||||||
|
# # To disable that feature, set it to 0 or less
|
||||||
|
# # optional, default is 10 minutes
|
||||||
|
# max_additional_period => 10,
|
||||||
|
# # Lufi follows privacy-by-design, so, by default, no files URLs (with the decode secret) are stored in database.
|
||||||
|
# # However, the concern is different for this case. Storing files URLs makes users able to retrieve the guests’ sent files
|
||||||
|
# # from their `invitations` page.
|
||||||
|
# # Set to 1 to store guests’ files URLs in database
|
||||||
|
# # optional, default is 0 (disabled)
|
||||||
|
# save_files_url_in_db => 0,
|
||||||
|
# # Users can resend the invitation to their guest. This does not extend the invitation’s expiration delay unless you
|
||||||
|
# # set this option to 1.
|
||||||
|
# # optional, default is 0 (disabled)
|
||||||
|
# extend_invitation_expiration_on_resend => 0,
|
||||||
|
#},
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
# Htpasswd authentication
|
# Htpasswd authentication
|
||||||
#########################
|
#########################
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
||||||
#secrets => ['fdjsofjoihrei'],
|
#secrets => ['fdjsofjoihrei'],
|
||||||
|
|
||||||
|
# Name of the instance, displayed next to the logo
|
||||||
|
# optional, default is Lufi
|
||||||
|
#instance_name => 'Lufi',
|
||||||
|
|
||||||
# Choose a theme. See the available themes in `themes` directory
|
# Choose a theme. See the available themes in `themes` directory
|
||||||
# Optional, default is 'default'
|
# Optional, default is 'default'
|
||||||
#theme => 'default',
|
#theme => 'default',
|
||||||
|
@ -97,10 +101,6 @@
|
||||||
# optional, no domains allowed by default
|
# optional, no domains allowed by default
|
||||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||||
|
|
||||||
# If set, the shortened URLs will use this domain
|
|
||||||
# optional
|
|
||||||
#fixed_domain => 'example.org',
|
|
||||||
|
|
||||||
# Define a path to the upload directory, where the uploaded files will be stored
|
# Define a path to the upload directory, where the uploaded files will be stored
|
||||||
# You can define it relative to lufi directory or set an absolute path
|
# You can define it relative to lufi directory or set an absolute path
|
||||||
# Remember that it has to be in a directory writable by Lufi user
|
# Remember that it has to be in a directory writable by Lufi user
|
||||||
|
@ -108,6 +108,12 @@
|
||||||
# optional, default is 'files'
|
# optional, default is 'files'
|
||||||
#upload_dir => 'files',
|
#upload_dir => 'files',
|
||||||
|
|
||||||
|
# You can store files on Swift object storage (https://en.wikipedia.org/wiki/OpenStack#Swift) instead of filesystem
|
||||||
|
# Please read https://metacpan.org/pod/Net::OpenStack::Swift#SYNOPSIS to know how to configure this setting
|
||||||
|
# IMPORTANT: add a `container` key in it, to let Lufi know which container to use. This is not a regular Net::OpenStack::Swift setting, but Lufi need it.
|
||||||
|
# optional, no default
|
||||||
|
#swift => { auth_url => 'http://swiftstack-picoswiftstack:8080/auth/v1.0', user => 'test', password => 'test', container => 'lufi', auth_version => '1.0' },
|
||||||
|
|
||||||
# Allow to add a password on files, asked before allowing to download files
|
# Allow to add a password on files, asked before allowing to download files
|
||||||
# optional, default is 0
|
# optional, default is 0
|
||||||
allow_pwd_on_files => 1,
|
allow_pwd_on_files => 1,
|
||||||
|
@ -172,6 +178,7 @@
|
||||||
#port => 5432,
|
#port => 5432,
|
||||||
user => 'lufi',
|
user => 'lufi',
|
||||||
pwd => 'lufi_pwd'
|
pwd => 'lufi_pwd'
|
||||||
|
# # https://mojolicious.org/perldoc/Mojo/Pg#max_connections
|
||||||
# # optional, default is 1
|
# # optional, default is 1
|
||||||
# #max_connections => 1,
|
# #max_connections => 1,
|
||||||
},
|
},
|
||||||
|
@ -212,11 +219,47 @@
|
||||||
#
|
#
|
||||||
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
||||||
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
||||||
|
# optional, no default
|
||||||
#ldap_map_attr => {
|
#ldap_map_attr => {
|
||||||
# displayname => 'cn',
|
# displayname => 'cn',
|
||||||
# mail => 'mail'
|
# mail => 'mail'
|
||||||
#},
|
#},
|
||||||
|
|
||||||
|
# When using LDAP authentication, LDAP users can invite people (by mail) to use Lufi to send them files without
|
||||||
|
# being authenticated.
|
||||||
|
# This is where you configure the behavior of the invitations.
|
||||||
|
# You may need to fetch some attributes from LDAP to use some invitations settings. See `ldap_map_attr` above.
|
||||||
|
# optional, no default
|
||||||
|
#invitations => {
|
||||||
|
# # The name of the key set in `ldap_map_attr` (above) that corresponds to the mail of the LDAP user
|
||||||
|
# # optional, default is `mail`
|
||||||
|
# mail_attr => 'mail',
|
||||||
|
# # The `From` header of invitation mail can be the mail of the LDAP user
|
||||||
|
# # Be sure to have a mail system that will correctly send the mail from your users! (DKIM, SPF…)
|
||||||
|
# # To enable this feature, set it to 1
|
||||||
|
# # optional, disabled by default
|
||||||
|
# send_invitation_with_ldap_user_mail => 1,
|
||||||
|
# # The user is able to set an expiration delay for the invitation.
|
||||||
|
# # This expiration delay can’t be more than this setting (in days).
|
||||||
|
# # optional, default is 30 days
|
||||||
|
# max_invitation_expiration_delay => 30,
|
||||||
|
# # Once the guest has submitted his files, he has an additional period of time to submit forgotten files.
|
||||||
|
# # You can set that additional period of time in minutes here.
|
||||||
|
# # To disable that feature, set it to 0 or less
|
||||||
|
# # optional, default is 10 minutes
|
||||||
|
# max_additional_period => 10,
|
||||||
|
# # Lufi follows privacy-by-design, so, by default, no files URLs (with the decode secret) are stored in database.
|
||||||
|
# # However, the concern is different for this case. Storing files URLs makes users able to retrieve the guests’ sent files
|
||||||
|
# # from their `invitations` page.
|
||||||
|
# # Set to 1 to store guests’ files URLs in database
|
||||||
|
# # optional, default is 0 (disabled)
|
||||||
|
# save_files_url_in_db => 0,
|
||||||
|
# # Users can resend the invitation to their guest. This does not extend the invitation’s expiration delay unless you
|
||||||
|
# # set this option to 1.
|
||||||
|
# # optional, default is 0 (disabled)
|
||||||
|
# extend_invitation_expiration_on_resend => 0,
|
||||||
|
#},
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
# Htpasswd authentication
|
# Htpasswd authentication
|
||||||
#########################
|
#########################
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
||||||
#secrets => ['fdjsofjoihrei'],
|
#secrets => ['fdjsofjoihrei'],
|
||||||
|
|
||||||
|
# Name of the instance, displayed next to the logo
|
||||||
|
# optional, default is Lufi
|
||||||
|
#instance_name => 'Lufi',
|
||||||
|
|
||||||
# Choose a theme. See the available themes in `themes` directory
|
# Choose a theme. See the available themes in `themes` directory
|
||||||
# Optional, default is 'default'
|
# Optional, default is 'default'
|
||||||
#theme => 'default',
|
#theme => 'default',
|
||||||
|
@ -97,10 +101,6 @@
|
||||||
# optional, no domains allowed by default
|
# optional, no domains allowed by default
|
||||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||||
|
|
||||||
# If set, the shortened URLs will use this domain
|
|
||||||
# optional
|
|
||||||
#fixed_domain => 'example.org',
|
|
||||||
|
|
||||||
# Define a path to the upload directory, where the uploaded files will be stored
|
# Define a path to the upload directory, where the uploaded files will be stored
|
||||||
# You can define it relative to lufi directory or set an absolute path
|
# You can define it relative to lufi directory or set an absolute path
|
||||||
# Remember that it has to be in a directory writable by Lufi user
|
# Remember that it has to be in a directory writable by Lufi user
|
||||||
|
@ -108,6 +108,12 @@
|
||||||
# optional, default is 'files'
|
# optional, default is 'files'
|
||||||
#upload_dir => 'files',
|
#upload_dir => 'files',
|
||||||
|
|
||||||
|
# You can store files on Swift object storage (https://en.wikipedia.org/wiki/OpenStack#Swift) instead of filesystem
|
||||||
|
# Please read https://metacpan.org/pod/Net::OpenStack::Swift#SYNOPSIS to know how to configure this setting
|
||||||
|
# IMPORTANT: add a `container` key in it, to let Lufi know which container to use. This is not a regular Net::OpenStack::Swift setting, but Lufi need it.
|
||||||
|
# optional, no default
|
||||||
|
#swift => { auth_url => 'http://swiftstack-picoswiftstack:8080/auth/v1.0', user => 'test', password => 'test', container => 'lufi', auth_version => '1.0' },
|
||||||
|
|
||||||
# Allow to add a password on files, asked before allowing to download files
|
# Allow to add a password on files, asked before allowing to download files
|
||||||
# optional, default is 0
|
# optional, default is 0
|
||||||
allow_pwd_on_files => 1,
|
allow_pwd_on_files => 1,
|
||||||
|
@ -217,11 +223,47 @@
|
||||||
#
|
#
|
||||||
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
||||||
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
||||||
|
# optional, no default
|
||||||
#ldap_map_attr => {
|
#ldap_map_attr => {
|
||||||
# displayname => 'cn',
|
# displayname => 'cn',
|
||||||
# mail => 'mail'
|
# mail => 'mail'
|
||||||
#},
|
#},
|
||||||
|
|
||||||
|
# When using LDAP authentication, LDAP users can invite people (by mail) to use Lufi to send them files without
|
||||||
|
# being authenticated.
|
||||||
|
# This is where you configure the behavior of the invitations.
|
||||||
|
# You may need to fetch some attributes from LDAP to use some invitations settings. See `ldap_map_attr` above.
|
||||||
|
# optional, no default
|
||||||
|
#invitations => {
|
||||||
|
# # The name of the key set in `ldap_map_attr` (above) that corresponds to the mail of the LDAP user
|
||||||
|
# # optional, default is `mail`
|
||||||
|
# mail_attr => 'mail',
|
||||||
|
# # The `From` header of invitation mail can be the mail of the LDAP user
|
||||||
|
# # Be sure to have a mail system that will correctly send the mail from your users! (DKIM, SPF…)
|
||||||
|
# # To enable this feature, set it to 1
|
||||||
|
# # optional, disabled by default
|
||||||
|
# send_invitation_with_ldap_user_mail => 1,
|
||||||
|
# # The user is able to set an expiration delay for the invitation.
|
||||||
|
# # This expiration delay can’t be more than this setting (in days).
|
||||||
|
# # optional, default is 30 days
|
||||||
|
# max_invitation_expiration_delay => 30,
|
||||||
|
# # Once the guest has submitted his files, he has an additional period of time to submit forgotten files.
|
||||||
|
# # You can set that additional period of time in minutes here.
|
||||||
|
# # To disable that feature, set it to 0 or less
|
||||||
|
# # optional, default is 10 minutes
|
||||||
|
# max_additional_period => 10,
|
||||||
|
# # Lufi follows privacy-by-design, so, by default, no files URLs (with the decode secret) are stored in database.
|
||||||
|
# # However, the concern is different for this case. Storing files URLs makes users able to retrieve the guests’ sent files
|
||||||
|
# # from their `invitations` page.
|
||||||
|
# # Set to 1 to store guests’ files URLs in database
|
||||||
|
# # optional, default is 0 (disabled)
|
||||||
|
# save_files_url_in_db => 0,
|
||||||
|
# # Users can resend the invitation to their guest. This does not extend the invitation’s expiration delay unless you
|
||||||
|
# # set this option to 1.
|
||||||
|
# # optional, default is 0 (disabled)
|
||||||
|
# extend_invitation_expiration_on_resend => 0,
|
||||||
|
#},
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
# Htpasswd authentication
|
# Htpasswd authentication
|
||||||
#########################
|
#########################
|
||||||
|
|
27
t/test.t
27
t/test.t
|
@ -77,6 +77,9 @@ BEGIN {
|
||||||
Lufi::DB::Slice->new(app => $m)->delete_all;
|
Lufi::DB::Slice->new(app => $m)->delete_all;
|
||||||
Lufi::DB::File->new(app => $m)->delete_all;
|
Lufi::DB::File->new(app => $m)->delete_all;
|
||||||
|
|
||||||
|
$config_file = Mojo::File->new($cfile->to_abs->to_string);
|
||||||
|
$config_orig = $config_file->slurp;
|
||||||
|
|
||||||
my $t = Test::Mojo->new('Lufi');
|
my $t = Test::Mojo->new('Lufi');
|
||||||
|
|
||||||
## Wait for short generation
|
## Wait for short generation
|
||||||
|
@ -103,6 +106,12 @@ test_infos_api(true);
|
||||||
auth_test_suite('zoidberg', 'zoidberg');
|
auth_test_suite('zoidberg', 'zoidberg');
|
||||||
restore_config();
|
restore_config();
|
||||||
|
|
||||||
|
## Test Swift object storage
|
||||||
|
switch_to_swift();
|
||||||
|
test_upload_file();
|
||||||
|
test_download_file();
|
||||||
|
restore_config();
|
||||||
|
|
||||||
done_testing();
|
done_testing();
|
||||||
|
|
||||||
######
|
######
|
||||||
|
@ -263,9 +272,7 @@ sub restore_config {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub switch_to_htpasswd {
|
sub switch_to_htpasswd {
|
||||||
$config_file = Mojo::File->new($cfile->to_abs->to_string);
|
$config_content = $config_orig;
|
||||||
$config_content = $config_file->slurp;
|
|
||||||
$config_orig = $config_content;
|
|
||||||
$config_content =~ s/#?htpasswd.*/htpasswd => 't\/lufi.passwd',/gm;
|
$config_content =~ s/#?htpasswd.*/htpasswd => 't\/lufi.passwd',/gm;
|
||||||
$config_file->spurt($config_content);
|
$config_file->spurt($config_content);
|
||||||
|
|
||||||
|
@ -291,3 +298,17 @@ sub switch_to_ldap {
|
||||||
## Wait for short generation
|
## Wait for short generation
|
||||||
sleep 5;
|
sleep 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub switch_to_swift {
|
||||||
|
$config_content = $config_orig;
|
||||||
|
$config_content =~ s/^( +)#?swift => \{ auth_url/$1swift => { auth_url/gm;
|
||||||
|
$config_file->spurt($config_content);
|
||||||
|
|
||||||
|
Lufi::DB::Slice->new(app => $m)->delete_all;
|
||||||
|
Lufi::DB::File->new(app => $m)->delete_all;
|
||||||
|
|
||||||
|
$t = Test::Mojo->new('Lufi');
|
||||||
|
|
||||||
|
## Wait for short generation
|
||||||
|
sleep 5;
|
||||||
|
}
|
||||||
|
|
|
@ -138,15 +138,15 @@ msgstr "Copy all links to clipboard"
|
||||||
msgid "Copy to clipboard"
|
msgid "Copy to clipboard"
|
||||||
msgstr "Copy to clipboard"
|
msgstr "Copy to clipboard"
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:507
|
#: lib/Lufi/Controller/Files.pm:502
|
||||||
msgid "Could not delete the file. You are not authenticated."
|
msgid "Could not delete the file. You are not authenticated."
|
||||||
msgstr "Could not delete the file. You are not authenticated."
|
msgstr "Could not delete the file. You are not authenticated."
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:489
|
#: lib/Lufi/Controller/Files.pm:484
|
||||||
msgid "Could not find the file. Are you sure of the URL and the token?"
|
msgid "Could not find the file. Are you sure of the URL and the token?"
|
||||||
msgstr "Could not find the file. Are you sure of the URL and the token?"
|
msgstr "Could not find the file. Are you sure of the URL and the token?"
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:400
|
#: lib/Lufi/Controller/Files.pm:395
|
||||||
msgid "Could not find the file. Are you sure of the URL?"
|
msgid "Could not find the file. Are you sure of the URL?"
|
||||||
msgstr "Could not find the file. Are you sure of the URL?"
|
msgstr "Could not find the file. Are you sure of the URL?"
|
||||||
|
|
||||||
|
@ -222,15 +222,15 @@ msgstr "Emails"
|
||||||
msgid "Encrypting part XX1 of XX2"
|
msgid "Encrypting part XX1 of XX2"
|
||||||
msgstr "Encrypting part XX1 of XX2"
|
msgstr "Encrypting part XX1 of XX2"
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:289
|
#: lib/Lufi/Controller/Files.pm:284
|
||||||
msgid "Error: the file existed but was deleted."
|
msgid "Error: the file existed but was deleted."
|
||||||
msgstr "Error: the file existed but was deleted."
|
msgstr "Error: the file existed but was deleted."
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:369
|
#: lib/Lufi/Controller/Files.pm:364
|
||||||
msgid "Error: the file has not been sent entirely."
|
msgid "Error: the file has not been sent entirely."
|
||||||
msgstr "Error: the file has not been sent entirely."
|
msgstr "Error: the file has not been sent entirely."
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:379
|
#: lib/Lufi/Controller/Files.pm:374
|
||||||
msgid "Error: unable to find the file. Are you sure of your URL?"
|
msgid "Error: unable to find the file. Are you sure of your URL?"
|
||||||
msgstr "Error: unable to find the file. Are you sure of your URL?"
|
msgstr "Error: unable to find the file. Are you sure of your URL?"
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ msgstr "Expires at"
|
||||||
msgid "Export localStorage data"
|
msgid "Export localStorage data"
|
||||||
msgstr "Export localStorage data"
|
msgstr "Export localStorage data"
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:471
|
#: lib/Lufi/Controller/Files.pm:466
|
||||||
msgid "File deleted"
|
msgid "File deleted"
|
||||||
msgstr "File deleted"
|
msgstr "File deleted"
|
||||||
|
|
||||||
|
@ -436,7 +436,7 @@ msgid "Name of the zip file"
|
||||||
msgstr "Name of the zip file"
|
msgstr "Name of the zip file"
|
||||||
|
|
||||||
#. (format_bytes($json->{size})
|
#. (format_bytes($json->{size})
|
||||||
#: lib/Lufi/Controller/Files.pm:108
|
#: lib/Lufi/Controller/Files.pm:109
|
||||||
msgid "No enough space available on the server for this file (size: %1)."
|
msgid "No enough space available on the server for this file (size: %1)."
|
||||||
msgstr "No enough space available on the server for this file (size: %1)."
|
msgstr "No enough space available on the server for this file (size: %1)."
|
||||||
|
|
||||||
|
@ -551,7 +551,7 @@ msgid "Sorry, your invitation has expired or has been deleted."
|
||||||
msgstr "Sorry, your invitation has expired or has been deleted."
|
msgstr "Sorry, your invitation has expired or has been deleted."
|
||||||
|
|
||||||
#. ($invit->ldap_user_mail)
|
#. ($invit->ldap_user_mail)
|
||||||
#: lib/Lufi/Controller/Files.pm:122
|
#: lib/Lufi/Controller/Files.pm:123
|
||||||
msgid "Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation."
|
msgid "Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation."
|
||||||
msgstr "Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation."
|
msgstr "Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation."
|
||||||
|
|
||||||
|
@ -585,7 +585,7 @@ msgstr "The email subject can't be empty."
|
||||||
msgid "The expiration delay (%1) is not between 1 and %2 days."
|
msgid "The expiration delay (%1) is not between 1 and %2 days."
|
||||||
msgstr "The expiration delay (%1) is not between 1 and %2 days."
|
msgstr "The expiration delay (%1) is not between 1 and %2 days."
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:468
|
#: lib/Lufi/Controller/Files.pm:463
|
||||||
msgid "The file has already been deleted"
|
msgid "The file has already been deleted"
|
||||||
msgstr "The file has already been deleted"
|
msgstr "The file has already been deleted"
|
||||||
|
|
||||||
|
@ -640,11 +640,11 @@ msgstr "The mail has been sent."
|
||||||
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>."
|
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>."
|
||||||
msgstr "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>."
|
msgstr "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>."
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:236
|
#: lib/Lufi/Controller/Files.pm:231
|
||||||
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
|
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
|
||||||
msgstr "The server was unable to find the file record to add your file part to. Please, contact the administrator."
|
msgstr "The server was unable to find the file record to add your file part to. Please, contact the administrator."
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:295
|
#: lib/Lufi/Controller/Files.pm:290
|
||||||
msgid "This file has been deactivated by the admins. Contact them to know why."
|
msgid "This file has been deactivated by the admins. Contact them to know why."
|
||||||
msgstr "This file has been deactivated by the admins. Contact them to know why."
|
msgstr "This file has been deactivated by the admins. Contact them to know why."
|
||||||
|
|
||||||
|
@ -674,17 +674,17 @@ msgid "Unable to copy the link(s) to your clipboard"
|
||||||
msgstr "Unable to copy the link(s) to your clipboard"
|
msgstr "Unable to copy the link(s) to your clipboard"
|
||||||
|
|
||||||
#. ($short)
|
#. ($short)
|
||||||
#: lib/Lufi/Controller/Files.pm:439
|
#: lib/Lufi/Controller/Files.pm:434
|
||||||
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
|
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
|
||||||
msgstr "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
|
msgstr "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
|
||||||
|
|
||||||
#. ($short)
|
#. ($short)
|
||||||
#: lib/Lufi/Controller/Files.pm:429
|
#: lib/Lufi/Controller/Files.pm:424
|
||||||
msgid "Unable to get counter for %1. The token is invalid."
|
msgid "Unable to get counter for %1. The token is invalid."
|
||||||
msgstr "Unable to get counter for %1. The token is invalid."
|
msgstr "Unable to get counter for %1. The token is invalid."
|
||||||
|
|
||||||
#. ($short)
|
#. ($short)
|
||||||
#: lib/Lufi/Controller/Files.pm:449
|
#: lib/Lufi/Controller/Files.pm:444
|
||||||
msgid "Unable to get counter for %1. You are not authenticated."
|
msgid "Unable to get counter for %1. You are not authenticated."
|
||||||
msgstr "Unable to get counter for %1. You are not authenticated."
|
msgstr "Unable to get counter for %1. You are not authenticated."
|
||||||
|
|
||||||
|
@ -769,7 +769,7 @@ msgstr "Your browser does not have enough entropy to generate a strong encryptio
|
||||||
msgid "Your file is too big: %1 (maximum size allowed: %2)"
|
msgid "Your file is too big: %1 (maximum size allowed: %2)"
|
||||||
msgstr "Your file is too big: %1 (maximum size allowed: %2)"
|
msgstr "Your file is too big: %1 (maximum size allowed: %2)"
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:351
|
#: lib/Lufi/Controller/Files.pm:346
|
||||||
msgid "Your password is not valid. Please refresh the page to retry."
|
msgid "Your password is not valid. Please refresh the page to retry."
|
||||||
msgstr "Your password is not valid. Please refresh the page to retry."
|
msgstr "Your password is not valid. Please refresh the page to retry."
|
||||||
|
|
||||||
|
|
|
@ -138,15 +138,15 @@ msgstr ""
|
||||||
msgid "Copy to clipboard"
|
msgid "Copy to clipboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:507
|
#: lib/Lufi/Controller/Files.pm:502
|
||||||
msgid "Could not delete the file. You are not authenticated."
|
msgid "Could not delete the file. You are not authenticated."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:489
|
#: lib/Lufi/Controller/Files.pm:484
|
||||||
msgid "Could not find the file. Are you sure of the URL and the token?"
|
msgid "Could not find the file. Are you sure of the URL and the token?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:400
|
#: lib/Lufi/Controller/Files.pm:395
|
||||||
msgid "Could not find the file. Are you sure of the URL?"
|
msgid "Could not find the file. Are you sure of the URL?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -222,15 +222,15 @@ msgstr ""
|
||||||
msgid "Encrypting part XX1 of XX2"
|
msgid "Encrypting part XX1 of XX2"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:289
|
#: lib/Lufi/Controller/Files.pm:284
|
||||||
msgid "Error: the file existed but was deleted."
|
msgid "Error: the file existed but was deleted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:369
|
#: lib/Lufi/Controller/Files.pm:364
|
||||||
msgid "Error: the file has not been sent entirely."
|
msgid "Error: the file has not been sent entirely."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:379
|
#: lib/Lufi/Controller/Files.pm:374
|
||||||
msgid "Error: unable to find the file. Are you sure of your URL?"
|
msgid "Error: unable to find the file. Are you sure of your URL?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ msgstr ""
|
||||||
msgid "Export localStorage data"
|
msgid "Export localStorage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:471
|
#: lib/Lufi/Controller/Files.pm:466
|
||||||
msgid "File deleted"
|
msgid "File deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -436,7 +436,7 @@ msgid "Name of the zip file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. (format_bytes($json->{size})
|
#. (format_bytes($json->{size})
|
||||||
#: lib/Lufi/Controller/Files.pm:108
|
#: lib/Lufi/Controller/Files.pm:109
|
||||||
msgid "No enough space available on the server for this file (size: %1)."
|
msgid "No enough space available on the server for this file (size: %1)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -551,7 +551,7 @@ msgid "Sorry, your invitation has expired or has been deleted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. ($invit->ldap_user_mail)
|
#. ($invit->ldap_user_mail)
|
||||||
#: lib/Lufi/Controller/Files.pm:122
|
#: lib/Lufi/Controller/Files.pm:123
|
||||||
msgid "Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation."
|
msgid "Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -585,7 +585,7 @@ msgstr ""
|
||||||
msgid "The expiration delay (%1) is not between 1 and %2 days."
|
msgid "The expiration delay (%1) is not between 1 and %2 days."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:468
|
#: lib/Lufi/Controller/Files.pm:463
|
||||||
msgid "The file has already been deleted"
|
msgid "The file has already been deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -640,11 +640,11 @@ msgstr ""
|
||||||
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>."
|
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:236
|
#: lib/Lufi/Controller/Files.pm:231
|
||||||
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
|
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:295
|
#: lib/Lufi/Controller/Files.pm:290
|
||||||
msgid "This file has been deactivated by the admins. Contact them to know why."
|
msgid "This file has been deactivated by the admins. Contact them to know why."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -674,17 +674,17 @@ msgid "Unable to copy the link(s) to your clipboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. ($short)
|
#. ($short)
|
||||||
#: lib/Lufi/Controller/Files.pm:439
|
#: lib/Lufi/Controller/Files.pm:434
|
||||||
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
|
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. ($short)
|
#. ($short)
|
||||||
#: lib/Lufi/Controller/Files.pm:429
|
#: lib/Lufi/Controller/Files.pm:424
|
||||||
msgid "Unable to get counter for %1. The token is invalid."
|
msgid "Unable to get counter for %1. The token is invalid."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. ($short)
|
#. ($short)
|
||||||
#: lib/Lufi/Controller/Files.pm:449
|
#: lib/Lufi/Controller/Files.pm:444
|
||||||
msgid "Unable to get counter for %1. You are not authenticated."
|
msgid "Unable to get counter for %1. You are not authenticated."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -769,7 +769,7 @@ msgstr ""
|
||||||
msgid "Your file is too big: %1 (maximum size allowed: %2)"
|
msgid "Your file is too big: %1 (maximum size allowed: %2)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/Lufi/Controller/Files.pm:351
|
#: lib/Lufi/Controller/Files.pm:346
|
||||||
msgid "Your password is not valid. Please refresh the page to retry."
|
msgid "Your password is not valid. Please refresh the page to retry."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -51,3 +51,7 @@ DROP TABLE invitations;
|
||||||
ALTER TABLE files MODIFY filesize bigint;
|
ALTER TABLE files MODIFY filesize bigint;
|
||||||
-- 4 down
|
-- 4 down
|
||||||
ALTER TABLE files MODIFY filesize integer;
|
ALTER TABLE files MODIFY filesize integer;
|
||||||
|
-- 5 up
|
||||||
|
ALTER TABLE slices MODIFY path varchar(255);
|
||||||
|
-- 5 down
|
||||||
|
ALTER TABLE slices MODIFY path varchar(255) unique NOT NULL;
|
||||||
|
|
|
@ -54,3 +54,9 @@ DROP TABLE invitations;
|
||||||
ALTER TABLE files ALTER COLUMN filesize TYPE bigint;
|
ALTER TABLE files ALTER COLUMN filesize TYPE bigint;
|
||||||
-- 5 down
|
-- 5 down
|
||||||
ALTER TABLE files ALTER COLUMN filesize TYPE integer;
|
ALTER TABLE files ALTER COLUMN filesize TYPE integer;
|
||||||
|
-- 6 up
|
||||||
|
ALTER TABLE slices ALTER COLUMN path DROP NOT NULL;
|
||||||
|
ALTER TABLE slices DROP CONSTRAINT slices_path_key;
|
||||||
|
-- 6 down
|
||||||
|
ALTER TABLE slices ADD CONSTRAINT slices_path_key UNIQUE (path) ;
|
||||||
|
ALTER TABLE slices ALTER COLUMN path SET NOT NULL;
|
||||||
|
|
Loading…
Reference in New Issue