init
This commit is contained in:
commit
eaa1ecd55e
26 changed files with 1032 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/_data
|
||||
0
Makefile
Normal file
0
Makefile
Normal file
78
cli/user/add/command.go
Normal file
78
cli/user/add/command.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package add
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
)
|
||||
|
||||
type promptContent struct {
|
||||
errorMsg string
|
||||
label string
|
||||
}
|
||||
|
||||
func promptGetInput(pc promptContent) string {
|
||||
validate := func(input string) error {
|
||||
if len(input) <= 0 {
|
||||
return errors.New(pc.errorMsg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
templates := &promptui.PromptTemplates{
|
||||
Prompt: "{{ . }} ",
|
||||
Valid: "{{ . | green }} ",
|
||||
Invalid: "{{ . | red }} ",
|
||||
Success: "{{ . | bold }} ",
|
||||
}
|
||||
|
||||
prompt := promptui.Prompt{
|
||||
Label: pc.label,
|
||||
Templates: templates,
|
||||
Validate: validate,
|
||||
}
|
||||
|
||||
result, err := prompt.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
func Command(cCtx *cli.Context) error {
|
||||
username := promptGetInput(promptContent{
|
||||
"Please provide a username.",
|
||||
"Username:",
|
||||
})
|
||||
password := promptGetInput(promptContent{
|
||||
"Please provide a password.",
|
||||
"Password:",
|
||||
})
|
||||
displayName := promptGetInput(promptContent{
|
||||
"Please provide a display name.",
|
||||
"Display name:",
|
||||
})
|
||||
|
||||
var count int64
|
||||
db := manager.Get()
|
||||
db.Db.Model(model.User{}).Where("username = ?", username).Count(&count)
|
||||
|
||||
if count > 0 {
|
||||
fmt.Print("User already exists!\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
user := model.NewUser(username, password, displayName)
|
||||
db.Db.Create(user)
|
||||
|
||||
return nil
|
||||
}
|
||||
78
cli/user/changepassword/command.go
Normal file
78
cli/user/changepassword/command.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package changepassword
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
)
|
||||
|
||||
type promptContent struct {
|
||||
errorMsg string
|
||||
label string
|
||||
}
|
||||
|
||||
func promptGetInput(pc promptContent) string {
|
||||
validate := func(input string) error {
|
||||
if len(input) <= 0 {
|
||||
return errors.New(pc.errorMsg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
templates := &promptui.PromptTemplates{
|
||||
Prompt: "{{ . }} ",
|
||||
Valid: "{{ . | green }} ",
|
||||
Invalid: "{{ . | red }} ",
|
||||
Success: "{{ . | bold }} ",
|
||||
}
|
||||
|
||||
prompt := promptui.Prompt{
|
||||
Label: pc.label,
|
||||
Templates: templates,
|
||||
Validate: validate,
|
||||
}
|
||||
|
||||
result, err := prompt.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
func Command(cCtx *cli.Context) error {
|
||||
username := promptGetInput(promptContent{
|
||||
"Please provide a username.",
|
||||
"Username:",
|
||||
})
|
||||
|
||||
var count int64
|
||||
db := manager.Get()
|
||||
db.Db.Model(model.User{}).Where("username = ?", username).Count(&count)
|
||||
|
||||
if count == 0 {
|
||||
fmt.Printf("User does not exist!\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
password := promptGetInput(promptContent{
|
||||
"Please provide a password.",
|
||||
"Password:",
|
||||
})
|
||||
|
||||
var user model.User
|
||||
db.Db.Model(model.User{}).Where("username = ?", username).Find(&user)
|
||||
|
||||
user.UpdatePassword(password)
|
||||
db.Db.Save(user)
|
||||
|
||||
return nil
|
||||
}
|
||||
71
cli/user/delete/command.go
Normal file
71
cli/user/delete/command.go
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package delete
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
)
|
||||
|
||||
type promptContent struct {
|
||||
errorMsg string
|
||||
label string
|
||||
}
|
||||
|
||||
func promptGetInput(pc promptContent) string {
|
||||
validate := func(input string) error {
|
||||
if len(input) <= 0 {
|
||||
return errors.New(pc.errorMsg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
templates := &promptui.PromptTemplates{
|
||||
Prompt: "{{ . }} ",
|
||||
Valid: "{{ . | green }} ",
|
||||
Invalid: "{{ . | red }} ",
|
||||
Success: "{{ . | bold }} ",
|
||||
}
|
||||
|
||||
prompt := promptui.Prompt{
|
||||
Label: pc.label,
|
||||
Templates: templates,
|
||||
Validate: validate,
|
||||
}
|
||||
|
||||
result, err := prompt.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(result)
|
||||
}
|
||||
|
||||
func Command(cCtx *cli.Context) error {
|
||||
username := promptGetInput(promptContent{
|
||||
"Please provide a username.",
|
||||
"Username:",
|
||||
})
|
||||
|
||||
var count int64
|
||||
db := manager.Get()
|
||||
db.Db.Model(model.User{}).Where("username = ?", username).Count(&count)
|
||||
|
||||
if count == 0 {
|
||||
fmt.Printf("User does not exist!\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var user model.User
|
||||
db.Db.Model(model.User{}).Where("username = ?", username).Find(&user)
|
||||
db.Db.Delete(user)
|
||||
|
||||
return nil
|
||||
}
|
||||
37
cmd/cli/cli.go
Normal file
37
cmd/cli/cli.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
userAdd "gitnet.fr/deblan/budget/cli/user/add"
|
||||
userChangePassword "gitnet.fr/deblan/budget/cli/user/changepassword"
|
||||
userDelete "gitnet.fr/deblan/budget/cli/user/delete"
|
||||
"gitnet.fr/deblan/budget/config"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ini := flag.String("c", "config.ini", "Path to config.ini")
|
||||
config.Get().Load(*ini)
|
||||
manager.Get().AutoMigrate()
|
||||
|
||||
app := &cli.App{
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "user",
|
||||
Subcommands: []*cli.Command{
|
||||
{Name: "add", Action: userAdd.Command},
|
||||
{Name: "delete", Action: userDelete.Command},
|
||||
{Name: "change-password", Action: userChangePassword.Command},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
37
cmd/server/server.go
Normal file
37
cmd/server/server.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"text/template"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/labstack/echo-contrib/session"
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/config"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/web/router"
|
||||
)
|
||||
|
||||
type TemplateRenderer struct {
|
||||
templates *template.Template
|
||||
}
|
||||
|
||||
func main() {
|
||||
ini := flag.String("c", "config.ini", "Path to config.ini")
|
||||
conf := config.Get()
|
||||
conf.Load(*ini)
|
||||
manager.Get().Db.AutoMigrate(&model.User{})
|
||||
|
||||
e := echo.New()
|
||||
e.Use(session.Middleware(sessions.NewCookieStore([]byte("secret"))))
|
||||
router.RegisterControllers(e)
|
||||
|
||||
if err := e.Start(fmt.Sprintf("%s:%d", conf.Server.Address, conf.Server.Port)); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
12
config.ini
Normal file
12
config.ini
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[server]
|
||||
port = 1324
|
||||
address = "127.0.0.1"
|
||||
|
||||
[security]
|
||||
secret = "e93865c991358ff7a14f9781fa33ba4f28c33bb8d1cf3490ce6fd68521513536"
|
||||
|
||||
[log]
|
||||
level = "debug"
|
||||
|
||||
[database]
|
||||
dsn = "root:root@tcp(127.0.0.1:3306)/budget"
|
||||
55
config/config.go
Normal file
55
config/config.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
type database struct {
|
||||
Dsn string
|
||||
}
|
||||
|
||||
type logging struct {
|
||||
Level string
|
||||
}
|
||||
|
||||
type security struct {
|
||||
Secret string
|
||||
}
|
||||
|
||||
type server struct {
|
||||
Address string
|
||||
Port int
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Database database
|
||||
Log logging
|
||||
Security security
|
||||
Server server
|
||||
}
|
||||
|
||||
var config *Config
|
||||
|
||||
func Get() *Config {
|
||||
if config == nil {
|
||||
config = &Config{}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
func (c *Config) Load(file string) {
|
||||
cfg, err := ini.Load(file)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
config.Database.Dsn = cfg.Section("database").Key("dsn").String()
|
||||
config.Log.Level = cfg.Section("log").Key("level").String()
|
||||
config.Security.Secret = cfg.Section("security").Key("secret").String()
|
||||
config.Server.Address = cfg.Section("server").Key("address").String()
|
||||
config.Server.Port, _ = cfg.Section("server").Key("port").Int()
|
||||
}
|
||||
60
database/manager/manager.go
Normal file
60
database/manager/manager.go
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package manager
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gitnet.fr/deblan/budget/config"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
lg "gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
Db *gorm.DB
|
||||
}
|
||||
|
||||
var manager *Manager
|
||||
|
||||
func Get() *Manager {
|
||||
if manager == nil {
|
||||
manager = &Manager{}
|
||||
config := config.Get()
|
||||
dsn := config.Database.Dsn
|
||||
|
||||
var logLevel lg.LogLevel
|
||||
|
||||
if config.Log.Level == "debug" {
|
||||
logLevel = lg.Info
|
||||
} else if config.Log.Level == "warning" {
|
||||
logLevel = lg.Warn
|
||||
} else if config.Log.Level == "quiet" {
|
||||
logLevel = lg.Silent
|
||||
} else {
|
||||
logLevel = lg.Silent
|
||||
}
|
||||
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
Logger: logger.New(
|
||||
log.New(os.Stdout, "\r\n", log.LstdFlags),
|
||||
lg.Config{
|
||||
SlowThreshold: time.Second,
|
||||
LogLevel: lg.LogLevel(logLevel),
|
||||
IgnoreRecordNotFoundError: true,
|
||||
ParameterizedQueries: true,
|
||||
Colorful: true,
|
||||
},
|
||||
),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
manager.Db = db
|
||||
}
|
||||
|
||||
return manager
|
||||
}
|
||||
69
database/model/user.go
Normal file
69
database/model/user.go
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo-contrib/session"
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
Username string `gorm:"unique"`
|
||||
Password string
|
||||
DisplayName string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func NewUser(username, password, displayName string) *User {
|
||||
user := User{
|
||||
Username: username,
|
||||
DisplayName: displayName,
|
||||
}
|
||||
|
||||
user.UpdatePassword(password)
|
||||
|
||||
return &user
|
||||
}
|
||||
|
||||
func (u *User) UpdatePassword(password string) {
|
||||
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), 1000)
|
||||
|
||||
u.Password = string(hashedPassword)
|
||||
}
|
||||
|
||||
func (u *User) HasPassword(password string) bool {
|
||||
return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) == nil
|
||||
}
|
||||
|
||||
func LoadSessionUser(c echo.Context) *User {
|
||||
sess, err := session.Get("session", c)
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
value := sess.Values["user"]
|
||||
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
id := value.(uint)
|
||||
|
||||
var count int64
|
||||
db := manager.Get()
|
||||
db.Db.Model(User{}).Where("id = ?", id).Count(&count)
|
||||
|
||||
if count == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var user User
|
||||
manager.Get().Db.Model(User{}).Where("id = ?", id).Find(&user)
|
||||
|
||||
return &user
|
||||
}
|
||||
40
go.mod
Normal file
40
go.mod
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
module gitnet.fr/deblan/budget
|
||||
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/manifoldco/promptui v0.9.0
|
||||
github.com/urfave/cli/v2 v2.27.4
|
||||
golang.org/x/crypto v0.27.0
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gorm.io/driver/mysql v1.5.7
|
||||
gorm.io/gorm v1.25.12
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/a-h/templ v0.2.778 // indirect
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/gorilla/context v1.1.2 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/gorilla/sessions v1.4.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/labstack/echo-contrib v0.17.1 // indirect
|
||||
github.com/labstack/echo/v4 v4.12.0 // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
golang.org/x/net v0.28.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
)
|
||||
90
go.sum
Normal file
90
go.sum
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM=
|
||||
github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
|
||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
|
||||
github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM=
|
||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
||||
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/labstack/echo-contrib v0.17.1 h1:7I/he7ylVKsDUieaGRZ9XxxTYOjfQwVzHzUYrNykfCU=
|
||||
github.com/labstack/echo-contrib v0.17.1/go.mod h1:SnsCZtwHBAZm5uBSAtQtXQHI3wqEA73hvTn0bYMKnZA=
|
||||
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8=
|
||||
github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
49
view/template/auth/login.templ
Normal file
49
view/template/auth/login.templ
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package auth
|
||||
|
||||
import "gitnet.fr/deblan/budget/view/template"
|
||||
|
||||
templ Page(hasError bool) {
|
||||
<!doctype html>
|
||||
<html>
|
||||
@template.Head("Login")
|
||||
<body>
|
||||
<section class="vh-100 gradient-custom">
|
||||
<div class="container py-5 h-100">
|
||||
<div class="row d-flex justify-content-center align-items-center h-100">
|
||||
<div class="col-12 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card bg-dark text-white" style="border-radius: 1rem;">
|
||||
<div class="card-body p-5">
|
||||
<div class="mb-md-5 mt-md-4 pb-5">
|
||||
<form action="/login" method="POST">
|
||||
if hasError {
|
||||
<div class="alert alert-danger">
|
||||
Mauvais identifiants.
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="form-outline form-white mb-4">
|
||||
<label class="form-label" for="username">Nom d'utilisateur</label>
|
||||
<input type="text" name="username" id="username" class="form-control form-control-lg" />
|
||||
</div>
|
||||
|
||||
<div class="form-outline form-white mb-4">
|
||||
<label class="form-label" for="password">Mot de passe</label>
|
||||
<input type="password" name="password" id="password" class="form-control form-control-lg" />
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<input class="btn btn-lg btn-primary" type="submit" value="Login" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@template.JS()
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
63
view/template/auth/login_templ.go
Normal file
63
view/template/auth/login_templ.go
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.747
|
||||
package auth
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "gitnet.fr/deblan/budget/view/template"
|
||||
|
||||
func Page(hasError bool) 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
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = template.Head("Login").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if hasError {
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = template.JS().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
5
view/template/auth/login_templ.txt
Normal file
5
view/template/auth/login_templ.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<!doctype html><html>
|
||||
<body><section class=\"vh-100 gradient-custom\"><div class=\"container py-5 h-100\"><div class=\"row d-flex justify-content-center align-items-center h-100\"><div class=\"col-12 col-md-8 col-lg-6 col-xl-5\"><div class=\"card bg-dark text-white\" style=\"border-radius: 1rem;\"><div class=\"card-body p-5\"><div class=\"mb-md-5 mt-md-4 pb-5\"><form action=\"/login\" method=\"POST\">
|
||||
<div class=\"alert alert-danger\">Mauvais identifiants.</div>
|
||||
<div class=\"form-outline form-white mb-4\"><label class=\"form-label\" for=\"username\">Nom d'utilisateur</label> <input type=\"text\" name=\"username\" id=\"username\" class=\"form-control form-control-lg\"></div><div class=\"form-outline form-white mb-4\"><label class=\"form-label\" for=\"password\">Mot de passe</label> <input type=\"password\" name=\"password\" id=\"password\" class=\"form-control form-control-lg\"></div><div class=\"d-grid gap-2\"><input class=\"btn btn-lg btn-primary\" type=\"submit\" value=\"Login\"></div></form></div></div></div></div></div></div></section>
|
||||
</body></html>
|
||||
20
view/template/base.templ
Normal file
20
view/template/base.templ
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package template
|
||||
|
||||
templ Head(title string) {
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{ title }</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
<style>
|
||||
.gradient-custom {
|
||||
background: linear-gradient(to right, rgba(106, 17, 203, 1), rgba(37, 117, 252, 1))
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
}
|
||||
|
||||
templ JS() {
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
|
||||
<script src="main.js"></script>
|
||||
}
|
||||
74
view/template/base_templ.go
Normal file
74
view/template/base_templ.go
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.747
|
||||
package template
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func Head(title string) 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
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/template/base.templ`, Line: 7, Col: 16}
|
||||
}
|
||||
_, 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.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func JS() 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
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
3
view/template/base_templ.txt
Normal file
3
view/template/base_templ.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>
|
||||
</title><link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN\" crossorigin=\"anonymous\"><style>\n\t\t\t.gradient-custom {\n\t\t\t\tbackground: linear-gradient(to right, rgba(106, 17, 203, 1), rgba(37, 117, 252, 1))\n\t\t\t}\n\t\t</style></head>
|
||||
<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL\" crossorigin=\"anonymous\"></script><script src=\"main.js\"></script>
|
||||
15
view/template/home/page.templ
Normal file
15
view/template/home/page.templ
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package home
|
||||
|
||||
import "gitnet.fr/deblan/budget/view/template"
|
||||
|
||||
templ Page() {
|
||||
<!doctype html>
|
||||
<html>
|
||||
@template.Head("Login")
|
||||
<body>
|
||||
Home!
|
||||
|
||||
@template.JS()
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
53
view/template/home/page_templ.go
Normal file
53
view/template/home/page_templ.go
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.747
|
||||
package home
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "gitnet.fr/deblan/budget/view/template"
|
||||
|
||||
func Page() 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
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = template.Head("Login").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = template.JS().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
3
view/template/home/page_templ.txt
Normal file
3
view/template/home/page_templ.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<!doctype html><html>
|
||||
<body>Home!
|
||||
</body></html>
|
||||
17
view/view.go
Normal file
17
view/view.go
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func Render(ctx echo.Context, statusCode int, t templ.Component) error {
|
||||
buf := templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(buf)
|
||||
|
||||
if err := t.Render(ctx.Request().Context(), buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ctx.HTML(statusCode, buf.String())
|
||||
}
|
||||
63
web/controller/auth/controller.go
Normal file
63
web/controller/auth/controller.go
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"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/view"
|
||||
"gitnet.fr/deblan/budget/view/template/auth"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
}
|
||||
|
||||
func New(e *echo.Echo) *Controller {
|
||||
c := Controller{}
|
||||
|
||||
e.GET("/login", c.LoginGet)
|
||||
e.POST("/login", c.LoginPost)
|
||||
e.GET("/logout", c.LogoutGet)
|
||||
|
||||
return &c
|
||||
}
|
||||
|
||||
func (ctrl *Controller) LoginGet(c echo.Context) error {
|
||||
return view.Render(c, 200, auth.Page(false))
|
||||
}
|
||||
|
||||
func (ctrl *Controller) LoginPost(c echo.Context) error {
|
||||
username := c.FormValue("username")
|
||||
password := c.FormValue("password")
|
||||
|
||||
var count int64
|
||||
db := manager.Get()
|
||||
db.Db.Model(model.User{}).Where("username = ?", username).Count(&count)
|
||||
|
||||
if count > 0 {
|
||||
var user model.User
|
||||
db.Db.Model(model.User{}).Where("username = ?", username).Find(&user)
|
||||
|
||||
if user.HasPassword(password) {
|
||||
sess, _ := session.Get("session", c)
|
||||
sess.Options = &sessions.Options{
|
||||
Path: "/",
|
||||
MaxAge: 86400 * 7,
|
||||
HttpOnly: true,
|
||||
}
|
||||
sess.Values["user"] = user.ID
|
||||
sess.Save(c.Request(), c.Response())
|
||||
|
||||
return c.Redirect(302, "/")
|
||||
}
|
||||
}
|
||||
|
||||
return view.Render(c, 200, auth.Page(true))
|
||||
}
|
||||
|
||||
func (ctrl *Controller) LogoutGet(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "Hello, World!")
|
||||
}
|
||||
27
web/controller/home/controller.go
Normal file
27
web/controller/home/controller.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package home
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/view"
|
||||
"gitnet.fr/deblan/budget/view/template/home"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
}
|
||||
|
||||
func New(e *echo.Echo) *Controller {
|
||||
c := Controller{}
|
||||
|
||||
e.GET("/", c.HomeGet)
|
||||
|
||||
return &c
|
||||
}
|
||||
|
||||
func (ctrl *Controller) HomeGet(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
}
|
||||
|
||||
return view.Render(c, 200, home.Page())
|
||||
}
|
||||
12
web/router/router.go
Normal file
12
web/router/router.go
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/web/controller/auth"
|
||||
"gitnet.fr/deblan/budget/web/controller/home"
|
||||
)
|
||||
|
||||
func RegisterControllers(e *echo.Echo) {
|
||||
auth.New(e)
|
||||
home.New(e)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue