Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
anicioalexandre committed Oct 7, 2024
1 parent 94225bc commit db2e264
Show file tree
Hide file tree
Showing 51 changed files with 3,103 additions and 374 deletions.
45 changes: 28 additions & 17 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup Node.js 20.x
uses: actions/setup-node@v3
- name: Setup Node.js 20.17.0
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 20.17.0

- name: Install Dependencies
run: pnpm i
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9.12.0

- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Build Applications and Packages
run: pnpm build

Expand All @@ -32,33 +36,40 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup Node.js 20.x
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 20.17.0

- name: Install Dependencies
run: pnpm i
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9.12.0

- name: Lint Applications and Packages
run: pnpm lint
- name: Install Dependencies
run: pnpm install --frozen-lockfile

test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup Node.js 20.x
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20.17.0

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
node-version: 20.x
version: 9.12.0

- name: Install Dependencies
run: pnpm i
run: pnpm install --frozen-lockfile

- name: Test Applications and Packages
run: pnpm test
61 changes: 54 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,73 @@ on:
concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
setup:
name: Setup and Install Dependencies
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4

- name: Setup Node.js 20.17.0
uses: actions/setup-node@v4
with:
node-version: 20.17.0

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9.12.0

- name: Restore pnpm Cache
uses: actions/cache/restore@v4
with:
path: node_modules
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-
- name: Install Dependencies
run: pnpm install
env:
CI: true

- name: Save pnpm Cache
uses: actions/cache/save@v4
with:
path: node_modules
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}

release:
name: Release
runs-on: ubuntu-latest
needs: setup
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup Node.js 16.x
uses: actions/setup-node@v3
- name: Setup Node.js 20.17.0
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 20.17.0

- name: Install Dependencies
run: yarn
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9.12.0

- name: Restore pnpm Cache
uses: actions/cache/restore@v4
with:
path: node_modules
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
publish: yarn release
publish: pnpm release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# custom
# build
dist

# dependencies
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ComponentWithProviders, MockAdapter, renderHook } from '@baseapp-frontend/test'
import { TokenTypes, axios } from '@baseapp-frontend/utils'
import { axios } from '@baseapp-frontend/utils'

