Merge remote-tracking branch 'origin/v2.x' into v2.x

# Conflicts:
#	backend/dvadmin/system/views/login.py
pull/57/head
李强 2022-05-14 00:11:33 +08:00
commit 6e4b2a4b19
3 changed files with 102 additions and 35 deletions

View File

@ -14,7 +14,7 @@ from rest_framework.views import APIView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from django.conf import settings
from application import settings
from dvadmin.system.models import Users
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
from dvadmin.utils.request_util import save_login_log
@ -34,7 +34,7 @@ class CaptchaView(APIView):
)
def get(self, request):
data = {}
if settings.SYSTEM_CONFIG.get("base.captcha_state"):
if settings.CAPTCHA_STATE:
hashkey = CaptchaStore.generate_key()
id = CaptchaStore.objects.filter(hashkey=hashkey).first().id
imgage = captcha_image(request, hashkey)
@ -47,6 +47,15 @@ class CaptchaView(APIView):
return DetailResponse(data=data)
class CaptchaStatusView(APIView):
authentication_classes = []
permission_classes = []
def get(self, request):
return DetailResponse(data={"status": settings.CAPTCHA_STATE})
class LoginSerializer(TokenObtainPairSerializer):
"""
登录的序列化器:
@ -66,7 +75,7 @@ class LoginSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
captcha = self.initial_data.get("captcha", None)
if settings.SYSTEM_CONFIG.get("base.captcha_state"):
if settings.CAPTCHA_STATE:
if captcha is None:
raise CustomValidationError("验证码不能为空")
self.image_code = CaptchaStore.objects.filter(
@ -78,8 +87,8 @@ class LoginSerializer(TokenObtainPairSerializer):
raise CustomValidationError("验证码过期")
else:
if self.image_code and (
self.image_code.response == captcha
or self.image_code.challenge == captcha
self.image_code.response == captcha
or self.image_code.challenge == captcha
):
self.image_code and self.image_code.delete()
else:
@ -161,11 +170,12 @@ class ApiLogin(APIView):
def post(self, request):
username = request.data.get("username")
password = request.data.get("password")
if user_obj := auth.authenticate(
request,
username=username,
password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
):
user_obj = auth.authenticate(
request,
username=username,
password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
)
if user_obj:
login(request, user_obj)
return redirect("/")
else:

View File

@ -45,6 +45,15 @@ class UserCreateSerializer(CustomModelSerializer):
),
)
def validate_password(self, value):
"""
对密码进行验证
"""
password = self.initial_data.get("password")
if password:
return make_password(value)
return value
def save(self, **kwargs):
data = super().save(**kwargs)
data.post.set(self.initial_data.get("post", []))

View File

@ -109,19 +109,38 @@ export const crudOptions = (vm) => {
type: 'input',
form: {
rules: [ // 表单校验规则
{ required: true, message: '账号必填项' }
{
required: true,
message: '账号必填项'
}
],
component: {
placeholder: '请输入账号'
},
itemProps: {
class: { yxtInput: true }
}
}
},
{
title: '密码',
key: 'password',
minWidth: 90,
type: 'input',
form: {
component: {
span: 12,
showPassword: true,
placeholder: '不填则默认为:admin123456'
},
helper: {
render (h) {
return (< el-alert title="密码默认为:admin123456" type="warning"/>
)
}
itemProps: {
class: { yxtInput: true }
}
},
disabled: true,
valueResolve (row, key) {
if (row.password) {
row.password = vm.$md5(row.password)
}
}
},
@ -135,7 +154,10 @@ export const crudOptions = (vm) => {
type: 'input',
form: {
rules: [ // 表单校验规则
{ required: true, message: '姓名必填项' }
{
required: true,
message: '姓名必填项'
}
],
component: {
span: 12,
@ -153,24 +175,28 @@ export const crudOptions = (vm) => {
disabled: true
},
minWidth: 140,
type: 'table-selector',
type: 'tree-selector',
dict: {
cache: false,
isTree: true,
url: deptPrefix,
value: 'id', // 数据字典中value字段的属性名
label: 'name', // 数据字典中label字段的属性名
getData: (url, dict, { form, component }) => {
return request({ url: url, params: { page: 1, limit: 10, status: 1 } }).then(ret => {
component._elProps.page = ret.data.page
component._elProps.limit = ret.data.limit
component._elProps.total = ret.data.total
return ret.data.data
})
}
label: 'name' // 数据字典中label字段的属性名
// getData: (url, dict, { form, component }) => {
// return request({ url: url, params: { page: 1, limit: 10, status: 1 } }).then(ret => {
// component._elProps.page = ret.data.page
// component._elProps.limit = ret.data.limit
// component._elProps.total = ret.data.total
// return ret.data.data
// })
// }
},
form: {
rules: [ // 表单校验规则
{ required: true, message: '必填项' }
{
required: true,
message: '必填项'
}
],
itemProps: {
class: { yxtInput: true }
@ -208,8 +234,15 @@ export const crudOptions = (vm) => {
type: 'input',
form: {
rules: [
{ max: 20, message: '请输入正确的手机号码', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码' }
{
max: 20,
message: '请输入正确的手机号码',
trigger: 'blur'
},
{
pattern: /^1[3-9]\d{9}$/,
message: '请输入正确的手机号码'
}
],
itemProps: {
class: { yxtInput: true }
@ -224,7 +257,11 @@ export const crudOptions = (vm) => {
minWidth: 180,
form: {
rules: [
{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }
{
type: 'email',
message: '请输入正确的邮箱地址',
trigger: ['blur', 'change']
}
],
component: {
placeholder: '请输入邮箱'
@ -250,7 +287,6 @@ export const crudOptions = (vm) => {
title: '用户类型',
key: 'user_type',
search: {
value: 0,
disabled: false
},
width: 140,
@ -316,8 +352,17 @@ export const crudOptions = (vm) => {
url: '/api/system/role/',
value: 'id', // 数据字典中value字段的属性名
label: 'name', // 数据字典中label字段的属性名
getData: (url, dict, { form, component }) => {
return request({ url: url, params: { page: 1, limit: 10 } }).then(ret => {
getData: (url, dict, {
form,
component
}) => {
return request({
url: url,
params: {
page: 1,
limit: 10
}
}).then(ret => {
component._elProps.page = ret.data.page
component._elProps.limit = ret.data.limit
component._elProps.total = ret.data.total
@ -327,7 +372,10 @@ export const crudOptions = (vm) => {
},
form: {
rules: [ // 表单校验规则
{ required: true, message: '必填项' }
{
required: true,
message: '必填项'
}
],
itemProps: {
class: { yxtInput: true }