Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5d0744f
[feat] :sparkles: add security events endpoint mapping (#288)
dappsar Jan 20, 2026
c96a944
[feat] :sparkles: add security events hook and types (#288)
dappsar Jan 20, 2026
0f30a44
[feat] :sparkles: add security events backend service (#288)
dappsar Jan 20, 2026
6232926
[feat] :sparkles: add security events API route (#288)
dappsar Jan 20, 2026
104dbfa
[feat] :sparkles: add security events dashboard page (#288)
dappsar Jan 20, 2026
020211a
[feat] :sparkles: add security events route path (#288)
dappsar Jan 20, 2026
5f62a2e
[feat] :sparkles: add security events entry to security list (#288)
dappsar Jan 20, 2026
f4ee4f6
[feat] :label: define security event types (#288)
dappsar Jan 20, 2026
3ee93e6
[feat] :sparkles: add security events table with filters (#288)
dappsar Jan 20, 2026
f208b69
[feat] :sparkles: add security events view layout (#288)
dappsar Jan 20, 2026
3bbf33c
[feat] :sparkles: export security events view (#288)
dappsar Jan 20, 2026
59d4cc9
[feat] :globe_with_meridians: add security events translations (en) (…
dappsar Jan 20, 2026
f1c5d79
[feat] :globe_with_meridians: add security events translations (pt-BR…
dappsar Jan 20, 2026
f893d1b
[feat] :globe_with_meridians: add security events translations (es) (…
dappsar Jan 20, 2026
fbdcc98
[docs] :memo: add sample security events response (#288)
dappsar Jan 20, 2026
d785eb0
Merge branch 'develop' of github.com:P4-Games/ChatterPay into develop
dappsar Jan 20, 2026
a68cbe9
Merge branch 'develop' of github.com:P4-Games/ChatterPay into develop
dappsar Feb 5, 2026
4973f63
[feat] :sparkles: add template and language support for 2FA messages …
dappsar Feb 5, 2026
82395c7
[feat] :globe_with_meridians: add preferred language support in auth …
dappsar Feb 5, 2026
de425c6
[feat] :globe_with_meridians: add preferred language support in user …
dappsar Feb 5, 2026
30e6f5b
[feat] :globe_with_meridians: add locale-aware language detection for…
dappsar Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 31 additions & 18 deletions src/app/api/services/chatizalo/chatizalo-service.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
import { BOT_API_TOKEN } from 'src/config-global'
import { post, endpoints } from 'src/app/api/hooks/api-resolver'

// ----------------------------------------------------------------------

export async function send2FACode(phone: string, code: number, codeMsg: string) {
const botSendMsgEndpoint = endpoints.backend_bot.sendMessage()
const botSendMsgData = {
data_token: BOT_API_TOKEN,
channel_user_id: phone,
message: codeMsg.replace('{2FA_CODE}', code.toString())
}
console.info('botSendMsgData', botSendMsgData)
const botSendMsgResult = await post(botSendMsgEndpoint, botSendMsgData)
console.info('botSendMsgResult', botSendMsgResult)

return true
}
import { endpoints, post } from 'src/app/api/hooks/api-resolver'
import { BOT_API_TOKEN } from 'src/config-global'

// ----------------------------------------------------------------------

export async function send2FACode(
phone: string,
code: number,
codeMsg: string,
preferredLanguage: 'es' | 'pt' | 'en'
) {
const botSendMsgEndpoint = endpoints.backend_bot.sendMessage()
const codeAsString = code.toString()
const botSendMsgData = {
data_token: BOT_API_TOKEN,
channel_user_id: phone,
message_kind: 'auth',
template_key: 'login_v1',
template_params: { code: codeAsString },
template_buttons: { 0: codeAsString },
force_template: 'true',
preferred_language: preferredLanguage,
message: codeMsg.replace('{2FA_CODE}', codeAsString)
}
const { data_token: _redactedToken, ...botSendMsgDataSafe } = botSendMsgData
console.info('botSendMsgData', botSendMsgDataSafe)
const botSendMsgResult = await post(botSendMsgEndpoint, botSendMsgData)
console.info('botSendMsgResult', botSendMsgResult)

return true
}
26 changes: 22 additions & 4 deletions src/app/api/v1/auth/code/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,14 @@ export async function POST(req: NextRequest) {
const {
phone,
codeMsg,
recaptchaToken
}: { phone: string; codeMsg: string; recaptchaToken: string } = await req.json()
recaptchaToken,
preferred_language: preferredLanguageInput
}: {
phone: string
codeMsg: string
recaptchaToken: string
preferred_language?: string
} = await req.json()

const ip = getIpFromRequest(req)

Expand Down Expand Up @@ -77,6 +83,8 @@ export async function POST(req: NextRequest) {
const code: number = Math.floor(Math.random() * (999999 - 100000 + 1)) + 100000
await updateUserCode(user.id, code)

const preferredLanguage = normalizePreferredLanguage(preferredLanguageInput)

// Send 2FA code to user'whatsapp
let botSentCodeResult: boolean = true
if (botApiWappEnabled) {
Expand All @@ -86,10 +94,10 @@ export async function POST(req: NextRequest) {
// which may cause it to take about 10 seconds, so this variable is used to improve that logic.
// send async
console.info('/auth/code, calling send2FACode ASYNC', phone, code)
send2FACode(phone, code, codeMsg)
send2FACode(phone, code, codeMsg, preferredLanguage)
} else {
console.info('/auth/code, calling send2FACode SYNC', phone, code)
botSentCodeResult = await send2FACode(phone, code, codeMsg)
botSentCodeResult = await send2FACode(phone, code, codeMsg, preferredLanguage)
}

if (!botSentCodeResult) {
Expand Down Expand Up @@ -128,3 +136,13 @@ export async function POST(req: NextRequest) {
})
}
}

function normalizePreferredLanguage(preferredLanguage?: string): 'es' | 'pt' | 'en' {
const normalized = (preferredLanguage || '').trim().toLowerCase()

if (normalized.startsWith('es')) return 'es'
if (normalized.startsWith('pt') || normalized.startsWith('br')) return 'pt'
if (normalized.startsWith('en')) return 'en'

return 'en'
}
21 changes: 18 additions & 3 deletions src/app/api/v1/user/[id]/code/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ export async function POST(req: NextRequest, { params }: { params: IParams }) {
const userValidationResult = await validateUserCommonsInputs(req, params.id)
if (userValidationResult instanceof NextResponse) return userValidationResult

const { phone, codeMsg }: { phone: string; codeMsg: string; recaptchaToken: string } =
await req.json()
const {
phone,
codeMsg,
preferred_language: preferredLanguageInput
}: { phone: string; codeMsg: string; preferred_language?: string } = await req.json()

if (!phone || !codeMsg) {
return new NextResponse(
Expand Down Expand Up @@ -59,11 +62,13 @@ export async function POST(req: NextRequest, { params }: { params: IParams }) {
const code: number = Math.floor(Math.random() * (999999 - 100000 + 1)) + 100000
await updateUserCode(user.id, code)

const preferredLanguage = normalizePreferredLanguage(preferredLanguageInput)

// Send 2FA code to user'whatsapp
let botSentCodeResult: boolean = true
if (botApiWappEnabled) {
console.info('/user/[id]/code, calling send2FACode SYNC', phone, code)
botSentCodeResult = await send2FACode(phone, code, codeMsg)
botSentCodeResult = await send2FACode(phone, code, codeMsg, preferredLanguage)

if (!botSentCodeResult) {
return new NextResponse(
Expand Down Expand Up @@ -93,3 +98,13 @@ export async function POST(req: NextRequest, { params }: { params: IParams }) {
})
}
}

function normalizePreferredLanguage(preferredLanguage?: string): 'es' | 'pt' | 'en' {
const normalized = (preferredLanguage || '').trim().toLowerCase()

if (normalized.startsWith('es')) return 'es'
if (normalized.startsWith('pt') || normalized.startsWith('br')) return 'pt'
if (normalized.startsWith('en')) return 'en'

return 'en'
}
21 changes: 19 additions & 2 deletions src/auth/context/jwt/auth-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useMemo, useEffect, useReducer, useCallback } from 'react'

import { post, fetcher, endpoints } from 'src/app/api/hooks/api-resolver'
import { useLocales } from 'src/locales'
import { setSession } from 'src/auth/context/jwt/utils'

import { AuthContext } from './auth-context'
Expand Down Expand Up @@ -69,6 +70,7 @@ type Props = { children: React.ReactNode }

export function AuthProvider({ children }: Props) {
const [state, dispatch] = useReducer(reducer, initialState)
const { currentLang } = useLocales()

const initialize = useCallback(async () => {
try {
Expand Down Expand Up @@ -106,10 +108,15 @@ export function AuthProvider({ children }: Props) {

const generate2faCodeLogin = useCallback(
async (phone: string, codeMsg: string, recaptchaToken: string) => {
await post(endpoints.auth.code(), { phone, codeMsg, recaptchaToken })
await post(endpoints.auth.code(), {
phone,
codeMsg,
recaptchaToken,
preferred_language: normalizePreferredLanguage(currentLang?.value)
})
dispatch({ type: Types.GENERATE_CODE_LOGIN, payload: { user: null } })
},
[]
[currentLang?.value]
)

const generate2faCodeEmail = useCallback(
Expand Down Expand Up @@ -194,3 +201,13 @@ export function AuthProvider({ children }: Props) {

return <AuthContext.Provider value={memoizedValue}>{children}</AuthContext.Provider>
}

function normalizePreferredLanguage(langValue?: string): 'es' | 'pt' | 'en' {
const normalized = (langValue || '').trim().toLowerCase()

if (normalized.startsWith('es')) return 'es'
if (normalized.startsWith('pt') || normalized.startsWith('br')) return 'pt'
if (normalized.startsWith('en')) return 'en'

return 'en'
}
Loading