diff --git a/cmdb-api/Pipfile b/cmdb-api/Pipfile index 0d3347e..7c4ca41 100644 --- a/cmdb-api/Pipfile +++ b/cmdb-api/Pipfile @@ -5,24 +5,24 @@ name = "pypi" [packages] # Flask -Flask = "==1.0.3" -Werkzeug = "==0.15.5" +Flask = "==2.3.2" +Werkzeug = "==2.3.6" click = ">=5.0" # Api -Flask-RESTful = "==0.3.7" +Flask-RESTful = "==0.3.10" # Database -Flask-SQLAlchemy = "==2.4.0" -SQLAlchemy = "==1.3.5" -PyMySQL = "==0.9.3" +Flask-SQLAlchemy = "==2.5.0" +SQLAlchemy = "==1.4.49" +PyMySQL = "==1.1.0" redis = "==3.2.1" # Migrations Flask-Migrate = "==2.5.2" # Deployment -gunicorn = "==19.5.0" +gunicorn = "==21.0.1" supervisor = "==4.0.3" # Auth -Flask-Login = "==0.4.1" -Flask-Bcrypt = "==0.7.1" +Flask-Login = "==0.6.2" +Flask-Bcrypt = "==1.0.1" Flask-Cors = ">=3.0.8" python-ldap = "==3.4.0" pycryptodome = "==3.12.0" @@ -37,7 +37,6 @@ celery_once = "==3.0.1" more-itertools = "==5.0.0" kombu = "==4.4.0" # common setting -Flask-APScheduler = "==1.12.4" timeout-decorator = "==0.5.0" WTForms = "==3.0.0" email-validator = "==1.3.1" @@ -52,8 +51,8 @@ requests = ">=2.22.0" PyJWT = "==2.4.0" elasticsearch = "==7.17.9" future = "==0.18.2" -itsdangerous = "==2.0.1" -Jinja2 = "==3.0.1" +itsdangerous = "==2.1.2" +Jinja2 = "==3.1.2" jinja2schema = "==0.1.4" msgpack-python = "==0.5.6" alembic = "==1.7.7" diff --git a/cmdb-api/api/app.py b/cmdb-api/api/app.py index c29aabb..4df68fc 100644 --- a/cmdb-api/api/app.py +++ b/cmdb-api/api/app.py @@ -6,26 +6,16 @@ import logging import os import sys from inspect import getmembers +from json import JSONEncoder from logging.handlers import RotatingFileHandler from flask import Flask -from flask import make_response, jsonify +from flask import jsonify, make_response from flask.blueprints import Blueprint from flask.cli import click -from flask.json import JSONEncoder import api.views.entry -from api.extensions import ( - bcrypt, - cors, - cache, - db, - login_manager, - migrate, - celery, - rd, - es, -) +from api.extensions import (bcrypt, cache, celery, cors, db, es, login_manager, migrate, rd) from api.flask_cas import CAS from api.models.acl import User diff --git a/cmdb-api/api/lib/cmdb/attribute.py b/cmdb-api/api/lib/cmdb/attribute.py index bc17d97..83f2029 100644 --- a/cmdb-api/api/lib/cmdb/attribute.py +++ b/cmdb-api/api/lib/cmdb/attribute.py @@ -3,13 +3,13 @@ import requests from flask import abort from flask import current_app -from flask import g from flask import session +from flask_login import current_user from api.extensions import db from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.const import CITypeOperateType -from api.lib.cmdb.const import ResourceTypeEnum, RoleEnum, PermEnum +from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum from api.lib.cmdb.const import ValueTypeEnum from api.lib.cmdb.history import CITypeHistoryManager from api.lib.cmdb.resp_format import ErrFormat @@ -177,7 +177,7 @@ class AttributeManager(object): name=name, alias=alias, is_choice=is_choice, - uid=g.user.uid, + uid=current_user.uid, **kwargs) if choice_value: @@ -240,7 +240,7 @@ class AttributeManager(object): def _can_edit_attribute(attr): from api.lib.cmdb.ci_type import CITypeManager - if attr.uid == g.user.uid: + if attr.uid == current_user.uid: return True for i in CITypeAttribute.get_by(attr_id=attr.id, to_dict=False): @@ -319,7 +319,7 @@ class AttributeManager(object): if CIType.get_by(unique_id=attr.id, first=True, to_dict=False) is not None: return abort(400, ErrFormat.attribute_is_unique_id) - if attr.uid and attr.uid != g.user.uid: + if attr.uid and attr.uid != current_user.uid: return abort(403, ErrFormat.cannot_delete_attribute) if attr.is_choice: diff --git a/cmdb-api/api/lib/cmdb/auto_discovery/auto_discovery.py b/cmdb-api/api/lib/cmdb/auto_discovery/auto_discovery.py index c044c9c..052d970 100644 --- a/cmdb-api/api/lib/cmdb/auto_discovery/auto_discovery.py +++ b/cmdb-api/api/lib/cmdb/auto_discovery/auto_discovery.py @@ -5,7 +5,7 @@ import os from flask import abort from flask import current_app -from flask import g +from flask_login import current_user from sqlalchemy import func from api.extensions import db @@ -156,7 +156,7 @@ class AutoDiscoveryCITypeCRUD(DBMixin): continue if isinstance(rule.get("extra_option"), dict) and rule['extra_option'].get('secret'): - if not (g.user.username == "cmdb_agent" or g.user.uid == rule['uid']): + if not (current_user.username == "cmdb_agent" or current_user.uid == rule['uid']): rule['extra_option'].pop('secret', None) else: rule['extra_option']['secret'] = AESCrypto.decrypt(rule['extra_option']['secret']) @@ -213,7 +213,7 @@ class AutoDiscoveryCITypeCRUD(DBMixin): agent_id = agent_id.strip() q = "op_duty:{0},-rd_duty:{0},oneagent_id:{1}" - s = search(q.format(g.user.username, agent_id.strip())) + s = search(q.format(current_user.username, agent_id.strip())) try: response, _, _, _, _, _ = s.search() if response: @@ -222,7 +222,7 @@ class AutoDiscoveryCITypeCRUD(DBMixin): current_app.logger.warning(e) return abort(400, str(e)) - s = search(q.format(g.user.nickname, agent_id.strip())) + s = search(q.format(current_user.nickname, agent_id.strip())) try: response, _, _, _, _, _ = s.search() if response: @@ -240,9 +240,9 @@ class AutoDiscoveryCITypeCRUD(DBMixin): try: response, _, _, _, _, _ = s.search() for i in response: - if g.user.username not in (i.get('rd_duty') or []) and g.user.username not in \ - (i.get('op_duty') or []) and g.user.nickname not in (i.get('rd_duty') or []) and \ - g.user.nickname not in (i.get('op_duty') or []): + if current_user.username not in (i.get('rd_duty') or []) and current_user.username not in \ + (i.get('op_duty') or []) and current_user.nickname not in (i.get('rd_duty') or []) and \ + current_user.nickname not in (i.get('op_duty') or []): return abort(403, ErrFormat.adt_target_expr_no_permission.format( i.get("{}_name".format(i.get('ci_type'))))) except SearchError as e: @@ -270,7 +270,7 @@ class AutoDiscoveryCITypeCRUD(DBMixin): if isinstance(kwargs.get('extra_option'), dict) and kwargs['extra_option'].get('secret'): kwargs['extra_option']['secret'] = AESCrypto.encrypt(kwargs['extra_option']['secret']) - kwargs['uid'] = g.user.uid + kwargs['uid'] = current_user.uid return kwargs @@ -281,7 +281,7 @@ class AutoDiscoveryCITypeCRUD(DBMixin): self.__valid_exec_target(kwargs.get('agent_id'), kwargs.get('query_expr')) if isinstance(kwargs.get('extra_option'), dict) and kwargs['extra_option'].get('secret'): - if g.user.uid != existed.uid: + if current_user.uid != existed.uid: return abort(403, ErrFormat.adt_secret_no_permission) return existed @@ -477,7 +477,7 @@ class AutoDiscoveryCICRUD(DBMixin): pass adc.update(is_accept=True, - accept_by=nickname or g.user.nickname, + accept_by=nickname or current_user.nickname, accept_time=datetime.datetime.now(), ci_id=ci_id) diff --git a/cmdb-api/api/lib/cmdb/ci.py b/cmdb-api/api/lib/cmdb/ci.py index e2196e2..a51bac0 100644 --- a/cmdb-api/api/lib/cmdb/ci.py +++ b/cmdb-api/api/lib/cmdb/ci.py @@ -7,7 +7,7 @@ import json from flask import abort from flask import current_app -from flask import g +from flask_login import current_user from werkzeug.exceptions import BadRequest from api.extensions import db @@ -24,8 +24,8 @@ from api.lib.cmdb.const import CMDB_QUEUE from api.lib.cmdb.const import ConstraintEnum from api.lib.cmdb.const import ExistPolicy from api.lib.cmdb.const import OperateType +from api.lib.cmdb.const import PermEnum, ResourceTypeEnum from api.lib.cmdb.const import REDIS_PREFIX_CI -from api.lib.cmdb.const import ResourceTypeEnum, PermEnum from api.lib.cmdb.const import RetKey from api.lib.cmdb.history import AttributeHistoryManger from api.lib.cmdb.history import CIRelationHistoryManager @@ -38,8 +38,8 @@ from api.lib.decorator import kwargs_required from api.lib.perm.acl.acl import ACLManager from api.lib.perm.acl.acl import is_app_admin from api.lib.perm.acl.acl import validate_permission -from api.lib.utils import Lock from api.lib.utils import handle_arg_list +from api.lib.utils import Lock from api.models.cmdb import CI from api.models.cmdb import CIRelation from api.models.cmdb import CITypeAttribute @@ -316,7 +316,7 @@ class CIManager(object): ci_attr2type_attr = {type_attr.attr_id: type_attr for type_attr, _ in attrs} ci = None - need_lock = g.user.username not in ("worker", "cmdb_agent", "agent") + need_lock = current_user.username not in ("worker", "cmdb_agent", "agent") with Lock(ci_type_name, need_lock=need_lock): existed = cls.ci_is_exist(unique_key, unique_value, ci_type.id) if existed is not None: @@ -411,7 +411,7 @@ class CIManager(object): limit_attrs = self._valid_ci_for_no_read(ci) if not _is_admin else {} - need_lock = g.user.username not in ("worker", "cmdb_agent", "agent") + need_lock = current_user.username not in ("worker", "cmdb_agent", "agent") with Lock(ci.ci_type.name, need_lock=need_lock): self._valid_unique_constraint(ci.type_id, ci_dict, ci_id) diff --git a/cmdb-api/api/lib/cmdb/ci_type.py b/cmdb-api/api/lib/cmdb/ci_type.py index 8f95265..44f123e 100644 --- a/cmdb-api/api/lib/cmdb/ci_type.py +++ b/cmdb-api/api/lib/cmdb/ci_type.py @@ -5,7 +5,7 @@ import datetime from flask import abort from flask import current_app -from flask import g +from flask_login import current_user from api.extensions import db from api.lib.cmdb.attribute import AttributeManager @@ -118,7 +118,7 @@ class CITypeManager(object): cls._validate_unique(alias=kwargs['alias']) kwargs["unique_id"] = unique_key.id - kwargs['uid'] = g.user.uid + kwargs['uid'] = current_user.uid ci_type = CIType.create(**kwargs) CITypeAttributeManager.add(ci_type.id, [unique_key.id], is_required=True) @@ -132,7 +132,7 @@ class CITypeManager(object): ResourceTypeEnum.CI, permissions=[PermEnum.READ]) ACLManager().grant_resource_to_role(ci_type.name, - g.user.username, + current_user.username, ResourceTypeEnum.CI) CITypeHistoryManager.add(CITypeOperateType.ADD, ci_type.id, change=ci_type.to_dict()) @@ -185,7 +185,7 @@ class CITypeManager(object): def delete(cls, type_id): ci_type = cls.check_is_existed(type_id) - if ci_type.uid and ci_type.uid != g.user.uid: + if ci_type.uid and ci_type.uid != current_user.uid: return abort(403, ErrFormat.only_owner_can_delete) if CI.get_by(type_id=type_id, first=True, to_dict=False) is not None: @@ -582,7 +582,7 @@ class CITypeRelationManager(object): ResourceTypeEnum.CI_TYPE_RELATION, permissions=[PermEnum.READ]) ACLManager().grant_resource_to_role(resource_name, - g.user.username, + current_user.username, ResourceTypeEnum.CI_TYPE_RELATION) CITypeHistoryManager.add(CITypeOperateType.ADD_RELATION, p.id, @@ -816,7 +816,7 @@ class CITypeTemplateManager(object): ResourceTypeEnum.CI, permissions=[PermEnum.READ]) ACLManager().grant_resource_to_role(type_name, - g.user.username, + current_user.username, ResourceTypeEnum.CI) else: @@ -954,7 +954,7 @@ class CITypeTemplateManager(object): rule.pop("created_at", None) rule.pop("updated_at", None) - rule['uid'] = g.user.uid + rule['uid'] = current_user.uid try: AutoDiscoveryCITypeCRUD.add(**rule) except: diff --git a/cmdb-api/api/lib/cmdb/history.py b/cmdb-api/api/lib/cmdb/history.py index 43474ec..5ebd282 100644 --- a/cmdb-api/api/lib/cmdb/history.py +++ b/cmdb-api/api/lib/cmdb/history.py @@ -4,7 +4,7 @@ import json from flask import abort -from flask import g +from flask_login import current_user from api.extensions import db from api.lib.cmdb.cache import AttributeCache @@ -201,7 +201,7 @@ class AttributeHistoryManger(object): @staticmethod def add(record_id, ci_id, history_list, type_id=None, flush=False, commit=True): if record_id is None: - record = OperationRecord.create(uid=g.user.uid, type_id=type_id) + record = OperationRecord.create(uid=current_user.uid, type_id=type_id) record_id = record.id for attr_id, operate_type, old, new in history_list or []: @@ -220,7 +220,7 @@ class AttributeHistoryManger(object): class CIRelationHistoryManager(object): @staticmethod def add(rel_obj, operate_type=OperateType.ADD): - record = OperationRecord.create(uid=g.user.uid) + record = OperationRecord.create(uid=current_user.uid) CIRelationHistory.create(relation_id=rel_obj.id, record_id=record.id, @@ -279,7 +279,7 @@ class CITypeHistoryManager(object): for _type_id in type_ids: payload = dict(operate_type=operate_type, type_id=_type_id, - uid=g.user.uid, + uid=current_user.uid, attr_id=attr_id, trigger_id=trigger_id, unique_constraint_id=unique_constraint_id, diff --git a/cmdb-api/api/lib/cmdb/perms.py b/cmdb-api/api/lib/cmdb/perms.py index b4b149e..3b5ad6f 100644 --- a/cmdb-api/api/lib/cmdb/perms.py +++ b/cmdb-api/api/lib/cmdb/perms.py @@ -4,8 +4,8 @@ import functools from flask import abort from flask import current_app -from flask import g from flask import request +from flask_login import current_user from api.lib.cmdb.const import ResourceTypeEnum from api.lib.cmdb.resp_format import ErrFormat @@ -74,7 +74,7 @@ class CIFilterPermsCRUD(DBMixin): @classmethod def get_attr_filter(cls, type_id): - if is_app_admin('cmdb') or g.user.username in ('worker', 'cmdb_agent'): + if is_app_admin('cmdb') or current_user.username in ('worker', 'cmdb_agent'): return [] res2 = ACLManager('cmdb').get_resources(ResourceTypeEnum.CI_FILTER) @@ -160,7 +160,7 @@ def has_perm_for_ci(arg_name, resource_type, perm, callback=None, app=None): resource = callback(resource) if current_app.config.get("USE_ACL") and resource: - if g.user.username == "worker" or g.user.username == "cmdb_agent": + if current_user.username == "worker" or current_user.username == "cmdb_agent": request.values['__is_admin'] = True return func(*args, **kwargs) diff --git a/cmdb-api/api/lib/cmdb/preference.py b/cmdb-api/api/lib/cmdb/preference.py index 2c07880..8e680e3 100644 --- a/cmdb-api/api/lib/cmdb/preference.py +++ b/cmdb-api/api/lib/cmdb/preference.py @@ -7,7 +7,7 @@ import six import toposort from flask import abort from flask import current_app -from flask import g +from flask_login import current_user from api.extensions import db from api.lib.cmdb.attribute import AttributeManager @@ -36,10 +36,10 @@ class PreferenceManager(object): @staticmethod def get_types(instance=False, tree=False): types = db.session.query(PreferenceShowAttributes.type_id).filter( - PreferenceShowAttributes.uid == g.user.uid).filter( + PreferenceShowAttributes.uid == current_user.uid).filter( PreferenceShowAttributes.deleted.is_(False)).group_by(PreferenceShowAttributes.type_id).all() \ if instance else [] - tree_types = PreferenceTreeView.get_by(uid=g.user.uid, to_dict=False) if tree else [] + tree_types = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=False) if tree else [] type_ids = list(set([i.type_id for i in types + tree_types])) return [CITypeCache.get(type_id).to_dict() for type_id in type_ids] @@ -62,7 +62,7 @@ class PreferenceManager(object): PreferenceShowAttributes.deleted.is_(False)).group_by( PreferenceShowAttributes.uid, PreferenceShowAttributes.type_id) for i in types: - if i.uid == g.user.uid: + if i.uid == current_user.uid: result['self']['instance'].append(i.type_id) if str(i.created_at) > str(result['self']['type_id2subs_time'].get(i.type_id, "")): result['self']['type_id2subs_time'][i.type_id] = i.created_at @@ -72,7 +72,7 @@ class PreferenceManager(object): if tree: types = PreferenceTreeView.get_by(to_dict=False) for i in types: - if i.uid == g.user.uid: + if i.uid == current_user.uid: result['self']['tree'].append(i.type_id) if str(i.created_at) > str(result['self']['type_id2subs_time'].get(i.type_id, "")): result['self']['type_id2subs_time'][i.type_id] = i.created_at @@ -91,7 +91,7 @@ class PreferenceManager(object): attrs = db.session.query(PreferenceShowAttributes, CITypeAttribute.order).join( CITypeAttribute, CITypeAttribute.attr_id == PreferenceShowAttributes.attr_id).filter( - PreferenceShowAttributes.uid == g.user.uid).filter( + PreferenceShowAttributes.uid == current_user.uid).filter( PreferenceShowAttributes.type_id == type_id).filter( PreferenceShowAttributes.deleted.is_(False)).filter(CITypeAttribute.deleted.is_(False)).filter( CITypeAttribute.type_id == type_id).all() @@ -120,7 +120,7 @@ class PreferenceManager(object): @classmethod def create_or_update_show_attributes(cls, type_id, attr_order): - existed_all = PreferenceShowAttributes.get_by(type_id=type_id, uid=g.user.uid, to_dict=False) + existed_all = PreferenceShowAttributes.get_by(type_id=type_id, uid=current_user.uid, to_dict=False) for x, order in attr_order: if isinstance(x, list): _attr, is_fixed = x @@ -128,13 +128,13 @@ class PreferenceManager(object): _attr, is_fixed = x, False attr = AttributeCache.get(_attr) or abort(404, ErrFormat.attribute_not_found.format("id={}".format(_attr))) existed = PreferenceShowAttributes.get_by(type_id=type_id, - uid=g.user.uid, + uid=current_user.uid, attr_id=attr.id, first=True, to_dict=False) if existed is None: PreferenceShowAttributes.create(type_id=type_id, - uid=g.user.uid, + uid=current_user.uid, attr_id=attr.id, order=order, is_fixed=is_fixed) @@ -148,7 +148,7 @@ class PreferenceManager(object): @staticmethod def get_tree_view(): - res = PreferenceTreeView.get_by(uid=g.user.uid, to_dict=True) + res = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=True) for item in res: if item["levels"]: ci_type = CITypeCache.get(item['type_id']).to_dict() @@ -176,14 +176,14 @@ class PreferenceManager(object): if i == attr.id or i == attr.name or i == attr.alias: levels[idx] = attr.id - existed = PreferenceTreeView.get_by(uid=g.user.uid, type_id=type_id, to_dict=False, first=True) + existed = PreferenceTreeView.get_by(uid=current_user.uid, type_id=type_id, to_dict=False, first=True) if existed is not None: if not levels: existed.soft_delete() return existed return existed.update(levels=levels) elif levels: - return PreferenceTreeView.create(levels=levels, type_id=type_id, uid=g.user.uid) + return PreferenceTreeView.create(levels=levels, type_id=type_id, uid=current_user.uid) @staticmethod def get_relation_view(): @@ -254,7 +254,7 @@ class PreferenceManager(object): existed = PreferenceRelationView.get_by(name=name, to_dict=False, first=True) current_app.logger.debug(existed) if existed is None: - PreferenceRelationView.create(name=name, cr_ids=cr_ids, uid=g.user.uid, is_public=is_public) + PreferenceRelationView.create(name=name, cr_ids=cr_ids, uid=current_user.uid, is_public=is_public) if current_app.config.get("USE_ACL"): ACLManager().add_resource(name, ResourceTypeEnum.RELATION_VIEW) @@ -278,7 +278,7 @@ class PreferenceManager(object): @staticmethod def get_search_option(**kwargs): query = PreferenceSearchOption.get_by(only_query=True) - query = query.filter(PreferenceSearchOption.uid == g.user.uid) + query = query.filter(PreferenceSearchOption.uid == current_user.uid) for k in kwargs: if hasattr(PreferenceSearchOption, k) and kwargs[k]: @@ -288,9 +288,9 @@ class PreferenceManager(object): @staticmethod def add_search_option(**kwargs): - kwargs['uid'] = g.user.uid + kwargs['uid'] = current_user.uid - existed = PreferenceSearchOption.get_by(uid=g.user.uid, + existed = PreferenceSearchOption.get_by(uid=current_user.uid, name=kwargs.get('name'), prv_id=kwargs.get('prv_id'), ptv_id=kwargs.get('ptv_id'), @@ -306,10 +306,10 @@ class PreferenceManager(object): existed = PreferenceSearchOption.get_by_id(_id) or abort(404, ErrFormat.preference_search_option_not_found) - if g.user.uid != existed.uid: + if current_user.uid != existed.uid: return abort(400, ErrFormat.no_permission2) - other = PreferenceSearchOption.get_by(uid=g.user.uid, + other = PreferenceSearchOption.get_by(uid=current_user.uid, name=kwargs.get('name'), prv_id=kwargs.get('prv_id'), ptv_id=kwargs.get('ptv_id'), @@ -324,7 +324,7 @@ class PreferenceManager(object): def delete_search_option(_id): existed = PreferenceSearchOption.get_by_id(_id) or abort(404, ErrFormat.preference_search_option_not_found) - if g.user.uid != existed.uid: + if current_user.uid != existed.uid: return abort(400, ErrFormat.no_permission2) existed.soft_delete() diff --git a/cmdb-api/api/lib/cmdb/search/ci/db/search.py b/cmdb-api/api/lib/cmdb/search/ci/db/search.py index 48e2fb9..f6b5e98 100644 --- a/cmdb-api/api/lib/cmdb/search/ci/db/search.py +++ b/cmdb-api/api/lib/cmdb/search/ci/db/search.py @@ -7,8 +7,9 @@ import copy import time from flask import current_app -from flask import g +from flask_login import current_user from jinja2 import Template + from api.extensions import db from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.cache import CITypeCache @@ -105,7 +106,7 @@ class Search(object): ci_filter = self.type2filter_perms[ci_type.id].get('ci_filter') if ci_filter: sub = [] - ci_filter = Template(ci_filter).render(user=g.user) + ci_filter = Template(ci_filter).render(user=current_user) for i in ci_filter.split(','): if i.startswith("~") and not sub: queries.append(i) @@ -355,7 +356,7 @@ class Search(object): else: result.append(q) - _is_app_admin = is_app_admin('cmdb') or g.user.username == "worker" + _is_app_admin = is_app_admin('cmdb') or current_user.username == "worker" if result and not has_type and not _is_app_admin: type_q = self.__get_types_has_read() if id_query: diff --git a/cmdb-api/api/lib/http_cli.py b/cmdb-api/api/lib/http_cli.py index 6c59777..186c285 100644 --- a/cmdb-api/api/lib/http_cli.py +++ b/cmdb-api/api/lib/http_cli.py @@ -4,16 +4,16 @@ import hashlib import requests -from future.moves.urllib.parse import urlparse from flask import abort -from flask import g from flask import current_app +from flask_login import current_user +from future.moves.urllib.parse import urlparse def build_api_key(path, params): - g.user is not None or abort(403, u"您得登陆才能进行该操作") - key = g.user.key - secret = g.user.secret + current_user is not None or abort(403, u"您得登陆才能进行该操作") + key = current_user.key + secret = current_user.secret values = "".join([str(params[k]) for k in sorted(params.keys()) if params[k] is not None]) if params.keys() else "" _secret = "".join([path, secret, values]).encode("utf-8") diff --git a/cmdb-api/api/lib/perm/acl/acl.py b/cmdb-api/api/lib/perm/acl/acl.py index 66dc7a2..9294152 100644 --- a/cmdb-api/api/lib/perm/acl/acl.py +++ b/cmdb-api/api/lib/perm/acl/acl.py @@ -5,8 +5,9 @@ import hashlib import requests import six -from flask import current_app, g, request -from flask import session, abort +from flask import abort, session +from flask import current_app, request +from flask_login import current_user from api.extensions import cache from api.lib.perm.acl.audit import AuditCRUD @@ -154,9 +155,9 @@ class ACLManager(object): if is_app_admin(self.app_id): return True - role = self._get_role(g.user.username) + role = self._get_role(current_user.username) - role or abort(404, ErrFormat.role_not_found.format(g.user.username)) + role or abort(404, ErrFormat.role_not_found.format(current_user.username)) return RoleCRUD.has_permission(role.id, resource_name, resource_type, self.app_id, perm, resource_id=resource_id) @@ -193,9 +194,9 @@ class ACLManager(object): return user def get_resources(self, resource_type_name=None): - role = self._get_role(g.user.username) + role = self._get_role(current_user.username) - role or abort(404, ErrFormat.role_not_found.format(g.user.username)) + role or abort(404, ErrFormat.role_not_found.format(current_user.username)) rid = role.id return RoleCRUD.recursive_resources(rid, self.app_id, resource_type_name).get('resources') @@ -215,7 +216,7 @@ def validate_permission(resources, resource_type, perm, app=None): return if current_app.config.get("USE_ACL"): - if g.user.username == "worker": + if current_user.username == "worker": return resources = [resources] if isinstance(resources, six.string_types) else resources @@ -313,7 +314,7 @@ def role_required(role_name, app=None): return if current_app.config.get("USE_ACL"): - if getattr(g.user, 'username', None) == "worker": + if getattr(current_user, 'username', None) == "worker": return func(*args, **kwargs) if role_name not in session.get("acl", {}).get("parentRoles", []) and not is_app_admin(app): diff --git a/cmdb-api/api/lib/perm/acl/audit.py b/cmdb-api/api/lib/perm/acl/audit.py index 819c9d3..921d619 100644 --- a/cmdb-api/api/lib/perm/acl/audit.py +++ b/cmdb-api/api/lib/perm/acl/audit.py @@ -9,8 +9,8 @@ from flask_login import current_user from sqlalchemy import func from api.lib.perm.acl import AppCache -from api.models.acl import AuditRoleLog, AuditResourceLog, AuditPermissionLog, AuditTriggerLog, RolePermission, \ - Resource, ResourceGroup, Permission, Role, ResourceType +from api.models.acl import AuditPermissionLog, AuditResourceLog, AuditRoleLog, AuditTriggerLog, Permission, Resource, \ + ResourceGroup, ResourceType, Role, RolePermission class AuditScope(str, Enum): @@ -50,7 +50,7 @@ class AuditCRUD(object): @staticmethod def get_current_operate_uid(uid=None): - user_id = uid or (hasattr(g, 'user') and getattr(g.user, 'uid', None)) \ + user_id = uid or (hasattr(g, 'user') and getattr(current_user, 'uid', None)) \ or getattr(current_user, 'user_id', None) if has_request_context() and request.headers.get('X-User-Id'): diff --git a/cmdb-api/api/lib/perm/acl/role.py b/cmdb-api/api/lib/perm/acl/role.py index 470e748..712c7d5 100644 --- a/cmdb-api/api/lib/perm/acl/role.py +++ b/cmdb-api/api/lib/perm/acl/role.py @@ -6,6 +6,7 @@ import time import six from flask import abort from flask import current_app +from sqlalchemy import or_ from api.extensions import db from api.lib.perm.acl.app import AppCRUD @@ -212,18 +213,16 @@ class RoleCRUD(object): @staticmethod def search(q, app_id, page=1, page_size=None, user_role=True, is_all=False, user_only=False): - query = db.session.query(Role).filter(Role.deleted.is_(False)) - query1 = query.filter(Role.app_id == app_id).filter(Role.uid.is_(None)) - query2 = query.filter(Role.app_id.is_(None)).filter(Role.uid.is_(None)) - query = query1.union(query2) - if user_role: - query1 = db.session.query(Role).filter(Role.deleted.is_(False)).filter(Role.uid.isnot(None)) - query = query.union(query1) - - if user_only: + if user_only: # only user role query = db.session.query(Role).filter(Role.deleted.is_(False)).filter(Role.uid.isnot(None)) + else: + query = db.session.query(Role).filter(Role.deleted.is_(False)).filter( + or_(Role.app_id == app_id, Role.app_id.is_(None))) + if not user_role: # only virtual role + query = query.filter(Role.uid.is_(None)) + if not is_all: role_ids = list(HasResourceRoleCache.get(app_id).keys()) query = query.filter(Role.id.in_(role_ids)) diff --git a/cmdb-api/api/lib/perm/acl/user.py b/cmdb-api/api/lib/perm/acl/user.py index 733cb0f..9c9141d 100644 --- a/cmdb-api/api/lib/perm/acl/user.py +++ b/cmdb-api/api/lib/perm/acl/user.py @@ -6,7 +6,7 @@ import string import uuid from flask import abort -from flask import g +from flask_login import current_user from api.extensions import db from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditScope @@ -90,9 +90,9 @@ class UserCRUD(object): @classmethod def reset_key_secret(cls): key, secret = cls.gen_key_secret() - g.user.update(key=key, secret=secret) + current_user.update(key=key, secret=secret) - UserCache.clean(g.user) + UserCache.clean(current_user) return key, secret diff --git a/cmdb-api/api/lib/perm/auth.py b/cmdb-api/api/lib/perm/auth.py index c57a4b5..3b999ef 100644 --- a/cmdb-api/api/lib/perm/auth.py +++ b/cmdb-api/api/lib/perm/auth.py @@ -10,6 +10,7 @@ from flask import current_app from flask import g from flask import request from flask import session +from flask_login import current_user from flask_login import login_user from api.lib.perm.acl.acl import ACLManager @@ -65,7 +66,7 @@ def _auth_with_key(): def _auth_with_session(): if isinstance(getattr(g, 'user', None), User): - login_user(g.user) + login_user(current_user) return True if "acl" in session and "userName" in (session["acl"] or {}): login_user(UserCache.get(session["acl"]["userName"])) diff --git a/cmdb-api/api/models/acl.py b/cmdb-api/api/models/acl.py index ebf02ff..d13e702 100644 --- a/cmdb-api/api/models/acl.py +++ b/cmdb-api/api/models/acl.py @@ -62,10 +62,10 @@ class UserQuery(BaseQuery): ldap_conn.set_option(ldap.OPT_REFERRALS, 0) if '@' in username: email = username - who = '{0}@{1}'.format(username.split('@')[0], current_app.config.get('LDAP_DOMAIN')) + who = current_app.config.get('LDAP_USER_DN').format(username.split('@')[0]) else: - who = '{0}@{1}'.format(username, current_app.config.get('LDAP_DOMAIN')) - email = who + who = current_app.config.get('LDAP_USER_DN').format(username) + email = "{}@{}".format(who, current_app.config.get('LDAP_DOMAIN')) username = username.split('@')[0] user = self.get_by_username(username) diff --git a/cmdb-api/api/views/acl/resources.py b/cmdb-api/api/views/acl/resources.py index da5fc8a..df080b8 100644 --- a/cmdb-api/api/views/acl/resources.py +++ b/cmdb-api/api/views/acl/resources.py @@ -2,6 +2,7 @@ from flask import g from flask import request +from flask_login import current_user from api.lib.decorator import args_required from api.lib.decorator import args_validate @@ -103,8 +104,8 @@ class ResourceView(APIView): type_id = request.values.get('type_id') app_id = request.values.get('app_id') uid = request.values.get('uid') - if not uid and hasattr(g, "user") and hasattr(g.user, "uid"): - uid = g.user.uid + if not uid and hasattr(g, "user") and hasattr(current_user, "uid"): + uid = current_user.uid resource = ResourceCRUD.add(name, type_id, app_id, uid) diff --git a/cmdb-api/api/views/acl/role.py b/cmdb-api/api/views/acl/role.py index 1afad37..03a45e1 100644 --- a/cmdb-api/api/views/acl/role.py +++ b/cmdb-api/api/views/acl/role.py @@ -2,8 +2,8 @@ from flask import abort from flask import current_app -from flask import g from flask import request +from flask_login import current_user from api.lib.decorator import args_required from api.lib.decorator import args_validate @@ -31,12 +31,9 @@ class RoleView(APIView): page_size = get_page_size(request.values.get("page_size")) q = request.values.get('q') app_id = request.values.get('app_id') - is_all = request.values.get('is_all', True) - is_all = True if is_all in current_app.config.get("BOOL_TRUE") else False - user_role = request.values.get('user_role', True) - user_only = request.values.get('user_only', False) - user_role = True if user_role in current_app.config.get("BOOL_TRUE") else False - user_only = True if user_only in current_app.config.get("BOOL_TRUE") else False + is_all = request.values.get('is_all', True) in current_app.config.get("BOOL_TRUE") + user_role = request.values.get('user_role', True) in current_app.config.get("BOOL_TRUE") + user_only = request.values.get('user_only', False) in current_app.config.get("BOOL_TRUE") numfound, roles = RoleCRUD.search(q, app_id, page, page_size, user_role, is_all, user_only) @@ -160,8 +157,8 @@ class RoleHasPermissionView(APIView): @auth_with_app_token def get(self): if not request.values.get('rid'): - role = RoleCache.get_by_name(None, g.user.username) - role or abort(404, ErrFormat.role_not_found.format(g.user.username)) + role = RoleCache.get_by_name(None, current_user.username) + role or abort(404, ErrFormat.role_not_found.format(current_user.username)) else: role = RoleCache.get(int(request.values.get('rid'))) diff --git a/cmdb-api/api/views/acl/user.py b/cmdb-api/api/views/acl/user.py index dc681a4..d5e0d86 100644 --- a/cmdb-api/api/views/acl/user.py +++ b/cmdb-api/api/views/acl/user.py @@ -13,7 +13,6 @@ from api.lib.decorator import args_required from api.lib.decorator import args_validate from api.lib.perm.acl.acl import ACLManager from api.lib.perm.acl.acl import role_required -from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType from api.lib.perm.acl.cache import AppCache from api.lib.perm.acl.cache import UserCache from api.lib.perm.acl.resp_format import ErrFormat @@ -116,7 +115,7 @@ class UserView(APIView): @role_required("acl_admin") def delete(self, uid): - if g.user.uid == uid: + if current_user.uid == uid: return abort(400, ErrFormat.invalid_operation) UserCRUD.delete(uid) @@ -163,7 +162,7 @@ class UserResetPasswordView(APIView): return abort(403, ErrFormat.invalid_request) elif hasattr(g, 'user'): - if g.user.username != request.values['username']: + if current_user.username != request.values['username']: return abort(403, ErrFormat.invalid_request) else: diff --git a/cmdb-api/api/views/cmdb/auto_discovery.py b/cmdb-api/api/views/cmdb/auto_discovery.py index 2a4e600..d10b1c2 100644 --- a/cmdb-api/api/views/cmdb/auto_discovery.py +++ b/cmdb-api/api/views/cmdb/auto_discovery.py @@ -5,8 +5,8 @@ from io import BytesIO from flask import abort from flask import current_app -from flask import g from flask import request +from flask_login import current_user from api.lib.cmdb.auto_discovery.auto_discovery import AutoDiscoveryCICRUD from api.lib.cmdb.auto_discovery.auto_discovery import AutoDiscoveryCITypeCRUD @@ -119,7 +119,7 @@ class AutoDiscoveryCITypeView(APIView): _, res = AutoDiscoveryCITypeCRUD.search(page=1, page_size=100000, type_id=type_id, **request.values) for i in res: if isinstance(i.get("extra_option"), dict) and i['extra_option'].get('secret'): - if not (g.user.username == "cmdb_agent" or g.user.uid == i['uid']): + if not (current_user.username == "cmdb_agent" or current_user.uid == i['uid']): i['extra_option'].pop('secret', None) else: i['extra_option']['secret'] = AESCrypto.decrypt(i['extra_option']['secret']) @@ -213,7 +213,7 @@ class AutoDiscoveryRuleSyncView(APIView): url_prefix = ("/adt/sync",) def get(self): - if g.user.username not in ("cmdb_agent", "worker", "admin"): + if current_user.username not in ("cmdb_agent", "worker", "admin"): return abort(403) oneagent_name = request.values.get('oneagent_name') diff --git a/cmdb-api/autoapp.py b/cmdb-api/autoapp.py index 9ff83cc..d16e79d 100644 --- a/cmdb-api/autoapp.py +++ b/cmdb-api/autoapp.py @@ -1,14 +1,7 @@ # -*- coding: utf-8 -*- """Create an application instance.""" -from flask import g -from flask_login import current_user from api.app import create_app app = create_app() - - -@app.before_request -def before_request(): - g.user = current_user diff --git a/cmdb-api/requirements.txt b/cmdb-api/requirements.txt index 14182ea..be049a2 100644 --- a/cmdb-api/requirements.txt +++ b/cmdb-api/requirements.txt @@ -2,7 +2,6 @@ alembic==1.7.7 amqp==2.6.1 aniso8601==9.0.1 -APScheduler==3.10.1 attrs==23.1.0 backports.zoneinfo==0.2.1 bcrypt==4.0.1 @@ -20,22 +19,22 @@ elasticsearch==7.17.9 email-validator==1.3.1 environs==4.2.0 flasgger==0.9.5 -Flask==1.0.3 -Flask-APScheduler==1.12.4 -Flask-Bcrypt==0.7.1 +Flask==2.3.2 +Flask-Bcrypt==1.0.1 Flask-Caching==2.0.2 Flask-Cors==4.0.0 -Flask-Login==0.4.1 +Flask-Login==0.6.2 Flask-Migrate==2.5.2 -Flask-RESTful==0.3.7 -Flask-SQLAlchemy==2.4.0 +Flask-RESTful==0.3.10 +Flask-SQLAlchemy==2.5.0 future==0.18.2 -gunicorn==19.5.0 +gunicorn==21.0.1 idna==3.4 importlib-metadata==6.8.0 -importlib-resources==6.0.0 -itsdangerous==2.0.1 -Jinja2==3.0.1 +importlib-resources= +=6.0.0 +itsdangerous==2.1.2 +Jinja2==3.1.2 jinja2schema==0.1.4 jsonschema==4.18.0 jsonschema-specifications==2023.6.1 @@ -47,13 +46,13 @@ meld3==2.0.1 mistune==3.0.1 more-itertools==5.0.0 msgpack-python==0.5.6 -Pillow==9.2.0 +Pillow==9.3.0 pkgutil_resolve_name==1.3.10 pyasn1==0.5.0 pyasn1-modules==0.3.0 pycryptodome==3.12.0 PyJWT==2.4.0 -PyMySQL==0.9.3 +PyMySQL==1.1.0 python-dateutil==2.8.2 python-dotenv==1.0.0 python-ldap==3.4.0 @@ -65,7 +64,7 @@ requests==2.31.0 rpds-py==0.8.8 six==1.12.0 soupsieve==2.4.1 -SQLAlchemy==1.3.5 +SQLAlchemy==1.4.49 supervisor==4.0.3 timeout-decorator==0.5.0 toposort==1.10 @@ -73,6 +72,6 @@ treelib==1.6.1 tzlocal==5.0.1 urllib3==1.26.16 vine==1.3.0 -Werkzeug==0.15.5 +Werkzeug==2.3.6 WTForms==3.0.0 zipp==3.16.0 \ No newline at end of file diff --git a/cmdb-api/settings.example.py b/cmdb-api/settings.example.py index 3f73517..fc22f59 100644 --- a/cmdb-api/settings.example.py +++ b/cmdb-api/settings.example.py @@ -76,6 +76,7 @@ DEFAULT_SERVICE = "http://127.0.0.1:8000" AUTH_WITH_LDAP = False LDAP_SERVER = '' LDAP_DOMAIN = '' +LDAP_USER_DN = 'cn={},ou=users,dc=xxx,dc=com' # # pagination DEFAULT_PAGE_COUNT = 50 diff --git a/cmdb-api/tests/sample.py b/cmdb-api/tests/sample.py index 4e7548b..5961ed1 100644 --- a/cmdb-api/tests/sample.py +++ b/cmdb-api/tests/sample.py @@ -3,6 +3,7 @@ import uuid import random + from api.models.cmdb import ( Attribute, CIType,