Improve initial loading

This commit is contained in:
Andrew-71 2024-10-13 16:38:13 +03:00
parent 1f50b8621e
commit acab4bc68b
8 changed files with 47 additions and 44 deletions

1
.gitignore vendored
View file

@ -1,4 +1,3 @@
pye pye
private.key private.key
dev-data.db
data.db data.db

View file

@ -5,4 +5,4 @@ run:
go build && ./pye serve go build && ./pye serve
dev: dev:
go build && ./pye serve --db dev-data.db --debug go build && ./pye serve --debug

View file

@ -9,19 +9,29 @@ with(out) blazingly fast cloud-native web3 memory-safe blockchain reactive AI
This should be done by **October 17th 2024**. Or, at the very least, This should be done by **October 17th 2024**. Or, at the very least,
in a state that proves I am competent Go developer. in a state that proves I am competent Go developer.
## Commands ## Usage
## JWT server ```
Usage:
pye [command]
Serve a simple JWT auth system Available Commands:
**Usage**: `pye serve [--config] [--port] [--db]` completion Generate the autocompletion script for the specified shell
find Find a user
help Help about any command
serve Start JWT service
verify Verify a JWT token
* `POST /register` - register a user with Basic Auth Flags:
* `POST /login` - get a JWT token by Basic Auth -c, --config string config file (default "config.json")
* `GET /pem` - get PEM-encoded public RS256 key --db string database to use
* Data and RS256 key persistently stored in an SQLite database and a PEM file -d, --debug enable debug mode
-h, --help help for pye
## JWT verification Use "pye [command] --help" for more information about a command.
```
Verify a JWT with a public key from a PEM file ## Technologies used
**Usage**: `pye verify <jwt> <pem_file>`
* **Storage** - [SQLite](https://github.com/mattn/go-sqlite3) and a PEM file
* **CLI management** - [Cobra](https://cobra.dev/)

View file

@ -42,7 +42,7 @@ func MustLoadKey() {
slog.Error("error closing file", "error", err) slog.Error("error closing file", "error", err)
os.Exit(1) os.Exit(1)
} }
slog.Info("generated new key", "file", config.Cfg.KeyFile) slog.Debug("generated new key", "file", config.Cfg.KeyFile)
} else { } else {
km, err := os.ReadFile(config.Cfg.KeyFile) km, err := os.ReadFile(config.Cfg.KeyFile)
if err != nil { if err != nil {
@ -54,14 +54,10 @@ func MustLoadKey() {
slog.Error("error parsing key", "error", err) slog.Error("error parsing key", "error", err)
os.Exit(1) os.Exit(1)
} }
slog.Info("loaded private key", "file", config.Cfg.KeyFile) slog.Debug("loaded private key", "file", config.Cfg.KeyFile)
} }
} }
func init() {
MustLoadKey()
}
// PublicKey returns our public key as PEM block over http // PublicKey returns our public key as PEM block over http
func PublicKey(w http.ResponseWriter, r *http.Request) { func PublicKey(w http.ResponseWriter, r *http.Request) {
key_marshalled := x509.MarshalPKCS1PublicKey(&key.PublicKey) key_marshalled := x509.MarshalPKCS1PublicKey(&key.PublicKey)

View file

@ -2,9 +2,9 @@ package cmd
import ( import (
"fmt" "fmt"
"log/slog"
"os" "os"
"git.a71.su/Andrew71/pye/auth"
"git.a71.su/Andrew71/pye/config" "git.a71.su/Andrew71/pye/config"
"git.a71.su/Andrew71/pye/logging" "git.a71.su/Andrew71/pye/logging"
"git.a71.su/Andrew71/pye/storage" "git.a71.su/Andrew71/pye/storage"
@ -26,22 +26,19 @@ var (
func initConfig() { func initConfig() {
logging.LogInit(*debugMode) logging.LogInit(*debugMode)
if cfgFile != "" { config.MustLoadConfig(cfgFile)
err := config.LoadConfig(cfgFile)
if err != nil {
slog.Error("error loading custom config", "error", err)
}
}
if cfgDb != "" { if cfgDb != "" {
config.Cfg.SQLiteFile = cfgDb config.Cfg.SQLiteFile = cfgDb
} }
auth.MustLoadKey()
storage.Data = sqlite.MustLoadSQLite(config.Cfg.SQLiteFile) storage.Data = sqlite.MustLoadSQLite(config.Cfg.SQLiteFile)
} }
func init() { func init() {
cobra.OnInitialize(initConfig) cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "config.json", "config file") rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "config.json", "config file")
rootCmd.PersistentFlags().StringVar(&cfgDb, "db", "", "database to use") rootCmd.PersistentFlags().StringVar(&cfgDb, "db", "", "database to use")
debugMode = rootCmd.PersistentFlags().BoolP("debug", "d", false, "enable debug mode") debugMode = rootCmd.PersistentFlags().BoolP("debug", "d", false, "enable debug mode")
} }

View file

@ -18,19 +18,19 @@ var (
func init() { func init() {
verifyCmd.Flags().StringVarP(&verifyToken, "token", "t", "", "token to verify") verifyCmd.Flags().StringVarP(&verifyToken, "token", "t", "", "token to verify")
verifyCmd.MarkFlagRequired("token") verifyCmd.MarkFlagRequired("token")
verifyCmd.Flags().StringVarP(&verifyFile, "file", "f", "", "file to use") verifyCmd.Flags().StringVarP(&verifyFile, "file", "f", "", "PEM file to use")
rootCmd.AddCommand(verifyCmd) rootCmd.AddCommand(verifyCmd)
} }
var verifyCmd = &cobra.Command{ var verifyCmd = &cobra.Command{
Use: "verify", Use: "verify",
Short: "Verify a JWT token", Short: "Verify a JWT token",
Long: `Pass a JWT token and a path to PEM-encoded file with a public key Long: `Pass a JWT token (and optionally a path to a PEM-formatted file with the public key)
to verify whether it is legit.`, to verify whether it is valid.`,
Run: verifyFunc, Run: verifyFunc,
} }
// TODO: Better name. // TODO: Needs a better name?
func verifyFunc(cmd *cobra.Command, args []string) { func verifyFunc(cmd *cobra.Command, args []string) {
if verifyToken == "" { if verifyToken == "" {
fmt.Println("Empty token supplied!") fmt.Println("Empty token supplied!")
@ -50,5 +50,10 @@ func verifyFunc(cmd *cobra.Command, args []string) {
} }
t, err = auth.VerifyJWT(verifyToken, key) t, err = auth.VerifyJWT(verifyToken, key)
} }
slog.Info("result", "token", t, "error", err, "ok", err == nil) slog.Debug("result", "token", t, "error", err, "ok", err == nil)
if err == nil {
fmt.Println("Token valid!")
} else {
fmt.Println("Token invalid!", err)
}
} }

View file

@ -38,18 +38,14 @@ func LoadConfig(filename string) error {
return err return err
} }
Cfg = temp_config Cfg = temp_config
slog.Info("Loaded config", "file", filename) slog.Debug("Loaded config", "file", filename)
return nil return nil
} }
func MustLoadConfig() { func MustLoadConfig(filename string) {
err := LoadConfig(DefaultLocation) err := LoadConfig(filename)
if err != nil { if err != nil {
slog.Error("error initially loading config", "error", err) slog.Error("error initially loading config", "error", err)
os.Exit(1) os.Exit(1)
} }
} }
func init() {
MustLoadConfig()
}

View file

@ -61,7 +61,7 @@ func (s SQLiteStorage) EmailExists(email string) bool {
func MustLoadSQLite(dataFile string) SQLiteStorage { func MustLoadSQLite(dataFile string) SQLiteStorage {
if _, err := os.Stat(dataFile); errors.Is(err, os.ErrNotExist) { if _, err := os.Stat(dataFile); errors.Is(err, os.ErrNotExist) {
os.Create(dataFile) os.Create(dataFile)
slog.Info("created sqlite3 database file", "file", dataFile) slog.Debug("created sqlite3 database file", "file", dataFile)
} }
db, err := sql.Open("sqlite3", dataFile) db, err := sql.Open("sqlite3", dataFile)
if err != nil { if err != nil {
@ -72,13 +72,13 @@ func MustLoadSQLite(dataFile string) SQLiteStorage {
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 sqlite3 database table", "error", err) slog.Error("error initialising sqlite3 database table", "error", err)
os.Exit(1) os.Exit(1)
} }
} else { } else {
statement.Exec() statement.Exec()
} }
slog.Info("loaded database", "file", dataFile) slog.Debug("loaded database", "file", dataFile)
return SQLiteStorage{db} return SQLiteStorage{db}
} }