From 530b69c58ffe3acee444b7cb5930418cc63b22cc Mon Sep 17 00:00:00 2001 From: magicwind <2814461814@qq.com> Date: Tue, 7 Jun 2022 14:03:11 +0800 Subject: [PATCH] feat: integrate Casdoor --- conf/oauth.conf.example | 65 +-- controllers/AcountController.go | 611 +++---------------------- controllers/BaseController.go | 316 +++++++------ controllers/SettingController.go | 195 +------- controllers/UserController.go | 1 + controllers/token_jwt_key.pem | 29 ++ go.mod | 4 +- go.sum | 369 ++++++++++++++- models/member.go | 7 - routers/web.go | 10 +- views/account/bind.html | 135 ------ views/account/find_password_setp1.html | 112 ----- views/account/find_password_setp2.html | 125 ----- views/account/mail_template.html | 98 ---- views/setting/index.html | 219 --------- views/setting/menu.html | 3 - views/setting/password.html | 94 ---- views/widgets/header.html | 2 +- 18 files changed, 651 insertions(+), 1744 deletions(-) create mode 100644 controllers/token_jwt_key.pem delete mode 100644 views/account/bind.html delete mode 100644 views/account/find_password_setp1.html delete mode 100644 views/account/find_password_setp2.html delete mode 100644 views/account/mail_template.html delete mode 100644 views/setting/index.html delete mode 100644 views/setting/password.html diff --git a/conf/oauth.conf.example b/conf/oauth.conf.example index e897adcd..10e399a4 100644 --- a/conf/oauth.conf.example +++ b/conf/oauth.conf.example @@ -1,57 +1,10 @@ -# 第三方登录配置 [oauth] - -##### Gitee(码云) #### -# 申请地址(需要先登录):https://gitee.com/oauth/applications - -# 您的ClientId -giteeClientId= - -# 您的ClientSecret -giteeClientSecret= - -# 回调地址,把下面的bookstack.cn的域名换成你的即可 -giteeCallback=http://www.bookstack.cn/login/gitee - -# 下面这两项不要动 -giteeAccesstoken=https://gitee.com/oauth/token -giteeUserInfo=https://gitee.com/api/v5/user - - - -######## GitHub ######## -# 申请地址(需要先登录你的GitHub):https://github.com/settings/developers - -# 您的ClientId -githubClientId= - -# 您的ClientSecret -githubClientSecret= - -# 回调地址,把下面的bookstack.cn的域名换成你的即可 -githubCallback=http://www.bookstack.cn/login/github - -# 下面这两项不要动 -githubAccesstoken=https://github.com/login/oauth/access_token -githubUserInfo=https://api.github.com/user - - - -#### QQ #### -# 申请地址(需要先登录你的QQ):https://connect.qq.com/manage.html - -#ClientId,即 APP ID -qqClientId= - -#ClientSecret,即 APP Key -qqClientSecret= - -# 回调地址,把下面的bookstack.cn的域名换成你的即可 -qqCallback=http://www.bookstack.cn/login/qq - -# 下面这三项不要动 -qqAccesstoken=https://graph.qq.com/oauth2.0/token -qqOpenId=https://graph.qq.com/oauth2.0/me -qqUserInfo=https://graph.qq.com/user/get_user_info - -### TODO 微信和微博登录,主要是我这边忘记了以前注册的个人开发者信息,当前没开发,后续会开发出来 #### +######## casdoor ######## +# 先部署casdoor + +casdoorOrganization = +casdoorApplication = "bookstack" +casdoorEndpoint = http://localhost:8000 +clientId = +clientSecret = +redirectUrl = http://localhost:8181/login/callback \ No newline at end of file diff --git a/controllers/AcountController.go b/controllers/AcountController.go index 5282b6cc..fc0c3f68 100644 --- a/controllers/AcountController.go +++ b/controllers/AcountController.go @@ -1,25 +1,21 @@ package controllers import ( - "regexp" - "strings" - "time" - - "errors" - + _ "embed" "fmt" - "github.com/TruthHun/BookStack/conf" "github.com/TruthHun/BookStack/models" - "github.com/TruthHun/BookStack/oauth" - "github.com/TruthHun/BookStack/utils" "github.com/astaxie/beego" "github.com/astaxie/beego/cache" - "github.com/astaxie/beego/orm" "github.com/astaxie/beego/utils/captcha" + "github.com/casdoor/casdoor-go-sdk/auth" + "strings" //"github.com/lifei6671/gocaptcha" ) +//go:embed token_jwt_key.pem +var JwtPublicKey string + // AccountController 用户登录与注册. type AccountController struct { BaseController @@ -28,576 +24,111 @@ type AccountController struct { var cpt *captcha.Captcha func init() { + InitAuthConfig() // use beego cache system store the captcha data fc := &cache.FileCache{CachePath: "./cache/captcha"} cpt = captcha.NewWithFilter("/captcha/", fc) } -//第三方登录回调 -//封装一个内部调用的函数,loginByMemberId -func (this *AccountController) Oauth() { - - var ( - nickname string //昵称 - avatar string //头像的http链接地址 - email string //邮箱地址 - username string //用户名 - tips string - id interface{} //第三方的用户id,唯一识别码 - IsEmail bool //是否是使用邮箱注册 - captchaOn bool //是否开启了验证码 - ) - - //如果开启了验证码 - if v, ok := this.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") { - captchaOn = true - this.Data["CaptchaOn"] = captchaOn - } - - oauthLogin := false - if v, ok := this.Option["LOGIN_QQ"]; ok && strings.EqualFold(v, "true") { - this.Data["LoginQQ"] = true - oauthLogin = true - } - if v, ok := this.Option["LOGIN_GITHUB"]; ok && strings.EqualFold(v, "true") { - this.Data["LoginGitHub"] = true - oauthLogin = true - } - if v, ok := this.Option["LOGIN_GITEE"]; ok && strings.EqualFold(v, "true") { - this.Data["LoginGitee"] = true - oauthLogin = true - } - this.Data["OauthLogin"] = oauthLogin - - oa := this.GetString(":oauth") - code := this.GetString("code") - switch oa { - case "gitee": - tips = `您正在使用【码云】登录` - token, err := oauth.GetGiteeAccessToken(code) - if err != nil { - beego.Error(err) - this.Abort("404") - } - - info, err := oauth.GetGiteeUserInfo(token.AccessToken) - if err != nil { - beego.Error(err) - this.Abort("404") - } - - if info.Id > 0 { - existInfo, _ := models.ModelGitee.GetUserByGiteeId(info.Id, "id", "member_id") - if existInfo.MemberId > 0 { //直接登录 - err = this.loginByMemberId(existInfo.MemberId) - if err != nil { - beego.Error(err) - this.Abort("404") - } - this.Redirect(beego.URLFor("HomeController.Index"), 302) - return - } - if existInfo.Id == 0 { //原本不存在于数据库中的数据需要入库 - orm.NewOrm().Insert(&models.Gitee{GiteeUser: info}) - } - nickname = info.Name - username = info.Login - avatar = info.AvatarURL - email = info.Email - id = info.Id - } else { - err = errors.New("获取gitee用户数据失败") - beego.Error(err) - this.Abort("404") - } - case "github": - tips = `您正在使用【GitHub】登录` - token, err := oauth.GetGithubAccessToken(code) - if err != nil { - beego.Error(err.Error()) - this.Abort("404") - } - - info, err := oauth.GetGithubUserInfo(token.AccessToken) - if err != nil { - beego.Error(err.Error()) - this.Abort("404") - } - - if info.Id > 0 { - existInfo, _ := models.ModelGithub.GetUserByGithubId(info.Id, "id", "member_id") - if existInfo.MemberId > 0 { //直接登录 - err = this.loginByMemberId(existInfo.MemberId) - if err != nil { - beego.Error(err.Error()) - this.Abort("404") - } - this.Redirect(beego.URLFor("HomeController.Index"), 302) - return - } - if existInfo.Id == 0 { //原本不存在于数据库中的数据需要入库 - orm.NewOrm().Insert(&models.Github{GithubUser: info}) - } - nickname = info.Name - username = info.Login - avatar = info.AvatarURL - email = info.Email - id = info.Id - } else { - err = errors.New("获取github用户数据失败") - beego.Error(err.Error()) - this.Abort("404") - } - - case "qq": - tips = `您正在使用【QQ】登录` - token, err := oauth.GetQQAccessToken(code) - if err != nil { - beego.Error(err) - this.Abort("404") - } - - openid, err := oauth.GetQQOpenId(token) - if err != nil { - beego.Error(err.Error()) - this.Abort("404") - } - - info, err := oauth.GetQQUserInfo(token.AccessToken, openid) - if err != nil { - beego.Error(err.Error()) - this.Abort("404") - } - - if info.Ret == 0 { - existInfo, _ := models.ModelQQ.GetUserByOpenid(openid, "id", "member_id") - if existInfo.MemberId > 0 { //直接登录 - err = this.loginByMemberId(existInfo.MemberId) - if err != nil { - beego.Error(err.Error()) - this.Abort("404") - } - this.Redirect(beego.URLFor("HomeController.Index"), 302) - return - } +func InitAuthConfig() { + casdoorEndpoint := beego.AppConfig.String("oauth::casdoorEndpoint") + clientId := beego.AppConfig.String("oauth::clientId") + clientSecret := beego.AppConfig.String("oauth::clientSecret") + casdoorOrganization := beego.AppConfig.String("oauth::casdoorOrganization") + casdoorApplication := beego.AppConfig.String("oauth::casdoorApplication") - if existInfo.Id == 0 { //原本不存在于数据库中的数据需要入库 - orm.NewOrm().Insert(&models.QQ{ - OpenId: openid, - Name: info.Name, - Gender: info.Gender, - AvatarURL: info.AvatarURL, - }) - } - nickname = info.Name - username = "" - avatar = info.AvatarURL - email = "" - id = openid - } else { - err = errors.New(info.Msg) - beego.Error(err) - this.Abort("404") - } - default: //email - IsEmail = true - } + auth.InitConfig(casdoorEndpoint, clientId, clientSecret, JwtPublicKey, casdoorOrganization, casdoorApplication) +} - this.Data["IsEmail"] = IsEmail - this.Data["Nickname"] = nickname - this.Data["Avatar"] = avatar - this.Data["Email"] = email - this.Data["Username"] = username - this.Data["AuthType"] = oa - this.Data["SeoTitle"] = "完善信息" - this.Data["Tips"] = tips - this.Data["Id"] = id - this.Data["GiteeClientId"] = beego.AppConfig.String("oauth::giteeClientId") - this.Data["GiteeCallback"] = beego.AppConfig.String("oauth::giteeCallback") - this.Data["GithubClientId"] = beego.AppConfig.String("oauth::githubClientId") - this.Data["GithubCallback"] = beego.AppConfig.String("oauth::githubCallback") - this.Data["QQClientId"] = beego.AppConfig.String("oauth::qqClientId") - this.Data["QQCallback"] = beego.AppConfig.String("oauth::qqCallback") - this.Data["RandomStr"] = time.Now().Unix() - this.SetSession("auth", fmt.Sprintf("%v-%v", oa, id)) //存储标识,以标记是哪个用户,在完善用户信息的时候跟传递过来的auth和id进行校验 - this.TplName = "account/bind.html" +// @Title Login +func (c *BaseController) Login() { + redirectUrl := auth.GetSigninUrl(beego.AppConfig.String("oauth::redirectUrl")) + c.Redirect(redirectUrl, 302) +} +// @Title Signup +func (c *BaseController) Signup() { + redirectUrl := auth.GetSignupUrl(true, beego.AppConfig.String("oauth::redirectUrl")) + c.Redirect(redirectUrl, 302) } -// Login 用户登录. -func (this *AccountController) Login() { +// @Title Callback +// @Description sign in as a member +func (c *BaseController) Callback() { + var ( - remember CookieRemember - captchaOn bool //是否开启了验证码 + nickname string //昵称 + avatar string //头像的http链接地址 + email string //邮箱地址 + username string //用户名 ) - this.TplName = "account/login.html" - - //如果开启了验证码 - if v, ok := this.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") { - captchaOn = true - this.Data["CaptchaOn"] = captchaOn - } - - oauthLogin := false - if v, ok := this.Option["LOGIN_QQ"]; ok && strings.EqualFold(v, "true") { - this.Data["LoginQQ"] = true - oauthLogin = true - } - if v, ok := this.Option["LOGIN_GITHUB"]; ok && strings.EqualFold(v, "true") { - this.Data["LoginGitHub"] = true - oauthLogin = true - } - if v, ok := this.Option["LOGIN_GITEE"]; ok && strings.EqualFold(v, "true") { - this.Data["LoginGitee"] = true - oauthLogin = true - } - this.Data["OauthLogin"] = oauthLogin - - //如果Cookie中存在登录信息 - if cookie, ok := this.GetSecureCookie(conf.GetAppKey(), "login"); ok { - if err := utils.Decode(cookie, &remember); err == nil { - if err = this.loginByMemberId(remember.MemberId); err == nil { - this.Redirect(beego.URLFor("HomeController.Index"), 302) - return - } - } - } - - if this.Ctx.Input.IsPost() { - account := this.GetString("account") - password := this.GetString("password") - - if captchaOn && !cpt.VerifyReq(this.Ctx.Request) { - this.JsonResult(1, "验证码不正确") - } - - member, err := models.NewMember().Login(account, password) - - //如果没有数据 - if err != nil { - beego.Error("用户登录 =>", err) - this.JsonResult(500, "账号或密码错误", nil) - } - member.LastLoginTime = time.Now() - member.Update() - this.SetMember(*member) - remember.MemberId = member.MemberId - remember.Account = member.Account - remember.Time = time.Now() - v, err := utils.Encode(remember) - if err == nil { - this.SetSecureCookie(conf.GetAppKey(), "login", v, 24*3600*365) - } - this.JsonResult(0, "ok") - } - - this.Data["GiteeClientId"] = beego.AppConfig.String("oauth::giteeClientId") - this.Data["GiteeCallback"] = beego.AppConfig.String("oauth::giteeCallback") - this.Data["GithubClientId"] = beego.AppConfig.String("oauth::githubClientId") - this.Data["GithubCallback"] = beego.AppConfig.String("oauth::githubCallback") - this.Data["QQClientId"] = beego.AppConfig.String("oauth::qqClientId") - this.Data["QQCallback"] = beego.AppConfig.String("oauth::qqCallback") - this.Data["RandomStr"] = time.Now().Unix() - this.GetSeoByPage("login", map[string]string{ - "title": "登录 - " + this.Sitename, - "keywords": "登录," + this.Sitename, - "description": this.Sitename + "专注于文档在线写作、协作、分享、阅读与托管,让每个人更方便地发布、分享和获得知识。", - }) -} - -//用户注册.[移除用户注册,直接叫用户绑定] -//注意:如果用户输入的账号密码跟现有的账号密码相一致,则表示绑定账号,否则表示注册新账号。 -func (this *AccountController) Bind() { - var err error - account := this.GetString("account") - nickname := strings.TrimSpace(this.GetString("nickname")) - password1 := this.GetString("password1") - password2 := this.GetString("password2") - email := this.GetString("email") - oauthType := this.GetString("oauth") - oauthId := this.GetString("id") - avatar := this.GetString("avatar") //用户头像 - isbind, _ := this.GetInt("isbind", 0) + code := c.Input().Get("code") + state := c.Input().Get("state") - ibind := func(oauthType string, oauthId, memberId interface{}) (err error) { - //注册成功,绑定用户 - switch oauthType { - case "gitee": - err = models.ModelGitee.Bind(oauthId, memberId) - case "github": - err = models.ModelGithub.Bind(oauthId, memberId) - case "qq": - err = models.ModelQQ.Bind(oauthId, memberId) - } - return + token, err := auth.GetOAuthToken(code, state) + if err != nil { + beego.Error(err) + c.Abort("404") } - if oauthType != "email" { - if auth, ok := this.GetSession("auth").(string); !ok || fmt.Sprintf("%v-%v", oauthType, oauthId) != auth { - this.JsonResult(6005, "绑定信息有误,授权类型不符") - } - } else { //邮箱登录,如果开启了验证码,则对验证码进行校验 - if v, ok := this.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") { - if !cpt.VerifyReq(this.Ctx.Request) { - this.JsonResult(1, "验证码不正确") - } - } + claims, err := auth.ParseJwtToken(token.AccessToken) + if err != nil { + panic(err) } - member := models.NewMember() - - if isbind == 1 { - if member, err = models.NewMember().Login(account, password1); err != nil || member.MemberId == 0 { - beego.Error("绑定用户失败", err, member) - this.JsonResult(1, "绑定用户失败,用户名或密码不正确") - } - } else { - if password1 != password2 { - this.JsonResult(6003, "登录密码与确认密码不一致") - } - - if ok, err := regexp.MatchString(conf.RegexpAccount, account); account == "" || !ok || err != nil { - this.JsonResult(6001, "用户名只能由英文字母数字组成,且在3-50个字符") - } - if l := strings.Count(password1, ""); password1 == "" || l > 50 || l < 6 { - this.JsonResult(6002, "密码必须在6-50个字符之间") - } + claims.AccessToken = token.AccessToken + c.SetSessionClaims(claims) - if ok, err := regexp.MatchString(conf.RegexpEmail, email); !ok || err != nil || email == "" { - this.JsonResult(6004, "邮箱格式不正确") - } - if l := strings.Count(nickname, "") - 1; l < 2 || l > 20 { - this.JsonResult(6004, "用户昵称限制在2-20个字符") - } + info := &claims.User + nickname = info.DisplayName + username = info.Name + avatar = info.Avatar + email = info.Email - //出错或者用户不存在,则重新注册用户,否则直接登录 - member.Account = account + member, err := models.NewMember().FindByAccount(username) + if member.MemberId == 0 { + //用户不存在,则重新注册用户 + member.Account = username member.Nickname = nickname - member.Password = password1 member.Role = conf.MemberGeneralRole - member.Avatar = conf.GetDefaultAvatar() + member.Avatar = avatar member.CreateAt = 0 member.Email = email member.Status = 0 - if len(avatar) > 0 { - member.Avatar = avatar - } if err := member.Add(); err != nil { beego.Error(err) - this.JsonResult(6006, err.Error()) - } - } - if err = this.loginByMemberId(member.MemberId); err != nil { - beego.Error(err.Error()) - this.JsonResult(1, err.Error()) - } - - if err = ibind(oauthType, oauthId, member.MemberId); err != nil { - beego.Error(err) - this.JsonResult(0, "登录失败") - } - - if oauthType == "email" { - this.JsonResult(0, "注册成功") - } - this.JsonResult(0, "登录成功") -} - -//找回密码. -func (this *AccountController) FindPassword() { - - this.TplName = "account/find_password_setp1.html" - mailConf := conf.GetMailConfig() - - if this.Ctx.Input.IsPost() { - - email := this.GetString("email") - - if email == "" { - this.JsonResult(6005, "邮箱地址不能为空") - } - if !mailConf.EnableMail { - this.JsonResult(6004, "未启用邮件服务") - } - - //captcha := this.GetString("code") - //如果开启了验证码 - //if v, ok := this.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") { - // v, ok := this.GetSession(conf.CaptchaSessionName).(string) - // if !ok || !strings.EqualFold(v, captcha) { - // this.JsonResult(6001, "验证码不正确") - // } - //} - - if !cpt.VerifyReq(this.Ctx.Request) { - this.JsonResult(6001, "验证码不正确") - } - - member, err := models.NewMember().FindByFieldFirst("email", email) - if err != nil { - beego.Error(err) - this.JsonResult(6006, "邮箱不存在") - } - if member.Status != 0 { - this.JsonResult(6007, "账号已被禁用") - } - if member.AuthMethod == conf.AuthMethodLDAP { - this.JsonResult(6011, "当前用户不支持找回密码") - } - - count, err := models.NewMemberToken().FindSendCount(email, time.Now().Add(-1*time.Hour), time.Now()) - - if err != nil { - beego.Error(err) - this.JsonResult(6008, "发送邮件失败") - } - if count > mailConf.MailNumber { - this.JsonResult(6008, "发送次数太多,请稍候再试") - } - - memberToken := models.NewMemberToken() - - memberToken.Token = string(utils.Krand(32, utils.KC_RAND_KIND_ALL)) - memberToken.Email = email - memberToken.MemberId = member.MemberId - memberToken.IsValid = false - if _, err := memberToken.InsertOrUpdate(); err != nil { - this.JsonResult(6009, "邮件发送失败") - } - - data := map[string]interface{}{ - "SITE_NAME": this.Option["SITE_NAME"], - "url": this.BaseUrl() + beego.URLFor("AccountController.FindPassword", "token", memberToken.Token, "mail", email), - } - - body, err := this.ExecuteViewPathTemplate("account/mail_template.html", data) - if err != nil { - beego.Error(err) - this.JsonResult(6003, "邮件发送失败") - } - - if err = utils.SendMail(mailConf, "找回密码", email, body); err != nil { - beego.Error(err) - this.JsonResult(6003, "邮件发送失败") - } - - this.JsonResult(0, "ok", this.BaseUrl()+beego.URLFor("AccountController.Login")) - } - - this.GetSeoByPage("findpwd", map[string]string{ - "title": "找回密码 - " + this.Sitename, - "keywords": "找回密码", - "description": this.Sitename + "专注于文档在线写作、协作、分享、阅读与托管,让每个人更方便地发布、分享和获得知识。", - }) - - token := this.GetString("token") - mail := this.GetString("mail") - - if token != "" && mail != "" { - memberToken, err := models.NewMemberToken().FindByFieldFirst("token", token) - - if err != nil { - beego.Error(err) - this.Data["ErrorMessage"] = "邮件已失效" - this.TplName = "errors/error.html" - return } - subTime := memberToken.SendTime.Sub(time.Now()) - - if !strings.EqualFold(memberToken.Email, mail) || subTime.Minutes() > float64(mailConf.MailExpired) || !memberToken.ValidTime.IsZero() { - this.Data["ErrorMessage"] = "验证码已过期,请重新操作。" - this.TplName = "errors/error.html" - return - } - this.Data["Email"] = memberToken.Email - this.Data["Token"] = memberToken.Token - this.TplName = "account/find_password_setp2.html" - - } - -} - -//校验邮件并修改密码. -func (this *AccountController) ValidEmail() { - password1 := this.GetString("password1") - password2 := this.GetString("password2") - token := this.GetString("token") - mail := this.GetString("mail") - - if password1 == "" { - this.JsonResult(6001, "密码不能为空") - } - if l := strings.Count(password1, ""); l < 6 || l > 50 { - this.JsonResult(6001, "密码不能为空且必须在6-50个字符之间") - } - if password2 == "" { - this.JsonResult(6002, "确认密码不能为空") - } - if password1 != password2 { - this.JsonResult(6003, "确认密码输入不正确") - } - - if !cpt.VerifyReq(this.Ctx.Request) { - this.JsonResult(6001, "验证码不正确") } - mailConf := conf.GetMailConfig() - memberToken, err := models.NewMemberToken().FindByFieldFirst("token", token) - - if err != nil { - beego.Error(err) - this.JsonResult(6007, "邮件已失效") - } - subTime := memberToken.SendTime.Sub(time.Now()) - - if !strings.EqualFold(memberToken.Email, mail) || subTime.Minutes() > float64(mailConf.MailExpired) || !memberToken.ValidTime.IsZero() { - - this.JsonResult(6008, "验证码已过期,请重新操作。") - } - member, err := models.NewMember().Find(memberToken.MemberId) - if err != nil { - beego.Error(err) - this.JsonResult(6005, "用户不存在") - } - hash, err := utils.PasswordHash(password1) - - if err != nil { - beego.Error(err) - this.JsonResult(6006, "保存密码失败") - } - - member.Password = hash - - err = member.Update("password") - memberToken.ValidTime = time.Now() - memberToken.IsValid = true - memberToken.InsertOrUpdate() - - if err != nil { - beego.Error(err) - this.JsonResult(6006, "保存密码失败") + if err = c.loginByMemberId(member.MemberId); err != nil { + beego.Error(err.Error()) } - this.JsonResult(0, "ok", this.BaseUrl()+beego.URLFor("AccountController.Login")) + c.Redirect(beego.URLFor("HomeController.Index"), 302) } -// Logout 退出登录. -func (this *AccountController) Logout() { - this.SetMember(models.Member{}) +// @Title Signout +// @Description sign out the current member +// @Success 200 {object} controllers.api_controller.Response The Response object +// @router /signout [post] +// @Tag Account API +func (c *BaseController) Logout() { - this.SetSecureCookie(conf.GetAppKey(), "login", "", -3600) + c.SetSessionClaims(nil) + c.SetMember(models.Member{}) - this.Redirect(beego.URLFor("AccountController.Login"), 302) + c.SetSecureCookie(conf.GetAppKey(), "login", "", -3600) + c.Redirect(beego.URLFor("HomeController.Index"), 302) } //记录笔记 -func (this *AccountController) Note() { - docid, _ := this.GetInt("doc_id") +func (c *AccountController) Note() { + docid, _ := c.GetInt("doc_id") fmt.Println(docid) - if strings.ToLower(this.Ctx.Request.Method) == "post" { + if strings.ToLower(c.Ctx.Request.Method) == "post" { } else { - this.Data["SeoTitle"] = "笔记" - this.TplName = "account/note.html" + c.Data["SeoTitle"] = "笔记" + c.TplName = "account/note.html" } } diff --git a/controllers/BaseController.go b/controllers/BaseController.go index cd85aa03..869b8ef6 100644 --- a/controllers/BaseController.go +++ b/controllers/BaseController.go @@ -2,13 +2,13 @@ package controllers import ( "bytes" + "encoding/gob" "fmt" + "net/url" "strconv" "unicode/utf8" - "github.com/TruthHun/BookStack/utils" - "encoding/json" "io" "strings" @@ -22,8 +22,10 @@ import ( "github.com/PuerkitoBio/goquery" "github.com/TruthHun/BookStack/conf" "github.com/TruthHun/BookStack/models" + "github.com/TruthHun/BookStack/utils" "github.com/astaxie/beego" "github.com/astaxie/beego/orm" + "github.com/casdoor/casdoor-go-sdk/auth" ) type BaseController struct { @@ -46,8 +48,54 @@ type CookieRemember struct { Time time.Time } -func (this *BaseController) refreshReferer() { - referer := this.Ctx.Request.Header.Get("referer") +func init() { + gob.Register(auth.Claims{}) +} + +func (c *BaseController) GetSessionClaims() *auth.Claims { + s := c.GetSession("user") + if s == nil { + return nil + } + + claims := s.(auth.Claims) + return &claims +} + +func (c *BaseController) SetSessionClaims(claims *auth.Claims) { + if claims == nil { + c.DelSession("user") + return + } + + c.SetSession("user", *claims) +} + +func (c *BaseController) refreshUser() { + //casdoor用户信息更新,需要同步 + if c.GetSession("isUpdateUser") == 1 { + account := c.GetSessionClaims() + if account == nil { + c.Redirect(beego.URLFor("AccountController.Login"), 302) + } + user, err := auth.GetUser(account.Name) + if err != nil { + return + } + if member, err := models.NewMember().Find(c.Member.MemberId); err == nil { + member.Avatar = user.Avatar + member.Nickname = user.DisplayName + err = member.Update() + if err != nil { + c.JsonResult(60001, "更新用户信息失败") + } + } + c.SetSession("isUpdateUser", 0) + } +} + +func (c *BaseController) refreshReferer() { + referer := c.Ctx.Request.Header.Get("referer") if referer != "" { referer, _ = url.QueryUnescape(referer) referer = strings.ToLower(referer) @@ -56,12 +104,12 @@ func (this *BaseController) refreshReferer() { for _, item := range forbid { item = strings.ToLower(strings.TrimSpace(item)) // 先判断是否带有非法关键字 - if item != "" && strings.Contains(referer, item) && !strings.HasSuffix(referer, strings.ToLower(this.Ctx.Request.RequestURI)) { + if item != "" && strings.Contains(referer, item) && !strings.HasSuffix(referer, strings.ToLower(c.Ctx.Request.RequestURI)) { if u, err := url.Parse(referer); err == nil { // 且referer的host与当前请求的host不是同一个,则进行302跳转以刷新过滤当前referer - if strings.ToLower(u.Host) != strings.ToLower(this.Ctx.Request.Host) { - this.Redirect(this.Ctx.Request.RequestURI, 302) - this.StopRun() + if strings.ToLower(u.Host) != strings.ToLower(c.Ctx.Request.Host) { + c.Redirect(c.Ctx.Request.RequestURI, 302) + c.StopRun() return } } @@ -72,124 +120,124 @@ func (this *BaseController) refreshReferer() { } // Prepare 预处理. -func (this *BaseController) Prepare() { - this.refreshReferer() - - this.Data["Version"] = utils.Version - this.IsMobile = utils.IsMobile(this.Ctx.Request.UserAgent()) - this.Data["IsMobile"] = this.IsMobile - this.Member = models.NewMember() //初始化 - this.EnableAnonymous = false - this.AllowRegister = true - this.EnableDocumentHistory = 0 - this.OssDomain = strings.TrimRight(beego.AppConfig.String("oss::Domain"), "/ ") - this.Data["OssDomain"] = this.OssDomain - this.StaticDomain = strings.Trim(beego.AppConfig.DefaultString("static_domain", ""), "/") - this.Data["StaticDomain"] = this.StaticDomain +func (c *BaseController) Prepare() { + c.refreshReferer() + + c.Data["Version"] = utils.Version + c.IsMobile = utils.IsMobile(c.Ctx.Request.UserAgent()) + c.Data["IsMobile"] = c.IsMobile + c.Member = models.NewMember() //初始化 + c.EnableAnonymous = false + c.AllowRegister = true + c.EnableDocumentHistory = 0 + c.OssDomain = strings.TrimRight(beego.AppConfig.String("oss::Domain"), "/ ") + c.Data["OssDomain"] = c.OssDomain + c.StaticDomain = strings.Trim(beego.AppConfig.DefaultString("static_domain", ""), "/") + c.Data["StaticDomain"] = c.StaticDomain //从session中获取用户信息 - if member, ok := this.GetSession(conf.LoginSessionName).(models.Member); ok && member.MemberId > 0 { + if member, ok := c.GetSession(conf.LoginSessionName).(models.Member); ok && member.MemberId > 0 { m, _ := models.NewMember().Find(member.MemberId) - this.Member = m + c.Member = m } else { //如果Cookie中存在登录信息,从cookie中获取用户信息 - if cookie, ok := this.GetSecureCookie(conf.GetAppKey(), "login"); ok { + if cookie, ok := c.GetSecureCookie(conf.GetAppKey(), "login"); ok { var remember CookieRemember err := utils.Decode(cookie, &remember) if err == nil { member, err := models.NewMember().Find(remember.MemberId) if err == nil { - this.SetMember(*member) - this.Member = member + c.SetMember(*member) + c.Member = member } } } } - if this.Member.RoleName == "" { - this.Member.ResolveRoleName() + if c.Member.RoleName == "" { + c.Member.ResolveRoleName() } - this.Data["Member"] = this.Member - this.Data["BaseUrl"] = this.BaseUrl() - this.Data["IsSignedToday"] = false - if this.Member.MemberId > 0 { - this.Data["IsSignedToday"] = models.NewSign().IsSignToday(this.Member.MemberId) + c.Data["Member"] = c.Member + c.Data["BaseUrl"] = c.BaseUrl() + c.Data["IsSignedToday"] = false + if c.Member.MemberId > 0 { + c.Data["IsSignedToday"] = models.NewSign().IsSignToday(c.Member.MemberId) } if options, err := models.NewOption().All(); err == nil { - this.Option = make(map[string]string, len(options)) + c.Option = make(map[string]string, len(options)) for _, item := range options { if item.OptionName == "SITE_NAME" { - this.Sitename = item.OptionValue + c.Sitename = item.OptionValue } - this.Data[item.OptionName] = item.OptionValue - this.Option[item.OptionName] = item.OptionValue + c.Data[item.OptionName] = item.OptionValue + c.Option[item.OptionName] = item.OptionValue if strings.EqualFold(item.OptionName, "ENABLE_ANONYMOUS") && item.OptionValue == "true" { - this.EnableAnonymous = true + c.EnableAnonymous = true } if strings.EqualFold(item.OptionName, "ENABLED_REGISTER") && item.OptionValue == "false" { - this.AllowRegister = false + c.AllowRegister = false } if verNum, _ := strconv.Atoi(item.OptionValue); strings.EqualFold(item.OptionName, "ENABLE_DOCUMENT_HISTORY") && verNum > 0 { - this.EnableDocumentHistory = verNum + c.EnableDocumentHistory = verNum } } } - if v, ok := this.Option["CLOSE_OPEN_SOURCE_LINK"]; ok { - this.Data["CloseOpenSourceLink"] = v == "true" + if v, ok := c.Option["CLOSE_OPEN_SOURCE_LINK"]; ok { + c.Data["CloseOpenSourceLink"] = v == "true" } - if v, ok := this.Option["HIDE_TAG"]; ok { - this.Data["HideTag"] = v == "true" + if v, ok := c.Option["HIDE_TAG"]; ok { + c.Data["HideTag"] = v == "true" } - if v, ok := this.Option["CLOSE_SUBMIT_ENTER"]; ok { - this.Data["CloseSubmitEnter"] = v == "true" + if v, ok := c.Option["CLOSE_SUBMIT_ENTER"]; ok { + c.Data["CloseSubmitEnter"] = v == "true" } - this.Data["SiteName"] = this.Sitename + c.Data["SiteName"] = c.Sitename // 默认显示创建书籍的入口 ShowCreateBookEntrance := false - if this.Member.MemberId > 0 { + if c.Member.MemberId > 0 { ShowCreateBookEntrance = true if opt, err := models.NewOption().FindByKey("ALL_CAN_WRITE_BOOK"); err == nil { - if opt.OptionValue == "false" && this.Member.Role == conf.MemberGeneralRole { + if opt.OptionValue == "false" && c.Member.Role == conf.MemberGeneralRole { // 如果用户现在是普通用户,但是之前是作者或者之前有新建书籍书籍的权限并且创建了书籍,则也给用户显示入口 - ShowCreateBookEntrance = models.NewRelationship().HasRelatedBook(this.Member.MemberId) + ShowCreateBookEntrance = models.NewRelationship().HasRelatedBook(c.Member.MemberId) } } } - this.Data["ShowCreateBookEntrance"] = ShowCreateBookEntrance + c.Data["ShowCreateBookEntrance"] = ShowCreateBookEntrance - if this.Member.MemberId == 0 { - if this.EnableAnonymous == false && !this.NoNeedLoginRouter { // 不允许游客访问 + if c.Member.MemberId == 0 { + if c.EnableAnonymous == false && !c.NoNeedLoginRouter { // 不允许游客访问 allowPaths := map[string]bool{ beego.URLFor("AccountController.Login"): true, beego.URLFor("AccountController.Logout"): true, beego.URLFor("AccountController.FindPassword"): true, beego.URLFor("AccountController.ValidEmail"): true, } - if _, ok := allowPaths[this.Ctx.Request.URL.Path]; !ok { - this.Redirect(beego.URLFor("AccountController.Login"), 302) + if _, ok := allowPaths[c.Ctx.Request.URL.Path]; !ok { + c.Redirect(beego.URLFor("AccountController.Login"), 302) return } } - if this.AllowRegister == false { // 不允许用户注册 + if c.AllowRegister == false { // 不允许用户注册 denyPaths := map[string]bool{ // 第三方登录,如果是新注册的话,需要绑定信息,这里不让绑定信息就是不让注册 beego.URLFor("AccountController.Bind"): true, // 禁止邮箱注册 beego.URLFor("AccountController.Oauth", ":oauth", "email"): true, } - if _, ok := denyPaths[this.Ctx.Request.URL.Path]; ok { - this.Redirect("/login", 302) + if _, ok := denyPaths[c.Ctx.Request.URL.Path]; ok { + c.Redirect("/login", 302) return } } @@ -198,20 +246,20 @@ func (this *BaseController) Prepare() { } // SetMember 获取或设置当前登录用户信息,如果 MemberId 小于 0 则标识删除 Session -func (this *BaseController) SetMember(member models.Member) { +func (c *BaseController) SetMember(member models.Member) { if member.MemberId <= 0 { - this.DelSession(conf.LoginSessionName) - this.DelSession("uid") - this.DestroySession() + c.DelSession(conf.LoginSessionName) + c.DelSession("uid") + c.DestroySession() } else { - this.SetSession(conf.LoginSessionName, member) - this.SetSession("uid", member.MemberId) + c.SetSession(conf.LoginSessionName, member) + c.SetSession("uid", member.MemberId) } } // JsonResult 响应 json 结果 -func (this *BaseController) JsonResult(errCode int, errMsg string, data ...interface{}) { +func (c *BaseController) JsonResult(errCode int, errMsg string, data ...interface{}) { jsonData := make(map[string]interface{}, 3) jsonData["errcode"] = errCode jsonData["message"] = errMsg @@ -223,29 +271,29 @@ func (this *BaseController) JsonResult(errCode int, errMsg string, data ...inter if err != nil { beego.Error(err) } - this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8") + c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8") //this.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache, no-store")//解决回退出现json的问题 //使用gzip原始,json数据会只有原本数据的10分之一左右 - if strings.Contains(strings.ToLower(this.Ctx.Request.Header.Get("Accept-Encoding")), "gzip") { - this.Ctx.ResponseWriter.Header().Set("Content-Encoding", "gzip") + if strings.Contains(strings.ToLower(c.Ctx.Request.Header.Get("Accept-Encoding")), "gzip") { + c.Ctx.ResponseWriter.Header().Set("Content-Encoding", "gzip") //gzip压缩 - w := gzip.NewWriter(this.Ctx.ResponseWriter) + w := gzip.NewWriter(c.Ctx.ResponseWriter) defer w.Close() w.Write(returnJSON) w.Flush() } else { - io.WriteString(this.Ctx.ResponseWriter, string(returnJSON)) + io.WriteString(c.Ctx.ResponseWriter, string(returnJSON)) } - this.StopRun() + c.StopRun() } // ExecuteViewPathTemplate 执行指定的模板并返回执行结果. -func (this *BaseController) ExecuteViewPathTemplate(tplName string, data interface{}) (string, error) { +func (c *BaseController) ExecuteViewPathTemplate(tplName string, data interface{}) (string, error) { var buf bytes.Buffer - viewPath := this.ViewPath + viewPath := c.ViewPath - if this.ViewPath == "" { + if c.ViewPath == "" { viewPath = beego.BConfig.WebConfig.ViewsPath } @@ -256,33 +304,33 @@ func (this *BaseController) ExecuteViewPathTemplate(tplName string, data interfa return buf.String(), nil } -func (this *BaseController) BaseUrl() string { +func (c *BaseController) BaseUrl() string { host := beego.AppConfig.String("sitemap_host") if len(host) > 0 { if strings.HasPrefix(host, "http://") || strings.HasPrefix(host, "https://") { return host } - return this.Ctx.Input.Scheme() + "://" + host + return c.Ctx.Input.Scheme() + "://" + host } - return this.Ctx.Input.Scheme() + "://" + this.Ctx.Request.Host + return c.Ctx.Input.Scheme() + "://" + c.Ctx.Request.Host } //显示错误信息页面. -func (this *BaseController) ShowErrorPage(errCode int, errMsg string) { - this.TplName = "errors/error.html" - this.Data["ErrorMessage"] = errMsg - this.Data["ErrorCode"] = errCode - this.StopRun() +func (c *BaseController) ShowErrorPage(errCode int, errMsg string) { + c.TplName = "errors/error.html" + c.Data["ErrorMessage"] = errMsg + c.Data["ErrorCode"] = errCode + c.StopRun() } //根据页面获取seo //@param page 页面标识 //@param defSeo 默认的seo的map,必须有title、keywords和description字段 -func (this *BaseController) GetSeoByPage(page string, defSeo map[string]string) { +func (c *BaseController) GetSeoByPage(page string, defSeo map[string]string) { var seo models.Seo orm.NewOrm().QueryTable(models.TableSeo).Filter("Page", page).One(&seo) - defSeo["sitename"] = this.Sitename + defSeo["sitename"] = c.Sitename if seo.Id > 0 { for k, v := range defSeo { seo.Title = strings.Replace(seo.Title, fmt.Sprintf("{%v}", k), v, -1) @@ -290,29 +338,29 @@ func (this *BaseController) GetSeoByPage(page string, defSeo map[string]string) seo.Description = strings.Replace(seo.Description, fmt.Sprintf("{%v}", k), v, -1) } } - this.Data["SeoTitle"] = seo.Title - this.Data["SeoKeywords"] = seo.Keywords - this.Data["SeoDescription"] = seo.Description + c.Data["SeoTitle"] = seo.Title + c.Data["SeoKeywords"] = seo.Keywords + c.Data["SeoDescription"] = seo.Description } //站点地图 -func (this *BaseController) Sitemap() { - this.Data["SeoTitle"] = "站点地图 - " + this.Sitename - page, _ := this.GetInt("page") +func (c *BaseController) Sitemap() { + c.Data["SeoTitle"] = "站点地图 - " + c.Sitename + page, _ := c.GetInt("page") listRows := 100 totalCount, docs := models.SitemapData(page, listRows) if totalCount > 0 { - html := utils.GetPagerHtml(this.Ctx.Request.RequestURI, page, listRows, int(totalCount)) - this.Data["PageHtml"] = html + html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, page, listRows, int(totalCount)) + c.Data["PageHtml"] = html } else { - this.Data["PageHtml"] = "" + c.Data["PageHtml"] = "" } //this.JsonResult(0, "aaa", docs) - this.Data["Docs"] = docs - this.TplName = "widgets/sitemap.html" + c.Data["Docs"] = docs + c.TplName = "widgets/sitemap.html" } -func (this *BaseController) loginByMemberId(memberId int) (err error) { +func (c *BaseController) loginByMemberId(memberId int) (err error) { member, err := models.NewMember().Find(memberId) if member.MemberId == 0 { return errors.New("用户不存在") @@ -323,20 +371,20 @@ func (this *BaseController) loginByMemberId(memberId int) (err error) { } member.LastLoginTime = time.Now() member.Update() - this.SetMember(*member) + c.SetMember(*member) var remember CookieRemember remember.MemberId = member.MemberId remember.Account = member.Account remember.Time = time.Now() v, err := utils.Encode(remember) if err == nil { - this.SetSecureCookie(conf.GetAppKey(), "login", v, 24*3600*365) + c.SetSecureCookie(conf.GetAppKey(), "login", v, 24*3600*365) } return err } //在markdown头部加上或者,即解析markdown中的ul>li>a链接作为目录 -func (this *BaseController) sortBySummary(bookIdentify, htmlStr string, bookId int) string { +func (c *BaseController) sortBySummary(bookIdentify, htmlStr string, bookId int) string { debug := beego.AppConfig.String("runmod") != "prod" o := orm.NewOrm() qs := o.QueryTable("md_documents").Filter("book_id", bookId) @@ -450,7 +498,7 @@ func (this *BaseController) sortBySummary(bookIdentify, htmlStr string, bookId i htmlStr, _ = doc.Find("body").Html() if len(hrefs) > 0 { //如果有新创建的文档,则再调用一遍,用于处理排序 - htmlStr = this.replaceLinks(bookIdentify, htmlStr, true) + htmlStr = c.replaceLinks(bookIdentify, htmlStr, true) } return htmlStr } @@ -465,7 +513,7 @@ type Sort struct { //替换链接 //如果是summary,则根据这个进行排序调整 -func (this *BaseController) replaceLinks(bookIdentify string, docHtml string, isSummary ...bool) string { +func (c *BaseController) replaceLinks(bookIdentify string, docHtml string, isSummary ...bool) string { var ( book models.Book docs []models.Document @@ -510,7 +558,7 @@ func (this *BaseController) replaceLinks(bookIdentify string, docHtml string, is if newHtml, err := gq.Find("body").Html(); err == nil { docHtml = newHtml if len(isSummary) > 0 && isSummary[0] == true { //更新排序 - docHtml = this.sortBySummary(bookIdentify, docHtml, book.BookId) //更新排序 + docHtml = c.sortBySummary(bookIdentify, docHtml, book.BookId) //更新排序 } } } else { @@ -522,58 +570,58 @@ func (this *BaseController) replaceLinks(bookIdentify string, docHtml string, is } //内容采集 -func (this *BaseController) Crawl() { - if this.Member.MemberId > 0 { - if val, ok := this.GetSession("crawl").(string); ok && val == "1" { - this.JsonResult(1, "您提交的上一次采集未完成,请稍后再提交新的内容采集") +func (c *BaseController) Crawl() { + if c.Member.MemberId > 0 { + if val, ok := c.GetSession("crawl").(string); ok && val == "1" { + c.JsonResult(1, "您提交的上一次采集未完成,请稍后再提交新的内容采集") } - this.SetSession("crawl", "1") - defer this.DelSession("crawl") - urlStr := this.GetString("url") - force, _ := this.GetBool("force") //是否是强力采集,强力采集,使用Chrome - intelligence, _ := this.GetInt("intelligence") //是否是强力采集,强力采集,使用Chrome - contType, _ := this.GetInt("type") - diySel := this.GetString("diy") + c.SetSession("crawl", "1") + defer c.DelSession("crawl") + urlStr := c.GetString("url") + force, _ := c.GetBool("force") //是否是强力采集,强力采集,使用Chrome + intelligence, _ := c.GetInt("intelligence") //是否是强力采集,强力采集,使用Chrome + contType, _ := c.GetInt("type") + diySel := c.GetString("diy") content, err := utils.CrawlHtml2Markdown(urlStr, contType, force, intelligence, diySel, []string{}, nil) if err != nil { - this.JsonResult(1, "采集失败:"+err.Error()) + c.JsonResult(1, "采集失败:"+err.Error()) } - this.JsonResult(0, "采集成功", content) + c.JsonResult(0, "采集成功", content) } - this.JsonResult(1, "请先登录再操作") + c.JsonResult(1, "请先登录再操作") } //关注或取消关注 -func (this *BaseController) SetFollow() { +func (c *BaseController) SetFollow() { var cancel bool - if this.Member == nil || this.Member.MemberId == 0 { - this.JsonResult(1, "请先登录") + if c.Member == nil || c.Member.MemberId == 0 { + c.JsonResult(1, "请先登录") } - uid, _ := this.GetInt(":uid") - if uid == this.Member.MemberId { - this.JsonResult(1, "自己不能关注自己") + uid, _ := c.GetInt(":uid") + if uid == c.Member.MemberId { + c.JsonResult(1, "自己不能关注自己") } - cancel, _ = new(models.Fans).FollowOrCancel(uid, this.Member.MemberId) + cancel, _ = new(models.Fans).FollowOrCancel(uid, c.Member.MemberId) if cancel { - this.JsonResult(0, "您已经成功取消了关注") + c.JsonResult(0, "您已经成功取消了关注") } - this.JsonResult(0, "您已经成功关注了Ta") + c.JsonResult(0, "您已经成功关注了Ta") } -func (this *BaseController) SignToday() { - if this.Member == nil || this.Member.MemberId == 0 { - this.JsonResult(1, "请先登录") +func (c *BaseController) SignToday() { + if c.Member == nil || c.Member.MemberId == 0 { + c.JsonResult(1, "请先登录") } - reward, err := models.NewSign().Sign(this.Member.MemberId, false) + reward, err := models.NewSign().Sign(c.Member.MemberId, false) if err != nil { - this.JsonResult(1, "签到失败:"+err.Error()) + c.JsonResult(1, "签到失败:"+err.Error()) } - this.JsonResult(0, fmt.Sprintf("恭喜您,签到成功,奖励阅读时长 %v 秒", reward)) + c.JsonResult(0, fmt.Sprintf("恭喜您,签到成功,奖励阅读时长 %v 秒", reward)) } -func (this *BaseController) forbidGeneralRole() bool { +func (c *BaseController) forbidGeneralRole() bool { // 如果只有作者和管理员才能写作的话,那么已创建了书籍的普通用户无法将书籍转为公开或者是私密分享 - if this.Member.Role == conf.MemberGeneralRole && models.GetOptionValue("ALL_CAN_WRITE_BOOK", "true") != "true" { + if c.Member.Role == conf.MemberGeneralRole && models.GetOptionValue("ALL_CAN_WRITE_BOOK", "true") != "true" { return true } return false diff --git a/controllers/SettingController.go b/controllers/SettingController.go index df3583f5..724517e7 100644 --- a/controllers/SettingController.go +++ b/controllers/SettingController.go @@ -3,21 +3,18 @@ package controllers import ( "os" "path/filepath" - "strconv" "strings" "time" - "github.com/TruthHun/BookStack/graphics" - "github.com/TruthHun/BookStack/models/store" - "fmt" "github.com/TruthHun/BookStack/conf" "github.com/TruthHun/BookStack/models" + "github.com/TruthHun/BookStack/models/store" "github.com/TruthHun/BookStack/utils" "github.com/astaxie/beego" - "github.com/astaxie/beego/logs" "github.com/astaxie/beego/orm" + "github.com/casdoor/casdoor-go-sdk/auth" ) type SettingController struct { @@ -26,91 +23,14 @@ type SettingController struct { //基本信息 func (this *SettingController) Index() { - if this.Ctx.Input.IsPost() { - email := strings.TrimSpace(this.GetString("email", "")) - phone := strings.TrimSpace(this.GetString("phone")) - wechatNO := strings.TrimSpace(this.GetString("wechat_no")) - description := strings.TrimSpace(this.GetString("description")) - nickname := strings.TrimSpace(this.GetString("nickname")) - if email == "" { - this.JsonResult(601, "邮箱不能为空") - } - - if l := strings.Count(nickname, "") - 1; l < 2 || l > 20 { - this.JsonResult(6004, "用户昵称限制在2-20个字符") - } - - existMember := models.NewMember().FindByNickname(nickname, "member_id") - if existMember.MemberId > 0 && this.Member.MemberId != existMember.MemberId { - this.JsonResult(6004, "用户昵称已存在,请换一个") - } - - member := this.Member - member.Email = email - member.Phone = phone - member.WechatNO = wechatNO - member.Description = description - if err := member.Update(); err != nil { - this.JsonResult(602, err.Error()) - } - this.SetMember(*member) - this.JsonResult(0, "ok") - } - this.Data["SeoTitle"] = "基本信息 - " + this.Sitename - this.Data["SettingBasic"] = true - this.TplName = "setting/index.html" -} - -//修改密码 -func (this *SettingController) Password() { - - if this.Ctx.Input.IsPost() { - if this.Member.AuthMethod == conf.AuthMethodLDAP { - this.JsonResult(6009, "当前用户不支持修改密码") - } - password1 := this.GetString("password1") - password2 := this.GetString("password2") - password3 := this.GetString("password3") - if password1 == "" { - this.JsonResult(6003, "原密码不能为空") - } - - if password2 == "" { - this.JsonResult(6004, "新密码不能为空") - } - - if count := strings.Count(password2, ""); count < 6 || count > 18 { - this.JsonResult(6009, "密码必须在6-18字之间") - } - - if password2 != password3 { - this.JsonResult(6003, "确认密码不正确") - } - - if ok, _ := utils.PasswordVerify(this.Member.Password, password1); !ok { - this.JsonResult(6005, "原始密码不正确") - } - - if password1 == password2 { - this.JsonResult(6006, "新密码不能和原始密码相同") - } - - pwd, err := utils.PasswordHash(password2) - if err != nil { - this.JsonResult(6007, "密码加密失败") - } - - this.Member.Password = pwd - if err := this.Member.Update(); err != nil { - this.JsonResult(6008, err.Error()) - } - - this.JsonResult(0, "ok") + this.SetSession("isUpdateUser", 1) + account := this.GetSessionClaims() + if account == nil { + this.Redirect(beego.URLFor("AccountController.Login"), 302) + } else { + myProfileUrl := auth.GetMyProfileUrl(account.AccessToken) + this.Redirect(myProfileUrl, 302) } - - this.Data["SettingPwd"] = true - this.Data["SeoTitle"] = "修改密码 - " + this.Sitename - this.TplName = "setting/password.html" } //收藏 @@ -225,100 +145,3 @@ func (this *SettingController) Qrcode() { this.Data["Qrcode"] = new(models.Member).GetQrcodeByUid(this.Member.MemberId) this.Data["SettingQrcode"] = true } - -// Upload 上传图片 -func (this *SettingController) Upload() { - - file, moreFile, err := this.GetFile("image-file") - if err != nil { - logs.Error("", err.Error()) - this.JsonResult(500, "读取文件异常") - } - defer file.Close() - - ext := filepath.Ext(moreFile.Filename) - if !strings.EqualFold(ext, ".png") && !strings.EqualFold(ext, ".jpg") && !strings.EqualFold(ext, ".gif") && !strings.EqualFold(ext, ".jpeg") { - this.JsonResult(500, "不支持的图片格式") - } - - x1, _ := strconv.ParseFloat(this.GetString("x"), 10) - y1, _ := strconv.ParseFloat(this.GetString("y"), 10) - w1, _ := strconv.ParseFloat(this.GetString("width"), 10) - h1, _ := strconv.ParseFloat(this.GetString("height"), 10) - - x := int(x1) - y := int(y1) - width := int(w1) - height := int(h1) - - // fmt.Println(x, x1, y, y1) - - fileName := strconv.FormatInt(time.Now().UnixNano(), 16) - - filePath := filepath.Join("uploads", time.Now().Format("2006/01"), fileName+ext) - - path := filepath.Dir(filePath) - - os.MkdirAll(path, os.ModePerm) - - err = this.SaveToFile("image-file", filePath) - - if err != nil { - logs.Error("", err) - this.JsonResult(500, "图片保存失败") - } - - //剪切图片 - subImg, err := graphics.ImageCopyFromFile(filePath, x, y, width, height) - - if err != nil { - logs.Error("ImageCopyFromFile => ", err) - this.JsonResult(6001, "头像剪切失败") - } - os.Remove(filePath) - - filePath = filepath.Join("uploads", time.Now().Format("200601"), fileName+ext) - - err = graphics.ImageResizeSaveFile(subImg, 120, 120, filePath) - err = graphics.SaveImage(filePath, subImg) - - if err != nil { - logs.Error("保存文件失败 => ", err.Error()) - this.JsonResult(500, "保存文件失败") - } - - url := "/" + strings.Replace(filePath, "\\", "/", -1) - if strings.HasPrefix(url, "//") { - url = string(url[1:]) - } - - if member, err := models.NewMember().Find(this.Member.MemberId); err == nil { - avatar := member.Avatar - member.Avatar = url - err = member.Update() - if err != nil { - this.JsonResult(60001, "保存头像失败") - } - avatar = strings.TrimLeft(avatar, "./") - if strings.HasPrefix(avatar, "uploads/") { - os.Remove(avatar) - } - this.SetMember(*member) - } - switch utils.StoreType { - case utils.StoreOss: //oss存储 - if err := store.ModelStoreOss.MoveToOss("."+url, strings.TrimLeft(url, "./"), true, false); err != nil { - beego.Error(err.Error()) - } else { - url = strings.TrimRight(beego.AppConfig.String("oss::Domain"), "/ ") + url + "/avatar" - } - case utils.StoreLocal: //本地存储 - if err := store.ModelStoreLocal.MoveToStore("."+url, strings.TrimLeft(url, "./")); err != nil { - beego.Error(err.Error()) - } else { - url = "/" + strings.TrimLeft(url, "./") - } - } - - this.JsonResult(0, "ok", url) -} diff --git a/controllers/UserController.go b/controllers/UserController.go index 5d194d7d..1bca9902 100644 --- a/controllers/UserController.go +++ b/controllers/UserController.go @@ -49,6 +49,7 @@ func (this *UserController) Index() { books, totalCount, _ := models.NewBook().FindToPager(page, pageSize, this.UcenterMember.MemberId, 0) this.Data["Books"] = books + this.refreshUser() if totalCount > 0 { html := utils.NewPaginations(conf.RollPage, totalCount, pageSize, page, beego.URLFor("UserController.Index", ":username", this.UcenterMember.Account), "") this.Data["PageHtml"] = html diff --git a/controllers/token_jwt_key.pem b/controllers/token_jwt_key.pem new file mode 100644 index 00000000..c2d6d5f5 --- /dev/null +++ b/controllers/token_jwt_key.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE+TCCAuGgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMDYxHTAbBgNVBAoTFENh +c2Rvb3IgT3JnYW5pemF0aW9uMRUwEwYDVQQDEwxDYXNkb29yIENlcnQwHhcNMjEx +MDE1MDgxMTUyWhcNNDExMDE1MDgxMTUyWjA2MR0wGwYDVQQKExRDYXNkb29yIE9y +Z2FuaXphdGlvbjEVMBMGA1UEAxMMQ2FzZG9vciBDZXJ0MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAsInpb5E1/ym0f1RfSDSSE8IR7y+lw+RJjI74e5ej +rq4b8zMYk7HeHCyZr/hmNEwEVXnhXu1P0mBeQ5ypp/QGo8vgEmjAETNmzkI1NjOQ +CjCYwUrasO/f/MnI1C0j13vx6mV1kHZjSrKsMhYY1vaxTEP3+VB8Hjg3MHFWrb07 +uvFMCJe5W8+0rKErZCKTR8+9VB3janeBz//zQePFVh79bFZate/hLirPK0Go9P1g +OvwIoC1A3sarHTP4Qm/LQRt0rHqZFybdySpyWAQvhNaDFE7mTstRSBb/wUjNCUBD +PTSLVjC04WllSf6Nkfx0Z7KvmbPstSj+btvcqsvRAGtvdsB9h62Kptjs1Yn7GAuo +I3qt/4zoKbiURYxkQJXIvwCQsEftUuk5ew5zuPSlDRLoLByQTLbx0JqLAFNfW3g/ +pzSDjgd/60d6HTmvbZni4SmjdyFhXCDb1Kn7N+xTojnfaNkwep2REV+RMc0fx4Gu +hRsnLsmkmUDeyIZ9aBL9oj11YEQfM2JZEq+RVtUx+wB4y8K/tD1bcY+IfnG5rBpw +IDpS262boq4SRSvb3Z7bB0w4ZxvOfJ/1VLoRftjPbLIf0bhfr/AeZMHpIKOXvfz4 +yE+hqzi68wdF0VR9xYc/RbSAf7323OsjYnjjEgInUtRohnRgCpjIk/Mt2Kt84Kb0 +wn8CAwEAAaMQMA4wDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAn2lf +DKkLX+F1vKRO/5gJ+Plr8P5NKuQkmwH97b8CS2gS1phDyNgIc4/LSdzuf4Awe6ve +C06lVdWSIis8UPUPdjmT2uMPSNjwLxG3QsrimMURNwFlLTfRem/heJe0Zgur9J1M +8haawdSdJjH2RgmFoDeE2r8NVRfhbR8KnCO1ddTJKuS1N0/irHz21W4jt4rxzCvl +2nR42Fybap3O/g2JXMhNNROwZmNjgpsF7XVENCSuFO1jTywLaqjuXCg54IL7XVLG +omKNNNcc8h1FCeKj/nnbGMhodnFWKDTsJcbNmcOPNHo6ixzqMy/Hqc+mWYv7maAG +Jtevs3qgMZ8F9Qzr3HpUc6R3ZYYWDY/xxPisuKftOPZgtH979XC4mdf0WPnOBLqL +2DJ1zaBmjiGJolvb7XNVKcUfDXYw85ZTZQ5b9clI4e+6bmyWqQItlwt+Ati/uFEV +XzCj70B4lALX6xau1kLEpV9O1GERizYRz5P9NJNA7KoO5AVMp9w0DQTkt+LbXnZE +HHnWKy8xHQKZF9sR7YBPGLs/Ac6tviv5Ua15OgJ/8dLRZ/veyFfGo2yZsI+hKVU5 +nCCJHBcAyFnm1hdvdwEdH33jDBjNB6ciotJZrf/3VYaIWSalADosHAgMWfXuWP+h +8XKXmzlxuHbTMQYtZPDgspS5aK+S4Q9wb8RRAYo= +-----END CERTIFICATE----- diff --git a/go.mod b/go.mod index 72a3f719..3b8e73eb 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/TruthHun/BookStack -go 1.13 +go 1.16 replace github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 => github.com/ugorji/go v1.1.7 @@ -17,6 +17,7 @@ require ( github.com/astaxie/beego v1.12.0 github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect github.com/boombuler/barcode v1.0.0 + github.com/casdoor/casdoor-go-sdk v0.4.1 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/disintegration/imaging v1.6.1 github.com/go-sql-driver/mysql v1.5.0 @@ -31,7 +32,6 @@ require ( github.com/stretchr/testify v1.6.1 // indirect github.com/unknwon/com v1.0.1 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect - golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect golang.org/x/sys v0.0.0-20201223074533-0d417f636930 // indirect golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect diff --git a/go.sum b/go.sum index 985cffae..fa20a549 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,45 @@ -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM= -github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk= github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= github.com/PuerkitoBio/goquery v1.6.0 h1:j7taAbelrdcsOlGeMenZxc2AWXD5fieT1/znArdnx94= github.com/PuerkitoBio/goquery v1.6.0/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/TruthHun/converter v0.0.0-20180618131031-80268d67d7a8 h1:E+006K+eHyJkdvR1IPv8jFGA9zvuK47OxlNKoDxMvWM= github.com/TruthHun/converter v0.0.0-20180618131031-80268d67d7a8/go.mod h1:bW/ArSdu0OB6XR3NcPdPBIEeGdQ1GLW9fQavW3Auy2A= -github.com/TruthHun/gotil v0.0.0-20191003091818-17b80aad8a45 h1:o+hC+QvRJlpj6meIX4AC/LKi7UxdEWFs+6zOsLzGoBs= -github.com/TruthHun/gotil v0.0.0-20191003091818-17b80aad8a45/go.mod h1:0V5BlPJa24R0PzuXVURUfjaQ8Z7cmqsVSW7ftuhesN0= github.com/TruthHun/gotil v0.0.0-20210817134928-d2d642c3c7b7 h1:TL0LZ/cmjfX0sEsygVruVoJNGR9krd8UiTPlSg4nT+o= github.com/TruthHun/gotil v0.0.0-20210817134928-d2d642c3c7b7/go.mod h1:i5tqOvH+rsm0voXHnKkzayNkWnv8L/F7wVv+mBdrAL0= github.com/TruthHun/html2article v0.0.0-20180202140721-67d6ff09647b h1:JXD7vWKiJGRqkRuitwA8BxJVGr1yp2hQULQII7RaAXo= @@ -20,9 +50,7 @@ github.com/alexcesaro/mail v0.0.0-20141015155039-29068ce49a17 h1:S0JNYJ6Gv0RGmbz github.com/alexcesaro/mail v0.0.0-20141015155039-29068ce49a17/go.mod h1:WVybKoXJAI3a3TlXlkzIMWs3SmoF29WtmOgInQpL0Ps= github.com/aliyun/aliyun-oss-go-sdk v2.1.0+incompatible h1:90Z2Cp7EqcbaYfVwVjmQoK8kgoFPz+doQlujcwe1BRg= github.com/aliyun/aliyun-oss-go-sdk v2.1.0+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= -github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= -github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/andybalholm/cascadia v1.2.0 h1:vuRCkM5Ozh/BfmsaTm26kbjm0mIOM3yS5Ek/F5h18aE= github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY= @@ -41,7 +69,15 @@ github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDd github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= +github.com/casdoor/casdoor-go-sdk v0.4.1 h1:rCvfmMlxLqSx05kFkDGJ6xh5w4/+mSKny8HA/8JA8Js= +github.com/casdoor/casdoor-go-sdk v0.4.1/go.mod h1:MBed3ISHQfXTtoOCAk5T8l5lt4wFvsyynrw0awggydY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -60,47 +96,96 @@ github.com/disintegration/imaging v1.6.1/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7 github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gin-contrib/cors v1.3.0 h1:PolezCc89peu+NgkIWt9OB01Kbzt6IP0J/JvkG6xxlg= github.com/gin-contrib/cors v1.3.0/go.mod h1:artPvLlhkF7oG06nK8v3U8TNz6IeX+w1uzCSEId5/Vc= -github.com/gin-contrib/gzip v0.0.1 h1:ezvKOL6jH+jlzdHNE4h9h8q8uMpDQjyl0NN0Jd7jozc= github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w= github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= -github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= +github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kardianos/service v1.0.0 h1:HgQS3mFfOlyntWX8Oke98JcJLqt1DBcHR4kxShpYef0= github.com/kardianos/service v1.0.0/go.mod h1:8CzDhVuCuugtsHyZoTvsOBuvonN/UDBvl0kH+BUxvbo= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -110,29 +195,25 @@ github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lifei6671/gocaptcha v0.0.0-20190301083731-c467a25bc100 h1:DkXBDLKHcTtca65BA9tZoFdWMZ9YJtNm5YyC36tKX2U= github.com/lifei6671/gocaptcha v0.0.0-20190301083731-c467a25bc100/go.mod h1:jEGhhJ8Op4YifySgvIySNtK5vxJta0V8nwwu+1uoVmE= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mssola/user_agent v0.5.0 h1:gRF7/x8cKt8qzAosYGsBNyirta+F8fvYDlJrgXws9AQ= github.com/mssola/user_agent v0.5.0/go.mod h1:UFiKPVaShrJGW93n4uo8dpPdg1BSVpw2P9bneo0Mtp8= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk= github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -148,8 +229,10 @@ github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBf github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg= github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -161,6 +244,8 @@ github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXc github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -171,51 +256,276 @@ github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo= golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU= @@ -224,4 +534,15 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/models/member.go b/models/member.go index e19b9a5c..a831821a 100644 --- a/models/member.go +++ b/models/member.go @@ -169,10 +169,6 @@ func (m *Member) Add() error { return errors.New("邮箱格式不正确") } - if l := strings.Count(m.Password, ""); l < 7 || l >= 50 { - return errors.New("密码不能为空且必须在6-50个字符之间") - } - cond := orm.NewCondition().Or("email", m.Email).Or("nickname", m.Nickname).Or("account", m.Account) var one Member if o.QueryTable(m.TableNameWithPrefix()).SetCond(cond).One(&one, "member_id", "nickname", "account", "email"); one.MemberId > 0 { @@ -217,9 +213,6 @@ func (m *Member) Add() error { func (m *Member) Update(cols ...string) error { o := orm.NewOrm() - if m.Email == "" { - return errors.New("邮箱不能为空") - } if _, err := o.Update(m, cols...); err != nil { return err } diff --git a/routers/web.go b/routers/web.go index 5163d404..2bd8b212 100644 --- a/routers/web.go +++ b/routers/web.go @@ -16,13 +16,9 @@ func webRouter() { beego.Router("/submit", &controllers.SubmitController{}, "post:Post") beego.Router("/login", &controllers.AccountController{}, "*:Login") - beego.Router("/login/:oauth", &controllers.AccountController{}, "*:Oauth") + beego.Router("/signup", &controllers.AccountController{}, "*:Signup") + beego.Router("/login/callback", &controllers.AccountController{}, "*:Callback") beego.Router("/logout", &controllers.AccountController{}, "*:Logout") - beego.Router("/bind", &controllers.AccountController{}, "post:Bind") - beego.Router("/note", &controllers.AccountController{}, "get,post:Note") - beego.Router("/find_password", &controllers.AccountController{}, "*:FindPassword") - beego.Router("/valid_email", &controllers.AccountController{}, "post:ValidEmail") - //beego.Router("/captcha", &controllers.AccountController{}, "*:Captcha") beego.Router("/manager", &controllers.ManagerController{}, "*:Index") beego.Router("/manager/users", &controllers.ManagerController{}, "*:Users") @@ -73,8 +69,6 @@ func webRouter() { beego.Router("/manager/del-tags", &controllers.ManagerController{}, "get:DelTags") beego.Router("/setting", &controllers.SettingController{}, "*:Index") - beego.Router("/setting/password", &controllers.SettingController{}, "*:Password") - beego.Router("/setting/upload", &controllers.SettingController{}, "*:Upload") beego.Router("/setting/star", &controllers.SettingController{}, "*:Star") beego.Router("/setting/qrcode", &controllers.SettingController{}, "*:Qrcode") diff --git a/views/account/bind.html b/views/account/bind.html deleted file mode 100644 index 17374ba8..00000000 --- a/views/account/bind.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - {{template "widgets/head.html" .}} - - - - -
- -
-
-{{/**/}} - -{{/**/}} - - - -{{/*js直接写在这里了*/}} - - - \ No newline at end of file diff --git a/views/account/find_password_setp1.html b/views/account/find_password_setp1.html deleted file mode 100644 index b8978701..00000000 --- a/views/account/find_password_setp1.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - {{template "widgets/head.html" .}} - - - -
- -
-
-{{template "widgets/footer.html" .}} - - - - - - \ No newline at end of file diff --git a/views/account/find_password_setp2.html b/views/account/find_password_setp2.html deleted file mode 100644 index 4ae2360d..00000000 --- a/views/account/find_password_setp2.html +++ /dev/null @@ -1,125 +0,0 @@ - - - -{{template "widgets/head.html" .}} - - - -
- -
-
-{{template "widgets/footer.html" .}} - - - - - \ No newline at end of file diff --git a/views/account/mail_template.html b/views/account/mail_template.html deleted file mode 100644 index 875c1c6d..00000000 --- a/views/account/mail_template.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - 找回密码 - {{.SITE_NAME}} - - - -
-
- -
-
- -

您好:

- -

您在 {{.SITE_NAME}} 提交了找回密码申请。
如果您没有提交修改密码的申请, 请忽略本邮件

- -

- 请点击链接继续: {{.url}} -

-

- 好的密码,不但应该容易记住,还要尽量符合以下强度标准: -

    -
  • 包含大小写字母、数字和符号
  • -
  • 不少于 10 位
  • -
  • 不包含生日、手机号码等易被猜出的信息
  • -
-

- -
-
-
- - \ No newline at end of file diff --git a/views/setting/index.html b/views/setting/index.html deleted file mode 100644 index 9c9dd8d6..00000000 --- a/views/setting/index.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - {{template "widgets/head.html" .}} - - - - - -
- {{template "widgets/header.html" .}} -
-
- - {{template "setting/menu.html" .}} - -
-
-
- 个人设置 -
-
-
-
- - -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -

描述不能超过500字

-
-
- - -
-
-
- -
-
-
-
-
- - - - -{{/**/}} - -{{/**/}} - - - - - - - - - \ No newline at end of file diff --git a/views/setting/menu.html b/views/setting/menu.html index a2bdce26..a46c2bff 100644 --- a/views/setting/menu.html +++ b/views/setting/menu.html @@ -1,9 +1,6 @@
{{else}} -
  • 注册
  • +
  • 注册
  • 登录
  • {{end}}