✨ feat (auth): server side proxy login request
This commit is contained in:
@@ -1,22 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
// import PasswordInput from '~/components/PasswordInput.vue'
|
||||
import { Loader2 } from 'lucide-vue-next'
|
||||
|
||||
const email = ref('demo@gmail.com')
|
||||
const password = ref('password')
|
||||
const isLoading = ref(false)
|
||||
|
||||
function onSubmit(event: Event) {
|
||||
async function onSubmit(event: Event) {
|
||||
event.preventDefault()
|
||||
if (!email.value || !password.value) return
|
||||
|
||||
isLoading.value = true
|
||||
|
||||
setTimeout(() => {
|
||||
if (email.value === 'demo@gmail.com' && password.value === 'password') navigateTo('/')
|
||||
try {
|
||||
const { data: respData } = await useFetch('/api/v1/authentication/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
name: 'system',
|
||||
password: 'the-SYSTEM-1234',
|
||||
}),
|
||||
})
|
||||
|
||||
const resp = respData.value
|
||||
if (!resp) throw new Error('No response')
|
||||
|
||||
const { data: rawdata, meta } = resp
|
||||
console.log('DATA', rawdata)
|
||||
console.log('META', meta)
|
||||
|
||||
if (meta.status === 'verified') {
|
||||
await nextTick()
|
||||
navigateTo('/')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Login failed:', error)
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}, 3000)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
+23
-21
@@ -1,5 +1,5 @@
|
||||
import antfu from "@antfu/eslint-config";
|
||||
import withNuxt from "./.nuxt/eslint.config.mjs";
|
||||
import antfu from '@antfu/eslint-config'
|
||||
import withNuxt from './.nuxt/eslint.config.mjs'
|
||||
|
||||
export default withNuxt(
|
||||
antfu(
|
||||
@@ -9,7 +9,7 @@ export default withNuxt(
|
||||
// Relaxed stylistic options
|
||||
stylistic: {
|
||||
semi: false,
|
||||
quotes: "single",
|
||||
quotes: 'single',
|
||||
// Less strict formatting
|
||||
jsx: false,
|
||||
},
|
||||
@@ -17,34 +17,36 @@ export default withNuxt(
|
||||
{
|
||||
rules: {
|
||||
// Basic rules
|
||||
quotes: ["error", "single", { avoidEscape: true }],
|
||||
"style/no-trailing-spaces": ["error", { ignoreComments: true }],
|
||||
quotes: ['error', 'single', { avoidEscape: true }],
|
||||
'style/no-trailing-spaces': ['error', { ignoreComments: true }],
|
||||
|
||||
'no-console': 'off',
|
||||
|
||||
// Relax strict formatting rules
|
||||
"style/brace-style": "off", // Allow inline if
|
||||
curly: ["error", "multi-line"], // Only require braces for multi-line
|
||||
"style/arrow-parens": "off",
|
||||
'style/brace-style': 'off', // Allow inline if
|
||||
curly: ['error', 'multi-line'], // Only require braces for multi-line
|
||||
'style/arrow-parens': 'off',
|
||||
|
||||
// UnoCSS - make it warning instead of error, or disable completely
|
||||
"unocss/order": "off", // atau 'off' untuk disable
|
||||
'unocss/order': 'off', // atau 'off' untuk disable
|
||||
|
||||
// Vue specific - relax template formatting
|
||||
"vue/html-indent": "off",
|
||||
"vue/max-attributes-per-line": "off",
|
||||
"vue/singleline-html-element-content-newline": "off",
|
||||
"vue/multiline-html-element-content-newline": "off",
|
||||
"vue/html-self-closing": "off",
|
||||
'vue/html-indent': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/html-self-closing': 'off',
|
||||
|
||||
// Allow more flexible code style
|
||||
"style/max-statements-per-line": ["error", { max: 3 }],
|
||||
"antfu/if-newline": "off", // Disable newline after if requirement
|
||||
'style/max-statements-per-line': ['error', { max: 3 }],
|
||||
'antfu/if-newline': 'off', // Disable newline after if requirement
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["**/*.md"],
|
||||
files: ['**/*.md'],
|
||||
rules: {
|
||||
"style/no-trailing-spaces": "off",
|
||||
'style/no-trailing-spaces': 'off',
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
devtools: { enabled: true },
|
||||
runtimeConfig: {
|
||||
API_ORIGIN: process.env.API_ORIGIN || 'https://main-api.dev-hopis.sabbi.id',
|
||||
},
|
||||
modules: [
|
||||
'@unocss/nuxt',
|
||||
'shadcn-nuxt',
|
||||
|
||||
+5
-4
@@ -19,14 +19,12 @@
|
||||
"@unovis/ts": "^1.5.1",
|
||||
"@unovis/vue": "^1.5.1",
|
||||
"embla-carousel": "^8.5.2",
|
||||
"embla-carousel-vue": "^8.5.2"
|
||||
"embla-carousel-vue": "^8.5.2",
|
||||
"h3": "^1.15.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^4.10.1",
|
||||
"@nuxt/eslint": "^1.2.0",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-tailwindcss": "^0.5.14",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"@nuxt/icon": "^1.11.0",
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
"@pinia/nuxt": "^0.5.1",
|
||||
@@ -39,9 +37,12 @@
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint": "^9.22.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-format": "^1.0.1",
|
||||
"lucide-vue-next": "^0.482.0",
|
||||
"nuxt": "^4.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-tailwindcss": "^0.5.14",
|
||||
"radix-vue": "^1.9.17",
|
||||
"shadcn-nuxt": "^0.10.4",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
|
||||
Generated
+3
-10
@@ -26,6 +26,9 @@ dependencies:
|
||||
embla-carousel-vue:
|
||||
specifier: ^8.5.2
|
||||
version: 8.6.0(vue@3.5.18)
|
||||
h3:
|
||||
specifier: ^1.15.4
|
||||
version: 1.15.4
|
||||
|
||||
devDependencies:
|
||||
'@antfu/eslint-config':
|
||||
@@ -5279,7 +5282,6 @@ packages:
|
||||
|
||||
/cookie-es@1.2.2:
|
||||
resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==}
|
||||
dev: true
|
||||
|
||||
/cookie-es@2.0.0:
|
||||
resolution: {integrity: sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==}
|
||||
@@ -5365,7 +5367,6 @@ packages:
|
||||
resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}
|
||||
dependencies:
|
||||
uncrypto: 0.1.3
|
||||
dev: true
|
||||
|
||||
/css-declaration-sorter@7.2.0(postcss@8.5.6):
|
||||
resolution: {integrity: sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==}
|
||||
@@ -5865,7 +5866,6 @@ packages:
|
||||
|
||||
/defu@6.1.4:
|
||||
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
||||
dev: true
|
||||
|
||||
/delaunator@5.0.1:
|
||||
resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==}
|
||||
@@ -5890,7 +5890,6 @@ packages:
|
||||
|
||||
/destr@2.0.5:
|
||||
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
|
||||
dev: true
|
||||
|
||||
/detect-libc@1.0.3:
|
||||
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||
@@ -7320,7 +7319,6 @@ packages:
|
||||
radix3: 1.1.2
|
||||
ufo: 1.6.1
|
||||
uncrypto: 0.1.3
|
||||
dev: true
|
||||
|
||||
/has-flag@4.0.0:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
@@ -7486,7 +7484,6 @@ packages:
|
||||
|
||||
/iron-webcrypto@1.2.1:
|
||||
resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
|
||||
dev: true
|
||||
|
||||
/is-arrayish@0.2.1:
|
||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||
@@ -8817,7 +8814,6 @@ packages:
|
||||
|
||||
/node-mock-http@1.0.2:
|
||||
resolution: {integrity: sha512-zWaamgDUdo9SSLw47we78+zYw/bDr5gH8pH7oRRs8V3KmBtu8GLgGIbV2p/gRPd3LWpEOpjQj7X1FOU3VFMJ8g==}
|
||||
dev: true
|
||||
|
||||
/node-releases@2.0.19:
|
||||
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
|
||||
@@ -9945,7 +9941,6 @@ packages:
|
||||
|
||||
/radix3@1.1.2:
|
||||
resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
|
||||
dev: true
|
||||
|
||||
/randombytes@2.1.0:
|
||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
||||
@@ -10883,7 +10878,6 @@ packages:
|
||||
|
||||
/ufo@1.6.1:
|
||||
resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
|
||||
dev: true
|
||||
|
||||
/ultrahtml@1.6.0:
|
||||
resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==}
|
||||
@@ -10900,7 +10894,6 @@ packages:
|
||||
|
||||
/uncrypto@0.1.3:
|
||||
resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
|
||||
dev: true
|
||||
|
||||
/unctx@2.4.1:
|
||||
resolution: {integrity: sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg==}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useRuntimeConfig } from '#imports'
|
||||
import { getRequestURL, readBody, setCookie } from 'h3'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event)
|
||||
const url = getRequestURL(event)
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
const apiOrigin = config.API_ORIGIN
|
||||
|
||||
const externalUrl = apiOrigin + url.pathname.replace(/^\/api/, '') + url.search
|
||||
|
||||
const resp = await fetch(externalUrl, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
if (resp.status === 200) {
|
||||
const data = await resp.json()
|
||||
|
||||
if (data?.data?.accessToken) {
|
||||
setCookie(event, 'authentication', data.data.accessToken, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'strict',
|
||||
maxAge: 60 * 60 * 24,
|
||||
})
|
||||
|
||||
delete data.data.accessToken
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
return new Response(await resp.text(), {
|
||||
status: resp.status,
|
||||
headers: {
|
||||
'Content-Type': resp.headers.get('content-type') || 'text/plain',
|
||||
},
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user