updates
Some checks failed
build / build (push) Failing after 0s

This commit is contained in:
Tijl 2024-08-21 01:08:47 +02:00
parent e6d6ba4041
commit c6dc9cd110
Signed by: tijl
GPG Key ID: DAE24BFCD722F053
21 changed files with 518 additions and 109 deletions

View File

@ -6,34 +6,43 @@ import (
"git.tijl.dev/tijl/tijl.dev/internal/assets"
"git.tijl.dev/tijl/tijl.dev/internal/config"
"git.tijl.dev/tijl/tijl.dev/internal/i18n"
"git.tijl.dev/tijl/tijl.dev/modules/logger"
"git.tijl.dev/tijl/tijl.dev/static"
"git.tijl.dev/tijl/tijl.dev/views"
"github.com/gofiber/contrib/fiberzerolog"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"github.com/gofiber/template/html/v2"
"github.com/mikhail-bigun/fiberlogrus"
log "github.com/sirupsen/logrus"
)
func main() {
log.SetLevel(log.DebugLevel)
// Load config
config.Load()
// Load assets
assets.Load()
// Load translations
i18n.Load()
engine := html.NewFileSystem(http.FS(views.Embed), ".html")
// Todo load db, migrations and plugins
// Init templating engine
engine := html.NewFileSystem(http.FS(views.Embed), ".html")
engine.AddFunc("icon", assets.Svg)
// Init fiber
app := fiber.New(fiber.Config{
Views: engine,
DisableStartupMessage: true,
})
app.Use(fiberzerolog.New(fiberzerolog.Config{
Logger: &log.Logger,
}))
app.Use(fiberlogrus.New())
/*
Routes
*/
app.Get("/", func(c *fiber.Ctx) error {
data := getCommon(c)
data["Title"] = i18n.Translate(c, "home")
@ -70,18 +79,24 @@ func main() {
return nil
})
// Static routes
app.Use("/static", filesystem.New(filesystem.Config{
Root: http.FS(static.Embed),
}))
// 404
app.Use(func(c *fiber.Ctx) error {
data := getCommon(c)
return c.Render("404", data, "layouts/base")
})
log.Fatal(app.Listen(":3000"))
// Listen web server
if err := app.Listen(":3000"); err != nil {
log.Fatal().Err(err).Msg("Fiber app error")
}
}
// Common functions for in templating
func getCommon(c *fiber.Ctx) fiber.Map {
return fiber.Map{
"Path": c.Path(),

3
go.mod
View File

@ -7,13 +7,16 @@ require (
github.com/gofiber/fiber/v2 v2.52.5
github.com/gofiber/template/html/v2 v2.1.2
github.com/mikhail-bigun/fiberlogrus v0.1.3
github.com/rs/zerolog v1.33.0
github.com/sirupsen/logrus v1.9.3
github.com/sqlc-dev/pqtype v0.3.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
github.com/gofiber/contrib/fiberzerolog v1.0.2 // indirect
github.com/gofiber/template v1.8.3 // indirect
github.com/gofiber/utils v1.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect

12
go.sum
View File

@ -2,11 +2,15 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
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-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofiber/contrib/fiberzerolog v1.0.2 h1:LMa/luarQVeINoRwZLHtLQYepLPDIwUNB5OmdZKk+s8=
github.com/gofiber/contrib/fiberzerolog v1.0.2/go.mod h1:aTPsgArSgxRWcUeJ/K6PiICz3mbQENR1QOR426QwOoQ=
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
@ -24,19 +28,26 @@ github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ib
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.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
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/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mikhail-bigun/fiberlogrus v0.1.3 h1:2aVtFSfMr/T8J2p4228TwV6txvUEOQxKlu5LpcKyym0=
github.com/mikhail-bigun/fiberlogrus v0.1.3/go.mod h1:Tt0FrmLd2maF8VSHsx1pfiWNRTrjyBrKfDA2JW5hvmY=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sqlc-dev/pqtype v0.3.0 h1:b09TewZ3cSnO5+M1Kqq05y0+OjqIptxELaSayg7bmqk=
github.com/sqlc-dev/pqtype v0.3.0/go.mod h1:oyUjp5981ctiL9UYvj1bVvCKi8OXkCa0u645hce7CAs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
@ -54,6 +65,7 @@ golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbht
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

View File

@ -6,7 +6,7 @@ import (
"path/filepath"
"strings"
log "github.com/sirupsen/logrus"
"git.tijl.dev/tijl/tijl.dev/modules/logger"
)
var SVGData map[string]string
@ -18,13 +18,13 @@ func loadSVGs() {
files, err := filepath.Glob(filepath.Join(dir, "*.svg"))
if err != nil {
log.Fatalf("Error loading SVG files: %v", err)
log.Fatal().Err(err)
}
for _, file := range files {
data, err := os.ReadFile(file)
if err != nil {
log.Warnf("Error reading SVG file %s: %v", file, err)
log.Fatal().Err(err)
continue
}
filename := filepath.Base(file)
@ -32,7 +32,7 @@ func loadSVGs() {
SVGData[key] = string(data)
}
log.Debug("Loaded SVG files")
log.Debug().Msg("Loaded SVG files")
}
func Svg(name string) template.HTML {

View File

@ -3,7 +3,7 @@ package config
import (
"os"
log "github.com/sirupsen/logrus"
log "git.tijl.dev/tijl/tijl.dev/modules/logger"
"gopkg.in/yaml.v3"
)
@ -17,15 +17,15 @@ func Load() {
indexFile, err := os.ReadFile(configPath)
if err != nil {
log.Fatal(err)
log.Fatal().Err(err)
}
err = yaml.Unmarshal(indexFile, &Config)
if err != nil {
log.Fatal(err)
log.Fatal().Err(err)
}
log.Debug("loaded config")
log.Debug().Msg("loaded config")
}
type ConfigType struct {

View File

@ -2,11 +2,11 @@ package i18n
import (
"encoding/json"
"github.com/gofiber/fiber/v2"
"os"
"path/filepath"
log "github.com/sirupsen/logrus"
log "git.tijl.dev/tijl/tijl.dev/modules/logger"
"github.com/gofiber/fiber/v2"
)
var translations map[string]map[string]string
@ -19,7 +19,7 @@ func Load() {
dir := "locales"
files, err := filepath.Glob(filepath.Join(dir, "*.json"))
if err != nil {
log.Fatalf("Error loading language files: %v", err)
log.Fatal().Err(err)
}
for _, file := range files {
@ -28,20 +28,20 @@ func Load() {
file, err := os.Open(file)
if err != nil {
log.Errorf("Error opening translation file %s: %v", file, err)
log.Error().Err(err)
continue
}
defer file.Close()
var messages map[string]string
if err := json.NewDecoder(file).Decode(&messages); err != nil {
log.Errorf("Error decoding translation file %s: %v", file, err)
log.Error().Err(err)
continue
}
translations[lang] = messages
}
log.Debug("Loaded translations")
log.Debug().Msg("Loaded translations")
}
func Translate(c *fiber.Ctx, key string) string {

View File

@ -1,7 +1,5 @@
package oidc
import "github.com/coreos/go-oidc/v3/oidc"
func Setup() {
}

View File

@ -7,8 +7,11 @@ npm-build-css:
npm-build:
npm run build
generate-sqlc:
sqlc generate
go-build:
go build -o tijl.dev cmd/server/main.go
build: npm-build-css npm-build go-build
build: npm-build-css npm-build generate-sqlc go-build

View File

@ -0,0 +1,30 @@
CREATE TABLE users (
id SERIAL PRIMARY KEY,
uid VARCHAR UNIQUE NOT NULL, -- username as unique identifier
email VARCHAR UNIQUE,
full_name VARCHAR,
displayname VARCHAR,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE sessions (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
title VARCHAR,
token VARCHAR NOT NULL UNIQUE,
password VARCHAR,
last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (user_id) REFERENCES users (id)
);
CREATE TABLE session_ips (
id SERIAL PRIMARY KEY,
session_id INTEGER NOT NULL,
ip_address INET NOT NULL,
access_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (session_id) REFERENCES sessions (id)
);

View File

@ -0,0 +1,3 @@
DROP TABLE IF EXISTS session_ips;
DROP TABLE IF EXISTS sessions;
DROP TABLE IF EXISTS users;

6
migrations/migrations.go Normal file
View File

@ -0,0 +1,6 @@
package migrations
import "embed"
//go:embed *
var Embed embed.FS

31
modules/db/db.go Normal file
View File

@ -0,0 +1,31 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package db
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
}
}

40
modules/db/models.go Normal file
View File

@ -0,0 +1,40 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package db
import (
"database/sql"
"time"
"github.com/sqlc-dev/pqtype"
)
type Session struct {
ID int32
UserID int32
Title sql.NullString
Token string
Password sql.NullString
LastActivity sql.NullTime
Expires sql.NullTime
CreatedAt time.Time
}
type SessionIp struct {
ID int32
SessionID int32
IpAddress pqtype.Inet
AccessTime sql.NullTime
}
type User struct {
ID int32
Uid string
Email sql.NullString
FullName sql.NullString
Displayname sql.NullString
CreatedAt time.Time
UpdatedAt sql.NullTime
}

18
modules/db/sessions.sql Normal file
View File

@ -0,0 +1,18 @@
-- name: GetSesssion :one
SELECT * FROM sessions WHERE token = $1;
-- name: GetSessions :many
SELECT * FROM sessions WHERE user_id = $1 ORDER BY $2;
-- name: GetActiveSessions :many
SELECT * FROM sessions WHERE user_id = $1 AND (expires > CURRENT_TIMESTAMP OR expires IS NULL) ORDER BY $2;
-- name: CreateSession :exec
INSERT INTO sessions (user_id, title, token) VALUES ($1, $2, $3);
-- name: QuickUpdateSession :exec
UPDATE sessions SET last_activity = GETDATE() WHERE id = $1;
-- name: ExpireSession :exec
UPDATE sessions SET expires = 1 WHERE id = $1;

146
modules/db/sessions.sql.go Normal file
View File

@ -0,0 +1,146 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: sessions.sql
package db
import (
"context"
"database/sql"
)
const createSession = `-- name: CreateSession :exec
INSERT INTO sessions (user_id, title, token) VALUES ($1, $2, $3)
`
type CreateSessionParams struct {
UserID int32
Title sql.NullString
Token string
}
func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) error {
_, err := q.db.ExecContext(ctx, createSession, arg.UserID, arg.Title, arg.Token)
return err
}
const expireSession = `-- name: ExpireSession :exec
UPDATE sessions SET expires = 1 WHERE id = $1
`
func (q *Queries) ExpireSession(ctx context.Context, id int32) error {
_, err := q.db.ExecContext(ctx, expireSession, id)
return err
}
const getActiveSessions = `-- name: GetActiveSessions :many
SELECT id, user_id, title, token, password, last_activity, expires, created_at FROM sessions WHERE user_id = $1 AND (expires > CURRENT_TIMESTAMP OR expires IS NULL) ORDER BY $2
`
type GetActiveSessionsParams struct {
UserID int32
Column2 interface{}
}
func (q *Queries) GetActiveSessions(ctx context.Context, arg GetActiveSessionsParams) ([]Session, error) {
rows, err := q.db.QueryContext(ctx, getActiveSessions, arg.UserID, arg.Column2)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Session
for rows.Next() {
var i Session
if err := rows.Scan(
&i.ID,
&i.UserID,
&i.Title,
&i.Token,
&i.Password,
&i.LastActivity,
&i.Expires,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getSessions = `-- name: GetSessions :many
SELECT id, user_id, title, token, password, last_activity, expires, created_at FROM sessions WHERE user_id = $1 ORDER BY $2
`
type GetSessionsParams struct {
UserID int32
Column2 interface{}
}
func (q *Queries) GetSessions(ctx context.Context, arg GetSessionsParams) ([]Session, error) {
rows, err := q.db.QueryContext(ctx, getSessions, arg.UserID, arg.Column2)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Session
for rows.Next() {
var i Session
if err := rows.Scan(
&i.ID,
&i.UserID,
&i.Title,
&i.Token,
&i.Password,
&i.LastActivity,
&i.Expires,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getSesssion = `-- name: GetSesssion :one
SELECT id, user_id, title, token, password, last_activity, expires, created_at FROM sessions WHERE token = $1
`
func (q *Queries) GetSesssion(ctx context.Context, token string) (Session, error) {
row := q.db.QueryRowContext(ctx, getSesssion, token)
var i Session
err := row.Scan(
&i.ID,
&i.UserID,
&i.Title,
&i.Token,
&i.Password,
&i.LastActivity,
&i.Expires,
&i.CreatedAt,
)
return i, err
}
const quickUpdateSession = `-- name: QuickUpdateSession :exec
UPDATE sessions SET last_activity = GETDATE() WHERE id = $1
`
func (q *Queries) QuickUpdateSession(ctx context.Context, id int32) error {
_, err := q.db.ExecContext(ctx, quickUpdateSession, id)
return err
}

25
modules/db/users.sql Normal file
View File

@ -0,0 +1,25 @@
-- name: GetUser :one
SELECT * FROM users WHERE uid = $1 LIMIT 1;
-- name: GetUserUid :one
SELECT uid FROM users WHERE id = $1 LIMIT 1;
-- name: GetUserById :one
SELECT * FROM users WHERE id = $1 LIMIT 1;
-- name: DeleteUser :exec
DELETE FROM users WHERE uid = $1;
-- name: CreateUser :exec
INSERT INTO users (uid, email, full_name, displayname)
VALUES ($1, $2, $3, $4)
RETURNING id;
-- name: UpdateUserData :exec
UPDATE users
SET email = COALESCE($2, email),
full_name = COALESCE($3, full_name),
displayname = COALESCE($4, displayname),
updated_at = CURRENT_TIMESTAMP
WHERE uid = $1;

118
modules/db/users.sql.go Normal file
View File

@ -0,0 +1,118 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: users.sql
package db
import (
"context"
"database/sql"
)
const createUser = `-- name: CreateUser :exec
INSERT INTO users (uid, email, full_name, displayname)
VALUES ($1, $2, $3, $4)
RETURNING id
`
type CreateUserParams struct {
Uid string
Email sql.NullString
FullName sql.NullString
Displayname sql.NullString
}
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) error {
_, err := q.db.ExecContext(ctx, createUser,
arg.Uid,
arg.Email,
arg.FullName,
arg.Displayname,
)
return err
}
const deleteUser = `-- name: DeleteUser :exec
DELETE FROM users WHERE uid = $1
`
func (q *Queries) DeleteUser(ctx context.Context, uid string) error {
_, err := q.db.ExecContext(ctx, deleteUser, uid)
return err
}
const getUser = `-- name: GetUser :one
SELECT id, uid, email, full_name, displayname, created_at, updated_at FROM users WHERE uid = $1 LIMIT 1
`
func (q *Queries) GetUser(ctx context.Context, uid string) (User, error) {
row := q.db.QueryRowContext(ctx, getUser, uid)
var i User
err := row.Scan(
&i.ID,
&i.Uid,
&i.Email,
&i.FullName,
&i.Displayname,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const getUserById = `-- name: GetUserById :one
SELECT id, uid, email, full_name, displayname, created_at, updated_at FROM users WHERE id = $1 LIMIT 1
`
func (q *Queries) GetUserById(ctx context.Context, id int32) (User, error) {
row := q.db.QueryRowContext(ctx, getUserById, id)
var i User
err := row.Scan(
&i.ID,
&i.Uid,
&i.Email,
&i.FullName,
&i.Displayname,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const getUserUid = `-- name: GetUserUid :one
SELECT uid FROM users WHERE id = $1 LIMIT 1
`
func (q *Queries) GetUserUid(ctx context.Context, id int32) (string, error) {
row := q.db.QueryRowContext(ctx, getUserUid, id)
var uid string
err := row.Scan(&uid)
return uid, err
}
const updateUserData = `-- name: UpdateUserData :exec
UPDATE users
SET email = COALESCE($2, email),
full_name = COALESCE($3, full_name),
displayname = COALESCE($4, displayname),
updated_at = CURRENT_TIMESTAMP
WHERE uid = $1
`
type UpdateUserDataParams struct {
Uid string
Email sql.NullString
FullName sql.NullString
Displayname sql.NullString
}
func (q *Queries) UpdateUserData(ctx context.Context, arg UpdateUserDataParams) error {
_, err := q.db.ExecContext(ctx, updateUserData,
arg.Uid,
arg.Email,
arg.FullName,
arg.Displayname,
)
return err
}

35
modules/logger/logger.go Normal file
View File

@ -0,0 +1,35 @@
package log
import (
"os"
"github.com/rs/zerolog"
)
var (
Logger zerolog.Logger
)
func init() {
Logger = zerolog.New(os.Stderr).With().Timestamp().Logger()
}
func Info() *zerolog.Event {
return Logger.Info()
}
func Error() *zerolog.Event {
return Logger.Error()
}
func Debug() *zerolog.Event {
return Logger.Debug()
}
func Fatal() *zerolog.Event {
return Logger.Fatal()
}
func SetLevel(level zerolog.Level) {
Logger = Logger.Level(level)
}

10
sqlc.yaml Normal file
View File

@ -0,0 +1,10 @@
version: "2"
sql:
- engine: "postgresql"
queries: "modules/db/*.sql"
schema: "migrations/*.sql"
gen:
go:
package: "db"
out: "modules/db/"
sql_package: "database/sql"

View File

@ -1,87 +1,3 @@
<h2>Welcome to My Go App</h2>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
<p>This is the homepage.</p>
{{.T.about}}

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="static/css/styles.css" />
<link rel="stylesheet" href="/static/css/styles.css" />
<link rel="icon" href="/static/assets/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#f28c18" />