add api-key authentication
This commit is contained in:
parent
47ceb07d1b
commit
da44d18375
21 changed files with 244 additions and 123 deletions
|
|
@ -2,9 +2,9 @@ package app
|
|||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/backend/view"
|
||||
"gitnet.fr/deblan/budget/backend/view/template/app"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
|
|
@ -19,9 +19,10 @@ func New(e *echo.Echo) *Controller {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) HomeGet(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
user := model.LoadSessionUser(c)
|
||||
if nil == user {
|
||||
return c.Redirect(302, "/login")
|
||||
}
|
||||
|
||||
return view.Render(c, 200, app.Page())
|
||||
return view.Render(c, 200, app.Page(*user))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/labstack/echo-contrib/session"
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/backend/view"
|
||||
"gitnet.fr/deblan/budget/backend/view/template/auth"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
|
|
@ -40,10 +42,13 @@ func (ctrl *Controller) LoginPost(c echo.Context) error {
|
|||
db.Db.Model(model.User{}).Where("username = ?", username).Find(&user)
|
||||
|
||||
if user.HasPassword(password) {
|
||||
user.LoggedAt = time.Now()
|
||||
db.Db.Save(user)
|
||||
|
||||
sess, _ := session.Get("session", c)
|
||||
sess.Options = &sessions.Options{
|
||||
Path: "/",
|
||||
MaxAge: 86400 * 7,
|
||||
MaxAge: 3600 * 24 * 2,
|
||||
HttpOnly: true,
|
||||
}
|
||||
sess.Values["user"] = user.ID
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package bank_account
|
|||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
|
@ -39,32 +39,32 @@ func New(e *echo.Echo) *Controller {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) List(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).List(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Show(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Show(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Delete(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Delete(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Create(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
@ -83,8 +83,8 @@ func (ctrl *Controller) Create(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) Update(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ package category
|
|||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
|
@ -46,32 +46,32 @@ func New(e *echo.Echo) *Controller {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) List(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).List(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Show(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Show(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Delete(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Delete(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Create(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
@ -93,8 +93,8 @@ func (ctrl *Controller) Create(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) Update(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
|
|||
|
|
@ -12,11 +12,12 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gitnet.fr/deblan/budget/backend/view"
|
||||
tpl "gitnet.fr/deblan/budget/backend/view/template/collabora"
|
||||
"gitnet.fr/deblan/budget/config"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
f "gitnet.fr/deblan/budget/file"
|
||||
"gitnet.fr/deblan/budget/backend/view"
|
||||
tpl "gitnet.fr/deblan/budget/backend/view/template/collabora"
|
||||
)
|
||||
|
||||
func getToken() string {
|
||||
|
|
@ -55,8 +56,8 @@ func New(e *echo.Echo) *Controller {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) Iframe(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
resp, err := http.Get(config.Get().Collabora.HostingDiscoveryUrl())
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gitnet.fr/deblan/budget/config"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
f "gitnet.fr/deblan/budget/file"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
|
|
@ -30,8 +30,8 @@ func New(e *echo.Echo) *Controller {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) List(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
tree := f.GetTree("", config.Get().File.Path)
|
||||
|
|
@ -40,8 +40,8 @@ func (ctrl *Controller) List(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) CreateFile(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
file, err := c.FormFile("file")
|
||||
|
|
@ -76,8 +76,8 @@ func (ctrl *Controller) CreateFile(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) CreateDirectory(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
@ -125,8 +125,8 @@ func (ctrl *Controller) CreateDirectory(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) Download(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
var file string
|
||||
|
|
@ -152,8 +152,8 @@ func (ctrl *Controller) Download(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) Delete(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
var file string
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package saving_account
|
|||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
|
@ -39,32 +39,32 @@ func New(e *echo.Echo) *Controller {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) List(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).List(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Show(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Show(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Delete(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Delete(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Create(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
@ -85,8 +85,8 @@ func (ctrl *Controller) Create(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) Update(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
|
@ -49,24 +49,24 @@ func New(e *echo.Echo) *Controller {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) List(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).List(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Show(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Show(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) UpdateCategories(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
datas := model.UpdateTransactionsCategories()
|
||||
|
|
@ -75,8 +75,8 @@ func (ctrl *Controller) UpdateCategories(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) Create(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
db := manager.Get().Db
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package user
|
|||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/backend/controller/crud"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
|
@ -38,32 +38,32 @@ func New(e *echo.Echo) *Controller {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) List(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).List(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Show(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Show(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Delete(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
return ctrl.crud.With(ctrl.Config()).Delete(c)
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Create(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
@ -83,8 +83,8 @@ func (ctrl *Controller) Create(c echo.Context) error {
|
|||
}
|
||||
|
||||
func (ctrl *Controller) Update(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
if nil == model.LoadApiUser(c) {
|
||||
return c.JSON(403, crud.Error{Code: 403, Message: "Login required"})
|
||||
}
|
||||
|
||||
type body struct {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
package app
|
||||
|
||||
import "gitnet.fr/deblan/budget/backend/view/template"
|
||||
import (
|
||||
"gitnet.fr/deblan/budget/backend/view/template"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
)
|
||||
|
||||
templ Page() {
|
||||
templ Page(user model.User) {
|
||||
<!doctype html>
|
||||
<html>
|
||||
<html data-api-key={ user.ApiKey }>
|
||||
@template.Head("Budget")
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ package app
|
|||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "gitnet.fr/deblan/budget/backend/view/template"
|
||||
import (
|
||||
"gitnet.fr/deblan/budget/backend/view/template"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
)
|
||||
|
||||
func Page() templ.Component {
|
||||
func Page(user model.User) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
|
|
@ -31,7 +34,20 @@ func Page() templ.Component {
|
|||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html data-api-key=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(user.ApiKey)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `backend/view/template/app/page.templ`, Line: 10, Col: 33}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo-contrib/session"
|
||||
|
|
@ -14,6 +17,8 @@ type User struct {
|
|||
Username string `gorm:"unique;not null" json:"username"`
|
||||
Password string `gorm:"not null" json:"-"`
|
||||
DisplayName string `gorm:"not null" json:"display_name"`
|
||||
ApiKey string `json:"api_key"`
|
||||
LoggedAt time.Time `json:"logged_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
|
@ -29,6 +34,13 @@ func NewUser(username, password, displayName string) *User {
|
|||
return &user
|
||||
}
|
||||
|
||||
func (u *User) GenerateApiKey() {
|
||||
buffer := make([]byte, 64)
|
||||
rand.Read(buffer)
|
||||
|
||||
u.ApiKey = base64.URLEncoding.EncodeToString(buffer)[:64]
|
||||
}
|
||||
|
||||
func (u *User) UpdatePassword(password string) {
|
||||
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
|
||||
|
|
@ -39,6 +51,44 @@ func (u *User) HasPassword(password string) bool {
|
|||
return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) == nil
|
||||
}
|
||||
|
||||
func LoadUser(c echo.Context) *User {
|
||||
user := LoadApiUser(c)
|
||||
|
||||
if user == nil {
|
||||
user = LoadSessionUser(c)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
func LoadApiUser(c echo.Context) *User {
|
||||
headers := c.Request().Header
|
||||
apiKey := ""
|
||||
|
||||
for key, values := range headers {
|
||||
if strings.ToLower(key) == "x-api-key" {
|
||||
apiKey = values[0]
|
||||
}
|
||||
}
|
||||
|
||||
if apiKey == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var count int64
|
||||
db := manager.Get()
|
||||
db.Db.Model(User{}).Where("api_key = ?", apiKey).Count(&count)
|
||||
|
||||
if count == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var user User
|
||||
manager.Get().Db.Model(User{}).Where("api_key = ?", apiKey).Find(&user)
|
||||
|
||||
return &user
|
||||
}
|
||||
|
||||
func LoadSessionUser(c echo.Context) *User {
|
||||
sess, err := session.Get("session", c)
|
||||
|
||||
|
|
@ -65,5 +115,10 @@ func LoadSessionUser(c echo.Context) *User {
|
|||
var user User
|
||||
manager.Get().Db.Model(User{}).Where("id = ?", id).Find(&user)
|
||||
|
||||
if user.ApiKey == "" {
|
||||
user.GenerateApiKey()
|
||||
db.Db.Save(user)
|
||||
}
|
||||
|
||||
return &user
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
const addZero = (value) => {
|
||||
if (value < 10) {
|
||||
value = `0${value}`
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
const renderDate = (value) => {
|
||||
const d = new Date(value)
|
||||
|
||||
let day = d.getUTCDate()
|
||||
let month = d.getUTCMonth() + 1
|
||||
let day = addZero(d.getUTCDate())
|
||||
let month = addZero(d.getUTCMonth() + 1)
|
||||
const year = d.getUTCFullYear()
|
||||
|
||||
if (month < 10) {
|
||||
month = `0${month}`
|
||||
}
|
||||
|
||||
if (day < 10) {
|
||||
day = `0${day}`
|
||||
}
|
||||
|
||||
return `${day}/${month}/${year}`
|
||||
}
|
||||
|
||||
const renderDateTime = (value) => {
|
||||
const d = new Date(value)
|
||||
|
||||
return `${renderDate(value)} ${addZero(d.getHours())}:${addZero(d.getMinutes())}`
|
||||
}
|
||||
|
||||
const renderCategory = (item) => {
|
||||
if (item !== null) {
|
||||
return `<span class="badge" style="background: ${item.color}"> </span> ${item.label}`
|
||||
|
|
@ -58,6 +64,7 @@ const renderLabelWithSum = (label, rows, key) => {
|
|||
|
||||
export {
|
||||
renderDate,
|
||||
renderDateTime,
|
||||
renderCategory,
|
||||
renderBankAccount,
|
||||
renderEuro,
|
||||
|
|
|
|||
16
frontend/js/lib/request.js
Normal file
16
frontend/js/lib/request.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
const createRequestOptions = (options) => {
|
||||
options = options || {}
|
||||
|
||||
const apiKey = document.querySelector('html').getAttribute('data-api-key')
|
||||
|
||||
if (apiKey) {
|
||||
options['headers'] = options['headers'] || {}
|
||||
options['headers']['x-api-key'] = apiKey
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
export {
|
||||
createRequestOptions
|
||||
}
|
||||
|
|
@ -159,6 +159,7 @@ import Header from './../components/crud/Header.vue'
|
|||
import Pager from './../components/crud/Pager.vue'
|
||||
import {ref, onMounted, watch} from 'vue'
|
||||
import {getStorage, saveStorage} from '../lib/storage'
|
||||
import {createRequestOptions} from '../lib/request'
|
||||
|
||||
const endpoint = `/api/bank_account`
|
||||
const order = ref(getStorage(`${endpoint}:order`))
|
||||
|
|
@ -183,6 +184,7 @@ const refresh = () => {
|
|||
page: page.value,
|
||||
limit: limit.value,
|
||||
})}`,
|
||||
createRequestOptions()
|
||||
)
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
|
|
@ -246,13 +248,13 @@ const doDelete = () => {
|
|||
return
|
||||
}
|
||||
|
||||
fetch(`${endpoint}/${form.value.data.id}`, {
|
||||
fetch(`${endpoint}/${form.value.data.id}`, createRequestOptions({
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}).then(() => {
|
||||
})).then(() => {
|
||||
formShow.value = false
|
||||
refresh()
|
||||
})
|
||||
|
|
@ -265,14 +267,14 @@ const doSave = (e) => {
|
|||
? `${endpoint}/${form.value.data.id}`
|
||||
: endpoint
|
||||
|
||||
fetch(url, {
|
||||
fetch(url, createRequestOptions({
|
||||
method: form.value.method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(form.value.data),
|
||||
})
|
||||
}))
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -289,6 +289,7 @@ import Pager from './../components/crud/Pager.vue'
|
|||
import {ref, onMounted, watch, useTemplateRef} from 'vue'
|
||||
import {getStorage, saveStorage} from '../lib/storage'
|
||||
import {renderCategory, renderEuro, renderLabelWithSum} from '../lib/renderers'
|
||||
import {createRequestOptions} from '../lib/request'
|
||||
|
||||
const endpoint = `/api/category`
|
||||
const order = ref(getStorage(`${endpoint}:order`))
|
||||
|
|
@ -345,7 +346,7 @@ const doAddRule = (item) => {
|
|||
|
||||
const doApply = () => {
|
||||
applyInProgress.value = true
|
||||
fetch('/api/transactions/update_categories', {method: 'POST'}).then(() => {
|
||||
fetch('/api/transactions/update_categories', createRequestOptions({method: 'POST'})).then(() => {
|
||||
applyInProgress.value = false
|
||||
})
|
||||
}
|
||||
|
|
@ -358,6 +359,7 @@ const refresh = () => {
|
|||
page: page.value,
|
||||
limit: limit.value,
|
||||
})}`,
|
||||
createRequestOptions()
|
||||
)
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
|
|
@ -517,13 +519,13 @@ const doDelete = () => {
|
|||
return
|
||||
}
|
||||
|
||||
fetch(`${endpoint}/${form.value.data.id}`, {
|
||||
fetch(`${endpoint}/${form.value.data.id}`, createRequestOptions({
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}).then(() => {
|
||||
})).then(() => {
|
||||
formShow.value = false
|
||||
refresh()
|
||||
})
|
||||
|
|
@ -584,14 +586,14 @@ const doSave = (e) => {
|
|||
}
|
||||
})
|
||||
|
||||
fetch(url, {
|
||||
fetch(url, createRequestOptions({
|
||||
method: form.value.method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(form.value.data),
|
||||
})
|
||||
}))
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ import MonthThresholds from './../components/dashboard/MonthThresholds.vue'
|
|||
import DiffCreditDebit from './../components/dashboard/DiffCreditDebit.vue'
|
||||
import CategoriesStats from './../components/dashboard/CategoriesStats.vue'
|
||||
import {VueDraggableNext as Draggable} from 'vue-draggable-next'
|
||||
import {createRequestOptions} from '../lib/request'
|
||||
|
||||
const data = ref(null)
|
||||
const isLoading = ref(true)
|
||||
|
|
@ -207,7 +208,7 @@ const refresh = () => {
|
|||
query['bank_account_id__eq'] = account.value
|
||||
}
|
||||
|
||||
fetch(`/api/transaction?${new URLSearchParams(query)}`)
|
||||
fetch(`/api/transaction?${new URLSearchParams(query)}`, createRequestOptions())
|
||||
.then((response) => response.json())
|
||||
.then((value) => {
|
||||
data.value = value.rows.filter(
|
||||
|
|
@ -222,20 +223,20 @@ onMounted(() => {
|
|||
|
||||
refresh()
|
||||
|
||||
fetch('/api/category?order=label&sort=asc&ignore_transactions__eq=0')
|
||||
fetch('/api/category?order=label&sort=asc&ignore_transactions__eq=0', createRequestOptions())
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
categories.value = data.rows
|
||||
categories.value.push({id: -1, label: 'Sans catégorie', color: '#cccccc'})
|
||||
})
|
||||
|
||||
fetch('/api/bank_account')
|
||||
fetch('/api/bank_account', createRequestOptions())
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
accounts.value = data.rows
|
||||
})
|
||||
|
||||
fetch('/api/saving_account')
|
||||
fetch('/api/saving_account', createRequestOptions())
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
savingAccounts.value = data.rows
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ import {
|
|||
BDropdown,
|
||||
BDropdownItem,
|
||||
} from 'bootstrap-vue-next'
|
||||
import {createRequestOptions} from '../lib/request'
|
||||
|
||||
let formFile = false
|
||||
const tree = ref(null)
|
||||
|
|
@ -271,9 +272,9 @@ const doDelete = (item) => {
|
|||
return
|
||||
}
|
||||
|
||||
fetch(`/api/filemanager/file/${item.id}`, {
|
||||
fetch(`/api/filemanager/file/${item.id}`, createRequestOptions({
|
||||
method: 'DELETE',
|
||||
}).then(() => {
|
||||
})).then(() => {
|
||||
refresh({current: tree.value.id})
|
||||
})
|
||||
}
|
||||
|
|
@ -286,13 +287,13 @@ const doSave = (e) => {
|
|||
payload.append('file', form.value.data.file)
|
||||
payload.append('path', tree.value.id)
|
||||
|
||||
fetch(`/api/filemanager/file`, {
|
||||
fetch(`/api/filemanager/file`, createRequestOptions({
|
||||
method: form.value.method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
},
|
||||
body: payload,
|
||||
})
|
||||
}))
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
@ -309,14 +310,14 @@ const doSave = (e) => {
|
|||
form.value.error = `Une erreur s'est produite : ${err}`
|
||||
})
|
||||
} else {
|
||||
fetch(`/api/filemanager/directory`, {
|
||||
fetch(`/api/filemanager/directory`, createRequestOptions({
|
||||
method: form.value.method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(form.value.data),
|
||||
})
|
||||
}))
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
@ -338,7 +339,7 @@ const doSave = (e) => {
|
|||
const refresh = (options) => {
|
||||
options = options || {}
|
||||
|
||||
fetch('/api/filemanager/files')
|
||||
fetch('/api/filemanager/files', createRequestOptions())
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
tree.value = withParents(data)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ import Pager from './../components/crud/Pager.vue'
|
|||
import {ref, onMounted, watch} from 'vue'
|
||||
import {getStorage, saveStorage} from '../lib/storage'
|
||||
import {renderDate, renderEuro, renderLabelWithSum} from '../lib/renderers'
|
||||
import {createRequestOptions} from '../lib/request'
|
||||
|
||||
const endpoint = `/api/saving_account`
|
||||
const order = ref(getStorage(`${endpoint}:order`))
|
||||
|
|
@ -185,6 +186,7 @@ const refresh = () => {
|
|||
page: page.value,
|
||||
limit: limit.value,
|
||||
})}`,
|
||||
createRequestOptions()
|
||||
)
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
|
|
@ -268,13 +270,13 @@ const doDelete = () => {
|
|||
return
|
||||
}
|
||||
|
||||
fetch(`${endpoint}/${form.value.data.id}`, {
|
||||
fetch(`${endpoint}/${form.value.data.id}`, createRequestOptions({
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}).then(() => {
|
||||
})).then(() => {
|
||||
formShow.value = false
|
||||
refresh()
|
||||
})
|
||||
|
|
@ -290,14 +292,14 @@ const doSave = (e) => {
|
|||
form.value.data.released_amount = parseFloat(form.value.data.released_amount)
|
||||
form.value.data.blocked_amount = parseFloat(form.value.data.blocked_amount)
|
||||
|
||||
fetch(url, {
|
||||
fetch(url, createRequestOptions({
|
||||
method: form.value.method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(form.value.data),
|
||||
})
|
||||
}))
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -267,6 +267,7 @@ import {
|
|||
} from '../lib/renderers'
|
||||
import {queryFilters, appendRequestQueryFilters} from '../lib/filter'
|
||||
import {useRoute} from 'vue-router'
|
||||
import {createRequestOptions} from '../lib/request'
|
||||
|
||||
const endpoint = `/api/transaction`
|
||||
const order = ref(getStorage(`${endpoint}:order`))
|
||||
|
|
@ -311,7 +312,7 @@ const refresh = () => {
|
|||
|
||||
query = appendRequestQueryFilters(query, route)
|
||||
|
||||
fetch(`${endpoint}?${new URLSearchParams(query)}`)
|
||||
fetch(`${endpoint}?${new URLSearchParams(query)}`, createRequestOptions())
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
@ -328,7 +329,7 @@ const refresh = () => {
|
|||
const doAdd = () => {
|
||||
const data = {category_id: null, file: null, format: 'caisse_epargne'}
|
||||
|
||||
fetch(`/api/bank_account?order=label`)
|
||||
fetch(`/api/bank_account?order=label`, createRequestOptions())
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
@ -387,13 +388,13 @@ const doSave = (e) => {
|
|||
payload.append('file', form.value.data.file)
|
||||
payload.append('format', form.value.data.format)
|
||||
|
||||
fetch(`/api/transactions`, {
|
||||
fetch(`/api/transactions`, createRequestOptions({
|
||||
method: form.value.method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
},
|
||||
body: payload,
|
||||
})
|
||||
}))
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
@ -487,7 +488,7 @@ onMounted(() => {
|
|||
route = useRoute()
|
||||
refresh()
|
||||
|
||||
fetch('/api/category')
|
||||
fetch('/api/category', createRequestOptions())
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
filtersFields.value.forEach((value, key) => {
|
||||
|
|
@ -502,7 +503,7 @@ onMounted(() => {
|
|||
})
|
||||
})
|
||||
|
||||
fetch('/api/bank_account')
|
||||
fetch('/api/bank_account', createRequestOptions())
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
filtersFields.value.forEach((value, key) => {
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ import Header from './../components/crud/Header.vue'
|
|||
import Pager from './../components/crud/Pager.vue'
|
||||
import {ref, onMounted, watch} from 'vue'
|
||||
import {getStorage, saveStorage} from '../lib/storage'
|
||||
import {createRequestOptions} from '../lib/request'
|
||||
import {renderDateTime} from '../lib/renderers'
|
||||
|
||||
const endpoint = `/api/user`
|
||||
const order = ref(getStorage(`${endpoint}:order`))
|
||||
|
|
@ -181,6 +183,7 @@ const refresh = () => {
|
|||
page: page.value,
|
||||
limit: limit.value,
|
||||
})}`,
|
||||
createRequestOptions()
|
||||
)
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
|
|
@ -268,13 +271,13 @@ const doDelete = () => {
|
|||
return
|
||||
}
|
||||
|
||||
fetch(`${endpoint}/${form.value.data.id}`, {
|
||||
fetch(`${endpoint}/${form.value.data.id}`, createRequestOptions({
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}).then(() => {
|
||||
})).then(() => {
|
||||
formShow.value = false
|
||||
refresh()
|
||||
})
|
||||
|
|
@ -287,14 +290,14 @@ const doSave = (e) => {
|
|||
? `${endpoint}/${form.value.data.id}`
|
||||
: endpoint
|
||||
|
||||
fetch(url, {
|
||||
fetch(url, createRequestOptions({
|
||||
method: form.value.method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(form.value.data),
|
||||
})
|
||||
}))
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
|
|
@ -336,6 +339,11 @@ const fields = [
|
|||
key: 'username',
|
||||
label: 'Utilisateur',
|
||||
},
|
||||
{
|
||||
key: 'logged_at',
|
||||
label: 'Dernière connexion',
|
||||
render: (item) => renderDateTime(item.logged_at),
|
||||
},
|
||||
]
|
||||
|
||||
onMounted(() => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue