commit 61052c4596b5ca94a5340d86d30d2c4348c1acb0
parent c5b7648f443e441ef192709701a94ad03c2650e2
Author: n0tr1v <n0tr1v@protonmail.com>
Date: Mon, 12 Jun 2023 19:42:32 -0700
move code
Diffstat:
2 files changed, 895 insertions(+), 872 deletions(-)
diff --git a/pkg/web/handlers/handlers.go b/pkg/web/handlers/handlers.go
@@ -46,7 +46,6 @@ import (
"dkforest/pkg/cache"
"dkforest/pkg/captcha"
- "dkforest/pkg/global"
armor1 "filippo.io/age/armor"
"dkforest/pkg/config"
@@ -2531,448 +2530,6 @@ func ShopHandler(c echo.Context) error {
return c.Render(http.StatusOK, "shop", data)
}
-// SettingsChatHandler ...
-func SettingsChatHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- var data settingsChatData
- data.ActiveTab = "chat"
- data.AllFonts = utils.GetFonts()
- data.ChatColor = authUser.ChatColor
- data.ChatBackgroundColor = authUser.ChatBackgroundColor
- data.ChatFont = authUser.ChatFont
- data.ChatItalic = authUser.ChatItalic
- data.ChatBold = authUser.ChatBold
- data.DateFormat = authUser.DateFormat
- data.ChatReadMarkerEnabled = authUser.ChatReadMarkerEnabled
- data.ChatReadMarkerColor = authUser.ChatReadMarkerColor
- data.ChatReadMarkerSize = authUser.ChatReadMarkerSize
- data.DisplayHellbanned = authUser.DisplayHellbanned
- data.DisplayModerators = authUser.DisplayModerators
- data.DisplayDeleteButton = authUser.DisplayDeleteButton
- data.DisplayKickButton = authUser.DisplayKickButton
- data.DisplayHellbanButton = authUser.DisplayHellbanButton
- data.HideRightColumn = authUser.HideRightColumn
- data.ChatBarAtBottom = authUser.ChatBarAtBottom
- data.AutocompleteCommandsEnabled = authUser.AutocompleteCommandsEnabled
- data.SpellcheckEnabled = authUser.SpellcheckEnabled
- data.AfkIndicatorEnabled = authUser.AfkIndicatorEnabled
- data.HideIgnoredUsersFromList = authUser.HideIgnoredUsersFromList
- data.HellbanOpacity = float64(authUser.HellbanOpacity) / 100
- data.CodeBlockHeight = authUser.CodeBlockHeight
- data.RefreshRate = authUser.RefreshRate
- data.NotifyNewMessage = authUser.NotifyNewMessage
- data.NotifyTagged = authUser.NotifyTagged
- data.NotifyPmmed = authUser.NotifyPmmed
- data.NotifyNewMessageSound = authUser.NotifyNewMessageSound
- data.NotifyTaggedSound = authUser.NotifyTaggedSound
- data.NotifyPmmedSound = authUser.NotifyPmmedSound
- data.Theme = authUser.Theme
- data.NotifyChessGames = authUser.NotifyChessGames
- data.NotifyChessMove = authUser.NotifyChessMove
- data.UseStream = authUser.UseStream
- data.ConfirmExternalLinks = authUser.ConfirmExternalLinks
- data.ChessSoundsEnabled = authUser.ChessSoundsEnabled
-
- if c.Request().Method == http.MethodGet {
- return c.Render(http.StatusOK, "settings.chat", data)
- }
-
- // POST
- formName := c.FormValue("formName")
- if formName == "changeSettings" {
- return changeSettingsForm(c, data)
- }
- return c.Render(http.StatusOK, "settings.chat", data)
-}
-
-func SettingsChatPMHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsChatPMData
- data.ActiveTab = "chat"
- data.PmMode = authUser.PmMode
- data.BlockNewUsersPm = authUser.BlockNewUsersPm
- data.WhitelistedUsers, _ = db.GetPmWhitelistedUsers(authUser.ID)
- data.BlacklistedUsers, _ = db.GetPmBlacklistedUsers(authUser.ID)
-
- if c.Request().Method == http.MethodGet {
- return c.Render(http.StatusOK, "settings.chat-pm", data)
- }
-
- // POST
- formName := c.Request().PostFormValue("formName")
-
- if formName == "addWhitelist" {
- data.AddWhitelist = database.Username(strings.TrimSpace(c.Request().PostFormValue("username")))
- user, err := db.GetUserByUsername(data.AddWhitelist)
- if err != nil {
- data.Error = "username not found"
- return c.Render(http.StatusOK, "settings.chat-pm", data)
- }
- db.AddWhitelistedUser(authUser.ID, user.ID)
- return c.Redirect(http.StatusFound, c.Request().Referer())
-
- } else if formName == "rmWhitelist" {
- userID := dutils.DoParseUserID(c.Request().PostFormValue("userID"))
- db.RmWhitelistedUser(authUser.ID, userID)
- return c.Redirect(http.StatusFound, c.Request().Referer())
-
- } else if formName == "addBlacklist" {
- data.AddBlacklist = database.Username(strings.TrimSpace(c.Request().PostFormValue("username")))
- user, err := db.GetUserByUsername(data.AddBlacklist)
- if err != nil {
- data.Error = "username not found"
- return c.Render(http.StatusOK, "settings.chat-pm", data)
- }
- db.AddBlacklistedUser(authUser.ID, user.ID)
- return c.Redirect(http.StatusFound, c.Request().Referer())
-
- } else if formName == "rmBlacklist" {
- userID := dutils.DoParseUserID(c.Request().PostFormValue("userID"))
- db.RmBlacklistedUser(authUser.ID, userID)
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
-
- data.PmMode = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("pm_mode")), 0, 1)
- authUser.BlockNewUsersPm = utils.DoParseBool(c.Request().PostFormValue("block_new_users_pm"))
- authUser.PmMode = data.PmMode
- authUser.DoSave(db)
- return c.Redirect(http.StatusFound, c.Request().Referer())
-}
-
-func SettingsChatIgnoreHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsChatIgnoreData
- data.ActiveTab = "chat"
- data.PmMode = authUser.PmMode
- data.IgnoredUsers, _ = db.GetIgnoredUsers(authUser.ID)
-
- if c.Request().Method == http.MethodGet {
- return c.Render(http.StatusOK, "settings.chat-ignore", data)
- }
-
- // POST
- formName := c.Request().PostFormValue("formName")
-
- if formName == "addIgnored" {
- data.AddIgnored = database.Username(strings.TrimSpace(c.Request().PostFormValue("username")))
- user, err := db.GetUserByUsername(data.AddIgnored)
- if err != nil {
- data.Error = "username not found"
- return c.Render(http.StatusOK, "settings.chat-ignore", data)
- }
- db.IgnoreUser(authUser.ID, user.ID)
- return c.Redirect(http.StatusFound, c.Request().Referer())
-
- } else if formName == "rmIgnored" {
- userID := dutils.DoParseUserID(c.Request().PostFormValue("userID"))
- db.UnIgnoreUser(authUser.ID, userID)
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
-
- data.PmMode = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("pm_mode")), 0, 1)
- authUser.PmMode = data.PmMode
- authUser.DoSave(db)
- return c.Redirect(http.StatusFound, c.Request().Referer())
-}
-
-func SettingsChatSnippetsHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsChatSnippetsData
- data.ActiveTab = "snippets"
- data.Snippets, _ = db.GetUserSnippets(authUser.ID)
-
- if c.Request().Method == http.MethodGet {
- return c.Render(http.StatusOK, "settings.chat-snippets", data)
- }
-
- // POST
- formName := c.Request().PostFormValue("formName")
-
- if formName == "addSnippet" {
- data.Name = strings.TrimSpace(c.Request().PostFormValue("name"))
- data.Text = strings.TrimSpace(c.Request().PostFormValue("text"))
- if len(data.Snippets) >= 20 {
- data.Error = "snippets limit reached"
- return c.Render(http.StatusOK, "settings.chat-snippets", data)
- }
- if !govalidator.Matches(data.Name, `^\w{1,20}$`) {
- data.Error = "name must match : ^\\w{1,20}$"
- return c.Render(http.StatusOK, "settings.chat-snippets", data)
- }
- if !govalidator.StringLength(data.Name, "1", "20") {
- data.Error = "name must be 1-20 characters"
- return c.Render(http.StatusOK, "settings.chat-snippets", data)
- }
- if !govalidator.StringLength(data.Text, "1", "1000") {
- data.Error = "text must be 1-1000 characters"
- return c.Render(http.StatusOK, "settings.chat-snippets", data)
- }
- if _, err := db.CreateSnippet(authUser.ID, data.Name, data.Text); err != nil {
- data.Error = err.Error()
- return c.Render(http.StatusOK, "settings.chat-snippets", data)
- }
- return c.Redirect(http.StatusFound, c.Request().Referer())
-
- } else if formName == "rmSnippet" {
- snippetName := c.Request().PostFormValue("snippetName")
- db.DeleteSnippet(authUser.ID, snippetName)
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
-
- return c.Redirect(http.StatusFound, c.Request().Referer())
-}
-
-func SettingsUploadsHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsUploadsData
- data.ActiveTab = "uploads"
- data.Files, _ = db.GetUserUploads(authUser.ID)
- for _, f := range data.Files {
- data.TotalSize += f.FileSize
- }
-
- if c.Request().Method == http.MethodGet {
- return c.Render(http.StatusOK, "settings.uploads", data)
- }
-
- // POST
- formName := c.FormValue("formName")
- if formName == "deleteUpload" {
- fileName := c.Request().PostFormValue("file_name")
- file, err := db.GetUploadByFileName(fileName)
- if err != nil {
- return c.Redirect(http.StatusFound, "/")
- }
- if authUser.ID != file.UserID {
- return c.Redirect(http.StatusFound, "/")
- }
- if err := file.Delete(db); err != nil {
- logrus.Error(err)
- }
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
- return c.Render(http.StatusOK, "settings.uploads", data)
-}
-
-func SettingsPublicNotesHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- if !authUser.CanUseForumFn() {
- return c.Render(http.StatusOK, "flash", FlashResponse{Message: hutils.AccountTooYoungErr.Error(), Redirect: c.Request().Referer(), Type: "alert-danger"})
- }
- var data settingsPublicNotesData
- data.ActiveTab = "notes"
- data.Notes, _ = db.GetUserPublicNotes(authUser.ID)
-
- if c.Request().Method == http.MethodPost {
- notes := c.Request().PostFormValue("public_notes")
- if err := db.SetUserPublicNotes(authUser.ID, notes); err != nil {
- data.Error = err.Error()
- return c.Render(http.StatusOK, "settings.public-notes", data)
- }
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
-
- return c.Render(http.StatusOK, "settings.public-notes", data)
-}
-
-func SettingsPrivateNotesHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- if !authUser.CanUseForumFn() {
- return c.Render(http.StatusOK, "flash", FlashResponse{Message: hutils.AccountTooYoungErr.Error(), Redirect: c.Request().Referer(), Type: "alert-danger"})
- }
- var data settingsPrivateNotesData
- data.ActiveTab = "notes"
- if !authUser.IsUnderDuress {
- data.Notes, _ = db.GetUserPrivateNotes(authUser.ID)
- }
-
- if c.Request().Method == http.MethodPost {
- notes := c.Request().PostFormValue("private_notes")
- if err := db.SetUserPrivateNotes(authUser.ID, notes); err != nil {
- data.Error = err.Error()
- return c.Render(http.StatusOK, "settings.private-notes", data)
- }
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
-
- return c.Render(http.StatusOK, "settings.private-notes", data)
-}
-
-func SettingsInboxHandler(c echo.Context) error {
- authCookie, _ := c.Cookie(hutils.AuthCookieName)
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsInboxData
- data.ActiveTab = "inbox"
- // Do not fetch inboxes & notifications if logged in under duress
- if !authUser.IsUnderDuress {
- global.DeleteUserNotificationCount(authUser.ID, authCookie.Value)
- data.ChatMessages, _ = db.GetUserChatInboxMessages(authUser.ID)
- data.Notifications, _ = db.GetUserNotifications(authUser.ID)
- data.SessionNotifications, _ = db.GetUserSessionNotifications(authCookie.Value)
- }
- for _, m := range data.ChatMessages {
- data.Notifs = append(data.Notifs, InboxTmp{IsNotif: false, ChatInboxMessage: m})
- }
- for _, m := range data.Notifications {
- data.Notifs = append(data.Notifs, InboxTmp{IsNotif: true, Notification: m})
- }
- for _, m := range data.SessionNotifications {
- data.Notifs = append(data.Notifs, InboxTmp{IsNotif: true, SessionNotification: m})
- }
- sort.Slice(data.Notifs, func(i, j int) bool {
- a := data.Notifs[i]
- b := data.Notifs[j]
- var tsa time.Time
- var tsb time.Time
- if a.Notification.ID != 0 {
- tsa = a.Notification.CreatedAt
- } else if a.SessionNotification.ID != 0 {
- tsa = a.SessionNotification.CreatedAt
- } else {
- tsa = a.ChatInboxMessage.CreatedAt
- }
- if b.Notification.ID != 0 {
- tsb = b.Notification.CreatedAt
- } else if b.SessionNotification.ID != 0 {
- tsb = b.SessionNotification.CreatedAt
- } else {
- tsb = b.ChatInboxMessage.CreatedAt
- }
- return tsa.After(tsb)
- })
- return c.Render(http.StatusOK, "settings.inbox", data)
-}
-
-func SettingsInboxSentHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsInboxSentData
- data.ActiveTab = "inbox"
- // Do not fetch inboxes & notifications if logged in under duress
- if !authUser.IsUnderDuress {
- data.ChatInboxSent, _ = db.GetUserChatInboxMessagesSent(authUser.ID)
- }
- return c.Render(http.StatusOK, "settings.inbox-sent", data)
-}
-
-func SettingsAPIHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsAPIData
- data.ActiveTab = "api"
- data.APIKey = authUser.ApiKey
- if c.Request().Method == http.MethodPost {
- formName := c.Request().PostFormValue("formName")
- btnSubmit := c.Request().PostFormValue("btn_submit")
- if btnSubmit == "Cancel" {
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
- if formName == "confirm" {
- token := utils.GenerateToken16()
- authUser.ApiKey = token
- authUser.DoSave(db)
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
- data.NeedConfirm = true
- }
- return c.Render(http.StatusOK, "settings.api", data)
-}
-
-func SettingsSecurityHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsSecurityData
- data.ActiveTab = "security"
- data.Logs, _ = db.GetSecurityLogs(authUser.ID)
- return c.Render(http.StatusOK, "settings.security", data)
-}
-
-func SettingsSessionsHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data settingsSessionsData
- data.ActiveTab = "sessions"
- sessions := db.GetActiveUserSessions(authUser.ID)
- authCookie, _ := c.Cookie(hutils.AuthCookieName)
- for _, session := range sessions {
- s := WrapperSession{Session: session}
- if authCookie.Value == s.Token {
- s.CurrentSession = true
- }
- data.Sessions = append(data.Sessions, s)
- }
-
- if c.Request().Method == http.MethodPost {
- formName := c.Request().PostFormValue("formName")
- if formName == "revoke_all_other_sessions" {
- _ = db.DeleteUserOtherSessions(authUser.ID, authCookie.Value)
- } else {
- sessionToken := c.Request().PostFormValue("sessionToken")
- _ = db.DeleteUserSessionByToken(authUser.ID, sessionToken)
- }
- return c.Redirect(http.StatusFound, c.Request().Referer())
- }
-
- return c.Render(http.StatusOK, "settings.sessions", data)
-}
-
-// SettingsAccountHandler ...
-func SettingsAccountHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- var data settingsAccountData
- data.AccountTooYoungErrorString = hutils.AccountTooYoungErr.Error()
- data.ActiveTab = "account"
- data.Username = authUser.Username
- data.Email = authUser.Email
- data.LastSeenPublic = authUser.LastSeenPublic
- data.TerminateAllSessionsOnLogout = authUser.TerminateAllSessionsOnLogout
- data.Website = authUser.Website
-
- if c.Request().Method == http.MethodGet {
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- // POST
- formName := c.FormValue("formName")
- switch formName {
- case "changeUsername":
- return changeUsernameForm(c, data)
- case "editProfile":
- return editProfileForm(c, data)
- case "changeAvatar":
- return changeAvatarForm(c, data)
- default:
- return c.Render(http.StatusOK, "settings.account", data)
- }
-}
-
-func SettingsPasswordHandler(c echo.Context) error {
- var data settingsPasswordData
- data.ActiveTab = "password"
-
- if c.Request().Method == http.MethodGet {
- return c.Render(http.StatusOK, "settings.password", data)
- }
-
- // POST
- formName := c.FormValue("formName")
- switch formName {
- case "changePassword":
- return changePasswordForm(c, data)
- case "changeDuressPassword":
- return changeDuressPasswordForm(c, data)
- default:
- return c.Render(http.StatusOK, "settings.password", data)
- }
-}
-
func SettingsSecretPhraseHandler(c echo.Context) error {
authUser := c.Get("authUser").(*database.User)
db := c.Get("database").(*database.DkfDB)
@@ -3057,315 +2614,6 @@ func SettingsWebsiteHandler(c echo.Context) error {
return c.Render(http.StatusOK, "settings.website", data)
}
-func editProfileForm(c echo.Context, data settingsAccountData) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
-
- email := c.Request().PostFormValue("email")
- website := c.Request().PostFormValue("website")
- lastSeenPublic := utils.DoParseBool(c.Request().PostFormValue("last_seen_public"))
- terminateAllSessionsOnLogout := utils.DoParseBool(c.Request().PostFormValue("terminate_all_sessions_on_logout"))
- data.Email = email
- data.Website = website
- data.LastSeenPublic = lastSeenPublic
- data.TerminateAllSessionsOnLogout = terminateAllSessionsOnLogout
-
- if data.Email != "" && !govalidator.IsEmail(data.Email) {
- data.ErrorEmail = "invalid email"
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- if data.Website != "" && !govalidator.IsURL(data.Website) {
- data.ErrorWebsite = "invalid website"
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- authUser.Website = data.Website
- authUser.Email = data.Email
- authUser.LastSeenPublic = data.LastSeenPublic
- authUser.TerminateAllSessionsOnLogout = data.TerminateAllSessionsOnLogout
- authUser.DoSave(db)
-
- return c.Render(http.StatusOK, "flash", FlashResponse{Message: "Profile changed successfully", Redirect: c.Request().Referer()})
-}
-
-func changeAvatarForm(c echo.Context, data settingsAccountData) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- if !authUser.CanUpload() {
- data.ErrorAvatar = hutils.AccountTooYoungErr.Error()
- return c.Render(http.StatusOK, "settings.account", data)
- }
- if err := c.Request().ParseMultipartForm(config.MaxAvatarFormSize); err != nil {
- data.ErrorAvatar = err.Error()
- return c.Render(http.StatusOK, "settings.account", data)
- }
- file, handler, err := c.Request().FormFile("avatar")
- if err != nil {
- data.ErrorAvatar = "Failed to get avatar: " + err.Error()
- return c.Render(http.StatusOK, "settings.account", data)
- }
- defer file.Close()
- if handler.Size > config.MaxAvatarSize {
- data.ErrorAvatar = fmt.Sprintf("The maximum file size for avatars is %s", humanize.Bytes(config.MaxAvatarSize))
- return c.Render(http.StatusOK, "settings.account", data)
- }
- fileBytes, err := ioutil.ReadAll(file)
- if err != nil {
- data.ErrorAvatar = err.Error()
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- filetype := http.DetectContentType(fileBytes)
- if !utils.InArr(filetype, []string{"image/jpeg", "image/png", "image/gif", "image/bmp", "image/webp"}) {
- data.ErrorAvatar = "The provided file format is not allowed. Please upload a JPEG, PNG, WEBP, BMP or GIF image"
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- // Validate image type and determine extension
- if handler.Header.Get("Content-Type") != filetype {
- data.ErrorAvatar = "Content-Type does not match mimetype"
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- im, _, err := image.DecodeConfig(bytes.NewReader(fileBytes))
- if err != nil {
- data.ErrorAvatar = err.Error()
- return c.Render(http.StatusOK, "settings.account", data)
- }
- if im.Width > 120 || im.Height > 120 {
- data.ErrorAvatar = "The maximum dimensions for avatars are: 120x120 pixels"
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- if filetype == "image/jpeg" {
- fileBytes, err = utils.ReencodeJpg(fileBytes)
- } else if filetype == "image/png" {
- fileBytes, err = utils.ReencodePng(fileBytes)
- }
- if err != nil {
- data.Error = err.Error()
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- authUser.SetAvatar(fileBytes)
- authUser.DoSave(db)
- return c.Render(http.StatusOK, "flash", FlashResponse{Message: "Avatar changed successfully", Redirect: c.Request().Referer()})
-}
-
-func changeUsernameForm(c echo.Context, data settingsAccountData) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- if !authUser.CanChangeUsername {
- data.ErrorUsername = "Not allowed to change your username"
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- username := database.Username(c.Request().PostFormValue("username"))
- data.Username = username
-
- if username == authUser.Username {
- data.ErrorUsername = "username did not change"
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- if err := db.CanRenameTo(authUser.Username, username); err != nil {
- data.ErrorUsername = err.Error()
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- managers.ActiveUsers.RemoveUser(authUser.ID)
- authUser.Username = username
- if err := db.DB().Save(authUser).Error; err != nil {
- logrus.Error(err)
- data.ErrorUsername = err.Error()
- return c.Render(http.StatusOK, "settings.account", data)
- }
-
- db.CreateSecurityLog(authUser.ID, database.UsernameChangedSecurityLog)
- return c.Render(http.StatusOK, "flash", FlashResponse{Message: "Username changed successfully", Redirect: c.Request().Referer()})
-}
-
-func changeSettingsForm(c echo.Context, data settingsChatData) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
-
- data.RefreshRate = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("refresh_rate")), 5, 60)
- data.ChatColor = c.Request().PostFormValue("chat_color")
- data.ChatBackgroundColor = c.Request().PostFormValue("chat_background_color")
- data.ChatFont = utils.DoParseInt64(c.Request().PostFormValue("chat_font"))
- data.ChatBold = utils.DoParseBool(c.Request().PostFormValue("chat_bold"))
- data.DateFormat = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("date_format")), 0, 4)
- data.ChatReadMarkerEnabled = utils.DoParseBool(c.Request().PostFormValue("chat_read_marker_enabled"))
- data.ChatReadMarkerColor = c.Request().PostFormValue("chat_read_marker_color")
- data.ChatReadMarkerSize = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("chat_read_marker_size")), 1, 5)
- data.DisplayHellbanned = utils.DoParseBool(c.Request().PostFormValue("display_hellbanned"))
- data.DisplayModerators = utils.DoParseBool(c.Request().PostFormValue("display_moderators"))
- data.DisplayKickButton = utils.DoParseBool(c.Request().PostFormValue("display_kick_button"))
- data.DisplayDeleteButton = utils.DoParseBool(c.Request().PostFormValue("display_delete_button"))
- data.DisplayHellbanButton = utils.DoParseBool(c.Request().PostFormValue("display_hellban_button"))
- data.HideIgnoredUsersFromList = utils.DoParseBool(c.Request().PostFormValue("hide_ignored_users_from_list"))
- data.HideRightColumn = utils.DoParseBool(c.Request().PostFormValue("hide_right_column"))
- data.ChatBarAtBottom = utils.DoParseBool(c.Request().PostFormValue("chat_bar_at_bottom"))
- data.AutocompleteCommandsEnabled = utils.DoParseBool(c.Request().PostFormValue("autocomplete_commands_enabled"))
- data.SpellcheckEnabled = utils.DoParseBool(c.Request().PostFormValue("spellcheck_enabled"))
- data.AfkIndicatorEnabled = utils.DoParseBool(c.Request().PostFormValue("afk_indicator_enabled"))
- data.ChatItalic = utils.DoParseBool(c.Request().PostFormValue("chat_italic"))
- data.NotifyNewMessage = utils.DoParseBool(c.Request().PostFormValue("notify_new_message"))
- data.NotifyTagged = utils.DoParseBool(c.Request().PostFormValue("notify_tagged"))
- data.NotifyPmmed = utils.DoParseBool(c.Request().PostFormValue("notify_pmmed"))
- data.Theme = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("theme")), 0, 2)
- data.NotifyChessGames = utils.DoParseBool(c.Request().PostFormValue("notify_chess_games"))
- data.NotifyChessMove = utils.DoParseBool(c.Request().PostFormValue("notify_chess_move"))
- data.UseStream = utils.DoParseBool(c.Request().PostFormValue("use_stream"))
- data.ConfirmExternalLinks = utils.DoParseBool(c.Request().PostFormValue("confirm_external_links"))
- data.ChessSoundsEnabled = utils.DoParseBool(c.Request().PostFormValue("chess_sounds_enabled"))
- data.HellbanOpacity = utils.DoParseF64(c.Request().PostFormValue("hellban_opacity"))
- data.CodeBlockHeight = utils.DoParseInt64(c.Request().PostFormValue("code_block_height"))
- //data.NotifyNewMessageSound = utils.DoParseInt64(c.Request().PostFormValue("notify_new_message_sound"))
- //data.NotifyTaggedSound = utils.DoParseInt64(c.Request().PostFormValue("notify_tagged_sound"))
- //data.NotifyPmmedSound = utils.DoParseInt64(c.Request().PostFormValue("notify_pmmed_sound"))
- colorRgx := regexp.MustCompile(`^#[0-9a-fA-F]{6}$`)
- if !colorRgx.MatchString(data.ChatColor) {
- data.Error = "Invalid color format (text)"
- return c.Render(http.StatusOK, "settings.chat", data)
- }
- if !colorRgx.MatchString(data.ChatBackgroundColor) {
- data.Error = "Invalid color format (background)"
- return c.Render(http.StatusOK, "settings.chat", data)
- }
- if !colorRgx.MatchString(data.ChatReadMarkerColor) {
- data.Error = "Invalid marker color format"
- return c.Render(http.StatusOK, "settings.chat", data)
- }
- authUser.RefreshRate = data.RefreshRate
- if authUser.CanChangeColor {
- authUser.ChatColor = data.ChatColor
- }
- authUser.ChatBackgroundColor = data.ChatBackgroundColor
- authUser.ChatFont = data.ChatFont
- authUser.ChatItalic = data.ChatItalic
- authUser.ChatBold = data.ChatBold
- authUser.DateFormat = data.DateFormat
- authUser.ChatReadMarkerEnabled = data.ChatReadMarkerEnabled
- authUser.ChatReadMarkerColor = data.ChatReadMarkerColor
- authUser.ChatReadMarkerSize = data.ChatReadMarkerSize
- authUser.DisplayDeleteButton = data.DisplayDeleteButton
- authUser.HideIgnoredUsersFromList = data.HideIgnoredUsersFromList
- authUser.HideRightColumn = data.HideRightColumn
- authUser.ChatBarAtBottom = data.ChatBarAtBottom
- authUser.AutocompleteCommandsEnabled = data.AutocompleteCommandsEnabled
- authUser.SpellcheckEnabled = data.SpellcheckEnabled
- authUser.AfkIndicatorEnabled = data.AfkIndicatorEnabled
- authUser.NotifyNewMessage = data.NotifyNewMessage
- authUser.NotifyTagged = data.NotifyTagged
- authUser.NotifyPmmed = data.NotifyPmmed
- authUser.NotifyChessGames = data.NotifyChessGames
- authUser.NotifyChessMove = data.NotifyChessMove
- authUser.UseStream = data.UseStream
- authUser.ConfirmExternalLinks = data.ConfirmExternalLinks
- authUser.ChessSoundsEnabled = data.ChessSoundsEnabled
- authUser.Theme = data.Theme
- //authUser.NotifyNewMessageSound = data.NotifyNewMessageSound
- //authUser.NotifyTaggedSound = data.NotifyTaggedSound
- //authUser.NotifyPmmedSound = data.NotifyPmmedSound
-
- authUser.CodeBlockHeight = utils.Clamp(data.CodeBlockHeight, 15, 300)
- if authUser.CanSeeHB() {
- authUser.HellbanOpacity = utils.Clamp(int64(data.HellbanOpacity*100), 0, 100)
- }
- if authUser.IsModerator() {
- authUser.DisplayHellbanned = data.DisplayHellbanned
- authUser.DisplayModerators = data.DisplayModerators
- authUser.DisplayKickButton = data.DisplayKickButton
- authUser.DisplayHellbanButton = data.DisplayHellbanButton
- }
-
- if err := authUser.Save(db); err != nil {
- logrus.Error(err)
- data.Error = err.Error()
- return c.Render(http.StatusOK, "settings.chat", data)
- }
-
- return c.Render(http.StatusOK, "flash", FlashResponse{Message: "Settings changed successfully", Redirect: c.Request().Referer()})
-}
-
-func changePasswordForm(c echo.Context, data settingsPasswordData) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- oldPassword := c.Request().PostFormValue("oldPassword")
- newPassword := c.Request().PostFormValue("newPassword")
- rePassword := c.Request().PostFormValue("rePassword")
- data.OldPassword = oldPassword
- data.NewPassword = newPassword
- data.RePassword = rePassword
-
- if len(oldPassword) == 0 {
- data.ErrorOldPassword = "This field is required"
- return c.Render(http.StatusOK, "settings.password", data)
- }
-
- if len(newPassword) > 0 || len(rePassword) > 0 {
- hashedPassword, err := database.NewPasswordValidator(db, newPassword).CompareWith(rePassword).Hash()
- if err != nil {
- data.ErrorNewPassword = err.Error()
- return c.Render(http.StatusOK, "settings.password", data)
- }
-
- if !authUser.CheckPassword(db, oldPassword) {
- data.ErrorOldPassword = "Invalid password"
- return c.Render(http.StatusOK, "settings.password", data)
- }
-
- if err := authUser.ChangePassword(db, hashedPassword); err != nil {
- logrus.Error(err)
- }
- c.SetCookie(hutils.DeleteCookie(hutils.AuthCookieName))
- db.CreateSecurityLog(authUser.ID, database.ChangePasswordSecurityLog)
- return c.Render(http.StatusFound, "flash", FlashResponse{Message: "Password changed successfully", Redirect: "/login"})
- }
-
- return c.Redirect(http.StatusFound, c.Request().Referer())
-}
-
-func changeDuressPasswordForm(c echo.Context, data settingsPasswordData) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- oldDuressPassword := c.Request().PostFormValue("oldDuressPassword")
- newDuressPassword := c.Request().PostFormValue("newDuressPassword")
- reDuressPassword := c.Request().PostFormValue("reDuressPassword")
- data.OldDuressPassword = oldDuressPassword
- data.NewDuressPassword = newDuressPassword
- data.ReDuressPassword = reDuressPassword
-
- if len(oldDuressPassword) == 0 {
- data.ErrorOldDuressPassword = "This field is required"
- return c.Render(http.StatusOK, "settings.password", data)
- }
-
- if len(newDuressPassword) > 0 || len(reDuressPassword) > 0 {
- hashedPassword, err := database.NewPasswordValidator(db, newDuressPassword).CompareWith(reDuressPassword).Hash()
- if err != nil {
- data.ErrorNewDuressPassword = err.Error()
- return c.Render(http.StatusOK, "settings.password", data)
- }
-
- if !authUser.CheckPassword(db, oldDuressPassword) {
- data.ErrorOldDuressPassword = "Invalid password"
- return c.Render(http.StatusOK, "settings.password", data)
- }
-
- if err := authUser.ChangeDuressPassword(db, hashedPassword); err != nil {
- logrus.Error(err)
- }
- c.SetCookie(hutils.DeleteCookie(hutils.AuthCookieName))
- db.CreateSecurityLog(authUser.ID, database.ChangeDuressPasswordSecurityLog)
- return c.Render(http.StatusFound, "flash", FlashResponse{Message: "Password changed successfully", Redirect: "/login"})
- }
-
- return c.Redirect(http.StatusFound, c.Request().Referer())
-}
-
func ChatDeleteHandler(c echo.Context) error {
authUser := c.Get("authUser").(*database.User)
db := c.Get("database").(*database.DkfDB)
@@ -3506,28 +2754,6 @@ type ValueTokenCache struct {
var ageTokenCache = cache.NewWithKey[database.UserID, ValueTokenCache](2*time.Minute, time.Hour)
var pgpTokenCache = cache.NewWithKey[database.UserID, ValueTokenCache](2*time.Minute, time.Hour)
-func SettingsPGPHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- var data settingsPGPData
- data.ActiveTab = "pgp"
-
- if authUser.GPGPublicKey != "" {
- if e := utils.GetEntityFromPKey(authUser.GPGPublicKey); e != nil {
- data.PGPPublicKeyID = e.PrimaryKey.KeyIdString()
- }
- }
-
- return c.Render(http.StatusOK, "settings.pgp", data)
-}
-
-func SettingsAgeHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- var data settingsAgeData
- data.ActiveTab = "age"
- data.AgePublicKey = authUser.AgePublicKey
- return c.Render(http.StatusOK, "settings.age", data)
-}
-
func generateTokenMsg(token string) string {
msg := "The required code is below the line.\n"
msg += "----------------------------------------------------------------------------------\n"
@@ -3574,104 +2800,6 @@ func generatePgpToBeSignedTokenMessage(userID database.UserID, pkey string) stri
return msg
}
-func AddPGPHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data addPGPData
- data.PGPPublicKey = authUser.GPGPublicKey
- if c.Request().Method == http.MethodPost {
- formName := c.Request().PostFormValue("formName")
- if formName == "pgp_step1" {
-
- data.PGPPublicKey = c.Request().PostFormValue("pgp_public_key")
- data.GpgMode = utils.DoParseBool(c.Request().PostFormValue("gpg_mode"))
-
- if data.GpgMode {
- data.ToBeSignedMessage = generatePgpToBeSignedTokenMessage(authUser.ID, data.PGPPublicKey)
- return c.Render(http.StatusOK, "pgp_code", data)
-
- } else {
- msg, err := generatePgpEncryptedTokenMessage(authUser.ID, data.PGPPublicKey)
- if err != nil {
- data.ErrorPGPPublicKey = err.Error()
- return c.Render(http.StatusOK, "pgp", data)
- }
- data.EncryptedMessage = msg
- return c.Render(http.StatusOK, "pgp_code", data)
- }
-
- } else if formName == "pgp_step2" {
- token, found := pgpTokenCache.Get(authUser.ID)
- if !found {
- return c.Redirect(http.StatusFound, "/settings/pgp")
- }
-
- data.PGPPublicKey = c.Request().PostFormValue("pgp_public_key")
- data.GpgMode = utils.DoParseBool(c.Request().PostFormValue("gpg_mode"))
- if data.GpgMode {
- data.ToBeSignedMessage = c.Request().PostFormValue("to_be_signed_message")
- data.SignedMessage = c.Request().PostFormValue("signed_message")
- if !utils.PgpCheckSignMessage(token.PKey, token.Value, data.SignedMessage) {
- data.ErrorSignedMessage = "invalid signature"
- return c.Render(http.StatusOK, "pgp_code", data)
- }
-
- } else {
- data.EncryptedMessage = c.Request().PostFormValue("encrypted_message")
- data.Code = c.Request().PostFormValue("pgp_code")
- if data.Code != token.Value {
- data.ErrorCode = "invalid code"
- return c.Render(http.StatusOK, "pgp_code", data)
- }
- }
-
- pgpTokenCache.Delete(authUser.ID)
- authUser.GPGPublicKey = token.PKey
- authUser.DoSave(db)
- return c.Redirect(http.StatusFound, "/settings/pgp")
- }
- }
- return c.Render(http.StatusOK, "pgp", data)
-}
-
-func AddAgeHandler(c echo.Context) error {
- authUser := c.Get("authUser").(*database.User)
- db := c.Get("database").(*database.DkfDB)
- var data addAgeData
- data.AgePublicKey = authUser.AgePublicKey
- if c.Request().Method == http.MethodPost {
- formName := c.Request().PostFormValue("formName")
- if formName == "age_step1" {
- data.AgePublicKey = c.Request().PostFormValue("age_public_key")
- msg, err := generateAgeEncryptedTokenMessage(authUser.ID, data.AgePublicKey)
- if err != nil {
- data.ErrorAgePublicKey = err.Error()
- return c.Render(http.StatusOK, "age", data)
- }
- data.EncryptedMessage = msg
- return c.Render(http.StatusOK, "age_code", data)
-
- } else if formName == "age_step2" {
- token, found := ageTokenCache.Get(authUser.ID)
- if !found {
- return c.Redirect(http.StatusFound, "/settings/age")
- }
- data.AgePublicKey = token.PKey
- data.EncryptedMessage = c.Request().PostFormValue("encrypted_message")
- data.Code = c.Request().PostFormValue("age_code")
- if data.Code != token.Value {
- data.ErrorCode = "invalid code"
- return c.Render(http.StatusOK, "age_code", data)
- }
- ageTokenCache.Delete(authUser.ID)
- authUser.AgePublicKey = token.PKey
- authUser.DoSave(db)
- return c.Redirect(http.StatusFound, "/settings/age")
- }
- }
- return c.Render(http.StatusOK, "age", data)
-}
-
// twoFactorCache ...
var twoFactorCache = cache.NewWithKey[database.UserID, twoFactorObj](10*time.Minute, time.Hour)
diff --git a/pkg/web/handlers/settings.go b/pkg/web/handlers/settings.go
@@ -0,0 +1,895 @@
+package handlers
+
+import (
+ "bytes"
+ "dkforest/pkg/config"
+ "dkforest/pkg/database"
+ dutils "dkforest/pkg/database/utils"
+ "dkforest/pkg/global"
+ "dkforest/pkg/managers"
+ "dkforest/pkg/utils"
+ hutils "dkforest/pkg/web/handlers/utils"
+ "fmt"
+ "github.com/asaskevich/govalidator"
+ "github.com/dustin/go-humanize"
+ "github.com/labstack/echo"
+ "github.com/sirupsen/logrus"
+ "image"
+ "io/ioutil"
+ "net/http"
+ "regexp"
+ "sort"
+ "strings"
+ "time"
+)
+
+// SettingsChatHandler ...
+func SettingsChatHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ var data settingsChatData
+ data.ActiveTab = "chat"
+ data.AllFonts = utils.GetFonts()
+ data.ChatColor = authUser.ChatColor
+ data.ChatBackgroundColor = authUser.ChatBackgroundColor
+ data.ChatFont = authUser.ChatFont
+ data.ChatItalic = authUser.ChatItalic
+ data.ChatBold = authUser.ChatBold
+ data.DateFormat = authUser.DateFormat
+ data.ChatReadMarkerEnabled = authUser.ChatReadMarkerEnabled
+ data.ChatReadMarkerColor = authUser.ChatReadMarkerColor
+ data.ChatReadMarkerSize = authUser.ChatReadMarkerSize
+ data.DisplayHellbanned = authUser.DisplayHellbanned
+ data.DisplayModerators = authUser.DisplayModerators
+ data.DisplayDeleteButton = authUser.DisplayDeleteButton
+ data.DisplayKickButton = authUser.DisplayKickButton
+ data.DisplayHellbanButton = authUser.DisplayHellbanButton
+ data.HideRightColumn = authUser.HideRightColumn
+ data.ChatBarAtBottom = authUser.ChatBarAtBottom
+ data.AutocompleteCommandsEnabled = authUser.AutocompleteCommandsEnabled
+ data.SpellcheckEnabled = authUser.SpellcheckEnabled
+ data.AfkIndicatorEnabled = authUser.AfkIndicatorEnabled
+ data.HideIgnoredUsersFromList = authUser.HideIgnoredUsersFromList
+ data.HellbanOpacity = float64(authUser.HellbanOpacity) / 100
+ data.CodeBlockHeight = authUser.CodeBlockHeight
+ data.RefreshRate = authUser.RefreshRate
+ data.NotifyNewMessage = authUser.NotifyNewMessage
+ data.NotifyTagged = authUser.NotifyTagged
+ data.NotifyPmmed = authUser.NotifyPmmed
+ data.NotifyNewMessageSound = authUser.NotifyNewMessageSound
+ data.NotifyTaggedSound = authUser.NotifyTaggedSound
+ data.NotifyPmmedSound = authUser.NotifyPmmedSound
+ data.Theme = authUser.Theme
+ data.NotifyChessGames = authUser.NotifyChessGames
+ data.NotifyChessMove = authUser.NotifyChessMove
+ data.UseStream = authUser.UseStream
+ data.ConfirmExternalLinks = authUser.ConfirmExternalLinks
+ data.ChessSoundsEnabled = authUser.ChessSoundsEnabled
+
+ if c.Request().Method == http.MethodGet {
+ return c.Render(http.StatusOK, "settings.chat", data)
+ }
+
+ // POST
+ formName := c.FormValue("formName")
+ if formName == "changeSettings" {
+ return changeSettingsForm(c, data)
+ }
+ return c.Render(http.StatusOK, "settings.chat", data)
+}
+
+func changeSettingsForm(c echo.Context, data settingsChatData) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+
+ data.RefreshRate = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("refresh_rate")), 5, 60)
+ data.ChatColor = c.Request().PostFormValue("chat_color")
+ data.ChatBackgroundColor = c.Request().PostFormValue("chat_background_color")
+ data.ChatFont = utils.DoParseInt64(c.Request().PostFormValue("chat_font"))
+ data.ChatBold = utils.DoParseBool(c.Request().PostFormValue("chat_bold"))
+ data.DateFormat = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("date_format")), 0, 4)
+ data.ChatReadMarkerEnabled = utils.DoParseBool(c.Request().PostFormValue("chat_read_marker_enabled"))
+ data.ChatReadMarkerColor = c.Request().PostFormValue("chat_read_marker_color")
+ data.ChatReadMarkerSize = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("chat_read_marker_size")), 1, 5)
+ data.DisplayHellbanned = utils.DoParseBool(c.Request().PostFormValue("display_hellbanned"))
+ data.DisplayModerators = utils.DoParseBool(c.Request().PostFormValue("display_moderators"))
+ data.DisplayKickButton = utils.DoParseBool(c.Request().PostFormValue("display_kick_button"))
+ data.DisplayDeleteButton = utils.DoParseBool(c.Request().PostFormValue("display_delete_button"))
+ data.DisplayHellbanButton = utils.DoParseBool(c.Request().PostFormValue("display_hellban_button"))
+ data.HideIgnoredUsersFromList = utils.DoParseBool(c.Request().PostFormValue("hide_ignored_users_from_list"))
+ data.HideRightColumn = utils.DoParseBool(c.Request().PostFormValue("hide_right_column"))
+ data.ChatBarAtBottom = utils.DoParseBool(c.Request().PostFormValue("chat_bar_at_bottom"))
+ data.AutocompleteCommandsEnabled = utils.DoParseBool(c.Request().PostFormValue("autocomplete_commands_enabled"))
+ data.SpellcheckEnabled = utils.DoParseBool(c.Request().PostFormValue("spellcheck_enabled"))
+ data.AfkIndicatorEnabled = utils.DoParseBool(c.Request().PostFormValue("afk_indicator_enabled"))
+ data.ChatItalic = utils.DoParseBool(c.Request().PostFormValue("chat_italic"))
+ data.NotifyNewMessage = utils.DoParseBool(c.Request().PostFormValue("notify_new_message"))
+ data.NotifyTagged = utils.DoParseBool(c.Request().PostFormValue("notify_tagged"))
+ data.NotifyPmmed = utils.DoParseBool(c.Request().PostFormValue("notify_pmmed"))
+ data.Theme = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("theme")), 0, 2)
+ data.NotifyChessGames = utils.DoParseBool(c.Request().PostFormValue("notify_chess_games"))
+ data.NotifyChessMove = utils.DoParseBool(c.Request().PostFormValue("notify_chess_move"))
+ data.UseStream = utils.DoParseBool(c.Request().PostFormValue("use_stream"))
+ data.ConfirmExternalLinks = utils.DoParseBool(c.Request().PostFormValue("confirm_external_links"))
+ data.ChessSoundsEnabled = utils.DoParseBool(c.Request().PostFormValue("chess_sounds_enabled"))
+ data.HellbanOpacity = utils.DoParseF64(c.Request().PostFormValue("hellban_opacity"))
+ data.CodeBlockHeight = utils.DoParseInt64(c.Request().PostFormValue("code_block_height"))
+ //data.NotifyNewMessageSound = utils.DoParseInt64(c.Request().PostFormValue("notify_new_message_sound"))
+ //data.NotifyTaggedSound = utils.DoParseInt64(c.Request().PostFormValue("notify_tagged_sound"))
+ //data.NotifyPmmedSound = utils.DoParseInt64(c.Request().PostFormValue("notify_pmmed_sound"))
+ colorRgx := regexp.MustCompile(`^#[0-9a-fA-F]{6}$`)
+ if !colorRgx.MatchString(data.ChatColor) {
+ data.Error = "Invalid color format (text)"
+ return c.Render(http.StatusOK, "settings.chat", data)
+ }
+ if !colorRgx.MatchString(data.ChatBackgroundColor) {
+ data.Error = "Invalid color format (background)"
+ return c.Render(http.StatusOK, "settings.chat", data)
+ }
+ if !colorRgx.MatchString(data.ChatReadMarkerColor) {
+ data.Error = "Invalid marker color format"
+ return c.Render(http.StatusOK, "settings.chat", data)
+ }
+ authUser.RefreshRate = data.RefreshRate
+ if authUser.CanChangeColor {
+ authUser.ChatColor = data.ChatColor
+ }
+ authUser.ChatBackgroundColor = data.ChatBackgroundColor
+ authUser.ChatFont = data.ChatFont
+ authUser.ChatItalic = data.ChatItalic
+ authUser.ChatBold = data.ChatBold
+ authUser.DateFormat = data.DateFormat
+ authUser.ChatReadMarkerEnabled = data.ChatReadMarkerEnabled
+ authUser.ChatReadMarkerColor = data.ChatReadMarkerColor
+ authUser.ChatReadMarkerSize = data.ChatReadMarkerSize
+ authUser.DisplayDeleteButton = data.DisplayDeleteButton
+ authUser.HideIgnoredUsersFromList = data.HideIgnoredUsersFromList
+ authUser.HideRightColumn = data.HideRightColumn
+ authUser.ChatBarAtBottom = data.ChatBarAtBottom
+ authUser.AutocompleteCommandsEnabled = data.AutocompleteCommandsEnabled
+ authUser.SpellcheckEnabled = data.SpellcheckEnabled
+ authUser.AfkIndicatorEnabled = data.AfkIndicatorEnabled
+ authUser.NotifyNewMessage = data.NotifyNewMessage
+ authUser.NotifyTagged = data.NotifyTagged
+ authUser.NotifyPmmed = data.NotifyPmmed
+ authUser.NotifyChessGames = data.NotifyChessGames
+ authUser.NotifyChessMove = data.NotifyChessMove
+ authUser.UseStream = data.UseStream
+ authUser.ConfirmExternalLinks = data.ConfirmExternalLinks
+ authUser.ChessSoundsEnabled = data.ChessSoundsEnabled
+ authUser.Theme = data.Theme
+ //authUser.NotifyNewMessageSound = data.NotifyNewMessageSound
+ //authUser.NotifyTaggedSound = data.NotifyTaggedSound
+ //authUser.NotifyPmmedSound = data.NotifyPmmedSound
+
+ authUser.CodeBlockHeight = utils.Clamp(data.CodeBlockHeight, 15, 300)
+ if authUser.CanSeeHB() {
+ authUser.HellbanOpacity = utils.Clamp(int64(data.HellbanOpacity*100), 0, 100)
+ }
+ if authUser.IsModerator() {
+ authUser.DisplayHellbanned = data.DisplayHellbanned
+ authUser.DisplayModerators = data.DisplayModerators
+ authUser.DisplayKickButton = data.DisplayKickButton
+ authUser.DisplayHellbanButton = data.DisplayHellbanButton
+ }
+
+ if err := authUser.Save(db); err != nil {
+ logrus.Error(err)
+ data.Error = err.Error()
+ return c.Render(http.StatusOK, "settings.chat", data)
+ }
+
+ return c.Render(http.StatusOK, "flash", FlashResponse{Message: "Settings changed successfully", Redirect: c.Request().Referer()})
+}
+
+func SettingsSecurityHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsSecurityData
+ data.ActiveTab = "security"
+ data.Logs, _ = db.GetSecurityLogs(authUser.ID)
+ return c.Render(http.StatusOK, "settings.security", data)
+}
+
+// SettingsAccountHandler ...
+func SettingsAccountHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ var data settingsAccountData
+ data.AccountTooYoungErrorString = hutils.AccountTooYoungErr.Error()
+ data.ActiveTab = "account"
+ data.Username = authUser.Username
+ data.Email = authUser.Email
+ data.LastSeenPublic = authUser.LastSeenPublic
+ data.TerminateAllSessionsOnLogout = authUser.TerminateAllSessionsOnLogout
+ data.Website = authUser.Website
+
+ if c.Request().Method == http.MethodGet {
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ // POST
+ formName := c.FormValue("formName")
+ switch formName {
+ case "changeUsername":
+ return changeUsernameForm(c, data)
+ case "editProfile":
+ return editProfileForm(c, data)
+ case "changeAvatar":
+ return changeAvatarForm(c, data)
+ default:
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+}
+
+func changeUsernameForm(c echo.Context, data settingsAccountData) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ if !authUser.CanChangeUsername {
+ data.ErrorUsername = "Not allowed to change your username"
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ username := database.Username(c.Request().PostFormValue("username"))
+ data.Username = username
+
+ if username == authUser.Username {
+ data.ErrorUsername = "username did not change"
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ if err := db.CanRenameTo(authUser.Username, username); err != nil {
+ data.ErrorUsername = err.Error()
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ managers.ActiveUsers.RemoveUser(authUser.ID)
+ authUser.Username = username
+ if err := db.DB().Save(authUser).Error; err != nil {
+ logrus.Error(err)
+ data.ErrorUsername = err.Error()
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ db.CreateSecurityLog(authUser.ID, database.UsernameChangedSecurityLog)
+ return c.Render(http.StatusOK, "flash", FlashResponse{Message: "Username changed successfully", Redirect: c.Request().Referer()})
+}
+
+func editProfileForm(c echo.Context, data settingsAccountData) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+
+ email := c.Request().PostFormValue("email")
+ website := c.Request().PostFormValue("website")
+ lastSeenPublic := utils.DoParseBool(c.Request().PostFormValue("last_seen_public"))
+ terminateAllSessionsOnLogout := utils.DoParseBool(c.Request().PostFormValue("terminate_all_sessions_on_logout"))
+ data.Email = email
+ data.Website = website
+ data.LastSeenPublic = lastSeenPublic
+ data.TerminateAllSessionsOnLogout = terminateAllSessionsOnLogout
+
+ if data.Email != "" && !govalidator.IsEmail(data.Email) {
+ data.ErrorEmail = "invalid email"
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ if data.Website != "" && !govalidator.IsURL(data.Website) {
+ data.ErrorWebsite = "invalid website"
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ authUser.Website = data.Website
+ authUser.Email = data.Email
+ authUser.LastSeenPublic = data.LastSeenPublic
+ authUser.TerminateAllSessionsOnLogout = data.TerminateAllSessionsOnLogout
+ authUser.DoSave(db)
+
+ return c.Render(http.StatusOK, "flash", FlashResponse{Message: "Profile changed successfully", Redirect: c.Request().Referer()})
+}
+
+func changeAvatarForm(c echo.Context, data settingsAccountData) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ if !authUser.CanUpload() {
+ data.ErrorAvatar = hutils.AccountTooYoungErr.Error()
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+ if err := c.Request().ParseMultipartForm(config.MaxAvatarFormSize); err != nil {
+ data.ErrorAvatar = err.Error()
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+ file, handler, err := c.Request().FormFile("avatar")
+ if err != nil {
+ data.ErrorAvatar = "Failed to get avatar: " + err.Error()
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+ defer file.Close()
+ if handler.Size > config.MaxAvatarSize {
+ data.ErrorAvatar = fmt.Sprintf("The maximum file size for avatars is %s", humanize.Bytes(config.MaxAvatarSize))
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+ fileBytes, err := ioutil.ReadAll(file)
+ if err != nil {
+ data.ErrorAvatar = err.Error()
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ filetype := http.DetectContentType(fileBytes)
+ if !utils.InArr(filetype, []string{"image/jpeg", "image/png", "image/gif", "image/bmp", "image/webp"}) {
+ data.ErrorAvatar = "The provided file format is not allowed. Please upload a JPEG, PNG, WEBP, BMP or GIF image"
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ // Validate image type and determine extension
+ if handler.Header.Get("Content-Type") != filetype {
+ data.ErrorAvatar = "Content-Type does not match mimetype"
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ im, _, err := image.DecodeConfig(bytes.NewReader(fileBytes))
+ if err != nil {
+ data.ErrorAvatar = err.Error()
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+ if im.Width > 120 || im.Height > 120 {
+ data.ErrorAvatar = "The maximum dimensions for avatars are: 120x120 pixels"
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ if filetype == "image/jpeg" {
+ fileBytes, err = utils.ReencodeJpg(fileBytes)
+ } else if filetype == "image/png" {
+ fileBytes, err = utils.ReencodePng(fileBytes)
+ }
+ if err != nil {
+ data.Error = err.Error()
+ return c.Render(http.StatusOK, "settings.account", data)
+ }
+
+ authUser.SetAvatar(fileBytes)
+ authUser.DoSave(db)
+ return c.Render(http.StatusOK, "flash", FlashResponse{Message: "Avatar changed successfully", Redirect: c.Request().Referer()})
+}
+
+func SettingsChatPMHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsChatPMData
+ data.ActiveTab = "chat"
+ data.PmMode = authUser.PmMode
+ data.BlockNewUsersPm = authUser.BlockNewUsersPm
+ data.WhitelistedUsers, _ = db.GetPmWhitelistedUsers(authUser.ID)
+ data.BlacklistedUsers, _ = db.GetPmBlacklistedUsers(authUser.ID)
+
+ if c.Request().Method == http.MethodGet {
+ return c.Render(http.StatusOK, "settings.chat-pm", data)
+ }
+
+ // POST
+ formName := c.Request().PostFormValue("formName")
+
+ if formName == "addWhitelist" {
+ data.AddWhitelist = database.Username(strings.TrimSpace(c.Request().PostFormValue("username")))
+ user, err := db.GetUserByUsername(data.AddWhitelist)
+ if err != nil {
+ data.Error = "username not found"
+ return c.Render(http.StatusOK, "settings.chat-pm", data)
+ }
+ db.AddWhitelistedUser(authUser.ID, user.ID)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+
+ } else if formName == "rmWhitelist" {
+ userID := dutils.DoParseUserID(c.Request().PostFormValue("userID"))
+ db.RmWhitelistedUser(authUser.ID, userID)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+
+ } else if formName == "addBlacklist" {
+ data.AddBlacklist = database.Username(strings.TrimSpace(c.Request().PostFormValue("username")))
+ user, err := db.GetUserByUsername(data.AddBlacklist)
+ if err != nil {
+ data.Error = "username not found"
+ return c.Render(http.StatusOK, "settings.chat-pm", data)
+ }
+ db.AddBlacklistedUser(authUser.ID, user.ID)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+
+ } else if formName == "rmBlacklist" {
+ userID := dutils.DoParseUserID(c.Request().PostFormValue("userID"))
+ db.RmBlacklistedUser(authUser.ID, userID)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+
+ data.PmMode = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("pm_mode")), 0, 1)
+ authUser.BlockNewUsersPm = utils.DoParseBool(c.Request().PostFormValue("block_new_users_pm"))
+ authUser.PmMode = data.PmMode
+ authUser.DoSave(db)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+}
+
+func SettingsChatIgnoreHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsChatIgnoreData
+ data.ActiveTab = "chat"
+ data.PmMode = authUser.PmMode
+ data.IgnoredUsers, _ = db.GetIgnoredUsers(authUser.ID)
+
+ if c.Request().Method == http.MethodGet {
+ return c.Render(http.StatusOK, "settings.chat-ignore", data)
+ }
+
+ // POST
+ formName := c.Request().PostFormValue("formName")
+
+ if formName == "addIgnored" {
+ data.AddIgnored = database.Username(strings.TrimSpace(c.Request().PostFormValue("username")))
+ user, err := db.GetUserByUsername(data.AddIgnored)
+ if err != nil {
+ data.Error = "username not found"
+ return c.Render(http.StatusOK, "settings.chat-ignore", data)
+ }
+ db.IgnoreUser(authUser.ID, user.ID)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+
+ } else if formName == "rmIgnored" {
+ userID := dutils.DoParseUserID(c.Request().PostFormValue("userID"))
+ db.UnIgnoreUser(authUser.ID, userID)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+
+ data.PmMode = utils.Clamp(utils.DoParseInt64(c.Request().PostFormValue("pm_mode")), 0, 1)
+ authUser.PmMode = data.PmMode
+ authUser.DoSave(db)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+}
+
+func SettingsChatSnippetsHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsChatSnippetsData
+ data.ActiveTab = "snippets"
+ data.Snippets, _ = db.GetUserSnippets(authUser.ID)
+
+ if c.Request().Method == http.MethodGet {
+ return c.Render(http.StatusOK, "settings.chat-snippets", data)
+ }
+
+ // POST
+ formName := c.Request().PostFormValue("formName")
+
+ if formName == "addSnippet" {
+ data.Name = strings.TrimSpace(c.Request().PostFormValue("name"))
+ data.Text = strings.TrimSpace(c.Request().PostFormValue("text"))
+ if len(data.Snippets) >= 20 {
+ data.Error = "snippets limit reached"
+ return c.Render(http.StatusOK, "settings.chat-snippets", data)
+ }
+ if !govalidator.Matches(data.Name, `^\w{1,20}$`) {
+ data.Error = "name must match : ^\\w{1,20}$"
+ return c.Render(http.StatusOK, "settings.chat-snippets", data)
+ }
+ if !govalidator.StringLength(data.Name, "1", "20") {
+ data.Error = "name must be 1-20 characters"
+ return c.Render(http.StatusOK, "settings.chat-snippets", data)
+ }
+ if !govalidator.StringLength(data.Text, "1", "1000") {
+ data.Error = "text must be 1-1000 characters"
+ return c.Render(http.StatusOK, "settings.chat-snippets", data)
+ }
+ if _, err := db.CreateSnippet(authUser.ID, data.Name, data.Text); err != nil {
+ data.Error = err.Error()
+ return c.Render(http.StatusOK, "settings.chat-snippets", data)
+ }
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+
+ } else if formName == "rmSnippet" {
+ snippetName := c.Request().PostFormValue("snippetName")
+ db.DeleteSnippet(authUser.ID, snippetName)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+}
+
+func SettingsPublicNotesHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ if !authUser.CanUseForumFn() {
+ return c.Render(http.StatusOK, "flash", FlashResponse{Message: hutils.AccountTooYoungErr.Error(), Redirect: c.Request().Referer(), Type: "alert-danger"})
+ }
+ var data settingsPublicNotesData
+ data.ActiveTab = "notes"
+ data.Notes, _ = db.GetUserPublicNotes(authUser.ID)
+
+ if c.Request().Method == http.MethodPost {
+ notes := c.Request().PostFormValue("public_notes")
+ if err := db.SetUserPublicNotes(authUser.ID, notes); err != nil {
+ data.Error = err.Error()
+ return c.Render(http.StatusOK, "settings.public-notes", data)
+ }
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+
+ return c.Render(http.StatusOK, "settings.public-notes", data)
+}
+
+func SettingsPrivateNotesHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ if !authUser.CanUseForumFn() {
+ return c.Render(http.StatusOK, "flash", FlashResponse{Message: hutils.AccountTooYoungErr.Error(), Redirect: c.Request().Referer(), Type: "alert-danger"})
+ }
+ var data settingsPrivateNotesData
+ data.ActiveTab = "notes"
+ if !authUser.IsUnderDuress {
+ data.Notes, _ = db.GetUserPrivateNotes(authUser.ID)
+ }
+
+ if c.Request().Method == http.MethodPost {
+ notes := c.Request().PostFormValue("private_notes")
+ if err := db.SetUserPrivateNotes(authUser.ID, notes); err != nil {
+ data.Error = err.Error()
+ return c.Render(http.StatusOK, "settings.private-notes", data)
+ }
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+
+ return c.Render(http.StatusOK, "settings.private-notes", data)
+}
+
+func SettingsSessionsHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsSessionsData
+ data.ActiveTab = "sessions"
+ sessions := db.GetActiveUserSessions(authUser.ID)
+ authCookie, _ := c.Cookie(hutils.AuthCookieName)
+ for _, session := range sessions {
+ s := WrapperSession{Session: session}
+ if authCookie.Value == s.Token {
+ s.CurrentSession = true
+ }
+ data.Sessions = append(data.Sessions, s)
+ }
+
+ if c.Request().Method == http.MethodPost {
+ formName := c.Request().PostFormValue("formName")
+ if formName == "revoke_all_other_sessions" {
+ _ = db.DeleteUserOtherSessions(authUser.ID, authCookie.Value)
+ } else {
+ sessionToken := c.Request().PostFormValue("sessionToken")
+ _ = db.DeleteUserSessionByToken(authUser.ID, sessionToken)
+ }
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+
+ return c.Render(http.StatusOK, "settings.sessions", data)
+}
+
+func SettingsAPIHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsAPIData
+ data.ActiveTab = "api"
+ data.APIKey = authUser.ApiKey
+ if c.Request().Method == http.MethodPost {
+ formName := c.Request().PostFormValue("formName")
+ btnSubmit := c.Request().PostFormValue("btn_submit")
+ if btnSubmit == "Cancel" {
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+ if formName == "confirm" {
+ token := utils.GenerateToken16()
+ authUser.ApiKey = token
+ authUser.DoSave(db)
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+ data.NeedConfirm = true
+ }
+ return c.Render(http.StatusOK, "settings.api", data)
+}
+
+func SettingsPasswordHandler(c echo.Context) error {
+ var data settingsPasswordData
+ data.ActiveTab = "password"
+
+ if c.Request().Method == http.MethodGet {
+ return c.Render(http.StatusOK, "settings.password", data)
+ }
+
+ // POST
+ formName := c.FormValue("formName")
+ switch formName {
+ case "changePassword":
+ return changePasswordForm(c, data)
+ case "changeDuressPassword":
+ return changeDuressPasswordForm(c, data)
+ default:
+ return c.Render(http.StatusOK, "settings.password", data)
+ }
+}
+
+func changePasswordForm(c echo.Context, data settingsPasswordData) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ oldPassword := c.Request().PostFormValue("oldPassword")
+ newPassword := c.Request().PostFormValue("newPassword")
+ rePassword := c.Request().PostFormValue("rePassword")
+ data.OldPassword = oldPassword
+ data.NewPassword = newPassword
+ data.RePassword = rePassword
+
+ if len(oldPassword) == 0 {
+ data.ErrorOldPassword = "This field is required"
+ return c.Render(http.StatusOK, "settings.password", data)
+ }
+
+ if len(newPassword) > 0 || len(rePassword) > 0 {
+ hashedPassword, err := database.NewPasswordValidator(db, newPassword).CompareWith(rePassword).Hash()
+ if err != nil {
+ data.ErrorNewPassword = err.Error()
+ return c.Render(http.StatusOK, "settings.password", data)
+ }
+
+ if !authUser.CheckPassword(db, oldPassword) {
+ data.ErrorOldPassword = "Invalid password"
+ return c.Render(http.StatusOK, "settings.password", data)
+ }
+
+ if err := authUser.ChangePassword(db, hashedPassword); err != nil {
+ logrus.Error(err)
+ }
+ c.SetCookie(hutils.DeleteCookie(hutils.AuthCookieName))
+ db.CreateSecurityLog(authUser.ID, database.ChangePasswordSecurityLog)
+ return c.Render(http.StatusFound, "flash", FlashResponse{Message: "Password changed successfully", Redirect: "/login"})
+ }
+
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+}
+
+func changeDuressPasswordForm(c echo.Context, data settingsPasswordData) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ oldDuressPassword := c.Request().PostFormValue("oldDuressPassword")
+ newDuressPassword := c.Request().PostFormValue("newDuressPassword")
+ reDuressPassword := c.Request().PostFormValue("reDuressPassword")
+ data.OldDuressPassword = oldDuressPassword
+ data.NewDuressPassword = newDuressPassword
+ data.ReDuressPassword = reDuressPassword
+
+ if len(oldDuressPassword) == 0 {
+ data.ErrorOldDuressPassword = "This field is required"
+ return c.Render(http.StatusOK, "settings.password", data)
+ }
+
+ if len(newDuressPassword) > 0 || len(reDuressPassword) > 0 {
+ hashedPassword, err := database.NewPasswordValidator(db, newDuressPassword).CompareWith(reDuressPassword).Hash()
+ if err != nil {
+ data.ErrorNewDuressPassword = err.Error()
+ return c.Render(http.StatusOK, "settings.password", data)
+ }
+
+ if !authUser.CheckPassword(db, oldDuressPassword) {
+ data.ErrorOldDuressPassword = "Invalid password"
+ return c.Render(http.StatusOK, "settings.password", data)
+ }
+
+ if err := authUser.ChangeDuressPassword(db, hashedPassword); err != nil {
+ logrus.Error(err)
+ }
+ c.SetCookie(hutils.DeleteCookie(hutils.AuthCookieName))
+ db.CreateSecurityLog(authUser.ID, database.ChangeDuressPasswordSecurityLog)
+ return c.Render(http.StatusFound, "flash", FlashResponse{Message: "Password changed successfully", Redirect: "/login"})
+ }
+
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+}
+
+func SettingsUploadsHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsUploadsData
+ data.ActiveTab = "uploads"
+ data.Files, _ = db.GetUserUploads(authUser.ID)
+ for _, f := range data.Files {
+ data.TotalSize += f.FileSize
+ }
+
+ if c.Request().Method == http.MethodGet {
+ return c.Render(http.StatusOK, "settings.uploads", data)
+ }
+
+ // POST
+ formName := c.FormValue("formName")
+ if formName == "deleteUpload" {
+ fileName := c.Request().PostFormValue("file_name")
+ file, err := db.GetUploadByFileName(fileName)
+ if err != nil {
+ return c.Redirect(http.StatusFound, "/")
+ }
+ if authUser.ID != file.UserID {
+ return c.Redirect(http.StatusFound, "/")
+ }
+ if err := file.Delete(db); err != nil {
+ logrus.Error(err)
+ }
+ return c.Redirect(http.StatusFound, c.Request().Referer())
+ }
+ return c.Render(http.StatusOK, "settings.uploads", data)
+}
+
+func SettingsInboxHandler(c echo.Context) error {
+ authCookie, _ := c.Cookie(hutils.AuthCookieName)
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsInboxData
+ data.ActiveTab = "inbox"
+ // Do not fetch inboxes & notifications if logged in under duress
+ if !authUser.IsUnderDuress {
+ global.DeleteUserNotificationCount(authUser.ID, authCookie.Value)
+ data.ChatMessages, _ = db.GetUserChatInboxMessages(authUser.ID)
+ data.Notifications, _ = db.GetUserNotifications(authUser.ID)
+ data.SessionNotifications, _ = db.GetUserSessionNotifications(authCookie.Value)
+ }
+ for _, m := range data.ChatMessages {
+ data.Notifs = append(data.Notifs, InboxTmp{IsNotif: false, ChatInboxMessage: m})
+ }
+ for _, m := range data.Notifications {
+ data.Notifs = append(data.Notifs, InboxTmp{IsNotif: true, Notification: m})
+ }
+ for _, m := range data.SessionNotifications {
+ data.Notifs = append(data.Notifs, InboxTmp{IsNotif: true, SessionNotification: m})
+ }
+ sort.Slice(data.Notifs, func(i, j int) bool {
+ a := data.Notifs[i]
+ b := data.Notifs[j]
+ var tsa time.Time
+ var tsb time.Time
+ if a.Notification.ID != 0 {
+ tsa = a.Notification.CreatedAt
+ } else if a.SessionNotification.ID != 0 {
+ tsa = a.SessionNotification.CreatedAt
+ } else {
+ tsa = a.ChatInboxMessage.CreatedAt
+ }
+ if b.Notification.ID != 0 {
+ tsb = b.Notification.CreatedAt
+ } else if b.SessionNotification.ID != 0 {
+ tsb = b.SessionNotification.CreatedAt
+ } else {
+ tsb = b.ChatInboxMessage.CreatedAt
+ }
+ return tsa.After(tsb)
+ })
+ return c.Render(http.StatusOK, "settings.inbox", data)
+}
+
+func SettingsInboxSentHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data settingsInboxSentData
+ data.ActiveTab = "inbox"
+ // Do not fetch inboxes & notifications if logged in under duress
+ if !authUser.IsUnderDuress {
+ data.ChatInboxSent, _ = db.GetUserChatInboxMessagesSent(authUser.ID)
+ }
+ return c.Render(http.StatusOK, "settings.inbox-sent", data)
+}
+
+func AddPGPHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data addPGPData
+ data.PGPPublicKey = authUser.GPGPublicKey
+ if c.Request().Method == http.MethodPost {
+ formName := c.Request().PostFormValue("formName")
+ if formName == "pgp_step1" {
+
+ data.PGPPublicKey = c.Request().PostFormValue("pgp_public_key")
+ data.GpgMode = utils.DoParseBool(c.Request().PostFormValue("gpg_mode"))
+
+ if data.GpgMode {
+ data.ToBeSignedMessage = generatePgpToBeSignedTokenMessage(authUser.ID, data.PGPPublicKey)
+ return c.Render(http.StatusOK, "pgp_code", data)
+
+ } else {
+ msg, err := generatePgpEncryptedTokenMessage(authUser.ID, data.PGPPublicKey)
+ if err != nil {
+ data.ErrorPGPPublicKey = err.Error()
+ return c.Render(http.StatusOK, "pgp", data)
+ }
+ data.EncryptedMessage = msg
+ return c.Render(http.StatusOK, "pgp_code", data)
+ }
+
+ } else if formName == "pgp_step2" {
+ token, found := pgpTokenCache.Get(authUser.ID)
+ if !found {
+ return c.Redirect(http.StatusFound, "/settings/pgp")
+ }
+
+ data.PGPPublicKey = c.Request().PostFormValue("pgp_public_key")
+ data.GpgMode = utils.DoParseBool(c.Request().PostFormValue("gpg_mode"))
+ if data.GpgMode {
+ data.ToBeSignedMessage = c.Request().PostFormValue("to_be_signed_message")
+ data.SignedMessage = c.Request().PostFormValue("signed_message")
+ if !utils.PgpCheckSignMessage(token.PKey, token.Value, data.SignedMessage) {
+ data.ErrorSignedMessage = "invalid signature"
+ return c.Render(http.StatusOK, "pgp_code", data)
+ }
+
+ } else {
+ data.EncryptedMessage = c.Request().PostFormValue("encrypted_message")
+ data.Code = c.Request().PostFormValue("pgp_code")
+ if data.Code != token.Value {
+ data.ErrorCode = "invalid code"
+ return c.Render(http.StatusOK, "pgp_code", data)
+ }
+ }
+
+ pgpTokenCache.Delete(authUser.ID)
+ authUser.GPGPublicKey = token.PKey
+ authUser.DoSave(db)
+ return c.Redirect(http.StatusFound, "/settings/pgp")
+ }
+ }
+ return c.Render(http.StatusOK, "pgp", data)
+}
+
+func SettingsPGPHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ var data settingsPGPData
+ data.ActiveTab = "pgp"
+
+ if authUser.GPGPublicKey != "" {
+ if e := utils.GetEntityFromPKey(authUser.GPGPublicKey); e != nil {
+ data.PGPPublicKeyID = e.PrimaryKey.KeyIdString()
+ }
+ }
+
+ return c.Render(http.StatusOK, "settings.pgp", data)
+}
+
+func SettingsAgeHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ var data settingsAgeData
+ data.ActiveTab = "age"
+ data.AgePublicKey = authUser.AgePublicKey
+ return c.Render(http.StatusOK, "settings.age", data)
+}
+
+func AddAgeHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
+ db := c.Get("database").(*database.DkfDB)
+ var data addAgeData
+ data.AgePublicKey = authUser.AgePublicKey
+ if c.Request().Method == http.MethodPost {
+ formName := c.Request().PostFormValue("formName")
+ if formName == "age_step1" {
+ data.AgePublicKey = c.Request().PostFormValue("age_public_key")
+ msg, err := generateAgeEncryptedTokenMessage(authUser.ID, data.AgePublicKey)
+ if err != nil {
+ data.ErrorAgePublicKey = err.Error()
+ return c.Render(http.StatusOK, "age", data)
+ }
+ data.EncryptedMessage = msg
+ return c.Render(http.StatusOK, "age_code", data)
+
+ } else if formName == "age_step2" {
+ token, found := ageTokenCache.Get(authUser.ID)
+ if !found {
+ return c.Redirect(http.StatusFound, "/settings/age")
+ }
+ data.AgePublicKey = token.PKey
+ data.EncryptedMessage = c.Request().PostFormValue("encrypted_message")
+ data.Code = c.Request().PostFormValue("age_code")
+ if data.Code != token.Value {
+ data.ErrorCode = "invalid code"
+ return c.Render(http.StatusOK, "age_code", data)
+ }
+ ageTokenCache.Delete(authUser.ID)
+ authUser.AgePublicKey = token.PKey
+ authUser.DoSave(db)
+ return c.Redirect(http.StatusFound, "/settings/age")
+ }
+ }
+ return c.Render(http.StatusOK, "age", data)
+}