Add debug mode to log
This commit is contained in:
parent
ba31bc24a6
commit
c22cf9e7c8
7 changed files with 56 additions and 9 deletions
2
Makefile
2
Makefile
|
@ -5,4 +5,4 @@ serve:
|
||||||
go build && ./pye serve
|
go build && ./pye serve
|
||||||
|
|
||||||
dev:
|
dev:
|
||||||
go build && ./pye serve --db dev-data.db
|
go build && ./pye serve --db dev-data.db --debug
|
10
README.md
10
README.md
|
@ -11,15 +11,17 @@ in a state that proves I am competent Go developer.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
## `pye serve [--config] [--port] [--db]`
|
## JWT server
|
||||||
|
|
||||||
Serve a simple JWT auth system
|
Serve a simple JWT auth system
|
||||||
|
**Usage**: `pye serve [--config] [--port] [--db]`
|
||||||
|
|
||||||
* `POST /register` - register a user with Basic Auth
|
* `POST /register` - register a user with Basic Auth
|
||||||
* `POST /login` - get a JWT token by Basic Auth
|
* `POST /login` - get a JWT token by Basic Auth
|
||||||
* `GET /pem` - get PEM-encoded public RS256 key
|
* `GET /pem` - get PEM-encoded public RS256 key
|
||||||
* Data and RS256 key persistently stored in an SQLite database and a PEM file
|
* Data and RS256 key persistently stored in an SQLite database and a PEM file
|
||||||
|
|
||||||
## `pye verify <jwt> <pem file>`
|
## JWT verification
|
||||||
|
|
||||||
Verify a JWT with a public key from a PEM file
|
Verify a JWT with a public key from a PEM file
|
||||||
|
**Usage**: `pye verify <jwt> <pem_file>`
|
|
@ -9,16 +9,19 @@ import (
|
||||||
"git.a71.su/Andrew71/pye/cmd/serve"
|
"git.a71.su/Andrew71/pye/cmd/serve"
|
||||||
"git.a71.su/Andrew71/pye/cmd/verify"
|
"git.a71.su/Andrew71/pye/cmd/verify"
|
||||||
"git.a71.su/Andrew71/pye/config"
|
"git.a71.su/Andrew71/pye/config"
|
||||||
|
"git.a71.su/Andrew71/pye/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run() {
|
func Run() {
|
||||||
|
|
||||||
serveCmd := flag.NewFlagSet("serve", flag.ExitOnError)
|
serveCmd := flag.NewFlagSet("serve", flag.ExitOnError)
|
||||||
serveConfig := serveCmd.String("config", "", "override config file")
|
serveConfig := serveCmd.String("config", "", "override config file")
|
||||||
servePort := serveCmd.Int("port", 0, "override port")
|
servePort := serveCmd.Int("port", 0, "override port")
|
||||||
serveDb := serveCmd.String("db", "", "override sqlite database")
|
serveDb := serveCmd.String("db", "", "override sqlite database")
|
||||||
|
serveDebug := serveCmd.Bool("debug", false, "debug logging")
|
||||||
|
|
||||||
verifyCmd := flag.NewFlagSet("verify", flag.ExitOnError)
|
verifyCmd := flag.NewFlagSet("verify", flag.ExitOnError)
|
||||||
|
verifyDebug := verifyCmd.Bool("debug", false, "debug logging")
|
||||||
|
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
fmt.Println("expected 'serve' or 'verify' subcommands")
|
fmt.Println("expected 'serve' or 'verify' subcommands")
|
||||||
|
@ -28,6 +31,7 @@ func Run() {
|
||||||
switch os.Args[1] {
|
switch os.Args[1] {
|
||||||
case "serve":
|
case "serve":
|
||||||
serveCmd.Parse(os.Args[2:])
|
serveCmd.Parse(os.Args[2:])
|
||||||
|
logging.LogInit(*serveDebug)
|
||||||
if *serveConfig != "" {
|
if *serveConfig != "" {
|
||||||
err := config.LoadConfig(*serveConfig)
|
err := config.LoadConfig(*serveConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -43,8 +47,9 @@ func Run() {
|
||||||
serve.Serve()
|
serve.Serve()
|
||||||
case "verify":
|
case "verify":
|
||||||
verifyCmd.Parse(os.Args[2:])
|
verifyCmd.Parse(os.Args[2:])
|
||||||
|
logging.LogInit(*verifyDebug)
|
||||||
if len(os.Args) != 4 {
|
if len(os.Args) != 4 {
|
||||||
fmt.Println("Usage: <jwt> <pem file>")
|
fmt.Println("Usage: <jwt> <pem file> [--debug]")
|
||||||
}
|
}
|
||||||
verify.Verify(os.Args[2], os.Args[3])
|
verify.Verify(os.Args[2], os.Args[3])
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -28,5 +28,6 @@ func Serve() {
|
||||||
router.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) { auth.Login(w, r, data) })
|
router.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) { auth.Login(w, r, data) })
|
||||||
|
|
||||||
slog.Info("🪐 pye started", "port", config.Cfg.Port)
|
slog.Info("🪐 pye started", "port", config.Cfg.Port)
|
||||||
|
slog.Debug("debug mode active")
|
||||||
http.ListenAndServe(":"+strconv.Itoa(config.Cfg.Port), router)
|
http.ListenAndServe(":"+strconv.Itoa(config.Cfg.Port), router)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,16 @@ type Config struct {
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
KeyFile string `json:"key-file"`
|
KeyFile string `json:"key-file"`
|
||||||
SQLiteFile string `json:"sqlite-file"`
|
SQLiteFile string `json:"sqlite-file"`
|
||||||
|
LogToFile bool `json:"log-to-file"`
|
||||||
|
LogFile string `json:"log-file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultConfig = Config{
|
var DefaultConfig = Config{
|
||||||
Port: 7102,
|
Port: 7102,
|
||||||
KeyFile: "private.key",
|
KeyFile: "private.key",
|
||||||
SQLiteFile: "data.db",
|
SQLiteFile: "data.db",
|
||||||
|
LogToFile: false,
|
||||||
|
LogFile: "pye.log",
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
34
logging/log.go
Normal file
34
logging/log.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.a71.su/Andrew71/pye/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LogInit makes slog output to both os.Stdout and a file if needed, and sets slog.LevelDebug if enabled.
|
||||||
|
func LogInit(debugMode bool) {
|
||||||
|
var w io.Writer
|
||||||
|
if config.Cfg.LogToFile {
|
||||||
|
f, err := os.OpenFile(config.Cfg.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("error opening log file, logging to stdout only", "path", config.Cfg.LogFile, "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// No defer f.Close() because that breaks the MultiWriter
|
||||||
|
w = io.MultiWriter(f, os.Stdout)
|
||||||
|
} else {
|
||||||
|
w = os.Stdout
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make slog use intended format
|
||||||
|
var opts *slog.HandlerOptions
|
||||||
|
if debugMode {
|
||||||
|
opts = &slog.HandlerOptions{Level: slog.LevelDebug}
|
||||||
|
}
|
||||||
|
slog.SetDefault(slog.New(slog.NewTextHandler(w, opts)))
|
||||||
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ const create string = `
|
||||||
PRIMARY KEY("uuid")
|
PRIMARY KEY("uuid")
|
||||||
);`
|
);`
|
||||||
|
|
||||||
|
// SQLiteStorage is a storage.Storage implementation with SQLite3
|
||||||
type SQLiteStorage struct {
|
type SQLiteStorage struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
}
|
}
|
||||||
|
@ -64,14 +65,14 @@ func MustLoadSQLite(dataFile string) SQLiteStorage {
|
||||||
}
|
}
|
||||||
db, err := sql.Open("sqlite3", dataFile)
|
db, err := sql.Open("sqlite3", dataFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("error opening database", "error", err)
|
slog.Error("error opening sqlite3 database", "error", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
statement, err := db.Prepare(create)
|
statement, err := db.Prepare(create)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != "table \"users\" already exists" {
|
if err.Error() != "table \"users\" already exists" {
|
||||||
slog.Info("error initialising database table", "error", err)
|
slog.Info("error initialising sqlite3 database table", "error", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue