Merge branch 'feature/auth'
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { db, table } from '~/db'
|
||||
import { generateApiKey, generateSecretKey } from '~/helpers/signature'
|
||||
import { DataAlreadyExistsError } from '~/helpers/errors'
|
||||
import { CreateMerchantBody } from '../schema'
|
||||
import { checkMerchantExists } from '../queries/query'
|
||||
|
||||
export async function createMerchant(body: CreateMerchantBody) {
|
||||
// Check if merchant with same email or phone exists
|
||||
const exists = await checkMerchantExists(body.contactEmail, body.contactPhone)
|
||||
if (exists) {
|
||||
throw new DataAlreadyExistsError('Merchant with this email or phone already exists')
|
||||
}
|
||||
|
||||
// Generate keys
|
||||
const apiKey = generateApiKey()
|
||||
const secretKey = generateSecretKey()
|
||||
|
||||
// Insert new merchant
|
||||
const result = await db
|
||||
.insert(table.merchants)
|
||||
.values({
|
||||
merchantName: body.merchantName,
|
||||
contactEmail: body.contactEmail,
|
||||
contactPhone: body.contactPhone,
|
||||
apiKey,
|
||||
secretKey,
|
||||
})
|
||||
.returning({
|
||||
merchantId: table.merchants.merchantId,
|
||||
apiKey: table.merchants.apiKey,
|
||||
secretKey: table.merchants.secretKey,
|
||||
createdAt: table.merchants.createdAt,
|
||||
})
|
||||
|
||||
if (result.length === 0) {
|
||||
throw new Error('Failed to create merchant')
|
||||
}
|
||||
|
||||
return result[0]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createMerchant } from './command'
|
||||
import { CreateMerchantBody } from '../schema'
|
||||
|
||||
export default abstract class CreateMerchantService {
|
||||
static async createMerchant(body: CreateMerchantBody): Promise<{
|
||||
merchantId: string
|
||||
apiKey: string
|
||||
secretKey: string
|
||||
}> {
|
||||
return await createMerchant(body)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { eq, or } from 'drizzle-orm'
|
||||
import { db, table } from '~/db'
|
||||
|
||||
export async function checkMerchantExists(email: string, phone: string) {
|
||||
const existingMerchant = await db.$count(table.merchants, or(
|
||||
eq(table.merchants.contactEmail, email),
|
||||
eq(table.merchants.contactPhone, phone),
|
||||
))
|
||||
|
||||
return existingMerchant > 0
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Elysia } from 'elysia'
|
||||
import { createMerchantBody, createMerchantResponseSchema } from './schema'
|
||||
import CreateMerchantService from './commands/service'
|
||||
import { basicAuthMiddleware } from '~/middlewares/basicAuth'
|
||||
import { DataAlreadyExistsError } from '~/helpers/errors'
|
||||
|
||||
export const router = new Elysia({
|
||||
name: 'modules.auth',
|
||||
detail: { tags: ['Auth'] },
|
||||
prefix: '/auth',
|
||||
})
|
||||
.post('/get-key', async ({ body, headers, set }) => {
|
||||
basicAuthMiddleware(headers, set)
|
||||
|
||||
try {
|
||||
const result = await CreateMerchantService.createMerchant(body)
|
||||
return {
|
||||
status: 'success' as const,
|
||||
message: 'Merchant created successfully' as const,
|
||||
data: result,
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DataAlreadyExistsError) {
|
||||
set.status = 409
|
||||
return {
|
||||
status: 'conflict' as const,
|
||||
message: 'Merchant with this email or phone already exists' as const,
|
||||
}
|
||||
}
|
||||
set.status = 500
|
||||
return {
|
||||
status: 'internal_error' as const,
|
||||
message: 'Server error' as const,
|
||||
}
|
||||
}
|
||||
}, {
|
||||
body: createMerchantBody,
|
||||
response: createMerchantResponseSchema,
|
||||
detail: {
|
||||
security: [{ basicAuth: [] }],
|
||||
},
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -0,0 +1,34 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
// Request body schema
|
||||
export const createMerchantBody = z.object({
|
||||
merchantName: z.string(),
|
||||
contactEmail: z.string().email(),
|
||||
contactPhone: z.string(),
|
||||
})
|
||||
export type CreateMerchantBody = z.infer<typeof createMerchantBody>
|
||||
|
||||
// Response schemas
|
||||
export const createMerchantResponseSchema = {
|
||||
200: z.object({
|
||||
status: z.literal('success'),
|
||||
message: z.literal('Merchant created successfully'),
|
||||
data: z.object({
|
||||
merchantId: z.string(),
|
||||
apiKey: z.string(),
|
||||
secretKey: z.string(),
|
||||
}),
|
||||
}),
|
||||
400: z.object({
|
||||
status: z.literal('invalid_request'),
|
||||
message: z.literal('Invalid request format'),
|
||||
}),
|
||||
409: z.object({
|
||||
status: z.literal('conflict'),
|
||||
message: z.literal('Merchant with this email or phone already exists'),
|
||||
}),
|
||||
500: z.object({
|
||||
status: z.literal('internal_error'),
|
||||
message: z.literal('Server error'),
|
||||
}),
|
||||
}
|
||||
Reference in New Issue
Block a user