From 5e5ec3f88792401e8e33b6630ff15feec60bfb81 Mon Sep 17 00:00:00 2001 From: simontigers <47096077+simontigers@users.noreply.github.com> Date: Mon, 30 Oct 2023 17:35:34 +0800 Subject: [PATCH] style(common-setting): clean warning (#246) --- cmdb-api/api/commands/click_common_setting.py | 69 ++++----- cmdb-api/api/lib/common_setting/acl.py | 18 ++- cmdb-api/api/lib/common_setting/department.py | 137 +++++++++++++++++- cmdb-api/api/lib/common_setting/employee.py | 136 ++++++++++++++++- .../api/lib/common_setting/notice_config.py | 2 +- .../api/views/common_setting/common_data.py | 4 +- .../api/views/common_setting/company_info.py | 2 - cmdb-api/api/views/common_setting/employee.py | 4 +- .../api/views/common_setting/notice_config.py | 2 +- 9 files changed, 306 insertions(+), 68 deletions(-) diff --git a/cmdb-api/api/commands/click_common_setting.py b/cmdb-api/api/commands/click_common_setting.py index 775548f..a1f325e 100644 --- a/cmdb-api/api/commands/click_common_setting.py +++ b/cmdb-api/api/commands/click_common_setting.py @@ -10,9 +10,6 @@ from api.models.common_setting import Employee, Department class InitEmployee(object): - """ - 初始化员工 - """ def __init__(self): self.log = current_app.logger @@ -58,7 +55,8 @@ class InitEmployee(object): self.log.error(ErrFormat.acl_import_user_failed.format(user['username'], str(e))) self.log.error(e) - def get_rid_by_uid(self, uid): + @staticmethod + def get_rid_by_uid(uid): from api.models.acl import Role role = Role.get_by(first=True, uid=uid) return role['id'] if role is not None else 0 @@ -71,7 +69,8 @@ class InitDepartment(object): def init(self): self.init_wide_company() - def hard_delete(self, department_id, department_name): + @staticmethod + def hard_delete(department_id, department_name): existed_deleted_list = Department.query.filter( Department.department_name == department_name, Department.department_id == department_id, @@ -80,11 +79,12 @@ class InitDepartment(object): for existed in existed_deleted_list: existed.delete() - def get_department(self, department_name): + @staticmethod + def get_department(department_name): return Department.query.filter( Department.department_name == department_name, Department.deleted == 0, - ).order_by(Department.created_at.asc()).first() + ).first() def run(self, department_id, department_name, department_parent_id): self.hard_delete(department_id, department_name) @@ -94,7 +94,7 @@ class InitDepartment(object): if res.department_id == department_id: return else: - new_d = res.update( + res.update( department_id=department_id, department_parent_id=department_parent_id, ) @@ -108,11 +108,11 @@ class InitDepartment(object): new_d = self.get_department(department_name) if new_d.department_id != department_id: - new_d = new_d.update( + new_d.update( department_id=department_id, department_parent_id=department_parent_id, ) - self.log.info(f"初始化 {department_name} 部门成功.") + self.log.info(f"init {department_name} success.") def run_common(self, department_id, department_name, department_parent_id): try: @@ -123,19 +123,14 @@ class InitDepartment(object): raise Exception(e) def init_wide_company(self): - """ - 创建 id 0, name 全公司 的部门 - """ department_id = 0 department_name = '全公司' department_parent_id = -1 self.run_common(department_id, department_name, department_parent_id) - def create_acl_role_with_department(self): - """ - 当前所有部门,在ACL创建 role - """ + @staticmethod + def create_acl_role_with_department(): acl = ACLManager('acl') role_name_map = {role['name']: role for role in acl.get_all_roles()} @@ -146,7 +141,7 @@ class InitDepartment(object): continue role = role_name_map.get(department.department_name) - if role is None: + if not role: payload = { 'app_id': 'acl', 'name': department.department_name, @@ -208,25 +203,20 @@ class InitDepartment(object): if acl_rid > 0: acl.grant_resource(acl_rid, resource['id'], perms) - def check_app(self, app_name): + @staticmethod + def check_app(app_name): acl = ACLManager(app_name) payload = dict( name=app_name, description=app_name ) - try: - app = acl.validate_app() - if not app: - acl.create_app(payload) - return acl - except Exception as e: - current_app.logger.error(e) - if '不存在' in str(e): - acl.create_app(payload) - return acl - raise Exception(e) + app = acl.validate_app() + if not app: + acl.create_app(payload) + return acl - def get_admin_user_rid(self): + @staticmethod + def get_admin_user_rid(): admin = Employee.get_by(first=True, username='admin', to_dict=False) return admin.acl_rid if admin else 0 @@ -261,17 +251,19 @@ def common_check_new_columns(): from api.extensions import db from sqlalchemy import inspect, text - def get_model_by_table_name(table_name): - for model in db.Model.registry._class_registry.values(): - if hasattr(model, '__tablename__') and model.__tablename__ == table_name: - return model + def get_model_by_table_name(_table_name): + registry = getattr(db.Model, 'registry', None) + class_registry = getattr(registry, '_class_registry', None) + for _model in class_registry.values(): + if hasattr(_model, '__tablename__') and _model.__tablename__ == _table_name: + return _model return None - def add_new_column(table_name, new_column): + def add_new_column(target_table_name, new_column): column_type = new_column.type.compile(engine.dialect) default_value = new_column.default.arg if new_column.default else None - sql = f"ALTER TABLE {table_name} ADD COLUMN {new_column.name} {column_type} " + sql = "ALTER TABLE " + target_table_name + " ADD COLUMN " + new_column.name + " " + column_type if new_column.comment: sql += f" comment '{new_column.comment}'" @@ -297,7 +289,8 @@ def common_check_new_columns(): model = get_model_by_table_name(table_name) if model is None: continue - model_columns = model.__table__.columns._all_columns + + model_columns = getattr(getattr(getattr(model, '__table__'), 'columns'), '_all_columns') for column in model_columns: if column.name not in existed_column_name_list: try: diff --git a/cmdb-api/api/lib/common_setting/acl.py b/cmdb-api/api/lib/common_setting/acl.py index f705377..67774ce 100644 --- a/cmdb-api/api/lib/common_setting/acl.py +++ b/cmdb-api/api/lib/common_setting/acl.py @@ -80,20 +80,22 @@ class ACLManager(object): return role.to_dict() @staticmethod - def delete_role(_id, payload): + def delete_role(_id): RoleCRUD.delete_role(_id) return dict(rid=_id) def get_user_info(self, username): from api.lib.perm.acl.acl import ACLManager as ACL user_info = ACL().get_user_info(username, self.app_name) - result = dict(name=user_info.get('nickname') or username, - username=user_info.get('username') or username, - email=user_info.get('email'), - uid=user_info.get('uid'), - rid=user_info.get('rid'), - role=dict(permissions=user_info.get('parents')), - avatar=user_info.get('avatar')) + result = dict( + name=user_info.get('nickname') or username, + username=user_info.get('username') or username, + email=user_info.get('email'), + uid=user_info.get('uid'), + rid=user_info.get('rid'), + role=dict(permissions=user_info.get('parents')), + avatar=user_info.get('avatar') + ) return result diff --git a/cmdb-api/api/lib/common_setting/department.py b/cmdb-api/api/lib/common_setting/department.py index 8da3c58..f068b53 100644 --- a/cmdb-api/api/lib/common_setting/department.py +++ b/cmdb-api/api/lib/common_setting/department.py @@ -1,6 +1,6 @@ # -*- coding:utf-8 -*- -from flask import abort +from flask import abort, current_app from treelib import Tree from wtforms import Form from wtforms import IntegerField @@ -9,6 +9,7 @@ from wtforms import validators from api.extensions import db from api.lib.common_setting.resp_format import ErrFormat +from api.lib.common_setting.acl import ACLManager from api.lib.perm.acl.role import RoleCRUD from api.models.common_setting import Department, Employee @@ -152,6 +153,10 @@ class DepartmentForm(Form): class DepartmentCRUD(object): + @staticmethod + def get_department_by_id(d_id, to_dict=True): + return Department.get_by(first=True, department_id=d_id, to_dict=to_dict) + @staticmethod def add(**kwargs): DepartmentCRUD.check_department_name_unique(kwargs['department_name']) @@ -186,10 +191,11 @@ class DepartmentCRUD(object): filter(lambda d: d['department_id'] == department_parent_id, allow_p_d_id_list)) if len(target) == 0: try: - d = Department.get_by( + dep = Department.get_by( first=True, to_dict=False, department_id=department_parent_id) - name = d.department_name if d else ErrFormat.department_id_not_found.format(department_parent_id) + name = dep.department_name if dep else ErrFormat.department_id_not_found.format(department_parent_id) except Exception as e: + current_app.logger.error(str(e)) name = ErrFormat.department_id_not_found.format(department_parent_id) abort(400, ErrFormat.cannot_to_be_parent_department.format(name)) @@ -253,7 +259,7 @@ class DepartmentCRUD(object): try: RoleCRUD.delete_role(existed.acl_rid) except Exception as e: - pass + current_app.logger.error(str(e)) return existed.soft_delete() @@ -268,7 +274,7 @@ class DepartmentCRUD(object): try: tree.remove_subtree(department_id) except Exception as e: - pass + current_app.logger.error(str(e)) [allow_d_id_list.append({'department_id': int(n.identifier), 'department_name': n.tag}) for n in tree.all_nodes()] @@ -390,6 +396,125 @@ class DepartmentCRUD(object): [id_list.append(int(n.identifier)) for n in tmp_tree.all_nodes()] except Exception as e: - pass + current_app.logger.error(str(e)) return id_list + + +class EditDepartmentInACL(object): + + @staticmethod + def add_department_to_acl(department_id, op_uid): + db_department = DepartmentCRUD.get_department_by_id(department_id, to_dict=False) + if not db_department: + return + + from api.models.acl import Role + role = Role.get_by(first=True, name=db_department.department_name, app_id=None) + + acl = ACLManager('acl', str(op_uid)) + if role is None: + payload = { + 'app_id': 'acl', + 'name': db_department.department_name, + } + role = acl.create_role(payload) + + acl_rid = role.get('id') if role else 0 + + db_department.update( + acl_rid=acl_rid + ) + info = f"add_department_to_acl, acl_rid: {acl_rid}" + current_app.logger.info(info) + return info + + @staticmethod + def delete_department_from_acl(department_rids, op_uid): + acl = ACLManager('acl', str(op_uid)) + + result = [] + + for rid in department_rids: + try: + acl.delete_role(rid) + except Exception as e: + result.append(f"delete_department_in_acl, rid: {rid}, error: {e}") + continue + + return result + + @staticmethod + def edit_department_name_in_acl(d_rid: int, d_name: str, op_uid: int): + acl = ACLManager('acl', str(op_uid)) + payload = { + 'name': d_name + } + try: + acl.edit_role(d_rid, payload) + except Exception as e: + return f"edit_department_name_in_acl, rid: {d_rid}, error: {e}" + + return f"edit_department_name_in_acl, rid: {d_rid}, success" + + @staticmethod + def edit_employee_department_in_acl(e_list: list, new_d_id: int, op_uid: int): + result = [] + new_department = DepartmentCRUD.get_department_by_id(new_d_id, False) + if not new_department: + result.append(f"{new_d_id} new_department is None") + return result + + from api.models.acl import Role + new_role = Role.get_by(first=True, name=new_department.department_name, app_id=None) + new_d_rid_in_acl = new_role.get('id') if new_role else 0 + if new_d_rid_in_acl == 0: + return + + if new_d_rid_in_acl != new_department.acl_rid: + new_department.update( + acl_rid=new_d_rid_in_acl + ) + new_department_acl_rid = new_department.acl_rid if new_d_rid_in_acl == new_department.acl_rid else \ + new_d_rid_in_acl + + acl = ACLManager('acl', str(op_uid)) + for employee in e_list: + old_department = DepartmentCRUD.get_department_by_id(employee.get('department_id'), False) + if not old_department: + continue + employee_acl_rid = employee.get('e_acl_rid') + if employee_acl_rid == 0: + result.append(f"employee_acl_rid == 0") + continue + + old_role = Role.get_by(first=True, name=old_department.department_name, app_id=None) + old_d_rid_in_acl = old_role.get('id') if old_role else 0 + if old_d_rid_in_acl == 0: + return + if old_d_rid_in_acl != old_department.acl_rid: + old_department.update( + acl_rid=old_d_rid_in_acl + ) + d_acl_rid = old_department.acl_rid if old_d_rid_in_acl == old_department.acl_rid else old_d_rid_in_acl + payload = { + 'app_id': 'acl', + 'parent_id': d_acl_rid, + } + try: + acl.remove_user_from_role(employee_acl_rid, payload) + except Exception as e: + result.append( + f"remove_user_from_role employee_acl_rid: {employee_acl_rid}, parent_id: {d_acl_rid}, err: {e}") + + payload = { + 'app_id': 'acl', + 'child_ids': [employee_acl_rid], + } + try: + acl.add_user_to_role(new_department_acl_rid, payload) + except Exception as e: + result.append( + f"add_user_to_role employee_acl_rid: {employee_acl_rid}, parent_id: {d_acl_rid}, err: {e}") + + return result diff --git a/cmdb-api/api/lib/common_setting/employee.py b/cmdb-api/api/lib/common_setting/employee.py index 19d7f6d..cb75d4c 100644 --- a/cmdb-api/api/lib/common_setting/employee.py +++ b/cmdb-api/api/lib/common_setting/employee.py @@ -178,7 +178,7 @@ class EmployeeCRUD(object): def edit_employee_by_uid(_uid, **kwargs): existed = EmployeeCRUD.get_employee_by_uid(_uid) try: - user = edit_acl_user(_uid, **kwargs) + edit_acl_user(_uid, **kwargs) for column in employee_pop_columns: if kwargs.get(column): @@ -190,9 +190,9 @@ class EmployeeCRUD(object): @staticmethod def change_password_by_uid(_uid, password): - existed = EmployeeCRUD.get_employee_by_uid(_uid) + EmployeeCRUD.get_employee_by_uid(_uid) try: - user = edit_acl_user(_uid, password=password) + edit_acl_user(_uid, password=password) except Exception as e: return abort(400, str(e)) @@ -359,9 +359,11 @@ class EmployeeCRUD(object): if value and column == "last_login": try: - value = datetime.strptime(value, "%Y-%m-%d %H:%M:%S") + return datetime.strptime(value, "%Y-%m-%d %H:%M:%S") except Exception as e: - abort(400, ErrFormat.datetime_format_error.format(column)) + err = f"{ErrFormat.datetime_format_error.format(column)}: {str(e)}" + abort(400, err) + return value @staticmethod def get_attr_by_column(column): @@ -382,7 +384,7 @@ class EmployeeCRUD(object): relation = condition.get("relation", None) value = condition.get("value", None) - EmployeeCRUD.check_condition(column, operator, value, relation) + value = EmployeeCRUD.check_condition(column, operator, value, relation) a, o = EmployeeCRUD.get_expr_by_condition( column, operator, value, relation) and_list += a @@ -565,6 +567,125 @@ class EmployeeCRUD(object): results.append(tmp) return results + @staticmethod + def import_employee(employee_list): + res = CreateEmployee().batch_create(employee_list) + return res + + @staticmethod + def batch_edit_employee_department(employee_id_list, column_value): + err_list = [] + employee_list = [] + for _id in employee_id_list: + try: + existed = EmployeeCRUD.get_employee_by_id(_id) + employee = dict( + e_acl_rid=existed.acl_rid, + department_id=existed.department_id + ) + employee_list.append(employee) + existed.update(department_id=column_value) + + except Exception as e: + err_list.append({ + 'employee_id': _id, + 'err': str(e), + }) + from api.lib.common_setting.department import EditDepartmentInACL + EditDepartmentInACL.edit_employee_department_in_acl( + employee_list, column_value, current_user.uid + ) + return err_list + + @staticmethod + def batch_edit_password_or_block_column(column_name, employee_id_list, column_value, is_acl=False): + if column_name == 'block': + err_list = [] + success_list = [] + for _id in employee_id_list: + try: + employee = EmployeeCRUD.edit_employee_block_column( + _id, is_acl, **{column_name: column_value}) + success_list.append(employee) + except Exception as e: + err_list.append({ + 'employee_id': _id, + 'err': str(e), + }) + return err_list + else: + return EmployeeCRUD.batch_edit_column(column_name, employee_id_list, column_value, is_acl) + + @staticmethod + def batch_edit_column(column_name, employee_id_list, column_value, is_acl=False): + err_list = [] + for _id in employee_id_list: + try: + EmployeeCRUD.edit_employee_single_column( + _id, is_acl, **{column_name: column_value}) + except Exception as e: + err_list.append({ + 'employee_id': _id, + 'err': str(e), + }) + + return err_list + + @staticmethod + def edit_employee_single_column(_id, is_acl=False, **kwargs): + existed = EmployeeCRUD.get_employee_by_id(_id) + if 'direct_supervisor_id' in kwargs.keys(): + if kwargs['direct_supervisor_id'] == existed.direct_supervisor_id: + raise Exception(ErrFormat.direct_supervisor_is_not_self) + + if is_acl: + return edit_acl_user(existed.acl_uid, **kwargs) + + try: + for column in employee_pop_columns: + if kwargs.get(column): + kwargs.pop(column) + + return existed.update(**kwargs) + except Exception as e: + return abort(400, str(e)) + + @staticmethod + def edit_employee_block_column(_id, is_acl=False, **kwargs): + existed = EmployeeCRUD.get_employee_by_id(_id) + value = get_block_value(kwargs.get('block')) + if value is True: + check_department_director_id_or_direct_supervisor_id(_id) + value = 1 + else: + value = 0 + + if is_acl: + kwargs['block'] = value + edit_acl_user(existed.acl_uid, **kwargs) + + existed.update(block=value) + data = existed.to_dict() + return data + + @staticmethod + def batch_employee(column_name, column_value, employee_id_list): + if column_value is None: + abort(400, ErrFormat.value_is_required) + if column_name in ['password', 'block']: + return EmployeeCRUD.batch_edit_password_or_block_column(column_name, employee_id_list, column_value, True) + + elif column_name in ['department_id']: + return EmployeeCRUD.batch_edit_employee_department(employee_id_list, column_value) + + elif column_name in [ + 'direct_supervisor_id', 'position_name' + ]: + return EmployeeCRUD.batch_edit_column(column_name, employee_id_list, column_value, False) + + else: + abort(400, ErrFormat.column_name_not_support) + def get_user_map(key='uid', acl=None): """ @@ -641,7 +762,8 @@ class CreateEmployee(object): **kwargs ) - def get_department_by_name(self, d_name): + @staticmethod + def get_department_by_name(d_name): return Department.get_by(first=True, department_name=d_name) def get_end_department_id(self, department_name_list, department_name_map): diff --git a/cmdb-api/api/lib/common_setting/notice_config.py b/cmdb-api/api/lib/common_setting/notice_config.py index 569ac35..152eb53 100644 --- a/cmdb-api/api/lib/common_setting/notice_config.py +++ b/cmdb-api/api/lib/common_setting/notice_config.py @@ -162,4 +162,4 @@ class NoticeConfigUpdateForm(Form): info = StringField(validators=[ validators.DataRequired(message="信息 不能为空"), validators.Length(max=255), - ]) \ No newline at end of file + ]) diff --git a/cmdb-api/api/views/common_setting/common_data.py b/cmdb-api/api/views/common_setting/common_data.py index 6d44ba1..3793a5e 100644 --- a/cmdb-api/api/views/common_setting/common_data.py +++ b/cmdb-api/api/views/common_setting/common_data.py @@ -24,12 +24,12 @@ class DataView(APIView): class DataViewWithId(APIView): url_prefix = (f'{prefix}//',) - def put(self, data_type, _id): + def put(self, _id): params = request.json res = CommonDataCRUD.update_data(_id, **params) return self.jsonify(res.to_dict()) - def delete(self, data_type, _id): + def delete(self, _id): CommonDataCRUD.delete(_id) return self.jsonify({}) diff --git a/cmdb-api/api/views/common_setting/company_info.py b/cmdb-api/api/views/common_setting/company_info.py index d027a9e..4298cfd 100644 --- a/cmdb-api/api/views/common_setting/company_info.py +++ b/cmdb-api/api/views/common_setting/company_info.py @@ -1,9 +1,7 @@ # -*- coding:utf-8 -*- -from flask import abort from flask import request from api.lib.common_setting.company_info import CompanyInfoCRUD -from api.lib.common_setting.resp_format import ErrFormat from api.resource import APIView prefix = '/company' diff --git a/cmdb-api/api/views/common_setting/employee.py b/cmdb-api/api/views/common_setting/employee.py index e31ee59..173dc13 100644 --- a/cmdb-api/api/views/common_setting/employee.py +++ b/cmdb-api/api/views/common_setting/employee.py @@ -1,7 +1,5 @@ # -*- coding:utf-8 -*- -import os - -from flask import abort, current_app, send_from_directory +from flask import abort from flask import request from werkzeug.datastructures import MultiDict diff --git a/cmdb-api/api/views/common_setting/notice_config.py b/cmdb-api/api/views/common_setting/notice_config.py index 49273cf..e5dea63 100644 --- a/cmdb-api/api/views/common_setting/notice_config.py +++ b/cmdb-api/api/views/common_setting/notice_config.py @@ -47,7 +47,7 @@ class CheckEmailServer(APIView): def post(self): receive_address = request.args.get('receive_address') - info = request.values.get('info') + info = request.values.get('info', {}) try: