@dargmuesli/nuxt-vio 20.3.0 → 20.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/nuxt.config.ts CHANGED
@@ -113,6 +113,13 @@ export default defineNuxtConfig(
113
113
  isTesting: false,
114
114
  },
115
115
  },
116
+ vio: {
117
+ email: {
118
+ nodemailer: {
119
+ transport: undefined,
120
+ },
121
+ },
122
+ },
116
123
  },
117
124
  typescript: {
118
125
  tsConfig: {
package/package.json CHANGED
@@ -35,6 +35,7 @@
35
35
  "jiti": "2.6.1",
36
36
  "jose": "6.1.3",
37
37
  "lucide-vue-next": "0.562.0",
38
+ "nodemailer": "7.0.13",
38
39
  "nuxt-gtag": "4.1.0",
39
40
  "nuxt-security": "2.5.1",
40
41
  "reka-ui": "2.7.0",
@@ -45,6 +46,7 @@
45
46
  "vue-tsc": "3.2.2"
46
47
  },
47
48
  "devDependencies": {
49
+ "@types/nodemailer": "7.0.9",
48
50
  "@types/node": "24.10.9",
49
51
  "@urql/devtools": "2.0.3",
50
52
  "@urql/exchange-graphcache": "9.0.0",
@@ -115,5 +117,5 @@
115
117
  "start:static": "serve playground/.output/public --ssl-cert ./.config/certificates/ssl.crt --ssl-key ./.config/certificates/ssl.key"
116
118
  },
117
119
  "type": "module",
118
- "version": "20.3.0"
120
+ "version": "20.5.0"
119
121
  }
@@ -0,0 +1,38 @@
1
+ import { createTransport, type Transporter } from 'nodemailer'
2
+
3
+ export default defineNitroPlugin((nitroApp) => {
4
+ const runtimeConfig = useRuntimeConfig()
5
+
6
+ if (!runtimeConfig.vio.email.nodemailer.transport) {
7
+ ;(import.meta.dev ? console.warn : console.error)(
8
+ 'The SMTP configuration secret is missing!',
9
+ )
10
+ return
11
+ }
12
+
13
+ const transporter = createTransport(
14
+ runtimeConfig.vio.email.nodemailer.transport,
15
+ )
16
+
17
+ nitroApp.hooks.hook('request', (event) => {
18
+ event.context.$email = {
19
+ nodemailer: {
20
+ transporter,
21
+ },
22
+ }
23
+ })
24
+
25
+ nitroApp.hooks.hookOnce('close', () => {
26
+ transporter.close()
27
+ })
28
+ })
29
+
30
+ declare module 'h3' {
31
+ interface H3EventContext {
32
+ $email?: {
33
+ nodemailer: {
34
+ transporter: Transporter
35
+ }
36
+ }
37
+ }
38
+ }
@@ -0,0 +1 @@
1
+ export * from './turnstile'
@@ -0,0 +1,25 @@
1
+ import { consola } from 'consola'
2
+
3
+ /**
4
+ * Verifies a Turnstile token from the request body
5
+ * @throws {Error} If token is missing or verification fails
6
+ */
7
+ export const assertTurnstileValid = async ({ token }: { token?: string }) => {
8
+ if (!token) {
9
+ throw createError({
10
+ statusCode: 422,
11
+ statusMessage: 'Turnstile token not provided.',
12
+ })
13
+ }
14
+
15
+ const result = await verifyTurnstileToken(token)
16
+
17
+ if (!result.success) {
18
+ throw createError({
19
+ statusCode: 403,
20
+ statusMessage: `Turnstile verification unsuccessful: ${result['error-codes'].join(', ')}`,
21
+ })
22
+ }
23
+
24
+ consola.debug('Turnstile verification succeeded')
25
+ }
@@ -0,0 +1 @@
1
+ export * from './dependencies'
@@ -45,6 +45,11 @@ export const VIO_GET_CSP = ({ siteUrl }: { siteUrl: URL }) =>
45
45
  // Google Service Worker (https://developers.google.com/tag-platform/tag-manager/web/csp)
46
46
  'frame-src': ['https://www.googletagmanager.com'],
47
47
  },
48
+ {
49
+ // Cloudflare Turnstile
50
+ 'frame-src': ['https://challenges.cloudflare.com'],
51
+ 'script-src-elem': ['https://challenges.cloudflare.com'],
52
+ },
48
53
  {
49
54
  // vio
50
55
  'manifest-src': [`${siteUrl}site.webmanifest`],