package service import ( "github.com/leanote/leanote/app/info" . "github.com/leanote/leanote/app/lea" "github.com/leanote/leanote/app/db" "gopkg.in/mgo.v2/bson" "github.com/revel/revel" "time" "os" "os/exec" "fmt" "strings" "strconv" ) // 配置服务 // 只是全局的, 用户的配置没有 type ConfigService struct { // 全局的 GlobalAllConfigs map[string]interface{} GlobalStringConfigs map[string]string GlobalArrayConfigs map[string][]string GlobalMapConfigs map[string]map[string]string GlobalArrMapConfigs map[string][]map[string]string } var adminUserId = "" // 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{} adminUsername, _ := revel.Config.String("adminUsername") if adminUsername == "" { adminUsername = "admin" } userInfo := userService.GetUserInfoByAny(adminUsername) if userInfo.UserId == "" { return false } adminUserId = userInfo.UserId.Hex() configs := []info.Config{} db.ListByQ(db.Configs, bson.M{"UserId": userInfo.UserId}, &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 } } return true } // 通用方法 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) } } // 更新用户配置 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) 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(adminUserId, "registerSharedUserId", "") return } else { user := userService.GetUserInfo(registerSharedUserId) if user.UserId == "" { ok = false msg = "no such user: " + registerSharedUserId return } else { this.UpdateGlobalStringConfig(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(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(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(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(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 += " --directoryperdb " + 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(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(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() { 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://" } }) } func (this *ConfigService) GetSchema() string { return schema; } // 默认 func (this *ConfigService) GetDefaultDomain() string { return defaultDomain } // 包含http:// func (this *ConfigService) GetDefaultUrl() string { return schema + defaultDomain } // note func (this *ConfigService) GetNoteDomain() string { subDomain := this.GetGlobalStringConfig("noteSubDomain"); if subDomain != "" { return subDomain + port } return this.GetDefaultDomain() + "/note" } func (this *ConfigService) GetNoteUrl() string { return schema + this.GetNoteDomain(); } // blog func (this *ConfigService) GetBlogDomain() string { subDomain := this.GetGlobalStringConfig("blogSubDomain"); if subDomain != "" { return subDomain + port } return this.GetDefaultDomain() + "/blog" } func (this *ConfigService) GetBlogUrl() string { return schema + this.GetBlogDomain(); } // lea func (this *ConfigService) GetLeaDomain() string { subDomain := this.GetGlobalStringConfig("leaSubDomain"); if subDomain != "" { return subDomain + port } return this.GetDefaultDomain() + "/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 }