mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
refactor: alert handling
This commit is contained in:
@ -229,7 +229,6 @@ func Load() *Config {
|
|||||||
|
|
||||||
config.Version = readVersion()
|
config.Version = readVersion()
|
||||||
config.App.LanguageColors = readLanguageColors()
|
config.App.LanguageColors = readLanguageColors()
|
||||||
// TODO: Read keys from env, so that users are not logged out every time the server is restarted
|
|
||||||
config.Security.SecureCookie = securecookie.New(
|
config.Security.SecureCookie = securecookie.New(
|
||||||
securecookie.GenerateRandomKey(64),
|
securecookie.GenerateRandomKey(64),
|
||||||
securecookie.GenerateRandomKey(32),
|
securecookie.GenerateRandomKey(32),
|
||||||
|
15
main.go
15
main.go
@ -107,7 +107,8 @@ func main() {
|
|||||||
healthHandler := routes.NewHealthHandler(db)
|
healthHandler := routes.NewHealthHandler(db)
|
||||||
heartbeatHandler := routes.NewHeartbeatHandler(heartbeatService, languageMappingService)
|
heartbeatHandler := routes.NewHeartbeatHandler(heartbeatService, languageMappingService)
|
||||||
settingsHandler := routes.NewSettingsHandler(userService, summaryService, aggregationService, languageMappingService)
|
settingsHandler := routes.NewSettingsHandler(userService, summaryService, aggregationService, languageMappingService)
|
||||||
publicHandler := routes.NewIndexHandler(userService, keyValueService)
|
homeHandler := routes.NewHomeHandler(userService)
|
||||||
|
imprintHandler := routes.NewImprintHandler(keyValueService)
|
||||||
wakatimeV1AllHandler := wtV1Routes.NewAllTimeHandler(summaryService)
|
wakatimeV1AllHandler := wtV1Routes.NewAllTimeHandler(summaryService)
|
||||||
wakatimeV1SummariesHandler := wtV1Routes.NewSummariesHandler(summaryService)
|
wakatimeV1SummariesHandler := wtV1Routes.NewSummariesHandler(summaryService)
|
||||||
shieldV1BadgeHandler := shieldsV1Routes.NewBadgeHandler(summaryService, userService)
|
shieldV1BadgeHandler := shieldsV1Routes.NewBadgeHandler(summaryService, userService)
|
||||||
@ -138,12 +139,12 @@ func main() {
|
|||||||
apiRouter.Use(corsMiddleware, authenticateMiddleware)
|
apiRouter.Use(corsMiddleware, authenticateMiddleware)
|
||||||
|
|
||||||
// Public Routes
|
// Public Routes
|
||||||
publicRouter.Path("/").Methods(http.MethodGet).HandlerFunc(publicHandler.GetIndex)
|
publicRouter.Path("/").Methods(http.MethodGet).HandlerFunc(homeHandler.GetIndex)
|
||||||
publicRouter.Path("/login").Methods(http.MethodPost).HandlerFunc(publicHandler.PostLogin)
|
publicRouter.Path("/login").Methods(http.MethodPost).HandlerFunc(homeHandler.PostLogin)
|
||||||
publicRouter.Path("/logout").Methods(http.MethodPost).HandlerFunc(publicHandler.PostLogout)
|
publicRouter.Path("/logout").Methods(http.MethodPost).HandlerFunc(homeHandler.PostLogout)
|
||||||
publicRouter.Path("/signup").Methods(http.MethodGet).HandlerFunc(publicHandler.GetSignup)
|
publicRouter.Path("/signup").Methods(http.MethodGet).HandlerFunc(homeHandler.GetSignup)
|
||||||
publicRouter.Path("/signup").Methods(http.MethodPost).HandlerFunc(publicHandler.PostSignup)
|
publicRouter.Path("/signup").Methods(http.MethodPost).HandlerFunc(homeHandler.PostSignup)
|
||||||
publicRouter.Path("/imprint").Methods(http.MethodGet).HandlerFunc(publicHandler.GetImprint)
|
publicRouter.Path("/imprint").Methods(http.MethodGet).HandlerFunc(imprintHandler.GetImprint)
|
||||||
|
|
||||||
// Summary Routes
|
// Summary Routes
|
||||||
summaryRouter.Methods(http.MethodGet).HandlerFunc(summaryHandler.GetIndex)
|
summaryRouter.Methods(http.MethodGet).HandlerFunc(summaryHandler.GetIndex)
|
||||||
|
16
models/view/home.go
Normal file
16
models/view/home.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
type HomeViewModel struct {
|
||||||
|
Success string
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HomeViewModel) WithSuccess(m string) *HomeViewModel {
|
||||||
|
s.Success = m
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HomeViewModel) WithError(m string) *HomeViewModel {
|
||||||
|
s.Error = m
|
||||||
|
return s
|
||||||
|
}
|
22
models/view/imprint.go
Normal file
22
models/view/imprint.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
type ImprintViewModel struct {
|
||||||
|
HtmlText string
|
||||||
|
Success string
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ImprintViewModel) WithSuccess(m string) *ImprintViewModel {
|
||||||
|
s.Success = m
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ImprintViewModel) WithError(m string) *ImprintViewModel {
|
||||||
|
s.Error = m
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ImprintViewModel) WithHtmlText(t string) *ImprintViewModel {
|
||||||
|
s.HtmlText = t
|
||||||
|
return s
|
||||||
|
}
|
20
models/view/settings.go
Normal file
20
models/view/settings.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
import "github.com/muety/wakapi/models"
|
||||||
|
|
||||||
|
type SettingsViewModel struct {
|
||||||
|
User *models.User
|
||||||
|
LanguageMappings []*models.LanguageMapping
|
||||||
|
Success string
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SettingsViewModel) WithSuccess(m string) *SettingsViewModel {
|
||||||
|
s.Success = m
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SettingsViewModel) WithError(m string) *SettingsViewModel {
|
||||||
|
s.Error = m
|
||||||
|
return s
|
||||||
|
}
|
16
models/view/summary.go
Normal file
16
models/view/summary.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
type SummaryViewModel struct {
|
||||||
|
Success string
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SummaryViewModel) WithSuccess(m string) *SummaryViewModel {
|
||||||
|
s.Success = m
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SummaryViewModel) WithError(m string) *SummaryViewModel {
|
||||||
|
s.Error = m
|
||||||
|
return s
|
||||||
|
}
|
@ -43,13 +43,6 @@ func (h *HeartbeatHandler) ApiPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*languageMappings, err := h.languageMappingSrvc.ResolveByUser(user.ID)
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
w.Write([]byte(err.Error()))
|
|
||||||
return
|
|
||||||
}*/
|
|
||||||
|
|
||||||
for _, hb := range heartbeats {
|
for _, hb := range heartbeats {
|
||||||
hb.OperatingSystem = opSys
|
hb.OperatingSystem = opSys
|
||||||
hb.Editor = editor
|
hb.Editor = editor
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
conf "github.com/muety/wakapi/config"
|
conf "github.com/muety/wakapi/config"
|
||||||
"github.com/muety/wakapi/middlewares"
|
"github.com/muety/wakapi/middlewares"
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
|
"github.com/muety/wakapi/models/view"
|
||||||
"github.com/muety/wakapi/services"
|
"github.com/muety/wakapi/services"
|
||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -13,24 +14,22 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexHandler struct {
|
type HomeHandler struct {
|
||||||
config *conf.Config
|
config *conf.Config
|
||||||
userSrvc *services.UserService
|
userSrvc *services.UserService
|
||||||
keyValueSrvc *services.KeyValueService
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var loginDecoder = schema.NewDecoder()
|
var loginDecoder = schema.NewDecoder()
|
||||||
var signupDecoder = schema.NewDecoder()
|
var signupDecoder = schema.NewDecoder()
|
||||||
|
|
||||||
func NewIndexHandler(userService *services.UserService, keyValueService *services.KeyValueService) *IndexHandler {
|
func NewHomeHandler(userService *services.UserService) *HomeHandler {
|
||||||
return &IndexHandler{
|
return &HomeHandler{
|
||||||
config: conf.Get(),
|
config: conf.Get(),
|
||||||
userSrvc: userService,
|
userSrvc: userService,
|
||||||
keyValueSrvc: keyValueService,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *IndexHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
func (h *HomeHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
||||||
if h.config.IsDev() {
|
if h.config.IsDev() {
|
||||||
loadTemplates()
|
loadTemplates()
|
||||||
}
|
}
|
||||||
@ -40,29 +39,10 @@ func (h *IndexHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if handleAlerts(w, r, "") {
|
templates[conf.IndexTemplate].Execute(w, h.buildViewModel(r))
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
templates[conf.IndexTemplate].Execute(w, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *IndexHandler) GetImprint(w http.ResponseWriter, r *http.Request) {
|
func (h *HomeHandler) PostLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
if h.config.IsDev() {
|
|
||||||
loadTemplates()
|
|
||||||
}
|
|
||||||
|
|
||||||
text := "failed to load content"
|
|
||||||
if data, err := h.keyValueSrvc.GetString(models.ImprintKey); err == nil {
|
|
||||||
text = data.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
templates[conf.ImprintTemplate].Execute(w, &struct {
|
|
||||||
HtmlText string
|
|
||||||
}{HtmlText: text})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *IndexHandler) PostLogin(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if h.config.IsDev() {
|
if h.config.IsDev() {
|
||||||
loadTemplates()
|
loadTemplates()
|
||||||
}
|
}
|
||||||
@ -74,29 +54,34 @@ func (h *IndexHandler) PostLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
var login models.Login
|
var login models.Login
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
respondAlert(w, "missing parameters", "", "", http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
templates[conf.IndexTemplate].Execute(w, h.buildViewModel(r).WithError("missing parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := loginDecoder.Decode(&login, r.PostForm); err != nil {
|
if err := loginDecoder.Decode(&login, r.PostForm); err != nil {
|
||||||
respondAlert(w, "missing parameters", "", "", http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
templates[conf.IndexTemplate].Execute(w, h.buildViewModel(r).WithError("missing parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := h.userSrvc.GetUserById(login.Username)
|
user, err := h.userSrvc.GetUserById(login.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondAlert(w, "resource not found", "", "", http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
templates[conf.IndexTemplate].Execute(w, h.buildViewModel(r).WithError("resource not found"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: depending on middleware package here is a hack
|
// TODO: depending on middleware package here is a hack
|
||||||
if !middlewares.CheckAndMigratePassword(user, &login, h.config.Security.PasswordSalt, h.userSrvc) {
|
if !middlewares.CheckAndMigratePassword(user, &login, h.config.Security.PasswordSalt, h.userSrvc) {
|
||||||
respondAlert(w, "invalid credentials", "", "", http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
templates[conf.IndexTemplate].Execute(w, h.buildViewModel(r).WithError("invalid credentials"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
encoded, err := h.config.Security.SecureCookie.Encode(models.AuthCookieKey, login)
|
encoded, err := h.config.Security.SecureCookie.Encode(models.AuthCookieKey, login)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondAlert(w, "internal server error", "", "", http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.IndexTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +99,7 @@ func (h *IndexHandler) PostLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Redirect(w, r, fmt.Sprintf("%s/summary", h.config.Server.BasePath), http.StatusFound)
|
http.Redirect(w, r, fmt.Sprintf("%s/summary", h.config.Server.BasePath), http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *IndexHandler) PostLogout(w http.ResponseWriter, r *http.Request) {
|
func (h *HomeHandler) PostLogout(w http.ResponseWriter, r *http.Request) {
|
||||||
if h.config.IsDev() {
|
if h.config.IsDev() {
|
||||||
loadTemplates()
|
loadTemplates()
|
||||||
}
|
}
|
||||||
@ -123,7 +108,7 @@ func (h *IndexHandler) PostLogout(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Redirect(w, r, fmt.Sprintf("%s/", h.config.Server.BasePath), http.StatusFound)
|
http.Redirect(w, r, fmt.Sprintf("%s/", h.config.Server.BasePath), http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *IndexHandler) GetSignup(w http.ResponseWriter, r *http.Request) {
|
func (h *HomeHandler) GetSignup(w http.ResponseWriter, r *http.Request) {
|
||||||
if h.config.IsDev() {
|
if h.config.IsDev() {
|
||||||
loadTemplates()
|
loadTemplates()
|
||||||
}
|
}
|
||||||
@ -133,14 +118,10 @@ func (h *IndexHandler) GetSignup(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if handleAlerts(w, r, conf.SignupTemplate) {
|
templates[conf.SignupTemplate].Execute(w, h.buildViewModel(r))
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
templates[conf.SignupTemplate].Execute(w, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *IndexHandler) PostSignup(w http.ResponseWriter, r *http.Request) {
|
func (h *HomeHandler) PostSignup(w http.ResponseWriter, r *http.Request) {
|
||||||
if h.config.IsDev() {
|
if h.config.IsDev() {
|
||||||
loadTemplates()
|
loadTemplates()
|
||||||
}
|
}
|
||||||
@ -152,29 +133,41 @@ func (h *IndexHandler) PostSignup(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
var signup models.Signup
|
var signup models.Signup
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
respondAlert(w, "missing parameters", "", conf.SignupTemplate, http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
templates[conf.SignupTemplate].Execute(w, h.buildViewModel(r).WithError("missing parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := signupDecoder.Decode(&signup, r.PostForm); err != nil {
|
if err := signupDecoder.Decode(&signup, r.PostForm); err != nil {
|
||||||
respondAlert(w, "missing parameters", "", conf.SignupTemplate, http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
templates[conf.SignupTemplate].Execute(w, h.buildViewModel(r).WithError("missing parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !signup.IsValid() {
|
if !signup.IsValid() {
|
||||||
respondAlert(w, "invalid parameters", "", conf.SignupTemplate, http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
templates[conf.SignupTemplate].Execute(w, h.buildViewModel(r).WithError("invalid parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, created, err := h.userSrvc.CreateOrGet(&signup)
|
_, created, err := h.userSrvc.CreateOrGet(&signup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondAlert(w, "failed to create new user", "", conf.SignupTemplate, http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SignupTemplate].Execute(w, h.buildViewModel(r).WithError("failed to create new user"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !created {
|
if !created {
|
||||||
respondAlert(w, "user already existing", "", conf.SignupTemplate, http.StatusConflict)
|
w.WriteHeader(http.StatusConflict)
|
||||||
|
templates[conf.SignupTemplate].Execute(w, h.buildViewModel(r).WithError("user already existing"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := url.QueryEscape("account created successfully")
|
msg := url.QueryEscape("account created successfully")
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/?success=%s", h.config.Server.BasePath, msg), http.StatusFound)
|
http.Redirect(w, r, fmt.Sprintf("%s/?success=%s", h.config.Server.BasePath, msg), http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *HomeHandler) buildViewModel(r *http.Request) *view.HomeViewModel {
|
||||||
|
return &view.HomeViewModel{
|
||||||
|
Success: r.URL.Query().Get("success"),
|
||||||
|
Error: r.URL.Query().Get("error"),
|
||||||
|
}
|
||||||
|
}
|
41
routes/imprint.go
Normal file
41
routes/imprint.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
conf "github.com/muety/wakapi/config"
|
||||||
|
"github.com/muety/wakapi/models"
|
||||||
|
"github.com/muety/wakapi/models/view"
|
||||||
|
"github.com/muety/wakapi/services"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ImprintHandler struct {
|
||||||
|
config *conf.Config
|
||||||
|
keyValueSrvc *services.KeyValueService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewImprintHandler(keyValueService *services.KeyValueService) *ImprintHandler {
|
||||||
|
return &ImprintHandler{
|
||||||
|
config: conf.Get(),
|
||||||
|
keyValueSrvc: keyValueService,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ImprintHandler) GetImprint(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if h.config.IsDev() {
|
||||||
|
loadTemplates()
|
||||||
|
}
|
||||||
|
|
||||||
|
text := "failed to load content"
|
||||||
|
if data, err := h.keyValueSrvc.GetString(models.ImprintKey); err == nil {
|
||||||
|
text = data.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
templates[conf.ImprintTemplate].Execute(w, h.buildViewModel(r).WithHtmlText(text))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ImprintHandler) buildViewModel(r *http.Request) *view.ImprintViewModel {
|
||||||
|
return &view.ImprintViewModel{
|
||||||
|
Success: r.URL.Query().Get("success"),
|
||||||
|
Error: r.URL.Query().Get("error"),
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -58,33 +57,3 @@ func loadTemplates() {
|
|||||||
templates[tplName] = tpl
|
templates[tplName] = tpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func respondAlert(w http.ResponseWriter, error, success, tplName string, status int) {
|
|
||||||
w.WriteHeader(status)
|
|
||||||
if tplName == "" {
|
|
||||||
tplName = config.IndexTemplate
|
|
||||||
}
|
|
||||||
templates[tplName].Execute(w, struct {
|
|
||||||
Error string
|
|
||||||
Success string
|
|
||||||
}{Error: error, Success: success})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: do better
|
|
||||||
func handleAlerts(w http.ResponseWriter, r *http.Request, tplName string) bool {
|
|
||||||
if err := r.URL.Query().Get("error"); err != "" {
|
|
||||||
if err == "unauthorized" {
|
|
||||||
respondAlert(w, err, "", tplName, http.StatusUnauthorized)
|
|
||||||
} else {
|
|
||||||
respondAlert(w, err, "", tplName, http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if success := r.URL.Query().Get("success"); success != "" {
|
|
||||||
respondAlert(w, "", success, tplName, http.StatusOK)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
conf "github.com/muety/wakapi/config"
|
conf "github.com/muety/wakapi/config"
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
|
"github.com/muety/wakapi/models/view"
|
||||||
"github.com/muety/wakapi/services"
|
"github.com/muety/wakapi/services"
|
||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
"log"
|
"log"
|
||||||
@ -38,16 +39,7 @@ func (h *SettingsHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
|||||||
loadTemplates()
|
loadTemplates()
|
||||||
}
|
}
|
||||||
|
|
||||||
user := r.Context().Value(models.UserKey).(*models.User)
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r))
|
||||||
mappings, _ := h.languageMappingSrvc.GetByUser(user.ID)
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"User": user,
|
|
||||||
"LanguageMappings": mappings,
|
|
||||||
"Success": r.FormValue("success"),
|
|
||||||
"Error": r.FormValue("error"),
|
|
||||||
}
|
|
||||||
|
|
||||||
templates[conf.SettingsTemplate].Execute(w, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request) {
|
func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -59,34 +51,40 @@ func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request
|
|||||||
|
|
||||||
var credentials models.CredentialsReset
|
var credentials models.CredentialsReset
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("missing parameters")), http.StatusFound)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("missing parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := credentialsDecoder.Decode(&credentials, r.PostForm); err != nil {
|
if err := credentialsDecoder.Decode(&credentials, r.PostForm); err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("missing parameters")), http.StatusFound)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("missing parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !utils.CompareBcrypt(user.Password, credentials.PasswordOld, h.config.Security.PasswordSalt) {
|
if !utils.CompareBcrypt(user.Password, credentials.PasswordOld, h.config.Security.PasswordSalt) {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("invalid credentials")), http.StatusFound)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("invalid credentials"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !credentials.IsValid() {
|
if !credentials.IsValid() {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("invalid parameters")), http.StatusFound)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("invalid parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Password = credentials.PasswordNew
|
user.Password = credentials.PasswordNew
|
||||||
if hash, err := utils.HashBcrypt(user.Password, h.config.Security.PasswordSalt); err != nil {
|
if hash, err := utils.HashBcrypt(user.Password, h.config.Security.PasswordSalt); err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("internal server error")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
user.Password = hash
|
user.Password = hash
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := h.userSrvc.Update(user); err != nil {
|
if _, err := h.userSrvc.Update(user); err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("internal server error")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +94,8 @@ func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request
|
|||||||
}
|
}
|
||||||
encoded, err := h.config.Security.SecureCookie.Encode(models.AuthCookieKey, login)
|
encoded, err := h.config.Security.SecureCookie.Encode(models.AuthCookieKey, login)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("internal server error")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +108,7 @@ func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request
|
|||||||
}
|
}
|
||||||
http.SetCookie(w, cookie)
|
http.SetCookie(w, cookie)
|
||||||
|
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?success=%s", h.config.Server.BasePath, url.QueryEscape("password was updated successfully")), http.StatusFound)
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("password was updated successfully"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SettingsHandler) DeleteLanguageMapping(w http.ResponseWriter, r *http.Request) {
|
func (h *SettingsHandler) DeleteLanguageMapping(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -120,7 +119,8 @@ func (h *SettingsHandler) DeleteLanguageMapping(w http.ResponseWriter, r *http.R
|
|||||||
user := r.Context().Value(models.UserKey).(*models.User)
|
user := r.Context().Value(models.UserKey).(*models.User)
|
||||||
id, err := strconv.Atoi(r.PostFormValue("mapping_id"))
|
id, err := strconv.Atoi(r.PostFormValue("mapping_id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("could not delete mapping")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("could not delete mapping"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,11 +131,12 @@ func (h *SettingsHandler) DeleteLanguageMapping(w http.ResponseWriter, r *http.R
|
|||||||
|
|
||||||
err = h.languageMappingSrvc.Delete(mapping)
|
err = h.languageMappingSrvc.Delete(mapping)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("could not delete mapping")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("could not delete mapping"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?success=%s", h.config.Server.BasePath, url.QueryEscape("mapping deleted successfully")), http.StatusFound)
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("mapping deleted successfully"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SettingsHandler) PostLanguageMapping(w http.ResponseWriter, r *http.Request) {
|
func (h *SettingsHandler) PostLanguageMapping(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -157,11 +158,12 @@ func (h *SettingsHandler) PostLanguageMapping(w http.ResponseWriter, r *http.Req
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := h.languageMappingSrvc.Create(mapping); err != nil {
|
if _, err := h.languageMappingSrvc.Create(mapping); err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("mapping already exists")), http.StatusFound)
|
w.WriteHeader(http.StatusConflict)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("mapping already exists"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?success=%s", h.config.Server.BasePath, url.QueryEscape("mapping added successfully")), http.StatusFound)
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("mapping added successfully"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SettingsHandler) PostResetApiKey(w http.ResponseWriter, r *http.Request) {
|
func (h *SettingsHandler) PostResetApiKey(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -171,12 +173,13 @@ func (h *SettingsHandler) PostResetApiKey(w http.ResponseWriter, r *http.Request
|
|||||||
|
|
||||||
user := r.Context().Value(models.UserKey).(*models.User)
|
user := r.Context().Value(models.UserKey).(*models.User)
|
||||||
if _, err := h.userSrvc.ResetApiKey(user); err != nil {
|
if _, err := h.userSrvc.ResetApiKey(user); err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("internal server error")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := url.QueryEscape(fmt.Sprintf("your new api key is: %s", user.ApiKey))
|
msg := url.QueryEscape(fmt.Sprintf("your new api key is: %s", user.ApiKey))
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?success=%s", h.config.Server.BasePath, msg), http.StatusFound)
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SettingsHandler) PostToggleBadges(w http.ResponseWriter, r *http.Request) {
|
func (h *SettingsHandler) PostToggleBadges(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -186,11 +189,12 @@ func (h *SettingsHandler) PostToggleBadges(w http.ResponseWriter, r *http.Reques
|
|||||||
|
|
||||||
user := r.Context().Value(models.UserKey).(*models.User)
|
user := r.Context().Value(models.UserKey).(*models.User)
|
||||||
if _, err := h.userSrvc.ToggleBadges(user); err != nil {
|
if _, err := h.userSrvc.ToggleBadges(user); err != nil {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("internal server error")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings", h.config.Server.BasePath), http.StatusFound)
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SettingsHandler) PostRegenerateSummaries(w http.ResponseWriter, r *http.Request) {
|
func (h *SettingsHandler) PostRegenerateSummaries(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -203,15 +207,28 @@ func (h *SettingsHandler) PostRegenerateSummaries(w http.ResponseWriter, r *http
|
|||||||
log.Printf("clearing summaries for user '%s'\n", user.ID)
|
log.Printf("clearing summaries for user '%s'\n", user.ID)
|
||||||
if err := h.summarySrvc.DeleteByUser(user.ID); err != nil {
|
if err := h.summarySrvc.DeleteByUser(user.ID); err != nil {
|
||||||
log.Printf("failed to clear summaries: %v\n", err)
|
log.Printf("failed to clear summaries: %v\n", err)
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("failed to delete old summaries")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("failed to delete old summaries"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.aggregationSrvc.Run(map[string]bool{user.ID: true}); err != nil {
|
if err := h.aggregationSrvc.Run(map[string]bool{user.ID: true}); err != nil {
|
||||||
log.Printf("failed to regenerate summaries: %v\n", err)
|
log.Printf("failed to regenerate summaries: %v\n", err)
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?error=%s", h.config.Server.BasePath, url.QueryEscape("failed to generate aggregations")), http.StatusFound)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("failed to generate aggregations"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/settings?success=%s", h.config.Server.BasePath, url.QueryEscape("summaries are being regenerated – this may take a few second")), http.StatusFound)
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("summaries are being regenerated – this may take a few seconds"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SettingsHandler) buildViewModel(r *http.Request) *view.SettingsViewModel {
|
||||||
|
user := r.Context().Value(models.UserKey).(*models.User)
|
||||||
|
mappings, _ := h.languageMappingSrvc.GetByUser(user.ID)
|
||||||
|
return &view.SettingsViewModel{
|
||||||
|
User: user,
|
||||||
|
LanguageMappings: mappings,
|
||||||
|
Success: r.URL.Query().Get("success"),
|
||||||
|
Error: r.URL.Query().Get("error"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package routes
|
|||||||
import (
|
import (
|
||||||
conf "github.com/muety/wakapi/config"
|
conf "github.com/muety/wakapi/config"
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
|
"github.com/muety/wakapi/models/view"
|
||||||
"github.com/muety/wakapi/services"
|
"github.com/muety/wakapi/services"
|
||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -44,13 +45,15 @@ func (h *SummaryHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
summary, err, status := h.loadUserSummary(r)
|
summary, err, status := h.loadUserSummary(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondAlert(w, err.Error(), "", conf.SummaryTemplate, status)
|
w.WriteHeader(status)
|
||||||
|
templates[conf.SummaryTemplate].Execute(w, h.buildViewModel(r).WithError(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user := r.Context().Value(models.UserKey).(*models.User)
|
user := r.Context().Value(models.UserKey).(*models.User)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
respondAlert(w, "unauthorized", "", conf.SummaryTemplate, http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
templates[conf.SummaryTemplate].Execute(w, h.buildViewModel(r).WithError("unauthorized"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,3 +81,10 @@ func (h *SummaryHandler) loadUserSummary(r *http.Request) (*models.Summary, erro
|
|||||||
|
|
||||||
return summary, nil, http.StatusOK
|
return summary, nil, http.StatusOK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *SummaryHandler) buildViewModel(r *http.Request) *view.SummaryViewModel {
|
||||||
|
return &view.SummaryViewModel{
|
||||||
|
Success: r.URL.Query().Get("success"),
|
||||||
|
Error: r.URL.Query().Get("error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
1.15.0
|
1.15.1
|
||||||
|
Reference in New Issue
Block a user