import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
Expand Down Expand Up @@ -34,7 +34,6 @@ describe('useSimpleTokenLogin', () => {
hasOnSuccessRan = true
},
},
tokenType: TokenTypes.simple,
}),
{
wrapper: ComponentWithProviders,
Expand Down
53 changes: 5 additions & 48 deletions packages/authentication/modules/access/useLogin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,95 +5,52 @@ import { useState } from 'react'
import {
ACCESS_COOKIE_NAME,
REFRESH_COOKIE_NAME,
TokenTypes,
setFormApiErrors,
setTokenAsync,
} from '@baseapp-frontend/utils'

import { zodResolver } from '@hookform/resolvers/zod'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import Cookies from 'js-cookie'
import { useMutation } from '@tanstack/react-query'
import { useForm } from 'react-hook-form'

import AuthApi from '../../../services/auth'
import MfaApi from '../../../services/mfa'
import { USER_API_KEY } from '../../../services/user'
import type {
LoginChangeExpiredPasswordRedirectResponse,
LoginJWTResponse,
LoginMfaRequest,
LoginRequest,
LoginSimpleTokenResponse,
} from '../../../types/auth'
import {
isJWTResponse,
isLoginChangeExpiredPasswordRedirectResponse,
isLoginMfaResponse,
} from '../../../utils/login'
import { CODE_VALIDATION_INITIAL_VALUES, CODE_VALIDATION_SCHEMA } from '../../mfa/constants'
import { useSimpleTokenUser } from '../../user'
import { DEFAULT_INITIAL_VALUES, DEFAULT_VALIDATION_SCHEMA } from './constants'
import type { UseLoginOptions } from './types'

const jwtSuccessHandler = (
response: LoginJWTResponse,
cookieName: string,
refreshCookieName: string,
) => {
Cookies.set(cookieName, response.access, {
secure: process.env.NODE_ENV === 'production',
})
Cookies.set(refreshCookieName, response.refresh, {
secure: process.env.NODE_ENV === 'production',
})
}

const simpleTokenSuccessHandler = (
response: LoginSimpleTokenResponse,
cookieName: string,
onSuccess: () => void,
) => {
Cookies.set(cookieName, response.token, {
secure: process.env.NODE_ENV === 'production',
})

onSuccess()
}

const useLogin = ({
loginFormOptions = {},
loginOptions = {},
mfaOptions = {},
tokenType = TokenTypes.jwt,
cookieName = ACCESS_COOKIE_NAME,
refreshCookieName = REFRESH_COOKIE_NAME,
ApiClass = AuthApi,
enableFormApiErrors = true,
}: UseLoginOptions = {}) => {
const queryClient = useQueryClient()
const [mfaEphemeralToken, setMfaEphemeralToken] = useState<string | null>(null)
const { refetch: refetchUser } = useSimpleTokenUser({ options: { enabled: false } })

/*
* Handles login success with the auth token in response
*/
async function handleLoginSuccess(
response:
| LoginJWTResponse
| LoginSimpleTokenResponse
| LoginChangeExpiredPasswordRedirectResponse,
response: LoginJWTResponse | LoginChangeExpiredPasswordRedirectResponse,
) {
if (isLoginChangeExpiredPasswordRedirectResponse(response)) {
return
}
if (isJWTResponse(tokenType, response)) {
jwtSuccessHandler(response, cookieName, refreshCookieName)
} else {
simpleTokenSuccessHandler(response, cookieName, () => {
// by invalidating the cache we force a reload of /v1/users/me and the state used by useUser hook
queryClient.invalidateQueries({ queryKey: USER_API_KEY.getUser() })
refetchUser()
})
}
await setTokenAsync(cookieName, response.access)
await setTokenAsync(refreshCookieName, response.refresh)
}

const form = useForm({
Expand Down
3 changes: 0 additions & 3 deletions packages/authentication/modules/access/useLogin/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { TokenTypes } from '@baseapp-frontend/utils'

import type { UseMutationOptions } from '@tanstack/react-query'
import type { UseFormProps } from 'react-hook-form'

Expand All @@ -17,7 +15,6 @@ export interface UseLoginOptions extends CustomCookieNames {
loginFormOptions?: UseFormProps<Partial<LoginRequest>>
loginOptions?: UseMutationOptions<LoginResponse, unknown, LoginRequest, any>
mfaOptions?: UseMutationOptions<LoginResponse, unknown, LoginMfaRequest, any>
tokenType?: TokenTypes
ApiClass?: ApiClass
enableFormApiErrors?: boolean
}
4 changes: 2 additions & 2 deletions packages/authentication/modules/user/getUser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import type { User } from '../../../types/user'
import type { GetUserOptions } from './types'

const getUser = <TUser extends Partial<User> & JWTContent>({
cookieName = ACCESS_COOKIE_NAME,
key = ACCESS_COOKIE_NAME,
noSSR = false,
}: GetUserOptions = {}) => {
const token = getToken(cookieName, { noSSR })
const token = getToken(key, { noSSR })
if (token) {
try {
const user = decodeJWT<TUser>(token)
Expand Down
6 changes: 3 additions & 3 deletions packages/authentication/modules/user/getUser/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ServerSideRenderingOption } from '@baseapp-frontend/utils'

import type { CustomCookieNames } from '../../../types/auth'

export interface GetUserOptions extends CustomCookieNames, ServerSideRenderingOption {}
export interface GetUserOptions extends ServerSideRenderingOption {
key?: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjk1MDc2NDgyLCJpYXQiOjE2OTUwNzYxODIsImp0aSI6ImVmMTFhYWE3OGMyODQ4YTBiOWJiYWYwMTU5MjY3MWY5IiwidXNlcl9pZCI6MSwiaWQiOjEsImVtYWlsIjoidXNlckBjb21wYW55LmNvbSIsImlzX2VtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmV3X2VtYWlsIjoiIiwiaXNfbmV3X2VtYWlsX2NvbmZpcm1lZCI6ZmFsc2UsInJlZmVycmFsX2NvZGUiOiIiLCJmaXJzdF9uYW1lIjoiSm9obiIsImxhc3RfbmFtZSI6IkRvZSJ9.QSy7NSAzk7w49kC9BxdZR-x0J8RLHS4ZYa5Jk0aUcSk"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { CookiesGetByNameFn } from '@baseapp-frontend/test'

import Cookies from 'js-cookie'

import getUser from '../index'
import jwt from './fixtures/jwt.json'

describe('getUser', () => {
it('should return the user from the JWT cookie', async () => {
;(Cookies.get as CookiesGetByNameFn) = jest.fn(() => jwt.token)
const user = getUser()

expect(user?.email).toBe('user@company.com')
expect(user?.firstName).toBe('John')
expect(user?.lastName).toBe('Doe')
})

it('should return null if the JWT cookie is not set', async () => {
;(Cookies.get as CookiesGetByNameFn) = jest.fn(() => undefined)
const user = getUser()

expect(user).toBeNull()
})
})
24 changes: 24 additions & 0 deletions packages/authentication/modules/user/getUserAsync/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ACCESS_COOKIE_NAME } from '@baseapp-frontend/utils/constants/cookie'
import { decodeJWT, getTokenAsync } from '@baseapp-frontend/utils/functions/token'
import type { JWTContent } from '@baseapp-frontend/utils/types/jwt'

import type { User } from '../../../types/user'
import type { GetUserAsyncOptions } from './types'

const getUserAsync = async <TUser extends Partial<User> & JWTContent>({
key = ACCESS_COOKIE_NAME,
noSSR = false,
}: GetUserAsyncOptions = {}) => {
const token = await getTokenAsync(key, { noSSR })
if (token) {
try {
const user = decodeJWT<TUser>(token)
return user
} catch (error) {
return null
}
}
return null
}

export default getUserAsync
5 changes: 5 additions & 0 deletions packages/authentication/modules/user/getUserAsync/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { ServerSideRenderingOption } from '@baseapp-frontend/utils'

export interface GetUserAsyncOptions extends ServerSideRenderingOption {
key?: string
}
1 change: 1 addition & 0 deletions packages/authentication/modules/user/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { default as getUser } from './getUser'
export { default as getUserAsync } from './getUserAsync'
export { default as useSimpleTokenUser } from './useSimpleTokenUser'
export { default as useUpdateUser } from './useUpdateUser'
export { default as useJWTUser } from './useJWTUser'
Expand Down
Loading

0 comments on commit db2e264

Please sign in to comment.