Upgrade API Key Management : Permission to allow managing API

api-key-management-upgrades
Moe 2025-02-09 22:35:53 -08:00
parent 95d66f99e0
commit bae9254079
9 changed files with 144 additions and 139 deletions

View File

@ -77,6 +77,10 @@ module.exports = (s,config,lang) => {
name: lang['Can Authenticate Websocket'],
value: 'auth_socket',
},
{
name: lang['Can Create API Keys'],
value: 'create_api_keys',
},
{
name: lang['Can Get Monitors'],
value: 'get_monitors',

View File

@ -340,6 +340,7 @@
"Group Key": "Group Key",
"Allowed IPs": "Allowed IPs",
"Separate with commas, no spaces": "Separate with commas, no spaces",
"Can Create API Keys": "Can Create API Keys",
"Can Get Monitors": "Can Get Monitors",
"Can Get Logs": "Can Get Logs",
"Can Authenticate Websocket": "Can Authenticate Websocket",

View File

@ -88,6 +88,7 @@ module.exports = (s,config) => {
ip : '0.0.0.0',
details : s.stringJSON({
"auth_socket": "1",
"create_api_keys": "1",
"get_monitors": "1",
"edit_monitors": "1",
"control_monitors": "1",

View File

@ -856,6 +856,7 @@ module.exports = function(s,config,lang){
const details = user.details;
[
'auth_socket',
'create_api_keys',
'get_monitors',
'edit_monitors',
'control_monitors',

View File

@ -17,10 +17,9 @@ module.exports = function(s,config,lang){
}
return details
}
async function getApiKeys({ ke, code, uid }){
async function getApiKeys({ ke, uid }){
const whereQuery = {
ke,
code
};
if(uid)whereQuery.uid = uid;
const { rows } = await s.knexQueryPromise({
@ -29,7 +28,10 @@ module.exports = function(s,config,lang){
table: "API",
where: whereQuery
});
return rows[0]
for(row of rows){
row.details = JSON.parse(row.details);
}
return rows
}
async function getApiKey({ ke, code, uid }){
const whereQuery = {

128
libs/webPaths/apiKeys.js Normal file
View File

@ -0,0 +1,128 @@
module.exports = function(s,config,lang,app){
const { getApiKeys, createApiKey, editApiKey, deleteApiKey } = require('../user/apiKeys.js')(s,config,lang)
/**
* API : Add/Edit API Key, binded to the user who created it
*/
app.post([
config.webPaths.adminApiPrefix+':auth/api/:ke/add',
config.webPaths.apiPrefix+':auth/api/:ke/add',
],function (req,res){
var endData = {ok:false}
s.auth(req.params,async function(user){
const {
isSubAccount,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
const endData = {
ok : false
}
if(isRestrictedApiKey && apiKeyPermissions.create_api_keys_disallowed){
endData.msg = lang['Not Authorized']
}else{
const groupKey = req.params.ke;
var form = s.getPostData(req) || {}
try{
const targetUID = form.uid || req.body.uid;
const code = form.code;
const editResponse = await editApiKey({
code,
ke : groupKey,
uid : !isSubAccount && targetUID ? targetUID : user.uid,
ip : typeof form.ip === 'string' ? form.ip.trim() : '',
details : form.details ? s.stringJSON(form.details) : undefined
});
if(editResponse.ok){
s.tx({
f: 'api_key_added',
uid: user.uid,
form: editResponse.api
},'GRP_' + groupKey)
}
endData.ok = editResponse.ok
endData.api = editResponse.api
}catch(err){
console.error(err)
}
}
s.closeJsonResponse(res,endData)
},res,req)
})
/**
* API : Delete API Key
*/
app.post([
config.webPaths.adminApiPrefix+':auth/api/:ke/delete',
config.webPaths.apiPrefix+':auth/api/:ke/delete',
],function (req,res){
var endData = {ok:false}
s.auth(req.params, async function(user){
const {
isSubAccount,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
const endData = {
ok : false
}
if(isRestrictedApiKey && apiKeyPermissions.create_api_keys_disallowed){
endData.msg = lang['Not Authorized']
}else{
var form = s.getPostData(req) || {}
const code = form.code || s.getPostData(req,'code',false)
if(!code){
endData.msg = lang.postDataBroken
}else{
const groupKey = req.params.ke;
const targetUID = req.query.uid;
endData.uid = !isSubAccount && targetUID ? targetUID : user.uid;
const { ok } = await deleteApiKey({ ke: groupKey, code, uid: endData.uid })
if(ok){
s.tx({
f: 'api_key_deleted',
uid: user.uid,
form: {
code: code
}
},'GRP_' + groupKey)
endData.ok = ok
delete(s.api[code])
}
}
}
s.closeJsonResponse(res,endData)
},res,req)
})
/**
* API : List API Keys for Authenticated user
*/
app.get([
config.webPaths.adminApiPrefix+':auth/api/:ke/list',
config.webPaths.apiPrefix+':auth/api/:ke/list',
],function (req,res){
var endData = {ok:false}
s.auth(req.params, async function(user){
const {
isSubAccount,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
const endData = {
ok : false,
keys: []
}
if(isRestrictedApiKey && apiKeyPermissions.create_api_keys_disallowed){
endData.msg = lang['Not Authorized']
}else{
const groupKey = req.params.ke;
const targetUID = req.query.uid;
endData.uid = !isSubAccount && targetUID ? targetUID : user.uid;
const rows = await getApiKeys({ ke: groupKey, uid: endData.uid })
endData.ok = true
endData.keys = rows
endData.ke = user.ke
}
s.closeJsonResponse(res,endData)
},res,req)
})
}

View File

@ -10,7 +10,8 @@ module.exports = function(s,config,lang,app){
} = require('./monitor/utils.js')(s,config,lang);
require('./webPaths/permissionSets.js')(s,config,lang,app)
require('./webPaths/customSettings.js')(s,config,lang,app)
const { createApiKey, editApiKey } = require('./user/apiKeys.js')(s,config,lang)
require('./webPaths/apiKeys.js')(s,config,lang,app)
const { createApiKey } = require('./user/apiKeys.js')(s,config,lang)
/**
* API : Administrator : Edit Sub-Account (Account to share cameras with)
*/
@ -363,140 +364,6 @@ module.exports = function(s,config,lang,app){
},res,req)
})
/**
* API : Add API Key, binded to the user who created it
*/
app.post([
config.webPaths.adminApiPrefix+':auth/api/:ke/add',
config.webPaths.apiPrefix+':auth/api/:ke/add',
],function (req,res){
var endData = {ok:false}
res.setHeader('Content-Type', 'application/json');
s.auth(req.params,async function(user){
const {
isSubAccount,
} = s.checkPermission(user)
var endData = {
ok : false
}
var form = s.getPostData(req) || {}
try{
const targetUID = form.uid || req.body.uid;
const code = form.code;
const editResponse = await editApiKey({
code,
ke : req.params.ke,
uid : !isSubAccount && targetUID ? targetUID : user.uid,
ip : typeof form.ip === 'string' ? form.ip.trim() : '',
details : form.details ? s.stringJSON(form.details) : undefined
});
s.tx({
f: 'api_key_added',
uid: user.uid,
form: editResponse.api
},'GRP_' + req.params.ke)
endData.ok = editResponse.ok
endData.api = editResponse.api
}catch(err){
console.error(err)
}
s.closeJsonResponse(res,endData)
},res,req)
})
/**
* API : Delete API Key
*/
app.all([
config.webPaths.adminApiPrefix+':auth/api/:ke/delete',
config.webPaths.apiPrefix+':auth/api/:ke/delete',
],function (req,res){
var endData = {ok:false}
res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){
var endData = {
ok : false
}
var form = s.getPostData(req) || {}
const code = form.code || s.getPostData(req,'code',false)
if(!code){
s.tx({
f:'form_incomplete',
uid: user.uid,
form:'APIs'
},'GRP_' + req.params.ke)
endData.msg = lang.postDataBroken
s.closeJsonResponse(res,endData)
return
}
if(code){
s.knexQuery({
action: "delete",
table: "API",
where: {
ke: req.params.ke,
uid: user.uid,
code: code,
}
},(err,r) => {
if(!err){
s.tx({
f: 'api_key_deleted',
uid: user.uid,
form: {
code: code
}
},'GRP_' + req.params.ke)
endData.ok = true
delete(s.api[code])
}
s.closeJsonResponse(res,endData)
})
}else{
endData.msg = lang.postDataBroken
s.closeJsonResponse(res,endData)
}
},res,req)
})
/**
* API : List API Keys for Authenticated user
*/
app.get([
config.webPaths.adminApiPrefix+':auth/api/:ke/list',
config.webPaths.apiPrefix+':auth/api/:ke/list',
],function (req,res){
var endData = {ok:false}
s.auth(req.params,function(user){
const {
isSubAccount,
} = s.checkPermission(user)
var endData = {
ok : false,
keys: []
}
const targetUID = req.query.uid;
endData.uid = !isSubAccount && targetUID ? targetUID : user.uid;
const whereQuery = {
ke : req.params.ke,
uid : endData.uid
}
s.knexQuery({
action: "select",
columns: "*",
table: "API",
where: whereQuery
},function(err,rows) {
if(rows && rows[0]){
rows.forEach(function(row){
row.details = JSON.parse(row.details)
})
endData.ok = true
endData.ke = user.ke
endData.keys = rows
}
s.closeJsonResponse(res,endData)
})
},res,req)
})
/**
* API : Administrator : Get Monitor State Presets List
*/
app.all([

View File

@ -285,6 +285,7 @@ module.exports = function(s,config,lang,io){
"ip": "0.0.0.0",
"details": {
"auth_socket": "1",
"create_api_keys": "1",
"get_monitors": "1",
"control_monitors": "1",
"get_logs": "1",

View File

@ -99,7 +99,7 @@ $(document).ready(function(e){
details[permissionValue] = "0"
}
});
details.monitorPermissions = getMonitorsSelectedInPermissionForm();
details.monitorPermissions = details.monitorsRestricted === '1' ? getMonitorsSelectedInPermissionForm() : {};
return details
}
function getMonitorsSelectedInPermissionForm(){