mirror of https://github.com/veops/cmdb.git
975 lines
32 KiB
Python
975 lines
32 KiB
Python
# -*- coding:utf-8 -*-
|
|
import copy
|
|
import traceback
|
|
from datetime import datetime
|
|
|
|
import requests
|
|
from flask import abort, current_app
|
|
from flask_login import current_user
|
|
from sqlalchemy import or_, literal_column, func, not_, and_
|
|
from werkzeug.datastructures import MultiDict
|
|
from wtforms import Form
|
|
from wtforms import IntegerField
|
|
from wtforms import StringField
|
|
from wtforms import validators
|
|
|
|
from api.extensions import db
|
|
from api.lib.common_setting.acl import ACLManager
|
|
from api.lib.common_setting.const import OperatorType
|
|
from api.lib.perm.acl.const import ACL_QUEUE
|
|
from api.lib.common_setting.resp_format import ErrFormat
|
|
from api.models.common_setting import Employee, Department
|
|
|
|
from api.tasks.common_setting import refresh_employee_acl_info, edit_employee_department_in_acl
|
|
|
|
acl_user_columns = [
|
|
'email',
|
|
'mobile',
|
|
'nickname',
|
|
'username',
|
|
'password',
|
|
'block',
|
|
'avatar',
|
|
]
|
|
employee_pop_columns = ['password']
|
|
can_not_edit_columns = ['email']
|
|
|
|
|
|
def edit_acl_user(uid, **kwargs):
|
|
user_data = {column: kwargs.get(
|
|
column, '') for column in acl_user_columns if kwargs.get(column, '')}
|
|
if 'block' in kwargs:
|
|
user_data['block'] = kwargs.get('block')
|
|
try:
|
|
acl = ACLManager()
|
|
return acl.edit_user(uid, user_data)
|
|
except Exception as e:
|
|
abort(400, ErrFormat.acl_edit_user_failed.format(str(e)))
|
|
|
|
|
|
def get_block_value(value):
|
|
if value in ['False', 'false', '0', 0]:
|
|
value = False
|
|
else:
|
|
value = True
|
|
|
|
return value
|
|
|
|
|
|
def get_employee_list_by_direct_supervisor_id(direct_supervisor_id):
|
|
return Employee.get_by(direct_supervisor_id=direct_supervisor_id)
|
|
|
|
|
|
def get_department_list_by_director_id(director_id):
|
|
return Department.get_by(department_director_id=director_id)
|
|
|
|
|
|
def raise_exception(err):
|
|
raise Exception(err)
|
|
|
|
|
|
def check_department_director_id_or_direct_supervisor_id(_id):
|
|
get_employee_list_by_direct_supervisor_id(
|
|
_id) and raise_exception(ErrFormat.cannot_block_this_employee_is_other_direct_supervisor)
|
|
get_department_list_by_director_id(
|
|
_id) and raise_exception(ErrFormat.cannot_block_this_employee_is_department_manager)
|
|
|
|
|
|
class EmployeeCRUD(object):
|
|
@staticmethod
|
|
def get_employee_by_id(_id):
|
|
return Employee.get_by(
|
|
first=True, to_dict=False, deleted=0, employee_id=_id
|
|
) or abort(404, ErrFormat.employee_id_not_found.format(_id))
|
|
|
|
@staticmethod
|
|
def get_employee_by_uid_with_create(_uid):
|
|
try:
|
|
return EmployeeCRUD.get_employee_by_uid(_uid).to_dict()
|
|
except Exception as e:
|
|
if '不存在' not in str(e):
|
|
abort(400, str(e))
|
|
|
|
try:
|
|
acl = ACLManager('acl')
|
|
user_info = acl.get_user_info(_uid)
|
|
return EmployeeCRUD.check_acl_user_and_create(user_info)
|
|
|
|
except Exception as e:
|
|
abort(400, str(e))
|
|
|
|
@staticmethod
|
|
def get_employee_by_uid(_uid):
|
|
return Employee.get_by(
|
|
first=True, to_dict=False, deleted=0, acl_uid=_uid
|
|
) or abort(404, ErrFormat.acl_uid_not_found.format(_uid))
|
|
|
|
@staticmethod
|
|
def check_acl_user_and_create(user_info):
|
|
existed = Employee.get_by(
|
|
first=True, to_dict=False, username=user_info['username'])
|
|
if existed:
|
|
existed.update(
|
|
acl_uid=user_info['uid'],
|
|
)
|
|
return existed.to_dict()
|
|
if not user_info.get('nickname', None):
|
|
user_info['nickname'] = user_info['name']
|
|
|
|
form = EmployeeAddForm(MultiDict(user_info))
|
|
data = form.data
|
|
data['password'] = ''
|
|
data['acl_uid'] = user_info['uid']
|
|
|
|
employee = CreateEmployee().create_single(**data)
|
|
return employee.to_dict()
|
|
|
|
@staticmethod
|
|
def add_employee_from_acl_created(**kwargs):
|
|
try:
|
|
kwargs['acl_uid'] = kwargs.pop('uid')
|
|
kwargs['acl_rid'] = kwargs.pop('rid')
|
|
kwargs['department_id'] = 0
|
|
|
|
Employee.create(
|
|
**kwargs
|
|
)
|
|
except Exception as e:
|
|
abort(400, str(e))
|
|
|
|
@staticmethod
|
|
def add(**kwargs):
|
|
try:
|
|
res = CreateEmployee().create_single(**kwargs)
|
|
refresh_employee_acl_info.apply_async(args=(res.employee_id,), queue=ACL_QUEUE)
|
|
return res
|
|
except Exception as e:
|
|
abort(400, str(e))
|
|
|
|
@staticmethod
|
|
def update(_id, **kwargs):
|
|
EmployeeCRUD.check_email_unique(kwargs['email'], _id)
|
|
|
|
existed = EmployeeCRUD.get_employee_by_id(_id)
|
|
|
|
try:
|
|
edit_acl_user(existed.acl_uid, **kwargs)
|
|
|
|
for column in employee_pop_columns:
|
|
kwargs.pop(column, None)
|
|
|
|
new_department_id = kwargs.get('department_id', None)
|
|
e_list = []
|
|
if new_department_id is not None and new_department_id != existed.department_id:
|
|
e_list = [dict(
|
|
e_acl_rid=existed.acl_rid,
|
|
department_id=existed.department_id
|
|
)]
|
|
|
|
existed.update(**kwargs)
|
|
|
|
if len(e_list) > 0:
|
|
edit_employee_department_in_acl.apply_async(
|
|
args=(e_list, new_department_id, current_user.uid),
|
|
queue=ACL_QUEUE
|
|
)
|
|
|
|
return existed
|
|
except Exception as e:
|
|
return abort(400, str(e))
|
|
|
|
@staticmethod
|
|
def edit_employee_by_uid(_uid, **kwargs):
|
|
existed = EmployeeCRUD.get_employee_by_uid(_uid)
|
|
try:
|
|
edit_acl_user(_uid, **kwargs)
|
|
|
|
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 change_password_by_uid(_uid, password):
|
|
EmployeeCRUD.get_employee_by_uid(_uid)
|
|
try:
|
|
edit_acl_user(_uid, password=password)
|
|
except Exception as e:
|
|
return abort(400, str(e))
|
|
|
|
@staticmethod
|
|
def get_all_position():
|
|
criterion = [
|
|
Employee.deleted == 0,
|
|
]
|
|
results = Employee.query.with_entities(
|
|
Employee.position_name
|
|
).filter(*criterion).group_by(
|
|
Employee.position_name
|
|
).order_by(
|
|
func.CONVERT(literal_column('position_name using gbk'))
|
|
).all()
|
|
|
|
return [item[0] for item in results if (item[0] is not None and item[0] != '')]
|
|
|
|
@staticmethod
|
|
def get_employee_count(block_status):
|
|
criterion = [
|
|
Employee.deleted == 0
|
|
]
|
|
|
|
if block_status >= 0:
|
|
criterion.append(
|
|
Employee.block == block_status
|
|
)
|
|
|
|
return Employee.query.filter(
|
|
*criterion
|
|
).count()
|
|
|
|
@staticmethod
|
|
def check_email_unique(email, _id=0):
|
|
criterion = [
|
|
Employee.email == email,
|
|
Employee.deleted == 0,
|
|
]
|
|
if _id > 0:
|
|
criterion.append(
|
|
Employee.employee_id != _id
|
|
)
|
|
res = Employee.query.filter(
|
|
*criterion
|
|
).all()
|
|
|
|
if res:
|
|
err = ErrFormat.email_already_exists.format(email)
|
|
raise Exception(err)
|
|
|
|
@staticmethod
|
|
def get_employee_list_by_body(department_id, block_status, search='', order='', conditions=None, page=1,
|
|
page_size=10):
|
|
criterion = [
|
|
Employee.deleted == 0
|
|
]
|
|
|
|
if block_status >= 0:
|
|
criterion.append(
|
|
Employee.block == block_status
|
|
)
|
|
|
|
if len(search) > 0:
|
|
search_key = f"%{search}%"
|
|
criterion.append(
|
|
or_(
|
|
Employee.email.like(search_key),
|
|
Employee.username.like(search_key),
|
|
Employee.nickname.like(search_key)
|
|
)
|
|
)
|
|
|
|
if department_id > 0:
|
|
from api.lib.common_setting.department import DepartmentCRUD
|
|
department_id_list = DepartmentCRUD.get_department_id_list_by_root(
|
|
department_id)
|
|
criterion.append(
|
|
Employee.department_id.in_(department_id_list)
|
|
)
|
|
|
|
if conditions:
|
|
query = EmployeeCRUD.parse_condition_list_to_query(conditions).filter(
|
|
*criterion
|
|
)
|
|
else:
|
|
query = db.session.query(Employee, Department).outerjoin(Department).filter(
|
|
*criterion
|
|
)
|
|
|
|
if len(order) > 0:
|
|
query = EmployeeCRUD.format_query_sort(query, order)
|
|
|
|
pagination = query.paginate(page=page, per_page=page_size)
|
|
|
|
employees = []
|
|
for r in pagination.items:
|
|
d = r.Employee.to_dict()
|
|
d['department_name'] = r.Department.department_name if r.Department else ''
|
|
if r.Employee.department_id == 0:
|
|
d['department_name'] = ErrFormat.company_wide
|
|
employees.append(d)
|
|
|
|
return {
|
|
'data_list': employees,
|
|
'page': page,
|
|
'page_size': page_size,
|
|
'total': pagination.total,
|
|
}
|
|
|
|
@staticmethod
|
|
def parse_condition_list_to_query(condition_list):
|
|
query = db.session.query(Employee, Department).outerjoin(Department)
|
|
|
|
query = EmployeeCRUD.get_query_by_conditions(query, condition_list)
|
|
return query
|
|
|
|
@staticmethod
|
|
def get_expr_by_condition(column, operator, value, relation):
|
|
"""
|
|
get expr: (and_list, or_list)
|
|
"""
|
|
attr = EmployeeCRUD.get_attr_by_column(column)
|
|
# 根据operator生成条件表达式
|
|
if operator == OperatorType.EQUAL:
|
|
expr = [attr == value]
|
|
elif operator == OperatorType.NOT_EQUAL:
|
|
expr = [attr != value]
|
|
elif operator == OperatorType.IN:
|
|
expr = [attr.like('%{}%'.format(value))]
|
|
elif operator == OperatorType.NOT_IN:
|
|
expr = [not_(attr.like('%{}%'.format(value)))]
|
|
elif operator == OperatorType.GREATER_THAN:
|
|
expr = [attr > value]
|
|
elif operator == OperatorType.LESS_THAN:
|
|
expr = [attr < value]
|
|
elif operator == OperatorType.IS_EMPTY:
|
|
if value:
|
|
abort(400, ErrFormat.query_column_none_keep_value_empty.format(column))
|
|
expr = [attr.is_(None)]
|
|
if column not in ["last_login"]:
|
|
expr += [attr == '']
|
|
expr = [or_(*expr)]
|
|
elif operator == OperatorType.IS_NOT_EMPTY:
|
|
if value:
|
|
abort(400, ErrFormat.query_column_none_keep_value_empty.format(column))
|
|
|
|
expr = [attr.isnot(None)]
|
|
if column not in ["last_login"]:
|
|
expr += [attr != '']
|
|
expr = [and_(*expr)]
|
|
else:
|
|
abort(400, ErrFormat.not_support_operator.format(operator))
|
|
|
|
if relation == "&":
|
|
return expr, []
|
|
elif relation == "|":
|
|
return [], expr
|
|
else:
|
|
return abort(400, ErrFormat.not_support_relation.format(relation))
|
|
|
|
@staticmethod
|
|
def check_condition(column, operator, value, relation):
|
|
if column is None or operator is None or relation is None:
|
|
return abort(400, ErrFormat.conditions_field_missing)
|
|
|
|
if value and column == "last_login":
|
|
try:
|
|
return datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
|
except Exception as e:
|
|
err = f"{ErrFormat.datetime_format_error.format(column)}: {str(e)}"
|
|
abort(400, err)
|
|
return value
|
|
|
|
@staticmethod
|
|
def get_attr_by_column(column):
|
|
if 'department' in column:
|
|
attr = Department.__dict__[column]
|
|
else:
|
|
attr = Employee.__dict__[column]
|
|
return attr
|
|
|
|
@staticmethod
|
|
def get_query_by_conditions(query, conditions):
|
|
and_list = []
|
|
or_list = []
|
|
|
|
for condition in conditions:
|
|
operator = condition.get("operator", None)
|
|
column = condition.get("column", None)
|
|
relation = condition.get("relation", None)
|
|
value = condition.get("value", None)
|
|
|
|
value = EmployeeCRUD.check_condition(column, operator, value, relation)
|
|
a, o = EmployeeCRUD.get_expr_by_condition(
|
|
column, operator, value, relation)
|
|
and_list += a
|
|
or_list += o
|
|
|
|
query = query.filter(
|
|
Employee.deleted == 0,
|
|
or_(and_(*and_list), *or_list)
|
|
)
|
|
|
|
return query
|
|
|
|
@staticmethod
|
|
def get_employee_list_by(department_id, block_status, search='', order='', page=1, page_size=10):
|
|
criterion = [
|
|
Employee.deleted == 0
|
|
]
|
|
|
|
if block_status >= 0:
|
|
criterion.append(
|
|
Employee.block == block_status
|
|
)
|
|
|
|
if len(search) > 0:
|
|
search_key = f"%{search}%"
|
|
criterion.append(
|
|
or_(
|
|
Employee.email.like(search_key),
|
|
Employee.username.like(search_key),
|
|
Employee.nickname.like(search_key)
|
|
)
|
|
)
|
|
|
|
if department_id > 0:
|
|
from api.lib.common_setting.department import DepartmentCRUD
|
|
department_id_list = DepartmentCRUD.get_department_id_list_by_root(
|
|
department_id)
|
|
criterion.append(
|
|
Employee.department_id.in_(department_id_list)
|
|
)
|
|
|
|
query = db.session.query(Employee, Department).outerjoin(Department).filter(
|
|
*criterion
|
|
)
|
|
|
|
if len(order) > 0:
|
|
query = EmployeeCRUD.format_query_sort(query, order)
|
|
|
|
pagination = query.paginate(page=page, per_page=page_size)
|
|
employees = []
|
|
for r in pagination.items:
|
|
d = r.Employee.to_dict()
|
|
d['department_name'] = r.Department.department_name if r.Department else ''
|
|
employees.append(d)
|
|
|
|
return {
|
|
'data_list': employees,
|
|
'page': page,
|
|
'page_size': page_size,
|
|
'total': pagination.total,
|
|
}
|
|
|
|
@staticmethod
|
|
def format_query_sort(query, order):
|
|
order_list = order.split(',')
|
|
all_columns = Employee.get_columns()
|
|
|
|
for order_column in order_list:
|
|
if order_column.startswith('-'):
|
|
target_column = order_column[1:]
|
|
if target_column not in all_columns:
|
|
continue
|
|
query = query.order_by(getattr(Employee, target_column).desc())
|
|
else:
|
|
if order_column not in all_columns:
|
|
continue
|
|
|
|
query = query.order_by(getattr(Employee, order_column).asc())
|
|
|
|
return query
|
|
|
|
@staticmethod
|
|
def get_employees_by_department_id(department_id, block):
|
|
criterion = [
|
|
Employee.deleted == 0,
|
|
Employee.block == block,
|
|
]
|
|
if isinstance(department_id, list):
|
|
if len(department_id) == 0:
|
|
return []
|
|
else:
|
|
criterion.append(
|
|
Employee.department_id.in_(department_id)
|
|
)
|
|
else:
|
|
criterion.append(
|
|
Employee.department_id == department_id
|
|
)
|
|
|
|
results = Employee.query.filter(
|
|
*criterion
|
|
).all()
|
|
|
|
return [r.to_dict() for r in results]
|
|
|
|
@staticmethod
|
|
def remove_bind_notice_by_uid(_platform, _uid):
|
|
existed = EmployeeCRUD.get_employee_by_uid(_uid)
|
|
employee_data = existed.to_dict()
|
|
|
|
notice_info = employee_data.get('notice_info', {})
|
|
notice_info = copy.deepcopy(notice_info) if notice_info else {}
|
|
|
|
notice_info[_platform] = ''
|
|
|
|
existed.update(
|
|
notice_info=notice_info
|
|
)
|
|
return ErrFormat.notice_remove_bind_success
|
|
|
|
@staticmethod
|
|
def bind_notice_by_uid(_platform, _uid):
|
|
existed = EmployeeCRUD.get_employee_by_uid(_uid)
|
|
mobile = existed.mobile
|
|
if not mobile or len(mobile) == 0:
|
|
abort(400, ErrFormat.notice_bind_err_with_empty_mobile)
|
|
|
|
from api.lib.common_setting.notice_config import NoticeConfigCRUD
|
|
messenger = NoticeConfigCRUD.get_messenger_url()
|
|
if not messenger or len(messenger) == 0:
|
|
abort(400, ErrFormat.notice_please_config_messenger_first)
|
|
|
|
url = f"{messenger}/v1/uid/getbyphone"
|
|
try:
|
|
payload = dict(
|
|
phone=mobile,
|
|
sender=_platform
|
|
)
|
|
res = requests.post(url, json=payload)
|
|
result = res.json()
|
|
if res.status_code != 200:
|
|
raise Exception(result.get('msg', ''))
|
|
target_id = result.get('uid', '')
|
|
|
|
employee_data = existed.to_dict()
|
|
|
|
notice_info = employee_data.get('notice_info', {})
|
|
notice_info = copy.deepcopy(notice_info) if notice_info else {}
|
|
|
|
notice_info[_platform] = '' if not target_id else target_id
|
|
|
|
existed.update(
|
|
notice_info=notice_info
|
|
)
|
|
return ErrFormat.notice_bind_success
|
|
|
|
except Exception as e:
|
|
return abort(400, ErrFormat.notice_bind_failed.format(str(e)))
|
|
|
|
@staticmethod
|
|
def get_employee_notice_by_ids(employee_ids):
|
|
criterion = [
|
|
Employee.employee_id.in_(employee_ids),
|
|
Employee.deleted == 0,
|
|
]
|
|
direct_columns = ['email', 'mobile']
|
|
employees = Employee.query.filter(
|
|
*criterion
|
|
).all()
|
|
results = []
|
|
for employee in employees:
|
|
d = employee.to_dict()
|
|
tmp = dict(
|
|
employee_id=employee.employee_id,
|
|
)
|
|
for column in direct_columns:
|
|
tmp[column] = d.get(column, '')
|
|
notice_info = d.get('notice_info', {})
|
|
notice_info = copy.deepcopy(notice_info) if notice_info else {}
|
|
tmp.update(**notice_info)
|
|
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)
|
|
|
|
@staticmethod
|
|
def update_last_login_by_uid(uid, last_login=None):
|
|
employee = Employee.get_by(acl_uid=uid, first=True, to_dict=False)
|
|
if not employee:
|
|
return
|
|
if last_login:
|
|
try:
|
|
last_login = datetime.strptime(last_login, '%Y-%m-%d %H:%M:%S')
|
|
except Exception as e:
|
|
current_app.logger.error(f"strptime {last_login} err: {e}")
|
|
last_login = datetime.now()
|
|
else:
|
|
last_login = datetime.now()
|
|
|
|
try:
|
|
employee.update(
|
|
last_login=last_login
|
|
)
|
|
return last_login
|
|
except Exception as e:
|
|
current_app.logger.error(f"update last_login err: {e}")
|
|
return
|
|
|
|
|
|
def get_user_map(key='uid', acl=None):
|
|
"""
|
|
{
|
|
uid: userinfo
|
|
}
|
|
"""
|
|
if acl is None:
|
|
acl = ACLManager()
|
|
data = {user[key]: user for user in acl.get_all_users()}
|
|
|
|
return data
|
|
|
|
|
|
def format_params(params):
|
|
for k in ['_key', '_secret']:
|
|
params.pop(k, None)
|
|
return params
|
|
|
|
|
|
class CreateEmployee(object):
|
|
def __init__(self):
|
|
self.acl = ACLManager()
|
|
self.all_acl_users = self.acl.get_all_users()
|
|
|
|
def check_acl_user(self, user_data):
|
|
target_email = list(filter(lambda x: x['email'] == user_data['email'], self.all_acl_users))
|
|
if target_email:
|
|
return target_email[0]
|
|
|
|
target_username = list(filter(lambda x: x['username'] == user_data['username'], self.all_acl_users))
|
|
if target_username:
|
|
return target_username[0]
|
|
|
|
def add_acl_user(self, **kwargs):
|
|
user_data = {column: kwargs.get(
|
|
column, '') for column in acl_user_columns if kwargs.get(column, '')}
|
|
try:
|
|
existed = self.check_acl_user(user_data)
|
|
if not existed:
|
|
user_data['add_from'] = 'common'
|
|
return self.acl.create_user(user_data)
|
|
return existed
|
|
except Exception as e:
|
|
abort(400, ErrFormat.acl_add_user_failed.format(str(e)))
|
|
|
|
def create_single(self, **kwargs):
|
|
EmployeeCRUD.check_email_unique(kwargs['email'])
|
|
user = self.add_acl_user(**kwargs)
|
|
kwargs['acl_uid'] = user['uid']
|
|
kwargs['last_login'] = user['last_login']
|
|
|
|
for column in employee_pop_columns:
|
|
kwargs.pop(column)
|
|
|
|
return Employee.create(
|
|
**kwargs
|
|
)
|
|
|
|
def create_single_with_import(self, **kwargs):
|
|
user = self.add_acl_user(**kwargs)
|
|
kwargs['acl_uid'] = user['uid']
|
|
kwargs['last_login'] = user['last_login']
|
|
|
|
for column in employee_pop_columns:
|
|
kwargs.pop(column)
|
|
|
|
existed = Employee.get_by(
|
|
first=True, to_dict=False, deleted=0, acl_uid=user['uid']
|
|
)
|
|
if existed:
|
|
return existed
|
|
|
|
res = Employee.create(
|
|
**kwargs
|
|
)
|
|
refresh_employee_acl_info.apply_async(args=(res.employee_id,), queue=ACL_QUEUE)
|
|
return res
|
|
|
|
@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):
|
|
parent_id = 0
|
|
|
|
end_d_id = 0
|
|
for d_name in department_name_list:
|
|
tmp_d = self.get_department_by_name(d_name)
|
|
if not tmp_d:
|
|
tmp_d = Department.create(
|
|
department_name=d_name, department_parent_id=parent_id).to_dict()
|
|
else:
|
|
if tmp_d['department_parent_id'] != parent_id:
|
|
department_name_map[d_name] = tmp_d
|
|
raise Exception(ErrFormat.department_level_relation_error)
|
|
|
|
department_name_map[d_name] = tmp_d
|
|
|
|
end_d_id = tmp_d['department_id']
|
|
parent_id = tmp_d['department_id']
|
|
|
|
return end_d_id
|
|
|
|
def format_department_id(self, employee):
|
|
department_name_map = {}
|
|
try:
|
|
department_name = employee.get('department_name', '')
|
|
if len(department_name) == 0:
|
|
return employee
|
|
department_name_list = department_name.split('/')
|
|
employee['department_id'] = self.get_end_department_id(
|
|
department_name_list, department_name_map)
|
|
|
|
except Exception as e:
|
|
employee['err'] = str(e)
|
|
|
|
return employee
|
|
|
|
def batch_create(self, employee_list):
|
|
err_list = []
|
|
|
|
for employee in employee_list:
|
|
try:
|
|
username = employee.get('username', None)
|
|
if username is None:
|
|
employee['username'] = employee['email']
|
|
|
|
employee = self.format_department_id(employee)
|
|
err = employee.get('err', None)
|
|
if err:
|
|
raise Exception(err)
|
|
|
|
params = format_params(employee)
|
|
form = EmployeeAddForm(MultiDict(params))
|
|
if not form.validate():
|
|
raise Exception(
|
|
','.join(['{}: {}'.format(filed, ','.join(msg)) for filed, msg in form.errors.items()]))
|
|
|
|
self.create_single_with_import(**form.data)
|
|
except Exception as e:
|
|
err_list.append({
|
|
'email': employee.get('email', ''),
|
|
'nickname': employee.get('nickname', ''),
|
|
'err': str(e),
|
|
})
|
|
traceback.print_exc()
|
|
|
|
return err_list
|
|
|
|
|
|
class EmployeeAddForm(Form):
|
|
username = StringField(validators=[
|
|
validators.DataRequired(message=ErrFormat.username_is_required),
|
|
validators.Length(max=255),
|
|
])
|
|
email = StringField(validators=[
|
|
validators.DataRequired(message=ErrFormat.email_is_required),
|
|
validators.Email(message=ErrFormat.email_format_error),
|
|
validators.Length(max=255),
|
|
])
|
|
password = StringField(validators=[
|
|
validators.Length(max=255),
|
|
])
|
|
position_name = StringField(validators=[])
|
|
|
|
nickname = StringField(validators=[
|
|
validators.DataRequired(message=ErrFormat.nickname_is_required),
|
|
validators.Length(max=255),
|
|
])
|
|
sex = StringField(validators=[])
|
|
mobile = StringField(validators=[])
|
|
department_id = IntegerField(validators=[], default=0)
|
|
direct_supervisor_id = IntegerField(validators=[], default=0)
|
|
|
|
|
|
class EmployeeUpdateByUidForm(Form):
|
|
nickname = StringField(validators=[
|
|
validators.DataRequired(message=ErrFormat.nickname_is_required),
|
|
validators.Length(max=255),
|
|
])
|
|
avatar = StringField(validators=[])
|
|
sex = StringField(validators=[])
|
|
mobile = StringField(validators=[])
|
|
|
|
|
|
class GrantEmployeeACLPerm(object):
|
|
"""
|
|
Grant ACL Permission After Create New Employee
|
|
"""
|
|
|
|
def __init__(self, acl=None):
|
|
self.perms_by_create_resources_type = ['read', 'grant', 'delete', 'update']
|
|
self.perms_by_common_grant = ['read']
|
|
self.resource_name_list = ['公司信息', '公司架构', '通知设置']
|
|
|
|
self.acl = acl if acl else self.check_app('backend')
|
|
self.resources_types = self.acl.get_all_resources_types()
|
|
self.resources_type = self.get_resources_type()
|
|
self.resource_list = self.acl.get_resource_by_type(None, None, self.resources_type['id'])
|
|
|
|
@staticmethod
|
|
def check_app(app_name):
|
|
acl = ACLManager(app_name)
|
|
payload = dict(
|
|
name=app_name,
|
|
description=app_name
|
|
)
|
|
app = acl.validate_app()
|
|
if not app:
|
|
acl.create_app(payload)
|
|
return acl
|
|
|
|
def get_resources_type(self):
|
|
results = list(filter(lambda t: t['name'] == '操作权限', self.resources_types['groups']))
|
|
if len(results) == 0:
|
|
payload = dict(
|
|
app_id=self.acl.app_name,
|
|
name='操作权限',
|
|
description='',
|
|
perms=self.perms_by_create_resources_type
|
|
)
|
|
resource_type = self.acl.create_resources_type(payload)
|
|
else:
|
|
resource_type = results[0]
|
|
resource_type_id = resource_type['id']
|
|
existed_perms = self.resources_types.get('id2perms', {}).get(resource_type_id, [])
|
|
existed_perms = [p['name'] for p in existed_perms]
|
|
new_perms = []
|
|
for perm in self.perms_by_create_resources_type:
|
|
if perm not in existed_perms:
|
|
new_perms.append(perm)
|
|
if len(new_perms) > 0:
|
|
resource_type['perms'] = existed_perms + new_perms
|
|
self.acl.update_resources_type(resource_type_id, resource_type)
|
|
|
|
return resource_type
|
|
|
|
def grant(self, rid_list):
|
|
[self.grant_by_rid(rid) for rid in rid_list if rid > 0]
|
|
|
|
def grant_by_rid(self, rid, is_admin=False):
|
|
for name in self.resource_name_list:
|
|
resource = list(filter(lambda r: r['name'] == name, self.resource_list))
|
|
if len(resource) == 0:
|
|
payload = dict(
|
|
type_id=self.resources_type['id'],
|
|
app_id=self.acl.app_name,
|
|
name=name,
|
|
)
|
|
resource = self.acl.create_resource(payload)
|
|
else:
|
|
resource = resource[0]
|
|
|
|
perms = self.perms_by_create_resources_type if is_admin else self.perms_by_common_grant
|
|
self.acl.grant_resource(rid, resource['id'], perms)
|