@rpcbase/auth 0.44.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/me/handler.d.ts +5 -0
- package/dist/api/me/handler.d.ts.map +1 -0
- package/dist/api/me/index.d.ts +16 -0
- package/dist/api/me/index.d.ts.map +1 -0
- package/dist/api/sign-in/handler.d.ts +2 -1
- package/dist/api/sign-in/handler.d.ts.map +1 -1
- package/dist/api/sign-in/index.d.ts +4 -0
- package/dist/api/sign-in/index.d.ts.map +1 -1
- package/dist/api/sign-out/handler.d.ts.map +1 -1
- package/dist/api/sign-up/handler.d.ts +2 -1
- package/dist/api/sign-up/handler.d.ts.map +1 -1
- package/dist/api/sign-up/index.d.ts +4 -0
- package/dist/api/sign-up/index.d.ts.map +1 -1
- package/dist/components/PasswordInput/index.d.ts +10 -0
- package/dist/components/PasswordInput/index.d.ts.map +1 -0
- package/dist/components/SignInForm/index.d.ts.map +1 -1
- package/dist/components/SignUpForm/index.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/handler-BSoyBLZM.js +50 -0
- package/dist/handler-Ba3pgtfZ.js +57 -0
- package/dist/{handler-42q87FS8.js → handler-CNHucHrj.js} +4 -1
- package/dist/handler-rZR_dx7n.js +71 -0
- package/dist/{index-Nc4R1TKZ.js → index-Cq04nmsE.js} +7 -3
- package/dist/{index-oIC-DH2m.js → index-r56vqjph.js} +6 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +87 -6
- package/dist/middleware-BiMXO6Dq.js +21 -0
- package/dist/middleware.d.ts +6 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/routes.js +1 -1
- package/dist/{schemas-7XFc7XYG.js → schemas-KL7REOdt.js} +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/handler-BD2C82Z3.js +0 -17
- package/dist/handler-C7htSfmB.js +0 -32
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/api/me/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAA8B,MAAM,cAAc,CAAA;AAE9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;yBAkDlC,KAAK,GAAG,CAAC,eAAe,CAAC;AAAzC,wBAGC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from '../../../../vite/node_modules/zod';
|
|
2
|
+
export declare const Route = "/api/rb/auth/me";
|
|
3
|
+
export declare const requestSchema: z.ZodObject<{}, z.core.$strip>;
|
|
4
|
+
export type RequestPayload = z.infer<typeof requestSchema>;
|
|
5
|
+
export declare const responseSchema: z.ZodObject<{
|
|
6
|
+
id: z.ZodOptional<z.ZodString>;
|
|
7
|
+
email: z.ZodOptional<z.ZodString>;
|
|
8
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
9
|
+
name: z.ZodOptional<z.ZodString>;
|
|
10
|
+
tenants: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
11
|
+
current_tenant_id: z.ZodOptional<z.ZodString>;
|
|
12
|
+
signed_in_tenants: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString>>>;
|
|
13
|
+
error: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type ResponsePayload = z.infer<typeof responseSchema>;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/me/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,KAAK,oBAAoB,CAAA;AAEtC,eAAO,MAAM,aAAa,gCAAe,CAAA;AACzC,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAE1D,eAAO,MAAM,cAAc;;;;;;;;;iBASzB,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/api/sign-in/handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/api/sign-in/handler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAA8B,MAAM,cAAc,CAAA;AAG9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;yBAgElC,KAAK,GAAG,CAAC,eAAe,CAAC;AAAzC,wBAEC"}
|
|
@@ -2,11 +2,15 @@ import { z } from '../../../../vite/node_modules/zod';
|
|
|
2
2
|
export declare const Route = "/api/rb/auth/sign-in";
|
|
3
3
|
export declare const requestSchema: z.ZodObject<{
|
|
4
4
|
email_or_phone: z.ZodDefault<z.ZodString>;
|
|
5
|
+
password: z.ZodString;
|
|
5
6
|
remember_me: z.ZodDefault<z.ZodBoolean>;
|
|
6
7
|
}, z.core.$strip>;
|
|
7
8
|
export type RequestPayload = z.infer<typeof requestSchema>;
|
|
8
9
|
export declare const responseSchema: z.ZodObject<{
|
|
9
10
|
success: z.ZodBoolean;
|
|
11
|
+
error: z.ZodOptional<z.ZodString>;
|
|
12
|
+
user_id: z.ZodOptional<z.ZodString>;
|
|
13
|
+
tenant_id: z.ZodOptional<z.ZodString>;
|
|
10
14
|
}, z.core.$strip>;
|
|
11
15
|
export type ResponsePayload = z.infer<typeof responseSchema>;
|
|
12
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/sign-in/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,KAAK,yBAAyB,CAAA;AAE3C,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/sign-in/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,KAAK,yBAAyB,CAAA;AAE3C,eAAO,MAAM,aAAa;;;;iBAexB,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAE1D,eAAO,MAAM,cAAc;;;;;iBAKzB,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/api/sign-out/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/api/sign-out/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAO,MAAM,cAAc,CAAA;yBAkBvB,KAAK,GAAG;AAAxB,wBAEC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/api/sign-up/handler.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/api/sign-up/handler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAA8B,MAAM,cAAc,CAAA;AAG9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;yBAwFlC,KAAK,GAAG,CAAC,eAAe,CAAC;AAAzC,wBAEC"}
|
|
@@ -4,10 +4,14 @@ export declare const requestSchema: z.ZodObject<{
|
|
|
4
4
|
email_or_phone: z.ZodString;
|
|
5
5
|
password: z.ZodString;
|
|
6
6
|
password_confirmation: z.ZodString;
|
|
7
|
+
remember_me: z.ZodDefault<z.ZodBoolean>;
|
|
7
8
|
}, z.core.$strip>;
|
|
8
9
|
export type RequestPayload = z.infer<typeof requestSchema>;
|
|
9
10
|
export declare const responseSchema: z.ZodObject<{
|
|
10
11
|
success: z.ZodBoolean;
|
|
12
|
+
error: z.ZodOptional<z.ZodString>;
|
|
13
|
+
user_id: z.ZodOptional<z.ZodString>;
|
|
14
|
+
tenant_id: z.ZodOptional<z.ZodString>;
|
|
11
15
|
}, z.core.$strip>;
|
|
12
16
|
export type ResponsePayload = z.infer<typeof responseSchema>;
|
|
13
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/sign-up/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,KAAK,yBAAyB,CAAA;AAE3C,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/sign-up/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,KAAK,yBAAyB,CAAA;AAE3C,eAAO,MAAM,aAAa;;;;;iBAoBtB,CAAA;AAEJ,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAE1D,eAAO,MAAM,cAAc;;;;;iBAKzB,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type PasswordInputProps = {
|
|
2
|
+
id: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
autoComplete?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const PasswordInput: ({ id, name, className, placeholder, autoComplete, }: PasswordInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/PasswordInput/index.tsx"],"names":[],"mappings":"AAGA,KAAK,kBAAkB,GAAG;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,qDAM3B,kBAAkB,4CA0BpB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SignInForm/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAY,MAAM,OAAO,CAAA;AAW1C,eAAO,MAAM,UAAU,GAAI,yBAGxB;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SignInForm/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAY,MAAM,OAAO,CAAA;AAW1C,eAAO,MAAM,UAAU,GAAI,yBAGxB;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,4CA6CA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SignUpForm/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SignUpForm/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAsB,MAAM,OAAO,CAAA;AAWpD,eAAO,MAAM,UAAU,GAAI,yBAGxB;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,4CAyEA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
import { i as isEmail } from "./isEmail-IG0hXiQk.js";
|
|
3
|
+
import { loadModel } from "@rpcbase/api";
|
|
4
|
+
import { hashPassword } from "@rpcbase/server";
|
|
5
|
+
import { R as Route, r as requestSchema } from "./index-r56vqjph.js";
|
|
6
|
+
const signIn = async (payload, ctx) => {
|
|
7
|
+
const User = await loadModel("User", ctx);
|
|
8
|
+
const parsed = requestSchema.safeParse(payload);
|
|
9
|
+
if (!parsed.success) {
|
|
10
|
+
ctx.res.status(400);
|
|
11
|
+
return { success: false, error: "invalid_payload" };
|
|
12
|
+
}
|
|
13
|
+
const { email_or_phone, password } = parsed.data;
|
|
14
|
+
const query = isEmail(email_or_phone) ? { email: email_or_phone } : { phone: email_or_phone };
|
|
15
|
+
const user = await User.findOne(query, { password: 1, tenants: 1 });
|
|
16
|
+
if (!user?.password) {
|
|
17
|
+
ctx.res.status(401);
|
|
18
|
+
return { success: false, error: "invalid_credentials" };
|
|
19
|
+
}
|
|
20
|
+
const [salt, hashedPassword] = String(user.password).split(":");
|
|
21
|
+
if (!salt || !hashedPassword) {
|
|
22
|
+
ctx.res.status(500);
|
|
23
|
+
return { success: false, error: "invalid_password_format" };
|
|
24
|
+
}
|
|
25
|
+
const derivedKey = await hashPassword(password, salt);
|
|
26
|
+
const passwordMatches = crypto.timingSafeEqual(Buffer.from(hashedPassword, "hex"), derivedKey);
|
|
27
|
+
if (!passwordMatches) {
|
|
28
|
+
ctx.res.status(401);
|
|
29
|
+
return { success: false, error: "invalid_credentials" };
|
|
30
|
+
}
|
|
31
|
+
const tenantId = user.tenants?.[0]?.toString?.() || "00000000";
|
|
32
|
+
const signedInTenants = (user.tenants || []).map((t) => t.toString?.() || String(t)) || [tenantId];
|
|
33
|
+
if (!ctx.req.session) {
|
|
34
|
+
ctx.res.status(500);
|
|
35
|
+
return { success: false, error: "session_unavailable" };
|
|
36
|
+
}
|
|
37
|
+
ctx.req.session.user = {
|
|
38
|
+
id: user._id.toString(),
|
|
39
|
+
current_tenant_id: tenantId,
|
|
40
|
+
signed_in_tenants: signedInTenants.length ? signedInTenants : [tenantId],
|
|
41
|
+
is_entry_gate_authorized: true
|
|
42
|
+
};
|
|
43
|
+
return { success: true, user_id: user._id.toString(), tenant_id: tenantId };
|
|
44
|
+
};
|
|
45
|
+
const handler = (api) => {
|
|
46
|
+
api.post(Route, signIn);
|
|
47
|
+
};
|
|
48
|
+
export {
|
|
49
|
+
handler as default
|
|
50
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { loadModel } from "@rpcbase/api";
|
|
2
|
+
import { r as restrictSessionMiddleware } from "./middleware-BiMXO6Dq.js";
|
|
3
|
+
import { o as object, s as string, a as array } from "./schemas-KL7REOdt.js";
|
|
4
|
+
const Route = "/api/rb/auth/me";
|
|
5
|
+
object({});
|
|
6
|
+
object({
|
|
7
|
+
id: string().optional(),
|
|
8
|
+
email: string().email().optional(),
|
|
9
|
+
phone: string().optional(),
|
|
10
|
+
name: string().optional(),
|
|
11
|
+
tenants: array(string()).default([]),
|
|
12
|
+
current_tenant_id: string().optional(),
|
|
13
|
+
signed_in_tenants: array(string()).default([]).optional(),
|
|
14
|
+
error: string().optional()
|
|
15
|
+
});
|
|
16
|
+
const me = async (_payload, ctx) => {
|
|
17
|
+
const sessionUser = ctx.req.session?.user;
|
|
18
|
+
if (!sessionUser?.id) {
|
|
19
|
+
ctx.res.status(401);
|
|
20
|
+
return {
|
|
21
|
+
id: "",
|
|
22
|
+
current_tenant_id: "",
|
|
23
|
+
signed_in_tenants: [],
|
|
24
|
+
tenants: [],
|
|
25
|
+
error: "not_authenticated"
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const User = await loadModel("User", ctx);
|
|
29
|
+
const user = await User.findById(sessionUser.id);
|
|
30
|
+
if (!user) {
|
|
31
|
+
ctx.res.status(404);
|
|
32
|
+
return {
|
|
33
|
+
id: "",
|
|
34
|
+
current_tenant_id: "",
|
|
35
|
+
signed_in_tenants: [],
|
|
36
|
+
tenants: [],
|
|
37
|
+
error: "user_not_found"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const tenantId = sessionUser.current_tenant_id || user.tenants?.[0]?.toString?.() || "00000000";
|
|
41
|
+
return {
|
|
42
|
+
id: user._id.toString(),
|
|
43
|
+
email: user.email,
|
|
44
|
+
phone: user.phone,
|
|
45
|
+
name: user.name,
|
|
46
|
+
tenants: (user.tenants || []).map((t) => t.toString?.() || String(t)),
|
|
47
|
+
current_tenant_id: tenantId,
|
|
48
|
+
signed_in_tenants: sessionUser.signed_in_tenants || []
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
const handler = (api) => {
|
|
52
|
+
api.use(Route, restrictSessionMiddleware);
|
|
53
|
+
api.get(Route, me);
|
|
54
|
+
};
|
|
55
|
+
export {
|
|
56
|
+
handler as default
|
|
57
|
+
};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { o as object, b as boolean } from "./schemas-
|
|
1
|
+
import { o as object, b as boolean } from "./schemas-KL7REOdt.js";
|
|
2
2
|
const Route = "/api/rb/auth/sign-out";
|
|
3
3
|
object({});
|
|
4
4
|
object({
|
|
5
5
|
success: boolean()
|
|
6
6
|
});
|
|
7
7
|
const handleSignOut = async (_, ctx) => {
|
|
8
|
+
if (!ctx.req.session) {
|
|
9
|
+
return { success: true };
|
|
10
|
+
}
|
|
8
11
|
await new Promise((resolve) => ctx.req.session.destroy(() => resolve()));
|
|
9
12
|
return {
|
|
10
13
|
success: true
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
import { i as isEmail } from "./isEmail-IG0hXiQk.js";
|
|
3
|
+
import { loadModel } from "@rpcbase/api";
|
|
4
|
+
import { hashPassword, sendEmail } from "@rpcbase/server";
|
|
5
|
+
import { R as Route, r as requestSchema } from "./index-Cq04nmsE.js";
|
|
6
|
+
const signUp = async (payload, ctx) => {
|
|
7
|
+
const User = await loadModel("User", ctx);
|
|
8
|
+
const Tenant = await loadModel("Tenant", ctx);
|
|
9
|
+
const parsed = requestSchema.safeParse(payload);
|
|
10
|
+
if (!parsed.success) {
|
|
11
|
+
ctx.res.status(400);
|
|
12
|
+
return { success: false, error: "invalid_payload" };
|
|
13
|
+
}
|
|
14
|
+
const { email_or_phone, password, remember_me: _remember_me } = parsed.data;
|
|
15
|
+
const is_email = isEmail(email_or_phone);
|
|
16
|
+
const query = is_email ? { email: email_or_phone } : { phone: email_or_phone };
|
|
17
|
+
const existingUser = await User.findOne(query);
|
|
18
|
+
if (existingUser) {
|
|
19
|
+
console.log("user with email or phone already exists", email_or_phone);
|
|
20
|
+
ctx.res.status(409);
|
|
21
|
+
return { success: false, error: "user_exists" };
|
|
22
|
+
}
|
|
23
|
+
const salt = crypto.randomBytes(16).toString("hex");
|
|
24
|
+
const derivedKey = await hashPassword(password, salt);
|
|
25
|
+
const hashedPassword = `${salt}:${derivedKey.toString("hex")}`;
|
|
26
|
+
const tenantId = crypto.randomUUID();
|
|
27
|
+
const user = new User({
|
|
28
|
+
...query,
|
|
29
|
+
password: hashedPassword,
|
|
30
|
+
tenants: [tenantId]
|
|
31
|
+
});
|
|
32
|
+
await user.save();
|
|
33
|
+
if (is_email) {
|
|
34
|
+
try {
|
|
35
|
+
await sendEmail({
|
|
36
|
+
to: email_or_phone,
|
|
37
|
+
subject: "Verify your email",
|
|
38
|
+
html: "<p>Welcome to rpcbase!</p><p>We created your account. Use this email to sign in and finish verification.</p>",
|
|
39
|
+
text: "Welcome to rpcbase! We created your account. Use this email to sign in and finish verification."
|
|
40
|
+
});
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.warn("failed to send sign-up email", err);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
await Tenant.create({
|
|
47
|
+
tenant_id: tenantId,
|
|
48
|
+
name: query.email || query.phone
|
|
49
|
+
});
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.warn("failed to create tenant for user", err);
|
|
52
|
+
}
|
|
53
|
+
console.log("created new user", user._id.toString());
|
|
54
|
+
if (!ctx.req.session) {
|
|
55
|
+
ctx.res.status(500);
|
|
56
|
+
return { success: false, error: "session_unavailable" };
|
|
57
|
+
}
|
|
58
|
+
ctx.req.session.user = {
|
|
59
|
+
id: user._id.toString(),
|
|
60
|
+
current_tenant_id: tenantId,
|
|
61
|
+
signed_in_tenants: [tenantId],
|
|
62
|
+
is_entry_gate_authorized: true
|
|
63
|
+
};
|
|
64
|
+
return { success: true, user_id: user._id.toString(), tenant_id: tenantId };
|
|
65
|
+
};
|
|
66
|
+
const handler = (api) => {
|
|
67
|
+
api.post(Route, signUp);
|
|
68
|
+
};
|
|
69
|
+
export {
|
|
70
|
+
handler as default
|
|
71
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as isValidNumber } from "./isValidNumber-6pMDGLRn.js";
|
|
2
|
-
import { o as object,
|
|
2
|
+
import { o as object, b as boolean, s as string } from "./schemas-KL7REOdt.js";
|
|
3
3
|
const Route = "/api/rb/auth/sign-up";
|
|
4
4
|
const requestSchema = object({
|
|
5
5
|
email_or_phone: string().nonempty("Email or phone number is required").refine(
|
|
@@ -11,13 +11,17 @@ const requestSchema = object({
|
|
|
11
11
|
"Please enter a valid email address or phone number"
|
|
12
12
|
),
|
|
13
13
|
password: string().min(8, { message: "Password must be at least 8 characters long." }),
|
|
14
|
-
password_confirmation: string().nonempty({ message: "Please confirm your password." })
|
|
14
|
+
password_confirmation: string().nonempty({ message: "Please confirm your password." }),
|
|
15
|
+
remember_me: boolean().default(true)
|
|
15
16
|
}).refine((data) => data.password === data.password_confirmation, {
|
|
16
17
|
message: "Passwords do not match.",
|
|
17
18
|
path: ["password_confirmation"]
|
|
18
19
|
});
|
|
19
20
|
object({
|
|
20
|
-
success: boolean()
|
|
21
|
+
success: boolean(),
|
|
22
|
+
error: string().optional(),
|
|
23
|
+
user_id: string().optional(),
|
|
24
|
+
tenant_id: string().optional()
|
|
21
25
|
});
|
|
22
26
|
export {
|
|
23
27
|
Route as R,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as isValidNumber } from "./isValidNumber-6pMDGLRn.js";
|
|
2
|
-
import { o as object, b as boolean, s as string } from "./schemas-
|
|
2
|
+
import { o as object, b as boolean, s as string } from "./schemas-KL7REOdt.js";
|
|
3
3
|
const Route = "/api/rb/auth/sign-in";
|
|
4
4
|
const requestSchema = object({
|
|
5
5
|
email_or_phone: string().nonempty("Email or phone number is required").default("").refine(
|
|
@@ -10,10 +10,14 @@ const requestSchema = object({
|
|
|
10
10
|
},
|
|
11
11
|
"Please enter a valid email address or phone number"
|
|
12
12
|
),
|
|
13
|
+
password: string().min(1, { message: "Password is required" }),
|
|
13
14
|
remember_me: boolean().default(true)
|
|
14
15
|
});
|
|
15
16
|
object({
|
|
16
|
-
success: boolean()
|
|
17
|
+
success: boolean(),
|
|
18
|
+
error: string().optional(),
|
|
19
|
+
user_id: string().optional(),
|
|
20
|
+
tenant_id: string().optional()
|
|
17
21
|
});
|
|
18
22
|
export {
|
|
19
23
|
Route as R,
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,10 @@ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
|
2
2
|
import { useLocation, Link } from "@rpcbase/router";
|
|
3
3
|
import clsx from "clsx";
|
|
4
4
|
import { useFormContext, useForm, zodResolver, FormProvider } from "@rpcbase/form";
|
|
5
|
-
import { useEffect } from "react";
|
|
6
|
-
import { r as requestSchema } from "./index-
|
|
7
|
-
import { r as requestSchema$1 } from "./index-
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import { r as requestSchema } from "./index-r56vqjph.js";
|
|
7
|
+
import { r as requestSchema$1 } from "./index-Cq04nmsE.js";
|
|
8
|
+
import { b, a, r } from "./middleware-BiMXO6Dq.js";
|
|
8
9
|
const LINKS_REDIRECTION_MAP = {
|
|
9
10
|
"/auth/sign-in": {
|
|
10
11
|
"title": "Sign Up",
|
|
@@ -113,12 +114,29 @@ const SignInForm = ({
|
|
|
113
114
|
const methods = useForm({
|
|
114
115
|
defaultValues: {
|
|
115
116
|
email_or_phone: "",
|
|
117
|
+
password: "",
|
|
116
118
|
remember_me: true
|
|
117
119
|
},
|
|
118
120
|
resolver: zodResolver(requestSchema)
|
|
119
121
|
});
|
|
120
122
|
const onSubmit = async (data) => {
|
|
121
123
|
console.log("SUBMIT SIGNIN", data);
|
|
124
|
+
try {
|
|
125
|
+
const res = await fetch("/api/rb/auth/sign-in", {
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: {
|
|
128
|
+
"Content-Type": "application/json"
|
|
129
|
+
},
|
|
130
|
+
body: JSON.stringify(data)
|
|
131
|
+
});
|
|
132
|
+
const json = await res.json();
|
|
133
|
+
console.log("SIGN IN RESPONSE", json);
|
|
134
|
+
if (!res.ok) {
|
|
135
|
+
console.error("Sign-in failed", json);
|
|
136
|
+
}
|
|
137
|
+
} catch (err) {
|
|
138
|
+
console.error("Sign-in request error", err);
|
|
139
|
+
}
|
|
122
140
|
};
|
|
123
141
|
useEffect(() => {
|
|
124
142
|
console.log(methods.formState.errors);
|
|
@@ -129,21 +147,55 @@ const SignUpForm = ({
|
|
|
129
147
|
children,
|
|
130
148
|
className
|
|
131
149
|
}) => {
|
|
150
|
+
const [serverMessage, setServerMessage] = useState(null);
|
|
132
151
|
const methods = useForm({
|
|
133
152
|
defaultValues: {
|
|
134
153
|
email_or_phone: "",
|
|
135
154
|
password: "",
|
|
136
|
-
password_confirmation: ""
|
|
155
|
+
password_confirmation: "",
|
|
156
|
+
remember_me: true
|
|
137
157
|
},
|
|
138
158
|
resolver: zodResolver(requestSchema$1)
|
|
139
159
|
});
|
|
140
160
|
const onSubmit = async (data) => {
|
|
161
|
+
setServerMessage(null);
|
|
162
|
+
methods.clearErrors("root");
|
|
141
163
|
console.log("SUBMIT SIGNUp", data);
|
|
164
|
+
try {
|
|
165
|
+
const res = await fetch("/api/rb/auth/sign-up", {
|
|
166
|
+
method: "POST",
|
|
167
|
+
headers: {
|
|
168
|
+
"Content-Type": "application/json"
|
|
169
|
+
},
|
|
170
|
+
body: JSON.stringify(data)
|
|
171
|
+
});
|
|
172
|
+
const json = await res.json();
|
|
173
|
+
console.log("SIGN UP RESPONSE", json);
|
|
174
|
+
if (!res.ok) {
|
|
175
|
+
console.error("Sign-up failed", json);
|
|
176
|
+
const message = json.error === "user_exists" ? "An account already exists with this email or phone." : "Sign-up failed. Please try again.";
|
|
177
|
+
methods.setError("root", { type: "server", message });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (!json.success) {
|
|
181
|
+
methods.setError("root", { type: "server", message: "Sign-up failed. Please try again." });
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
setServerMessage("Account created. Check your inbox to verify your email.");
|
|
185
|
+
methods.reset();
|
|
186
|
+
} catch (err) {
|
|
187
|
+
console.error("Sign-up request error", err);
|
|
188
|
+
methods.setError("root", { type: "server", message: "Network error. Please try again." });
|
|
189
|
+
}
|
|
142
190
|
};
|
|
143
191
|
useEffect(() => {
|
|
144
192
|
console.log(methods.formState.errors);
|
|
145
193
|
}, [methods.formState.errors]);
|
|
146
|
-
return /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */
|
|
194
|
+
return /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */ jsxs("form", { method: "post", noValidate: true, className, onSubmit: methods.handleSubmit(onSubmit), children: [
|
|
195
|
+
children,
|
|
196
|
+
methods.formState.errors.root?.message && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-red-600", role: "alert", children: methods.formState.errors.root.message }),
|
|
197
|
+
serverMessage && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-green-700", role: "status", children: serverMessage })
|
|
198
|
+
] }) });
|
|
147
199
|
};
|
|
148
200
|
const RememberMeCheckbox = ({
|
|
149
201
|
label,
|
|
@@ -168,11 +220,40 @@ const RememberMeCheckbox = ({
|
|
|
168
220
|
)
|
|
169
221
|
] });
|
|
170
222
|
};
|
|
223
|
+
const PasswordInput = ({
|
|
224
|
+
id,
|
|
225
|
+
name = "password",
|
|
226
|
+
className,
|
|
227
|
+
placeholder,
|
|
228
|
+
autoComplete = "current-password"
|
|
229
|
+
}) => {
|
|
230
|
+
const { register, formState } = useFormContext();
|
|
231
|
+
const fieldError = formState.errors[name];
|
|
232
|
+
const errorMessage = typeof fieldError === "string" ? fieldError : typeof fieldError?.message === "string" ? fieldError.message : void 0;
|
|
233
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
234
|
+
/* @__PURE__ */ jsx(
|
|
235
|
+
"input",
|
|
236
|
+
{
|
|
237
|
+
id,
|
|
238
|
+
type: "password",
|
|
239
|
+
autoComplete,
|
|
240
|
+
className,
|
|
241
|
+
placeholder,
|
|
242
|
+
...register(name)
|
|
243
|
+
}
|
|
244
|
+
),
|
|
245
|
+
errorMessage ? /* @__PURE__ */ jsx("p", { className: "mt-1 -mb-2 text-sm/6 text-red-500", children: errorMessage }) : null
|
|
246
|
+
] });
|
|
247
|
+
};
|
|
171
248
|
export {
|
|
172
249
|
AppleSignInButton,
|
|
173
250
|
AuthLayout,
|
|
174
251
|
EmailOrPhoneInput,
|
|
252
|
+
PasswordInput,
|
|
175
253
|
RememberMeCheckbox,
|
|
176
254
|
SignInForm,
|
|
177
|
-
SignUpForm
|
|
255
|
+
SignUpForm,
|
|
256
|
+
b as redirectAuthMiddleware,
|
|
257
|
+
a as requireSession,
|
|
258
|
+
r as restrictSessionMiddleware
|
|
178
259
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const isAuthenticated = (req) => {
|
|
2
|
+
return Boolean(req.session?.user?.id);
|
|
3
|
+
};
|
|
4
|
+
const restrictSessionMiddleware = (req, res, next) => {
|
|
5
|
+
if (isAuthenticated(req)) {
|
|
6
|
+
return next();
|
|
7
|
+
}
|
|
8
|
+
res.status(401).json({ error: "unauthorized" });
|
|
9
|
+
};
|
|
10
|
+
const requireSession = restrictSessionMiddleware;
|
|
11
|
+
const redirectAuthMiddleware = (req, res, next) => {
|
|
12
|
+
if (req.path.startsWith("/app") && !isAuthenticated(req)) {
|
|
13
|
+
return res.redirect("/auth/sign-in");
|
|
14
|
+
}
|
|
15
|
+
next();
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
requireSession as a,
|
|
19
|
+
redirectAuthMiddleware as b,
|
|
20
|
+
restrictSessionMiddleware as r
|
|
21
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Middleware } from '../../api/src';
|
|
2
|
+
import { AuthSessionUser } from './types';
|
|
3
|
+
export declare const restrictSessionMiddleware: Middleware<AuthSessionUser>;
|
|
4
|
+
export declare const requireSession: Middleware<AuthSessionUser>;
|
|
5
|
+
export declare const redirectAuthMiddleware: Middleware<AuthSessionUser>;
|
|
6
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAO9C,eAAO,MAAM,yBAAyB,EAAE,UAAU,CAAC,eAAe,CAMjE,CAAA;AAED,eAAO,MAAM,cAAc,6BAA4B,CAAA;AAEvD,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,eAAe,CAM9D,CAAA"}
|
package/dist/routes.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const routes = Object.entries({
|
|
2
|
-
.../* @__PURE__ */ Object.assign({ "./api/sign-in/handler.ts": () => import("./handler-
|
|
2
|
+
.../* @__PURE__ */ Object.assign({ "./api/me/handler.ts": () => import("./handler-Ba3pgtfZ.js"), "./api/sign-in/handler.ts": () => import("./handler-BSoyBLZM.js"), "./api/sign-out/handler.ts": () => import("./handler-CNHucHrj.js"), "./api/sign-up/handler.ts": () => import("./handler-rZR_dx7n.js") })
|
|
3
3
|
}).reduce((acc, [path, mod]) => {
|
|
4
4
|
acc[path.replace("./api/", "@rpcbase/auth/api/")] = mod;
|
|
5
5
|
return acc;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,wBAAwB,EAAE,OAAO,CAAA;CAClC,CAAA"}
|
package/package.json
CHANGED
package/dist/handler-BD2C82Z3.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { i as isEmail } from "./isEmail-IG0hXiQk.js";
|
|
2
|
-
import { R as Route, r as requestSchema } from "./index-oIC-DH2m.js";
|
|
3
|
-
const signIn = async (payload, ctx) => {
|
|
4
|
-
const { email_or_phone } = requestSchema.parse(payload);
|
|
5
|
-
if (isEmail(email_or_phone)) {
|
|
6
|
-
console.log("is valid email");
|
|
7
|
-
} else {
|
|
8
|
-
console.log("is not valid email");
|
|
9
|
-
}
|
|
10
|
-
return { success: true };
|
|
11
|
-
};
|
|
12
|
-
const handler = (api) => {
|
|
13
|
-
api.post(Route, signIn);
|
|
14
|
-
};
|
|
15
|
-
export {
|
|
16
|
-
handler as default
|
|
17
|
-
};
|
package/dist/handler-C7htSfmB.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import crypto from "crypto";
|
|
2
|
-
import { i as isEmail } from "./isEmail-IG0hXiQk.js";
|
|
3
|
-
import { loadModel } from "@rpcbase/api";
|
|
4
|
-
import { hashPassword } from "@rpcbase/server";
|
|
5
|
-
import { R as Route, r as requestSchema } from "./index-Nc4R1TKZ.js";
|
|
6
|
-
const signUp = async (payload, ctx) => {
|
|
7
|
-
const User = await loadModel("User", ctx);
|
|
8
|
-
const { email_or_phone, password } = requestSchema.parse(payload);
|
|
9
|
-
const is_email = isEmail(email_or_phone);
|
|
10
|
-
const query = is_email ? { email: email_or_phone } : { phone: email_or_phone };
|
|
11
|
-
const existingUser = await User.findOne(query);
|
|
12
|
-
if (existingUser) {
|
|
13
|
-
console.log("user with email or phone already exists", email_or_phone);
|
|
14
|
-
return { success: false };
|
|
15
|
-
}
|
|
16
|
-
const salt = crypto.randomBytes(16).toString("hex");
|
|
17
|
-
const derivedKey = await hashPassword(password, salt);
|
|
18
|
-
const hashedPassword = `${salt}:${derivedKey.toString("hex")}`;
|
|
19
|
-
const user = new User({
|
|
20
|
-
...query,
|
|
21
|
-
password: hashedPassword
|
|
22
|
-
});
|
|
23
|
-
await user.save();
|
|
24
|
-
console.log("created new user", user._id.toString());
|
|
25
|
-
return { success: true };
|
|
26
|
-
};
|
|
27
|
-
const handler = (api) => {
|
|
28
|
-
api.post(Route, signUp);
|
|
29
|
-
};
|
|
30
|
-
export {
|
|
31
|
-
handler as default
|
|
32
|
-
};
|