1+ interface AsyncNonceInterface {
2+ setup ( form : HTMLFormElement ) : Promise < void > ;
3+ }
4+
5+ class AsyncNonce {
6+ /**
7+ * Constructor for AsyncNonce.
8+ * @param modularityFrontendFormData The form data object containing API routes.
9+ */
10+ constructor (
11+ private modularityFrontendFormData : ModularityFrontendFormData
12+ ) { }
13+
14+ /**
15+ * Fetch the nonce from the server.
16+ * @returns The nonce string or null if not found.
17+ */
18+ public async get ( ) : Promise < string | null > {
19+ const url = this . modularityFrontendFormData ?. apiRoutes ?. nonceGet ;
20+
21+ if ( ! url ) {
22+ console . error ( "Nonce URL is not defined." ) ;
23+ return null ;
24+ }
25+
26+ try {
27+ const response = await fetch ( url ) ;
28+ if ( ! response . ok ) {
29+ throw new Error ( `HTTP error: ${ response . status } ` ) ;
30+ }
31+
32+ const json = await response . json ( ) ;
33+ return json ?. nonce ?? null ;
34+ } catch ( error : any ) {
35+ console . error ( "Nonce fetching failed:" , error ?. message || error ) ;
36+ return null ;
37+ }
38+ }
39+
40+ /**
41+ * Inject the nonce into the form as a hidden input field.
42+ * @param form The form element to inject the nonce into.
43+ * @param nonce The nonce value to inject.
44+ */
45+ public inject ( form : HTMLFormElement , nonce : string , nonceElementId : string ) : void {
46+ if ( this . isNoncePresent ( form , nonceElementId ) ) {
47+ this . removeNonce ( form , nonceElementId ) ;
48+ }
49+
50+ form . appendChild (
51+ this . createNonceElement ( nonce , nonceElementId )
52+ ) ;
53+ }
54+
55+ /**
56+ * Check if the nonce is already present in the form.
57+ * @param form The form element to check.
58+ * @returns True if the nonce is present, false otherwise.
59+ */
60+ public isNoncePresent ( form : HTMLFormElement , nonceElementId : string ) : boolean {
61+ return form . querySelector ( "#" + nonceElementId ) !== null ;
62+ }
63+
64+ /**
65+ * Remove the nonce from the form.
66+ * @param form The form element to remove the nonce from.
67+ */
68+ public removeNonce ( form : HTMLFormElement , nonceElementId : string ) : void {
69+ const existingNonceInput = form . querySelector ( "#" + nonceElementId ) ;
70+ if ( existingNonceInput ) {
71+ form . removeChild ( existingNonceInput ) ;
72+ }
73+ }
74+
75+ /**
76+ * Create a nonce element to be injected into the form.
77+ * @param nonce The nonce value to inject.
78+ * @param nonceElementId The ID for the nonce input element.
79+ * @returns The created input element.
80+ */
81+ public createNonceElement ( nonce : string , nonceElementId : string ) : HTMLInputElement {
82+ const nonceInput = document . createElement ( "input" ) ;
83+
84+ nonceInput . id = nonceElementId ;
85+ nonceInput . type = "hidden" ;
86+ nonceInput . name = "nonce" ;
87+ nonceInput . value = nonce ;
88+
89+ nonceInput . setAttribute ( "aria-hidden" , "true" ) ;
90+ nonceInput . setAttribute ( "autocomplete" , "off" ) ;
91+ nonceInput . setAttribute ( "autocorrect" , "off" ) ;
92+
93+ return nonceInput ;
94+ }
95+
96+ /**
97+ * Setup the nonce by fetching it and injecting it into the form.
98+ * @param form The form element to inject the nonce into.
99+ */
100+ public async setup (
101+ form : HTMLFormElement
102+ ) : Promise < void > {
103+ console . log ( "Setting up nonce..." ) ;
104+ const nonce = await this . get ( ) ;
105+ if ( nonce ) {
106+ console . log ( "Nonce fetched successfully:" , nonce ) ;
107+ this . inject ( form , nonce , "async-nonce-element" ) ;
108+ } else {
109+ console . error ( "Nonce is not defined." ) ;
110+ }
111+ }
112+ }
113+ export default AsyncNonce ;
0 commit comments