🎨 Style!: Update CSRF and Limiter to remove repetitive names (#2846)

chore!: Update CSRF and Limiter to remove repetitive names

The `exported` rule of revive warns to not repeat the package name in
method names. For example, prefer `csrf.FromCookie` over
`csrf.CsrfFromCookie`.

This is a breaking change for v3.

It appears that these issues will not be caught by the linter until the
`exported` rule is reenabled. This requires comments on all exported
symbols, which is a much broader effort.
pull/2848/head
nickajacks1 2024-02-10 10:50:29 -08:00 committed by GitHub
parent 70067a1754
commit 97da409533
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 34 additions and 35 deletions

View File

@ -109,8 +109,6 @@ linters-settings:
disabled: true disabled: true
- name: exported - name: exported
disabled: true disabled: true
arguments:
- disableStutteringCheck # TODO https://github.com/gofiber/fiber/issues/2816
- name: file-header - name: file-header
disabled: true disabled: true
- name: function-result-limit - name: function-result-limit

View File

@ -31,7 +31,7 @@ By default, the middleware generates and stores tokens using the `fiber.Storage`
When the authorization status changes, the previously issued token MUST be deleted, and a new one generated. See [Token Lifecycle](#token-lifecycle) [Deleting Tokens](#deleting-tokens) for more information. When the authorization status changes, the previously issued token MUST be deleted, and a new one generated. See [Token Lifecycle](#token-lifecycle) [Deleting Tokens](#deleting-tokens) for more information.
:::caution :::caution
When using this pattern, it's important to set the `CookieSameSite` option to `Lax` or `Strict` and ensure that the Extractor is not `CsrfFromCookie`, and KeyLookup is not `cookie:<name>`. When using this pattern, it's important to set the `CookieSameSite` option to `Lax` or `Strict` and ensure that the Extractor is not `FromCookie`, and KeyLookup is not `cookie:<name>`.
::: :::
:::note :::note
@ -206,7 +206,7 @@ var ConfigDefault = Config{
Expiration: 1 * time.Hour, Expiration: 1 * time.Hour,
KeyGenerator: utils.UUIDv4, KeyGenerator: utils.UUIDv4,
ErrorHandler: defaultErrorHandler, ErrorHandler: defaultErrorHandler,
Extractor: CsrfFromHeader(HeaderName), Extractor: FromHeader(HeaderName),
SessionKey: "csrfToken", SessionKey: "csrfToken",
} }
``` ```
@ -226,7 +226,7 @@ var ConfigDefault = Config{
Expiration: 1 * time.Hour, Expiration: 1 * time.Hour,
KeyGenerator: utils.UUIDv4, KeyGenerator: utils.UUIDv4,
ErrorHandler: defaultErrorHandler, ErrorHandler: defaultErrorHandler,
Extractor: CsrfFromHeader(HeaderName), Extractor: FromHeader(HeaderName),
Session: session.Store, Session: session.Store,
SessionKey: "csrfToken", SessionKey: "csrfToken",
} }

View File

