mirror of
https://github.com/Foltik/Shimapan
synced 2025-01-07 08:42:49 -05:00
commit
1f56424d74
@ -200,35 +200,173 @@ body {
|
|||||||
user-select: none;
|
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;
|
display: block;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 10px 0;
|
||||||
|
background: #222;
|
||||||
|
color: #2a9fd6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal,
|
||||||
|
.modal-box {
|
||||||
|
z-index: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-sandbox {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 1;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 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;
|
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 {
|
.modal-header {
|
||||||
margin: 15% auto;
|
border: 2px solid #2a9fd6;
|
||||||
padding: 20px;
|
border-radius: 8px 8px 0 0;
|
||||||
border: 1px solid #888;
|
display: flex;
|
||||||
width: 80%;
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20px 40px;
|
||||||
|
background: #000;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-body {
|
.modal-body {
|
||||||
margin: auto;
|
border: 2px solid #2a9fd6;
|
||||||
padding: 20px;
|
border-top: none;
|
||||||
border: 1px solid #888;
|
background: #000;
|
||||||
width: 80%;
|
padding: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-footer {
|
.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;
|
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');
|
var angular = require('angular');
|
||||||
|
|
||||||
angular.module('ApiCtrl', ['ApiSvc', 'AuthSvc']).controller('ApiController', ['$scope', 'ApiService', 'AuthService', function($scope, ApiService, AuthService) {
|
angular.module('ApiCtrl', ['ApiSvc', 'AuthSvc']).controller('ApiController', ['$scope', 'ApiService', 'AuthService', function ($scope, ApiService, AuthService) {
|
||||||
$scope.getKeys = function() {
|
function splitScope(scope) {
|
||||||
ApiService.getAll(function(keys) {
|
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;
|
$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);
|
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) {
|
req.session.save(function(err) {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
useInvite(req.body.invite, req.body.username);
|
useInvite(req.body.invite, req.body.username);
|
||||||
|
req.session.username = req.body.username;
|
||||||
res.status(200).json({'message': 'Registered.'});
|
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});
|
if (!user) return res.status(401).json({'message': info});
|
||||||
req.logIn(user, function(err) {
|
req.logIn(user, function(err) {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
req.session.username = user;
|
||||||
res.status(200).json({'message': 'Logged in.'});
|
res.status(200).json({'message': 'Logged in.'});
|
||||||
});
|
});
|
||||||
})(req, res, next);
|
})(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;
|
module.exports = router;
|
||||||
|
@ -12,10 +12,10 @@ var fs = require('fs');
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
var requireLogin = function(req, res, next) {
|
var requireLogin = function(req, res, next) {
|
||||||
if (!req.session.passport.user)
|
if (!req.session || !req.session.passport)
|
||||||
res.redirect('/login');
|
return res.redirect('/login');
|
||||||
else
|
else
|
||||||
next();
|
return next();
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = function(app) {
|
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",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
"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": {
|
"cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
"config": "^1.26.2",
|
"config": "^1.26.2",
|
||||||
"connect-mongo": "^2.0.0",
|
"connect-mongo": "^2.0.0",
|
||||||
"cookie-parser": "^1.4.3",
|
|
||||||
"event-stream": "^3.3.4",
|
"event-stream": "^3.3.4",
|
||||||
"express": "^4.16.2",
|
"express": "^4.16.2",
|
||||||
"express-sanitizer": "^1.0.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="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>
|
<i class="fa fa-key"></i>
|
||||||
<span>{{key.identifier}}</span>
|
<span>{{key.identifier}}</span>
|
||||||
</div>
|
</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>
|
<i class="fa fa-plus"></i>
|
||||||
<span>Create</span>
|
<span>Create</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal" ng-show="showModal==true">
|
<div class="modal" style="{{kModalShow?'display:block':'display:none'}}">
|
||||||
<div class="modal-header">
|
<div class="modal-sandbox" ng-click="hideKeyInfo()"></div>
|
||||||
<button class="close" type="button"></button>
|
<div class="modal-box">
|
||||||
<h4 class="modal-title">API Key</h4>
|
<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>
|
||||||
<div class="modal-body modal-key">
|
</div>
|
||||||
<p>API Key:</p>
|
<div class="modal" style="{{nModalShow?'display:block':'display:none'}}">
|
||||||
<pre class="code">{{currKey.code}}</pre>
|
<div class="modal-sandbox" ng-click="hideNewKey()"></div>
|
||||||
<p>Use this key with your preferred method of utilizing the Shimapan API.</p>
|
<div class="modal-box" id="createKey">
|
||||||
<p>Example with cURL:</p>
|
<div class="modal-header">
|
||||||
<pre class="code"></pre>
|
<h1>Create a Key</h1>
|
||||||
<div id="qr"></div>
|
<div class="close-modal" ng-click="hideNewKey()"><i class="fa fa-times"></i></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-body">
|
||||||
<button class="btn-delete" type="button"></button>
|
<p>Identifier to describe the purpose/use of this key:</p>
|
||||||
<button class="btn-back" type="button"></button>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
@ -4,7 +4,6 @@ var methodOverride = require('method-override');
|
|||||||
var mongoose = require('mongoose');
|
var mongoose = require('mongoose');
|
||||||
var morgan = require('morgan');
|
var morgan = require('morgan');
|
||||||
var passport = require('passport');
|
var passport = require('passport');
|
||||||
var cookieParser = require('cookie-parser');
|
|
||||||
var session = require('express-session');
|
var session = require('express-session');
|
||||||
var sanitizer = require('express-sanitizer');
|
var sanitizer = require('express-sanitizer');
|
||||||
var helmet = require('helmet');
|
var helmet = require('helmet');
|
||||||
@ -45,7 +44,6 @@ app.use(session({
|
|||||||
}));
|
}));
|
||||||
app.use(passport.initialize());
|
app.use(passport.initialize());
|
||||||
app.use(passport.session());
|
app.use(passport.session());
|
||||||
app.use(cookieParser());
|
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.json({ type: 'application/*+json' }))
|
app.use(bodyParser.json({ type: 'application/*+json' }))
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
Loading…
Reference in New Issue
Block a user