feat: add permissions on user create, CORS middleware, cors server playground.
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"database/sql"
|
||||
"flag"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -48,6 +49,10 @@ type config struct {
|
||||
password string
|
||||
sender string
|
||||
}
|
||||
// Add a cors struct and trustedOrigins field with the type []string.
|
||||
cors struct {
|
||||
trustedOrigins []string
|
||||
}
|
||||
}
|
||||
|
||||
// Define an application struct to hold the dependencies for our HTTP handlers, helpers,
|
||||
@@ -101,6 +106,17 @@ func main() {
|
||||
flag.StringVar(&cfg.smtp.password, "smtp-password", "d06a774b484ca3", "SMTP password")
|
||||
flag.StringVar(&cfg.smtp.sender, "smtp-sender", "Greenlight <no-reply@greenlight.debuggingjon.dev>", "SMTP sender")
|
||||
|
||||
// Use the flag.Func() function to process the -cors-trusted-origins command line
|
||||
// flag. In this we use the strings.Fields() function to split the flag value into a
|
||||
// slice based on whitespace characters and assign it to our config struct.
|
||||
// Importantly, if the -cors-trusted-origins flag is not present, contains the empty
|
||||
// string, or contains only whitespace, then strings.Fields() will return an empty
|
||||
// []string slice.
|
||||
flag.Func("cors-trusted-origins", "Trusted CORS origins (space separated)", func(val string) error {
|
||||
cfg.cors.trustedOrigins = strings.Fields(val)
|
||||
return nil
|
||||
})
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// Call the openDB() helper function (see below) to create the connection pool,
|
||||
|
||||
@@ -244,3 +244,30 @@ func (app *application) requirePermission(code string, next http.HandlerFunc) ht
|
||||
// Wrap this with the requireActivatedUser() middleware before returning it.
|
||||
return app.requireActivatedUser(fn)
|
||||
}
|
||||
|
||||
func (app *application) enableCORS(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Add the "Vary: Origin" header.
|
||||
w.Header().Add("Vary", "Origin")
|
||||
|
||||
// Get the value of the request's Origin header.
|
||||
origin := r.Header.Get("Origin")
|
||||
|
||||
// Only run this if there's an Origin request header present AND at least one
|
||||
// trusted origin is configured.
|
||||
if origin != "" && len(app.config.cors.trustedOrigins) != 0 {
|
||||
// Loop through the list of trusted origins, checking to see if the request
|
||||
// origin exactly matches one of them.
|
||||
for i := range app.config.cors.trustedOrigins {
|
||||
if origin == app.config.cors.trustedOrigins[i] {
|
||||
// If there is a match, then set a "Access-Control-Allow-Origin
|
||||
// response header with the request origin as the value.
|
||||
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the next handler in the chain.
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -28,5 +28,5 @@ func (app *application) routes() http.Handler {
|
||||
router.HandlerFunc(http.MethodPost, "/v1/tokens/authentication",
|
||||
app.createAuthenticationTokenHandler)
|
||||
|
||||
return app.recoverPanic(app.rateLimit(app.authenticate(router)))
|
||||
return app.recoverPanic(app.enableCORS(app.rateLimit(app.authenticate(router))))
|
||||
}
|
||||
|
||||
@@ -63,6 +63,13 @@ func (app *application) registerUserHandler(w http.ResponseWriter, r *http.Reque
|
||||
return
|
||||
}
|
||||
|
||||
// Add the "movies:read" permission for the new user.
|
||||
err = app.models.Permissions.AddForUser(user.ID, "movies:read")
|
||||
if err != nil {
|
||||
app.serverErrorResponse(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
// After the user record has been created in the database, generate a new activation
|
||||
// token for the user.
|
||||
token, err := app.models.Tokens.New(user.ID, 3*24*time.Hour, data.ScopeActivation)
|
||||
|
||||
Reference in New Issue
Block a user