@ -117,7 +117,7 @@ var ConfigDefault = Config{
Expiration: 1 * time.Hour, Expiration: 1 * time.Hour,
KeyGenerator: utils.UUIDv4, KeyGenerator: utils.UUIDv4,
ErrorHandler: defaultErrorHandler, ErrorHandler: defaultErrorHandler,
Extractor: CsrfFromHeader(HeaderName), Extractor: FromHeader(HeaderName),
SessionKey: "csrfToken", SessionKey: "csrfToken",
} }
@ -169,15 +169,15 @@ func configDefault(config ...Config) Config {
if cfg.Extractor == nil { if cfg.Extractor == nil {
// By default we extract from a header // By default we extract from a header
cfg.Extractor = CsrfFromHeader(textproto.CanonicalMIMEHeaderKey(selectors[1])) cfg.Extractor = FromHeader(textproto.CanonicalMIMEHeaderKey(selectors[1]))
switch selectors[0] { switch selectors[0] {
case "form": case "form":
cfg.Extractor = CsrfFromForm(selectors[1]) cfg.Extractor = FromForm(selectors[1])
case "query": case "query":
cfg.Extractor = CsrfFromQuery(selectors[1]) cfg.Extractor = FromQuery(selectors[1])
case "param": case "param":
cfg.Extractor = CsrfFromParam(selectors[1]) cfg.Extractor = FromParam(selectors[1])
case "cookie": case "cookie":
if cfg.Session == nil { if cfg.Session == nil {
log.Warn("[CSRF] Cookie extractor is not recommended without a session store") log.Warn("[CSRF] Cookie extractor is not recommended without a session store")
@ -185,7 +185,7 @@ func configDefault(config ...Config) Config {
if cfg.CookieSameSite == "None" || cfg.CookieSameSite != "Lax" && cfg.CookieSameSite != "Strict" { if cfg.CookieSameSite == "None" || cfg.CookieSameSite != "Lax" && cfg.CookieSameSite != "Strict" {
log.Warn("[CSRF] Cookie extractor is only recommended for use with SameSite=Lax or SameSite=Strict") log.Warn("[CSRF] Cookie extractor is only recommended for use with SameSite=Lax or SameSite=Strict")
} }
cfg.Extractor = CsrfFromCookie(selectors[1]) cfg.Extractor = FromCookie(selectors[1])
cfg.CookieName = selectors[1] // Cookie name is the same as the key cfg.CookieName = selectors[1] // Cookie name is the same as the key
} }
} }

View File

@ -17,7 +17,8 @@ var (
dummyValue = []byte{'+'} dummyValue = []byte{'+'}
) )
type CSRFHandler struct { // Handler handles
type Handler struct {
config *Config config *Config
sessionManager *sessionManager sessionManager *sessionManager
storageManager *storageManager storageManager *storageManager
@ -58,7 +59,7 @@ func New(config ...Config) fiber.Handler {
} }
// Store the CSRF handler in the context // Store the CSRF handler in the context
c.Locals(handlerKey, &CSRFHandler{ c.Locals(handlerKey, &Handler{
config: &cfg, config: &cfg,
sessionManager: sessionManager, sessionManager: sessionManager,
storageManager: storageManager, storageManager: storageManager,
@ -98,10 +99,10 @@ func New(config ...Config) fiber.Handler {
return cfg.ErrorHandler(c, ErrTokenNotFound) return cfg.ErrorHandler(c, ErrTokenNotFound)
} }
// If not using CsrfFromCookie extractor, check that the token matches the cookie // If not using FromCookie extractor, check that the token matches the cookie
// This is to prevent CSRF attacks by using a Double Submit Cookie method // This is to prevent CSRF attacks by using a Double Submit Cookie method
// Useful when we do not have access to the users Session // Useful when we do not have access to the users Session
if !isCsrfFromCookie(cfg.Extractor) && !compareStrings(extractedToken, c.Cookies(cfg.CookieName)) { if !isFromCookie(cfg.Extractor) && !compareStrings(extractedToken, c.Cookies(cfg.CookieName)) {
return cfg.ErrorHandler(c, ErrTokenInvalid) return cfg.ErrorHandler(c, ErrTokenInvalid)
} }
@ -154,10 +155,10 @@ func TokenFromContext(c fiber.Ctx) string {
return token return token
} }
// HandlerFromContext returns the CSRFHandler found in the context // HandlerFromContext returns the Handler found in the context
// returns nil if the handler does not exist // returns nil if the handler does not exist
func HandlerFromContext(c fiber.Ctx) *CSRFHandler { func HandlerFromContext(c fiber.Ctx) *Handler {
handler, ok := c.Locals(handlerKey).(*CSRFHandler) handler, ok := c.Locals(handlerKey).(*Handler)
if !ok { if !ok {
return nil return nil
} }
@ -219,11 +220,11 @@ func setCSRFCookie(c fiber.Ctx, cfg Config, token string, expiry time.Duration)
// DeleteToken removes the token found in the context from the storage // DeleteToken removes the token found in the context from the storage
// and expires the CSRF cookie // and expires the CSRF cookie
func (handler *CSRFHandler) DeleteToken(c fiber.Ctx) error { func (handler *Handler) DeleteToken(c fiber.Ctx) error {
// Get the config from the context // Get the config from the context
config := handler.config config := handler.config
if config == nil { if config == nil {
panic("CSRFHandler config not found in context") panic("CSRF Handler config not found in context")
} }
// Extract token from the client request cookie // Extract token from the client request cookie
cookieToken := c.Cookies(config.CookieName) cookieToken := c.Cookies(config.CookieName)
@ -237,9 +238,9 @@ func (handler *CSRFHandler) DeleteToken(c fiber.Ctx) error {
return nil return nil
} }
// isCsrfFromCookie checks if the extractor is set to ExtractFromCookie // isFromCookie checks if the extractor is set to ExtractFromCookie
func isCsrfFromCookie(extractor any) bool { func isFromCookie(extractor any) bool {
return reflect.ValueOf(extractor).Pointer() == reflect.ValueOf(CsrfFromCookie).Pointer() return reflect.ValueOf(extractor).Pointer() == reflect.ValueOf(FromCookie).Pointer()
} }
// refererMatchesHost checks that the referer header matches the host header // refererMatchesHost checks that the referer header matches the host header

View File

@ -14,8 +14,8 @@ var (
ErrMissingCookie = errors.New("missing csrf token in cookie") ErrMissingCookie = errors.New("missing csrf token in cookie")
) )
// csrfFromParam returns a function that extracts token from the url param string. // FromParam returns a function that extracts token from the url param string.
func CsrfFromParam(param string) func(c fiber.Ctx) (string, error) { func FromParam(param string) func(c fiber.Ctx) (string, error) {
return func(c fiber.Ctx) (string, error) { return func(c fiber.Ctx) (string, error) {
token := c.Params(param) token := c.Params(param)
if token == "" { if token == "" {
@ -25,8 +25,8 @@ func CsrfFromParam(param string) func(c fiber.Ctx) (string, error) {
} }
} }
// csrfFromForm returns a function that extracts a token from a multipart-form. // FromForm returns a function that extracts a token from a multipart-form.
func CsrfFromForm(param string) func(c fiber.Ctx) (string, error) { func FromForm(param string) func(c fiber.Ctx) (string, error) {
return func(c fiber.Ctx) (string, error) { return func(c fiber.Ctx) (string, error) {
token := c.FormValue(param) token := c.FormValue(param)
if token == "" { if token == "" {
@ -36,8 +36,8 @@ func CsrfFromForm(param string) func(c fiber.Ctx) (string, error) {
} }
} }
// csrfFromCookie returns a function that extracts token from the cookie header. // FromCookie returns a function that extracts token from the cookie header.
func CsrfFromCookie(param string) func(c fiber.Ctx) (string, error) { func FromCookie(param string) func(c fiber.Ctx) (string, error) {
return func(c fiber.Ctx) (string, error) { return func(c fiber.Ctx) (string, error) {
token := c.Cookies(param) token := c.Cookies(param)
if token == "" { if token == "" {
@ -47,8 +47,8 @@ func CsrfFromCookie(param string) func(c fiber.Ctx) (string, error) {
} }
} }
// csrfFromHeader returns a function that extracts token from the request header. // FromHeader returns a function that extracts token from the request header.
func CsrfFromHeader(param string) func(c fiber.Ctx) (string, error) { func FromHeader(param string) func(c fiber.Ctx) (string, error) {
return func(c fiber.Ctx) (string, error) { return func(c fiber.Ctx) (string, error) {
token := c.Get(param) token := c.Get(param)
if token == "" { if token == "" {
@ -58,8 +58,8 @@ func CsrfFromHeader(param string) func(c fiber.Ctx) (string, error) {
} }
} }
// csrfFromQuery returns a function that extracts token from the query string. // FromQuery returns a function that extracts token from the query string.
func CsrfFromQuery(param string) func(c fiber.Ctx) (string, error) { func FromQuery(param string) func(c fiber.Ctx) (string, error) {
return func(c fiber.Ctx) (string, error) { return func(c fiber.Ctx) (string, error) {
token := fiber.Query[string](c, param) token := fiber.Query[string](c, param)
if token == "" { if token == "" {

View File

@ -55,7 +55,7 @@ type Config struct {
// LimiterMiddleware is the struct that implements a limiter middleware. // LimiterMiddleware is the struct that implements a limiter middleware.
// //
// Default: a new Fixed Window Rate Limiter // Default: a new Fixed Window Rate Limiter
LimiterMiddleware LimiterHandler LimiterMiddleware Handler
} }
// ConfigDefault is the default config // ConfigDefault is the default config

View File

@ -11,7 +11,7 @@ const (
xRateLimitReset = "X-RateLimit-Reset" xRateLimitReset = "X-RateLimit-Reset"
) )
type LimiterHandler interface { type Handler interface {
New(config Config) fiber.Handler New(config Config) fiber.Handler
} }