独角鲸同步合作方公司数据项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1164 lines
55 KiB

10 months ago
import datetime
import logging
import logging
import os
import random
import re
import time
import traceback
import uuid
from django.contrib.auth.hashers import make_password
from django.db import transaction
from django.db.models import Q
from django_filters.rest_framework import DjangoFilterBackend
from django_redis import get_redis_connection
from operator import itemgetter
from rest_framework.decorators import action
from rest_framework.filters import SearchFilter, OrderingFilter
from rest_framework.generics import ListAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
# from django.contrib.auth import authenticate
from rest_framework_jwt.settings import api_settings
# APPID_MP, SECRET_MP, \
# AuthorizationWX_URL, CCW_URL, FILE_HTTP,
from ChaCeRndTrans import settings
from ChaCeRndTrans.basic import CCAIResponse
from ChaCeRndTrans.code import *
from ChaCeRndTrans.settings import RELEASE_DOMAIN, TEST_DOMAIN, MAX_IMAGE_SIZE
from rbac.views.message import msg_redis_code
from utils.custom import CommonPagination, RbacPermission, CustomViewBase, \
generate_random_str, sha1_encrypt, is_all_chinese, is_valid_username
from utils.funcs import generate_random_str
from ..models import UserProfile, Menu, Role, Company
from ..serializers.menu_serializer import MenuSerializer
from ..serializers.user_serializer import UserListSerializer, UserCreateSerializer, UserModifySerializer, \
UserInfoListSerializer, CompanySerializer
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
err_logger = logging.getLogger('error')
class UserAuthView(APIView):
"""
用户认证获取token
"""
def post(self, request, *args, **kwargs):
try:
# type 登录类型 1:免密登录 2:账号登录
type = request.data.get("type", None)
if type is None:
return CCAIResponse(data="缺少必要参数", msg="缺少必要参数", status=BAD)
if type == 1:
mobile = request.data.get("telephone")
verifycode = request.data.get("verifycode")
if mobile == '' or mobile is None:
return CCAIResponse("手机号不能为空!", status=BAD)
if verifycode == '' or verifycode is None:
return CCAIResponse("验证码不能为空!", status=BAD)
user = UserProfile.objects.filter(mobile=mobile, is_active=1).first()
if user is not None:
try:
conn = get_redis_connection('default')
key = msg_redis_code + mobile
code = conn.hget(key, 'code')
count = conn.hget(key, 'count')
if code is None:
return CCAIResponse(data="验证码失效,请重新获取!", msg="验证码失效,请重新获取!", status=BAD)
elif code.decode('utf8') != verifycode:
if count is None:
conn.hset(key, 'count', 1)
else:
count = int(count.decode('utf8')) + 1
if count < 5:
conn.hset(key, 'count', count)
else:
conn.delete(key)
return CCAIResponse(data="验证码有误!", msg="验证码有误!", status=VERIFYCODE_ERROR)
else:
# 验证码,验证通过
payload = jwt_payload_handler(user)
if 'user_id' in payload:
payload.pop('user_id')
return CCAIResponse(data={"token": jwt_encode_handler(payload)}, status=OK)
except Exception as e:
err_logger.error(
"user: %s, connect redis failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse(data="手机号登录失败!", msg="手机号登录失败!", status=BAD)
else:
user = UserProfile.objects.filter(mobile=mobile).first()
if user:
if user.is_active == 1:
return CCAIResponse(data="根据相关法律规定,账号需要绑定手机号,请输入账号密码进行绑定!",
status="根据相关法律规定,账号需要绑定手机号,请输入账号密码进行绑定!", code=BAD)
else:
return CCAIResponse(data="用户未激活!", msg="用户未激活!", status=BAD)
else:
return CCAIResponse(
data="该手机号未注册,请点击下方“立即注册”按钮进行注册!",
msg="该手机号未注册,请点击下方“立即注册”按钮进行注册!",
status=BAD
)
else:
username = request.data.get("username", None)
password = request.data.get("password", None)
if not username:
return CCAIResponse(data="请输入用户名,手机号或邮箱!", status=BAD)
if not password:
return CCAIResponse(data="请输入密码", status=BAD)
if username:
# 查询用户 # 此处可能会有问题,A用户的账号为B用户的手机号,故账号设置需要有复杂度
user = UserProfile.objects.filter(Q(username=username) | Q(email=username) | Q(mobile=username)).first()
if user:
if user.check_password(password):
if user.is_active:
payload = jwt_payload_handler(user)
if 'user_id' in payload:
payload.pop('user_id')
return CCAIResponse({"token": jwt_encode_handler(payload)}, status=OK)
else:
return CCAIResponse(data="用户被锁定,请等待联系管理员。", msg="用户被锁定,请等待联系管理员。", status=BAD)
else:
return CCAIResponse(data="用户名或密码错误", msg="用户名或密码错误!", status=BAD)
else: # 用户不存在
return CCAIResponse(data="用户名或密码错误", msg="用户名或密码错误!", status=BAD)
except Exception as e:
err_logger.error("user login failed: \n%s" % traceback.format_exc())
return CCAIResponse(msg="用户名或密码错误!", status=SERVER_ERROR)
class UserInfoView(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
permission_classes = (IsAuthenticated,)
"""
获取当前用户信息和权限
"""
@classmethod
def get_permission_from_role(self, request, companyMid=None):
"""
根据用户角色与公司id,返回对应的权限
"""
try:
if request.user:
perms_list = []
# for item in request.user.roles.values("permissions__method").distinct():
# perms_list.append(item["permissions__method"])
if not companyMid:
for item in request.user.roles.values("permissions__method").distinct():
perms_list.append(item["permissions__method"])
else:
for item in request.user.roles.filter(Q(companyMid=companyMid) | Q(companyMid__isnull=True)).values("permissions__method").distinct():
perms_list.append(item["permissions__method"])
return perms_list
except AttributeError:
return None
@classmethod
def get_company_from_user(self, request):
try:
if request.user:
if 2 == request.user.label: # 后台内部人员可以查看所有公司
company_list = Company.objects.all()
else:
company_list = request.user.company.all()
return CompanySerializer(company_list, many=True).data
except AttributeError:
return None
def get(self, request):
try:
companyMid = request.GET.get("companyMid")
checkIn = None
company = None
if companyMid:
if not Company.objects.filter(MainId=companyMid).exists():
return CCAIResponse("公司不存在", status=BAD)
else:
checkIn = Company.objects.filter(MainId=companyMid).values("checkIn").first()['checkIn']
company = Company.objects.filter(MainId=companyMid).values("AmStart", "AmEnd", "PmStart", "PmEnd", "tolerance").first()
# else:
# companyMid = request.user.companyMid
if request.user.id is not None:
company_list = self.get_company_from_user(request)
if companyMid is None:
checkIn = company_list[0]['checkIn']
company = company_list[0]
perms = self.get_permission_from_role(request, companyMid)
data = {
"id": request.user.id,
"username": request.user.username,
"name": request.user.name,
"avatar": request.user.image if request.user.image else "/upload/logo/default.jpg",
"mobile": request.user.mobile,
"email": request.user.email,
"is_active": request.user.is_active,
"createTime": request.user.date_joined,
"roles": perms,
"is_superuser": request.user.is_superuser,
"area_code": request.user.area_code,
"area_name": request.user.area_name,
"is_sub": request.user.is_sub, # 1:子账号;2:主账号
"nowcompany": companyMid if companyMid else company_list[0]['MainId'],
"checkIn": checkIn,
"AmStart": company["AmStart"],
"AmEnd": company["AmEnd"],
"PmStart": company["PmStart"],
"PmEnd": company["PmEnd"],
"tolerance": company["tolerance"],
"company": company_list,
}
return CCAIResponse(data=data, status=OK)
else:
return CCAIResponse("请登录后访问!", status=FORBIDDEN)
except Exception as e:
err_logger.error("get permission from role failed: \n%s" % traceback.format_exc())
return CCAIResponse(msg="获取当前用户信息和权限失败!", status=SERVER_ERROR)
class UserBuildMenuView(APIView):
"""
绑定当前用户,绑定当前公司的菜单信息
"""
def get_menu_from_role(self, request):
menu_dict = {}
try:
if request.user:
companyMid = request.GET.get('companyMid')
if not companyMid:
menus = request.user.roles.values(
"menus__id",
"menus__name",
"menus__route_name",
"menus__path",
"menus__is_frame",
"menus__is_show",
"menus__component",
"menus__icon",
"menus__sort",
"menus__pid"
).distinct().order_by("menus__sort")
else:
menus = request.user.roles.filter(Q(companyMid=companyMid) | Q(companyMid__isnull=True)).values(
"menus__id",
"menus__name",
"menus__route_name",
"menus__path",
"menus__is_frame",
"menus__is_show",
"menus__component",
"menus__icon",
"menus__sort",
"menus__pid"
).distinct().order_by("menus__sort")
# 获取公司打卡方案
company = Company.objects.filter(MainId=companyMid).first()
companyCheckIn = company.checkIn
for item in menus:
# 如果公司打卡方案是A不展示B方案工时菜单
if item["menus__pid"] is None:
if item["menus__is_frame"]:
# 判断是否外部链接
top_menu = {
"id": item["menus__id"],
"path": item["menus__path"],
"component": "Layout",
"children": [{
"path": item["menus__path"],
"meta": {
"title": item["menus__name"],
"icon": item["menus__icon"]
}
}],
"pid": item["menus__pid"],
"sort": item["menus__sort"]
}
else:
top_menu = {
"id": item["menus__id"],
"name": item["menus__route_name"],
"path": "/" + item["menus__path"],
"redirect": "noredirect",
"component": "Layout",
"alwaysShow": True,
"meta": {
"title": item["menus__name"],
"icon": item["menus__icon"]
},
"pid": item["menus__pid"],
"sort": item["menus__sort"],
"children": []
}
menu_dict[item["menus__id"]] = top_menu
else:
if item["menus__is_frame"]:
children_menu = {
"id": item["menus__id"],
"name": item["menus__route_name"],
"path": item["menus__path"],
"component": "Layout",
"meta": {
"title": item["menus__name"],
"icon": item["menus__icon"],
},
"pid": item["menus__pid"],
"sort": item["menus__sort"]
}
elif item["menus__is_show"]:
children_menu = {
"id": item["menus__id"],
"name": item["menus__route_name"],
"path": item["menus__path"],
"component": item["menus__component"],
"meta": {
"title": item["menus__name"],
"icon": item["menus__icon"],
},
"pid": item["menus__pid"],
"sort": item["menus__sort"]
}
else:
children_menu = {
"id": item["menus__id"],
"name": item["menus__route_name"],
"path": item["menus__path"],
"component": item["menus__component"],
"meta": {
"title": item["menus__name"],
"noCache": True,
},
"hidden": True,
"pid": item["menus__pid"],
"sort": item["menus__sort"]
}
menu_dict[item["menus__id"]] = children_menu
return menu_dict
except Exception as e:
err_logger.error("get menu from role failed: \n%s" % traceback.format_exc())
return menu_dict
def get_all_menu_dict(self):
"""
获取所有菜单数据重组结构
"""
try:
menus = Menu.objects.all().order_by('sort')
serializer = MenuSerializer(menus, many=True)
tree_dict = {}
for item in serializer.data:
if item["pid"] is None:
if item["is_frame"]:
# 判断是否外部链接
top_menu = {
"id": item["id"],
"path": item["path"],
"component": "Layout",
"children": [{
"path": item["path"],
"meta": {
"title": item["name"],
"icon": item["icon"]
}
}],
"pid": item["pid"],
"sort": item["sort"]
}
else:
top_menu = {
"id": item["id"],
"name": item["route_name"],
"path": "/" + item["path"],
"redirect": "noredirect",
"component": "Layout",
"alwaysShow": True,
"meta": {
"title": item["name"],
"icon": item["icon"]
},
"pid": item["pid"],
"sort": item["sort"],
"children": []
}
tree_dict[item["id"]] = top_menu
else:
if item["is_frame"]:
children_menu = {
"id": item["id"],
"name": item["route_name"],
"path": item["path"],
"component": "Layout",
"meta": {
"title": item["name"],
"icon": item["icon"],
},
"pid": item["pid"],
"sort": item["sort"]
}
elif item["is_show"]:
children_menu = {
"id": item["id"],
"name": item["route_name"],
"path": item["path"],
"component": item["component"],
"meta": {
"title": item["name"],
"icon": item["icon"],
},
"pid": item["pid"],
"sort": item["sort"]
}
else:
children_menu = {
"id": item["id"],
"name": item["route_name"],
"path": item["path"],
"component": item["component"],
"meta": {
"title": item["name"],
"noCache": True,
},
"hidden": True,
"pid": item["pid"],
"sort": item["sort"]
}
tree_dict[item["id"]] = children_menu
return tree_dict
except Exception as e:
err_logger.error("get all menu from role failed: \n%s" % traceback.format_exc())
return tree_dict
def get_all_menus(self, request):
try:
perms = UserInfoView.get_permission_from_role(request)
tree_data = []
if "admin" in perms or request.user.is_superuser:
tree_dict = self.get_all_menu_dict()
else:
tree_dict = self.get_menu_from_role(request)
for i in tree_dict:
if tree_dict[i]["pid"]:
pid = tree_dict[i]["pid"]
try:
parent = tree_dict[pid]
except KeyError as e:
# 缺少父级菜单
continue
parent.setdefault("redirect", "noredirect")
parent.setdefault("alwaysShow", True)
parent.setdefault("children", []).append(tree_dict[i])
parent["children"] = sorted(parent["children"], key=itemgetter("sort"))
else:
tree_data.append(tree_dict[i])
return tree_data
except Exception as e:
err_logger.error("get all menu failed: \n%s" % traceback.format_exc())
return tree_data
def get(self, request):
try:
if request.user.id is not None:
menu_data = self.get_all_menus(request)
return CCAIResponse(menu_data, status=OK)
else:
return CCAIResponse(msg="请登录后访问!", status=FORBIDDEN)
except Exception as e:
err_logger.error("get all menu failed: \n%s" % traceback.format_exc())
return CCAIResponse([], status=OK)
class UserViewSet(CustomViewBase):
"""
用户管理增删改查
"""
perms_map = (
{"*": "admin"},
{"*": "user_all"},
{"get": "user_list"},
{"post": "user_create"},
{"put": "user_edit"},
{"delete": "user_delete"}
)
queryset = UserProfile.objects.all()
serializer_class = UserListSerializer
pagination_class = CommonPagination
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
filter_fields = ("is_active", "is_sub")
search_fields = ("username", "name", "mobile", "email")
ordering_fields = ("id",)
authentication_classes = (JSONWebTokenAuthentication,)
# permission_classes = (RbacPermission,)
def get_serializer_class(self):
# 根据请求类型动态变更serializer
if self.action == "create":
return UserCreateSerializer
elif self.action == "list":
return UserListSerializer
return UserModifySerializer
def create(self, request, *args, **kwargs):
# 创建用户默认添加密码
try:
with transaction.atomic():
data = request.data.copy()
password = sha1_encrypt("chacewang123456")
data['password'] = password
# 生成uuid,并设置到用户中,再create
data['MainId'] = uuid.uuid4().__str__() # 用户mid
companyname = data.get('companyname')
com = Company.objects.filter(name=companyname).first()
if com is None:
companyMid = uuid.uuid4().__str__() # 公司mid
com = Company()
com.MainId = companyMid
com.name = data.get('companyname')
com.EUCC = data.get('eucc')
com.userMid = data['MainId']
com.save()
else:
companyMid = com.MainId
data['companyMid'] = companyMid
serializer = self.get_serializer(data=data)
try:
serializer.is_valid(raise_exception=True)
except Exception as e:
msg = ""
count = 0
for k, v in e.detail.items():
count += 1
if count == 2:
msg += "" + e.detail[k][0]
else:
msg += e.detail[k][0]
return CCAIResponse(msg=msg, status=BAD)
self.perform_create(serializer)
user = UserProfile.objects.filter(id=serializer.data['id']).first()
if user:
# # 为注册用户添加角色
# # 公司管理员(公司的唯一最大权限拥有者)id=2
# role = Role.objects.filter(id=2).first()
# if role:
# user.roles.add(role) # 添加角色组合 其中角色仅为公司管理员
user.set_password(password)
# 为注册用户添加公司
user.company.add(com)
user.save()
headers = self.get_success_headers(serializer.data)
# data = serializer.data
return CCAIResponse(data="chacewang123456", status=CREATED, headers=headers)
except Exception as e:
err_logger.error("create user failed: \n%s" % traceback.format_exc())
return CCAIResponse(msg='创建用户失败', status=SERVER_ERROR)
def update(self, request, *args, **kwargs):
try:
partial = kwargs.pop('partial', False)
instance = self.get_object()
# 是否封禁用户
is_active = request.data.get('is_active')
is_active = True if is_active == "true" else False
flag = False
if instance.is_active and not is_active: # 操作为封禁
flag = True
# 查询是否存在已激活的子账号
subs = UserProfile.objects.filter(is_sub=1, parent_id=instance.id, is_active=1)
serializer = self.get_serializer(instance, data=request.data, partial=partial)
try:
serializer.is_valid(raise_exception=True)
except Exception as e:
msg = ""
count = 0
for k, v in e.detail.items():
count += 1
if count == 2:
msg += "" + k + e.detail[k][0]
else:
msg += k + e.detail[k][0]
return CCAIResponse(msg=msg, status=BAD)
with transaction.atomic():
self.perform_update(serializer)
if flag and subs:
subs.update(is_active=0)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return CCAIResponse(serializer.data, status=200)
except Exception as e:
err_logger.error("update user failed: \n%s" % traceback.format_exc())
return CCAIResponse(msg='修改用户失败', status=SERVER_ERROR)
def list(self, request, *args, **kwargs):
try:
queryset = self.filter_queryset(self.get_queryset().filter().all())
page = self.paginate_queryset(queryset)
domain = RELEASE_DOMAIN
if settings.DEVELOP_DEBUG:
domain = TEST_DOMAIN
if page is not None:
serializer = self.get_serializer(page, many=True)
return_data = serializer.data
# for item in return_data:
# start = item['image'].rindex('/media/')
# item['image'] = domain + item['image'][start:]
return self.get_paginated_response(return_data)
serializer = self.get_serializer(queryset, many=True)
return_data = serializer.data
for item in return_data:
start = item['image'].rindex('/media/')
item['image'] = domain + item['image'][start:]
return CCAIResponse(data=return_data, status=200)
except Exception as e:
err_logger.error("get user list failed: \n%s" % traceback.format_exc())
return CCAIResponse(msg='获取用户失败', status=SERVER_ERROR)
@action(methods=["post"], detail=True, permission_classes=[IsAuthenticated],
url_path="association_company", url_name="association")
def association_company(self, request, pk=None):
"""
增加或删除账户关联公司,如果账户只剩一个公司,不给删除
"""
try:
params = request.data
type = params.get('type', 1) # 1:增加关联公司 2:删除关联公司
companyId = params.get('companyId') # 对应的公司id
if not companyId:
return CCAIResponse('Missing param', BAD)
instance = self.get_object() # 获取对应用户
company = Company.objects.filter(id=companyId).first()
if company:
if 1 == int(type):
instance.company.add(company)
elif 2 == int(type):
instance.company.remove(company)
else:
pass
return CCAIResponse('success')
else:
return CCAIResponse('查找不到公司', BAD)
except Exception as e:
err_logger.error("user association company failed: \n%s" % traceback.format_exc())
return CCAIResponse(msg='用户关联公司操作失败', status=SERVER_ERROR)
@action(methods=["post"], detail=True, permission_classes=[IsAuthenticated],
url_path="change-passwd", url_name="change-passwd")
def update_password(self, request, pk=None):
try:
perms = UserInfoView.get_permission_from_role(request)
old_password = request.data.get("old_password", "")
new_password1 = request.data.get("new_password1", "")
new_password2 = request.data.get("new_password2", "")
if new_password1 == "" or new_password2 == "":
return CCAIResponse("密码不允许为空!", status=status.HTTP_400_BAD_REQUEST)
user = UserProfile.objects.get(id=pk if pk else request.user.id)
if "admin" in perms or "user_all" in perms or request.user.is_superuser:
new_password1 = request.data["new_password1"]
new_password2 = request.data["new_password2"]
if new_password1 == new_password2:
# result_dict = check_password_complexity(new_password1)
# if not result_dict["flag"]:
# return CCAIResponse(msg=result_dict["message"], status=BAD)
user.set_password(new_password2)
user.save()
return CCAIResponse(data="密码修改成功!", msg="密码修改成功!", status=OK)
else:
return CCAIResponse(data="新密码两次输入不一致!", msg="新密码两次输入不一致!",
status=status.HTTP_400_BAD_REQUEST)
else:
if old_password:
if not request.user.check_password(old_password):
return CCAIResponse(data="旧密码错误!", msg="旧密码错误!", status=BAD)
if new_password1 == new_password2:
if old_password == new_password1:
return CCAIResponse(data="新密码和旧密码不能一样!",
msg="新密码和旧密码不能一样!", status=BAD)
# 判断验证码是否正确
user.set_password(new_password1)
user.save()
return CCAIResponse(data="修改密码成功!", status=OK)
else:
return CCAIResponse(data="新密码两次输入不一致!", msg="新密码两次输入不一致!",
status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
err_logger.error("user update password failed: \n%s" % traceback.format_exc())
return CCAIResponse(msg='修改密码失败', status=SERVER_ERROR)
# 重置密码
@action(methods=["get"], detail=False, permission_classes=[RbacPermission],
url_path="reSetPassword", url_name="reSetPassword")
def reSetPassword(self, request):
try:
user_ids = request.query_params.get('ids', None)
if not user_ids:
return CCAIResponse("id参数不对啊!", NOT_FOUND)
password = ""
with transaction.atomic():
user_list = UserProfile.objects.filter(id__in=user_ids.split(","))
for userl in user_list:
user = UserProfile.objects.filter(username=userl.username).first()
if user:
# user.password = password
special_str = "*@&%"
password = "ccw" + user.mobile[-6:] + special_str[random.randint(0, len(special_str) - 1)] \
+ generate_random_str(randomlength=3)
password_ = sha1_encrypt(password)
user.password = make_password(password_)
user.save()
return CCAIResponse(data={"pwd": password}, status=OK)
except Exception as e:
err_logger.error(
"user: %s, reset password failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse("重新设置密码失败", SERVER_ERROR)
# @action(methods=["post"], detail=False, permission_classes=[IsAuthenticated],
# url_path="updateAvatar", url_name="updateAvatar")
# def updateAvatar(self, request):
# try:
# avatar = request.FILES.get('avatar', "")
# image_type = request.data.get("image_type", "")
#
# if avatar is None or avatar == '':
# return CCAIResponse(data="avatar参数缺失!", status=BAD)
# if not image_type:
# return CCAIResponse(data="image_type参数缺失!", status=BAD)
# if avatar.size > MAX_IMAGE_SIZE:
# return CCAIResponse(data="上传文件需小于或等于2M", status=SERVER_ERROR)
#
# file_name = generate_random_str(12) + "." + image_type
# ct = time.time() # 取得系统时间
# local_time = time.localtime(ct)
# date_head = time.strftime("%Y%m%d%H%M%S", local_time) # 格式化时间
# date_m_secs = str(datetime.datetime.now().timestamp()).split(".")[-1] # 毫秒级时间戳
# time_stamp = "%s%.3s" % (date_head, date_m_secs) # 拼接时间字符串
# # 本地存储目录
# save_path = os.path.join(settings.FILE_PATH, image_type, time_stamp)
# save_path = save_path.replace('\\', '/')
# # 前端显示目录
# start = file_name.rindex('.')
# show_path = os.path.join(settings.SHOW_UPLOAD_PATH, image_type, time_stamp, file_name)
# show_path = show_path.replace('\\', '/')
# # 如果不存在则创建目录
# if not os.path.exists(save_path):
# os.makedirs(save_path)
# os.chmod(save_path, mode=0o777)
#
# file_path = open(save_path + "/" + file_name, 'wb')
# for chunk in avatar.chunks():
# file_path.write(chunk)
# file_path.close()
#
# # 数据库存储路径
# request.user.image = show_path
# request.user.save()
# return CCAIResponse(status=200, data=show_path)
#
# except Exception as e:
# err_logger.error("user: %s, user update avatar failed: \n%s" % (request.user.id, traceback.format_exc()))
# return CCAIResponse(msg='修改头像失败', status=SERVER_ERROR)
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated],
url_path="updateAvatar", url_name="updateAvatar")
def updateAvatar(self, request):
"""
不支持用户上传图片
"""
try:
avatar = request.data.get('avatar')
if avatar is None or avatar == '':
return CCAIResponse("参数缺失!", BAD)
request.user.image = avatar
request.user.save()
return CCAIResponse("头像修改成功!")
except Exception as e:
err_logger.error("user: %s, user update avatar failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse('修改头像失败', status=BAD)
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated],
url_path="change_mobile", url_name="change_mobile")
def change_mobile(self, request, pk=None):
# 更新手机号
try:
user = UserProfile.objects.get(id=request.user.id)
params = request.data
mobile = params.get("mobile", "")
if mobile == None or mobile == '':
return CCAIResponse(data="手机号不能为空", msg="手机号不能为空", status=status.HTTP_400_BAD_REQUEST)
is_exist = UserProfile.objects.filter(mobile=mobile).first()
if is_exist:
return CCAIResponse(data="手机号已被绑定", msg="手机号已被绑定", status=BAD)
user.mobile = mobile
user.save()
return CCAIResponse("success")
except Exception as e:
err_logger.error("user update center mobile failed: \n%s" % traceback.format_exc())
return CCAIResponse(data='手机号修改失败', msg='手机号修改失败', status=SERVER_ERROR)
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated],
url_path="update_name", url_name="update_name")
def update_name(self, request, pk=None):
try:
params = request.data
name = params.get("name", None) # 真实姓名
if name:
if len(name) < 2 or len(name) > 5:
return CCAIResponse(data="请输入正确的真实名字!", msg="请输入正确的真实名字!", status=BAD)
if not is_all_chinese(name):
return CCAIResponse(data="格式不对,请输入正确的真实名字!", msg="格式不对,请输入正确的真实名字!",
status=BAD)
request.user.name = name
request.user.save()
return CCAIResponse(data="修改姓名成功!", msg='修改姓名成功!', status=OK)
else:
return CCAIResponse(data='真实姓名不能为空!', msg='真实姓名不能为空!', status=BAD)
except Exception as e:
err_logger.error(
"user: %s update name failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse(msg='完善个人信息失败', status=SERVER_ERROR)
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated],
url_path="updateInfo", url_name="updateInfo")
def updateInfo(self, request):
try:
params = request.data
name = params.get("name", "") # 真实姓名
area_code = params.get("area_code", None)
area_dict = params.get("area", None) # 地区字典
# if area_dict == None or area_dict == "":
# return CCAIResponse("area参数不能为空!", status=status.HTTP_400_BAD_REQUEST)
if not name:
return CCAIResponse(msg="真实姓名不能为空!", status=BAD)
request.user.name = name
if area_dict:
request.user.area_code = area_dict["value"]
request.user.area_name = area_dict['label']
request.user.last_login = datetime.datetime.now()
request.user.save()
return CCAIResponse("success")
except Exception as e:
err_logger.error(
"user: %s update user information failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse(msg='完善个人信息失败', status=SERVER_ERROR)
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated],
url_path="change_username", url_name="change_username")
def change_name(self, request, pk=None):
try:
# user = UserProfile.objects.get(id=request.user.id)
params = request.data
username = params.get("username", None)
if not username:
return CCAIResponse(data="用户名不能为空", msg="用户名不能为空", status=status.HTTP_400_BAD_REQUEST)
if not is_valid_username(username):
return CCAIResponse(data="用户名格式不对,只能输入汉字,英文字母,数字!",
msg="用户名格式不对,只能输入汉字,英文字母,数字!", status=BAD)
is_exist = UserProfile.objects.filter(username=username).first()
if is_exist:
return CCAIResponse(data="用户名已被使用,请重新修改", msg="用户名已被使用,请重新修改", status=BAD)
request.user.username = username
request.user.save()
return CCAIResponse(data="用户名修改成功!", msg="用户名修改成功!", status=OK)
except Exception as e:
err_logger.error("user: %s change user username failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse(msg='用户名修改失败', status=SERVER_ERROR)
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated],
url_path="update_email", url_name="update_email")
def update_email(self, request, pk=None):
try:
params = request.data
email = params.get("email", "")
if email == None or email == '':
return CCAIResponse("email参数不能为空!", status=status.HTTP_400_BAD_REQUEST)
ret = re.match(r'^\w+@(\w+.)+(com|cn|net)$', email)
if ret:
email_exist = UserProfile.objects.filter(email=email).count()
if email_exist > 0:
return CCAIResponse("该Email已被注册!", status=status.HTTP_400_BAD_REQUEST)
request.user.email = email
request.user.save()
return CCAIResponse("修改email成功!")
else:
return CCAIResponse("email格式不对,请检查!", status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
err_logger.error(
"user: %s update email failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse(msg='Email修改失败', status=SERVER_ERROR)
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated],
url_path="update_area", url_name="update_area")
def update_area(self, request, pk=None):
try:
params = request.data
area_dict = params.get("area", "")
if area_dict == None or area_dict == "":
return CCAIResponse("area参数不能为空!", status=status.HTTP_400_BAD_REQUEST)
request.user.area_code = area_dict["value"]
request.user.area_name = area_dict['label']
request.user.save()
return CCAIResponse("地区修改成功!")
except Exception as e:
err_logger.error(
"user: %s update area failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse(msg='地区修改失败', status=SERVER_ERROR)
@action(methods=["post"], detail=False, permission_classes=[],
url_path="forget_password", url_name="forget_password")
def forget_password(self, request, pk=None):
try:
mobile = request.data.get('mobile', None)
verification_code = request.data.get('verification_code', None)
new_password1 = request.data.get('new_password1')
new_password2 = request.data.get('new_password2')
if mobile is None:
return CCAIResponse(data="缺少参数mobile", msg="缺少参数mobile", status=BAD)
conn = get_redis_connection('default')
key = msg_redis_code + mobile
code = conn.hget(key, 'code')
count = conn.hget(key, 'count')
if code is None:
return CCAIResponse(data="验证码失效,请重新获取!", msg="验证码失效,请重新获取!", status=status.HTTP_206_PARTIAL_CONTENT)
elif code.decode('utf8') != verification_code:
if count is None:
conn.hset(key, 'count', 1)
else:
count = int(count.decode('utf8')) + 1
if count < 5:
conn.hset(key, 'count', count)
else:
conn.delete(key)
return CCAIResponse(data="验证码有误!", msg="验证码有误!", status=BAD)
else:
if new_password1 == new_password2:
user = UserProfile.objects.filter(mobile=mobile, is_active=1).first()
if user:
user.set_password(new_password2)
user.save()
conn.delete(key)
return CCAIResponse(data="密码修改成功!", msg="密码修改成功!", status=OK)
else:
err_logger.error(
"user: %s, connect redis failed: \n%s" % (request.user.id, traceback.format_exc()))
else:
return CCAIResponse(data="新密码两次输入不一致!", msg="新密码两次输入不一致!",
status=status.HTTP_400_BAD_REQUEST)
return CCAIResponse(data="密码修改失败!", msg="密码修改失败!", status=BAD)
except Exception as e:
err_logger.error(
"user: %s forget user password, reset password failed: \n%s" % (
request.user.id, traceback.format_exc()))
return CCAIResponse(data="忘记密码,重置密码失败!", msg="忘记密码,重置密码失败!", status=SERVER_ERROR)
class UserRegisterView(APIView):
"""
用户注册(注册为主账号)
"""
def post(self, request, *args, **kwargs):
try:
new_password1 = request.data.get("new_password1", None)
new_password2 = request.data.get("new_password2", None)
username = request.data.get("username", None) # 公司管理员账户
mobile = request.data.get("telephone", None) # 手机号码
companyname = request.data.get("companyname", None) # 公司名称
eucc = request.data.get("eucc", None) # 企业社会统一信用代码,一般为16为数字
verifycode = request.data.get("verifycode", None) # 短信验证码
name = request.data.get("name", None) # 姓名
if not companyname or companyname == '':
return CCAIResponse("公司名不能为空!", status=BAD)
if username == '' or username is None or \
new_password1 == '' or new_password1 is None or \
new_password2 == '' or new_password2 is None:
return CCAIResponse("用户名或密码不能为空!", status=BAD)
# if mobile is None or verifycode is None:
# return CCAIResponse(data="手机号与验证码不能为空!", msg="手机号与验证码不能为空!", status=BAD)
# 判断账号是否已经存在
username_exists = UserProfile.objects.filter(username=username).exists()
if username_exists:
return CCAIResponse(data="该账号已被注册!", msg="该账号已被注册!", status=BAD)
# 判断手机号是否已经被注册
phone_exist = UserProfile.objects.filter(mobile=mobile).count()
if phone_exist > 0:
return CCAIResponse(data="该手机号已被注册!", msg="该手机号已被注册!", status=BAD)
if new_password1 != new_password2:
return CCAIResponse(data="密码两次输入不一致!", msg="密码两次输入不一致!",
status=status.HTTP_400_BAD_REQUEST)
try:
conn = get_redis_connection('default')
key = msg_redis_code + mobile
code = conn.hget(key, 'code')
count = conn.hget(key, 'count')
if code is None:
return CCAIResponse(data="验证码失效,请重新获取!", msg="验证码失效,请重新获取!",
status=status.HTTP_206_PARTIAL_CONTENT)
elif code.decode('utf8') != verifycode:
if count is None:
conn.hset(key, 'count', 1)
else:
count = int(count.decode('utf8')) + 1
if count < 5:
conn.hset(key, 'count', count)
else:
conn.delete(key)
return CCAIResponse(data="验证码有误!", msg="验证码有误!", status=status.HTTP_202_ACCEPTED)
except Exception as e:
err_logger.error("user: %s, connect redis failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse("注册失败!", status=BAD)
with transaction.atomic():
# 生成用户与公司的全局id
userMid = uuid.uuid4().__str__()
company = Company.objects.filter(name=companyname).first()
if company is None:
# 创建绑定的公司
companyMid = uuid.uuid4().__str__() # 公司mid
company = Company()
company.MainId = companyMid
company.name = companyname
company.EUCC = eucc
company.userMid = userMid
company.save()
else:
companyMid = company.MainId
# 创建用户
user = UserProfile()
user.MainId = userMid
user.companyMid = companyMid
user.username = username
user.name = username
user.mobile = mobile
user.is_sub = 2 # 2:主账号
user.is_active = 0 # 注册时不激活,由后台管理员确认信息后手动激活
user.label = 1 # 默认前台用户
user.set_password(new_password1)
user.save()
# 为注册用户添加公司
user.company.add(company)
# 为注册用户添加角色
# 公司管理员(公司的唯一最大权限拥有者)id=2 其中包含的后台角色的权限(companyadmin)与菜单(company_system)
role = Role.objects.filter(id=2).first()
if role:
user.roles.add(role)
return CCAIResponse(data="注册成功", status=OK)
except Exception as e:
err_logger.error("user: %s, new_password1: %s, new_password1: %s, telphone: %s, user resister failed: "
"\n%s" % (request.user.id, new_password1, new_password2, mobile, traceback.format_exc()))
return CCAIResponse("注册失败", SERVER_ERROR)
# class UserBindWeChat(APIView):
# """
# 用户绑定个人微信
# """
# def post(self, request, *args):
# try:
# wx_code = request.GET.get('wx_code') # 微信临时code
# encryptedData = request.data.get("encryptedData") # 加密数据
# iv = request.data.get("iv") # 加密数据
# response_dict = get_session_key(wx_code, APPID_MP, SECRET_MP, AuthorizationWX_URL) # 获取session_key
# if not response_dict:
# return CCAIResponse("授权登录失败!", status=SERVER_ERROR)
# session_key = response_dict["session_key"]
# decrypted = decode_info(iv, encryptedData, APPID_MP, session_key) # 解密手机号码
# if not decrypted:
# return CCAIResponse("授权登录失败!", status=SERVER_ERROR)
#
# wxphone = decrypted["purePhoneNumber"]
#
# if wxphone == "" or wxphone is None:
# return CCAIResponse("授权登录失败!", status=SERVER_ERROR)
# user = UserProfile.objects.filter(mobile=wxphone, is_active=1, is_bind=1).first()
# if user is not None:
# # 存放微信相关信息
# user.wx_phone_info = json.dumps(decrypted)
# user.wx_openid = response_dict["openid"]
# user.save()
# else:
# return CCAIResponse("该微信的手机号码与八爪蛙账号的手机号码不一致!", status=SERVER_ERROR)
# return CCAIResponse("微信绑定成功!", status=OK)
#
# except Exception as e:
# err_logger("user: %s, bind Wechat failed: \n%s" % (request.user.id, traceback.format_exc()))
# return CCAIResponse("注册失败", SERVER_ERROR)
class UserListView(ListAPIView):
queryset = UserProfile.objects.all()
serializer_class = UserInfoListSerializer
filter_backends = (DjangoFilterBackend, OrderingFilter)
filter_fields = ("name",)
ordering_fields = ("id",)
authentication_classes = (JSONWebTokenAuthentication,)
permission_classes = (IsAuthenticated,)
class RefreshTokenView(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
permission_classes = (IsAuthenticated,)
"""
刷新token
"""
def post(self, request, *args, **kwargs):
try:
if request.user.id:
if request.user.is_active:
payload = jwt_payload_handler(request.user)
return CCAIResponse({"token": jwt_encode_handler(payload)}, status=OK)
else:
return CCAIResponse("用户未激活", status=BAD)
else:
return CCAIResponse("用户不存在!", status=BAD)
except Exception as e:
err_logger.error("user: %s, user refresh token failed: \n%s" % (request.user.id, traceback.format_exc()))
return CCAIResponse("用户不存在!", status=BAD)