mirror of
https://github.com/mindoc-org/mindoc.git
synced 2025-04-05 20:17:53 +08:00
1、实现管理员编辑用户信息
2、禁止管理员更改自己的权限和状态
This commit is contained in:
parent
36708f3171
commit
89b59ab1e1
@ -57,6 +57,9 @@ func (c *AccountController) Login() {
|
||||
|
||||
//如果没有数据
|
||||
if err == nil {
|
||||
member.LastLoginTime = time.Now()
|
||||
member.Update()
|
||||
|
||||
c.SetMember(*member)
|
||||
if strings.EqualFold(is_remember,"yes") {
|
||||
remember.MemberId = member.MemberId
|
||||
@ -68,6 +71,7 @@ func (c *AccountController) Login() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c.JsonResult(0,"ok")
|
||||
}else{
|
||||
logs.Error("用户登录 =>",err)
|
||||
|
@ -18,6 +18,14 @@ type ManagerController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (c *ManagerController) Prepare (){
|
||||
c.BaseController.Prepare()
|
||||
|
||||
if !c.Member.IsAdministrator() {
|
||||
c.Abort("403")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ManagerController) Index() {
|
||||
c.TplName = "manager/index.tpl"
|
||||
if !c.Member.IsAdministrator() {
|
||||
@ -141,6 +149,9 @@ func (c *ManagerController) UpdateMemberStatus() {
|
||||
if _, err := member.Find(member_id); err != nil {
|
||||
c.JsonResult(6002, "用户不存在")
|
||||
}
|
||||
if member.MemberId == c.Member.MemberId {
|
||||
c.JsonResult(6004,"不能变更自己的状态")
|
||||
}
|
||||
member.Status = status
|
||||
|
||||
if err := member.Update(); err != nil {
|
||||
@ -171,6 +182,9 @@ func (c *ManagerController) ChangeMemberRole() {
|
||||
if _, err := member.Find(member_id); err != nil {
|
||||
c.JsonResult(6002, "用户不存在")
|
||||
}
|
||||
if member.MemberId == c.Member.MemberId {
|
||||
c.JsonResult(6004,"不能变更自己的权限")
|
||||
}
|
||||
member.Role = role
|
||||
|
||||
if err := member.Update(); err != nil {
|
||||
@ -181,6 +195,60 @@ func (c *ManagerController) ChangeMemberRole() {
|
||||
c.JsonResult(0, "ok", member)
|
||||
}
|
||||
|
||||
func (c *ManagerController) EditMember() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/edit_users.tpl"
|
||||
if !c.Member.IsAdministrator() {
|
||||
c.Abort("403")
|
||||
}
|
||||
member_id,_ := c.GetInt(":id",0)
|
||||
|
||||
if member_id <= 0 {
|
||||
c.Abort("404")
|
||||
}
|
||||
|
||||
member ,err := models.NewMember().Find(member_id)
|
||||
|
||||
if err != nil {
|
||||
beego.Error(err)
|
||||
c.Abort("404")
|
||||
}
|
||||
if c.Ctx.Input.IsPost() {
|
||||
password1 := c.GetString("password1")
|
||||
password2 := c.GetString("password2")
|
||||
email := c.GetString("email")
|
||||
phone := c.GetString("phone")
|
||||
description := c.GetString("description")
|
||||
member.Email = email
|
||||
member.Phone = phone
|
||||
member.Description = description
|
||||
if password1 != "" && password2 != password1 {
|
||||
c.JsonResult(6001,"确认密码不正确")
|
||||
}
|
||||
if password1 != "" {
|
||||
member.Password = password1
|
||||
}
|
||||
if err := member.Valid(password1 == "");err != nil {
|
||||
c.JsonResult(6002,err.Error())
|
||||
}
|
||||
if password1 != "" {
|
||||
password,err := utils.PasswordHash(password1)
|
||||
if err != nil {
|
||||
beego.Error(err)
|
||||
c.JsonResult(6003,"对用户密码加密时出错")
|
||||
}
|
||||
member.Password = password
|
||||
}
|
||||
if err := member.Update();err != nil {
|
||||
beego.Error(err)
|
||||
c.JsonResult(6004,"保存失败")
|
||||
}
|
||||
c.JsonResult(0,"ok")
|
||||
}
|
||||
|
||||
c.Data["Model"] = member
|
||||
}
|
||||
|
||||
func (c *ManagerController) Books() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/books.tpl"
|
||||
@ -207,6 +275,9 @@ func (c *ManagerController) Books() {
|
||||
//编辑项目
|
||||
func (c *ManagerController) EditBook() {
|
||||
c.TplName = "manager/edit_book.tpl"
|
||||
if !c.Member.IsAdministrator() {
|
||||
c.Abort("403")
|
||||
}
|
||||
identify := c.GetString(":key")
|
||||
|
||||
if identify == "" {
|
||||
|
@ -6,7 +6,14 @@ import "errors"
|
||||
var (
|
||||
// ErrMemberNoExist 用户不存在.
|
||||
ErrMemberNoExist = errors.New("用户不存在")
|
||||
ErrMemberExist = errors.New("用户已存在")
|
||||
ErrMemberDisabled = errors.New("用户被禁用")
|
||||
ErrMemberEmailEmpty = errors.New("用户邮箱不能为空")
|
||||
ErrMemberEmailExist = errors.New("用户邮箱已被使用")
|
||||
ErrMemberDescriptionTooLong = errors.New("用户描述必须小于500字")
|
||||
ErrMemberEmailFormatError = errors.New("邮箱格式不正确")
|
||||
ErrMemberPasswordFormatError = errors.New("密码必须在6-50个字符之间")
|
||||
ErrMemberAccountFormatError = errors.New("账号只能由英文字母数字组成,且在3-50个字符")
|
||||
// ErrorMemberPasswordError 密码错误.
|
||||
ErrorMemberPasswordError = errors.New("用户密码错误")
|
||||
//ErrorMemberAuthMethodInvalid 不支持此认证方式
|
||||
|
@ -22,7 +22,7 @@ type Member struct {
|
||||
Account string `orm:"size(100);unique;column(account)" json:"account"`
|
||||
Password string `orm:"size(1000);column(password)" json:"-"`
|
||||
//认证方式: local 本地数据库 /ldap LDAP
|
||||
AuthMethod string `orm:"column(auth_method);default(local);size(50);" json:"auth_method)"`
|
||||
AuthMethod string `orm:"column(auth_method);default(local);size(50);" json:"auth_method"`
|
||||
Description string `orm:"column(description);size(2000)" json:"description"`
|
||||
Email string `orm:"size(100);column(email);unique" json:"email"`
|
||||
Phone string `orm:"size(255);column(phone);null;default(null)" json:"phone"`
|
||||
@ -73,6 +73,7 @@ func (m *Member) Login(account string, password string) (*Member, error) {
|
||||
}
|
||||
|
||||
switch member.AuthMethod {
|
||||
case "":
|
||||
case "local":
|
||||
ok, err := utils.PasswordVerify(member.Password, password)
|
||||
if ok && err == nil {
|
||||
@ -169,7 +170,9 @@ func (m *Member) Add() error {
|
||||
}
|
||||
|
||||
m.Password = hash
|
||||
|
||||
if m.AuthMethod == "" {
|
||||
m.AuthMethod = "local"
|
||||
}
|
||||
_, err = o.Insert(m)
|
||||
|
||||
if err != nil {
|
||||
@ -263,3 +266,66 @@ func (m *Member) FindByFieldFirst(field string, value interface{}) (*Member, err
|
||||
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (m *Member) Valid(is_hash_password bool) error {
|
||||
|
||||
//邮箱不能为空
|
||||
if m.Email == "" {
|
||||
return ErrMemberEmailEmpty
|
||||
}
|
||||
//用户描述必须小于500字
|
||||
if strings.Count(m.Description,"") > 500 {
|
||||
return ErrMemberDescriptionTooLong
|
||||
}
|
||||
//邮箱格式校验
|
||||
if ok,err := regexp.MatchString(conf.RegexpEmail,m.Email); !ok || err != nil || m.Email == "" {
|
||||
return ErrMemberEmailFormatError
|
||||
}
|
||||
//如果是未加密密码,需要校验密码格式
|
||||
if !is_hash_password {
|
||||
if l := strings.Count(m.Password,"") ; m.Password == "" || l > 50 || l < 6{
|
||||
return ErrMemberPasswordFormatError
|
||||
}
|
||||
}
|
||||
//校验邮箱是否呗使用
|
||||
if member,err := NewMember().FindByFieldFirst("email",m.Account); err == nil && member.MemberId > 0 {
|
||||
if m.MemberId > 0 && m.MemberId != member.MemberId {
|
||||
return ErrMemberEmailExist
|
||||
}
|
||||
if m.MemberId <= 0{
|
||||
return ErrMemberEmailExist
|
||||
}
|
||||
}
|
||||
if m.MemberId > 0{
|
||||
//校验用户是否存在
|
||||
if _,err := NewMember().Find(m.MemberId);err != nil {
|
||||
return err
|
||||
}
|
||||
}else{
|
||||
//校验账号格式是否正确
|
||||
if ok,err := regexp.MatchString(conf.RegexpAccount,m.Account); m.Account == "" || !ok || err != nil {
|
||||
return ErrMemberAccountFormatError
|
||||
}
|
||||
//校验账号是否被使用
|
||||
if member,err := NewMember().FindByAccount(m.Account); err == nil && member.MemberId > 0 {
|
||||
return ErrMemberExist
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@ func init() {
|
||||
|
||||
beego.Router("/manager", &controllers.ManagerController{},"*:Index")
|
||||
beego.Router("/manager/users", &controllers.ManagerController{},"*:Users")
|
||||
beego.Router("/manager/users/edit/:id", &controllers.ManagerController{},"*:EditMember")
|
||||
beego.Router("/manager/member/create", &controllers.ManagerController{},"post:CreateMember")
|
||||
beego.Router("/manager/member/update-member-status",&controllers.ManagerController{},"post:UpdateMemberStatus")
|
||||
beego.Router("/manager/member/change-member-role", &controllers.ManagerController{},"post:ChangeMemberRole")
|
||||
|
117
views/manager/edit_users.tpl
Normal file
117
views/manager/edit_users.tpl
Normal file
@ -0,0 +1,117 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>编辑用户 - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet">
|
||||
<link href="/static/css/main.css" rel="stylesheet">
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="/static/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||
<script src="/static/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="manual-reader">
|
||||
{{template "widgets/header.tpl" .}}
|
||||
<div class="container manual-body">
|
||||
<div class="row">
|
||||
<div class="page-left">
|
||||
<ul class="menu">
|
||||
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
|
||||
<li class="active"><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
|
||||
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
||||
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="page-right">
|
||||
<div class="m-box">
|
||||
<div class="box-head">
|
||||
<strong class="box-title"> 编辑用户</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body col-lg-6 col-sm-12">
|
||||
<form method="post" id="saveMemberInfoForm">
|
||||
<div class="form-group">
|
||||
<label>用户账号</label>
|
||||
<input type="text" class="form-control" name="account" disabled placeholder="用户账号" value="{{.Model.Account}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>用户密码</label>
|
||||
<input type="password" class="form-control" name="password1" placeholder="用户密码" maxlength="50">
|
||||
<p style="color: #999;font-size: 12px;">不修改密码请留空</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>确认密码</label>
|
||||
<input type="password" class="form-control" name="password2" placeholder="确认密码" maxlength="50">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>用户邮箱 <strong class="text-danger">*</strong></label>
|
||||
<input type="email" class="form-control" name="email" placeholder="用户邮箱" value="{{.Model.Email}}" maxlength="50">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>手机号码</label>
|
||||
<input type="text" class="form-control" name="phone" placeholder="手机号码" maxlength="50" value="{{.Model.Phone}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="description">描述</label>
|
||||
<textarea class="form-control" rows="3" title="描述" name="description" id="description" maxlength="500" >{{.Model.Description}}</textarea>
|
||||
<p style="color: #999;font-size: 12px;">描述不能超过500字</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" id="btnMemberInfo" class="btn btn-success" data-loading-text="保存中...">保存修改</button>
|
||||
<span id="form-error-message" class="error-message"></span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "widgets/footer.tpl" .}}
|
||||
</div>
|
||||
|
||||
|
||||
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||
<script src="/static/js/main.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$("#saveMemberInfoForm").ajaxForm({
|
||||
beforeSubmit : function () {
|
||||
var $then = $("#saveMemberInfoForm");
|
||||
|
||||
var email = $.trim($then.find("input[name='email']").val());
|
||||
var password1 = $.trim($then.find("input[name='password1']").val());
|
||||
var password2 = $.trim($then.find("input[name='password2']").val());
|
||||
if (email === ""){
|
||||
return showError("用户邮箱不能为空!");
|
||||
}
|
||||
if (password1 !== "" && password1 !== password2){
|
||||
return showError("确认密码不正确!");
|
||||
}
|
||||
$("#btnMemberInfo").button("loading");
|
||||
},success : function (res) {
|
||||
if(res.errcode === 0) {
|
||||
showSuccess("保存成功")
|
||||
}else{
|
||||
showError(res.message);
|
||||
}
|
||||
$("#btnMemberInfo").button("reset");
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -56,6 +56,7 @@
|
||||
<th width="80">头像</th>
|
||||
<th>账号</th>
|
||||
<th>角色</th>
|
||||
<th>类型</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
@ -69,6 +70,9 @@
|
||||
<template v-if="item.role == 0">
|
||||
超级管理员
|
||||
</template>
|
||||
<template v-else-if="item.member_id == {{.Member.MemberId}}">
|
||||
${item.role_name}
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@ -81,6 +85,9 @@
|
||||
</div>
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
${item.auth_method}
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="item.status == 0">
|
||||
<span class="label label-success">正常</span>
|
||||
@ -89,8 +96,15 @@
|
||||
<span class="label label-danger">禁用</span>
|
||||
</template>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<template v-if="item.role != 0">
|
||||
<template v-if="item.member_id == {{.Member.MemberId}}">
|
||||
|
||||
</template>
|
||||
<template v-else-if="item.role != 0">
|
||||
<a :href="'{{urlfor "ManagerController.EditMember" ":id" ""}}' + item.member_id" class="btn btn-sm btn-default" @click="editMember(item.member_id)">
|
||||
编辑
|
||||
</a>
|
||||
<template v-if="item.status == 0">
|
||||
<button type="button" class="btn btn-danger btn-sm" @click="setMemberStatus(item.member_id,1,$event)" data-loading-text="启用中...">禁用</button>
|
||||
</template>
|
||||
|
@ -62,7 +62,7 @@
|
||||
<li>
|
||||
<a href="{{urlfor "BookController.Index"}}" title="我的项目"><i class="fa fa-book" aria-hidden="true"></i> 我的项目</a>
|
||||
</li>
|
||||
{{if eq .Member.Role 0 }}
|
||||
{{if eq .Member.Role 0 1}}
|
||||
<li>
|
||||
<a href="{{urlfor "ManagerController.Index"}}" title="管理后台"><i class="fa fa-university" aria-hidden="true"></i> 管理后台</a>
|
||||
</li>
|
||||
|
Loading…
Reference in New Issue
Block a user