mirror of
https://github.com/Foltik/Shimapan
synced 2025-02-25 16:50:35 -05:00
commit
d3bef194ff
@ -14,4 +14,8 @@ var InviteSchema = mongoose.Schema({
|
||||
exp: Date
|
||||
});
|
||||
|
||||
InviteSchema.methods.use = function(canonicalname, cb) {
|
||||
return this.model('Invite').updateOne({code: this.code}, {recipient: canonicalname, used: Date.now()}, cb);
|
||||
};
|
||||
|
||||
module.exports = mongoose.model('Invite', InviteSchema);
|
@ -11,6 +11,7 @@ var UploadSchema = mongoose.Schema({
|
||||
default: 0
|
||||
},
|
||||
uploader: String,
|
||||
uploadKey: String,
|
||||
date: Date,
|
||||
file: Object
|
||||
});
|
||||
|
@ -7,6 +7,11 @@ var UserSchema = mongoose.Schema({
|
||||
unique: true,
|
||||
required: true
|
||||
},
|
||||
canonicalname: {
|
||||
type: String,
|
||||
unique: true,
|
||||
required: true
|
||||
},
|
||||
scope: [String],
|
||||
uploadCount: {
|
||||
type: Number,
|
||||
@ -19,6 +24,6 @@ var UserSchema = mongoose.Schema({
|
||||
date: Date
|
||||
});
|
||||
|
||||
UserSchema.plugin(passportLocalMongoose);
|
||||
UserSchema.plugin(passportLocalMongoose, {usernameField: 'canonicalname'});
|
||||
|
||||
module.exports = mongoose.model('User', UserSchema);
|
@ -58,8 +58,7 @@ fieldset:before {
|
||||
border: 1px solid #999;
|
||||
width: 226px;
|
||||
padding: 12px 12px;
|
||||
margin: auto;
|
||||
margin-bottom: 5px;
|
||||
margin: auto auto 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
@ -70,9 +69,8 @@ button {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding: 10px 30px;
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
transition: background 0.25s;
|
||||
margin: 20px auto auto;
|
||||
transition: background 0.25s, border-color 0.25s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
@ -81,3 +79,31 @@ button:hover {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button.shake {
|
||||
background: #ff6666;
|
||||
border-color: #ff6666;
|
||||
color: #fff;
|
||||
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
|
||||
transform: translate3d(0, 0, 0);
|
||||
backface-visibility: hidden;
|
||||
perspective: 1000px;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
10%, 90% {
|
||||
transform: translate3d(-1px, 0, 0);
|
||||
}
|
||||
|
||||
20%, 80% {
|
||||
transform: translate3d(2px, 0, 0);
|
||||
}
|
||||
|
||||
30%, 50%, 70% {
|
||||
transform: translate3d(-4px, 0, 0);
|
||||
}
|
||||
|
||||
40%, 60% {
|
||||
transform: translate3d(4px, 0, 0);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ body {
|
||||
|
||||
a {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
top: 40px;
|
||||
left: 48%;
|
||||
opacity: 0.1;
|
||||
height: 30px;
|
||||
@ -34,8 +34,6 @@ video {
|
||||
left: 50%;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
width: 1920px;
|
||||
height: 760px;
|
||||
z-index: -100;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
background-size: cover;
|
||||
|
@ -1,57 +1,48 @@
|
||||
var angular = require('angular');
|
||||
|
||||
angular.module('ApiCtrl', ['ApiSvc', 'AuthSvc']).controller('ApiController', ['$scope', 'ApiService', 'AuthService', function ($scope, ApiService, AuthService) {
|
||||
// Transforms an array of period-separated properties ex. ["file.upload", "user.view", "user.ban"]
|
||||
// to json ex. { "file": "upload", "user": ["view", "ban"] }
|
||||
function splitScope(scope) {
|
||||
var res = {};
|
||||
for (var i in scope) {
|
||||
var perm = scope[i];
|
||||
var prefix = perm.substr(0, perm.indexOf('.'));
|
||||
var postfix = perm.substr(perm.indexOf('.') + 1);
|
||||
if (!res[prefix]) res[prefix] = [];
|
||||
res[prefix].push({name: postfix});
|
||||
if (scope.hasOwnProperty(i)) {
|
||||
var perm = scope[i];
|
||||
var prefix = perm.substr(0, perm.indexOf('.'));
|
||||
var postfix = perm.substr(perm.indexOf('.') + 1);
|
||||
if (!res[prefix]) res[prefix] = [];
|
||||
res[prefix].push({name: postfix});
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
$scope.checkCkPerm = function(prefix, perm) {
|
||||
var index = $scope.scopeObj[prefix].indexOf(perm);
|
||||
if ($scope.scopeObj[prefix][index].isChecked) {
|
||||
$scope.ckScope.push(prefix + '.' + perm.name);
|
||||
} else {
|
||||
var index = $scope.ckScope.indexOf(prefix + '.' + perm.name);
|
||||
$scope.ckScope.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
// Called on init, retrieves the user's scope from the server.
|
||||
$scope.parseScope = function () {
|
||||
AuthService.currentUser(function (res) {
|
||||
$scope.scopeObj = splitScope(res.scope);
|
||||
$scope.ckScope = [];
|
||||
$scope.currKeyScope = [];
|
||||
})
|
||||
};
|
||||
|
||||
// Triggered when a checkbox for a permission changes.
|
||||
// Updates the currKeyScope object with the addition or removal.
|
||||
$scope.updateCurrKeyPerm = function(prefix, perm) {
|
||||
var index = $scope.scopeObj[prefix].indexOf(perm);
|
||||
if ($scope.scopeObj[prefix][index].isChecked) {
|
||||
$scope.currKeyScope.push(prefix + '.' + perm.name);
|
||||
} else {
|
||||
index = $scope.currKeyScope.indexOf(prefix + '.' + perm.name);
|
||||
$scope.currKeyScope.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.getKeys = function () {
|
||||
ApiService.getAll(function (keys) {
|
||||
ApiService.getAllKeys(function (keys) {
|
||||
$scope.keys = keys;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.hideNewKey = function () {
|
||||
$scope.nModalShow = false;
|
||||
};
|
||||
$scope.showNewKey = function () {
|
||||
$scope.nModalShow = true;
|
||||
};
|
||||
|
||||
$scope.hideKeyInfo = function () {
|
||||
$scope.kModalShow = false;
|
||||
};
|
||||
$scope.showKeyInfo = function (key) {
|
||||
$scope.kModalShow = true;
|
||||
$scope.currKey = key;
|
||||
$scope.currKey.scopeObj = splitScope($scope.currKey.scope);
|
||||
};
|
||||
|
||||
$scope.deleteKey = function (key) {
|
||||
ApiService.deleteKey(key, function () {
|
||||
var index = $scope.keys.indexOf(key);
|
||||
@ -62,17 +53,35 @@ angular.module('ApiCtrl', ['ApiSvc', 'AuthSvc']).controller('ApiController', ['$
|
||||
};
|
||||
|
||||
$scope.createKey = function () {
|
||||
if ($scope.ckScope.length === 0 || !$scope.ckIdentifier)
|
||||
if ($scope.currKeyScope.length === 0 || !$scope.currKeyIdentifier)
|
||||
return;
|
||||
|
||||
ApiService.createKey({
|
||||
identifier: $scope.ckIdentifier,
|
||||
scope: JSON.stringify($scope.ckScope)
|
||||
identifier: $scope.currKeyIdentifier,
|
||||
scope: JSON.stringify($scope.currKeyScope)
|
||||
}, function (res) {
|
||||
if (res.key) {
|
||||
$scope.hideNewKey();
|
||||
$scope.getKeys();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Hide/show new key modal dialog
|
||||
$scope.hideNewKey = function () {
|
||||
$scope.nModalShow = false;
|
||||
};
|
||||
$scope.showNewKey = function () {
|
||||
$scope.nModalShow = true;
|
||||
};
|
||||
|
||||
// Hide/show key info modal dialog
|
||||
$scope.hideKeyInfo = function () {
|
||||
$scope.kModalShow = false;
|
||||
};
|
||||
$scope.showKeyInfo = function (key) {
|
||||
$scope.kModalShow = true;
|
||||
$scope.currKey = key;
|
||||
$scope.currKey.scopeObj = splitScope($scope.currKey.scope);
|
||||
};
|
||||
}]);
|
64
app/public/panel/controllers/InviteCtrl.js
Normal file
64
app/public/panel/controllers/InviteCtrl.js
Normal file
@ -0,0 +1,64 @@
|
||||
var angular = require('angular');
|
||||
|
||||
angular.module('InviteCtrl', ['InviteSvc', 'AuthSvc']).controller('InviteController', ['$scope', 'InviteService', 'AuthService', function($scope, InviteService, AuthService) {
|
||||
// Transforms an array of period-separated properties ex. ["file.upload", "user.view", "user.ban"]
|
||||
// to json ex. { "file": "upload", "user": ["view", "ban"] }
|
||||
function splitScope(scope) {
|
||||
var res = {};
|
||||
for (var i in scope) {
|
||||
if (scope.hasOwnProperty(i)) {
|
||||
var perm = scope[i];
|
||||
var prefix = perm.substr(0, perm.indexOf('.'));
|
||||
var postfix = perm.substr(perm.indexOf('.') + 1);
|
||||
if (!res[prefix])
|
||||
res[prefix] = [];
|
||||
res[prefix].push({name: postfix});
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Called on init, retrieves the user's scope from the server.
|
||||
$scope.parseScope = function () {
|
||||
AuthService.currentUser(function (res) {
|
||||
$scope.scopeObj = splitScope(res.scope);
|
||||
$scope.currInvScope = [];
|
||||
})
|
||||
};
|
||||
|
||||
// Triggered when a checkbox for a permission changes.
|
||||
// Updates the currInvScope object with the addition or removal.
|
||||
$scope.updateCurrInvPerm = function(prefix, perm) {
|
||||
var index = $scope.scopeObj[prefix].indexOf(perm);
|
||||
if ($scope.scopeObj[prefix][index].isChecked) {
|
||||
$scope.currInvScope.push(prefix + '.' + perm.name);
|
||||
} else {
|
||||
index = $scope.currInvScope.indexOf(prefix + '.' + perm.name);
|
||||
$scope.currInvScope.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.getInvites = function() {
|
||||
InviteService.getAllInvites(function(invites) {
|
||||
$scope.invites = invites;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteInvite = function(invite) {
|
||||
InviteService.deleteInvite(function() {
|
||||
var index = $scope.invites.indexOf(invite);
|
||||
$scope.invites.splice(index, 1);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.createInvite = function() {
|
||||
InviteService.createInvite({
|
||||
scope: JSON.stringify($scope.currInvScope),
|
||||
exp: JSON.stringify($scope.currInvExpiry)
|
||||
}, function(res) {
|
||||
if (res.code) {
|
||||
$scope.getInvites();
|
||||
}
|
||||
});
|
||||
};
|
||||
}]);
|
@ -3,7 +3,7 @@ var angular = require('angular');
|
||||
angular.module('NavCtrl', ['AuthSvc']).controller('NavController', ['$scope', '$window', 'AuthService', function($scope, $window, AuthService) {
|
||||
$scope.user = {};
|
||||
AuthService.currentUser(function(user) {
|
||||
$scope.user = user;
|
||||
$scope.user = username;
|
||||
});
|
||||
|
||||
$scope.logout = AuthService.logout;
|
||||
@ -12,5 +12,4 @@ angular.module('NavCtrl', ['AuthSvc']).controller('NavController', ['$scope', '$
|
||||
if (!$scope.user.scope) return false;
|
||||
return $scope.user.scope.indexOf(permission) !== -1;
|
||||
};
|
||||
|
||||
}]);
|
9
app/public/panel/controllers/UserCtrl.js
Normal file
9
app/public/panel/controllers/UserCtrl.js
Normal file
@ -0,0 +1,9 @@
|
||||
var angular = require('angular');
|
||||
|
||||
angular.module('UserCtrl', ['UserSvc']).controller('UserController', ['$scope', 'UserService', function($scope, UserService) {
|
||||
$scope.getUsers = function() {
|
||||
UserService.getAllUsers(function(users) {
|
||||
$scope.users = users;
|
||||
});
|
||||
};
|
||||
}]);
|
@ -1,6 +1,6 @@
|
||||
var angular = require('angular');
|
||||
var uirouter = require('angular-ui-router');
|
||||
var app = angular.module('shimapan-panel', ['ui.router', 'AuthSvc', 'ApiSvc', 'ApiCtrl', 'NavCtrl', 'PanelRoutes']);
|
||||
var app = angular.module('shimapan-panel', ['ui.router', 'AuthSvc', 'ApiSvc', 'InviteSvc', 'UserSvc', 'ApiCtrl', 'InviteCtrl', 'UserCtrl', 'NavCtrl', 'PanelRoutes']);
|
||||
|
||||
app.run(['$rootScope', '$state', '$stateParams', function($rootScope, $state, $stateParams) {
|
||||
$rootScope.$state = $state;
|
||||
|
@ -1,6 +1,6 @@
|
||||
var angular = require('angular');
|
||||
|
||||
angular.module('ApiSvc', []).service('ApiService', ['$http', '$window', function ($http, $window) {
|
||||
angular.module('ApiSvc', []).service('ApiService', ['$http', function ($http) {
|
||||
this.getKey = function (identifier, cb) {
|
||||
$http({
|
||||
method: 'GET',
|
||||
@ -11,7 +11,7 @@ angular.module('ApiSvc', []).service('ApiService', ['$http', '$window', function
|
||||
});
|
||||
};
|
||||
|
||||
this.getAll = function (cb) {
|
||||
this.getAllKeys = function (cb) {
|
||||
$http({
|
||||
method: 'GET',
|
||||
url: '/api/keys/get'
|
||||
@ -28,7 +28,8 @@ angular.module('ApiSvc', []).service('ApiService', ['$http', '$window', function
|
||||
transformRequest: function (obj) {
|
||||
var str = [];
|
||||
for (var p in obj)
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
if (obj.hasOwnProperty(p))
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
return str.join("&");
|
||||
},
|
||||
data: {key: key.key}
|
||||
@ -45,7 +46,8 @@ angular.module('ApiSvc', []).service('ApiService', ['$http', '$window', function
|
||||
transformRequest: function (obj) {
|
||||
var str = [];
|
||||
for (var p in obj)
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
if (obj.hasOwnProperty(p))
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
return str.join("&");
|
||||
},
|
||||
data: key
|
||||
|
@ -9,13 +9,14 @@ angular.module('AuthSvc', []).service('AuthService', ['$http', '$window', functi
|
||||
transformRequest: function(obj) {
|
||||
var str = [];
|
||||
for (var p in obj)
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
if (obj.hasOwnProperty(p))
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
return str.join("&");
|
||||
},
|
||||
data: user
|
||||
}).then(function(res) {
|
||||
if (res.status === 401) return false;
|
||||
$window.location.href = '/home';
|
||||
if (res.status === 200)
|
||||
$window.location.href = '/home';
|
||||
})
|
||||
};
|
||||
|
||||
@ -36,13 +37,14 @@ angular.module('AuthSvc', []).service('AuthService', ['$http', '$window', functi
|
||||
transformRequest: function(obj) {
|
||||
var str = [];
|
||||
for (var p in obj)
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
if (obj.hasOwnProperty(p))
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
return str.join("&");
|
||||
},
|
||||
data: user
|
||||
}).then(function(res) {
|
||||
if (res.status === 401) return false;
|
||||
$window.location.href = '/home';
|
||||
if (res.status === 200)
|
||||
$window.location.href = '/home';
|
||||
});
|
||||
};
|
||||
|
||||
|
58
app/public/services/InviteSvc.js
Normal file
58
app/public/services/InviteSvc.js
Normal file
@ -0,0 +1,58 @@
|
||||
var angular = require('angular');
|
||||
|
||||
angular.module('InviteSvc', []).service('InviteService', ['$http', function ($http) {
|
||||
this.getInvite = function (code, cb) {
|
||||
$http({
|
||||
method: 'GET',
|
||||
url: '/api/invites/get',
|
||||
params: {code: code}
|
||||
}).then(function (res) {
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
|
||||
this.getAllInvites = function (cb) {
|
||||
$http({
|
||||
method: 'GET',
|
||||
url: '/api/invites/get'
|
||||
}).then(function (res) {
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
|
||||
this.deleteInvite = function (invite, cb) {
|
||||
$http({
|
||||
method: 'POST',
|
||||
url: '/api/invites/delete',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencode'},
|
||||
transformRequest: function (obj) {
|
||||
var str = [];
|
||||
for (var p in obj)
|
||||
if (obj.hasOwnProperty(p))
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
return str.join("&");
|
||||
},
|
||||
data: {code: invite.code}
|
||||
}).then(function (res) {
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
|
||||
this.createInvite = function (invite, cb) {
|
||||
$http({
|
||||
method: 'POST',
|
||||
url: '/api/invites/create',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencode'},
|
||||
transformRequest: function (obj) {
|
||||
var str = [];
|
||||
for (var p in obj)
|
||||
if (obj.hasOwnProperty(p))
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
return str.join("&");
|
||||
},
|
||||
data: invite
|
||||
}).then(function(res) {
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
}]);
|
22
app/public/services/UserSvc.js
Normal file
22
app/public/services/UserSvc.js
Normal file
@ -0,0 +1,22 @@
|
||||
var angular = require('angular');
|
||||
|
||||
angular.module('UserSvc', []).service('UserService', ['$http', function($http) {
|
||||
this.getUser = function(username, cb) {
|
||||
$http({
|
||||
method: 'GET',
|
||||
url: '/api/users/get',
|
||||
params: {username: username}
|
||||
}).then(function(res) {
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
|
||||
this.getAllUsers = function(cb) {
|
||||
$http({
|
||||
method: 'GET',
|
||||
url: '/api/users/get'
|
||||
}).then(function(res) {
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
}]);
|
@ -2,11 +2,16 @@ var angular = require('angular');
|
||||
|
||||
angular.module('LoginComp', ['AuthSvc']).component('loginComponent', {
|
||||
templateUrl: '/views/shimapan/login-form.html',
|
||||
controller: ['$scope', 'AuthService', function ($scope, AuthService) {
|
||||
controller: ['$scope', '$timeout', 'AuthService', function ($scope, $timeout, AuthService) {
|
||||
$scope.login = function () {
|
||||
AuthService.login({
|
||||
username: $scope.username,
|
||||
password: $scope.password
|
||||
}).catch(function() {
|
||||
$scope.error = true;
|
||||
$timeout(function() {
|
||||
$scope.error = false;
|
||||
}, 820);
|
||||
});
|
||||
};
|
||||
}]
|
||||
|
@ -2,12 +2,17 @@ var angular = require('angular');
|
||||
|
||||
angular.module('RegisterComp', ['AuthSvc']).component('registerComponent', {
|
||||
templateUrl: '/views/shimapan/register-form.html',
|
||||
controller: ['$scope', 'AuthService', function ($scope, AuthService) {
|
||||
controller: ['$scope', '$timeout', 'AuthService', function ($scope, $timeout, AuthService) {
|
||||
$scope.register = function () {
|
||||
AuthService.register({
|
||||
username: $scope.username,
|
||||
password: $scope.password,
|
||||
invite: $scope.invite
|
||||
}).catch(function() {
|
||||
$scope.error = true;
|
||||
$timeout(function() {
|
||||
$scope.error = false
|
||||
}, 820);
|
||||
});
|
||||
};
|
||||
}]
|
||||
|
@ -2,7 +2,7 @@ var angular = require('angular');
|
||||
|
||||
angular.module('UploadComp', ['ngFileUpload', 'AuthSvc']).component('uploadComponent', {
|
||||
templateUrl: '/views/shimapan/upload-form.html',
|
||||
controller: ['$scope', 'Upload', '$timeout', 'AuthService', function ($scope, Upload, $timeout, AuthService) {
|
||||
controller: ['$scope', 'Upload', '$timeout', function ($scope, Upload, $timeout) {
|
||||
$scope.errToString = function (err) {
|
||||
if (err === 'maxSize')
|
||||
return "File too large.";
|
||||
|
@ -1,6 +1,3 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
|
||||
@ -9,57 +6,124 @@ var Invite = require('../models/Invite.js');
|
||||
|
||||
var passport = require('passport');
|
||||
|
||||
function checkInvite(code, callback) {
|
||||
var async = require('async');
|
||||
|
||||
// Normalizes, decomposes, and lowercases a unicode string
|
||||
function canonicalize(username) {
|
||||
return username.normalize('NFKD').toLowerCase();
|
||||
}
|
||||
|
||||
// Checks if an invite code is valid
|
||||
// Returns the invite object if valid
|
||||
function checkInvite(code, cb) {
|
||||
Invite.findOne({code: code}, function (err, invite) {
|
||||
if (err) return callback(err);
|
||||
if (!invite || invite.used || invite.exp < new Date())
|
||||
callback(null, false);
|
||||
if (err)
|
||||
cb(err);
|
||||
else if (!invite)
|
||||
cb('Invalid invite code.');
|
||||
else if (invite.used)
|
||||
cb('Invite already used.');
|
||||
else if (invite.exp < Date.now())
|
||||
cb('Invite expired.');
|
||||
else
|
||||
callback(null, true, invite);
|
||||
cb(null, invite);
|
||||
});
|
||||
}
|
||||
|
||||
function useInvite(code, username) {
|
||||
Invite.updateOne({code: code}, {recipient: username, used: new Date()}, function (err) {
|
||||
if (err) throw err;
|
||||
// Validates the username, then registers the user in the database using the given invite.
|
||||
function registerUser(username, password, invite, sanitizeFn, cb) {
|
||||
async.series([
|
||||
function (cb) {
|
||||
// Canonicalize and sanitize the username, checking for HTML
|
||||
var canonicalName = canonicalize(username);
|
||||
var sanitizedName = sanitizeFn(canonicalName);
|
||||
|
||||
if (sanitizedName !== canonicalName)
|
||||
cb('Username failed sanitization check.');
|
||||
else if (canonicalName.length > 36)
|
||||
cb('Username too long.');
|
||||
else
|
||||
cb(null);
|
||||
},
|
||||
function (cb) {
|
||||
User.register(new User({
|
||||
username: username,
|
||||
canonicalname: canonicalize(username),
|
||||
scope: invite.scope,
|
||||
date: Date.now()
|
||||
}), password, cb);
|
||||
},
|
||||
function (cb) {
|
||||
invite.use(canonicalize(username), cb);
|
||||
}
|
||||
], function (err) {
|
||||
cb(err);
|
||||
});
|
||||
}
|
||||
|
||||
router.post('/register', function (req, res, next) {
|
||||
// Validate the invite code, then hand off to passport
|
||||
checkInvite(req.body.invite, function (err, valid, invite) {
|
||||
if (valid) {
|
||||
User.register(
|
||||
new User({username: req.body.username, scope: invite.scope, date: Date.now()}),
|
||||
req.body.password,
|
||||
function (err) {
|
||||
if (err) return res.status(403).json({'message': err.message});
|
||||
passport.authenticate('local')(req, res, function () {
|
||||
req.session.save(function(err) {
|
||||
if (err) return next(err);
|
||||
useInvite(req.body.invite, req.body.username);
|
||||
req.session.username = req.body.username;
|
||||
res.status(200).json({'message': 'Registered.'});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
// Authenticates and creates the required session variables
|
||||
function setupSession(username, req, res, cb) {
|
||||
// Body needs to contain canonical name for proper authentication
|
||||
req.body.canonicalname = canonicalize(req.body.username);
|
||||
|
||||
passport.authenticate('local')(req, res, function () {
|
||||
req.session.save(function (err) {
|
||||
if (!err) {
|
||||
req.session.passport.username = username;
|
||||
req.session.passport.canonicalname = canonicalize(username);
|
||||
}
|
||||
cb(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
router.post('/register', function (req, res) {
|
||||
async.waterfall([
|
||||
function (cb) {
|
||||
checkInvite(req.body.invite, cb);
|
||||
},
|
||||
function (invite, cb) {
|
||||
registerUser(req.body.username, req.body.password, invite, req.sanitize, cb);
|
||||
},
|
||||
function (cb) {
|
||||
setupSession(req.body.username, req, res, cb);
|
||||
}
|
||||
], function (err) {
|
||||
if (err) {
|
||||
res.status(401).json({'message': err});
|
||||
} else {
|
||||
res.status(401).json({'message': 'Invalid invite code.'});
|
||||
res.status(200).json({'message': 'Registration successful.'});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/login', function (req, res, next) {
|
||||
passport.authenticate('local', function(err, user, info) {
|
||||
if (err) return next(err);
|
||||
if (!user) return res.status(401).json({'message': info});
|
||||
req.logIn(user, function(err) {
|
||||
if (err) return next(err);
|
||||
req.session.username = user;
|
||||
res.status(200).json({'message': 'Logged in.'});
|
||||
});
|
||||
})(req, res, next);
|
||||
// Take 'username' from the form and canonicalize it for authentication.
|
||||
req.body.canonicalname = canonicalize(req.body.username);
|
||||
|
||||
async.waterfall([
|
||||
function (cb) {
|
||||
passport.authenticate('local', function(err, user, info) {
|
||||
cb(err, user, info);
|
||||
})(req, res, next);
|
||||
},
|
||||
function (user, info, cb) {
|
||||
if (!user)
|
||||
cb(info);
|
||||
else
|
||||
req.logIn(user, cb);
|
||||
},
|
||||
function (cb) {
|
||||
req.session.passport.username = req.body.username;
|
||||
req.session.passport.canonicalname = canonicalize(req.body.username);
|
||||
cb();
|
||||
}
|
||||
], function (err) {
|
||||
if (err)
|
||||
res.status(401).json({'message': err});
|
||||
else
|
||||
res.status(200).json({'message': 'Login successful.'});
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/logout', function (req, res) {
|
||||
@ -67,17 +131,19 @@ router.get('/logout', function (req, res) {
|
||||
res.status(200).json({'message': 'Logged out.'});
|
||||
});
|
||||
|
||||
router.get('/session', function(req, res) {
|
||||
if (req.session.passport.user) {
|
||||
User.findOne({username: req.session.passport.user}, function(err, user) {
|
||||
res.status(200).json({
|
||||
user: user.username,
|
||||
scope: user.scope
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.status(401).json({'message': 'Unauthorized.'});
|
||||
}
|
||||
router.get('/session', function (req, res) {
|
||||
console.log(req.session.passport);
|
||||
if (req.session.passport.canonicalname) {
|
||||
User.findOne({canonicalname: req.session.passport.canonicalname}, function (err, user) {
|
||||
res.status(200).json({
|
||||
username: user.username,
|
||||
canonicalname: user.canonicalname,
|
||||
scope: user.scope
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.status(401).json({'message': 'Unauthorized.'});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
78
app/routes/invites.js
Normal file
78
app/routes/invites.js
Normal file
@ -0,0 +1,78 @@
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
|
||||
var Invite = require('../models/Invite.js');
|
||||
|
||||
var requireScope = function (perm) {
|
||||
return function(req, res, next) {
|
||||
User.findOne({username: req.session.passport.user}, function(err, user) {
|
||||
if (err) throw err;
|
||||
if (user.scope.indexOf(perm) === -1)
|
||||
res.status(400).json({'message': 'No permission.'});
|
||||
else
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
router.post('/create', function (req, res) {
|
||||
if (!req.body.scope) {
|
||||
res.status(400).json({'message': 'Bad request.'});
|
||||
return;
|
||||
}
|
||||
|
||||
var scope;
|
||||
try {
|
||||
scope = JSON.parse(req.body.scope);
|
||||
} catch (e) {
|
||||
res.status(500).json({'message': e.name + ': ' + e.message});
|
||||
return;
|
||||
}
|
||||
|
||||
var expiry = req.body.exp;
|
||||
if (!expiry || expiry < Date.now())
|
||||
expiry = 0;
|
||||
|
||||
var entry = {
|
||||
code: crypto.randomBytes(12).toString('hex'),
|
||||
scope: scope,
|
||||
issuer: req.session.passport.user,
|
||||
issued: Date.now(),
|
||||
exp: expiry
|
||||
};
|
||||
|
||||
Invite.create(entry, function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
res.status(200).json({
|
||||
code: entry.code,
|
||||
scope: entry.scope
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
router.get('/get', function (req, res, next) {
|
||||
var query = {issuer: req.session.passport.user};
|
||||
|
||||
if (req.body.code)
|
||||
query.code = req.body.code;
|
||||
|
||||
Invite.find(query, function (err, invites) {
|
||||
if (err) {
|
||||
next(err);
|
||||
} else {
|
||||
res.status(200).json(invites);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
router.post('/delete', function (req, res, next) {
|
||||
Invite.deleteOne({code: req.body.code}, function (err) {
|
||||
if (err) next(err);
|
||||
else res.status(200).json({'message': 'Successfully deleted.'});
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
@ -2,9 +2,22 @@ var express = require('express');
|
||||
var router = express.Router();
|
||||
var crypto = require('crypto');
|
||||
|
||||
var User = require('../models/User.js');
|
||||
var Key = require('../models/Key.js');
|
||||
|
||||
router.post('/create', function (req, res) {
|
||||
var requireScope = function (perm) {
|
||||
return function(req, res, next) {
|
||||
User.findOne({username: req.session.passport.user}, function(err, user) {
|
||||
if (err) throw err;
|
||||
if (user.scope.indexOf(perm) === -1)
|
||||
res.status(400).json({'message': 'No permission.'});
|
||||
else
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
router.post('/create', requireScope('api.create'), function (req, res) {
|
||||
if (!req.body.identifier || !req.body.scope) {
|
||||
res.status(400).json({'message': 'Bad request.'});
|
||||
return;
|
||||
@ -20,7 +33,7 @@ router.post('/create', function (req, res) {
|
||||
try {
|
||||
scope = JSON.parse(req.body.scope);
|
||||
} catch (e) {
|
||||
res.status(400).json({'message': e.name + ': ' + e.message});
|
||||
res.status(500).json({'message': e.name + ': ' + e.message});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -64,7 +77,7 @@ router.get('/get', function (req, res, next) {
|
||||
})
|
||||
});
|
||||
|
||||
router.post('/delete', function(req, res, next) {
|
||||
router.post('/delete', requireScope('api.delete'), function(req, res, next) {
|
||||
Key.deleteOne({key: req.body.key}, function(err) {
|
||||
if (err) next(err);
|
||||
else res.status(200).json({'message': 'Successfully deleted.'});
|
||||
|
@ -2,7 +2,7 @@ var express = require('express');
|
||||
var router = express.Router();
|
||||
var path = require('path');
|
||||
|
||||
router.get('/', function(req, res, next) {
|
||||
router.get('/', function(req, res) {
|
||||
res.sendFile(path.join(__dirname, '../../public/views', 'login.html'));
|
||||
});
|
||||
|
||||
|
@ -2,7 +2,7 @@ var express = require('express');
|
||||
var router = express.Router();
|
||||
var path = require('path');
|
||||
|
||||
router.get('/', function(req, res, next) {
|
||||
router.get('/', function(req, res) {
|
||||
res.sendFile(path.join(__dirname, '../../public/views', 'panel.html'));
|
||||
});
|
||||
|
||||
|
@ -2,7 +2,7 @@ var express = require('express');
|
||||
var router = express.Router();
|
||||
var path = require('path');
|
||||
|
||||
router.get('/', function(req, res, next) {
|
||||
router.get('/', function(req, res) {
|
||||
res.sendFile(path.join(__dirname, '../../public/views', 'register.html'));
|
||||
});
|
||||
|
||||
|
@ -7,30 +7,57 @@ var register = require('./register.js');
|
||||
var login = require('./login.js');
|
||||
var panel = require('./panel.js');
|
||||
var keys = require('./keys.js');
|
||||
var invites = require('./invites.js');
|
||||
var users = require('./users.js');
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Key = require('../models/Key.js');
|
||||
|
||||
var requireLogin = function(req, res, next) {
|
||||
var checkApiKey = function (key, cb) {
|
||||
Key.find({key: key}, function (err, res) {
|
||||
if (err) throw err;
|
||||
cb(res.length === 1);
|
||||
});
|
||||
};
|
||||
|
||||
var requireLogin = function (req, res, next) {
|
||||
if (!req.session || !req.session.passport)
|
||||
return res.redirect('/login');
|
||||
else
|
||||
return next();
|
||||
};
|
||||
|
||||
module.exports = function(app) {
|
||||
var requireLoginApi = function(req, res, next) {
|
||||
if (!req.session || !req.session.passport) {
|
||||
if (!req.body.apikey) {
|
||||
return res.redirect('/login');
|
||||
} else {
|
||||
checkApiKey(res.body.apikey, function(valid) {
|
||||
if (!valid)
|
||||
return res.sendStatus(401);
|
||||
else
|
||||
return next();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function (app) {
|
||||
app.use('/', index);
|
||||
app.use('/home', requireLogin, home);
|
||||
app.use('/v', view);
|
||||
app.use('/api/upload', upload);
|
||||
app.use('/api/auth', auth);
|
||||
app.use('/api/keys', requireLogin, keys);
|
||||
app.use('/api/invites', requireLogin, invites);
|
||||
app.use('/api/users', requireLogin, users);
|
||||
app.use('/register', register);
|
||||
app.use('/login', login);
|
||||
app.use('/panel', requireLogin, panel);
|
||||
app.use('/panel*', requireLogin, panel);
|
||||
|
||||
app.use(function(err, req, res, next) {
|
||||
app.use(function (err, req, res) {
|
||||
if (err.name === 'UnauthorizedError') {
|
||||
res.status(401);
|
||||
res.json({"message": err.name + ": " + err.message});
|
||||
|
@ -4,6 +4,7 @@ var router = express.Router();
|
||||
var mongoose = require('mongoose');
|
||||
var User = require('../models/User.js');
|
||||
var Upload = require('../models/Upload.js');
|
||||
var Key = require('../models/Key.js');
|
||||
|
||||
var multer = require('multer');
|
||||
var dest = multer({dest: 'uploads/'});
|
||||
@ -14,12 +15,6 @@ function fileNameExists(name) {
|
||||
});
|
||||
}
|
||||
|
||||
function updateUserStats(user, size) {
|
||||
User.updateOne({username: user}, {$inc: {uploadCount: 1, uploadSize: size}}, function (err, res) {
|
||||
if (err) throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function genFileName() {
|
||||
var charset = "abcdefghijklmnopqrstuvwxyz";
|
||||
do {
|
||||
@ -30,32 +25,90 @@ function genFileName() {
|
||||
return chars.join('');
|
||||
}
|
||||
|
||||
router.post('/', dest.single('file'), function (req, res) {
|
||||
// Size must be below 128 Megabytes (1024*1024*128 Bytes)
|
||||
if (req.file.size >= 134217728) {
|
||||
res.status(413).json({'message': 'File too large.'});
|
||||
return;
|
||||
function updateStats(type, id, size) {
|
||||
if (type === 'session') {
|
||||
User.updateOne({username: id}, {$inc: {uploadCount: 1, uploadSize: size}}, function (err) {
|
||||
if (err) throw err;
|
||||
});
|
||||
} else if (type === 'apikey') {
|
||||
Key.updateOne({key: id}, {$inc: {uploadCount: 1, uploadSize: size}}, function (err) {
|
||||
if (err) throw err;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateUserStats(req.session.passport.user, req.file.size);
|
||||
var checkApiKey = function (key, cb) {
|
||||
Key.find({key: key}, function (err, res) {
|
||||
if (err) throw err;
|
||||
cb(res.length === 1, res);
|
||||
});
|
||||
};
|
||||
|
||||
var entry = {
|
||||
name: genFileName(),
|
||||
uploader: req.session.passport.user,
|
||||
created: Date.now(),
|
||||
file: req.file
|
||||
};
|
||||
var checkScope = function (type, id, perm, cb) {
|
||||
if (type === 'session') {
|
||||
User.findOne({username: id}, function (err, user) {
|
||||
if (err) throw err;
|
||||
cb(user.scope.indexOf(perm) !== -1);
|
||||
});
|
||||
} else {
|
||||
Key.findOne({key: id}, function (err, key) {
|
||||
if (err) throw err;
|
||||
cb(key.scope.indexOf(perm) !== -1);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Upload.create(entry, function (err, next) {
|
||||
if (err) {
|
||||
next(err);
|
||||
} else {
|
||||
res.send({
|
||||
function uploadFile(req, res, type, key) {
|
||||
if (!req.file)
|
||||
return res.status(400).json({'message': 'No file specified.'});
|
||||
|
||||
// Size must be below 128 Megabytes (1024*1024*128 Bytes)
|
||||
if (req.file.size >= 134217728)
|
||||
return res.status(413).json({'message': 'File too large.'});
|
||||
|
||||
var uploader = type === 'session' ? req.session.passport.user : key[0].username;
|
||||
var uploadKey = type === 'apikey' ? key[0].key : null;
|
||||
var id = type === 'session' ? req.session.passport.user : key[0].key;
|
||||
|
||||
checkScope(type, id, 'file.upload', function (valid) {
|
||||
if (!valid)
|
||||
return res.status(403).json({'message': 'No permission.'});
|
||||
|
||||
var entry = {
|
||||
name: genFileName(),
|
||||
uploader: uploader,
|
||||
uploadKey: uploadKey,
|
||||
date: Date.now(),
|
||||
file: req.file
|
||||
};
|
||||
|
||||
updateStats(type, id, req.file.size);
|
||||
|
||||
Upload.create(entry, function (err) {
|
||||
if (err) throw err;
|
||||
res.status(200).json({
|
||||
name: entry.name,
|
||||
url: 'https://shimapan.rocks/v/' + entry.name
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
router.post('/', dest.single('file'), function (req, res) {
|
||||
if (!req.session || !req.session.passport) {
|
||||
if (!req.body.apikey) {
|
||||
return res.sendStatus(401);
|
||||
} else {
|
||||
checkApiKey(req.body.apikey, function (valid, key) {
|
||||
if (!valid)
|
||||
return res.sendStatus(401);
|
||||
else
|
||||
uploadFile(req, res, 'apikey', key);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
uploadFile(req, res, 'session');
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
33
app/routes/users.js
Normal file
33
app/routes/users.js
Normal file
@ -0,0 +1,33 @@
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
|
||||
var User = require('../models/User.js');
|
||||
|
||||
var requireScope = function (perm) {
|
||||
return function(req, res, next) {
|
||||
User.findOne({username: req.session.passport.user}, function(err, user) {
|
||||
if (err) throw err;
|
||||
if (user.scope.indexOf(perm) === -1)
|
||||
res.status(400).json({'message': 'No permission.'});
|
||||
else
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
router.get('/get', requireScope('users.view'), function (req, res, next) {
|
||||
var query = {};
|
||||
|
||||
if (req.body.username)
|
||||
query.username = req.body.username;
|
||||
|
||||
User.find(query, function (err, users) {
|
||||
if (err) {
|
||||
next(err)
|
||||
} else {
|
||||
res.status(200).json(users);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
module.exports = router;
|
@ -105,7 +105,9 @@ gulp.task('concatjs', function () {
|
||||
var tasks = files.map(function (entry) {
|
||||
return gulp.src(entry.src)
|
||||
.pipe(concat(entry.name))
|
||||
.pipe(uglify())
|
||||
.pipe(uglify().on('error', function(err) {
|
||||
console.log(err.toString());
|
||||
}))
|
||||
.pipe(gulp.dest('public/js'));
|
||||
});
|
||||
|
||||
|
BIN
public/img/edge.webm
Normal file
BIN
public/img/edge.webm
Normal file
Binary file not shown.
@ -15,9 +15,7 @@
|
||||
</video>
|
||||
<script>
|
||||
var videos = [
|
||||
"/img/edge.mp4",
|
||||
"/img/endthis.mp4",
|
||||
"/img/hell.mp4"
|
||||
"/img/edge.webm"
|
||||
];
|
||||
var video = document.createElement("source");
|
||||
video.setAttribute("src", videos[Math.floor(Math.random() * videos.length)]);
|
||||
|
@ -12,13 +12,13 @@
|
||||
<div class="sidebar" ng-controller="NavController">
|
||||
<div class="sidebar-title" ng-click="$state.go('home')"><span>Shimapan</span></div>
|
||||
<ul class="nav">
|
||||
<li><a ui-sref="dashboard" ng-class="{active: $state.$current.name=='dashboard'}">Dashboard</a></li>
|
||||
<li><a ui-sref="search" ng-class="{active: $state.$current.name=='search'}">Search</a></li>
|
||||
<li><a ui-sref="api" ng-class="{active: $state.$current.name=='api'}">API</a></li>
|
||||
<li><a ui-sref="invites" ng-class="{active: $state.$current.name=='invites'}">Invites</a></li>
|
||||
<li ng-hide="!hasPermission('users.view')"><a ui-sref="users" ng-class="{active: $state.$current.name=='users'}">Users</a></li>
|
||||
<li><a ui-sref="stats" ng-class="{active: $state.$current.name=='stats'}">Statistics</a></li>
|
||||
<li><a ng-click="logout()">Logout</a></li>
|
||||
<li><a draggable="false" ui-sref="dashboard" ng-class="{active: $state.$current.name=='dashboard'}">Dashboard</a></li>
|
||||
<li><a draggable="false" ui-sref="search" ng-class="{active: $state.$current.name=='search'}">Search</a></li>
|
||||
<li><a draggable="false" ui-sref="api" ng-class="{active: $state.$current.name=='api'}">API</a></li>
|
||||
<li><a draggable="false" ui-sref="invites" ng-class="{active: $state.$current.name=='invites'}">Invites</a></li>
|
||||
<li ng-hide="!hasPermission('users.view')"><a draggable="false" ui-sref="users" ng-class="{active: $state.$current.name=='users'}">Users</a></li>
|
||||
<li><a draggable="false" ui-sref="stats" ng-class="{active: $state.$current.name=='stats'}">Statistics</a></li>
|
||||
<li><a draggable="false" ng-click="logout()">Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="content" ng-class="{isOpen: open}">
|
||||
|
@ -23,7 +23,7 @@
|
||||
<p>This key can be used with any 3rd party program or service to upload to and manage your account
|
||||
with Shimapan.</p>
|
||||
<p>For example, it can be used in a bash script to upload from the command line:</p>
|
||||
<pre>APIKEY=[Your API Key Here]<br/>URL=$(curl -s -F "apikey=$APIKEY" -F "file=@$1" https://shimapan.rocks/api/upload | grep url | awk '{print $2}')<br/>echo $URL | tr -d '[\\\,"\n]'</pre>
|
||||
<pre>APIKEY=[Your API Key Here]<br/>URL=$(curl -s -F "apikey=$APIKEY" -F "file=@$1" https://shimapan.rocks/api/upload | grep -Po '"'"url"'"\s*:\s*"\K([^"]*)'<br/>echo $URL</pre>
|
||||
<br/>
|
||||
<p>Key Permissions:</p>
|
||||
<table>
|
||||
@ -54,14 +54,14 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Identifier to describe the purpose/use of this key:</p>
|
||||
<input id="identifier" placeholder="Identifier" class="form-control" type="text" ng-model="ckIdentifier"/>
|
||||
<input id="identifier" placeholder="Identifier" class="form-control" type="text" ng-model="currKeyIdentifier"/>
|
||||
<br/>
|
||||
<p>Permissions the key should have:</p>
|
||||
<table>
|
||||
<tr ng-repeat="(prefix, perms) in scopeObj">
|
||||
<th>{{prefix}}:</th>
|
||||
<td ng-repeat="perm in perms">
|
||||
<input type="checkbox" name="{{perm.name}}" ng-model="perm.isChecked" ng-change="checkCkPerm(prefix, perm)"/>
|
||||
<input type="checkbox" title="{{perm.name}}" name="{{perm.name}}" ng-model="perm.isChecked" ng-change="updateCurrKeyPerm(prefix, perm)"/>
|
||||
<label for="{{perm.name}}" ng-bind="perm.name"></label>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -0,0 +1,14 @@
|
||||
<div class="inner" ng-controller="InviteController" ng-init="getInvites()">
|
||||
<table class="invites">
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Scope</th>
|
||||
<th>Expiry</th>
|
||||
</tr>
|
||||
<tr ng-repeat="invite in invites">
|
||||
<td>{{invite.code}}</td>
|
||||
<td>{{invite.scope}}</td>
|
||||
<td>{{invite.expiry}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
@ -0,0 +1,18 @@
|
||||
<div class="inner" ng-controller="UserController" ng-init="getUsers()">
|
||||
<table class="users">
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>Scope</th>
|
||||
<th>Upload Count</th>
|
||||
<th>Upload Size</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
<tr ng-repeat="user in users">
|
||||
<td>{{user.username}}</td>
|
||||
<td>{{user.scope}}</td>
|
||||
<td>{{user.uploadCount}}</td>
|
||||
<td>{{user.uploadSize}}</td>
|
||||
<td>{{user.date}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
@ -4,7 +4,7 @@
|
||||
<form ng-submit="login()">
|
||||
<input id="username" placeholder="Username" class="form-control" type="text" ng-model="username"/>
|
||||
<input id="password" placeholder="Password" class="form-control" type="password" ng-model="password"/>
|
||||
<button type="submit" class="btn">Submit</button>
|
||||
<button type="submit" class="btn" ng-class="{shake: error}">Submit</button>
|
||||
</form>
|
||||
</fieldset>
|
||||
</div>
|
@ -5,7 +5,7 @@
|
||||
<input id="username" placeholder="Username" class="form-control" type="text" ng-model="username"/>
|
||||
<input id="password" placeholder="Password" class="form-control" type="password" ng-model="password"/>
|
||||
<input id="invite" placeholder="Invite Code" class="form-control" type="text" ng-model="invite"/>
|
||||
<button type="submit" class="btn">Submit</button>
|
||||
<button type="submit" class="btn" ng-class="{shake: error}">Submit</button>
|
||||
</form>
|
||||
</fieldset>
|
||||
</div>
|
1
server.js
Normal file → Executable file
1
server.js
Normal file → Executable file
@ -50,7 +50,6 @@ app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(bodyParser.text());
|
||||
app.use(sanitizer());
|
||||
app.use(methodOverride('X-HTTP-Method-Override'));
|
||||
app.use(passport.initialize());
|
||||
|
||||
|
||||
//app.use(favicon(__dirname + '/public/img/favicon.ico'));
|
||||
|
11
test/permissions.txt
Normal file
11
test/permissions.txt
Normal file
@ -0,0 +1,11 @@
|
||||
users
|
||||
view
|
||||
edit
|
||||
ban
|
||||
|
||||
file
|
||||
upload
|
||||
|
||||
api
|
||||
create
|
||||
delete
|
Loading…
Reference in New Issue
Block a user