3 Commits

Author SHA1 Message Date
c82cdb4f13 Use best naming practices 2023-12-18 23:04:31 -06:00
ce81c36e9f Update x/crypto 2023-12-18 23:01:19 -06:00
ab1b82c680 Update x/crypto 2023-10-10 21:37:54 -05:00
8 changed files with 58 additions and 50 deletions

View File

@ -18,7 +18,7 @@ fine with getting your hands dirty, but I plan on having it ready to go for more
- Minimal user login/registration + sessions - Minimal user login/registration + sessions
- Config file handling - Config file handling
- Scheduled tasks - Scheduled tasks
- Entire website compiles into a single binary (~10mb) (excluding env.toml) - Entire website compiles into a single binary (~10mb) (excluding env.json)
- Minimal dependencies (just standard library, postgres driver, and experimental package for bcrypt) - Minimal dependencies (just standard library, postgres driver, and experimental package for bcrypt)
<hr> <hr>
@ -41,7 +41,7 @@ fine with getting your hands dirty, but I plan on having it ready to go for more
1. Clone 1. Clone
2. Delete the git folder, so you can start tracking in your own repo 2. Delete the git folder, so you can start tracking in your own repo
3. Run `go get` to install dependencies 3. Run `go get` to install dependencies
4. Copy env_example.toml to env.toml and fill in the values 4. Copy env_example.json to env.json and fill in the values
5. Run `go run main.go` to start the server 5. Run `go run main.go` to start the server
6. Rename the occurences of "GoWeb" to your app name 6. Rename the occurences of "GoWeb" to your app name
7. Start building your app! 7. Start building your app!
@ -62,4 +62,4 @@ fine with getting your hands dirty, but I plan on having it ready to go for more
- You and you alone are responsible for the security and everything else regarding your application. - You and you alone are responsible for the security and everything else regarding your application.
- It is not required, but I ask that when you use this project you give me credit by linking to this repository. - It is not required, but I ask that when you use this project you give me credit by linking to this repository.
- I also ask that when releasing self-hosted or other end-user applications that you release it under - I also ask that when releasing self-hosted or other end-user applications that you release it under
the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) license. This too is not required, but I would appreciate it. the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) license. This too is not required, but I would appreciate it.

View File

@ -1,44 +1,53 @@
package config package config
import ( import (
"encoding/json"
"flag" "flag"
"github.com/BurntSushi/toml" "log/slog"
"os" "os"
) )
type Configuration struct { type Configuration struct {
Db struct { Db struct {
Ip string `toml:"DbIp"` Ip string `json:"DbIp"`
Port string `toml:"DbPort"` Port string `json:"DbPort"`
Name string `toml:"DbName"` Name string `json:"DbName"`
User string `toml:"DbUser"` User string `json:"DbUser"`
Password string `toml:"DbPassword"` Password string `json:"DbPassword"`
AutoMigrate bool `toml:"DbAutoMigrate"` AutoMigrate bool `json:"DbAutoMigrate"`
} }
Listen struct { Listen struct {
Ip string `toml:"HttpIp"` Ip string `json:"HttpIp"`
Port string `toml:"HttpPort"` Port string `json:"HttpPort"`
} }
Template struct { Template struct {
BaseName string `toml:"BaseTemplateName"` BaseName string `json:"BaseTemplateName"`
} }
} }
// LoadConfig loads and returns a configuration struct // LoadConfig loads and returns a configuration struct
func LoadConfig() Configuration { func LoadConfig() Configuration {
c := flag.String("c", "env.toml", "Path to the toml configuration file") c := flag.String("c", "env.json", "Path to the json configuration file")
flag.Parse() flag.Parse()
file, err := os.ReadFile(*c) file, err := os.Open(*c)
if err != nil { if err != nil {
panic("Unable to read TOML config file: " + err.Error()) panic("unable to open JSON config file: " + err.Error())
} }
var Config Configuration defer func(file *os.File) {
_, err = toml.Decode(string(file), &Config) err := file.Close()
if err != nil {
slog.Error("unable to close JSON config file: ", err)
}
}(file)
decoder := json.NewDecoder(file)
Config := Configuration{}
err = decoder.Decode(&Config)
if err != nil { if err != nil {
panic("Unable to decode TOML config file: " + err.Error()) panic("unable to decode JSON config file: " + err.Error())
} }
return Config return Config

17
env_example.json Normal file
View File

@ -0,0 +1,17 @@
{
"Db": {
"DbIp": "127.0.0.1",
"DbPort": "5432",
"DbName": "database",
"DbUser": "user",
"DbPassword": "password",
"DbAutoMigrate": true
},
"Listen": {
"HttpIp": "127.0.0.1",
"HttpPort": "8090"
},
"Template": {
"BaseTemplateName": "templates/base.html"
}
}

View File

@ -1,14 +0,0 @@
[Db]
DbIp = "127.0.0.1"
DbPort = "5432"
DbName = "test"
DbUser = "postgres"
DbPassword = "postgres"
DbAutoMigrate = true
[Listen]
HttpIp = "127.0.0.1"
HttpPort = "8090"
[Template]
BaseTemplateName = "templates/base.html"

4
go.mod
View File

@ -4,7 +4,5 @@ go 1.21
require ( require (
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
golang.org/x/crypto v0.13.0 golang.org/x/crypto v0.17.0
) )
require github.com/BurntSushi/toml v1.3.2

6
go.sum
View File

@ -1,6 +1,4 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=

View File

@ -62,7 +62,7 @@ func CreateSession(app *app.App, w http.ResponseWriter, userId int64, remember b
return session, nil return session, nil
} }
func GetSessionByAuthToken(app *app.App, authToken string) (Session, error) { func SessionByAuthToken(app *app.App, authToken string) (Session, error) {
session := Session{} session := Session{}
err := app.Db.QueryRow(selectSessionByAuthToken, authToken).Scan(&session.Id, &session.UserId, &session.AuthToken, &session.RememberMe, &session.CreatedAt) err := app.Db.QueryRow(selectSessionByAuthToken, authToken).Scan(&session.Id, &session.UserId, &session.AuthToken, &session.RememberMe, &session.CreatedAt)

View File

@ -27,23 +27,23 @@ const (
insertUser = "INSERT INTO " + userTable + " (" + userColumnsNoId + ") VALUES ($1, $2, $3, $4) RETURNING \"Id\"" insertUser = "INSERT INTO " + userTable + " (" + userColumnsNoId + ") VALUES ($1, $2, $3, $4) RETURNING \"Id\""
) )
// GetCurrentUser finds the currently logged-in user by session cookie // CurrentUser finds the currently logged-in user by session cookie
func GetCurrentUser(app *app.App, r *http.Request) (User, error) { func CurrentUser(app *app.App, r *http.Request) (User, error) {
cookie, err := r.Cookie("session") cookie, err := r.Cookie("session")
if err != nil { if err != nil {
return User{}, err return User{}, err
} }
session, err := GetSessionByAuthToken(app, cookie.Value) session, err := SessionByAuthToken(app, cookie.Value)
if err != nil { if err != nil {
return User{}, err return User{}, err
} }
return GetUserById(app, session.UserId) return UserById(app, session.UserId)
} }
// GetUserById finds a User table row in the database by id and returns a struct representing this row // UserById finds a User table row in the database by id and returns a struct representing this row
func GetUserById(app *app.App, id int64) (User, error) { func UserById(app *app.App, id int64) (User, error) {
user := User{} user := User{}
err := app.Db.QueryRow(selectUserById, id).Scan(&user.Id, &user.Username, &user.Password, &user.CreatedAt, &user.UpdatedAt) err := app.Db.QueryRow(selectUserById, id).Scan(&user.Id, &user.Username, &user.Password, &user.CreatedAt, &user.UpdatedAt)
@ -54,8 +54,8 @@ func GetUserById(app *app.App, id int64) (User, error) {
return user, nil return user, nil
} }
// GetUserByUsername finds a User table row in the database by username and returns a struct representing this row // UserByUsername finds a User table row in the database by username and returns a struct representing this row
func GetUserByUsername(app *app.App, username string) (User, error) { func UserByUsername(app *app.App, username string) (User, error) {
user := User{} user := User{}
err := app.Db.QueryRow(selectUserByUsername, username).Scan(&user.Id, &user.Username, &user.Password, &user.CreatedAt, &user.UpdatedAt) err := app.Db.QueryRow(selectUserByUsername, username).Scan(&user.Id, &user.Username, &user.Password, &user.CreatedAt, &user.UpdatedAt)
@ -82,7 +82,7 @@ func CreateUser(app *app.App, username string, password string, createdAt time.T
return User{}, err return User{}, err
} }
return GetUserById(app, lastInsertId) return UserById(app, lastInsertId)
} }
// AuthenticateUser validates the password for the specified user // AuthenticateUser validates the password for the specified user