removed sms otp & created normal login & add update user
This commit is contained in:
@@ -1,8 +1,4 @@
|
|||||||
export const Config = {
|
export const Config = {
|
||||||
sms_api_key: "1796570121771765",
|
|
||||||
sms_api_secret: "0957b611d575febff1ae0fc51070c8b7",
|
|
||||||
sms_api_request_endpoint: "https://otp.thaibulksms.com/v2/otp/request",
|
|
||||||
sms_api_verify_endpoint: "https://otp.thaibulksms.com/v2/otp/verify",
|
|
||||||
jwt_secret:
|
jwt_secret:
|
||||||
"T4kE6/tIqCVEZYg9lwsqeJjYfOoXTXSXDEMyParsJjj57CjSdkrfPOLWP74/9lJpcBA=",
|
"T4kE6/tIqCVEZYg9lwsqeJjYfOoXTXSXDEMyParsJjj57CjSdkrfPOLWP74/9lJpcBA=",
|
||||||
token_duration: "365d",
|
token_duration: "365d",
|
||||||
|
|||||||
131
src/userRoute.ts
131
src/userRoute.ts
@@ -14,8 +14,13 @@ import { TRPCError } from "@trpc/server";
|
|||||||
import * as jwt from "jsonwebtoken";
|
import * as jwt from "jsonwebtoken";
|
||||||
|
|
||||||
const userInsertSchema = createInsertSchema(user, {
|
const userInsertSchema = createInsertSchema(user, {
|
||||||
cid: (schema) => schema.cid.length(13),
|
cid: (schema) =>
|
||||||
|
schema.cid.length(13).refine(isValidThaiID, { message: "Invalid Thai ID" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const userUpdateSchema = userInsertSchema
|
||||||
|
.omit({ id: true, cid: true, phone: true })
|
||||||
|
.partial();
|
||||||
const opinionInsertSchema = createInsertSchema(userOpinion)
|
const opinionInsertSchema = createInsertSchema(userOpinion)
|
||||||
.omit({
|
.omit({
|
||||||
userId: true,
|
userId: true,
|
||||||
@@ -30,6 +35,7 @@ const opinionUpdateSchema = createInsertSchema(userOpinion)
|
|||||||
.required({ opinionId: true });
|
.required({ opinionId: true });
|
||||||
type OpinionInsertSchema = z.infer<typeof opinionInsertSchema>;
|
type OpinionInsertSchema = z.infer<typeof opinionInsertSchema>;
|
||||||
type UserInsertSchema = z.infer<typeof userInsertSchema>;
|
type UserInsertSchema = z.infer<typeof userInsertSchema>;
|
||||||
|
type UserUpdateSchema = z.infer<typeof userUpdateSchema>;
|
||||||
|
|
||||||
export const userRoute = router({
|
export const userRoute = router({
|
||||||
getAllUser: publicProcedure
|
getAllUser: publicProcedure
|
||||||
@@ -45,27 +51,21 @@ export const userRoute = router({
|
|||||||
async ({ input }) =>
|
async ({ input }) =>
|
||||||
await getAllUser(input.offset, input.limit, input.group, input.zone)
|
await getAllUser(input.offset, input.limit, input.group, input.zone)
|
||||||
),
|
),
|
||||||
createUser: verifiedPhone
|
createUser: publicProcedure
|
||||||
.input(
|
.input(
|
||||||
userInsertSchema.omit({ id: true, phone: true }).extend({
|
userInsertSchema.omit({ id: true }).extend({
|
||||||
opinions: opinionInsertSchema,
|
opinions: opinionInsertSchema,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.mutation(
|
.mutation(
|
||||||
async ({ input, ctx }) =>
|
async ({ input }) => await createUser({ ...input }, input.opinions)
|
||||||
await createUser({ ...input, phone: ctx.phone }, input.opinions)
|
|
||||||
),
|
),
|
||||||
requestOtp: publicProcedure
|
updateUser: protectedProcedure
|
||||||
.input(z.object({ phone: z.string().trim().min(5) }))
|
.input(userUpdateSchema)
|
||||||
.mutation(async ({ input }) => await requestOtp(input.phone)),
|
.mutation(async ({ input, ctx }) => await updateUser(ctx.user.id, input)),
|
||||||
verifyOtp: publicProcedure
|
login: publicProcedure
|
||||||
.input(
|
.input(z.object({ cid: z.string(), phone: z.string() }))
|
||||||
z.object({
|
.mutation(async ({ input }) => await login(input.cid, input.phone)),
|
||||||
pin: z.string().trim(),
|
|
||||||
token: z.string(),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input }) => await verifyOtp(input.token, input.pin)),
|
|
||||||
changeOpinion: protectedProcedure
|
changeOpinion: protectedProcedure
|
||||||
.input(opinionUpdateSchema)
|
.input(opinionUpdateSchema)
|
||||||
.mutation(
|
.mutation(
|
||||||
@@ -114,95 +114,41 @@ async function createUser(
|
|||||||
for (let op of opinions) {
|
for (let op of opinions) {
|
||||||
await db.insert(userOpinion).values({ ...op, userId: result.id });
|
await db.insert(userOpinion).values({ ...op, userId: result.id });
|
||||||
}
|
}
|
||||||
return { status: "OK" };
|
return { token: createJWT(newUser.phone) };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
throw new Error(`Unable to create new user:\n${e}`);
|
throw new Error(`Unable to create new user`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function requestOtp(phone: string) {
|
async function updateUser(userId: number, update: UserUpdateSchema) {
|
||||||
const _phone = phone.trim();
|
|
||||||
try {
|
try {
|
||||||
let rs = await fetch(Config.sms_api_request_endpoint, {
|
await db.update(user).set(update).where(eq(user.id, userId));
|
||||||
method: "POST",
|
return { status: "success" };
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
body: new URLSearchParams({
|
|
||||||
key: Config.sms_api_key,
|
|
||||||
secret: Config.sms_api_secret,
|
|
||||||
msisdn: _phone,
|
|
||||||
}),
|
|
||||||
}).then((res) => res.json());
|
|
||||||
|
|
||||||
if (rs.errors) {
|
|
||||||
console.error(rs);
|
|
||||||
throw new TRPCError({
|
|
||||||
message: `Unable to request OTP`,
|
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await db.insert(phoneToken).values({ phone: _phone, token: rs.token });
|
|
||||||
return {
|
|
||||||
status: rs.status as string,
|
|
||||||
token: rs.token as string,
|
|
||||||
refno: rs.refno as string,
|
|
||||||
};
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
throw new TRPCError({
|
throw new Error(`Unable to update user`);
|
||||||
message: `Unable to request OTP:\n${e}`,
|
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function verifyOtp(token: string, pin: string) {
|
async function login(cid: string, phone: string) {
|
||||||
try {
|
let user = await db.query.user.findFirst({
|
||||||
let pt = await db.query.phoneToken.findFirst({
|
where: (user, { and, eq }) => and(eq(user.cid, cid), eq(user.phone, phone)),
|
||||||
where: (pt, { eq }) => eq(pt.token, token),
|
|
||||||
orderBy: (pt, { desc }) => desc(pt.createdOn),
|
|
||||||
});
|
});
|
||||||
if (pt === undefined) {
|
if (user === undefined) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
message: `Invalid token`,
|
message: "Invalid Credentials",
|
||||||
code: "BAD_REQUEST",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pt;
|
|
||||||
let rs = await fetch(Config.sms_api_verify_endpoint, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
body: new URLSearchParams({
|
|
||||||
key: Config.sms_api_key,
|
|
||||||
secret: Config.sms_api_secret,
|
|
||||||
token,
|
|
||||||
pin,
|
|
||||||
}),
|
|
||||||
}).then((res) => res.json());
|
|
||||||
if (rs.errors) {
|
|
||||||
console.error(rs);
|
|
||||||
throw new TRPCError({
|
|
||||||
message: `Unable to verify OTP`,
|
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await db.delete(phoneToken).where(eq(phoneToken.phone, pt.phone));
|
return { token: createJWT(user.phone) };
|
||||||
const token = jwt.sign({ phone: pt.phone }, Config.jwt_secret, {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createJWT(phone: string) {
|
||||||
|
return jwt.sign({ phone: phone }, Config.jwt_secret, {
|
||||||
expiresIn: "365d",
|
expiresIn: "365d",
|
||||||
});
|
});
|
||||||
return token;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
throw new TRPCError({
|
|
||||||
message: `Unable to verify OTP:\n${e}`,
|
|
||||||
code: "BAD_REQUEST",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function changeOpinion(
|
async function changeOpinion(
|
||||||
@@ -229,3 +175,14 @@ async function changeOpinion(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function isValidThaiID(id: string) {
|
||||||
|
if (!/^\d{13}$/.test(id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let sum = 0;
|
||||||
|
for (let i = 0; i < 12; i++) {
|
||||||
|
sum += Number(id[i]) * (13 - i);
|
||||||
|
}
|
||||||
|
const checkSum = (11 - (sum % 11)) % 10;
|
||||||
|
return checkSum === Number(id[12]);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user