diff --git a/go.mod b/go.mod index c4aa268..45547bf 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module github.com/rdarius/boot-dev-blog-aggregator go 1.23.6 + +require ( + github.com/google/uuid v1.6.0 // indirect + github.com/lib/pq v1.10.9 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ae20c4c --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= diff --git a/internal/config/state.go b/internal/config/state.go index 26b4060..780a4a7 100644 --- a/internal/config/state.go +++ b/internal/config/state.go @@ -1,5 +1,8 @@ package config +import "github.com/rdarius/boot-dev-blog-aggregator/internal/database" + type State struct { + DB *database.Queries Config *Config } diff --git a/internal/database/db.go b/internal/database/db.go new file mode 100644 index 0000000..bad7c4b --- /dev/null +++ b/internal/database/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package database + +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, + } +} diff --git a/internal/database/getUser.sql.go b/internal/database/getUser.sql.go new file mode 100644 index 0000000..dee6324 --- /dev/null +++ b/internal/database/getUser.sql.go @@ -0,0 +1,26 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: getUser.sql + +package database + +import ( + "context" +) + +const getUser = `-- name: GetUser :one +SELECT id, created_at, updated_at, name FROM users WHERE name = $1 +` + +func (q *Queries) GetUser(ctx context.Context, name string) (User, error) { + row := q.db.QueryRowContext(ctx, getUser, name) + var i User + err := row.Scan( + &i.ID, + &i.CreatedAt, + &i.UpdatedAt, + &i.Name, + ) + return i, err +} diff --git a/internal/database/models.go b/internal/database/models.go new file mode 100644 index 0000000..63aef10 --- /dev/null +++ b/internal/database/models.go @@ -0,0 +1,18 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package database + +import ( + "time" + + "github.com/google/uuid" +) + +type User struct { + ID uuid.UUID + CreatedAt time.Time + UpdatedAt time.Time + Name string +} diff --git a/internal/database/users.sql.go b/internal/database/users.sql.go new file mode 100644 index 0000000..6ff0da5 --- /dev/null +++ b/internal/database/users.sql.go @@ -0,0 +1,48 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: users.sql + +package database + +import ( + "context" + "time" + + "github.com/google/uuid" +) + +const createUser = `-- name: CreateUser :one +INSERT INTO users (id, created_at, updated_at, name) +VALUES ( + $1, + $2, + $3, + $4 + ) +RETURNING id, created_at, updated_at, name +` + +type CreateUserParams struct { + ID uuid.UUID + CreatedAt time.Time + UpdatedAt time.Time + Name string +} + +func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) { + row := q.db.QueryRowContext(ctx, createUser, + arg.ID, + arg.CreatedAt, + arg.UpdatedAt, + arg.Name, + ) + var i User + err := row.Scan( + &i.ID, + &i.CreatedAt, + &i.UpdatedAt, + &i.Name, + ) + return i, err +} diff --git a/internal/handlers/loginHandler.go b/internal/handlers/loginHandler.go index 7a6b24c..e86dd60 100644 --- a/internal/handlers/loginHandler.go +++ b/internal/handlers/loginHandler.go @@ -1,17 +1,27 @@ package handlers import ( + "context" "errors" "fmt" "github.com/rdarius/boot-dev-blog-aggregator/internal/config" + "os" ) -func HandlerLogin(s *config.State, cmd config.Command) error { +func LoginHandler(s *config.State, cmd config.Command) error { if len(cmd.Args) < 1 { return errors.New("missing required argument USERNAME") } - err := s.Config.SetUser(cmd.Args[0]) + ctx := context.Background() + + u, err := s.DB.GetUser(ctx, cmd.Args[0]) + if err != nil { + fmt.Println("User does not exist") + os.Exit(1) + } + + err = s.Config.SetUser(u.Name) if err != nil { return fmt.Errorf("failed to set current user: %w", err) } diff --git a/internal/handlers/registerHandler.go b/internal/handlers/registerHandler.go new file mode 100644 index 0000000..a5fa1d3 --- /dev/null +++ b/internal/handlers/registerHandler.go @@ -0,0 +1,46 @@ +package handlers + +import ( + "context" + "errors" + "fmt" + "github.com/google/uuid" + "github.com/rdarius/boot-dev-blog-aggregator/internal/config" + "github.com/rdarius/boot-dev-blog-aggregator/internal/database" + "os" + "time" +) + +func RegisterHandler(s *config.State, cmd config.Command) error { + if len(cmd.Args) < 1 { + return errors.New("missing required argument USERNAME") + } + + ctx := context.Background() + + _, err := s.DB.GetUser(ctx, cmd.Args[0]) + if err == nil { + fmt.Println("User already exists") + os.Exit(1) + } + + u, err := s.DB.CreateUser(ctx, database.CreateUserParams{ + ID: uuid.New(), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + Name: cmd.Args[0], + }) + if err != nil { + fmt.Printf("Failed to create user %v\n", err) + os.Exit(1) + } + + err = s.Config.SetUser(u.Name) + if err != nil { + return fmt.Errorf("failed to set current user: %w", err) + } + + fmt.Printf("User Created %v\n", u) + + return nil +} diff --git a/main.go b/main.go index 8e1e3a9..0152899 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,10 @@ package main import ( + "database/sql" + _ "github.com/lib/pq" "github.com/rdarius/boot-dev-blog-aggregator/internal/config" + "github.com/rdarius/boot-dev-blog-aggregator/internal/database" "github.com/rdarius/boot-dev-blog-aggregator/internal/handlers" "log" "os" @@ -16,7 +19,11 @@ func main() { log.Fatal(err) } + db, err := sql.Open("postgres", cfg.DbUrl) + dbQueries := database.New(db) + state := config.State{ + DB: dbQueries, Config: &cfg, } @@ -24,7 +31,8 @@ func main() { Commands: map[string]func(*config.State, config.Command) error{}, } - commands.Register("login", handlers.HandlerLogin) + commands.Register("login", handlers.LoginHandler) + commands.Register("register", handlers.RegisterHandler) if len(os.Args) < 2 { log.Fatal("usage: boot-dev-blog-aggregator [args...]") diff --git a/sql/queries/getUser.sql b/sql/queries/getUser.sql new file mode 100644 index 0000000..cc2d08b --- /dev/null +++ b/sql/queries/getUser.sql @@ -0,0 +1,2 @@ +-- name: GetUser :one +SELECT * FROM users WHERE name = $1; \ No newline at end of file diff --git a/sql/queries/users.sql b/sql/queries/users.sql new file mode 100644 index 0000000..7c840a4 --- /dev/null +++ b/sql/queries/users.sql @@ -0,0 +1,9 @@ +-- name: CreateUser :one +INSERT INTO users (id, created_at, updated_at, name) +VALUES ( + $1, + $2, + $3, + $4 + ) +RETURNING *; \ No newline at end of file diff --git a/sql/schema/0001_users.sql b/sql/schema/0001_users.sql new file mode 100644 index 0000000..fcc8338 --- /dev/null +++ b/sql/schema/0001_users.sql @@ -0,0 +1,10 @@ +-- +goose Up +CREATE TABLE users( + id UUID PRIMARY KEY, + created_at TIMESTAMP not null DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP not null, + name VARCHAR(64) not null UNIQUE +); + +-- +goose Down +DROP TABLE users; \ No newline at end of file diff --git a/sqlc.yaml b/sqlc.yaml new file mode 100644 index 0000000..08ef51e --- /dev/null +++ b/sqlc.yaml @@ -0,0 +1,8 @@ +version: "2" +sql: + - schema: "sql/schema" + queries: "sql/queries" + engine: "postgresql" + gen: + go: + out: "internal/database"