@spfn/auth 0.2.0-beta.40 → 0.2.0-beta.42
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/README.md +75 -0
- package/dist/{authenticate-BbugF32w.d.ts → authenticate-gnTzrnU-.d.ts} +2 -1
- package/dist/index.d.ts +4 -3
- package/dist/server.d.ts +113 -55
- package/dist/server.js +70 -5
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -7153,6 +7153,30 @@ var authRegisterEvent = defineEvent(
|
|
|
7153
7153
|
metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown()))
|
|
7154
7154
|
})
|
|
7155
7155
|
);
|
|
7156
|
+
var invitationCreatedEvent = defineEvent(
|
|
7157
|
+
"auth.invitation.created",
|
|
7158
|
+
Type.Object({
|
|
7159
|
+
invitationId: Type.String(),
|
|
7160
|
+
email: Type.String(),
|
|
7161
|
+
token: Type.String(),
|
|
7162
|
+
roleId: Type.Number(),
|
|
7163
|
+
invitedBy: Type.String(),
|
|
7164
|
+
expiresAt: Type.String(),
|
|
7165
|
+
isResend: Type.Boolean(),
|
|
7166
|
+
metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown()))
|
|
7167
|
+
})
|
|
7168
|
+
);
|
|
7169
|
+
var invitationAcceptedEvent = defineEvent(
|
|
7170
|
+
"auth.invitation.accepted",
|
|
7171
|
+
Type.Object({
|
|
7172
|
+
invitationId: Type.String(),
|
|
7173
|
+
email: Type.String(),
|
|
7174
|
+
userId: Type.String(),
|
|
7175
|
+
roleId: Type.Number(),
|
|
7176
|
+
invitedBy: Type.String(),
|
|
7177
|
+
metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown()))
|
|
7178
|
+
})
|
|
7179
|
+
);
|
|
7156
7180
|
|
|
7157
7181
|
// src/server/services/auth.service.ts
|
|
7158
7182
|
async function checkAccountExistsService(params) {
|
|
@@ -7566,7 +7590,7 @@ function calculateExpiresAt(days = 7) {
|
|
|
7566
7590
|
return expiresAt;
|
|
7567
7591
|
}
|
|
7568
7592
|
async function createInvitation(params) {
|
|
7569
|
-
const { email, roleId, invitedBy, expiresInDays = 7, metadata } = params;
|
|
7593
|
+
const { email, roleId, invitedBy, expiresInDays = 7, expiresAt: expiresAtParam, metadata } = params;
|
|
7570
7594
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
7571
7595
|
if (!emailRegex.test(email)) {
|
|
7572
7596
|
throw new Error("Invalid email format");
|
|
@@ -7588,7 +7612,7 @@ async function createInvitation(params) {
|
|
|
7588
7612
|
throw new Error(`User with id ${invitedBy} not found`);
|
|
7589
7613
|
}
|
|
7590
7614
|
const token = generateInvitationToken();
|
|
7591
|
-
const expiresAt = calculateExpiresAt(expiresInDays);
|
|
7615
|
+
const expiresAt = expiresAtParam ?? calculateExpiresAt(expiresInDays);
|
|
7592
7616
|
const invitation = await invitationsRepository.create({
|
|
7593
7617
|
email,
|
|
7594
7618
|
token,
|
|
@@ -7598,7 +7622,16 @@ async function createInvitation(params) {
|
|
|
7598
7622
|
expiresAt,
|
|
7599
7623
|
metadata: metadata || null
|
|
7600
7624
|
});
|
|
7601
|
-
|
|
7625
|
+
await invitationCreatedEvent.emit({
|
|
7626
|
+
invitationId: String(invitation.id),
|
|
7627
|
+
email,
|
|
7628
|
+
token,
|
|
7629
|
+
roleId,
|
|
7630
|
+
invitedBy: String(invitedBy),
|
|
7631
|
+
expiresAt: expiresAt.toISOString(),
|
|
7632
|
+
isResend: false,
|
|
7633
|
+
metadata
|
|
7634
|
+
});
|
|
7602
7635
|
return invitation;
|
|
7603
7636
|
}
|
|
7604
7637
|
async function getInvitationByToken(token) {
|
|
@@ -7662,7 +7695,14 @@ async function acceptInvitation(params) {
|
|
|
7662
7695
|
"accepted",
|
|
7663
7696
|
/* @__PURE__ */ new Date()
|
|
7664
7697
|
);
|
|
7665
|
-
|
|
7698
|
+
await invitationAcceptedEvent.emit({
|
|
7699
|
+
invitationId: String(invitation.id),
|
|
7700
|
+
email: invitation.email,
|
|
7701
|
+
userId: String(newUser.id),
|
|
7702
|
+
roleId: Number(invitation.roleId),
|
|
7703
|
+
invitedBy: String(invitation.invitedBy),
|
|
7704
|
+
metadata: invitation.metadata
|
|
7705
|
+
});
|
|
7666
7706
|
return {
|
|
7667
7707
|
userId: newUser.id,
|
|
7668
7708
|
email: newUser.email,
|
|
@@ -7707,7 +7747,16 @@ async function resendInvitation(id11, expiresInDays = 7) {
|
|
|
7707
7747
|
if (!updated) {
|
|
7708
7748
|
throw new Error("Failed to update invitation");
|
|
7709
7749
|
}
|
|
7710
|
-
|
|
7750
|
+
await invitationCreatedEvent.emit({
|
|
7751
|
+
invitationId: String(invitation.id),
|
|
7752
|
+
email: invitation.email,
|
|
7753
|
+
token: invitation.token,
|
|
7754
|
+
roleId: Number(invitation.roleId),
|
|
7755
|
+
invitedBy: String(invitation.invitedBy),
|
|
7756
|
+
expiresAt: newExpiresAt.toISOString(),
|
|
7757
|
+
isResend: true,
|
|
7758
|
+
metadata: invitation.metadata
|
|
7759
|
+
});
|
|
7711
7760
|
return updated;
|
|
7712
7761
|
}
|
|
7713
7762
|
|
|
@@ -8675,6 +8724,10 @@ var createInvitation2 = route2.post("/_auth/invitations").input({
|
|
|
8675
8724
|
maximum: 30,
|
|
8676
8725
|
description: "Days until invitation expires (default: 7)"
|
|
8677
8726
|
})),
|
|
8727
|
+
expiresAt: Type.Optional(Type.String({
|
|
8728
|
+
format: "date-time",
|
|
8729
|
+
description: "Exact expiration timestamp (ISO 8601). Takes precedence over expiresInDays."
|
|
8730
|
+
})),
|
|
8678
8731
|
metadata: Type.Optional(Type.Any({
|
|
8679
8732
|
description: "Custom metadata (welcome message, department, etc.)"
|
|
8680
8733
|
}))
|
|
@@ -8687,6 +8740,7 @@ var createInvitation2 = route2.post("/_auth/invitations").input({
|
|
|
8687
8740
|
roleId: body.roleId,
|
|
8688
8741
|
invitedBy: Number(userId),
|
|
8689
8742
|
expiresInDays: body.expiresInDays,
|
|
8743
|
+
expiresAt: body.expiresAt ? new Date(body.expiresAt) : void 0,
|
|
8690
8744
|
metadata: body.metadata
|
|
8691
8745
|
});
|
|
8692
8746
|
const baseUrl = process.env.SPFN_API_URL || "http://localhost:8790";
|
|
@@ -8992,6 +9046,7 @@ var oauthRouter = defineRouter4({
|
|
|
8992
9046
|
|
|
8993
9047
|
// src/server/routes/admin/index.ts
|
|
8994
9048
|
init_esm();
|
|
9049
|
+
import { ForbiddenError as ForbiddenError4 } from "@spfn/core/errors";
|
|
8995
9050
|
import { route as route5 } from "@spfn/core/route";
|
|
8996
9051
|
var listRoles = route5.get("/_auth/admin/roles").input({
|
|
8997
9052
|
query: Type.Object({
|
|
@@ -9059,6 +9114,14 @@ var updateUserRole = route5.patch("/_auth/admin/users/:userId/role").input({
|
|
|
9059
9114
|
})
|
|
9060
9115
|
}).use([authenticate, requireRole("superadmin")]).handler(async (c) => {
|
|
9061
9116
|
const { params, body } = await c.data();
|
|
9117
|
+
const auth = getAuth(c);
|
|
9118
|
+
if (params.userId === Number(auth.userId)) {
|
|
9119
|
+
throw new ForbiddenError4({ message: "Cannot change your own role" });
|
|
9120
|
+
}
|
|
9121
|
+
const targetRole = await getUserRole(params.userId);
|
|
9122
|
+
if (targetRole === "superadmin") {
|
|
9123
|
+
throw new ForbiddenError4({ message: "Cannot modify superadmin role" });
|
|
9124
|
+
}
|
|
9062
9125
|
await updateUserService(params.userId, { roleId: body.roleId });
|
|
9063
9126
|
return { userId: params.userId, roleId: body.roleId };
|
|
9064
9127
|
});
|
|
@@ -9498,6 +9561,8 @@ export {
|
|
|
9498
9561
|
hasRole,
|
|
9499
9562
|
hashPassword,
|
|
9500
9563
|
initializeAuth,
|
|
9564
|
+
invitationAcceptedEvent,
|
|
9565
|
+
invitationCreatedEvent,
|
|
9501
9566
|
invitationsRepository,
|
|
9502
9567
|
isGoogleOAuthEnabled,
|
|
9503
9568
|
isOAuthProviderEnabled,
|