-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
handler.go
137 lines (114 loc) · 3.93 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package cart
import (
"context"
"errors"
"fmt"
"net/http"
"time"
"github.com/jmoiron/sqlx"
"github.com/jatolentino/tutorialspoint/api/web"
"github.com/jatolentino/tutorialspoint/api/weberr"
"github.com/jatolentino/tutorialspoint/core/claims"
"github.com/jatolentino/tutorialspoint/core/course"
"github.com/jatolentino/tutorialspoint/database"
"github.com/jatolentino/tutorialspoint/validate"
)
// HandleShow returns the cart of the user.
// Returns an empty cart if the user has no cart.
func HandleShow(db *sqlx.DB) web.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
clm, err := claims.Get(ctx)
if err != nil {
return weberr.NotAuthorized(errors.New("user not authenticated"))
}
// Return an empty cart if it doesn't exist yet.
cart, err := Fetch(ctx, db, clm.UserID)
if err != nil {
if errors.Is(err, database.ErrDBNotFound) {
return web.Respond(ctx, w, Cart{Items: []Item{}}, http.StatusOK)
}
return fmt.Errorf("fetching user[%s] cart: %w", clm.UserID, err)
}
cart.Items, err = FetchItems(ctx, db, clm.UserID)
if err != nil {
return fmt.Errorf("fetching user[%s] cart items: %w", clm.UserID, err)
}
return web.Respond(ctx, w, cart, http.StatusOK)
}
}
// HandleDelete flushes the user's cart. It also drops
// all related items in cascade.
func HandleDelete(db *sqlx.DB) web.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
clm, err := claims.Get(ctx)
if err != nil {
return weberr.NotAuthorized(errors.New("user not authenticated"))
}
// Just delete the cart. Its items will be deleted in cascade.
if err := Delete(ctx, db, clm.UserID); err != nil {
return fmt.Errorf("deleting user[%s] cart: %w", clm.UserID, err)
}
return web.Respond(ctx, w, nil, http.StatusNoContent)
}
}
// HandleCreateItem adds a new item in the user's cart.
func HandleCreateItem(db *sqlx.DB) web.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
var itnew ItemNew
if err := web.Decode(w, r, &itnew); err != nil {
return weberr.BadRequest(fmt.Errorf("unable to decode payload: %w", err))
}
clm, err := claims.Get(ctx)
if err != nil {
return weberr.NotAuthorized(errors.New("user not authenticated"))
}
owned, err := course.FetchByOwner(ctx, db, clm.UserID)
if err != nil {
return fmt.Errorf("checking if course[%s] is already owned by user[%s]: %w",
itnew.CourseID,
clm.UserID,
err,
)
}
for _, o := range owned {
if itnew.CourseID == o.ID {
err := errors.New("course already owned")
return weberr.NewError(err, err.Error(), http.StatusUnprocessableEntity)
}
}
if _, err := Upsert(ctx, db, clm.UserID); err != nil {
return fmt.Errorf("upserting user[%s] cart: %w", clm.UserID, err)
}
now := time.Now().UTC()
item := Item{
UserID: clm.UserID,
CourseID: itnew.CourseID,
UpdatedAt: now,
CreatedAt: now,
}
if err := CreateItem(ctx, db, item); err != nil {
return fmt.Errorf("creating cart item[%s] for user[%s]: %w", item.CourseID, clm.UserID, err)
}
return web.Respond(ctx, w, item, http.StatusCreated)
}
}
// HandleDeleteItem deletes an item from the user's cart.
func HandleDeleteItem(db *sqlx.DB) web.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
courseID := web.Param(r, "course_id")
if err := validate.CheckID(courseID); err != nil {
return weberr.BadRequest(fmt.Errorf("passed id is not valid: %w", err))
}
clm, err := claims.Get(ctx)
if err != nil {
return weberr.NotAuthorized(errors.New("user not authenticated"))
}
if _, err := Upsert(ctx, db, clm.UserID); err != nil {
return fmt.Errorf("upserting user[%s] cart: %w", clm.UserID, err)
}
if err := DeleteItem(ctx, db, clm.UserID, courseID); err != nil {
return fmt.Errorf("deleting user[%s] cart item: %w", clm.UserID, err)
}
return web.Respond(ctx, w, nil, http.StatusNoContent)
}
}