package service import ( "fmt" "github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/info" . "github.com/leanote/leanote/app/lea" "github.com/revel/revel" "gopkg.in/mgo.v2/bson" "os" "os/exec" "strconv" "strings" "time" ) // 配置服务 // 只是全局的, 用户的配置没有 type ConfigService struct { adminUserId string siteUrl string adminUsername string // 全局的 GlobalAllConfigs map[string]interface{} GlobalStringConfigs map[string]string GlobalArrayConfigs map[string][]string GlobalMapConfigs map[string]map[string]string GlobalArrMapConfigs map[string][]map[string]string } // appStart时 将全局的配置从数据库中得到作为全局 func (this *ConfigService) InitGlobalConfigs() bool { this.GlobalAllConfigs = map[string]interface{}{} this.GlobalStringConfigs = map[string]string{} this.GlobalArrayConfigs = map[string][]string{} this.GlobalMapConfigs = map[string]map[string]string{} this.GlobalArrMapConfigs = map[string][]map[string]string{} this.adminUsername, _ = revel.Config.String("adminUsername") if this.adminUsername == "" { this.adminUsername = "admin" } this.siteUrl, _ = revel.Config.String("site.url") userInfo := userService.GetUserInfoByAny(this.adminUsername) if userInfo.UserId == "" { return false } this.adminUserId = userInfo.UserId.Hex() configs := []info.Config{} // db.ListByQ(db.Configs, bson.M{"UserId": userInfo.UserId}, &configs) db.ListByQ(db.Configs, bson.M{}, &configs) for _, config := range configs { if config.IsArr { this.GlobalArrayConfigs[config.Key] = config.ValueArr this.GlobalAllConfigs[config.Key] = config.ValueArr } else if config.IsMap { this.GlobalMapConfigs[config.Key] = config.ValueMap this.GlobalAllConfigs[config.Key] = config.ValueMap } else if config.IsArrMap { this.GlobalArrMapConfigs[config.Key] = config.ValueArrMap this.GlobalAllConfigs[config.Key] = config.ValueArrMap } else { this.GlobalStringConfigs[config.Key] = config.ValueStr this.GlobalAllConfigs[config.Key] = config.ValueStr } } // site URL if s, ok := this.GlobalStringConfigs["siteUrl"]; !ok || s != "" { this.GlobalStringConfigs["siteUrl"] = this.siteUrl } return true } func (this *ConfigService) GetSiteUrl() string { s := this.GetGlobalStringConfig("siteUrl") if s != "" { return s } return this.siteUrl } func (this *ConfigService) GetAdminUsername() string { return this.adminUsername } func (this *ConfigService) GetAdminUserId() string { return this.adminUserId } // 通用方法 func (this *ConfigService) updateGlobalConfig(userId, key string, value interface{}, isArr, isMap, isArrMap bool) bool { // 判断是否存在 if _, ok := this.GlobalAllConfigs[key]; !ok { // 需要添加 config := info.Config{ConfigId: bson.NewObjectId(), UserId: bson.ObjectIdHex(userId), // 没用 Key: key, IsArr: isArr, IsMap: isMap, IsArrMap: isArrMap, UpdatedTime: time.Now(), } if isArr { v, _ := value.([]string) config.ValueArr = v this.GlobalArrayConfigs[key] = v } else if isMap { v, _ := value.(map[string]string) config.ValueMap = v this.GlobalMapConfigs[key] = v } else if isArrMap { v, _ := value.([]map[string]string) config.ValueArrMap = v this.GlobalArrMapConfigs[key] = v } else { v, _ := value.(string) config.ValueStr = v this.GlobalStringConfigs[key] = v } return db.Insert(db.Configs, config) } else { i := bson.M{"UpdatedTime": time.Now()} this.GlobalAllConfigs[key] = value if isArr { v, _ := value.([]string) i["ValueArr"] = v this.GlobalArrayConfigs[key] = v } else if isMap { v, _ := value.(map[string]string) i["ValueMap"] = v this.GlobalMapConfigs[key] = v } else if isArrMap { v, _ := value.([]map[string]string) i["ValueArrMap"] = v this.GlobalArrMapConfigs[key] = v } else { v, _ := value.(string) i["ValueStr"] = v this.GlobalStringConfigs[key] = v } // return db.UpdateByQMap(db.Configs, bson.M{"UserId": bson.ObjectIdHex(userId), "Key": key}, i) return db.UpdateByQMap(db.Configs, bson.M{"Key": key}, i) } } // 更新用户配置 func (this *ConfigService) UpdateGlobalStringConfig(userId, key string, value string) bool { return this.updateGlobalConfig(userId, key, value, false, false, false) } func (this *ConfigService) UpdateGlobalArrayConfig(userId, key string, value []string) bool { return this.updateGlobalConfig(userId, key, value, true, false, false) } func (this *ConfigService) UpdateGlobalMapConfig(userId, key string, value map[string]string) bool { return this.updateGlobalConfig(userId, key, value, false, true, false) } func (this *ConfigService) UpdateGlobalArrMapConfig(userId, key string, value []map[string]string) bool { return this.updateGlobalConfig(userId, key, value, false, false, true) } // 获取全局配置, 博客平台使用 func (this *ConfigService) GetGlobalStringConfig(key string) string { return this.GlobalStringConfigs[key] } func (this *ConfigService) GetGlobalArrayConfig(key string) []string { arr := this.GlobalArrayConfigs[key] if arr == nil { return []string{} } return arr } func (this *ConfigService) GetGlobalMapConfig(key string) map[string]string { m := this.GlobalMapConfigs[key] if m == nil { return map[string]string{} } return m } func (this *ConfigService) GetGlobalArrMapConfig(key string) []map[string]string { m := this.GlobalArrMapConfigs[key] if m == nil { return []map[string]string{} } return m } func (this *ConfigService) IsOpenRegister() bool { return this.GetGlobalStringConfig("openRegister") != "" } //------- // 修改共享笔记的配置 func (this *ConfigService) UpdateShareNoteConfig(registerSharedUserId string, registerSharedNotebookPerms, registerSharedNotePerms []int, registerSharedNotebookIds, registerSharedNoteIds, registerCopyNoteIds []string) (ok bool, msg string) { defer func() { if err := recover(); err != nil { ok = false msg = fmt.Sprint(err) } }() // 用户是否存在? if registerSharedUserId == "" { ok = true msg = "share userId is blank, So it share nothing to register" this.UpdateGlobalStringConfig(this.adminUserId, "registerSharedUserId", "") return } else { user := userService.GetUserInfo(registerSharedUserId) if user.UserId == "" { ok = false msg = "no such user: " + registerSharedUserId return } else { this.UpdateGlobalStringConfig(this.adminUserId, "registerSharedUserId", registerSharedUserId) } } notebooks := []map[string]string{} // 共享笔记本 if len(registerSharedNotebookIds) > 0 { for i := 0; i < len(registerSharedNotebookIds); i++ { // 判断笔记本是否存在 notebookId := registerSharedNotebookIds[i] if notebookId == "" { continue } notebook := notebookService.GetNotebook(notebookId, registerSharedUserId) if notebook.NotebookId == "" { ok = false msg = "The user has no such notebook: " + notebookId return } else { perm := "0" if registerSharedNotebookPerms[i] == 1 { perm = "1" } notebooks = append(notebooks, map[string]string{"notebookId": notebookId, "perm": perm}) } } } this.UpdateGlobalArrMapConfig(this.adminUserId, "registerSharedNotebooks", notebooks) notes := []map[string]string{} // 共享笔记 if len(registerSharedNoteIds) > 0 { for i := 0; i < len(registerSharedNoteIds); i++ { // 判断笔记本是否存在 noteId := registerSharedNoteIds[i] if noteId == "" { continue } note := noteService.GetNote(noteId, registerSharedUserId) if note.NoteId == "" { ok = false msg = "The user has no such note: " + noteId return } else { perm := "0" if registerSharedNotePerms[i] == 1 { perm = "1" } notes = append(notes, map[string]string{"noteId": noteId, "perm": perm}) } } } this.UpdateGlobalArrMapConfig(this.adminUserId, "registerSharedNotes", notes) // 复制 noteIds := []string{} if len(registerCopyNoteIds) > 0 { for i := 0; i < len(registerCopyNoteIds); i++ { // 判断笔记本是否存在 noteId := registerCopyNoteIds[i] if noteId == "" { continue } note := noteService.GetNote(noteId, registerSharedUserId) if note.NoteId == "" { ok = false msg = "The user has no such note: " + noteId return } else { noteIds = append(noteIds, noteId) } } } this.UpdateGlobalArrayConfig(this.adminUserId, "registerCopyNoteIds", noteIds) ok = true return } // 添加备份 func (this *ConfigService) AddBackup(path, remark string) bool { backups := this.GetGlobalArrMapConfig("backups") // [{}, {}] n := time.Now().Unix() nstr := fmt.Sprintf("%v", n) backups = append(backups, map[string]string{"createdTime": nstr, "path": path, "remark": remark}) return this.UpdateGlobalArrMapConfig(this.adminUserId, "backups", backups) } func (this *ConfigService) getBackupDirname() string { n := time.Now() y, m, d := n.Date() return strconv.Itoa(y) + "_" + m.String() + "_" + strconv.Itoa(d) + "_" + fmt.Sprintf("%v", n.Unix()) } func (this *ConfigService) Backup(remark string) (ok bool, msg string) { binPath := configService.GetGlobalStringConfig("mongodumpPath") config := revel.Config dbname, _ := config.String("db.dbname") host, _ := revel.Config.String("db.host") port, _ := revel.Config.String("db.port") username, _ := revel.Config.String("db.username") password, _ := revel.Config.String("db.password") // mongodump -h localhost -d leanote -o /root/mongodb_backup/leanote-9-22/ -u leanote -p nKFAkxKnWkEQy8Vv2LlM binPath = binPath + " -h " + host + " -d " + dbname + " --port " + port if username != "" { binPath += " -u " + username + " -p " + password } // 保存的路径 dir := revel.BasePath + "/mongodb_backup/" + this.getBackupDirname() binPath += " -o " + dir err := os.MkdirAll(dir, 0755) if err != nil { ok = false msg = fmt.Sprintf("%v", err) return } cmd := exec.Command("/bin/sh", "-c", binPath) Log(binPath) b, err := cmd.Output() if err != nil { msg = fmt.Sprintf("%v", err) ok = false Log("error:......") Log(string(b)) return } ok = configService.AddBackup(dir, remark) return ok, msg } // 还原 func (this *ConfigService) Restore(createdTime string) (ok bool, msg string) { backups := this.GetGlobalArrMapConfig("backups") // [{}, {}] var i int var backup map[string]string for i, backup = range backups { if backup["createdTime"] == createdTime { break } } if i == len(backups) { return false, "Backup Not Found" } // 先备份当前 ok, msg = this.Backup("Auto backup when restore from " + backup["createdTime"]) if !ok { return } // mongorestore -h localhost -d leanote --directoryperdb /home/user1/gopackage/src/github.com/leanote/leanote/mongodb_backup/leanote_install_data/ binPath := configService.GetGlobalStringConfig("mongorestorePath") config := revel.Config dbname, _ := config.String("db.dbname") host, _ := revel.Config.String("db.host") port, _ := revel.Config.String("db.port") username, _ := revel.Config.String("db.username") password, _ := revel.Config.String("db.password") // mongorestore -h localhost -d leanote -o /root/mongodb_backup/leanote-9-22/ -u leanote -p nKFAkxKnWkEQy8Vv2LlM binPath = binPath + " --drop -h " + host + " -d " + dbname + " --port " + port if username != "" { binPath += " -u " + username + " -p " + password } path := backup["path"] + "/" + dbname // 判断路径是否存在 if !IsDirExists(path) { return false, path + " Is Not Exists" } binPath += " " + path cmd := exec.Command("/bin/sh", "-c", binPath) Log(binPath) b, err := cmd.Output() if err != nil { msg = fmt.Sprintf("%v", err) ok = false Log("error:......") Log(string(b)) return } return true, "" } func (this *ConfigService) DeleteBackup(createdTime string) (bool, string) { backups := this.GetGlobalArrMapConfig("backups") // [{}, {}] var i int var backup map[string]string for i, backup = range backups { if backup["createdTime"] == createdTime { break } } if i == len(backups) { return false, "Backup Not Found" } // 删除文件夹之 err := os.RemoveAll(backups[i]["path"]) if err != nil { return false, fmt.Sprintf("%v", err) } // 删除之 backups = append(backups[0:i], backups[i+1:]...) ok := this.UpdateGlobalArrMapConfig(this.adminUserId, "backups", backups) return ok, "" } func (this *ConfigService) UpdateBackupRemark(createdTime, remark string) (bool, string) { backups := this.GetGlobalArrMapConfig("backups") // [{}, {}] var i int var backup map[string]string for i, backup = range backups { if backup["createdTime"] == createdTime { break } } if i == len(backups) { return false, "Backup Not Found" } backup["remark"] = remark ok := this.UpdateGlobalArrMapConfig(this.adminUserId, "backups", backups) return ok, "" } // 得到备份 func (this *ConfigService) GetBackup(createdTime string) (map[string]string, bool) { backups := this.GetGlobalArrMapConfig("backups") // [{}, {}] var i int var backup map[string]string for i, backup = range backups { if backup["createdTime"] == createdTime { break } } if i == len(backups) { return map[string]string{}, false } return backup, true } //-------------- // sub domain var defaultDomain string var schema = "http://" var port string func init() { revel.OnAppStart(func() { /* 不用配置的, 因为最终通过命令可以改, 而且有的使用nginx代理 port = strconv.Itoa(revel.HttpPort) if port != "80" { port = ":" + port } else { port = ""; } */ siteUrl, _ := revel.Config.String("site.url") // 已包含:9000, http, 去掉成 leanote.com if strings.HasPrefix(siteUrl, "http://") { defaultDomain = siteUrl[len("http://"):] } else if strings.HasPrefix(siteUrl, "https://") { defaultDomain = siteUrl[len("https://"):] schema = "https://" } // port localhost:9000 ports := strings.Split(defaultDomain, ":") if len(ports) == 2 { port = ports[1] } if port == "80" { port = "" } else { port = ":" + port } }) } func (this *ConfigService) GetSchema() string { return schema } // 默认 func (this *ConfigService) GetDefaultDomain() string { return defaultDomain } // note func (this *ConfigService) GetNoteDomain() string { return "/note" } func (this *ConfigService) GetNoteUrl() string { return this.GetNoteDomain() } // blog func (this *ConfigService) GetBlogDomain() string { return "/blog" } func (this *ConfigService) GetBlogUrl() string { return this.GetBlogDomain() } // lea func (this *ConfigService) GetLeaDomain() string { return "/lea" } func (this *ConfigService) GetLeaUrl() string { return schema + this.GetLeaDomain() } func (this *ConfigService) GetUserUrl(domain string) string { return schema + domain + port } func (this *ConfigService) GetUserSubUrl(subDomain string) string { return schema + subDomain + "." + this.GetDefaultDomain() } // 是否允许自定义域名 func (this *ConfigService) AllowCustomDomain() bool { return configService.GetGlobalStringConfig("allowCustomDomain") != "" } // 是否是好的自定义域名 func (this *ConfigService) IsGoodCustomDomain(domain string) bool { blacks := this.GetGlobalArrayConfig("blackCustomDomains") for _, black := range blacks { if strings.Contains(domain, black) { return false } } return true } func (this *ConfigService) IsGoodSubDomain(domain string) bool { blacks := this.GetGlobalArrayConfig("blackSubDomains") LogJ(blacks) for _, black := range blacks { if domain == black { return false } } return true } // 上传大小 func (this *ConfigService) GetUploadSize(key string) float64 { f, _ := strconv.ParseFloat(this.GetGlobalStringConfig(key), 64) return f } func (this *ConfigService) GetInt64(key string) int64 { f, _ := strconv.ParseInt(this.GetGlobalStringConfig(key), 10, 64) return f } func (this *ConfigService) GetInt32(key string) int32 { f, _ := strconv.ParseInt(this.GetGlobalStringConfig(key), 10, 32) return int32(f) } func (this *ConfigService) GetUploadSizeLimit() map[string]float64 { return map[string]float64{ "uploadImageSize": this.GetUploadSize("uploadImageSize"), "uploadBlogLogoSize": this.GetUploadSize("uploadBlogLogoSize"), "uploadAttachSize": this.GetUploadSize("uploadAttachSize"), "uploadAvatarSize": this.GetUploadSize("uploadAvatarSize"), } } // 为用户得到全局的配置 // NoteController调用 func (this *ConfigService) GetGlobalConfigForUser() map[string]interface{} { uploadSizeConfigs := this.GetUploadSizeLimit() config := map[string]interface{}{} for k, v := range uploadSizeConfigs { config[k] = v } return config } // 主页是否是管理员的博客页 func (this *ConfigService) HomePageIsAdminsBlog() bool { return this.GetGlobalStringConfig("homePage") == "" } func (this *ConfigService) GetVersion() string { return "2.6.1" }