@sbc-connect/nuxt-auth 0.4.1 → 0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @sbc-connect/nuxt-auth
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#123](https://github.com/bcgov/connect-nuxt/pull/123) [`3c33132`](https://github.com/bcgov/connect-nuxt/commit/3c331327a27cfbd0613c268abf97842288d10f8c) Thanks [@cameron-eyds](https://github.com/cameron-eyds)! - Auth Redirect Enhancements
8
+
3
9
  ## 0.4.1
4
10
 
5
11
  ### Patch Changes
@@ -1,5 +1,3 @@
1
- import type { ConnectCreateAccount } from '#auth/app/interfaces/connect-account'
2
-
3
1
  export const useAuthApi = () => {
4
2
  const { $authApi } = useNuxtApp()
5
3
  const queryCache = useQueryCache()
@@ -34,7 +32,10 @@ export const useAuthApi = () => {
34
32
  */
35
33
  const useCreateAccount = defineMutation(() => {
36
34
  const { mutateAsync, ...mutation } = useMutation({
37
- mutation: (vars: { payload: ConnectCreateAccount, successCb?: () => Promise<unknown> }) => {
35
+ mutation: (vars: {
36
+ payload: ConnectCreateAccount
37
+ successCb?: (createRes: ConnectAuthProfile) => Promise<unknown>
38
+ }) => {
38
39
  return $authApi<ConnectAuthProfile>('/orgs', {
39
40
  method: 'POST',
40
41
  body: vars.payload
@@ -48,7 +49,7 @@ export const useAuthApi = () => {
48
49
  onSuccess: async (_, _vars) => {
49
50
  await queryCache.invalidateQueries({ key: ['auth-user-profile'], exact: true })
50
51
  if (_vars.successCb) {
51
- await _vars.successCb()
52
+ await _vars.successCb(_)
52
53
  }
53
54
  }
54
55
  })
@@ -1,7 +1,9 @@
1
1
  import type { RouteLocationNormalizedGeneric } from '#vue-router'
2
2
 
3
3
  export const useConnectAccountFlowRedirect = () => {
4
- function finalRedirect(route: RouteLocationNormalizedGeneric) {
4
+ function finalRedirect(route: RouteLocationNormalizedGeneric, manageAccount = false) {
5
+ const { authUser } = useConnectAuth()
6
+ const { userAccounts } = useConnectAccountStore()
5
7
  const localePath = useLocalePath()
6
8
  const ac = useAppConfig().connect.login
7
9
  const externalRedirectUrl = route.query.return as string | undefined
@@ -9,24 +11,37 @@ export const useConnectAccountFlowRedirect = () => {
9
11
 
10
12
  const query = { ...route.query }
11
13
 
12
- if (query.return) {
13
- delete query.return
14
+ if (manageAccount && userAccounts.length !== 1) {
15
+ const isBcscCreate
16
+ = userAccounts.length === 0
17
+ && authUser.value.loginSource === ConnectLoginSource.BCSC
18
+
19
+ return isBcscCreate
20
+ ? navigateTo({ path: localePath('/auth/account/create'), query })
21
+ : navigateTo({ path: localePath('/auth/account/select'), query })
14
22
  }
15
23
 
16
24
  if (externalRedirectUrl) {
25
+ const cleanQuery = { ...query }
26
+ delete cleanQuery.return
27
+
17
28
  return navigateTo(
18
29
  {
19
- path: appendUrlParam(externalRedirectUrl, 'accountid', useConnectAccountStore().currentAccount.id),
20
- query
30
+ path: appendUrlParam(
31
+ externalRedirectUrl,
32
+ 'accountid',
33
+ useConnectAccountStore().currentAccount.id
34
+ ),
35
+ query: cleanQuery
21
36
  },
22
37
  { external: true }
23
38
  )
24
- } else {
25
- return navigateTo({
26
- path: localePath(internalRedirectUrl),
27
- query
28
- })
29
39
  }
40
+
41
+ return navigateTo({
42
+ path: localePath(internalRedirectUrl),
43
+ query
44
+ })
30
45
  }
31
46
 
32
47
  return {
@@ -5,27 +5,33 @@ export default defineNuxtRouteMiddleware(async (to) => {
5
5
  const authApi = useAuthApi()
6
6
  const { finalRedirect } = useConnectAccountFlowRedirect()
7
7
 
8
- if (!isAuthenticated.value && !rtc.playwright) {
9
- return navigateTo({
10
- path: localePath('/auth/login'),
11
- query: {
12
- // include preset when present
13
- ...(to.query.preset ? { preset: String(to.query.preset) } : {}),
14
- return: `${rtc.baseUrl}${to.fullPath.slice(1)}`
8
+ const isLoginPage = to.meta.connectLogin === true
9
+ const isTosPage = to.meta.connectTosPage === true
10
+
11
+ if (!isAuthenticated.value && !isLoginPage && !rtc.playwright) {
12
+ const defaultReturn = `${rtc.baseUrl}${to.fullPath.slice(1)}`
13
+ const returnUrl = (to.query.return && String(to.query.return)) || defaultReturn
14
+
15
+ return navigateTo(
16
+ {
17
+ path: localePath('/auth/login'),
18
+ query: {
19
+ ...to.query,
20
+ return: returnUrl
21
+ }
15
22
  }
16
- })
23
+ )
17
24
  }
18
25
 
19
26
  if (isAuthenticated.value) {
20
27
  const { data, refresh } = await authApi.getAuthUserProfile()
21
28
  await refresh()
22
29
  const hasAccepted = data.value?.userTerms.isTermsOfUseAccepted
23
- const isTosPage = to.meta.connectTosPage === true
24
30
  if (!hasAccepted && !isTosPage) {
25
31
  const query = { ...to.query }
26
32
  return navigateTo({ path: localePath('/auth/terms-of-use'), query })
27
- } else if (hasAccepted && isTosPage) {
28
- return finalRedirect(to)
33
+ } else if (hasAccepted && (isTosPage || isLoginPage)) {
34
+ return finalRedirect(to, true)
29
35
  }
30
36
  }
31
37
 
@@ -12,7 +12,8 @@ useHead({
12
12
  definePageMeta({
13
13
  layout: 'connect-auth',
14
14
  hideBreadcrumbs: true,
15
- middleware: 'connect-login-page'
15
+ middleware: 'connect-auth',
16
+ connectLogin: true
16
17
  })
17
18
 
18
19
  const isSessionExpired = sessionStorage.getItem(ConnectAuthStorageKey.CONNECT_SESSION_EXPIRED)
@@ -70,7 +70,7 @@ const disableButtons = computed<boolean>(() => {
70
70
  @submit="patchTermsOfUse({
71
71
  accepted: true,
72
72
  version: data!.versionId,
73
- successCb: async () => await finalRedirect(useRoute()),
73
+ successCb: async () => await finalRedirect(useRoute(), true),
74
74
  })"
75
75
  />
76
76
  </UContainer>
@@ -1,6 +1,5 @@
1
1
  import { getAccountCreateSchema } from '#auth/app/utils/schemas/account'
2
2
  import type { AccountProfileSchema } from '#auth/app/utils/schemas/account'
3
- import type { ConnectCreateAccount } from '#auth/app/interfaces/connect-account'
4
3
 
5
4
  export const useConnectAccountStore = defineStore('connect-auth-account-store', () => {
6
5
  const { $authApi } = useNuxtApp()
@@ -88,13 +87,22 @@ export const useConnectAccountStore = defineStore('connect-auth-account-store',
88
87
  await createAccount({
89
88
  payload,
90
89
  // Update User Contact Info on create account success
91
- successCb: async () => await updateUserContact({
92
- email: accountFormState.emailAddress,
93
- phone: accountFormState.phone.phoneNumber,
94
- phoneExtension: accountFormState.phone.ext,
95
- successCb: async () => await finalRedirect(useRoute()),
96
- errorCb: async () => await finalRedirect(useRoute())
97
- })
90
+ successCb: async (createResponse: ConnectAuthProfile) => {
91
+ // Refresh and switch to new account prior to redirect
92
+ if (createResponse?.id) {
93
+ await setAccountInfo()
94
+ switchCurrentAccount(createResponse.id)
95
+ }
96
+
97
+ // Update user contact and then redirect regardless of success or failure
98
+ await updateUserContact({
99
+ email: accountFormState.emailAddress,
100
+ phone: accountFormState.phone.phoneNumber,
101
+ phoneExtension: accountFormState.phone.ext,
102
+ successCb: async () => await finalRedirect(useRoute()),
103
+ errorCb: async () => await finalRedirect(useRoute())
104
+ })
105
+ }
98
106
  })
99
107
  } catch (error) {
100
108
  // Error handled in useAuthApi
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sbc-connect/nuxt-auth",
3
3
  "type": "module",
4
- "version": "0.4.1",
4
+ "version": "0.5.0",
5
5
  "repository": "github:bcgov/connect-nuxt",
6
6
  "license": "BSD-3-Clause",
7
7
  "main": "./nuxt.config.ts",
@@ -1 +1,2 @@
1
+ export * from './profile'
1
2
  export * from './settings'
@@ -0,0 +1,9 @@
1
+ import fs from 'fs'
2
+ import { createResolver } from 'nuxt/kit'
3
+
4
+ const { resolve } = createResolver(import.meta.url)
5
+
6
+ export const getUserProfileMock = () => {
7
+ const json: ConnectAuthProfile = JSON.parse(fs.readFileSync(resolve('./json/PUBLIC_USER.json'), 'utf8'))
8
+ return json
9
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "contacts": [
3
+ {
4
+ "email": "v9x3z!q__mock@fuzzmail.zzz",
5
+ "phone": "(902) 555-xyzz",
6
+ "phoneExtension": "7q1"
7
+ }
8
+ ],
9
+ "created": "2024-03-19T04:92:17+00:00",
10
+ "firstname": "Nxlqrp3##",
11
+ "id": 88422,
12
+ "idpUserid": "ZZ91XQWPMR7T4!$CBA9900PLMNXXQTT",
13
+ "keycloakGuid": "xxxxxxxx-bb77-49c1-f01a-xxxxxxxxx",
14
+ "lastname": "T'W&&two--",
15
+ "loginSource": "BCSC",
16
+ "loginTime": "2026-01-23T28:77:59+00:00",
17
+ "modified": "2026-01-23T28:77:59+00:00",
18
+ "modifiedBy": "Nxlqrp3## T'W&&two--",
19
+ "type": "PUBLIC_USER",
20
+ "userStatus": 1,
21
+ "userTerms": {
22
+ "isTermsOfUseAccepted": true,
23
+ "termsOfUseAcceptedVersion": "999x"
24
+ },
25
+ "username": "bcsc/zz91xqwpmr7t4!$cba9900plmnxxqtt",
26
+ "verified": true,
27
+ "version": 9999
28
+ }
29
+
@@ -1,11 +1,14 @@
1
1
  import type { Page } from '@playwright/test'
2
2
  import { AccountType } from '#auth/app/enums/account-type'
3
- import { getUserSettingsMock } from '#auth/testMocks/auth'
3
+ import { getUserProfileMock, getUserSettingsMock } from '#auth/testMocks/auth'
4
4
 
5
5
  export const mockApiCallsForSetAccount = async (
6
6
  page: Page,
7
7
  accountType: AccountType = AccountType.PREMIUM
8
8
  ) => {
9
+ page.route('**/users/@me', async (route) => {
10
+ await route.fulfill({ json: getUserProfileMock() })
11
+ })
9
12
  page.route('**/users/**/settings', async (route) => {
10
13
  await route.fulfill({ json: getUserSettingsMock(accountType) })
11
14
  })
@@ -1,26 +0,0 @@
1
- export default defineNuxtRouteMiddleware((to) => {
2
- const { isAuthenticated, authUser } = useConnectAuth()
3
- const accountStore = useConnectAccountStore()
4
- const localePath = useLocalePath()
5
- const { finalRedirect } = useConnectAccountFlowRedirect()
6
-
7
- const numAccounts = accountStore.userAccounts.length
8
-
9
- if (isAuthenticated.value) {
10
- if (numAccounts === 1) {
11
- return finalRedirect(to)
12
- }
13
-
14
- if (numAccounts === 0 && authUser.value.loginSource === ConnectLoginSource.BCSC) {
15
- return navigateTo({
16
- path: localePath('/auth/account/create'),
17
- query: to.query
18
- })
19
- }
20
-
21
- return navigateTo({
22
- path: localePath('/auth/account/select'),
23
- query: to.query
24
- })
25
- }
26
- })