Skip to content

Commit 10e4f98

Browse files
committed
refactor: add docblocks
1 parent 33713b4 commit 10e4f98

File tree

13 files changed

+326
-42
lines changed

13 files changed

+326
-42
lines changed

src/debug.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,12 @@
88
*/
99

1010
import { debuglog } from 'node:util'
11+
12+
/**
13+
* Debug logger instance for the Shield package.
14+
* Logs debug messages when NODE_DEBUG=adonisjs:shield is set.
15+
*
16+
* @example
17+
* debug('csrf: ignoring request for "%s" method', ctx.request.method())
18+
*/
1119
export default debuglog('adonisjs:shield')

src/define_config.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,16 @@
1010
import type { ShieldConfig } from './types.ts'
1111

1212
/**
13-
* Define shield configuration
13+
* Define shield configuration with default values.
14+
* Merges provided partial configuration with defaults where all guards are disabled by default.
15+
*
16+
* @param config - Partial shield configuration object
17+
*
18+
* @example
19+
* const shieldConfig = defineConfig({
20+
* csrf: { enabled: true },
21+
* hsts: { enabled: true, maxAge: '1 year' }
22+
* })
1423
*/
1524
export function defineConfig(config: Partial<ShieldConfig>): ShieldConfig {
1625
return {

src/errors.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ import type { I18n } from '@adonisjs/i18n'
1313
import { Exception } from '@adonisjs/core/exceptions'
1414
import { type HttpContext } from '@adonisjs/core/http'
1515

16+
/**
17+
* Exception class for invalid or expired CSRF tokens.
18+
* Handles CSRF validation failures by flashing errors and redirecting back.
19+
*
20+
* @example
21+
* throw new E_BAD_CSRF_TOKEN()
22+
*/
1623
export const E_BAD_CSRF_TOKEN = class InvalidCSRFToken extends Exception {
1724
code = 'E_BAD_CSRF_TOKEN'
1825
status = 403
@@ -23,6 +30,9 @@ export const E_BAD_CSRF_TOKEN = class InvalidCSRFToken extends Exception {
2330
* Returns the message to be sent in the HTTP response.
2431
* Feel free to override this method and return a custom
2532
* response.
33+
*
34+
* @param error - The error instance
35+
* @param ctx - The HTTP context
2636
*/
2737
getResponseMessage(error: this, ctx: HttpContext) {
2838
if ('i18n' in ctx) {
@@ -31,6 +41,13 @@ export const E_BAD_CSRF_TOKEN = class InvalidCSRFToken extends Exception {
3141
return error.message
3242
}
3343

44+
/**
45+
* Handles the CSRF error by flashing session data and redirecting back.
46+
* For non-Inertia requests, flashes all session data except sensitive fields.
47+
*
48+
* @param error - The error instance
49+
* @param ctx - The HTTP context
50+
*/
3451
async handle(error: this, ctx: HttpContext) {
3552
if (!ctx.request.header('X-Inertia')) {
3653
ctx.session.flashExcept(['_csrf', '_method', 'password', 'password_confirmation'])

src/guards/csp/keywords.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,33 @@ import type { ContentSecurityPolicyOptions } from '../../helmet-csp.cts'
1414

1515
/**
1616
* A collection of CSP keywords that are resolved to actual values
17-
* during an HTTP request.
17+
* during an HTTP request. Allows registration of dynamic CSP directive values.
18+
*
19+
* @example
20+
* cspKeywords.register('@nonce', (req, res) => `'nonce-${res.nonce}'`)
1821
*/
1922
class CSPKeywords {
23+
/**
24+
* Registry of keyword resolvers that transform keywords to CSP directive values
25+
*/
2026
#keywordsResolvers: Record<string, (_: IncomingMessage, response: ServerResponse) => string> = {}
2127

2228
/**
23-
* Register a custom CSP directive keyword and resolve
24-
* it to a value during an HTTP request.
29+
* Registers a custom CSP directive keyword and its resolver function.
30+
* The resolver function transforms the keyword to an actual CSP value during requests.
31+
*
32+
* @param keyword - The keyword to register (e.g., '@nonce')
33+
* @param resolver - Function that resolves the keyword to a CSP value
2534
*/
2635
register(keyword: string, resolver: (_: IncomingMessage, response: ServerResponse) => string) {
2736
this.#keywordsResolvers[keyword] = resolver
2837
return this
2938
}
3039

3140
/**
32-
* Resolves keywords
41+
* Resolves registered keywords in CSP directive values to their actual values.
42+
*
43+
* @param directiveValues - The directive values that may contain keywords
3344
*/
3445
resolve(
3546
directiveValues: ValueOf<Exclude<ContentSecurityPolicyOptions['directives'], undefined>>
@@ -48,5 +59,11 @@ class CSPKeywords {
4859
}
4960
}
5061

62+
/**
63+
* Global instance of CSPKeywords for registering and resolving CSP directive keywords.
64+
*
65+
* @example
66+
* cspKeywords.register('@nonce', (req, res) => `'nonce-${res.nonce}'`)
67+
*/
5168
const cspKeywords = new CSPKeywords()
5269
export { cspKeywords }

src/guards/csp/main.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,18 @@ cspKeywords.register('@nonce', function (_, response) {
2727

2828
/**
2929
* Factory that returns a function to set the `Content-Security-Policy` header based upon
30-
* the user config
30+
* the user configuration. Provides protection against XSS and code injection attacks.
31+
*
32+
* @param options - CSP configuration options
33+
*
34+
* @example
35+
* const cspGuard = cspFactory({
36+
* enabled: true,
37+
* directives: {
38+
* defaultSrc: ["'self'"],
39+
* scriptSrc: ["'self'", '@nonce']
40+
* }
41+
* })
3142
*/
3243
export function cspFactory(options: CspOptions) {
3344
if (!options.enabled) {

src/guards/csrf.ts

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ export class CsrfGuard {
6161
*/
6262
#edge?: Edge
6363

64+
/**
65+
* Creates a new CsrfGuard instance.
66+
*
67+
* @param options - CSRF configuration options
68+
* @param encryption - Encryption service instance
69+
* @param edge - Optional Edge template engine instance
70+
*/
6471
constructor(options: CsrfOptions, encryption: Encryption, edge?: Edge) {
6572
this.#options = options
6673
this.#encryption = encryption
@@ -71,7 +78,10 @@ export class CsrfGuard {
7178
}
7279

7380
/**
74-
* Find if a request should be validated or not
81+
* Determines if a request should be validated for CSRF tokens.
82+
* Checks against allowed methods and routes to ignore.
83+
*
84+
* @param ctx - HTTP context object
7585
*/
7686
#shouldValidateRequest(ctx: HttpContext) {
7787
/**
@@ -106,12 +116,12 @@ export class CsrfGuard {
106116
}
107117

108118
/**
109-
* Read csrf token from one of the following sources.
119+
* Reads CSRF token from one of the following sources:
120+
* - `_csrf` form input field
121+
* - `x-csrf-token` request header
122+
* - `x-xsrf-token` header (when XSRF cookie is enabled)
110123
*
111-
* - `_csrf` input
112-
* - `x-csrf-token` header
113-
* - Or `x-xsrf-token` header. The header value must be set by
114-
* reading the `XSRF-TOKEN` cookie.
124+
* @param ctx - HTTP context object containing the request
115125
*/
116126
#getCsrfTokenFromRequest({ request }: HttpContext): string | null {
117127
if (request.input('_csrf')) {
@@ -142,7 +152,10 @@ export class CsrfGuard {
142152
}
143153

144154
/**
145-
* Share csrf helper methods with the view engine.
155+
* Shares CSRF helper methods with the view engine.
156+
* Makes csrfToken, csrfMeta(), and csrfField() available in templates.
157+
*
158+
* @param ctx - HTTP context object
146159
*/
147160
#shareCsrfViewLocals(ctx: HttpContext): void {
148161
if (!ctx.view || !this.#edge) {
@@ -165,16 +178,19 @@ export class CsrfGuard {
165178
}
166179

167180
/**
168-
* Generate a new csrf token using the csrf secret extracted from session.
181+
* Generates a new CSRF token using the CSRF secret extracted from session.
182+
*
183+
* @param csrfSecret - The CSRF secret from the user's session
169184
*/
170185
#generateCsrfToken(csrfSecret: string): string {
171186
return this.#tokens.create(csrfSecret)
172187
}
173188

174189
/**
175-
* Return the existing CSRF secret from the session or create a
176-
* new one. Newly created secret is persisted to session at
177-
* the same time
190+
* Returns the existing CSRF secret from the session or creates a new one.
191+
* Newly created secrets are persisted to the session automatically.
192+
*
193+
* @param ctx - HTTP context object
178194
*/
179195
async #getCsrfSecret(ctx: HttpContext): Promise<string> {
180196
let csrfSecret = ctx.session.get(this.#secretSessionKey)
@@ -189,10 +205,11 @@ export class CsrfGuard {
189205
}
190206

191207
/**
192-
* Handle csrf verification. First, get the secret,
193-
* next, check if the request method should be
194-
* verified. Next, attach the newly generated
195-
* csrf token to the request object.
208+
* Handles CSRF verification for the current request.
209+
* Gets or creates a CSRF secret, generates a token, optionally sets XSRF cookie,
210+
* shares helpers with views, and validates the request if required.
211+
*
212+
* @param ctx - HTTP context object
196213
*/
197214
async handle(ctx: HttpContext): Promise<void> {
198215
const csrfSecret = await this.#getCsrfSecret(ctx)
@@ -230,8 +247,18 @@ export class CsrfGuard {
230247
}
231248

232249
/**
233-
* A factory function that returns a new function to enforce CSRF
234-
* protection
250+
* A factory function that returns a new function to enforce CSRF protection.
251+
* Creates a CsrfGuard instance and returns its handle method.
252+
*
253+
* @param options - CSRF configuration options
254+
* @param encryption - Encryption service instance
255+
* @param edge - Optional Edge template engine instance
256+
*
257+
* @example
258+
* const csrfGuard = csrfFactory({
259+
* enabled: true,
260+
* methods: ['POST', 'PUT', 'DELETE']
261+
* }, encryption, edge)
235262
*/
236263
export function csrfFactory(options: CsrfOptions, encryption: Encryption, edge?: Edge) {
237264
if (!options.enabled) {

src/guards/frame_guard.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ const ALLOWED_ACTIONS = ['DENY', 'ALLOW-FROM', 'SAMEORIGIN']
1616

1717
/**
1818
* Factory function that returns a function to set `X-Frame-Options` header
19-
* based upon given user options.
19+
* based upon given user options. Prevents clickjacking attacks.
20+
*
21+
* @param options - Frame guard configuration options
22+
*
23+
* @example
24+
* const frameGuard = frameGuardFactory({
25+
* enabled: true,
26+
* action: 'SAMEORIGIN'
27+
* })
2028
*/
2129
export function frameGuardFactory(options: XFrameOptions) {
2230
if (!options.enabled) {

src/guards/hsts.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ import type { HstsOptions } from '../types.ts'
1616
const DEFAULT_MAX_AGE = 180 * 24 * 60 * 60
1717

1818
/**
19-
* Normalizes the max age to seconds
19+
* Normalizes the max age to seconds.
20+
* Converts string-based time expressions to seconds or uses the provided number.
21+
*
22+
* @param maxAge - The max age value as string (e.g., '1 year') or number (seconds)
2023
*/
2124
function normalizeMaxAge(maxAge?: string | number): number {
2225
if (maxAge === null || maxAge === undefined) {
@@ -32,8 +35,17 @@ function normalizeMaxAge(maxAge?: string | number): number {
3235
}
3336

3437
/**
35-
* Factory function that returns a new function to Add `Strict-Transport-Security`
36-
* header based upon given user options.
38+
* Factory function that returns a new function to add `Strict-Transport-Security`
39+
* header based upon given user options. Enables HTTPS enforcement for enhanced security.
40+
*
41+
* @param options - HSTS configuration options
42+
*
43+
* @example
44+
* const hstsGuard = hstsFactory({
45+
* enabled: true,
46+
* maxAge: '1 year',
47+
* includeSubDomains: true
48+
* })
3749
*/
3850
export function hstsFactory(options: HstsOptions) {
3951
if (!options.enabled) {

src/guards/no_sniff.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ import type { ContentTypeSniffingOptions } from '../types.ts'
1212
import { noop } from '../noop.ts'
1313

1414
/**
15-
* Factory function that returns a function to Add `X-Content-Type-Options`
16-
* header based upon given user options.
15+
* Factory function that returns a function to add `X-Content-Type-Options`
16+
* header based upon given user options. Prevents MIME type sniffing attacks.
17+
*
18+
* @param options - Content type sniffing configuration options
19+
*
20+
* @example
21+
* const noSniffGuard = noSniffFactory({ enabled: true })
1722
*/
1823
export function noSniffFactory(options: ContentTypeSniffingOptions) {
1924
if (!options.enabled) {

src/noop.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,15 @@
88
*/
99

1010
import type { HttpContext } from '@adonisjs/core/http'
11+
12+
/**
13+
* A no-operation function that does nothing with the provided HTTP context.
14+
* Used as a placeholder when a guard is disabled.
15+
*
16+
* @param _ - The HTTP context (unused)
17+
*
18+
* @example
19+
* const guard = options.enabled ? actualGuard : noop
20+
* guard(ctx)
21+
*/
1122
export function noop(_: HttpContext) {}

0 commit comments

Comments
 (0)