@dargmuesli/nuxt-vio 14.0.0 → 14.0.2

Sign up to get free protection for your applications and to get access to all the features.
package/.config/lint.js CHANGED
@@ -6,11 +6,12 @@ import eslintPluginCompat from 'eslint-plugin-compat'
6
6
  import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
7
7
  import eslintPluginYml from 'eslint-plugin-yml'
8
8
  import globals from 'globals'
9
- import jiti from 'jiti'
9
+ import { createJiti } from 'jiti'
10
10
 
11
- const moduleFileUrl = new URL(import.meta.url)
12
- const JITI = jiti(moduleFileUrl.pathname)
13
- const POLYFILLS = JITI('../utils/constants.ts').POLYFILLS
11
+ const jiti = createJiti(import.meta.url)
12
+ const constants = await jiti.import('../utils/constants.ts')
13
+ // @ts-ignore
14
+ const POLYFILLS = constants.POLYFILLS
14
15
 
15
16
  const vueI18nConfiguration = vueI18n.configs['flat/recommended']
16
17
  const compatConfiguration = eslintPluginCompat.configs['flat/recommended']
@@ -1,5 +1,3 @@
1
- import { GTAG_COOKIE_ID } from '../utils/constants'
2
-
3
1
  export const useVioGtag = () => {
4
2
  const {
5
3
  gtag,
@@ -8,9 +6,27 @@ export const useVioGtag = () => {
8
6
  enableAnalytics,
9
7
  } = useGtag()
10
8
  const cookieControl = useCookieControl()
9
+ const updateConsent = ({ isGranted }: { isGranted: boolean }) => {
10
+ gtag('consent', 'update', {
11
+ // // the following are denied per default in the gtag module configuration
12
+ // ad_user_data: 'denied',
13
+ // ad_personalization: 'denied',
14
+ // ad_storage: 'denied',
15
+ analytics_storage: isGranted ? 'granted' : 'denied',
16
+ })
17
+ }
18
+ const enableGtag = () => {
19
+ updateConsent({ isGranted: true })
20
+ initializeGtag()
21
+ enableAnalytics()
22
+ }
23
+ const disableGtag = () => {
24
+ updateConsent({ isGranted: false })
25
+ disableAnalytics()
26
+ }
11
27
 
12
28
  if (cookieControl.cookiesEnabledIds.value?.includes(GTAG_COOKIE_ID)) {
13
- initializeGtag()
29
+ enableGtag()
14
30
  }
15
31
 
16
32
  watch(cookieControl.cookiesEnabledIds, (current, previous) => {
@@ -18,21 +34,14 @@ export const useVioGtag = () => {
18
34
  !previous?.includes(GTAG_COOKIE_ID) &&
19
35
  current?.includes(GTAG_COOKIE_ID)
20
36
  ) {
21
- gtag('consent', 'update', {
22
- ad_user_data: 'denied',
23
- ad_personalization: 'denied',
24
- ad_storage: 'denied',
25
- analytics_storage: 'granted',
26
- })
27
- initializeGtag()
28
- enableAnalytics()
37
+ enableGtag()
29
38
  }
30
39
 
31
40
  if (
32
41
  previous?.includes(GTAG_COOKIE_ID) &&
33
42
  !current?.includes(GTAG_COOKIE_ID)
34
43
  ) {
35
- disableAnalytics()
44
+ disableGtag()
36
45
  }
37
46
  })
38
47
  }
package/nuxt.config.ts CHANGED
@@ -224,7 +224,6 @@ export default defineNuxtConfig(
224
224
  'frame-src': false as const,
225
225
  'img-src': false as const,
226
226
  'media-src': false as const,
227
- 'navigate-to': false as const,
228
227
  'object-src': false as const,
229
228
  'prefetch-src': false as const,
230
229
  'report-to': undefined,
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "dependencies": {
3
- "@dargmuesli/nuxt-cookie-control": "8.4.12",
3
+ "@dargmuesli/nuxt-cookie-control": "8.4.13",
4
4
  "@eslint/compat": "1.1.1",
5
5
  "@heroicons/vue": "2.1.5",
6
6
  "@http-util/status-i18n": "0.8.1",
7
7
  "@intlify/eslint-plugin-vue-i18n": "3.0.0",
8
- "@nuxt/devtools": "1.4.2",
8
+ "@nuxt/devtools": "1.5.1",
9
9
  "@nuxt/eslint": "0.5.7",
10
10
  "@nuxt/image": "1.8.0",
11
11
  "@nuxtjs/color-mode": "3.5.1",
@@ -22,16 +22,16 @@
22
22
  "@vuelidate/validators": "2.0.4",
23
23
  "clipboardy": "4.0.0",
24
24
  "dayjs": "2.0.0-alpha.4",
25
- "eslint": "9.10.0",
25
+ "eslint": "9.11.1",
26
26
  "eslint-config-prettier": "9.1.0",
27
27
  "eslint-plugin-compat": "6.0.1",
28
28
  "eslint-plugin-prettier": "5.2.1",
29
29
  "eslint-plugin-yml": "1.14.0",
30
30
  "globals": "15.9.0",
31
- "jose": "5.9.2",
31
+ "jose": "5.9.3",
32
32
  "nuxt-gtag": "3.0.1",
33
- "nuxt-security": "2.0.0-rc.9",
34
- "sweetalert2": "11.14.0",
33
+ "nuxt-security": "2.0.0",
34
+ "sweetalert2": "11.14.1",
35
35
  "vue-tsc": "2.1.6"
36
36
  },
37
37
  "devDependencies": {
@@ -43,21 +43,21 @@
43
43
  "cookie-es": "1.2.2",
44
44
  "defu": "6.1.4",
45
45
  "h3": "1.12.0",
46
- "jiti": "1.21.6",
46
+ "jiti": "2.0.0",
47
47
  "lodash-es": "4.17.21",
48
48
  "nuxt": "3.13.2",
49
49
  "pinia": "2.2.2",
50
50
  "prettier": "3.3.3",
51
- "prettier-plugin-tailwindcss": "0.6.6",
51
+ "prettier-plugin-tailwindcss": "0.6.8",
52
52
  "serve": "14.2.3",
53
53
  "sharp": "0.33.5",
54
54
  "stylelint": "16.9.0",
55
55
  "stylelint-config-recommended-vue": "1.5.0",
56
56
  "stylelint-config-standard": "36.0.1",
57
57
  "stylelint-no-unsupported-browser-features": "8.0.1",
58
- "tailwindcss": "3.4.12",
58
+ "tailwindcss": "3.4.13",
59
59
  "unhead": "1.11.6",
60
- "vue": "3.5.6",
60
+ "vue": "3.5.10",
61
61
  "vue-router": "4.4.5"
62
62
  },
63
63
  "engines": {
@@ -87,7 +87,7 @@
87
87
  "name": "@dargmuesli/nuxt-vio",
88
88
  "peerDependencies": {
89
89
  "nuxt": "3.13.2",
90
- "vue": "3.5.6",
90
+ "vue": "3.5.10",
91
91
  "vue-router": "4.4.5"
92
92
  },
93
93
  "publishConfig": {
@@ -117,5 +117,5 @@
117
117
  "start:static": "serve .playground/.output/public --ssl-cert ./.config/certificates/ssl.crt --ssl-key ./.config/certificates/ssl.key"
118
118
  },
119
119
  "type": "module",
120
- "version": "14.0.0"
120
+ "version": "14.0.2"
121
121
  }
@@ -28,17 +28,6 @@ export const cleanupCsp = (
28
28
  }
29
29
 
30
30
  export default defineNitroPlugin((nitroApp) => {
31
- // TODO: migrate to nuxt-security (https://github.com/Baroshem/nuxt-security/discussions/454)
32
- if (import.meta.dev) {
33
- nitroApp.hooks.hook('render:html', (html, { event }) => {
34
- if (!event.context.security?.nonce) return
35
-
36
- html.head.push(
37
- `<meta property="csp-nonce" nonce="${event.context.security.nonce}">`,
38
- )
39
- })
40
- }
41
-
42
31
  nitroApp.hooks.hook('nuxt-security:routeRules', async (routeRules) => {
43
32
  const runtimeConfig = useRuntimeConfig()
44
33
  const siteUrl = runtimeConfig.public.site.url
package/utils/auth.ts CHANGED
@@ -1,70 +1,65 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http'
2
-
1
+ import type { Client } from '@urql/vue'
3
2
  import { consola } from 'consola'
4
- import { parse, serialize } from 'cookie-es'
3
+ import { type H3Event, setCookie } from 'h3'
5
4
  import { decodeJwt } from 'jose'
6
- import type { Store } from 'pinia'
7
5
 
8
6
  import { useVioAuthStore } from '../store/auth'
9
7
  import { JWT_NAME } from './constants'
10
8
 
11
- export const getJwtFromCookie = ({ req }: { req: IncomingMessage }) => {
12
- if (req.headers.cookie) {
13
- const cookies = parse(req.headers.cookie)
9
+ export const getJwtFromCookie = () => {
10
+ const cookie = useCookie(JWT_NAME())
14
11
 
15
- if (cookies[JWT_NAME()]) {
16
- const cookie = decodeJwt(cookies[JWT_NAME()])
12
+ if (!cookie.value) {
13
+ consola.debug('No token cookie.')
14
+ return
15
+ }
17
16
 
18
- if (cookie.exp !== undefined && cookie.exp > Date.now() / 1000) {
19
- return {
20
- jwt: cookies[JWT_NAME()],
21
- jwtDecoded: cookie,
22
- }
23
- } else {
24
- consola.info('Token expired.')
25
- }
26
- } else {
27
- consola.debug('No token cookie.')
28
- }
29
- } else {
30
- consola.debug('No cookie header.')
17
+ const jwt = decodeJwt(cookie.value)
18
+
19
+ if (jwt.exp === undefined || jwt.exp <= Date.now() / 1000) {
20
+ consola.info('Token expired.')
21
+ return
22
+ }
23
+
24
+ return {
25
+ jwt: cookie.value,
26
+ jwtDecoded: jwt,
31
27
  }
32
28
  }
33
29
 
34
30
  export const jwtStore = async ({
35
31
  $urqlReset,
36
- store,
37
- res,
32
+ event,
33
+ isInProduction,
38
34
  jwt,
35
+ store,
39
36
  }: {
40
- $urqlReset: () => void
41
- store: Store
42
- res?: ServerResponse
37
+ $urqlReset: () => Client
38
+ event?: H3Event
39
+ isInProduction: boolean
43
40
  jwt?: string
41
+ store: ReturnType<typeof useVioAuthStore>
44
42
  }) => {
45
43
  $urqlReset()
46
44
 
47
45
  consola.trace('Storing the following JWT: ' + jwt)
48
- ;(store as unknown as { jwtSet: (jwtNew?: string) => void }).jwtSet(jwt)
46
+ store.jwtSet(jwt)
49
47
 
50
- if (import.meta.server) {
51
- res?.setHeader(
52
- 'Set-Cookie',
53
- serialize(JWT_NAME(), jwt || '', {
54
- expires: jwt ? new Date(Date.now() + 86400 * 1000 * 31) : new Date(0),
55
- httpOnly: true,
56
- path: '/',
57
- sameSite: 'lax', // Cannot be 'strict' to allow authentications after clicking on links within webmailers.
58
- secure: true,
59
- }),
60
- )
48
+ if (event) {
49
+ setCookie(event, JWT_NAME(), jwt || '', {
50
+ expires: jwt ? new Date(Date.now() + 86400 * 1000 * 31) : new Date(0),
51
+ httpOnly: true,
52
+ path: '/',
53
+ sameSite: 'lax', // Cannot be 'strict' to allow authentications after clicking on links within webmailers.
54
+ secure: isInProduction,
55
+ })
61
56
  } else {
62
57
  try {
63
58
  await $fetch('/api/auth', {
64
59
  method: 'POST',
65
60
  ...(jwt ? { headers: { Authorization: `Bearer ${jwt}` } } : {}),
66
61
  })
67
- } catch (error: unknown) {
62
+ } catch (error) {
68
63
  console.error(error)
69
64
  return Promise.reject(Error('Authentication api call failed.'))
70
65
  }
@@ -74,14 +69,16 @@ export const jwtStore = async ({
74
69
  export const useJwtStore = () => {
75
70
  const { $urqlReset, ssrContext } = useNuxtApp()
76
71
  const store = useVioAuthStore()
72
+ const runtimeConfig = useRuntimeConfig()
77
73
 
78
74
  return {
79
75
  async jwtStore(jwt?: string) {
80
76
  await jwtStore({
81
- $urqlReset: $urqlReset as () => void,
82
- store,
83
- res: ssrContext ? ssrContext.event.node.res : undefined,
77
+ $urqlReset: $urqlReset as () => Client,
78
+ event: ssrContext?.event,
79
+ isInProduction: runtimeConfig.public.vio.isInProduction,
84
80
  jwt,
81
+ store,
85
82
  })
86
83
  },
87
84
  }
@@ -89,27 +86,40 @@ export const useJwtStore = () => {
89
86
 
90
87
  export const signOut = async ({
91
88
  $urqlReset,
89
+ // client,
90
+ event,
91
+ isInProduction,
92
92
  store,
93
- res,
94
93
  }: {
95
- $urqlReset: () => void
96
- store: Store
97
- res?: ServerResponse
98
- }) => await jwtStore({ $urqlReset, store, res })
94
+ $urqlReset: () => Client
95
+ client: Client
96
+ event?: H3Event
97
+ isInProduction: boolean
98
+ store: ReturnType<typeof useVioAuthStore>
99
+ }) => {
100
+ await jwtStore({ $urqlReset, event, isInProduction, store })
101
+ // await authenticationAnonymous({
102
+ // $urqlReset,
103
+ // client,
104
+ // event,
105
+ // isInProduction,
106
+ // store,
107
+ // })
108
+ }
99
109
 
100
110
  export const useSignOut = () => {
101
- const { $urqlReset, ssrContext } = useNuxtApp()
111
+ const { $urql, $urqlReset, ssrContext } = useNuxtApp()
102
112
  const store = useVioAuthStore()
103
-
104
- if (typeof $urqlReset !== 'function')
105
- throw new Error('`$urqlReset` is not a function!')
113
+ const runtimeConfig = useRuntimeConfig()
106
114
 
107
115
  return {
108
116
  async signOut() {
109
117
  await signOut({
110
- $urqlReset: $urqlReset as () => void,
118
+ $urqlReset: $urqlReset as () => Client,
119
+ client: ($urql as Ref<Client>).value,
120
+ event: ssrContext?.event,
121
+ isInProduction: runtimeConfig.public.vio.isInProduction,
111
122
  store,
112
- res: ssrContext ? ssrContext.event.node.res : undefined,
113
123
  })
114
124
  },
115
125
  }