Skip to content

Commit

Permalink
basics
Browse files Browse the repository at this point in the history
  • Loading branch information
bnkamalesh committed Feb 16, 2024
1 parent be758fb commit b5f72df
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 0 deletions.
93 changes: 93 additions & 0 deletions internal/usernotes/store_postgres.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package usernotes

import (
"context"

"github.com/Masterminds/squirrel"
"github.com/bnkamalesh/errors"
"github.com/bnkamalesh/goapp/internal/users"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
)

type pgstore struct {
qbuilder squirrel.StatementBuilderType
pqdriver *pgxpool.Pool
tableName string
}

func (ps *pgstore) GetNoteByID(ctx context.Context, userID string, noteID string) (*Note, error) {
query, args, err := ps.qbuilder.Select(
"id",
"title",
"content",
).From(
ps.tableName,
).Where(
squirrel.Eq{
"id": noteID,
"user_id": userID,
},
).ToSql()
if err != nil {
return nil, errors.Wrap(err, "failed preparing query")
}

usernote := &Note{
Creator: &users.User{
ID: userID,
},
}

err = ps.pqdriver.QueryRow(
ctx, query, args...,
).Scan(
usernote.ID,
usernote.Title,
usernote.Content,
)
if err != nil {
return nil, errors.Wrap(err, "failed getting user note")
}

return usernote, nil
}

func (ps *pgstore) SaveNote(ctx context.Context, note *Note) (string, error) {
noteID := ps.newNoteID()
query, args, err := ps.qbuilder.Insert(
ps.tableName,
).Columns(
"id",
"title",
"content",
"user_id",
).Values(
note.ID,
note.Title,
note.Content,
note.Creator.ID,
).ToSql()
if err != nil {
return "", errors.Wrap(err, "failed preparing query")
}

_, err = ps.pqdriver.Exec(ctx, query, args...)
if err != nil {
return "", errors.Wrap(err, "failed storing note")
}

return noteID, nil
}

func (ps *pgstore) newNoteID() string {
return uuid.New().String()
}

func NewPostgresStore(pqdriver *pgxpool.Pool, tableName string) store {
return &pgstore{
qbuilder: squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar),
pqdriver: pqdriver,
tableName: tableName,
}
}
81 changes: 81 additions & 0 deletions internal/usernotes/usernotes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Package usernotes maintains notes of a user
package usernotes

import (
"context"
"strings"
"time"

"github.com/bnkamalesh/errors"
"github.com/bnkamalesh/goapp/internal/users"
)

type Note struct {
ID string
Title string
Content string
Creator *users.User
CreatedAt time.Time
UpdatedAt time.Time
}

func (note *Note) ValidateForCreate() error {
if note == nil {
return errors.Validation("empty note")
}

note.Sanitize()
if note.Title == "" {
return errors.Validation("note title cannot be empty")
}

if note.Content == "" {
return errors.Validation("note content cannot be empty")
}

if note.Creator == nil || note.Creator.ID == "" {
return errors.Validation("note creator cannot be anonymous")
}

return nil
}

func (note *Note) Sanitize() {
note.Title = strings.TrimSpace(note.Title)
note.Content = strings.TrimSpace(note.Content)
}

type store interface {
GetNoteByID(ctx context.Context, userID string, noteID string) (*Note, error)
SaveNote(ctx context.Context, note *Note) (string, error)
}

type UserNotes struct {
store store
}

func (un *UserNotes) SaveNote(ctx context.Context, note *Note) (*Note, error) {
err := note.ValidateForCreate()
if err != nil {
return nil, err
}

note.CreatedAt = time.Now()
note.UpdatedAt = time.Now()
note.ID, err = un.store.SaveNote(ctx, note)
if err != nil {
return nil, err
}

return note, nil
}

func (un *UserNotes) GetNoteByID(ctx context.Context, userID string, noteID string) (*Note, error) {
return un.store.GetNoteByID(ctx, userID, noteID)
}

func NewService(store store) *UserNotes {
return &UserNotes{
store: store,
}
}

0 comments on commit b5f72df

Please sign in to comment.