Compare commits
1 Commits
50187f5a34
...
login
| Author | SHA1 | Date | |
|---|---|---|---|
| 7730257cce |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
|||||||
/.vscode
|
/.vscode
|
||||||
/__debug*
|
/__debug*
|
||||||
/build
|
|
||||||
/tmp
|
/tmp
|
||||||
/config.yaml
|
/config.yaml
|
||||||
|
|||||||
6
Makefile
6
Makefile
@ -1,8 +1,2 @@
|
|||||||
EXEC=iris-test
|
|
||||||
|
|
||||||
run:
|
run:
|
||||||
@air
|
@air
|
||||||
|
|
||||||
.PHONY: build
|
|
||||||
build:
|
|
||||||
@go build -ldflags "-s -w" -o ./build/${EXEC} ./app/main.go
|
|
||||||
|
|||||||
52
README.md
52
README.md
@ -11,55 +11,3 @@
|
|||||||
- [Source](https://github.com/CloudyKit/jet)
|
- [Source](https://github.com/CloudyKit/jet)
|
||||||
- [Syntax reference](https://github.com/CloudyKit/jet/blob/master/docs/syntax.md)
|
- [Syntax reference](https://github.com/CloudyKit/jet/blob/master/docs/syntax.md)
|
||||||
|
|
||||||
## Howto
|
|
||||||
|
|
||||||
- [Password Hashing (bcrypt)](https://gowebexamples.com/password-hashing/)
|
|
||||||
|
|
||||||
|
|
||||||
## Tools
|
|
||||||
|
|
||||||
- [Bombardier benchmarking](https://github.com/codesenberg/bombardier)
|
|
||||||
|
|
||||||
|
|
||||||
## Bombardier benchmark
|
|
||||||
|
|
||||||
Pandora - Jet templating engine
|
|
||||||
|
|
||||||
```
|
|
||||||
eden@pandora:[~/apps/sandbox/golang/iris-web-framework]: bombardier -c 100 -d 10s -l http://localhost:8000 ±[A1][main]
|
|
||||||
Bombarding http://localhost:8000 for 10s using 100 connection(s)
|
|
||||||
Done!
|
|
||||||
Statistics Avg Stdev Max
|
|
||||||
Reqs/sec 10542.16 2631.23 17296.86
|
|
||||||
Latency 9.50ms 3.22ms 42.93ms
|
|
||||||
Latency Distribution
|
|
||||||
50% 8.77ms
|
|
||||||
75% 11.86ms
|
|
||||||
90% 15.31ms
|
|
||||||
95% 17.86ms
|
|
||||||
99% 23.90ms
|
|
||||||
HTTP codes:
|
|
||||||
1xx - 0, 2xx - 105258, 3xx - 0, 4xx - 0, 5xx - 0
|
|
||||||
others - 0
|
|
||||||
Throughput: 28.08MB/s
|
|
||||||
```
|
|
||||||
```
|
|
||||||
eden@pandora:[~/apps/sandbox/golang/iris-web-framework]: bombardier -c 100 -d 10s -l http://localhost:8000/users ±[A1][main]
|
|
||||||
Bombarding http://localhost:8000/users for 10s using 100 connection(s)
|
|
||||||
Done!
|
|
||||||
Statistics Avg Stdev Max
|
|
||||||
Reqs/sec 1096.26 427.09 3211.54
|
|
||||||
Latency 91.08ms 80.06ms 471.41ms
|
|
||||||
Latency Distribution
|
|
||||||
50% 78.37ms
|
|
||||||
75% 156.58ms
|
|
||||||
90% 191.60ms
|
|
||||||
95% 223.49ms
|
|
||||||
99% 309.59ms
|
|
||||||
HTTP codes:
|
|
||||||
1xx - 0, 2xx - 11060, 3xx - 0, 4xx - 0, 5xx - 0
|
|
||||||
others - 0
|
|
||||||
Throughput: 19.91MB/s
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package cfg
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -1,9 +1,7 @@
|
|||||||
package db
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"iris-test/app/lib/cfg"
|
|
||||||
"iris-test/app/lib/logging"
|
|
||||||
"iris-test/app/repository"
|
"iris-test/app/repository"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -22,18 +20,18 @@ var DBConn *gorm.DB
|
|||||||
func InitDB() *gorm.DB {
|
func InitDB() *gorm.DB {
|
||||||
var connectionString = strings.Join([]string{
|
var connectionString = strings.Join([]string{
|
||||||
"postgres://",
|
"postgres://",
|
||||||
cfg.Config.Database.Username, ":",
|
Config.Database.Username, ":",
|
||||||
cfg.Config.Database.Password, "@",
|
Config.Database.Password, "@",
|
||||||
cfg.Config.Database.Host, ":",
|
Config.Database.Host, ":",
|
||||||
cfg.Config.Database.Port, "/",
|
Config.Database.Port, "/",
|
||||||
cfg.Config.Database.Name,
|
Config.Database.Name,
|
||||||
"?sslmode=disable",
|
"?sslmode=disable",
|
||||||
"&TimeZone=UTC",
|
"&TimeZone=UTC",
|
||||||
"&connect_timeout=", strconv.Itoa(DB_CONNECTION_TIMEOUT),
|
"&connect_timeout=", strconv.Itoa(DB_CONNECTION_TIMEOUT),
|
||||||
}, "")
|
}, "")
|
||||||
|
|
||||||
var logLevel = gormLogger.Silent
|
var logLevel = gormLogger.Silent
|
||||||
if cfg.Config.Application.DebugSQL {
|
if Config.Application.DebugSQL {
|
||||||
logLevel = gormLogger.Info
|
logLevel = gormLogger.Info
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +41,7 @@ func InitDB() *gorm.DB {
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Error connecting to database: %s. Terminating!", err)
|
msg := fmt.Sprintf("Error connecting to database: %s. Terminating!", err)
|
||||||
logging.Error(msg)
|
Log.Error(msg)
|
||||||
panic(msg)
|
panic(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1 +0,0 @@
|
|||||||
package auth
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
package auth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// about bcrypt cost: https://docs.laminas.dev/laminas-crypt/password/#bcrypt
|
|
||||||
// bcrypt cost benchmarks: https://github.com/nsmithuk/bcrypt-cost-go
|
|
||||||
const BCRYPT_COST = 10
|
|
||||||
const MIN_PASSWORD_LENGTH = 10
|
|
||||||
|
|
||||||
func IsPasswordGoodEnough(password string) bool {
|
|
||||||
var re *regexp.Regexp
|
|
||||||
passwordBytes := []byte(password)
|
|
||||||
|
|
||||||
if len(password) < MIN_PASSWORD_LENGTH {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
re, _ = regexp.Compile("[a-z]")
|
|
||||||
if re.Find(passwordBytes) == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
re, _ = regexp.Compile("[A-Z]")
|
|
||||||
if re.Find(passwordBytes) == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
re, _ = regexp.Compile("[0-9]")
|
|
||||||
//lint:ignore S1008 allow early exit instead optimization
|
|
||||||
if re.Find(passwordBytes) == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func HashPassword(password string, secretKey string) (string, error) {
|
|
||||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password+secretKey), BCRYPT_COST)
|
|
||||||
return string(bytes), err
|
|
||||||
}
|
|
||||||
@ -1,10 +1,9 @@
|
|||||||
package logging
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"iris-test/app/lib/cfg"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -29,9 +28,9 @@ func Warn(message string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func InitLogging() {
|
func InitLogging() {
|
||||||
logLevel, err := logrus.ParseLevel(cfg.Config.Application.LogLevel)
|
logLevel, err := logrus.ParseLevel(Config.Application.LogLevel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Invalid configured logLevel: %s\n", cfg.Config.Application.LogLevel))
|
panic(fmt.Sprintf("Invalid configured logLevel: %s\n", Config.Application.LogLevel))
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.SetLevel(logLevel)
|
Log.SetLevel(logLevel)
|
||||||
@ -43,14 +42,14 @@ func InitLogging() {
|
|||||||
DisableQuote: true,
|
DisableQuote: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
LogFile := cfg.Config.Application.LogFile
|
LogFile := Config.Application.LogFile
|
||||||
file, err := os.OpenFile(
|
file, err := os.OpenFile(
|
||||||
LogFile,
|
LogFile,
|
||||||
os.O_CREATE|os.O_WRONLY|os.O_APPEND,
|
os.O_CREATE|os.O_WRONLY|os.O_APPEND,
|
||||||
0655,
|
0655,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Failed to log to file %s: %s", cfg.Config.Application.LogFile, err)
|
msg := fmt.Sprintf("Failed to log to file %s: %s", Config.Application.LogFile, err)
|
||||||
Log.Warning(msg)
|
Log.Warning(msg)
|
||||||
panic(msg)
|
panic(msg)
|
||||||
}
|
}
|
||||||
@ -58,7 +57,7 @@ func InitLogging() {
|
|||||||
mw := io.MultiWriter(os.Stdout, file)
|
mw := io.MultiWriter(os.Stdout, file)
|
||||||
Log.SetOutput(mw)
|
Log.SetOutput(mw)
|
||||||
|
|
||||||
configJson, err := json.Marshal(cfg.Config)
|
configJson, err := json.Marshal(Config)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
Info(fmt.Sprintf("Using config: %s", configJson))
|
Info(fmt.Sprintf("Using config: %s", configJson))
|
||||||
}
|
}
|
||||||
27
app/main.go
27
app/main.go
@ -2,9 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"iris-test/app/lib/cfg"
|
|
||||||
"iris-test/app/lib/db"
|
|
||||||
"iris-test/app/lib/logging"
|
|
||||||
"iris-test/app/views"
|
"iris-test/app/views"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
@ -18,32 +15,32 @@ import (
|
|||||||
var redisDB *redis.Database
|
var redisDB *redis.Database
|
||||||
|
|
||||||
func createSessionEngine() *sessions.Sessions {
|
func createSessionEngine() *sessions.Sessions {
|
||||||
redisAddr := fmt.Sprintf("%s:%d", cfg.Config.Redis.Host, cfg.Config.Redis.Port)
|
redisAddr := fmt.Sprintf("%s:%d", Config.Redis.Host, Config.Redis.Port)
|
||||||
|
|
||||||
redisDB = redis.New(redis.Config{
|
redisDB = redis.New(redis.Config{
|
||||||
Network: "tcp",
|
Network: "tcp",
|
||||||
Addr: redisAddr,
|
Addr: redisAddr,
|
||||||
Timeout: time.Duration(30) * time.Second,
|
Timeout: time.Duration(30) * time.Second,
|
||||||
MaxActive: 10,
|
MaxActive: 10,
|
||||||
Username: cfg.Config.Redis.Username,
|
Username: Config.Redis.Username,
|
||||||
Password: cfg.Config.Redis.Password,
|
Password: Config.Redis.Password,
|
||||||
Database: cfg.Config.Redis.Database,
|
Database: Config.Redis.Database,
|
||||||
Prefix: cfg.Config.Redis.Prefix,
|
Prefix: Config.Redis.Prefix,
|
||||||
Driver: redis.GoRedis(), // defaults to this driver.
|
Driver: redis.GoRedis(), // defaults to this driver.
|
||||||
// To set a custom, existing go-redis client, use the "SetClient" method:
|
// To set a custom, existing go-redis client, use the "SetClient" method:
|
||||||
// Driver: redis.GoRedis().SetClient(customGoRedisClient)
|
// Driver: redis.GoRedis().SetClient(customGoRedisClient)
|
||||||
})
|
})
|
||||||
|
|
||||||
sessionsEngine := sessions.New(sessions.Config{
|
sessions_engine := sessions.New(sessions.Config{
|
||||||
Cookie: "_session_id",
|
Cookie: "_session_id",
|
||||||
Expires: 0, // defaults to 0: unlimited life. Another good value is: 45 * time.Minute,
|
Expires: 0, // defaults to 0: unlimited life. Another good value is: 45 * time.Minute,
|
||||||
AllowReclaim: true,
|
AllowReclaim: true,
|
||||||
CookieSecureTLS: true,
|
CookieSecureTLS: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
sessionsEngine.UseDatabase(redisDB)
|
sessions_engine.UseDatabase(redisDB)
|
||||||
|
|
||||||
return sessionsEngine
|
return sessions_engine
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAccessLog() *accesslog.AccessLog {
|
func createAccessLog() *accesslog.AccessLog {
|
||||||
@ -86,7 +83,7 @@ func createApp() *iris.Application {
|
|||||||
accessLog := createAccessLog()
|
accessLog := createAccessLog()
|
||||||
|
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
app.Logger().SetLevel(cfg.Config.Application.LogLevel)
|
app.Logger().SetLevel(Config.Application.LogLevel)
|
||||||
app.Use(sessionsEngine.Handler())
|
app.Use(sessionsEngine.Handler())
|
||||||
app.UseRouter(accessLog.Handler)
|
app.UseRouter(accessLog.Handler)
|
||||||
app.RegisterView(iris.Jet("./app/templates", ".jet").Reload(true))
|
app.RegisterView(iris.Jet("./app/templates", ".jet").Reload(true))
|
||||||
@ -95,9 +92,9 @@ func createApp() *iris.Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfg.InitCfg()
|
InitCfg()
|
||||||
logging.InitLogging()
|
InitLogging()
|
||||||
db.InitDB()
|
InitDB()
|
||||||
|
|
||||||
app := createApp()
|
app := createApp()
|
||||||
defer redisDB.Close()
|
defer redisDB.Close()
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import "time"
|
||||||
"iris-test/app/lib/auth"
|
|
||||||
"iris-test/app/lib/cfg"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Id string `gorm:"type(uuid);unique"`
|
Id string `gorm:"type(uuid);unique"`
|
||||||
@ -20,13 +16,3 @@ type User struct {
|
|||||||
func (u *User) TableName() string {
|
func (u *User) TableName() string {
|
||||||
return "users"
|
return "users"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) SetPassword(password string) error {
|
|
||||||
secretKey := cfg.Config.Application.SecretKey
|
|
||||||
hashedPassword, err := auth.HashPassword(password, secretKey)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
u.Password = hashedPassword
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@ -12,7 +12,6 @@ type UsersRepository struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserFilter struct {
|
type UserFilter struct {
|
||||||
Id *string
|
|
||||||
IsActive *bool
|
IsActive *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,14 +22,9 @@ func CreateUsersRepository(db *gorm.DB) *UsersRepository {
|
|||||||
func applyFilter(db *gorm.DB, filter *UserFilter) *gorm.DB {
|
func applyFilter(db *gorm.DB, filter *UserFilter) *gorm.DB {
|
||||||
query := db
|
query := db
|
||||||
|
|
||||||
if filter.Id != nil {
|
// if filter.State != "" {
|
||||||
query = query.Where("id = ?", filter.Id)
|
// query = query.Where("state = ?", filter.State)
|
||||||
}
|
// }
|
||||||
|
|
||||||
if filter.IsActive != nil {
|
|
||||||
query = query.Where(map[string]interface{}{"is_active": filter.IsActive})
|
|
||||||
}
|
|
||||||
|
|
||||||
// if filter.SendAt_lt != nil {
|
// if filter.SendAt_lt != nil {
|
||||||
// query = query.Where("send_at < ?", filter.SendAt_lt)
|
// query = query.Where("send_at < ?", filter.SendAt_lt)
|
||||||
// }
|
// }
|
||||||
@ -75,18 +69,3 @@ func (repository *UsersRepository) List(filter *UserFilter, pagination *Paginati
|
|||||||
|
|
||||||
return &users
|
return &users
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repository *UsersRepository) Get(filter *UserFilter) *models.User {
|
|
||||||
var user models.User
|
|
||||||
|
|
||||||
query := repository.db.Model(&models.User{})
|
|
||||||
query = applyFilter(query, filter)
|
|
||||||
query.First(&user)
|
|
||||||
|
|
||||||
return &user
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repository *UsersRepository) Save(user *models.User) *models.User {
|
|
||||||
repository.db.Save(user)
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|||||||
@ -10,20 +10,14 @@
|
|||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container mt-3">
|
<div class="container">
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
|
|
||||||
<ul class="nav">
|
<p>
|
||||||
<li class="nav-item">
|
<a href="/">Frontpage</a>
|
||||||
<a href="/" class="nav-link">Frontpage</a>
|
<a href="/users">Users</a>
|
||||||
</li>
|
<a href="/about">About</a>
|
||||||
<li class="nav-item">
|
</p>
|
||||||
<a href="/users" class="nav-link">Users</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="/about" class="nav-link">About</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
{{ yield mainContent() }}
|
{{ yield mainContent() }}
|
||||||
|
|||||||
@ -1,19 +1,10 @@
|
|||||||
{{ block usersTable(users) }}
|
{{ block usersTable(users) }}
|
||||||
<table class="table table-hover">
|
<p>blablabla</p>
|
||||||
<thead>
|
|
||||||
<tr>
|
<table class="table">
|
||||||
<th>ID</th>
|
|
||||||
<th>First name</th>
|
|
||||||
<th>Last name</th>
|
|
||||||
<th>Email</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{{ range users }}
|
{{ range users }}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
|
||||||
<a href="/users/{{ .Id }}">{{ .Id }}</a>
|
|
||||||
</td>
|
|
||||||
<td>{{ .FirstName }}</td>
|
<td>{{ .FirstName }}</td>
|
||||||
<td>{{ .LastName }}</td>
|
<td>{{ .LastName }}</td>
|
||||||
<td>{{ .Email }}</td>
|
<td>{{ .Email }}</td>
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
{{ extends "/base/base.jet" }}
|
|
||||||
{{ import "/components/table_component.jet" }}
|
|
||||||
|
|
||||||
|
|
||||||
{{ block mainContent() }}
|
|
||||||
<h3>Edit user</h3>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<form class="mb-5 col-4 ms-auto me-auto" method="post" action="{{ .currentPath }}">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">First name</label>
|
|
||||||
<input type="text" name="first-name" class="form-control" value="{{ user.FirstName }}" required>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Last name</label>
|
|
||||||
<input type="text" name="last-name" class="form-control" value="{{ user.LastName }}" required>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Email</label>
|
|
||||||
<input type="email" name="email" class="form-control" value="{{ user.Email }}" required>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Password</label>
|
|
||||||
<input type="text" name="password" class="form-control">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="d-flex">
|
|
||||||
<a href="/users" class="btn btn-outline-secondary ms-auto me-2">
|
|
||||||
Cancel
|
|
||||||
</a>
|
|
||||||
<button type="submit" class="btn btn-success">
|
|
||||||
Save
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
@ -3,7 +3,13 @@
|
|||||||
|
|
||||||
|
|
||||||
{{ block mainContent() }}
|
{{ block mainContent() }}
|
||||||
<h3>Users</h3>
|
<ul>
|
||||||
|
{{ range params1 }}
|
||||||
|
<li>{{ . }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>{{ title }}</h3>
|
||||||
|
|
||||||
{{ yield usersTable(users=users) }}
|
{{ yield usersTable(users=users) }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
@ -7,8 +7,5 @@ func CreateRouter(app *iris.Application) {
|
|||||||
app.Post("/", PostIndexPage)
|
app.Post("/", PostIndexPage)
|
||||||
|
|
||||||
app.Get("/users", GetUsersPage)
|
app.Get("/users", GetUsersPage)
|
||||||
app.Get("/users/{userId:uuid}", EditUserPage)
|
|
||||||
app.Post("/users/{userId:uuid}", SaveUserPage)
|
|
||||||
|
|
||||||
app.Get("/about", GetAboutPage)
|
app.Get("/about", GetAboutPage)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,15 @@
|
|||||||
package views
|
package views
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"iris-test/app/lib/auth"
|
|
||||||
"iris-test/app/repository"
|
"iris-test/app/repository"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12"
|
"github.com/kataras/iris/v12"
|
||||||
)
|
)
|
||||||
|
|
||||||
type editUserForm struct {
|
|
||||||
FirstName string `form:"first-name"`
|
|
||||||
LastName string `form:"last-name"`
|
|
||||||
Email string `form:"email"`
|
|
||||||
Password string `form:"password"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUsersPage(ctx iris.Context) {
|
func GetUsersPage(ctx iris.Context) {
|
||||||
|
params1 := []string{"param 1", "param 2", "param 3"}
|
||||||
|
ctx.ViewData("params1", params1)
|
||||||
|
|
||||||
userRepository := repository.Dao.UsersRepository
|
userRepository := repository.Dao.UsersRepository
|
||||||
|
|
||||||
pagination := repository.NewPagination()
|
pagination := repository.NewPagination()
|
||||||
@ -24,8 +18,7 @@ func GetUsersPage(ctx iris.Context) {
|
|||||||
repository.NewOrdering("last_name", repository.ORDERING_ASC),
|
repository.NewOrdering("last_name", repository.ORDERING_ASC),
|
||||||
}
|
}
|
||||||
|
|
||||||
isActive := true
|
users := userRepository.List(&repository.UserFilter{}, &pagination, &ordering)
|
||||||
users := userRepository.List(&repository.UserFilter{IsActive: &isActive}, &pagination, &ordering)
|
|
||||||
|
|
||||||
ctx.ViewData("users", users)
|
ctx.ViewData("users", users)
|
||||||
|
|
||||||
@ -34,49 +27,3 @@ func GetUsersPage(ctx iris.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func EditUserPage(ctx iris.Context) {
|
|
||||||
userId := ctx.Params().Get("userId")
|
|
||||||
userRepository := repository.Dao.UsersRepository
|
|
||||||
|
|
||||||
filter := repository.UserFilter{Id: &userId}
|
|
||||||
user := userRepository.Get(&filter)
|
|
||||||
|
|
||||||
ctx.ViewData("user", user)
|
|
||||||
ctx.ViewData("currentPath", ctx.Path())
|
|
||||||
|
|
||||||
if err := ctx.View("pages/user-edit.jet"); err != nil {
|
|
||||||
showError(ctx, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SaveUserPage(ctx iris.Context) {
|
|
||||||
var form editUserForm
|
|
||||||
err := ctx.ReadForm(&form)
|
|
||||||
if err != nil {
|
|
||||||
ctx.StopWithError(iris.StatusBadRequest, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userId := ctx.Params().Get("userId")
|
|
||||||
userRepository := repository.Dao.UsersRepository
|
|
||||||
|
|
||||||
filter := repository.UserFilter{Id: &userId}
|
|
||||||
user := userRepository.Get(&filter)
|
|
||||||
|
|
||||||
user.FirstName = form.FirstName
|
|
||||||
user.LastName = form.LastName
|
|
||||||
user.Email = form.Email
|
|
||||||
|
|
||||||
if len(form.Password) > 0 {
|
|
||||||
user.SetPassword(form.Password)
|
|
||||||
fmt.Printf("Set password: %s\n", user.Password)
|
|
||||||
fmt.Printf("IsPasswordGoodEnough: %v\n", auth.IsPasswordGoodEnough(form.Password))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
userRepository.Save(user)
|
|
||||||
|
|
||||||
ctx.Redirect("/users")
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user