mirror of
https://github.com/Foltik/Shimapan
synced 2025-01-06 00:08:25 -05:00
commit
1f56424d74
@ -200,35 +200,173 @@ body {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.modal {
|
||||
.key-name {
|
||||
color: #2a9fd6;
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
line-height: 1.7em;
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
border: 1px solid #666;
|
||||
border-radius: 4px;
|
||||
display: block;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
margin: 10px 0;
|
||||
background: #222;
|
||||
color: #2a9fd6;
|
||||
}
|
||||
|
||||
.modal,
|
||||
.modal-box {
|
||||
z-index: 900;
|
||||
}
|
||||
|
||||
.modal-sandbox {
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: rgb(0,0,0);
|
||||
background: rgba(0,0,0,.8);
|
||||
overflow: auto;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.modal-box {
|
||||
position: relative;
|
||||
width: 80%;
|
||||
max-width: 700px;
|
||||
margin: 60px auto;
|
||||
animation-name: modalbox;
|
||||
animation-duration: .3s;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
#createKey {
|
||||
max-width: 920px;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 80%;
|
||||
border: 2px solid #2a9fd6;
|
||||
border-radius: 8px 8px 0 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 20px 40px;
|
||||
background: #000;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
margin: auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 80%;
|
||||
border: 2px solid #2a9fd6;
|
||||
border-top: none;
|
||||
background: #000;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
margin: auto;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
border: 2px solid #2a9fd6;
|
||||
border-radius: 0 0 8px 8px;
|
||||
border-top: none;
|
||||
background: #000;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.close-modal {
|
||||
text-align: right;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@keyframes modalbox {
|
||||
0% {
|
||||
top: -250px;
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
margin-left: 20px;
|
||||
color: #d3d3d3;
|
||||
background: #000;
|
||||
border: 2px solid #2a9fd6;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.25s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
color: #fff;
|
||||
background-color: #2a9fd6;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.btn-del {
|
||||
text-transform: uppercase;
|
||||
border: 2px solid #ff6666;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.btn-del:hover {
|
||||
background-color: #ff6666;
|
||||
}
|
||||
|
||||
em {
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#identifier {
|
||||
font-size: 14px;
|
||||
background: #222;
|
||||
color: #d3d3d3;
|
||||
border: 1px solid #666;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
th {
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
td input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
td label {
|
||||
margin-bottom: 2px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,78 @@
|
||||
var angular = require('angular');
|
||||
|
||||
angular.module('ApiCtrl', ['ApiSvc', 'AuthSvc']).controller('ApiController', ['$scope', 'ApiService', 'AuthService', function($scope, ApiService, AuthService) {
|
||||
$scope.getKeys = function() {
|
||||
ApiService.getAll(function(keys) {
|
||||
angular.module('ApiCtrl', ['ApiSvc', 'AuthSvc']).controller('ApiController', ['$scope', 'ApiService', 'AuthService', function ($scope, ApiService, AuthService) {
|
||||
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});
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.parseScope = function () {
|
||||
AuthService.currentUser(function (res) {
|
||||
$scope.scopeObj = splitScope(res.scope);
|
||||
$scope.ckScope = [];
|
||||
})
|
||||
};
|
||||
|
||||
$scope.getKeys = function () {
|
||||
ApiService.getAll(function (keys) {
|
||||
$scope.keys = keys;
|
||||
});
|
||||
console.log($scope.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);
|
||||
$scope.keys.splice(index, 1);
|
||||
$scope.hideKeyInfo();
|
||||
$scope.currKey = {};
|
||||
});
|
||||
};
|
||||
|
||||
$scope.createKey = function () {
|
||||
if ($scope.ckScope.length === 0 || !$scope.ckIdentifier)
|
||||
return;
|
||||
|
||||
ApiService.createKey({
|
||||
identifier: $scope.ckIdentifier,
|
||||
scope: JSON.stringify($scope.ckScope)
|
||||
}, function (res) {
|
||||
if (res.key) {
|
||||
$scope.hideNewKey();
|
||||
$scope.getKeys();
|
||||
}
|
||||
});
|
||||
}
|
||||
}]);
|
@ -19,4 +19,38 @@ angular.module('ApiSvc', []).service('ApiService', ['$http', '$window', function
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
|
||||
this.deleteKey = function (key, cb) {
|
||||
$http({
|
||||
method: 'POST',
|
||||
url: '/api/keys/delete',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
transformRequest: function (obj) {
|
||||
var str = [];
|
||||
for (var p in obj)
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
return str.join("&");
|
||||
},
|
||||
data: {key: key.key}
|
||||
}).then(function (res) {
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
|
||||
this.createKey = function (key, cb) {
|
||||
$http({
|
||||
method: 'POST',
|
||||
url: '/api/keys/create',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
transformRequest: function (obj) {
|
||||
var str = [];
|
||||
for (var p in obj)
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
return str.join("&");
|
||||
},
|
||||
data: key
|
||||
}).then(function(res) {
|
||||
cb(res.data);
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
@ -38,6 +38,7 @@ router.post('/register', function (req, res, next) {
|
||||
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.'});
|
||||
});
|
||||
});
|
||||
@ -55,6 +56,7 @@ router.post('/login', function (req, res, next) {
|
||||
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);
|
||||
|
@ -64,4 +64,11 @@ router.get('/get', function (req, res, next) {
|
||||
})
|
||||
});
|
||||
|
||||
router.post('/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.'});
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
@ -12,10 +12,10 @@ var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var requireLogin = function(req, res, next) {
|
||||
if (!req.session.passport.user)
|
||||
res.redirect('/login');
|
||||
if (!req.session || !req.session.passport)
|
||||
return res.redirect('/login');
|
||||
else
|
||||
next();
|
||||
return next();
|
||||
};
|
||||
|
||||
module.exports = function(app) {
|
||||
|
9
package-lock.json
generated
9
package-lock.json
generated
@ -942,15 +942,6 @@
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
||||
},
|
||||
"cookie-parser": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz",
|
||||
"integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=",
|
||||
"requires": {
|
||||
"cookie": "0.3.1",
|
||||
"cookie-signature": "1.0.6"
|
||||
}
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
|
@ -9,7 +9,6 @@
|
||||
"body-parser": "^1.18.2",
|
||||
"config": "^1.26.2",
|
||||
"connect-mongo": "^2.0.0",
|
||||
"cookie-parser": "^1.4.3",
|
||||
"event-stream": "^3.3.4",
|
||||
"express": "^4.16.2",
|
||||
"express-sanitizer": "^1.0.2",
|
||||
|
@ -1,30 +1,76 @@
|
||||
<div class="inner" ng-controller="ApiController" ng-init="currKey={};showModal=false;getKeys()">
|
||||
<div class="inner" ng-controller="ApiController" ng-init="getKeys();parseScope()">
|
||||
<div class="keys">
|
||||
<div class="key" ng-repeat="key in keys">
|
||||
<div class="key" ng-repeat="key in keys" ng-click="$parent.showKeyInfo(key)">
|
||||
<i class="fa fa-key"></i>
|
||||
<span>{{key.identifier}}</span>
|
||||
</div>
|
||||
<div class="key add-key" ng-hide="keys.length >= 10">
|
||||
<div class="key add-key" ng-hide="keys.length >= 10" ng-click="showNewKey()">
|
||||
<i class="fa fa-plus"></i>
|
||||
<span>Create</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" ng-show="showModal==true">
|
||||
<div class="modal-header">
|
||||
<button class="close" type="button"></button>
|
||||
<h4 class="modal-title">API Key</h4>
|
||||
<div class="modal" style="{{kModalShow?'display:block':'display:none'}}">
|
||||
<div class="modal-sandbox" ng-click="hideKeyInfo()"></div>
|
||||
<div class="modal-box">
|
||||
<div class="modal-header">
|
||||
<h1>Key Info: <span class="key-name">{{currKey.identifier}}</span></h1>
|
||||
<div class="close-modal" ng-click="hideKeyInfo()"><i class="fa fa-times"></i></div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>API Key:</p>
|
||||
<pre>{{currKey.key}}</pre>
|
||||
<br/>
|
||||
<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>
|
||||
<br/>
|
||||
<p>Key Permissions:</p>
|
||||
<table>
|
||||
<tr ng-repeat="(prefix, perms) in currKey.scopeObj">
|
||||
<th>{{prefix}}:</th>
|
||||
<td ng-repeat="perm in perms">
|
||||
<span ng-bind="perm.name"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<p>If your key is compromised, it can be used to upload and modify your account without your knowledge.
|
||||
If it is lost or compromised, you can delete the key below, but be warned that this <em>cannot</em>
|
||||
be undone.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-del" ng-click="deleteKey(currKey)">Delete Key</button>
|
||||
<button class="btn-close" ng-click="hideKeyInfo()">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body modal-key">
|
||||
<p>API Key:</p>
|
||||
<pre class="code">{{currKey.code}}</pre>
|
||||
<p>Use this key with your preferred method of utilizing the Shimapan API.</p>
|
||||
<p>Example with cURL:</p>
|
||||
<pre class="code"></pre>
|
||||
<div id="qr"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-delete" type="button"></button>
|
||||
<button class="btn-back" type="button"></button>
|
||||
</div>
|
||||
<div class="modal" style="{{nModalShow?'display:block':'display:none'}}">
|
||||
<div class="modal-sandbox" ng-click="hideNewKey()"></div>
|
||||
<div class="modal-box" id="createKey">
|
||||
<div class="modal-header">
|
||||
<h1>Create a Key</h1>
|
||||
<div class="close-modal" ng-click="hideNewKey()"><i class="fa fa-times"></i></div>
|
||||
</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"/>
|
||||
<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)"/>
|
||||
<label for="{{perm.name}}" ng-bind="perm.name"></label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button ng-click="createKey()">Create</button>
|
||||
<button ng-click="hideNewKey()">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -4,7 +4,6 @@ var methodOverride = require('method-override');
|
||||
var mongoose = require('mongoose');
|
||||
var morgan = require('morgan');
|
||||
var passport = require('passport');
|
||||
var cookieParser = require('cookie-parser');
|
||||
var session = require('express-session');
|
||||
var sanitizer = require('express-sanitizer');
|
||||
var helmet = require('helmet');
|
||||
@ -45,7 +44,6 @@ app.use(session({
|
||||
}));
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
app.use(cookieParser());
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.json({ type: 'application/*+json' }))
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
Loading…
Reference in New Issue
Block a user