[add] settings (pw & time offset), [fix] PWA issues, [fix] misc styling issues

This commit is contained in:
2023-09-27 18:58:47 -04:00
parent 25ab36e4b5
commit 5a8bdacf4f
16 changed files with 528 additions and 99 deletions

View File

@@ -14,6 +14,7 @@ import (
"reichard.io/bbank/config"
"reichard.io/bbank/database"
"reichard.io/bbank/graph"
"reichard.io/bbank/utils"
)
type API struct {
@@ -74,11 +75,13 @@ func (api *API) registerWebAppRoutes() {
render := multitemplate.NewRenderer()
helperFuncs := template.FuncMap{
"GetSVGGraphData": graph.GetSVGGraphData,
"GetUTCOffsets": utils.GetUTCOffsets,
}
render.AddFromFilesFuncs("login", helperFuncs, "templates/login.html")
render.AddFromFilesFuncs("home", helperFuncs, "templates/base.html", "templates/home.html")
render.AddFromFilesFuncs("graphs", helperFuncs, "templates/base.html", "templates/graphs.html")
render.AddFromFilesFuncs("settings", helperFuncs, "templates/base.html", "templates/settings.html")
render.AddFromFilesFuncs("activity", helperFuncs, "templates/base.html", "templates/activity.html")
render.AddFromFilesFuncs("documents", helperFuncs, "templates/base.html", "templates/documents.html")
render.AddFromFilesFuncs("document", helperFuncs, "templates/base.html", "templates/document.html")
@@ -93,6 +96,8 @@ func (api *API) registerWebAppRoutes() {
api.Router.POST("/register", api.authFormRegister)
api.Router.GET("/", api.authWebAppMiddleware, api.createAppResourcesRoute("home"))
api.Router.GET("/settings", api.authWebAppMiddleware, api.createAppResourcesRoute("settings"))
api.Router.POST("/settings", api.authWebAppMiddleware, api.editSettings)
api.Router.GET("/activity", api.authWebAppMiddleware, api.createAppResourcesRoute("activity"))
api.Router.GET("/documents", api.authWebAppMiddleware, api.createAppResourcesRoute("documents"))
api.Router.GET("/documents/:document", api.authWebAppMiddleware, api.createAppResourcesRoute("document"))

View File

@@ -1,6 +1,7 @@
package api
import (
"crypto/md5"
"fmt"
"mime/multipart"
"net/http"
@@ -9,6 +10,7 @@ import (
"strings"
"time"
argon2 "github.com/alexedwards/argon2id"
"github.com/gabriel-vasile/mimetype"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
@@ -40,6 +42,12 @@ type requestDocumentIdentify struct {
ISBN *string `form:"isbn"`
}
type requestSettingsEdit struct {
Password *string `form:"password"`
NewPassword *string `form:"new_password"`
TimeOffset *string `form:"time_offset"`
}
func baseResourceRoute(template string, args ...map[string]any) func(c *gin.Context) {
variables := gin.H{"RouteName": template}
if len(args) > 0 {
@@ -167,6 +175,27 @@ func (api *API) createAppResourcesRoute(routeName string, args ...map[string]any
"DatabaseInfo": database_info,
"GraphData": read_graph_data,
}
} else if routeName == "settings" {
user, err := api.DB.Queries.GetUser(api.DB.Ctx, rUser.(string))
if err != nil {
log.Error("[createAppResourcesRoute] GetUser DB Error:", err)
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
devices, err := api.DB.Queries.GetDevices(api.DB.Ctx, rUser.(string))
if err != nil {
log.Error("[createAppResourcesRoute] GetDevices DB Error:", err)
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
templateVars["Data"] = gin.H{
"Settings": gin.H{
"TimeOffset": *user.TimeOffset,
},
"Devices": devices,
}
} else if routeName == "login" {
templateVars["RegistrationEnabled"] = api.Config.RegistrationEnabled
}
@@ -471,6 +500,88 @@ func (api *API) identifyDocument(c *gin.Context) {
c.HTML(http.StatusOK, "document", templateVars)
}
func (api *API) editSettings(c *gin.Context) {
rUser, _ := c.Get("AuthorizedUser")
var rUserSettings requestSettingsEdit
if err := c.ShouldBind(&rUserSettings); err != nil {
log.Error("[editSettings] Invalid Form Bind")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
// Validate Something Exists
if rUserSettings.Password == nil && rUserSettings.NewPassword == nil && rUserSettings.TimeOffset == nil {
log.Error("[editSettings] Missing Form Values")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
templateVars := gin.H{
"User": rUser,
}
newUserSettings := database.UpdateUserParams{
UserID: rUser.(string),
}
// Set New Password
if rUserSettings.Password != nil && rUserSettings.NewPassword != nil {
password := fmt.Sprintf("%x", md5.Sum([]byte(*rUserSettings.Password)))
authorized := api.authorizeCredentials(rUser.(string), password)
if authorized == true {
password := fmt.Sprintf("%x", md5.Sum([]byte(*rUserSettings.NewPassword)))
hashedPassword, err := argon2.CreateHash(password, argon2.DefaultParams)
if err != nil {
templateVars["PasswordErrorMessage"] = "Unknown Error"
} else {
templateVars["PasswordMessage"] = "Password Updated"
newUserSettings.Password = &hashedPassword
}
} else {
templateVars["PasswordErrorMessage"] = "Invalid Password"
}
}
// Set Time Offset
if rUserSettings.TimeOffset != nil {
templateVars["TimeOffsetMessage"] = "Time Offset Updated"
newUserSettings.TimeOffset = rUserSettings.TimeOffset
}
// Update User
_, err := api.DB.Queries.UpdateUser(api.DB.Ctx, newUserSettings)
if err != nil {
log.Error("[editSettings] UpdateUser DB Error:", err)
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
// Get User
user, err := api.DB.Queries.GetUser(api.DB.Ctx, rUser.(string))
if err != nil {
log.Error("[editSettings] GetUser DB Error:", err)
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
// Get Devices
devices, err := api.DB.Queries.GetDevices(api.DB.Ctx, rUser.(string))
if err != nil {
log.Error("[editSettings] GetDevices DB Error:", err)
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
templateVars["Data"] = gin.H{
"Settings": gin.H{
"TimeOffset": *user.TimeOffset,
},
"Devices": devices,
}
c.HTML(http.StatusOK, "settings", templateVars)
}
func bindQueryParams(c *gin.Context) queryParams {
var qParams queryParams
c.BindQuery(&qParams)

View File

@@ -24,7 +24,7 @@ func (api *API) authorizeCredentials(username string, password string) (authoriz
return false
}
if match, err := argon2.ComparePasswordAndHash(password, user.Pass); err != nil || match != true {
if match, err := argon2.ComparePasswordAndHash(password, *user.Pass); err != nil || match != true {
return false
}
@@ -94,7 +94,6 @@ func (api *API) authFormLogin(c *gin.Context) {
// MD5 - KOSync Compatiblity
password := fmt.Sprintf("%x", md5.Sum([]byte(rawPassword)))
if authorized := api.authorizeCredentials(username, password); authorized != true {
c.HTML(http.StatusUnauthorized, "login", gin.H{
"RegistrationEnabled": api.Config.RegistrationEnabled,
@@ -140,7 +139,7 @@ func (api *API) authFormRegister(c *gin.Context) {
rows, err := api.DB.Queries.CreateUser(api.DB.Ctx, database.CreateUserParams{
ID: username,
Pass: hashedPassword,
Pass: &hashedPassword,
})
// SQL Error

View File

@@ -107,7 +107,7 @@ func (api *API) createUser(c *gin.Context) {
rows, err := api.DB.Queries.CreateUser(api.DB.Ctx, database.CreateUserParams{
ID: rUser.Username,
Pass: hashedPassword,
Pass: &hashedPassword,
})
if err != nil {
log.Error("[createUser] CreateUser DB Error:", err)