diff --git a/commands/command.go b/commands/command.go index 0b7f9dbe..3f722092 100644 --- a/commands/command.go +++ b/commands/command.go @@ -10,6 +10,7 @@ import ( "github.com/astaxie/beego/orm" "github.com/astaxie/beego/logs" "os" + "github.com/lifei6671/godoc/conf" ) // RegisterDataBase 注册数据库 @@ -33,13 +34,15 @@ func RegisterDataBase() { // RegisterModel 注册Model func RegisterModel() { - orm.RegisterModelWithPrefix("md_", + orm.RegisterModelWithPrefix(conf.GetDatabasePrefix(), new(models.Member), new(models.Book), new(models.Relationship), new(models.Comment), new(models.Option), new(models.Document), + new(models.Attachment), + new(models.Logger), ) } diff --git a/conf/enumerate.go b/conf/enumerate.go index cf14252b..471c6c3b 100644 --- a/conf/enumerate.go +++ b/conf/enumerate.go @@ -10,6 +10,30 @@ const RegexpEmail = `^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$` const RegexpAccount = `^[a-zA-Z][a-zA-z0-9]{2,50}$` +// PageSize 默认分页条数. +const PageSize = 15 + +// 用户权限 +const ( + // 超级管理员. + MemberSuperRole = 0 + //普通管理员. + MemberAdminRole = 1 + //普通用户. + MemberGeneralRole = 2 +) + +const ( + // 创始人. + BookFounder = 0 + //管理者 + BookAdmin = 1 + //编辑者. + BookEditor = 2 + //观察者 + BookObserver = 3 +) + // app_key func GetAppKey() (string) { return beego.AppConfig.DefaultString("app_key","go-git-webhook") diff --git a/controllers/account.go b/controllers/account.go index a6b17a67..6ef0669b 100644 --- a/controllers/account.go +++ b/controllers/account.go @@ -1,13 +1,13 @@ package controllers import ( - "fmt" "time" "github.com/lifei6671/godoc/conf" "github.com/lifei6671/godoc/models" "github.com/lifei6671/godoc/utils" "github.com/astaxie/beego" + "github.com/astaxie/beego/logs" ) // AccountController 用户登录与注册. @@ -38,8 +38,8 @@ func (c *AccountController) Login() { } if c.Ctx.Input.IsPost() { - account := c.GetString("inputAccount") - password := c.GetString("inputPassword") + account := c.GetString("account") + password := c.GetString("password") member,err := models.NewMember().Login(account,password) @@ -49,7 +49,7 @@ func (c *AccountController) Login() { c.JsonResult(0,"ok") c.StopRun() }else{ - fmt.Println(err) + logs.Error("用户登录 =>",err) c.JsonResult(500,"账号或密码错误",nil) } diff --git a/controllers/book.go b/controllers/book.go index 9fbc22d4..49c9127d 100644 --- a/controllers/book.go +++ b/controllers/book.go @@ -13,6 +13,7 @@ import ( "github.com/astaxie/beego" "github.com/astaxie/beego/orm" "github.com/astaxie/beego/logs" + "github.com/lifei6671/godoc/conf" ) type BookController struct { @@ -25,19 +26,22 @@ func (c *BookController) Index() { pageIndex, _ := c.GetInt("page", 1) - books,totalCount,err := models.NewBook().FindToPager(pageIndex,10,c.Member.MemberId) + books,totalCount,err := models.NewBook().FindToPager(pageIndex,conf.PageSize,c.Member.MemberId) if err != nil { c.Abort("500") } - html := utils.GetPagerHtml(c.Ctx.Request.RequestURI,pageIndex,10,totalCount) - - c.Data["PageHtml"] = html + if totalCount > 0 { + html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, totalCount) + c.Data["PageHtml"] = html + }else { + c.Data["PageHtml"] = "" + } b,err := json.Marshal(books) - if err != nil { + if err != nil || len(books) <= 0{ c.Data["Result"] = template.JS("[]") }else{ c.Data["Result"] = template.JS(string(b)) @@ -88,7 +92,8 @@ func (c *BookController) Setting() { c.Data["Model"] = *book } -//用户列表. + +// Users 用户列表. func (c *BookController) Users() { c.Prepare() c.TplName = "book/users.tpl" @@ -112,9 +117,13 @@ func (c *BookController) Users() { members,totalCount,err := models.NewMemberRelationshipResult().FindForUsersByBookId(book.BookId,pageIndex,15) - html := utils.GetPagerHtml(c.Ctx.Request.RequestURI,pageIndex,10,totalCount) + if totalCount > 0 { + html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, 10, totalCount) - c.Data["PageHtml"] = html + c.Data["PageHtml"] = html + }else{ + c.Data["PageHtml"] = "" + } b,err := json.Marshal(members) if err != nil { @@ -124,7 +133,7 @@ func (c *BookController) Users() { } } -// 参加参与用户. +// AddMember 参加参与用户. func (c *BookController) AddMember() { identify := c.GetString("identify") account := c.GetString("account") @@ -133,14 +142,14 @@ func (c *BookController) AddMember() { if identify == "" || account == ""{ c.JsonResult(6001,"参数错误") } - book ,err := models.NewBookResult().FindByIdentify("identify",c.Member.MemberId) + book ,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { c.JsonResult(403,"权限不足") } if err == orm.ErrNoRows { - c.JsonResult(404,"项目不能存在") + c.JsonResult(404,"项目不存在") } c.JsonResult(6002,err.Error()) } @@ -153,8 +162,11 @@ func (c *BookController) AddMember() { if err := member.FindByAccount(account) ; err != nil { c.JsonResult(404,"用户不存在") } + if member.Status == 1 { + c.JsonResult(6003,"用户已被禁用") + } - if _,err := models.NewRelationship().FindForRoleId(book.BookId,member.MemberId);err == orm.ErrNoRows { + if _,err := models.NewRelationship().FindForRoleId(book.BookId,member.MemberId);err == nil { c.JsonResult(6003,"用户已存在该项目中") } @@ -164,12 +176,104 @@ func (c *BookController) AddMember() { relationship.RoleId = role_id if err := relationship.Insert(); err == nil { - c.JsonResult(0,"ok",member) + memberRelationshipResult := models.NewMemberRelationshipResult().FromMember(member) + memberRelationshipResult.RoleId = role_id + memberRelationshipResult.RelationshipId = relationship.RelationshipId + memberRelationshipResult.BookId = book.BookId + memberRelationshipResult.ResolveRoleName() + + + c.JsonResult(0,"ok",memberRelationshipResult) } c.JsonResult(500,err.Error()) } -// 创建项目. +// 变更指定用户在指定项目中的权限 +func (c *BookController) ChangeRole() { + identify := c.GetString("identify") + member_id,_ := c.GetInt("member_id",0) + role,_ := c.GetInt("role_id",0) + + if identify == "" || member_id <=0 { + c.JsonResult(6001,"参数错误") + } + if member_id == c.Member.MemberId { + c.JsonResult(6006,"不能变更自己的权限") + } + book ,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId) + + if err != nil { + if err == models.ErrPermissionDenied { + c.JsonResult(403,"权限不足") + } + if err == orm.ErrNoRows { + c.JsonResult(404,"项目不存在") + } + c.JsonResult(6002,err.Error()) + } + if book.RoleId != 0 && book.RoleId != 1 { + c.JsonResult(403,"权限不足") + } + + member := models.NewMember() + + if err := member.Find(member_id); err != nil { + c.JsonResult(6003,"用户不存在") + } + if member.Status == 1 { + c.JsonResult(6004,"用户已被禁用") + } + + relationship,err := models.NewRelationship().UpdateRoleId(book.BookId,member_id,role); + + if err != nil { + logs.Error("变更用户在项目中的权限 => ",err) + c.JsonResult(6005,err.Error()) + } + + memberRelationshipResult := models.NewMemberRelationshipResult().FromMember(member) + memberRelationshipResult.RoleId = relationship.RoleId + memberRelationshipResult.RelationshipId = relationship.RelationshipId + memberRelationshipResult.BookId = book.BookId + memberRelationshipResult.ResolveRoleName() + + c.JsonResult(0,"ok",memberRelationshipResult) +} + +// 删除参与者. +func (c *BookController) RemoveMember() { + identify := c.GetString("identify") + member_id,_ := c.GetInt("member_id",0) + + if identify == "" || member_id <=0 { + c.JsonResult(6001,"参数错误") + } + if member_id == c.Member.MemberId { + c.JsonResult(6006,"不能变更自己的权限") + } + book ,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId) + + if err != nil { + if err == models.ErrPermissionDenied { + c.JsonResult(403,"权限不足") + } + if err == orm.ErrNoRows { + c.JsonResult(404,"项目不存在") + } + c.JsonResult(6002,err.Error()) + } + if book.RoleId != 0 && book.RoleId != 1 { + c.JsonResult(403,"权限不足") + } + err = models.NewRelationship().DeleteByBookIdAndMemberId(book.BookId,member_id) + + if err != nil { + c.JsonResult(6007,err.Error()) + } + c.JsonResult(0,"ok") +} + +// Create 创建项目. func (c *BookController) Create() { if c.Ctx.Input.IsPost() { @@ -203,7 +307,7 @@ func (c *BookController) Create() { book := models.NewBook() - if books,err := book.FindByField("identify",identify); err == nil || len(books) > 0 { + if books,_ := book.FindByField("identify",identify); len(books) > 0 { c.JsonResult(6006,"项目标识已存在") } @@ -224,7 +328,10 @@ func (c *BookController) Create() { if err != nil { c.JsonResult(6005,err.Error()) } - c.JsonResult(0,"ok",book) + bookResult := models.NewBookResult() + bookResult.FindByIdentify(book.Identify,c.Member.MemberId) + + c.JsonResult(0,"ok",bookResult) } c.JsonResult(6001,"error") } @@ -235,7 +342,7 @@ func (p *BookController) Edit() { } -//创建访问来令牌 +// CreateToken 创建访问来令牌. func (c *BookController) CreateToken() { book_id,_ := c.GetInt("book_id",0) @@ -268,7 +375,7 @@ func (c *BookController) CreateToken() { c.JsonResult(6001,"公开项目不能创建阅读令牌") } - book.PrivateToken = utils.Krand(20,utils.KC_RAND_KIND_ALL) + book.PrivateToken = string(utils.Krand(20,utils.KC_RAND_KIND_ALL)) if err := book.Update(); err != nil { logs.Error("生成阅读令牌失败 => ",err) c.JsonResult(6003,"生成阅读令牌失败") diff --git a/controllers/manager.go b/controllers/manager.go index 79e2b438..358efd8d 100644 --- a/controllers/manager.go +++ b/controllers/manager.go @@ -27,7 +27,7 @@ func (c *ManagerController) Users() { c.Prepare() c.TplName = "manager/users.tpl" - if c.Member.Role != 0 { + if !c.Member.IsAdministrator() { c.Abort("403") } @@ -40,9 +40,14 @@ func (c *ManagerController) Users() { return } - html := utils.GetPagerHtml(c.Ctx.Request.RequestURI,pageIndex,10,totalCount) + if totalCount > 0 { + html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, 10, int(totalCount)) + + c.Data["PageHtml"] = html + }else{ + c.Data["PageHtml"] = "" + } - c.Data["PageHtml"] = html b,err := json.Marshal(members) if err != nil { @@ -55,7 +60,7 @@ func (c *ManagerController) Users() { // 添加用户 func (c *ManagerController) CreateMember() { c.Prepare() - if c.Member.Role != 0{ + if !c.Member.IsAdministrator(){ c.Abort("403") } @@ -77,7 +82,7 @@ func (c *ManagerController) CreateMember() { c.JsonResult(6003,"确认密码不正确") } if ok,err := regexp.MatchString(conf.RegexpEmail,email); !ok || err != nil || email == "" { - c.JsonResult(6004,"邮箱不能为空") + c.JsonResult(6004,"邮箱格式不正确") } if role != 0 && role != 1 { role = 1 @@ -88,7 +93,7 @@ func (c *ManagerController) CreateMember() { member := models.NewMember() - if err := member.FindByAccount(account); err != nil { + if err := member.FindByAccount(account); err == nil && member.MemberId > 0 { c.JsonResult(6005,"账号已存在") } @@ -113,7 +118,7 @@ func (c *ManagerController) CreateMember() { func (c *ManagerController) UpdateMemberStatus() { c.Prepare() - if c.Member.Role != 0 { + if !c.Member.IsAdministrator() { c.Abort("403") } @@ -144,12 +149,43 @@ func (c *ManagerController) Books() { c.Prepare() c.TplName = "manager/books.tpl" + pageIndex, _ := c.GetInt("page", 1) + + books,totalCount,err := models.NewBookResult().FindToPager(pageIndex,conf.PageSize) + + if err != nil { + c.Abort("500") + } + + if totalCount > 0 { + html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, totalCount) + + c.Data["PageHtml"] = html + }else { + c.Data["PageHtml"] = "" + } + + c.Data["Lists"] = books +} + +func (c *ManagerController) EditBook() { + c.TplName = "manager/edit_book.tpl" + identify := c.GetString(":key") + + if identify == "" { + c.Abort("404") + } + book,err := models.NewBook().FindByFieldFirst("identify",identify) + if err != nil { + c.Abort("500") + } + c.Data["Model"] = book } // 删除项目. func (c *ManagerController) DeleteBook() { c.Prepare() - if c.Member.Role != 0 { + if !c.Member.IsAdministrator() { c.Abort("403") } @@ -174,7 +210,7 @@ func (c *ManagerController) DeleteBook() { func (c *ManagerController) Comments() { c.Prepare() - if c.Member.Role != 0 { + if !c.Member.IsAdministrator() { c.Abort("403") } } @@ -182,7 +218,7 @@ func (c *ManagerController) Comments() { //DeleteComment 标记评论为已删除 func (c *ManagerController) DeleteComment() { c.Prepare() - if c.Member.Role != 0 { + if !c.Member.IsAdministrator() { c.Abort("403") } comment_id,_ := c.GetInt("comment_id",0) diff --git a/models/attachment.go b/models/attachment.go new file mode 100644 index 00000000..559132e5 --- /dev/null +++ b/models/attachment.go @@ -0,0 +1,62 @@ +package models + +import ( + "time" + "github.com/lifei6671/godoc/conf" + "github.com/astaxie/beego/orm" +) + +// Attachment struct . +type Attachment struct { + AttachmentId int `orm:"column(attachment_id);pk;auto;unique" json:"attachment_id"` + DocumentId int `orm:"column(document_id);type(int)" json:"document_id"` + FileName string `orm:"column(file_name);size(2000)" json:"file_name"` + FileSize float64 `orm:"column(file_size);type(float)" json:"file_size"` + FileExt string `orm:"column(file_ext);size(50)" json:"file_ext"` + CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add"` + CreateAt int `orm:"column(create_at);type(int)" json:"create_at"` +} + + +// TableName 获取对应数据库表名. +func (m *Attachment) TableName() string { + return "attachment" +} +// TableEngine 获取数据使用的引擎. +func (m *Attachment) TableEngine() string { + return "INNODB" +} +func (m *Attachment) TableNameWithPrefix() string { + return conf.GetDatabasePrefix() + m.TableName() +} + +func NewAttachment() *Attachment { + return &Attachment{} +} + +func (m *Attachment) Insert() error { + o := orm.NewOrm() + + _,err := o.Insert(m) + + return err +} + +func (m *Attachment) Find(id int) (*Attachment,error) { + if id <= 0 { + return m,ErrInvalidParameter + } + o := orm.NewOrm() + + err := o.QueryTable(m.TableNameWithPrefix()).Filter("attachment_id",id).One(m) + + return m,err +} + + + + + + + + diff --git a/models/book.go b/models/book.go index e550b4e1..f9339d86 100644 --- a/models/book.go +++ b/models/book.go @@ -5,6 +5,7 @@ import ( "github.com/astaxie/beego/orm" "github.com/lifei6671/godoc/conf" + "github.com/astaxie/beego/logs" ) // Book struct . @@ -32,7 +33,7 @@ type Book struct { Cover string `orm:"column();size(1000)" json:"cover"` // CreateTime 创建时间 . - CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add"` + CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add" json:"create_time"` MemberId int `orm:"column(member_id);size(100)" json:"member_id"` ModifyTime time.Time `orm:"type(datetime);column(modify_time);null;auto_now" json:"modify_time"` Version int64 `orm:"type(bigint);column(version)" json:"version"` @@ -59,6 +60,14 @@ func (m *Book) Insert() error { o := orm.NewOrm() _,err := o.Insert(m) + if err == nil { + relationship := NewRelationship() + relationship.BookId = m.BookId + relationship.RoleId = 0 + relationship.MemberId = m.MemberId + err = relationship.Insert() + } + return err } @@ -87,7 +96,15 @@ func (m *Book) FindByField(field string,value interface{}) ([]Book,error) { return books,err } -func (m *Book) FindToPager(pageIndex, pageSize ,memberId int) (books []BookResult,totalCount int,err error){ +func (m *Book) FindByFieldFirst(field string,value interface{})(*Book,error) { + o := orm.NewOrm() + + err := o.QueryTable(conf.GetDatabasePrefix() + m.TableName()).Filter(field,value).One(m) + + return m,err + +} +func (m *Book) FindToPager(pageIndex, pageSize ,memberId int) (books []*BookResult,totalCount int,err error){ relationship := NewRelationship() @@ -116,12 +133,16 @@ func (m *Book) FindToPager(pageIndex, pageSize ,memberId int) (books []BookResul On("book.book_id=rel.book_id"). LeftJoin(NewMember().TableNameWithPrefix() + " AS m").On("rel.member_id=m.member_id AND rel.role_id=0"). Where("rel.member_id=?"). - OrderBy("book.order_index").Desc(). + OrderBy("book.order_index DESC ","book.book_id").Desc(). Limit(pageSize). Offset(offset) + //logs.Info("",qb2.String()) _,err = o.Raw(qb2.String(),memberId).QueryRows(&books) - + if err != nil { + logs.Error("分页查询项目列表 => ",err) + return + } sql := "SELECT m.account,doc.modify_time FROM md_documents AS doc LEFT JOIN md_members AS m ON doc.modify_at=m.member_id WHERE book_id = ? LIMIT 1 ORDER BY doc.modify_time DESC" if err == nil && len(books) > 0{ @@ -142,7 +163,7 @@ func (m *Book) FindToPager(pageIndex, pageSize ,memberId int) (books []BookResul book.RoleName = "管理员" }else if book.RoleId == 2 { book.RoleName = "编辑者" - }else if book.RoleId == 2 { + }else if book.RoleId == 3 { book.RoleName = "观察者" } } @@ -186,7 +207,7 @@ func (m *Book) ThoroughDeleteBook(id int) error { o.Rollback() return err } - sql4 := "DELETE FROM " + NewRelationship() + " WHERE book_id = ?" + sql4 := "DELETE FROM " + NewRelationship().TableNameWithPrefix() + " WHERE book_id = ?" _,err = o.Raw(sql4).Exec() diff --git a/models/book_result.go b/models/book_result.go index 6b60a370..2857f705 100644 --- a/models/book_result.go +++ b/models/book_result.go @@ -4,6 +4,7 @@ import ( "time" "github.com/astaxie/beego/orm" "strings" + "github.com/astaxie/beego/logs" ) type BookResult struct { @@ -23,6 +24,8 @@ type BookResult struct { Cover string `json:"cover"` Label string `json:"label"` MemberId int `json:"member_id"` + + RelationshipId int `json:"relationship_id"` RoleId int `json:"role_id"` RoleName string `json:"role_name"` Status int @@ -34,6 +37,7 @@ func NewBookResult() *BookResult { return &BookResult{} } +// 根据项目标识查询项目以及指定用户权限的信息. func (m *BookResult) FindByIdentify(identify string,member_id int) (*BookResult,error) { o := orm.NewOrm() @@ -57,6 +61,7 @@ func (m *BookResult) FindByIdentify(identify string,member_id int) (*BookResult, err = o.QueryTable(relationship.TableNameWithPrefix()).Filter("book_id",book.BookId).Filter("role_id",0).One(&relationship2) if err != nil { + logs.Error("根据项目标识查询项目以及指定用户权限的信息 => ",err) return m,ErrPermissionDenied } @@ -86,6 +91,7 @@ func (m *BookResult) FindByIdentify(identify string,member_id int) (*BookResult, m.MemberId = relationship.MemberId m.RoleId = relationship.RoleId + m.RelationshipId = relationship.RelationshipId if m.RoleId == 0{ m.RoleName = "创始人" @@ -112,3 +118,40 @@ func (m *BookResult) FindByIdentify(identify string,member_id int) (*BookResult, return m,nil } + +func (m *BookResult) FindToPager(pageIndex, pageSize int) (books []*BookResult,totalCount int,err error) { + o := orm.NewOrm() + + count,err := o.QueryTable(NewBook().TableNameWithPrefix()).Count() + + if err != nil { + return + } + totalCount = int(count) + + sql := "SELECT book.*,rel.relationship_id,rel.role_id,m.account AS create_name FROM md_books AS book LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.role_id = 0 LEFT JOIN md_members AS m ON rel.member_id = m.member_id ORDER BY book.order_index DESC ,book.book_id DESC LIMIT ?,?" + offset := (pageIndex -1 )* pageSize + + _,err = o.Raw(sql,offset,pageSize).QueryRows(&books) + + return +} + + + + + + + + + + + + + + + + + + + diff --git a/models/comment.go b/models/comment.go index 671ea804..a2e31f59 100644 --- a/models/comment.go +++ b/models/comment.go @@ -58,7 +58,7 @@ func (m *Comment) Find(id int) error { func (m *Comment) Update(cols... string) error { o := orm.NewOrm() - _,err := o.Update(m,cols) + _,err := o.Update(m,cols...) return err } diff --git a/models/logs.go b/models/logs.go new file mode 100644 index 00000000..b35998bd --- /dev/null +++ b/models/logs.go @@ -0,0 +1,55 @@ +package models + +import ( + "time" + "github.com/lifei6671/godoc/conf" +) + +const ( + Logger_Operate = "operate" + Logger_System = "system" + Logger_Exception = "exception" +) + +// Logger struct . +type Logger struct { + LoggerId int64 `orm:"pk;auto;unique;column(logger_id)" json:"logger_id"` + MemberId int `orm:"column(member_id);type(int)" json:"member_id"` + // 日志类别:operate 操作日志/ system 系统日志/ exception 异常日志 + Category string `orm:"column(category);size(255);default(operate)" json:"category"` + Content string `orm:"column(content);type(text)" json:"content"` + OriginalData string `orm:"column(original_data);type(text)" json:"original_data"` + PresentData string `orm:"column(present_data);type(text)" json:"present_data"` + CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add" json:"create_time"` + UserAgent string `orm:"column(user_agent);size(500)" json:"user_agent"` + IPAddress string `orm:"column(ip_address);size(255)" json:"ip_address"` +} + +// TableName 获取对应数据库表名. +func (m *Logger) TableName() string { + return "logs" +} +// TableEngine 获取数据使用的引擎. +func (m *Logger) TableEngine() string { + return "INNODB" +} +func (m *Logger) TableNameWithPrefix() string { + return conf.GetDatabasePrefix() + m.TableName() +} + + + + + + + + + + + + + + + + + diff --git a/models/member.go b/models/member.go index 5e843f83..bc03cb77 100644 --- a/models/member.go +++ b/models/member.go @@ -6,21 +6,25 @@ import ( "github.com/astaxie/beego/orm" "github.com/lifei6671/godoc/utils" "github.com/lifei6671/godoc/conf" + "github.com/astaxie/beego/logs" ) type Member struct { - MemberId int `orm:"pk;auto;unique;column(member_id)"` - Account string `orm:"size(100);unique;column(account)"` - Password string `orm:"size(1000);column(password)"` + MemberId int `orm:"pk;auto;unique;column(member_id)" json:"member_id"` + Account string `orm:"size(100);unique;column(account)" json:"account"` + Password string `orm:"size(1000);column(password)" json:"-"` Description string `orm:"column(description);size(2000)" json:"description"` - Email string `orm:"size(255);column(email);null;default(null)"` - Phone string `orm:"size(255);column(phone);null;default(null)"` - Avatar string `orm:"size(1000);column(avatar)"` - Role int `orm:"column(role);type(int);default(1);index"` //用户角色:0 管理员/ 1 普通用户 - Status int `orm:"column(status);type(int);default(0)"` //用户状态:0 正常/1 禁用 - CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add"` - CreateAt int `orm:"type(int);column(create_at)"` - LastLoginTime time.Time `orm:"type(datetime);column(last_login_time);null"` + Email string `orm:"size(255);column(email);null;default(null)" json:"email"` + Phone string `orm:"size(255);column(phone);null;default(null)" json:"phone"` + Avatar string `orm:"size(1000);column(avatar)" json:"avatar"` + //用户角色:0 超级管理员 /1 管理员/ 2 普通用户 . + Role int `orm:"column(role);type(int);default(1);index" json:"role"` + RoleName string `orm:"-" json:"role_name"` + Status int `orm:"column(status);type(int);default(0)" json:"status"` //用户状态:0 正常/1 禁用 + CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add" json:"create_time"` + CreateAt int `orm:"type(int);column(create_at)" json:"create_at"` + LastLoginTime time.Time `orm:"type(datetime);column(last_login_time);null" json:"last_login_time"` + } // TableName 获取对应数据库表名. @@ -46,9 +50,10 @@ func (m *Member) Login(account string,password string) (*Member,error) { member := &Member{} - err := o.QueryTable("md_" + m.TableName()).Filter("account",account).Filter("status",0).One(member); + err := o.QueryTable(m.TableNameWithPrefix()).Filter("account",account).Filter("status",0).One(member); if err != nil { + logs.Error("用户登录 => ",err) return member,ErrMemberNoExist } @@ -98,6 +103,13 @@ func (m *Member) Find(id int) error{ if err := o.Read(m); err != nil { return err } + if m.Role == 0 { + m.RoleName = "超级管理员" + }else if m.Role == 1 { + m.RoleName = "管理员" + }else if m.Role == 2 { + m.RoleName = "普通用户" + } return nil } @@ -106,13 +118,22 @@ func (m *Member) FindByAccount (account string) error { err := o.QueryTable(m.TableNameWithPrefix()).Filter("account",account).One(m) + if err == nil { + if m.Role == 0 { + m.RoleName = "超级管理员" + }else if m.Role == 1 { + m.RoleName = "管理员" + }else if m.Role == 2 { + m.RoleName = "普通用户" + } + } return err } -func (m *Member) FindToPager(pageIndex, pageSize int) ([]Member,int,error) { +func (m *Member) FindToPager(pageIndex, pageSize int) ([]*Member,int64,error) { o := orm.NewOrm() - var members []Member + var members []*Member offset := (pageIndex - 1) * pageSize @@ -122,16 +143,33 @@ func (m *Member) FindToPager(pageIndex, pageSize int) ([]Member,int,error) { return members,0,err } - _,err = o.QueryTable(m.TableNameWithPrefix()).Offset(offset).Limit(pageSize).All(&members) + _,err = o.QueryTable(m.TableNameWithPrefix()).OrderBy("-member_id").Offset(offset).Limit(pageSize).All(&members) if err != nil { return members,0,err } + for _,m := range members { + if m.Role == 0 { + m.RoleName = "超级管理员" + }else if m.Role == 1 { + m.RoleName = "管理员" + }else if m.Role == 2 { + m.RoleName = "普通用户" + } + } return members,totalCount,nil } +func (c *Member) IsAdministrator() bool { + if c == nil || c.MemberId <= 0{ + return false + } + return c.Role == 0 || c.Role == 1 +} + + diff --git a/models/member_result.go b/models/member_result.go index b570d90d..46491a91 100644 --- a/models/member_result.go +++ b/models/member_result.go @@ -3,6 +3,7 @@ package models import ( "time" "github.com/astaxie/beego/orm" + "github.com/lifei6671/godoc/conf" ) type MemberRelationshipResult struct { @@ -20,16 +21,43 @@ type MemberRelationshipResult struct { BookId int `json:"book_id"` // RoleId 角色:0 创始人(创始人不能被移除) / 1 管理员/2 编辑者/3 观察者 RoleId int `json:"role_id"` + RoleName string `json:"role_name"` } func NewMemberRelationshipResult() *MemberRelationshipResult { return &MemberRelationshipResult{} } -func (m *MemberRelationshipResult) FindForUsersByBookId(book_id ,pageIndex, pageSize int) ([]MemberRelationshipResult,int,error) { +func (m *MemberRelationshipResult) FromMember(member *Member) *MemberRelationshipResult { + m.MemberId = member.MemberId + m.Account = member.Account + m.Description = member.Description + m.Email = member.Email + m.Phone = member.Phone + m.Avatar = member.Avatar + m.Role = member.Role + m.Status = member.Status + m.CreateTime = member.CreateTime + m.CreateAt = member.CreateAt + + return m +} + +func (m *MemberRelationshipResult) ResolveRoleName () *MemberRelationshipResult { + if m.RoleId == conf.BookAdmin { + m.RoleName = "管理者" + }else if m.RoleId == conf.BookEditor { + m.RoleName = "编辑者" + }else if m.RoleId == conf.BookObserver { + m.RoleName = "观察者" + } + return m +} + +func (m *MemberRelationshipResult) FindForUsersByBookId(book_id ,pageIndex, pageSize int) ([]*MemberRelationshipResult,int,error) { o := orm.NewOrm() - var members []MemberRelationshipResult + var members []*MemberRelationshipResult sql1 := "SELECT * FROM md_relationship AS rel LEFT JOIN md_members as member ON rel.member_id = member.member_id WHERE rel.book_id = ? ORDER BY rel.relationship_id DESC LIMIT ?,?" @@ -51,6 +79,9 @@ func (m *MemberRelationshipResult) FindForUsersByBookId(book_id ,pageIndex, page return members,0,err } + for _,item := range members { + item.ResolveRoleName() + } return members,total_count,nil } diff --git a/models/relationship.go b/models/relationship.go index c483e037..65158962 100644 --- a/models/relationship.go +++ b/models/relationship.go @@ -3,6 +3,8 @@ package models import ( "github.com/lifei6671/godoc/conf" "github.com/astaxie/beego/orm" + "errors" + "github.com/astaxie/beego/logs" ) type Relationship struct { @@ -38,6 +40,42 @@ func NewRelationship() *Relationship { return &Relationship{} } +func (m *Relationship) Find(id int) (*Relationship,error) { + o := orm.NewOrm() + + err := o.QueryTable(m.TableNameWithPrefix()).Filter("relationship_id",id).One(m) + return m,err +} + +func (m *Relationship) UpdateRoleId(book_id,member_id, role_id int) (*Relationship,error) { + o := orm.NewOrm() + book := NewBook() + book.BookId = book_id + + if err := o.Read(book); err != nil { + logs.Error("UpdateRoleId => ", err) + return m,errors.New("项目不存在") + } + err := o.QueryTable(m.TableNameWithPrefix()).Filter("member_id",member_id).Filter("book_id",book_id).One(m) + + if err == orm.ErrNoRows { + m = NewRelationship() + m.BookId = book_id + m.MemberId = member_id + m.RoleId = role_id + }else if err != nil { + return m,err + }else if m.RoleId == conf.BookFounder{ + return m,errors.New("不能变更创始人的权限") + } + m.RoleId = role_id + + _,err = o.InsertOrUpdate(m) + + return m,err + +} + func (m *Relationship) FindForRoleId(book_id ,member_id int) (int,error) { o := orm.NewOrm() @@ -46,6 +84,7 @@ func (m *Relationship) FindForRoleId(book_id ,member_id int) (int,error) { err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("member_id",member_id).One(relationship) if err != nil { + return 0,err } return relationship.RoleId,nil @@ -67,5 +106,43 @@ func (m *Relationship) Update() error { return err } +func (m *Relationship) DeleteByBookIdAndMemberId(book_id,member_id int) error { + o := orm.NewOrm() + + err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("member_id",member_id).One(m) + + if err == orm.ErrNoRows { + return errors.New("用户未参与该项目") + } + if m.RoleId == conf.BookFounder { + return errors.New("不能删除创始人") + } + _,err = o.Delete(m) + + if err != nil { + logs.Error("删除项目参与者 => ",err) + return errors.New("删除失败") + } + return nil + +} + + + + + + + + + + + + + + + + + + diff --git a/routers/router.go b/routers/router.go index c5d73646..ae43eee8 100644 --- a/routers/router.go +++ b/routers/router.go @@ -15,6 +15,11 @@ func init() { beego.Router("/manager", &controllers.ManagerController{},"*:Index") beego.Router("/manager/users", &controllers.ManagerController{},"*:Users") + beego.Router("/manager/member/create", &controllers.ManagerController{},"post:CreateMember") + beego.Router("/manager/member/update-member-status",&controllers.ManagerController{},"post:UpdateMemberStatus") + beego.Router("/manager/books", &controllers.ManagerController{},"*:Books") + beego.Router("/manager/books/edit/:key", &controllers.ManagerController{},"*:EditBook") + beego.Router("/manager/comments", &controllers.ManagerController{},"*:Comments") beego.Router("/setting", &controllers.SettingController{},"*:Index") beego.Router("/setting/password", &controllers.SettingController{},"*:Password") @@ -26,7 +31,8 @@ func init() { beego.Router("/book/:key/users", &controllers.BookController{},"*:Users") beego.Router("/book/:key/edit", &controllers.BookController{},"*:Edit") beego.Router("/book/create", &controllers.BookController{},"*:Create") - beego.Router("/book/member/create", &controllers.BookController{},"POST:AddMember") + beego.Router("/book/member/create", &controllers.BookController{},"post:AddMember") + beego.Router("/book/member/change-role", &controllers.BookController{},"post:ChangeRole") beego.Router("/book/:key/users/create", &controllers.BookMemberController{},"*:Create") beego.Router("/book/:key/users/change", &controllers.BookMemberController{},"*:Change") diff --git a/static/images/book.jpg b/static/images/book.jpg new file mode 100644 index 00000000..4a29c860 Binary files /dev/null and b/static/images/book.jpg differ diff --git a/static/images/book.png b/static/images/book.png new file mode 100644 index 00000000..cb1fbaff Binary files /dev/null and b/static/images/book.png differ diff --git a/static/uploads/201704/avatar_1a17b5dc.jpeg b/static/uploads/201704/avatar_1a17b5dc.jpeg new file mode 100644 index 00000000..fc0e4825 Binary files /dev/null and b/static/uploads/201704/avatar_1a17b5dc.jpeg differ diff --git a/static/uploads/201704/avatar_29b82bd4.jpeg b/static/uploads/201704/avatar_29b82bd4.jpeg new file mode 100644 index 00000000..92ee9f17 Binary files /dev/null and b/static/uploads/201704/avatar_29b82bd4.jpeg differ diff --git a/static/uploads/201704/avatar_37594ca0.jpg b/static/uploads/201704/avatar_37594ca0.jpg new file mode 100644 index 00000000..eb04596a Binary files /dev/null and b/static/uploads/201704/avatar_37594ca0.jpg differ diff --git a/utils/pager.go b/utils/pager.go index 74c3b30e..8dafdcd4 100644 --- a/utils/pager.go +++ b/utils/pager.go @@ -8,6 +8,7 @@ import ( "github.com/astaxie/beego/orm" "fmt" + "math" ) type PageOptions struct { @@ -99,19 +100,21 @@ func GetPagerHtml(requestURI string,pageIndex, pageSize,totalCount int) (html.HT EnableFirstLastLink : true, ParamName : "page", } - setDefault(po,totalCount) + totalPages := int(math.Ceil(float64(totalCount) / float64(pageSize))) + + setDefault(po,totalPages) DealUri(po,requestURI) str := "" - if totalCount <= po.LinkItemCount { - str = fun1(po, totalCount) //显示完全 12345678910 - } else if totalCount > po.LinkItemCount { + if totalPages <= po.LinkItemCount { + str = fun1(po, totalPages) //显示完全 12345678910 + } else if totalPages > po.LinkItemCount { if po.CurrentPage < po.LinkItemCount { - str = fun2(po, totalCount) //123456789...200 + str = fun2(po, totalPages) //123456789...200 } else { - if po.CurrentPage + po.LinkItemCount < totalCount { - str = fun3(po, totalCount) + if po.CurrentPage + po.LinkItemCount < totalPages { + str = fun3(po, totalPages) } else { - str = fun4(po, totalCount) + str = fun4(po, totalPages) } } } diff --git a/views/account/login.tpl b/views/account/login.tpl index 51bcf017..e0ceb7b5 100644 --- a/views/account/login.tpl +++ b/views/account/login.tpl @@ -48,7 +48,7 @@
- + {{if ne .ENABLED_CAPTCHA "false"}} @@ -101,7 +101,7 @@ var $btn = $(this).button('loading'); var account = $.trim($("#account").val()); - var passwd = $.trim($("#passwd").val()); + var password = $.trim($("#password").val()); var code = $("#code").val(); if(account === ""){ $("#account").tooltip({placement:"auto",title : "账号不能为空",trigger : 'manual'}) @@ -110,8 +110,8 @@ $btn.button('reset'); return false; - }else if(passwd === ""){ - $("#passwd").tooltip({title : '密码不能为空',trigger : 'manual'}) + }else if(password === ""){ + $("#password").tooltip({title : '密码不能为空',trigger : 'manual'}) .tooltip('show') .parents('.form-group').addClass('has-error'); $btn.button('reset'); @@ -130,7 +130,7 @@ type : "POST", success : function (res) { - if(res.errcode != 20001){ + if(res.errcode !== 0){ $("#captcha-img").click(); $("#code").val(''); layer.msg(res.message); diff --git a/views/book/index.tpl b/views/book/index.tpl index 402f33e5..2f921047 100644 --- a/views/book/index.tpl +++ b/views/book/index.tpl @@ -36,10 +36,10 @@ -
-
+
+
- +
@@ -196,16 +200,17 @@ return showSuccess(""); }, success : function (res) { - console.log(res) + console.log(res); if(res.errcode === 0){ - + window.app.lists.splice(0,0,res.data); + $("#addBookDialogModal").modal("hide"); }else{ showError(res.message); } } }); - new Vue({ + window.app = new Vue({ el : "#bookList", data : { lists : {{.Result}} diff --git a/views/book/users.tpl b/views/book/users.tpl index 70c82076..b0a6c253 100644 --- a/views/book/users.tpl +++ b/views/book/users.tpl @@ -52,18 +52,31 @@ -