1、重新实现数据库初始化

2、新增超级管理员可以转让项目
3、新增超级管理员可以公开项目
pull/39/head
Minho 2017-05-11 13:39:34 +08:00
parent 45ef30c4d9
commit ca2e0478ca
15 changed files with 477 additions and 283 deletions

View File

@ -18,9 +18,9 @@ script:
before_deploy:
- sudo apt-get -qq update
- GOARCH=amd64 GOOS=linux go build -o godoc_linux_amd64 -ldflags="-w -X main.VERSION=$TAG -X 'main.BUILD_TIME=`date`' -X 'main.GO_VERSION=`go version`'"
- GOARCH=amd64 GOOS=darwin go build -o godoc_darwin_amd64 -ldflags="-w -X main.VERSION=$TAG -X 'main.BUILD_TIME=`date`' -X 'main.GO_VERSION=`go version`'"
- GOARCH=amd64 GOOS=windows go build -o godoc_windows_amd64.exe -ldflags="-w -X main.VERSION=$TAG -X 'main.BUILD_TIME=`date`' -X 'main.GO_VERSION=`go version`'"
- GOARCH=amd64 GOOS=linux go build -o godoc_linux_amd64 -ldflags="-w -X github.com/lifei6671/godoc/conf.VERSION=$TRAVIS_TAG -X 'github.com/lifei6671/godoc/conf.BUILD_TIME=`date`' -X 'conf.GO_VERSION=`github.com/lifei6671/godoc/go version`'"
- GOARCH=amd64 GOOS=darwin go build -o godoc_darwin_amd64 -ldflags="-w -X github.com/lifei6671/godoc/conf.VERSION=$TRAVIS_TAG -X 'github.com/lifei6671/godoc/conf.BUILD_TIME=`date`' -X 'conf.GO_VERSION=`github.com/lifei6671/godoc/go version`'"
- GOARCH=amd64 GOOS=windows go build -o godoc_windows_amd64.exe -ldflags="-w -X github.com/lifei6671/godoc/conf.VERSION=$TRAVIS_TAG -X 'github.com/lifei6671/godoc/conf.BUILD_TIME=`date`' -X 'conf.GO_VERSION=`github.com/lifei6671/godoc/go version`'"
- rm -rf commands controllers models modules data routers tasks vendor docs search utils graphics .git Godeps uploads/* .gitignore .travis.yml Dockerfile gide.yaml LICENSE main.go README.md conf/enumerate.go conf/mail.go install.lock *.md
- cp conf/app.conf.example conf/app.conf
- zip -r godoc_linux_amd64.zip conf logs static uploads views lib godoc_linux_amd64
@ -39,8 +39,4 @@ deploy:
overwrite: true
tags: true
all_branches: true
go: 1.8
env:
global:
- TAG: 0.1.3
go: 1.8

View File

@ -1,23 +1,22 @@
package commands
import (
"encoding/gob"
"fmt"
"net/url"
"time"
"os"
"encoding/gob"
"time"
"github.com/lifei6671/godoc/models"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/logs"
"github.com/lifei6671/godoc/conf"
"github.com/astaxie/beego/orm"
"github.com/lifei6671/gocaptcha"
"github.com/lifei6671/godoc/conf"
"github.com/lifei6671/godoc/models"
)
// RegisterDataBase 注册数据库
func RegisterDataBase() {
func RegisterDataBase() {
host := beego.AppConfig.String("db_host")
database := beego.AppConfig.String("db_database")
username := beego.AppConfig.String("db_username")
@ -26,22 +25,21 @@ func RegisterDataBase() {
port := beego.AppConfig.String("db_port")
dataSource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true&loc=%s",username,password,host,port,database,url.QueryEscape(timezone))
dataSource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true&loc=%s", username, password, host, port, database, url.QueryEscape(timezone))
orm.RegisterDataBase("default", "mysql", dataSource)
location , err := time.LoadLocation(timezone);
location, err := time.LoadLocation(timezone)
if err == nil {
orm.DefaultTimeLoc = location
}else{
} else {
fmt.Println(err)
}
}
// RegisterModel 注册Model
func RegisterModel() {
func RegisterModel() {
orm.RegisterModelWithPrefix(conf.GetDatabasePrefix(),
new(models.Member),
new(models.Book),
@ -57,88 +55,20 @@ func RegisterModel() {
}
//初始化数据
func Initialization() {
o := orm.NewOrm()
_,err := o.Raw(`INSERT INTO md_options (option_title, option_name, option_value) SELECT '是否启用注册','ENABLED_REGISTER','false' FROM dual WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'ENABLED_REGISTER');`).Exec()
if err != nil {
panic("ENABLED_REGISTER => " + err.Error())
os.Exit(1)
}
_,err = o.Raw(`INSERT INTO md_options (option_title, option_name, option_value) SELECT '是否启用验证码','ENABLED_CAPTCHA','false' FROM dual WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'ENABLED_CAPTCHA');`).Exec()
if err != nil {
panic("ENABLED_CAPTCHA => " + err.Error())
os.Exit(1)
}
_,err = o.Raw(`INSERT INTO md_options (option_title, option_name, option_value) SELECT '启用匿名访问','ENABLE_ANONYMOUS','true' FROM dual WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'ENABLE_ANONYMOUS');`).Exec()
if err != nil {
panic("ENABLE_ANONYMOUS => " + err.Error())
os.Exit(1)
}
_,err = o.Raw(`INSERT INTO md_options (option_title, option_name, option_value) SELECT '站点名称','SITE_NAME','MinDoc' FROM dual WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'SITE_NAME');`).Exec()
if err != nil {
panic("SITE_NAME => " + err.Error())
os.Exit(1)
}
member,err := models.NewMember().FindByFieldFirst("account","admin")
if err == orm.ErrNoRows {
member.Account = "admin"
member.Avatar = "/static/images/headimgurl.jpg"
member.Password = "123456"
member.Role = 0
member.Email = "admin@iminho.me"
if err := member.Add(); err != nil {
panic("Member.Add => " + err.Error())
os.Exit(0)
}
book := models.NewBook()
book.MemberId = member.MemberId
book.BookName = "MinDoc演示项目"
book.Status = 0
book.Description = "这是一个MinDoc演示项目该项目是由系统初始化时自动创建。"
book.CommentCount = 0
book.PrivatelyOwned = 0
book.CommentStatus = "closed"
book.Identify = "mindoc"
book.DocCount = 0
book.CommentCount = 0
book.Version = time.Now().Unix()
book.Cover = conf.GetDefaultCover()
book.Editor = "markdown"
book.Theme = "default"
if err := book.Insert(); err != nil {
panic("Book.Insert => " + err.Error())
os.Exit(0)
}
}
}
// RegisterLogger 注册日志
func RegisterLogger() {
func RegisterLogger() {
logs.SetLogFuncCall(true)
logs.SetLogger("console")
logs.EnableFuncCallDepth(true)
logs.Async()
if _,err := os.Stat("logs/log.log"); os.IsNotExist(err) {
os.MkdirAll("./logs",0777)
if _, err := os.Stat("logs/log.log"); os.IsNotExist(err) {
os.MkdirAll("./logs", 0777)
if f,err := os.Create("logs/log.log");err == nil {
if f, err := os.Create("logs/log.log"); err == nil {
f.Close()
beego.SetLogger("file",`{"filename":"logs/log.log"}`)
beego.SetLogger("file", `{"filename":"logs/log.log"}`)
}
}
@ -149,26 +79,16 @@ func RegisterLogger() {
// RunCommand 注册orm命令行工具
func RegisterCommand() {
if _,err := os.Stat("install.lock"); os.IsNotExist(err){
err = orm.RunSyncdb("default",false,true)
if err == nil {
Initialization()
f, _ := os.Create("install.lock")
defer f.Close()
}else{
panic(err.Error())
os.Exit(0)
}
}
Install()
Update()
CheckUpdate()
}
func RegisterFunction() {
beego.AddFuncMap("config",models.GetOptionValue)
func RegisterFunction() {
beego.AddFuncMap("config", models.GetOptionValue)
}
func init() {
func init() {
gocaptcha.ReadFonts("./static/fonts", ".ttf")
gob.Register(models.Member{})
}
}

View File

@ -0,0 +1,96 @@
package commands
import (
"fmt"
"os"
"time"
"github.com/astaxie/beego/orm"
"github.com/lifei6671/godoc/conf"
"github.com/lifei6671/godoc/models"
)
//系统安装.
func Install() {
if len(os.Args) >= 2 && os.Args[1] == "install" {
fmt.Println("Initializing...")
err := orm.RunSyncdb("default", false, true)
if err == nil {
initialization()
} else {
panic(err.Error())
os.Exit(1)
}
fmt.Println("Install Successfully!")
os.Exit(0)
}
}
//初始化数据
func initialization() {
o := orm.NewOrm()
_, err := o.Raw(`INSERT INTO md_options (option_title, option_name, option_value) SELECT '是否启用注册','ENABLED_REGISTER','false' FROM dual WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'ENABLED_REGISTER');`).Exec()
if err != nil {
panic("ENABLED_REGISTER => " + err.Error())
os.Exit(1)
}
_, err = o.Raw(`INSERT INTO md_options (option_title, option_name, option_value) SELECT '是否启用验证码','ENABLED_CAPTCHA','false' FROM dual WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'ENABLED_CAPTCHA');`).Exec()
if err != nil {
panic("ENABLED_CAPTCHA => " + err.Error())
os.Exit(1)
}
_, err = o.Raw(`INSERT INTO md_options (option_title, option_name, option_value) SELECT '启用匿名访问','ENABLE_ANONYMOUS','true' FROM dual WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'ENABLE_ANONYMOUS');`).Exec()
if err != nil {
panic("ENABLE_ANONYMOUS => " + err.Error())
os.Exit(1)
}
_, err = o.Raw(`INSERT INTO md_options (option_title, option_name, option_value) SELECT '站点名称','SITE_NAME','MinDoc' FROM dual WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'SITE_NAME');`).Exec()
if err != nil {
panic("SITE_NAME => " + err.Error())
os.Exit(1)
}
member, err := models.NewMember().FindByFieldFirst("account", "admin")
if err == orm.ErrNoRows {
member.Account = "admin"
member.Avatar = "/static/images/headimgurl.jpg"
member.Password = "123456"
member.Role = 0
member.Email = "admin@iminho.me"
if err := member.Add(); err != nil {
panic("Member.Add => " + err.Error())
os.Exit(0)
}
book := models.NewBook()
book.MemberId = member.MemberId
book.BookName = "MinDoc演示项目"
book.Status = 0
book.Description = "这是一个MinDoc演示项目该项目是由系统初始化时自动创建。"
book.CommentCount = 0
book.PrivatelyOwned = 0
book.CommentStatus = "closed"
book.Identify = "mindoc"
book.DocCount = 0
book.CommentCount = 0
book.Version = time.Now().Unix()
book.Cover = conf.GetDefaultCover()
book.Editor = "markdown"
book.Theme = "default"
if err := book.Insert(); err != nil {
panic("Book.Insert => " + err.Error())
os.Exit(0)
}
}
}

View File

@ -1,16 +1,21 @@
package commands
import (
"os"
"net/http"
"github.com/astaxie/beego"
"encoding/json"
"io/ioutil"
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/astaxie/beego"
"github.com/lifei6671/godoc/conf"
)
func Update() {
if len(os.Args) > 2 && os.Args[1] == "update" {
//系统升级.
func Update() {
if len(os.Args) >= 2 && os.Args[1] == "update" {
fmt.Println("update successed.")
os.Exit(0)
}
@ -45,8 +50,8 @@ func CheckUpdate() {
beego.Error("CheckUpdate => ", err)
os.Exit(1)
}
fmt.Println("MinDoc last version => ",result[0].Name)
fmt.Println("MinDoc current version => ", conf.VERSION)
fmt.Println("MinDoc last version => ", result[0].Name)
os.Exit(0)
}
}
}

View File

@ -2,21 +2,22 @@
package conf
import (
"github.com/astaxie/beego"
"strings"
"github.com/astaxie/beego"
)
// 登录用户的Session名
const LoginSessionName = "LoginSessionName"
const CaptchaSessionName = "__captcha__"
const CaptchaSessionName = "__captcha__"
const RegexpEmail = `^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$`
const RegexpEmail = `^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$`
const RegexpAccount = `^[a-zA-Z][a-zA-z0-9]{2,50}$`
// PageSize 默认分页条数.
const PageSize = 15
const PageSize = 15
// 用户权限
const (
@ -40,43 +41,45 @@ const (
)
var (
VERSION string
VERSION string
BUILD_TIME string
GO_VERSION string
)
// app_key
func GetAppKey() (string) {
return beego.AppConfig.DefaultString("app_key","godoc")
func GetAppKey() string {
return beego.AppConfig.DefaultString("app_key", "godoc")
}
func GetDatabasePrefix() string {
return beego.AppConfig.DefaultString("db_prefix","md_")
func GetDatabasePrefix() string {
return beego.AppConfig.DefaultString("db_prefix", "md_")
}
//获取默认头像
func GetDefaultAvatar() string {
return beego.AppConfig.DefaultString("avatar","/static/images/headimgurl.jpg")
return beego.AppConfig.DefaultString("avatar", "/static/images/headimgurl.jpg")
}
//获取阅读令牌长度.
func GetTokenSize() int {
return beego.AppConfig.DefaultInt("token_size",12)
return beego.AppConfig.DefaultInt("token_size", 12)
}
//获取默认文档封面.
func GetDefaultCover() string {
return beego.AppConfig.DefaultString("cover","/static/images/book.jpg")
return beego.AppConfig.DefaultString("cover", "/static/images/book.jpg")
}
//获取允许的商城文件的类型.
func GetUploadFileExt() []string {
ext := beego.AppConfig.DefaultString("upload_file_ext","png|jpg|jpeg|gif|txt|doc|docx|pdf")
temp := strings.Split(ext,"|")
exts := make([]string,len(temp))
func GetUploadFileExt() []string {
ext := beego.AppConfig.DefaultString("upload_file_ext", "png|jpg|jpeg|gif|txt|doc|docx|pdf")
temp := strings.Split(ext, "|")
exts := make([]string, len(temp))
i := 0
for _,item := range temp {
for _, item := range temp {
if item != "" {
exts[i] = item
i++
@ -86,23 +89,17 @@ func GetUploadFileExt() []string {
}
//判断是否是允许商城的文件类型.
func IsAllowUploadFileExt(ext string) bool {
func IsAllowUploadFileExt(ext string) bool {
if strings.HasPrefix(ext,".") {
if strings.HasPrefix(ext, ".") {
ext = string(ext[1:])
}
exts := GetUploadFileExt()
for _,item := range exts {
if strings.EqualFold(item,ext) {
return true
for _, item := range exts {
if strings.EqualFold(item, ext) {
return true
}
}
return false
}
//获取当前版本.
func Version() string {
return VERSION
}

View File

@ -161,6 +161,7 @@ func (c *BookController) SaveBook() {
c.JsonResult(0,"ok",bookResult)
}
//设置项目私有状态.
func (c *BookController) PrivatelyOwned() {
status := c.GetString("status")
@ -184,7 +185,6 @@ func (c *BookController) PrivatelyOwned() {
if bookResult.RoleId != conf.BookFounder {
c.JsonResult(6002,"权限不足")
}
fmt.Printf("%+v",bookResult)
book,err := models.NewBook().Find(bookResult.BookId)
@ -193,8 +193,6 @@ func (c *BookController) PrivatelyOwned() {
}
book.PrivatelyOwned = state
logs.Info("",state,status)
err = book.Update()
if err != nil {

View File

@ -1,18 +1,17 @@
package controllers
import (
"encoding/json"
"html/template"
"strings"
"regexp"
"strings"
"github.com/lifei6671/godoc/conf"
"github.com/astaxie/beego/logs"
"github.com/lifei6671/godoc/utils"
"github.com/lifei6671/godoc/models"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"github.com/lifei6671/godoc/conf"
"github.com/lifei6671/godoc/models"
"github.com/lifei6671/godoc/utils"
)
type ManagerController struct {
@ -29,7 +28,7 @@ func (c *ManagerController) Index() {
}
// 用户列表.
func (c *ManagerController) Users() {
func (c *ManagerController) Users() {
c.Prepare()
c.TplName = "manager/users.tpl"
@ -37,9 +36,9 @@ func (c *ManagerController) Users() {
c.Abort("403")
}
pageIndex,_ := c.GetInt("page",0)
pageIndex, _ := c.GetInt("page", 0)
members,totalCount,err := models.NewMember().FindToPager(pageIndex,15)
members, totalCount, err := models.NewMember().FindToPager(pageIndex, 15)
if err != nil {
c.Data["ErrorMessage"] = err.Error()
@ -50,23 +49,23 @@ func (c *ManagerController) Users() {
html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, 10, int(totalCount))
c.Data["PageHtml"] = html
}else{
} else {
c.Data["PageHtml"] = ""
}
b,err := json.Marshal(members)
b, err := json.Marshal(members)
if err != nil {
c.Data["Result"] = template.JS("[]")
}else{
} else {
c.Data["Result"] = template.JS(string(b))
}
}
// 添加用户
// 添加用户.
func (c *ManagerController) CreateMember() {
c.Prepare()
if !c.Member.IsAdministrator(){
if !c.Member.IsAdministrator() {
c.Abort("403")
}
@ -75,22 +74,22 @@ func (c *ManagerController) CreateMember() {
password2 := strings.TrimSpace(c.GetString("password2"))
email := strings.TrimSpace(c.GetString("email"))
phone := strings.TrimSpace(c.GetString("phone"))
role,_ := c.GetInt("role",1)
status,_ := c.GetInt("status",0)
role, _ := c.GetInt("role", 1)
status, _ := c.GetInt("status", 0)
if ok,err := regexp.MatchString(conf.RegexpAccount,account); account == "" || !ok || err != nil {
c.JsonResult(6001,"账号只能由英文字母数字组成且在3-50个字符")
if ok, err := regexp.MatchString(conf.RegexpAccount, account); account == "" || !ok || err != nil {
c.JsonResult(6001, "账号只能由英文字母数字组成且在3-50个字符")
}
if l := strings.Count(password1,"") ; password1 == "" || l > 50 || l < 6{
c.JsonResult(6002,"密码必须在6-50个字符之间")
if l := strings.Count(password1, ""); password1 == "" || l > 50 || l < 6 {
c.JsonResult(6002, "密码必须在6-50个字符之间")
}
if password1 != password2 {
c.JsonResult(6003,"确认密码不正确")
c.JsonResult(6003, "确认密码不正确")
}
if ok,err := regexp.MatchString(conf.RegexpEmail,email); !ok || err != nil || email == "" {
c.JsonResult(6004,"邮箱格式不正确")
if ok, err := regexp.MatchString(conf.RegexpEmail, email); !ok || err != nil || email == "" {
c.JsonResult(6004, "邮箱格式不正确")
}
if role != 0 && role != 1 {
if role != 0 && role != 1 && role != 2 {
role = 1
}
if status != 0 && status != 1 {
@ -99,8 +98,8 @@ func (c *ManagerController) CreateMember() {
member := models.NewMember()
if _,err := member.FindByAccount(account); err == nil && member.MemberId > 0 {
c.JsonResult(6005,"账号已存在")
if _, err := member.FindByAccount(account); err == nil && member.MemberId > 0 {
c.JsonResult(6005, "账号已存在")
}
member.Account = account
@ -114,80 +113,81 @@ func (c *ManagerController) CreateMember() {
}
if err := member.Add(); err != nil {
c.JsonResult(6006,err.Error())
c.JsonResult(6006, err.Error())
}
c.JsonResult(0,"ok",member)
c.JsonResult(0, "ok", member)
}
//更新用户状态.
func (c *ManagerController) UpdateMemberStatus() {
func (c *ManagerController) UpdateMemberStatus() {
c.Prepare()
if !c.Member.IsAdministrator() {
c.Abort("403")
}
member_id,_ := c.GetInt("member_id",0)
status ,_ := c.GetInt("status",0)
member_id, _ := c.GetInt("member_id", 0)
status, _ := c.GetInt("status", 0)
if member_id <= 0 {
c.JsonResult(6001,"参数错误")
c.JsonResult(6001, "参数错误")
}
if status != 0 && status != 1 {
status = 0
}
member := models.NewMember()
if _,err := member.Find(member_id); err != nil {
c.JsonResult(6002,"用户不存在")
if _, err := member.Find(member_id); err != nil {
c.JsonResult(6002, "用户不存在")
}
member.Status = status
if err := member.Update();err != nil {
logs.Error("",err)
c.JsonResult(6003,"用户状态设置失败")
if err := member.Update(); err != nil {
logs.Error("", err)
c.JsonResult(6003, "用户状态设置失败")
}
c.JsonResult(0,"ok",member)
c.JsonResult(0, "ok", member)
}
func (c *ManagerController) ChangeMemberRole() {
//变更用户权限.
func (c *ManagerController) ChangeMemberRole() {
c.Prepare()
if !c.Member.IsAdministrator() {
c.Abort("403")
}
member_id,_ := c.GetInt("member_id",0)
role ,_ := c.GetInt("role",0)
member_id, _ := c.GetInt("member_id", 0)
role, _ := c.GetInt("role", 0)
if member_id <= 0 {
c.JsonResult(6001,"参数错误")
c.JsonResult(6001, "参数错误")
}
if role != conf.MemberAdminRole && role != conf.MemberGeneralRole {
c.JsonResult(6001,"用户权限不正确")
c.JsonResult(6001, "用户权限不正确")
}
member := models.NewMember()
if _,err := member.Find(member_id); err != nil {
c.JsonResult(6002,"用户不存在")
if _, err := member.Find(member_id); err != nil {
c.JsonResult(6002, "用户不存在")
}
member.Role = role
if err := member.Update();err != nil {
logs.Error("",err)
c.JsonResult(6003,"用户权限设置失败")
if err := member.Update(); err != nil {
logs.Error("", err)
c.JsonResult(6003, "用户权限设置失败")
}
member.ResolveRoleName()
c.JsonResult(0,"ok",member)
c.JsonResult(0, "ok", member)
}
func (c *ManagerController) Books() {
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)
books, totalCount, err := models.NewBookResult().FindToPager(pageIndex, conf.PageSize)
if err != nil {
c.Abort("500")
@ -197,7 +197,7 @@ func (c *ManagerController) Books() {
html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, totalCount)
c.Data["PageHtml"] = html
}else {
} else {
c.Data["PageHtml"] = ""
}
@ -205,80 +205,79 @@ func (c *ManagerController) Books() {
}
//编辑项目
func (c *ManagerController) EditBook() {
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)
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
c.Abort("500")
}
if c.Ctx.Input.IsPost() {
book_name := strings.TrimSpace(c.GetString("book_name"))
description := strings.TrimSpace(c.GetString("description",""))
description := strings.TrimSpace(c.GetString("description", ""))
comment_status := c.GetString("comment_status")
tag := strings.TrimSpace(c.GetString("label"))
order_index ,_ := c.GetInt("order_index",0)
order_index, _ := c.GetInt("order_index", 0)
if strings.Count(description,"") > 500 {
c.JsonResult(6004,"项目描述不能大于500字")
if strings.Count(description, "") > 500 {
c.JsonResult(6004, "项目描述不能大于500字")
}
if comment_status != "open" && comment_status != "closed" && comment_status != "group_only" && comment_status != "registered_only" {
comment_status = "closed"
}
if tag != ""{
tags := strings.Split(tag,";")
if tag != "" {
tags := strings.Split(tag, ";")
if len(tags) > 10 {
c.JsonResult(6005,"最多允许添加10个标签")
c.JsonResult(6005, "最多允许添加10个标签")
}
}
book.BookName = book_name
book.Description = description
book.CommentStatus = comment_status
book.Label = tag
book.OrderIndex = order_index
if err := book.Update();err != nil {
c.JsonResult(6006,"保存失败")
if err := book.Update(); err != nil {
c.JsonResult(6006, "保存失败")
}
c.JsonResult(0,"ok")
c.JsonResult(0, "ok")
}
if book.PrivateToken != "" {
book.PrivateToken = c.BaseUrl() + beego.URLFor("DocumentController.Index",":key",book.Identify,"token",book.PrivateToken)
book.PrivateToken = c.BaseUrl() + beego.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken)
}
c.Data["Model"] = book
}
// 删除项目.
func (c *ManagerController) DeleteBook() {
func (c *ManagerController) DeleteBook() {
c.Prepare()
if !c.Member.IsAdministrator() {
c.Abort("403")
}
book_id,_ := c.GetInt("book_id",0)
book_id, _ := c.GetInt("book_id", 0)
if book_id <= 0{
c.JsonResult(6001,"参数错误")
if book_id <= 0 {
c.JsonResult(6001, "参数错误")
}
book := models.NewBook()
err := book.ThoroughDeleteBook(book_id)
if err == orm.ErrNoRows {
c.JsonResult(6002,"项目不存在")
c.JsonResult(6002, "项目不存在")
}
if err != nil {
logs.Error("DeleteBook => ",err)
c.JsonResult(6003,"删除失败")
logs.Error("DeleteBook => ", err)
c.JsonResult(6003, "删除失败")
}
c.JsonResult(0,"ok")
c.JsonResult(0, "ok")
}
// CreateToken 创建访问来令牌.
@ -288,10 +287,10 @@ func (c *ManagerController) CreateToken() {
identify := c.GetString("identify")
book,err := models.NewBook().FindByFieldFirst("identify",identify);
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
c.JsonResult(6001,"项目不存在")
c.JsonResult(6001, "项目不存在")
}
if action == "create" {
@ -304,17 +303,18 @@ func (c *ManagerController) CreateToken() {
logs.Error("生成阅读令牌失败 => ", err)
c.JsonResult(6003, "生成阅读令牌失败")
}
c.JsonResult(0, "ok", c.BaseUrl() + beego.URLFor("DocumentController.Index",":key",book.Identify,"token",book.PrivateToken))
}else{
c.JsonResult(0, "ok", c.BaseUrl()+beego.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken))
} else {
book.PrivateToken = ""
if err := book.Update();err != nil {
logs.Error("CreateToken => ",err)
c.JsonResult(6004,"删除令牌失败")
if err := book.Update(); err != nil {
logs.Error("CreateToken => ", err)
c.JsonResult(6004, "删除令牌失败")
}
c.JsonResult(0,"ok","")
c.JsonResult(0, "ok", "")
}
}
//项目设置.
func (c *ManagerController) Setting() {
c.Prepare()
c.TplName = "manager/setting.tpl"
@ -323,14 +323,14 @@ func (c *ManagerController) Setting() {
c.Abort("403")
}
options,err := models.NewOption().All()
options, err := models.NewOption().All()
if c.Ctx.Input.IsPost() {
for _,item := range options {
for _, item := range options {
item.OptionValue = c.GetString(item.OptionName)
item.InsertOrUpdate()
}
c.JsonResult(0,"ok")
c.JsonResult(0, "ok")
}
if err != nil {
@ -338,14 +338,60 @@ func (c *ManagerController) Setting() {
}
c.Data["SITE_TITLE"] = c.Option["SITE_NAME"]
for _,item := range options {
for _, item := range options {
c.Data[item.OptionName] = item
}
}
func (c *ManagerController) Comments() {
// Transfer 转让项目.
func (c *ManagerController) Transfer() {
c.Prepare()
account := c.GetString("account")
if account == "" {
c.JsonResult(6004, "接受者账号不能为空")
}
member, err := models.NewMember().FindByAccount(account)
if err != nil {
logs.Error("FindByAccount => ", err)
c.JsonResult(6005, "接受用户不存在")
}
if member.Status != 0 {
c.JsonResult(6006, "接受用户已被禁用")
}
if !c.Member.IsAdministrator() {
c.Abort("403")
}
identify := c.GetString("identify")
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
c.JsonResult(6001, err.Error())
}
rel, err := models.NewRelationship().FindFounder(book.BookId)
if err != nil {
beego.Error("FindFounder => ", err)
c.JsonResult(6009, "查询项目创始人失败")
}
if member.MemberId == rel.MemberId {
c.JsonResult(6007, "不能转让给自己")
}
err = models.NewRelationship().Transfer(book.BookId, rel.MemberId, member.MemberId)
if err != nil {
logs.Error("Transfer => ", err)
c.JsonResult(6008, err.Error())
}
c.JsonResult(0, "ok")
}
func (c *ManagerController) Comments() {
c.Prepare()
c.TplName = "manager/comments.tpl"
if !c.Member.IsAdministrator() {
@ -355,49 +401,65 @@ func (c *ManagerController) Comments() {
}
//DeleteComment 标记评论为已删除
func (c *ManagerController) DeleteComment() {
func (c *ManagerController) DeleteComment() {
c.Prepare()
if !c.Member.IsAdministrator() {
c.Abort("403")
}
comment_id,_ := c.GetInt("comment_id",0)
comment_id, _ := c.GetInt("comment_id", 0)
if comment_id <= 0 {
c.JsonResult(6001,"参数错误")
c.JsonResult(6001, "参数错误")
}
comment := models.NewComment()
if _,err := comment.Find(comment_id); err != nil {
c.JsonResult(6002,"评论不存在")
if _, err := comment.Find(comment_id); err != nil {
c.JsonResult(6002, "评论不存在")
}
comment.Approved = 3
if err := comment.Update("approved");err != nil {
c.JsonResult(6003,"删除评论失败")
if err := comment.Update("approved"); err != nil {
c.JsonResult(6003, "删除评论失败")
}
c.JsonResult(0,"ok",comment)
c.JsonResult(0, "ok", comment)
}
//设置项目私有状态.
func (c *ManagerController) PrivatelyOwned() {
status := c.GetString("status")
identify := c.GetString("identify")
if status != "open" && status != "close" {
c.JsonResult(6003, "参数错误")
}
state := 0
if status == "open" {
state = 0
} else {
state = 1
}
if !c.Member.IsAdministrator() {
c.Abort("403")
}
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
c.JsonResult(6001, err.Error())
}
book.PrivatelyOwned = state
logs.Info("", state, status)
err = book.Update()
if err != nil {
logs.Error("PrivatelyOwned => ", err)
c.JsonResult(6004, "保存失败")
}
c.JsonResult(0, "ok")
}

View File

@ -36,6 +36,7 @@ func (c *SettingController) Index() {
if err := member.Update(); err != nil {
c.JsonResult(602, err.Error())
}
c.SetMember(*member)
c.JsonResult(0, "ok")
}
}

24
main.go
View File

@ -3,37 +3,31 @@ package main
import (
"fmt"
"os"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lifei6671/godoc/routers"
_ "github.com/astaxie/beego/session/redis"
"github.com/astaxie/beego"
_ "github.com/astaxie/beego/session/memcache"
_ "github.com/astaxie/beego/session/mysql"
"github.com/astaxie/beego"
_ "github.com/astaxie/beego/session/redis"
_ "github.com/go-sql-driver/mysql"
"github.com/lifei6671/godoc/commands"
"github.com/lifei6671/godoc/conf"
"github.com/lifei6671/godoc/controllers"
_ "github.com/lifei6671/godoc/routers"
)
var (
VERSION string
BUILD_TIME string
GO_VERSION string
)
func main() {
fmt.Printf("MinDoc version => %s\nbuild time => %s\nstart directory => %s\n%s\n", VERSION, BUILD_TIME, os.Args[0],GO_VERSION)
commands.RegisterDataBase()
commands.RegisterModel()
commands.RegisterLogger()
commands.RegisterCommand()
commands.RegisterFunction()
beego.SetStaticPath("uploads","uploads")
beego.SetStaticPath("uploads", "uploads")
beego.ErrorController(&controllers.ErrorController{})
fmt.Printf("MinDoc version => %s\nbuild time => %s\nstart directory => %s\n%s\n", conf.VERSION, conf.BUILD_TIME, os.Args[0], conf.GO_VERSION)
beego.Run()
}

View File

@ -160,9 +160,9 @@ func (m *Book) FindToPager(pageIndex, pageSize ,memberId int) (books []*BookResu
qb2.Select("book.*,rel.member_id","rel.role_id","m.account as create_name").
From(m.TableNameWithPrefix() + " AS book").
LeftJoin(relationship.TableNameWithPrefix() + " AS rel").
On("book.book_id=rel.book_id").
LeftJoin(NewMember().TableNameWithPrefix() + " AS m").On("rel.member_id=m.member_id AND rel.role_id=0").
LeftJoin(relationship.TableNameWithPrefix() + " AS rel").On("book.book_id=rel.book_id").
LeftJoin(relationship.TableNameWithPrefix() + " AS rel1").On("book.book_id=rel1.book_id AND rel.role_id=0").
LeftJoin(NewMember().TableNameWithPrefix() + " AS m").On("rel1.member_id=m.member_id").
Where("rel.member_id=?").
OrderBy("book.order_index DESC ","book.book_id").Desc().
Limit(pageSize).

View File

@ -47,6 +47,15 @@ func (m *Relationship) Find(id int) (*Relationship,error) {
return m,err
}
//查询指定项目的创始人.
func (m *Relationship) FindFounder(book_id int) (*Relationship,error) {
o := orm.NewOrm()
err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("role_id",0).One(m)
return m,err
}
func (m *Relationship) UpdateRoleId(book_id,member_id, role_id int) (*Relationship,error) {
o := orm.NewOrm()
book := NewBook()

View File

@ -24,7 +24,7 @@ func init() {
beego.InsertFilter("/api/*",beego.BeforeRouter,FilterUser)
var FinishRouter = func(ctx *context.Context) {
ctx.ResponseWriter.Header().Add("MinDoc-Version",conf.Version())
ctx.ResponseWriter.Header().Add("MinDoc-Version",conf.VERSION)
ctx.ResponseWriter.Header().Add("MinDoc-Site","http://www.iminho.me")
}

View File

@ -25,6 +25,8 @@ func init() {
beego.Router("/manager/comments", &controllers.ManagerController{},"*:Comments")
beego.Router("/manager/books/token", &controllers.ManagerController{},"post:CreateToken")
beego.Router("/manager/setting",&controllers.ManagerController{},"*:Setting")
beego.Router("/manager/books/transfer", &controllers.ManagerController{},"post:Transfer")
beego.Router("/manager/books/open", &controllers.ManagerController{},"post:PrivatelyOwned")
beego.Router("/setting", &controllers.SettingController{},"*:Index")
beego.Router("/setting/password", &controllers.SettingController{},"*:Password")

View File

@ -38,6 +38,12 @@
<div class="m-box">
<div class="box-head">
<strong class="box-title"> 项目设置</strong>
<button type="button" class="btn btn-success btn-sm pull-right" data-toggle="modal" data-target="#transferBookModal">转让项目</button>
{{if eq .Model.PrivatelyOwned 1}}
<button type="button" class="btn btn-success btn-sm pull-right" data-toggle="modal" data-target="#changePrivatelyOwnedModal" style="margin-right: 5px;">转为公有</button>
{{else}}
<button type="button" class="btn btn-danger btn-sm pull-right" data-toggle="modal" data-target="#changePrivatelyOwnedModal" style="margin-right: 5px;">转为私有</button>
{{end}}
<button type="button" class="btn btn-danger btn-sm pull-right" style="margin-right: 5px;" data-toggle="modal" data-target="#deleteBookModal">删除项目</button>
</div>
</div>
@ -119,6 +125,43 @@
</div>
{{template "widgets/footer.tpl" .}}
</div>
<div class="modal fade" id="changePrivatelyOwnedModal" tabindex="-1" role="dialog" aria-labelledby="changePrivatelyOwnedModalLabel">
<div class="modal-dialog" role="document">
<form method="post" action="{{urlfor "ManagerController.PrivatelyOwned" }}" id="changePrivatelyOwnedForm">
<input type="hidden" name="identify" value="{{.Model.Identify}}">
<input type="hidden" name="status" value="{{if eq .Model.PrivatelyOwned 0}}close{{else}}open{{end}}">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">
{{if eq .Model.PrivatelyOwned 0}}
转为私有
{{else}}
转为共有
{{end}}
</h4>
</div>
<div class="modal-body">
{{if eq .Model.PrivatelyOwned 0}}
<span style="font-size: 14px;font-weight: 400;">确定将项目转为私有吗?</span>
<p></p>
<p class="text error-message">转为私有后需要通过阅读令牌才能访问该项目。</p>
{{else}}
<span style="font-size: 14px;font-weight: 400;"> 确定将项目转为公有吗?</span>
<p></p>
<p class="text error-message">转为公有后所有人都可以访问该项目。</p>
{{end}}
</div>
<div class="modal-footer">
<span class="error-message" id="form-error-message1"></span>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary" data-loading-text="变更中..." id="btnChangePrivatelyOwned">确定</button>
</div>
</div>
</form>
</div>
</div>
<!-- Delete Book Modal -->
<div class="modal fade" id="deleteBookModal" tabindex="-1" role="dialog" aria-labelledby="deleteBookModalLabel">
<div class="modal-dialog" role="document">
@ -143,7 +186,33 @@
</form>
</div>
</div>
<div class="modal fade" id="transferBookModal" tabindex="-1" role="dialog" aria-labelledby="transferBookModalLabel">
<div class="modal-dialog" role="document">
<form action="{{urlfor "ManagerController.Transfer"}}" method="post" id="transferBookForm">
<input type="hidden" name="identify" value="{{.Model.Identify}}">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">项目转让</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label class="col-sm-2 control-label">接收账号</label>
<div class="col-sm-10">
<input type="text" name="account" class="form-control" placeholder="接收者账号" id="receiveAccount" maxlength="50">
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="modal-footer">
<span id="form-error-message3" class="error-message"></span>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" id="btnTransferBook" class="btn btn-primary">确定转让</button>
</div>
</div>
</form>
</div>
</div>
<script src="/static/jquery/1.12.4/jquery.min.js" type="text/javascript"></script>
<script src="/static/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="/static/webuploader/webuploader.min.js" type="text/javascript"></script>
@ -213,7 +282,46 @@
}
}
});
$("#transferBookForm").ajaxForm({
beforeSubmit : function () {
var account = $.trim($("#receiveAccount").val());
if (account === ""){
return showError("接受者账号不能为空","#form-error-message3")
}
$("#btnTransferBook").button("loading");
},
success : function (res) {
if(res.errcode === 0){
window.location = window.location.href;
}else{
showError(res.message,"#form-error-message3");
}
$("#btnTransferBook").button("reset");
},
error : function () {
$("#btnTransferBook").button("reset");
}
});
$("#changePrivatelyOwnedForm").ajaxForm({
beforeSubmit :function () {
$("#btnChangePrivatelyOwned").button("loading");
},
success :function (res) {
if(res.errcode === 0){
window.location = window.location.href;
return;
}else{
showError(res.message,"#form-error-message1");
}
$("#btnChangePrivatelyOwned").button("reset");
},
error :function () {
showError("服务器异常","#form-error-message1");
$("#btnChangePrivatelyOwned").button("reset");
}
});
});
</script>
</body>
</html>

View File

@ -170,7 +170,7 @@
<div class="modal-footer">
<span id="form-error-message"></span>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-success">保存</button>
<button type="submit" class="btn btn-success" data-loading-text="保存中..." id="btnAddMember">保存</button>
</div>
</div>
</form>
@ -207,6 +207,7 @@
if (email === "") {
return showError("邮箱不能为空");
}
$("#btnAddMember").button("loading");
return true;
},
success : function (res) {
@ -216,6 +217,11 @@
}else{
showError(res.message);
}
$("#btnAddMember").button("reset");
},
error : function () {
showError("服务器异常");
$("#btnAddMember").button("reset");
}
});