@@ -6,11 +6,14 @@ import (
66 "fmt"
77 "log"
88 "net/http"
9- "net/url"
10- "strconv"
119
1210 "github.com/chadweimer/gomp/conf"
1311 "github.com/chadweimer/gomp/db"
12+ "github.com/chadweimer/gomp/generated/api/admin"
13+ "github.com/chadweimer/gomp/generated/api/adminOrSelf"
14+ "github.com/chadweimer/gomp/generated/api/editor"
15+ "github.com/chadweimer/gomp/generated/api/public"
16+ "github.com/chadweimer/gomp/generated/api/viewer"
1417 "github.com/chadweimer/gomp/upload"
1518 "github.com/go-chi/chi/v5"
1619 "github.com/go-chi/chi/v5/middleware"
@@ -22,21 +25,6 @@ var errMismatchedId = errors.New("id in the path does not match the one specifie
2225
2326// ---- End Standard Errors ----
2427
25- // ---- Begin Route Keys ----
26-
27- type routeKey string
28-
29- const (
30- destRecipeIdKey routeKey = "destRecipeId"
31- filterIdKey routeKey = "filterId"
32- imageIdKey routeKey = "imageId"
33- noteIdKey routeKey = "noteId"
34- recipeIdKey routeKey = "recipeId"
35- userIdKey routeKey = "userId"
36- )
37-
38- // ---- End Route Keys ----
39-
4028// ---- Begin Context Keys ----
4129
4230type contextKey struct {
@@ -72,69 +60,20 @@ func NewHandler(cfg *conf.Config, upl upload.Driver, db db.Driver) http.Handler
7260 r .Use (middleware .SetHeader ("Content-Type" , "application/json" ))
7361 r .Route ("/v1" , func (r chi.Router ) {
7462 // Public
75- r .Get ("/app/info" , h .getAppInfo )
76- r .Get ("/app/configuration" , h .getAppConfiguration )
77- r .Post ("/auth" , h .postAuthenticate )
63+ public .HandlerFromMux (h , r )
7864 r .NotFound (h .notFound )
7965
80- // Authenticated
8166 r .Group (func (r chi.Router ) {
8267 r .Use (h .requireAuthentication )
8368
84- r .Get ("/recipes" , h .getRecipes )
85- r .Get (fmt .Sprintf ("/recipes/{%s}" , recipeIdKey ), h .getRecipe )
86- r .Get (fmt .Sprintf ("/recipes/{%s}/image" , recipeIdKey ), h .getRecipeMainImage )
87- r .Get (fmt .Sprintf ("/recipes/{%s}/images" , recipeIdKey ), h .getRecipeImages )
88- r .Get (fmt .Sprintf ("/recipes/{%s}/notes" , recipeIdKey ), h .getRecipeNotes )
89- r .Get (fmt .Sprintf ("/recipes/{%s}/links" , recipeIdKey ), h .getRecipeLinks )
90-
69+ // Viewer
70+ viewer .HandlerFromMux (h , r )
9171 // Editor
92- r .Group (func (r chi.Router ) {
93- r .Use (h .requireEditor )
94-
95- r .Post ("/recipes" , h .postRecipe )
96- r .Put (fmt .Sprintf ("/recipes/{%s}" , recipeIdKey ), h .putRecipe )
97- r .Delete (fmt .Sprintf ("/recipes/{%s}" , recipeIdKey ), h .deleteRecipe )
98- r .Put (fmt .Sprintf ("/recipes/{%s}/state" , recipeIdKey ), h .putRecipeState )
99- r .Put (fmt .Sprintf ("/recipes/{%s}/rating" , recipeIdKey ), h .putRecipeRating )
100- r .Put (fmt .Sprintf ("/recipes/{%s}/image" , recipeIdKey ), h .putRecipeMainImage )
101- r .Post (fmt .Sprintf ("/recipes/{%s}/images" , recipeIdKey ), h .postRecipeImage )
102- r .Put (fmt .Sprintf ("/recipes/{%s}/links/{%s}" , recipeIdKey , destRecipeIdKey ), h .putRecipeLink )
103- r .Delete (fmt .Sprintf ("/recipes/{%s}/links/{%s}" , recipeIdKey , destRecipeIdKey ), h .deleteRecipeLink )
104- r .Delete (fmt .Sprintf ("/recipes/{%s}/images/{%s}" , recipeIdKey , imageIdKey ), h .deleteImage )
105- r .Post (fmt .Sprintf ("/recipes/{%s}/notes" , recipeIdKey ), h .postNote )
106- r .Put (fmt .Sprintf ("/recipes/{%s}/notes/{%s}" , recipeIdKey , noteIdKey ), h .putNote )
107- r .Delete (fmt .Sprintf ("/recipes/{%s}/notes/{%s}" , recipeIdKey , noteIdKey ), h .deleteNote )
108- r .Post ("/uploads" , h .postUpload )
109- })
110-
72+ editor .HandlerFromMux (h , r .With (h .requireEditor ))
11173 // Admin
112- r .Group (func (r chi.Router ) {
113- r .Use (h .requireAdmin )
114-
115- r .Put ("/app/configuration" , h .putAppConfiguration )
116- r .Get ("/users" , h .getUsers )
117- r .Post ("/users" , h .postUser )
118-
119- // Don't allow deleting self
120- r .With (h .disallowSelf ).Delete (fmt .Sprintf ("/users/{%s}" , userIdKey ), h .deleteUser )
121- })
122-
74+ admin .HandlerFromMux (h , r .With (h .requireAdmin ))
12375 // Admin or Self
124- r .Group (func (r chi.Router ) {
125- r .Use (h .requireAdminUnlessSelf )
126-
127- r .Get (fmt .Sprintf ("/users/{%s}" , userIdKey ), h .getUser )
128- r .Put (fmt .Sprintf ("/users/{%s}" , userIdKey ), h .putUser )
129- r .Put (fmt .Sprintf ("/users/{%s}/password" , userIdKey ), h .putUserPassword )
130- r .Get (fmt .Sprintf ("/users/{%s}/settings" , userIdKey ), h .getUserSettings )
131- r .Put (fmt .Sprintf ("/users/{%s}/settings" , userIdKey ), h .putUserSettings )
132- r .Get (fmt .Sprintf ("/users/{%s}/filters" , userIdKey ), h .getUserFilters )
133- r .Post (fmt .Sprintf ("/users/{%s}/filters" , userIdKey ), h .postUserFilter )
134- r .Get (fmt .Sprintf ("/users/{%s}/filters/{%s}" , userIdKey , filterIdKey ), h .getUserFilter )
135- r .Put (fmt .Sprintf ("/users/{%s}/filters/{%s}" , userIdKey , filterIdKey ), h .putUserFilter )
136- r .Delete (fmt .Sprintf ("/users/{%s}/filters/{%s}" , userIdKey , filterIdKey ), h .deleteUserFilter )
137- })
76+ adminOrSelf .HandlerFromMux (h , r .With (h .requireAdminUnlessSelf ))
13877 })
13978 })
14079
@@ -176,45 +115,10 @@ func (h *apiHandler) notFound(resp http.ResponseWriter, req *http.Request) {
176115 h .Error (resp , http .StatusNotFound , fmt .Errorf ("%s is not a valid API endpoint" , req .URL .Path ))
177116}
178117
179- func getParam (values url.Values , key string ) string {
180- val , _ := url .QueryUnescape (values .Get (key ))
181- return val
182- }
183-
184- func getParams (values url.Values , key string ) []string {
185- var vals []string
186- if rawVals , ok := values [key ]; ok {
187- for _ , rawVal := range rawVals {
188- safeVal , err := url .QueryUnescape (rawVal )
189- if err == nil && safeVal != "" {
190- vals = append (vals , safeVal )
191- }
192- }
193- }
194-
195- return vals
196- }
197-
198118func readJSONFromRequest (req * http.Request , data interface {}) error {
199119 return json .NewDecoder (req .Body ).Decode (data )
200120}
201121
202- func getResourceIdFromUrl (req * http.Request , idKey routeKey ) (int64 , error ) {
203- idStr := chi .URLParam (req , string (idKey ))
204-
205- // Special case for userId
206- if idKey == userIdKey && idStr == "current" {
207- return getResourceIdFromCtx (req , currentUserIdCtxKey )
208- }
209-
210- id , err := strconv .ParseInt (idStr , 10 , 64 )
211- if err != nil {
212- return 0 , fmt .Errorf ("failed to parse %s from URL, value = %s: %v" , idKey , idStr , err )
213- }
214-
215- return id , nil
216- }
217-
218122func getResourceIdFromCtx (req * http.Request , idKey * contextKey ) (int64 , error ) {
219123 idVal := req .Context ().Value (idKey )
220124
0 commit comments