Database support #1
25 changed files with 483 additions and 1 deletions
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
password => '',
|
|
||||||
db_file => 'sql/fotostore.db',
|
db_file => 'sql/fotostore.db',
|
||||||
|
invite_code => 'very_secure_invite_code',
|
||||||
}
|
}
|
39
fotostore.pl
Normal file → Executable file
39
fotostore.pl
Normal file → Executable file
|
@ -81,6 +81,45 @@ get '/logout' => sub {
|
||||||
$self->render( text => 'bye' );
|
$self->render( text => 'bye' );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
get '/register' => ( authenticated => 0 ) => sub {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
post '/register' => ( authenticated => 0 ) => sub {
|
||||||
|
my $self = shift;
|
||||||
|
my $username = $self->req->param('username');
|
||||||
|
my $password = $self->req->param('password');
|
||||||
|
my $fullname = $self->req->param('fullname');
|
||||||
|
my $invite = $self->req->param('invite');
|
||||||
|
|
||||||
|
if ($invite eq $config->{'invite_code'}) {
|
||||||
|
#chek that username is not taken
|
||||||
|
my $user = $db->get_user($username);
|
||||||
|
if ($user->{'user_id'} > 0) {
|
||||||
|
$self->render(template => 'error', message => 'Username already taken!');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($fullname eq '') {
|
||||||
|
$fullname = $username;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $digest = $sha->add($password);
|
||||||
|
$db->add_user($username, $digest->hexdigest(), $fullname);
|
||||||
|
|
||||||
|
#Authenticate user after add
|
||||||
|
if ( $self->authenticate( $username, $password ) ) {
|
||||||
|
$self->redirect_to('/');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$self->render( text => 'Login failed :(' );
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$self->render(template => 'error', message => 'invalid invite code');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
# Display top page
|
# Display top page
|
||||||
get '/' => sub {
|
get '/' => sub {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
67
lib/FotoStore/DB.pm
Normal file
67
lib/FotoStore/DB.pm
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package FotoStore::DB;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use feature qw(signatures);
|
||||||
|
no warnings qw(experimental::signatures);
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $class = shift;
|
||||||
|
my $db_file = shift;
|
||||||
|
|
||||||
|
my $dbh = DBI->connect(sprintf('dbi:SQLite:dbname=%s', $db_file),"","");
|
||||||
|
my $self = {
|
||||||
|
dbh => $dbh,
|
||||||
|
};
|
||||||
|
bless $self, $class;
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub check_user ($self, $nickname, $password) {
|
||||||
|
print STDERR "[$nickname][$password]";
|
||||||
|
my ($user_id) = $self->{'dbh'}->selectrow_array(q~select user_id from users where nickname=? and password=?~, undef, ($nickname, $password));
|
||||||
|
return $user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_user ($self, $user_id) {
|
||||||
|
if ($user_id =~ /^\d+$/) {
|
||||||
|
return $self->_get_user_by_user_id($user_id);
|
||||||
|
} else {
|
||||||
|
return $self->_get_user_by_username($user_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _get_user_by_user_id ($self, $user_id) {
|
||||||
|
my $user_data = $self->{'dbh'}->selectrow_hashref(q~select user_id, nickname, fullname, timestamp from users where user_id=?~, {}, ($user_id));
|
||||||
|
return $user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _get_user_by_username($self, $username) {
|
||||||
|
my $user_data = $self->{'dbh'}->selectrow_hashref(q~select user_id, nickname, fullname, timestamp from users where nickname=?~, {}, ($username));
|
||||||
|
return $user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub add_user($self, $username, $password, $fullname) {
|
||||||
|
my $rows = $self->{'dbh'}->do(q~insert into users (nickname, password, fullname) values (?, ?, ?)~, undef, ($username, $password, $fullname));
|
||||||
|
if ($self->{'dbh'}->errstr) {
|
||||||
|
die $self->{'dbh'}->errstr;
|
||||||
|
}
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub add_file($self, $user_id, $filename) {
|
||||||
|
my $rows = $self->{'dbh'}->do(q~insert into images (owner_id, file_name) values (?, ?)~, undef, ($user_id, $filename));
|
||||||
|
if ($self->{'dbh'}->errstr) {
|
||||||
|
die $self->{'dbh'}->errstr;
|
||||||
|
}
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_files($self, $user_id, $count=20, $start_at=0) {
|
||||||
|
return $self->{'dbh'}->selectall_arrayref(q~select * from images where owner_id=? order by created_time desc~, { Slice => {} }, $user_id );
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
9
public/css/main.css
Normal file
9
public/css/main.css
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.foto-block {
|
||||||
|
/* border: 1px solid black; */
|
||||||
|
}
|
||||||
|
.foto-block .image {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
.foto-block .foto-notes {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
3
public/file_uploader/.gitignore
vendored
Executable file
3
public/file_uploader/.gitignore
vendored
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
.DS_Store
|
||||||
|
*.pyc
|
||||||
|
node_modules
|
81
public/file_uploader/.jshintrc
Executable file
81
public/file_uploader/.jshintrc
Executable file
|
@ -0,0 +1,81 @@
|
||||||
|
{
|
||||||
|
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
|
||||||
|
"camelcase" : true, // true: Identifiers must be in camelCase
|
||||||
|
"curly" : true, // true: Require {} for every new block or scope
|
||||||
|
"eqeqeq" : true, // true: Require triple equals (===) for comparison
|
||||||
|
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
|
||||||
|
"immed" : true, // true: Require immediate invocations to be wrapped in parens
|
||||||
|
// e.g. `(function () { } ());`
|
||||||
|
"indent" : 4, // {int} Number of spaces to use for indentation
|
||||||
|
"latedef" : true, // true: Require variables/functions to be defined before being used
|
||||||
|
"newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
|
||||||
|
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
|
||||||
|
"noempty" : true, // true: Prohibit use of empty blocks
|
||||||
|
"nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment)
|
||||||
|
"plusplus" : false, // true: Prohibit use of `++` & `--`
|
||||||
|
"quotmark" : "single", // Quotation mark consistency:
|
||||||
|
// false : do nothing (default)
|
||||||
|
// true : ensure whatever is used is consistent
|
||||||
|
// "single" : require single quotes
|
||||||
|
// "double" : require double quotes
|
||||||
|
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
|
||||||
|
"unused" : true, // true: Require all defined variables be used
|
||||||
|
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
|
||||||
|
"trailing" : true, // true: Prohibit trailing whitespaces
|
||||||
|
"maxparams" : false, // {int} Max number of formal params allowed per function
|
||||||
|
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
|
||||||
|
"maxstatements" : false, // {int} Max number statements per function
|
||||||
|
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
|
||||||
|
"maxlen" : false, // {int} Max number of characters per line
|
||||||
|
|
||||||
|
// Relaxing
|
||||||
|
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
|
||||||
|
"boss" : false, // true: Tolerate assignments where comparisons would be expected
|
||||||
|
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
|
||||||
|
"eqnull" : false, // true: Tolerate use of `== null`
|
||||||
|
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
|
||||||
|
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
|
||||||
|
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
|
||||||
|
// (ex: `for each`, multiple try/catch, function expression…)
|
||||||
|
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
|
||||||
|
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
|
||||||
|
"funcscope" : false, // true: Tolerate defining variables inside control statements"
|
||||||
|
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
|
||||||
|
"iterator" : false, // true: Tolerate using the `__iterator__` property
|
||||||
|
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
|
||||||
|
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
|
||||||
|
"laxcomma" : false, // true: Tolerate comma-first style coding
|
||||||
|
"loopfunc" : false, // true: Tolerate functions being defined in loops
|
||||||
|
"multistr" : false, // true: Tolerate multi-line strings
|
||||||
|
"proto" : false, // true: Tolerate using the `__proto__` property
|
||||||
|
"scripturl" : false, // true: Tolerate script-targeted URLs
|
||||||
|
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
|
||||||
|
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
|
||||||
|
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
|
||||||
|
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
|
||||||
|
"validthis" : false, // true: Tolerate using this in a non-constructor function
|
||||||
|
|
||||||
|
// Environments
|
||||||
|
"browser" : false, // Web Browser (window, document, etc)
|
||||||
|
"couch" : false, // CouchDB
|
||||||
|
"devel" : false, // Development/debugging (alert, confirm, etc)
|
||||||
|
"dojo" : false, // Dojo Toolkit
|
||||||
|
"jquery" : false, // jQuery
|
||||||
|
"mootools" : false, // MooTools
|
||||||
|
"node" : false, // Node.js
|
||||||
|
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
|
||||||
|
"prototypejs" : false, // Prototype and Scriptaculous
|
||||||
|
"rhino" : false, // Rhino
|
||||||
|
"worker" : false, // Web Workers
|
||||||
|
"wsh" : false, // Windows Scripting Host
|
||||||
|
"yui" : false, // Yahoo User Interface
|
||||||
|
|
||||||
|
// Legacy
|
||||||
|
"nomen" : true, // true: Prohibit dangling `_` in variables
|
||||||
|
"onevar" : true, // true: Allow only one `var` statement per function
|
||||||
|
"passfail" : false, // true: Stop on first error
|
||||||
|
"white" : true, // true: Check against strict whitespace and indentation rules
|
||||||
|
|
||||||
|
// Custom Globals
|
||||||
|
"globals" : {} // additional predefined global variables
|
||||||
|
}
|
20
public/file_uploader/.npmignore
Executable file
20
public/file_uploader/.npmignore
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
*
|
||||||
|
!css/jquery.fileupload-noscript.css
|
||||||
|
!css/jquery.fileupload-ui-noscript.css
|
||||||
|
!css/jquery.fileupload-ui.css
|
||||||
|
!css/jquery.fileupload.css
|
||||||
|
!img/loading.gif
|
||||||
|
!img/progressbar.gif
|
||||||
|
!js/cors/jquery.postmessage-transport.js
|
||||||
|
!js/cors/jquery.xdr-transport.js
|
||||||
|
!js/vendor/jquery.ui.widget.js
|
||||||
|
!js/jquery.fileupload-angular.js
|
||||||
|
!js/jquery.fileupload-audio.js
|
||||||
|
!js/jquery.fileupload-image.js
|
||||||
|
!js/jquery.fileupload-jquery-ui.js
|
||||||
|
!js/jquery.fileupload-process.js
|
||||||
|
!js/jquery.fileupload-ui.js
|
||||||
|
!js/jquery.fileupload-validate.js
|
||||||
|
!js/jquery.fileupload-video.js
|
||||||
|
!js/jquery.fileupload.js
|
||||||
|
!js/jquery.iframe-transport.js
|
14
sql/deploy/album_images.sql
Normal file
14
sql/deploy/album_images.sql
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
-- Deploy fotostore:album_images to sqlite
|
||||||
|
-- requires: images
|
||||||
|
-- requires: albums
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE album_images (
|
||||||
|
record_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
album_id INTEGER REFERENCES albums (album_id),
|
||||||
|
image_id INTEGER REFERENCES images (file_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
14
sql/deploy/albums.sql
Normal file
14
sql/deploy/albums.sql
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
-- Deploy fotostore:albums to sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE albums (
|
||||||
|
album_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name STRING NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
created DATETIME DEFAULT (CURRENT_TIMESTAMP),
|
||||||
|
modified DATETIME DEFAULT (CURRENT_TIMESTAMP),
|
||||||
|
deleted BOOLEAN
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
14
sql/deploy/user_albums.sql
Normal file
14
sql/deploy/user_albums.sql
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
-- Deploy fotostore:user_albums to sqlite
|
||||||
|
-- requires: users
|
||||||
|
-- requires: albums
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE user_albums (
|
||||||
|
record_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
user_id INTEGER REFERENCES users (user_id),
|
||||||
|
album_id INTEGER REFERENCES albums (album_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
12
sql/deploy/user_images.sql
Normal file
12
sql/deploy/user_images.sql
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
-- Deploy fotostore:user_images to sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE user_images (
|
||||||
|
record_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
user_id INTEGER REFERENCES users (user_id) ON DELETE CASCADE,
|
||||||
|
image_id INTEGER REFERENCES images (file_id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
7
sql/revert/album_images.sql
Normal file
7
sql/revert/album_images.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Revert fotostore:album_images from sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DROP TABLE album_images;
|
||||||
|
|
||||||
|
COMMIT;
|
7
sql/revert/albums.sql
Normal file
7
sql/revert/albums.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Revert fotostore:albums from sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DROP TABLE albums;
|
||||||
|
|
||||||
|
COMMIT;
|
7
sql/revert/user_albums.sql
Normal file
7
sql/revert/user_albums.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Revert fotostore:user_albums from sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DROP TABLE user_albums;
|
||||||
|
|
||||||
|
COMMIT;
|
7
sql/revert/user_images.sql
Normal file
7
sql/revert/user_images.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Revert fotostore:user_images from sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DROP TABLE user_images;
|
||||||
|
|
||||||
|
COMMIT;
|
7
sql/verify/album_images.sql
Normal file
7
sql/verify/album_images.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Verify fotostore:album_images on sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
select record_id, album_id, image_id from album_images where 0;
|
||||||
|
|
||||||
|
ROLLBACK;
|
7
sql/verify/albums.sql
Normal file
7
sql/verify/albums.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Verify fotostore:albums on sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
select album_id, name, description, created, modified, deleted from albums where 0;
|
||||||
|
|
||||||
|
ROLLBACK;
|
7
sql/verify/user_albums.sql
Normal file
7
sql/verify/user_albums.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Verify fotostore:user_albums on sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
select record_id, album_id, user_id from user_albums where 0;
|
||||||
|
|
||||||
|
ROLLBACK;
|
7
sql/verify/user_images.sql
Normal file
7
sql/verify/user_images.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Verify fotostore:user_images on sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
select record_id, user_id, image_id from user_images where 0;
|
||||||
|
|
||||||
|
ROLLBACK;
|
10
templates/error.html.ep
Normal file
10
templates/error.html.ep
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" >
|
||||||
|
<title>Error</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%= $message %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
54
templates/images_list.html.ep
Normal file
54
templates/images_list.html.ep
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<div class="container">
|
||||||
|
<div class="logout"><a href="/logout">Logout</a></div>
|
||||||
|
<div class"upload-form">
|
||||||
|
<input id="fileupload" type="file" name="image" data-url="/upload" multiple>
|
||||||
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||||
|
<script src="/file_uploader/js/vendor/jquery.ui.widget.js"></script>
|
||||||
|
<script src="/file_uploader/js/jquery.iframe-transport.js"></script>
|
||||||
|
<script src="/file_uploader/js/jquery.fileupload.js"></script>
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
$('#fileupload').fileupload({
|
||||||
|
dataType: 'json',
|
||||||
|
done: function (e, data) {
|
||||||
|
$.each(data.result.files, function (index, file) {
|
||||||
|
$('<p/>').text(file.name).appendTo('#lastUploadLog');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
sequentialUploads: true,
|
||||||
|
progressall: function (e, data) {
|
||||||
|
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||||
|
$('#progress .bar').css(
|
||||||
|
'width',
|
||||||
|
progress + '%'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
<div id="progress">
|
||||||
|
<div class="bar" style="width: 0%;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="lastUploadLog"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- display images from server -->
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<% foreach my $image (@$images) { %>
|
||||||
|
<div class="foto-block col-md-3">
|
||||||
|
<div class="image">
|
||||||
|
<img src="<%= "/$image_base/$user_id/$thumbs_size/$image" %>">
|
||||||
|
</div>
|
||||||
|
<div class="foto-notes">
|
||||||
|
<a href='<%= "/$image_base/$user_id/$orig/$image" %>'>Image original</a>
|
||||||
|
<% for my $scale (@$scales) { %>
|
||||||
|
<a href='<%= "/$image_base/$user_id/$scale/$image" %>'><%= $scale %></a>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
18
templates/index.html.ep
Normal file
18
templates/index.html.ep
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
% layout 'base';
|
||||||
|
<h1>Rough, Slow, Stupid, Contrary Photohosting</h1>
|
||||||
|
|
||||||
|
<% if (is_user_authenticated()) { %>
|
||||||
|
%= include 'images_list'
|
||||||
|
<% } else { %>
|
||||||
|
|
||||||
|
<div class="login-form">
|
||||||
|
<form method="post" action="<%= url_for('login') %>" >
|
||||||
|
<input type="text" name="username" >
|
||||||
|
<input type="password" name="password">
|
||||||
|
<input type="submit" value="Login">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
|
29
templates/layouts/base.html.ep
Normal file
29
templates/layouts/base.html.ep
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" >
|
||||||
|
<title>Rough, Slow, Stupid, Contrary Photohosting</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<!-- Bootstrap styles -->
|
||||||
|
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
||||||
|
<!-- Generic page styles -->
|
||||||
|
<link rel="stylesheet" href="/file_uploader/css/style.css">
|
||||||
|
<!-- blueimp Gallery styles -->
|
||||||
|
<link rel="stylesheet" href="//blueimp.github.io/Gallery/css/blueimp-gallery.min.css">
|
||||||
|
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
|
||||||
|
<link rel="stylesheet" href="/file_uploader/css/jquery.fileupload.css">
|
||||||
|
<link rel="stylesheet" href="/file_uploader/css/jquery.fileupload-ui.css">
|
||||||
|
<link rel="stylesheet" href="/css/main.css">
|
||||||
|
<!-- CSS adjustments for browsers with JavaScript disabled -->
|
||||||
|
<noscript><link rel="stylesheet" href="/file_uploader/css/jquery.fileupload-noscript.css"></noscript>
|
||||||
|
<noscript><link rel="stylesheet" href="/file_uploader/css/jquery.fileupload-ui-noscript.css"></noscript>
|
||||||
|
<style>
|
||||||
|
.bar {
|
||||||
|
height: 18px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%= content %>
|
||||||
|
</body>
|
||||||
|
</html>
|
17
templates/no_logged.html.ep
Normal file
17
templates/no_logged.html.ep
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" >
|
||||||
|
<title>Rough, Slow, Stupid, Contrary Photohosting</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Rough, Slow, Stupid, Contrary Photohosting</h1>
|
||||||
|
<form method="post" action="<%= url_for('login') %>" >
|
||||||
|
<div>
|
||||||
|
<input type="text" name="username" >
|
||||||
|
<input type="password" name="password">
|
||||||
|
<input type="submit" value="Login">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
25
templates/register.html.ep
Normal file
25
templates/register.html.ep
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
% layout 'base';
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="register">
|
||||||
|
<form method="post" action="<%= url_for('register') %>" >
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Login:
|
||||||
|
<input type="text" name="username" >
|
||||||
|
</p><p>
|
||||||
|
Fullname:
|
||||||
|
<input type="text" name="Fullname" >
|
||||||
|
</p><p>
|
||||||
|
Password:
|
||||||
|
<input type="password" name="password">
|
||||||
|
</p><p>
|
||||||
|
Invite code:
|
||||||
|
<input type="text" name="invite" >
|
||||||
|
</p><p>
|
||||||
|
<input type="submit" value="Register">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in a new issue