added access control to actions of user in api

pull/80/head
13621160019@163.com 2021-11-10 18:04:15 +08:00
parent 72484ea920
commit dd279ba548
40 changed files with 114 additions and 99 deletions

View File

@ -46,7 +46,8 @@ app.controller('UserController', function ($scope,
}
});
modalInstance.result.then(function (user) {
UserService.addUser(user, function (response) {
let headers = { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token };
UserService.addUser(user, headers, function (response) {
if (angular.isDefined(response.status) && response.status === 201) {
toaster.pop({
type: "success",
@ -85,7 +86,8 @@ app.controller('UserController', function ($scope,
});
modalInstance.result.then(function (modifiedUser) {
UserService.editUser(modifiedUser, function (response) {
let headers = { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token };
UserService.editUser(modifiedUser, headers, function (response) {
if (angular.isDefined(response.status) && response.status === 200) {
toaster.pop({
type: "success",
@ -123,12 +125,8 @@ app.controller('UserController', function ($scope,
});
modalInstance.result.then(function (modifiedUser) {
let data = {
name: modifiedUser.name,
password: modifiedUser.password };
let data = {name: modifiedUser.name, password: modifiedUser.password };
let headers = { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token };
UserService.resetPassword(data, headers, function (response) {
if (angular.isDefined(response.status) && response.status === 200) {
toaster.pop({
@ -166,7 +164,8 @@ app.controller('UserController', function ($scope,
},
function (isConfirm) {
if (isConfirm) {
UserService.deleteUser(user, function (response) {
let headers = { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token };
UserService.deleteUser(user, headers, function (response) {
if (angular.isDefined(response.status) && response.status === 204) {
toaster.pop({
type: "success",

View File

@ -17,16 +17,16 @@ app.factory('UserService', function($http) {
callback(response);
});
},
addUser: function(user, callback) {
$http.post(getAPI()+'users',{data:user})
addUser: function(user, headers, callback) {
$http.post(getAPI()+'users', {data:user}, {headers})
.then(function (response) {
callback(response);
}, function (response) {
callback(response);
});
},
editUser: function(user, callback) {
$http.put(getAPI()+'users/'+user.id,{data:user})
editUser: function(user, headers, callback) {
$http.put(getAPI()+'users/'+user.id, {data:user}, {headers})
.then(function (response) {
callback(response);
}, function (response) {
@ -49,16 +49,16 @@ app.factory('UserService', function($http) {
callback(response);
});
},
deleteUser: function(user, callback) {
$http.delete(getAPI()+'users/'+user.id)
deleteUser: function(user, headers, callback) {
$http.delete(getAPI()+'users/'+user.id, {headers})
.then(function (response) {
callback(response);
}, function (response) {
callback(response);
});
},
getUser: function(id, callback) {
$http.get(getAPI()+'users/'+id)
getUser: function(id, headers, callback) {
$http.get(getAPI()+'users/'+id, {headers})
.then(function (response) {
callback(response);
}, function (response) {

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class CombinedEquipmentCollection:

View File

@ -4,7 +4,7 @@ import mysql.connector
import config
import uuid
import re
from core.userlogger import user_logger
from core.useractivity import user_logger
class ContactCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class CostCenterCollection:

View File

@ -5,7 +5,7 @@ import config
import uuid
from datetime import datetime, timezone, timedelta
import os
from core.userlogger import user_logger
from core.useractivity import user_logger
class CostFileCollection:

View File

@ -4,7 +4,7 @@ import mysql.connector
import config
import uuid
from datetime import datetime, timezone, timedelta
from core.userlogger import user_logger
from core.useractivity import user_logger
class DataSourceCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class DistributionCircuitCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class DistributionSystemCollection:

View File

@ -3,7 +3,7 @@ import json
import mysql.connector
import config
from datetime import datetime, timedelta, timezone
from core.userlogger import user_logger
from core.useractivity import user_logger
class EmailMessageCollection:

View File

@ -4,7 +4,7 @@ import mysql.connector
import config
import base64
import re
from core.userlogger import user_logger
from core.useractivity import user_logger
class EmailServerCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class EnergyCategoryCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class EnergyFlowDiagramCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class EnergyItemCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class EquipmentCollection:

View File

@ -4,7 +4,7 @@ import mysql.connector
import config
import uuid
from datetime import datetime, timezone, timedelta
from core.userlogger import user_logger
from core.useractivity import user_logger
class GatewayCollection:

View File

@ -7,7 +7,7 @@ from datetime import datetime, timezone, timedelta
import os
import base64
import sys
from core.userlogger import user_logger
from core.useractivity import user_logger
class KnowledgeFileCollection:

View File

@ -2,7 +2,7 @@ import falcon
import simplejson as json
import mysql.connector
import config
from core.userlogger import user_logger
from core.useractivity import user_logger
class MenuCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class MeterCollection:

View File

@ -3,7 +3,7 @@ import json
import mysql.connector
import config
from datetime import datetime, timedelta, timezone
from core.userlogger import user_logger
from core.useractivity import user_logger
class NotificationCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class OfflineMeterCollection:

View File

@ -5,7 +5,7 @@ import config
import uuid
from datetime import datetime, timezone, timedelta
import os
from core.userlogger import user_logger
from core.useractivity import user_logger
class OfflineMeterFileCollection:

View File

@ -2,7 +2,7 @@ import falcon
import simplejson as json
import mysql.connector
import config
from core.userlogger import user_logger
from core.useractivity import user_logger
class PointCollection:

View File

@ -2,7 +2,7 @@ import falcon
import simplejson as json
import mysql.connector
import config
from core.userlogger import user_logger
from core.useractivity import user_logger
class PrivilegeCollection:

View File

@ -4,7 +4,7 @@ import mysql.connector
import uuid
from datetime import datetime, timezone, timedelta
import config
from core.userlogger import user_logger
from core.useractivity import user_logger
class RuleCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class SensorCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class ShopfloorCollection:

View File

@ -6,7 +6,7 @@ import uuid
from datetime import datetime
from anytree import AnyNode
from anytree.exporter import JsonExporter
from core.userlogger import user_logger
from core.useractivity import user_logger
class SpaceCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class StoreCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class StoreTypeCollection:

View File

@ -4,7 +4,7 @@ import mysql.connector
import config
import uuid
from datetime import datetime, timedelta, timezone
from core.userlogger import user_logger
from core.useractivity import user_logger
class TariffCollection:

View File

@ -4,7 +4,7 @@ import mysql.connector
import config
import uuid
from datetime import datetime, timedelta, timezone
from core.userlogger import user_logger
from core.useractivity import user_logger
class TenantCollection:

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class TenantTypeCollection:

View File

@ -3,7 +3,7 @@ import json
import mysql.connector
import config
from datetime import datetime, timedelta, timezone
from core.userlogger import user_logger
from core.useractivity import user_logger
class TextMessageCollection:

View File

@ -2,7 +2,7 @@ import falcon
import simplejson as json
import mysql.connector
import config
from core.userlogger import user_logger
from core.useractivity import user_logger
class TimezoneCollection:

View File

@ -7,7 +7,7 @@ import hashlib
import re
import os
from datetime import datetime, timedelta, timezone
from core.userlogger import user_logger, write_log
from core.useractivity import user_logger, write_log, access_control
class UserCollection:
@ -22,52 +22,9 @@ class UserCollection:
@staticmethod
def on_get(req, resp):
if 'USER-UUID' not in req.headers or \
not isinstance(req.headers['USER-UUID'], str) or \
len(str.strip(req.headers['USER-UUID'])) == 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_USER_UUID')
admin_user_uuid = str.strip(req.headers['USER-UUID'])
if 'TOKEN' not in req.headers or \
not isinstance(req.headers['TOKEN'], str) or \
len(str.strip(req.headers['TOKEN'])) == 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_TOKEN')
admin_token = str.strip(req.headers['TOKEN'])
# Check administrator privilege
access_control(req)
cnx = mysql.connector.connect(**config.myems_user_db)
cursor = cnx.cursor()
query = (" SELECT utc_expires "
" FROM tbl_sessions "
" WHERE user_uuid = %s AND token = %s")
cursor.execute(query, (admin_user_uuid, admin_token,))
row = cursor.fetchone()
if row is None:
cursor.close()
cnx.disconnect()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.ADMINISTRATOR_SESSION_NOT_FOUND')
else:
utc_expires = row[0]
if datetime.utcnow() > utc_expires:
cursor.close()
cnx.disconnect()
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.ADMINISTRATOR_SESSION_TIMEOUT')
query = (" SELECT name "
" FROM tbl_users "
" WHERE uuid = %s AND is_admin = true ")
cursor.execute(query, (admin_user_uuid,))
row = cursor.fetchone()
if row is None:
cursor.close()
cnx.disconnect()
raise falcon.HTTPError(falcon.HTTP_400, 'API.BAD_REQUEST', 'API.INVALID_PRIVILEGE')
query = (" SELECT u.id, u.name, u.display_name, u.uuid, "
" u.email, u.is_admin, p.id, p.name, "
" u.account_expiration_datetime_utc, u.password_expiration_datetime_utc "
@ -110,7 +67,7 @@ class UserCollection:
@staticmethod
def on_post(req, resp):
"""Handles POST requests"""
# todo: add access control
access_control(req)
# todo: add user log
try:
raw_json = req.stream.read().decode('utf-8')
@ -246,7 +203,7 @@ class UserItem:
@staticmethod
def on_get(req, resp, id_):
# todo: add access control
access_control(req)
if not id_.isdigit() or int(id_) <= 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_USER_ID')
@ -291,6 +248,7 @@ class UserItem:
@staticmethod
@user_logger
def on_delete(req, resp, id_):
access_control(req)
if not id_.isdigit() or int(id_) <= 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_USER_ID')
@ -320,6 +278,7 @@ class UserItem:
@user_logger
def on_put(req, resp, id_):
"""Handles PUT requests"""
access_control(req)
try:
raw_json = req.stream.read().decode('utf-8')
except Exception as ex:

View File

@ -9,6 +9,58 @@ import simplejson as json
import falcon
def access_control(req):
"""
Check administrator privilege in request headers to protect resources from invalid access
:param req: HTTP request
:return: HTTPError if invalid else None
"""
if 'USER-UUID' not in req.headers or \
not isinstance(req.headers['USER-UUID'], str) or \
len(str.strip(req.headers['USER-UUID'])) == 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_USER_UUID')
admin_user_uuid = str.strip(req.headers['USER-UUID'])
if 'TOKEN' not in req.headers or \
not isinstance(req.headers['TOKEN'], str) or \
len(str.strip(req.headers['TOKEN'])) == 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_TOKEN')
admin_token = str.strip(req.headers['TOKEN'])
# Check administrator privilege
cnx = mysql.connector.connect(**config.myems_user_db)
cursor = cnx.cursor()
query = (" SELECT utc_expires "
" FROM tbl_sessions "
" WHERE user_uuid = %s AND token = %s")
cursor.execute(query, (admin_user_uuid, admin_token,))
row = cursor.fetchone()
if row is None:
cursor.close()
cnx.disconnect()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.ADMINISTRATOR_SESSION_NOT_FOUND')
else:
utc_expires = row[0]
if datetime.utcnow() > utc_expires:
cursor.close()
cnx.disconnect()
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.ADMINISTRATOR_SESSION_TIMEOUT')
query = (" SELECT name "
" FROM tbl_users "
" WHERE uuid = %s AND is_admin = true ")
cursor.execute(query, (admin_user_uuid,))
row = cursor.fetchone()
cursor.close()
cnx.disconnect()
if row is None:
raise falcon.HTTPError(falcon.HTTP_400, 'API.BAD_REQUEST', 'API.INVALID_PRIVILEGE')
def write_log(user_uuid, request_method, resource_type, resource_id, request_body):
"""
:param user_uuid: user_uuid
@ -43,6 +95,11 @@ def write_log(user_uuid, request_method, resource_type, resource_id, request_bod
def user_logger(func):
"""
Decorator for logging user activities
:param func: the decorated function
:return: the decorator
"""
@wraps(func)
def logger(*args, **kwargs):
qualified_name = func.__qualname__

View File

@ -3,7 +3,7 @@ import simplejson as json
import mysql.connector
import config
import uuid
from core.userlogger import user_logger
from core.useractivity import user_logger
class VirtualMeterCollection:

View File

@ -3,7 +3,7 @@ import json
import mysql.connector
import config
from datetime import datetime, timedelta, timezone
from core.userlogger import user_logger
from core.useractivity import user_logger
class WebMessageCollection:

View File

@ -3,7 +3,7 @@ import json
import mysql.connector
import config
from datetime import datetime, timedelta, timezone
from core.userlogger import user_logger
from core.useractivity import user_logger
class WechatMessageCollection(object):