better-auth-studio 1.0.79-beta.35 → 1.0.79-beta.36
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/cli.js +0 -0
- package/dist/public/assets/{main-R1O9iElM.css → main-BgI41EAt.css} +1 -1
- package/dist/public/assets/main-BxLtFscV.js +1155 -0
- package/dist/public/index.html +2 -2
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +322 -0
- package/dist/routes.js.map +1 -1
- package/package.json +30 -32
- package/public/assets/{main-R1O9iElM.css → main-BgI41EAt.css} +1 -1
- package/public/assets/main-BxLtFscV.js +1155 -0
- package/public/index.html +2 -2
- package/scripts/postinstall.js +0 -2
- package/dist/public/assets/main-DAv-RHMo.js +0 -1155
- package/public/assets/main-DAv-RHMo.js +0 -1155
package/dist/public/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/png" href="/logo.png" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Better Auth Studio</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/main-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/main-
|
|
8
|
+
<script type="module" crossorigin src="/assets/main-BxLtFscV.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/main-BgI41EAt.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAeA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAU9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AA0GnE,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAqLhG;AAeD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,gBAAgB,CAAC,EAAE,GAAG,EACtB,oBAAoB,CAAC,EAAE,GAAG,EAC1B,YAAY,CAAC,EAAE,kBAAkB,EACjC,YAAY,CAAC,EAAE,GAAG,GACjB,MAAM,
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAeA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAU9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AA0GnE,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAqLhG;AAeD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,gBAAgB,CAAC,EAAE,GAAG,EACtB,oBAAoB,CAAC,EAAE,GAAG,EAC1B,YAAY,CAAC,EAAE,kBAAkB,EACjC,YAAY,CAAC,EAAE,GAAG,GACjB,MAAM,CAkxMR;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,EAAE,GAAG,CAAC;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,GAAG,CAAC;IACV,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;CAChE,CAAC,CA+FD"}
|
package/dist/routes.js
CHANGED
|
@@ -320,6 +320,10 @@ export function createRoutes(authConfig, configPath, geoDbPath, preloadedAdapter
|
|
|
320
320
|
// For self-hosted studio, wrap the preloaded adapter to match expected interface
|
|
321
321
|
return {
|
|
322
322
|
...preloadedAdapter,
|
|
323
|
+
findUnique: preloadedAdapter.findUnique?.bind(preloadedAdapter),
|
|
324
|
+
findOne: preloadedAdapter.findOne?.bind(preloadedAdapter) ||
|
|
325
|
+
preloadedAdapter.findUnique?.bind(preloadedAdapter),
|
|
326
|
+
findFirst: preloadedAdapter.findFirst?.bind(preloadedAdapter),
|
|
323
327
|
findMany: preloadedAdapter.findMany?.bind(preloadedAdapter),
|
|
324
328
|
create: preloadedAdapter.create?.bind(preloadedAdapter),
|
|
325
329
|
update: preloadedAdapter.update?.bind(preloadedAdapter),
|
|
@@ -2731,6 +2735,238 @@ export function createRoutes(authConfig, configPath, geoDbPath, preloadedAdapter
|
|
|
2731
2735
|
res.status(500).json({ error: 'Failed to resend invitation' });
|
|
2732
2736
|
}
|
|
2733
2737
|
});
|
|
2738
|
+
router.get('/api/users/:userId/invitations', async (req, res) => {
|
|
2739
|
+
try {
|
|
2740
|
+
const { userId } = req.params;
|
|
2741
|
+
const adapter = await getAuthAdapterWithConfig();
|
|
2742
|
+
if (!adapter) {
|
|
2743
|
+
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
2744
|
+
}
|
|
2745
|
+
let user;
|
|
2746
|
+
try {
|
|
2747
|
+
user = await adapter.findOne({
|
|
2748
|
+
model: 'user',
|
|
2749
|
+
where: [{ field: 'id', value: userId }],
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2752
|
+
catch (error) {
|
|
2753
|
+
console.error('Error fetching user:', error);
|
|
2754
|
+
return res.status(500).json({
|
|
2755
|
+
error: 'Failed to fetch user',
|
|
2756
|
+
details: error?.message || String(error),
|
|
2757
|
+
});
|
|
2758
|
+
}
|
|
2759
|
+
if (!user || !user.email) {
|
|
2760
|
+
return res.json({ success: true, invitations: [] });
|
|
2761
|
+
}
|
|
2762
|
+
if (typeof adapter.findMany !== 'function') {
|
|
2763
|
+
return res.json({ success: true, invitations: [] });
|
|
2764
|
+
}
|
|
2765
|
+
let invitations;
|
|
2766
|
+
try {
|
|
2767
|
+
invitations = await adapter.findMany({
|
|
2768
|
+
model: 'invitation',
|
|
2769
|
+
where: [{ field: 'email', value: user.email }],
|
|
2770
|
+
});
|
|
2771
|
+
}
|
|
2772
|
+
catch (error) {
|
|
2773
|
+
console.error('Error fetching invitations:', error);
|
|
2774
|
+
return res.json({ success: true, invitations: [] });
|
|
2775
|
+
}
|
|
2776
|
+
if (!invitations || invitations.length === 0) {
|
|
2777
|
+
return res.json({ success: true, invitations: [] });
|
|
2778
|
+
}
|
|
2779
|
+
const transformedInvitations = await Promise.all(invitations.map(async (invitation) => {
|
|
2780
|
+
let organizationName = 'Unknown';
|
|
2781
|
+
let teamName;
|
|
2782
|
+
try {
|
|
2783
|
+
if (invitation.organizationId &&
|
|
2784
|
+
(typeof adapter.findOne === 'function' || typeof adapter.findUnique === 'function')) {
|
|
2785
|
+
try {
|
|
2786
|
+
const findMethod = adapter.findOne || adapter.findUnique;
|
|
2787
|
+
const org = await findMethod({
|
|
2788
|
+
model: 'organization',
|
|
2789
|
+
where: [{ field: 'id', value: invitation.organizationId }],
|
|
2790
|
+
});
|
|
2791
|
+
organizationName = org?.name || 'Unknown';
|
|
2792
|
+
}
|
|
2793
|
+
catch (_orgError) {
|
|
2794
|
+
// Ignore org fetch errors
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
if (invitation.teamId &&
|
|
2798
|
+
(typeof adapter.findOne === 'function' || typeof adapter.findUnique === 'function')) {
|
|
2799
|
+
try {
|
|
2800
|
+
const findMethod = adapter.findOne || adapter.findUnique;
|
|
2801
|
+
const team = await findMethod({
|
|
2802
|
+
model: 'team',
|
|
2803
|
+
where: [{ field: 'id', value: invitation.teamId }],
|
|
2804
|
+
});
|
|
2805
|
+
teamName = team?.name;
|
|
2806
|
+
}
|
|
2807
|
+
catch (_teamError) { }
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
catch (_error) { }
|
|
2811
|
+
return {
|
|
2812
|
+
id: invitation.id,
|
|
2813
|
+
email: invitation.email,
|
|
2814
|
+
role: invitation.role || 'member',
|
|
2815
|
+
status: invitation.status || 'pending',
|
|
2816
|
+
organizationId: invitation.organizationId,
|
|
2817
|
+
organizationName,
|
|
2818
|
+
teamId: invitation.teamId,
|
|
2819
|
+
teamName,
|
|
2820
|
+
inviterId: invitation.inviterId,
|
|
2821
|
+
expiresAt: invitation.expiresAt,
|
|
2822
|
+
createdAt: invitation.createdAt,
|
|
2823
|
+
};
|
|
2824
|
+
}));
|
|
2825
|
+
res.json({ success: true, invitations: transformedInvitations });
|
|
2826
|
+
}
|
|
2827
|
+
catch (error) {
|
|
2828
|
+
console.error('Error in /api/users/:userId/invitations:', error);
|
|
2829
|
+
res.status(500).json({
|
|
2830
|
+
error: 'Failed to fetch invitations',
|
|
2831
|
+
details: error?.message || String(error),
|
|
2832
|
+
});
|
|
2833
|
+
}
|
|
2834
|
+
});
|
|
2835
|
+
router.post('/api/invitations/:id/accept', async (req, res) => {
|
|
2836
|
+
try {
|
|
2837
|
+
const { id } = req.params;
|
|
2838
|
+
const { userId } = req.body;
|
|
2839
|
+
const adapter = await getAuthAdapterWithConfig();
|
|
2840
|
+
if (!adapter) {
|
|
2841
|
+
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
2842
|
+
}
|
|
2843
|
+
if (!userId) {
|
|
2844
|
+
return res.status(400).json({ error: 'User ID is required' });
|
|
2845
|
+
}
|
|
2846
|
+
const invitation = await adapter.findOne({
|
|
2847
|
+
model: 'invitation',
|
|
2848
|
+
where: [{ field: 'id', value: id }],
|
|
2849
|
+
});
|
|
2850
|
+
if (!invitation) {
|
|
2851
|
+
return res.status(404).json({ error: 'Invitation not found' });
|
|
2852
|
+
}
|
|
2853
|
+
if (invitation.status !== 'pending') {
|
|
2854
|
+
return res.status(400).json({ error: 'Invitation is not pending' });
|
|
2855
|
+
}
|
|
2856
|
+
await adapter.update({
|
|
2857
|
+
model: 'invitation',
|
|
2858
|
+
where: [{ field: 'id', value: id }],
|
|
2859
|
+
update: {
|
|
2860
|
+
status: 'accepted',
|
|
2861
|
+
updatedAt: new Date().toISOString(),
|
|
2862
|
+
},
|
|
2863
|
+
});
|
|
2864
|
+
if (invitation.organizationId) {
|
|
2865
|
+
try {
|
|
2866
|
+
// Check if member already exists
|
|
2867
|
+
let existingMember = null;
|
|
2868
|
+
if (typeof adapter.findFirst === 'function') {
|
|
2869
|
+
existingMember = await adapter.findFirst({
|
|
2870
|
+
model: 'member',
|
|
2871
|
+
where: [
|
|
2872
|
+
{ field: 'organizationId', value: invitation.organizationId },
|
|
2873
|
+
{ field: 'userId', value: userId },
|
|
2874
|
+
],
|
|
2875
|
+
});
|
|
2876
|
+
}
|
|
2877
|
+
else if (typeof adapter.findMany === 'function') {
|
|
2878
|
+
const members = await adapter.findMany({
|
|
2879
|
+
model: 'member',
|
|
2880
|
+
where: [
|
|
2881
|
+
{ field: 'organizationId', value: invitation.organizationId },
|
|
2882
|
+
{ field: 'userId', value: userId },
|
|
2883
|
+
],
|
|
2884
|
+
});
|
|
2885
|
+
existingMember = members && members.length > 0 ? members[0] : null;
|
|
2886
|
+
}
|
|
2887
|
+
if (!existingMember) {
|
|
2888
|
+
await adapter.create({
|
|
2889
|
+
model: 'member',
|
|
2890
|
+
data: {
|
|
2891
|
+
organizationId: invitation.organizationId,
|
|
2892
|
+
userId: userId,
|
|
2893
|
+
role: invitation.role || 'member',
|
|
2894
|
+
createdAt: new Date().toISOString(),
|
|
2895
|
+
},
|
|
2896
|
+
});
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
catch (error) {
|
|
2900
|
+
console.error('Error creating member:', error);
|
|
2901
|
+
// Ignore errors creating membership
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
if (invitation.teamId) {
|
|
2905
|
+
try {
|
|
2906
|
+
let existingMember = null;
|
|
2907
|
+
if (typeof adapter.findFirst === 'function') {
|
|
2908
|
+
existingMember = await adapter.findFirst({
|
|
2909
|
+
model: 'teamMember',
|
|
2910
|
+
where: [
|
|
2911
|
+
{ field: 'teamId', value: invitation.teamId },
|
|
2912
|
+
{ field: 'userId', value: userId },
|
|
2913
|
+
],
|
|
2914
|
+
});
|
|
2915
|
+
}
|
|
2916
|
+
else if (typeof adapter.findMany === 'function') {
|
|
2917
|
+
const members = await adapter.findMany({
|
|
2918
|
+
model: 'teamMember',
|
|
2919
|
+
where: [
|
|
2920
|
+
{ field: 'teamId', value: invitation.teamId },
|
|
2921
|
+
{ field: 'userId', value: userId },
|
|
2922
|
+
],
|
|
2923
|
+
});
|
|
2924
|
+
existingMember = members && members.length > 0 ? members[0] : null;
|
|
2925
|
+
}
|
|
2926
|
+
if (!existingMember) {
|
|
2927
|
+
await adapter.create({
|
|
2928
|
+
model: 'teamMember',
|
|
2929
|
+
data: {
|
|
2930
|
+
teamId: invitation.teamId,
|
|
2931
|
+
userId: userId,
|
|
2932
|
+
createdAt: new Date().toISOString(),
|
|
2933
|
+
},
|
|
2934
|
+
});
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
catch (error) {
|
|
2938
|
+
console.error('Error creating team member:', error);
|
|
2939
|
+
// Ignore errors creating team membership
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
res.json({ success: true });
|
|
2943
|
+
}
|
|
2944
|
+
catch (error) {
|
|
2945
|
+
console.error('Failed to accept invitation:', error);
|
|
2946
|
+
res.status(500).json({ error: 'Failed to accept invitation' });
|
|
2947
|
+
}
|
|
2948
|
+
});
|
|
2949
|
+
router.post('/api/invitations/:id/reject', async (req, res) => {
|
|
2950
|
+
try {
|
|
2951
|
+
const { id } = req.params;
|
|
2952
|
+
const adapter = await getAuthAdapterWithConfig();
|
|
2953
|
+
if (!adapter) {
|
|
2954
|
+
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
2955
|
+
}
|
|
2956
|
+
await adapter.update({
|
|
2957
|
+
model: 'invitation',
|
|
2958
|
+
where: [{ field: 'id', value: id }],
|
|
2959
|
+
update: {
|
|
2960
|
+
status: 'rejected',
|
|
2961
|
+
updatedAt: new Date().toISOString(),
|
|
2962
|
+
},
|
|
2963
|
+
});
|
|
2964
|
+
res.json({ success: true });
|
|
2965
|
+
}
|
|
2966
|
+
catch (_error) {
|
|
2967
|
+
res.status(500).json({ error: 'Failed to reject invitation' });
|
|
2968
|
+
}
|
|
2969
|
+
});
|
|
2734
2970
|
router.delete('/api/invitations/:id', async (req, res) => {
|
|
2735
2971
|
try {
|
|
2736
2972
|
const { id } = req.params;
|
|
@@ -3661,6 +3897,92 @@ export function createRoutes(authConfig, configPath, geoDbPath, preloadedAdapter
|
|
|
3661
3897
|
res.status(500).json({ success: false, error: 'Failed to fetch OAuth providers' });
|
|
3662
3898
|
}
|
|
3663
3899
|
});
|
|
3900
|
+
router.get('/api/tools/oauth/credentials', async (req, res) => {
|
|
3901
|
+
try {
|
|
3902
|
+
const { provider, origin } = req.query;
|
|
3903
|
+
if (!provider || typeof provider !== 'string') {
|
|
3904
|
+
return res.status(400).json({
|
|
3905
|
+
success: false,
|
|
3906
|
+
error: 'Provider is required',
|
|
3907
|
+
});
|
|
3908
|
+
}
|
|
3909
|
+
if (!origin || typeof origin !== 'string') {
|
|
3910
|
+
return res.status(400).json({
|
|
3911
|
+
success: false,
|
|
3912
|
+
error: 'Origin is required',
|
|
3913
|
+
});
|
|
3914
|
+
}
|
|
3915
|
+
// TODO: Import getOAuthCredentials at the top of this file:
|
|
3916
|
+
// import { getOAuthCredentials } from './path/to/your/oauth-config';
|
|
3917
|
+
// For now, we'll access it from a function that should be provided
|
|
3918
|
+
// This assumes getOAuthCredentials is available in the scope
|
|
3919
|
+
// You need to import it: import { getOAuthCredentials } from './your-oauth-config-file';
|
|
3920
|
+
// Placeholder - replace this with actual import at top of file
|
|
3921
|
+
const getOAuthCredentials = global.getOAuthCredentials;
|
|
3922
|
+
if (typeof getOAuthCredentials !== 'function') {
|
|
3923
|
+
return res.status(500).json({
|
|
3924
|
+
success: false,
|
|
3925
|
+
error: 'OAuth credentials function not configured. Please import getOAuthCredentials function.',
|
|
3926
|
+
});
|
|
3927
|
+
}
|
|
3928
|
+
const credentialsResult = getOAuthCredentials(provider, origin);
|
|
3929
|
+
// Handle null return (provider not found)
|
|
3930
|
+
if (credentialsResult === null) {
|
|
3931
|
+
return res.status(404).json({
|
|
3932
|
+
success: false,
|
|
3933
|
+
error: 'No credential found',
|
|
3934
|
+
});
|
|
3935
|
+
}
|
|
3936
|
+
// Handle error cases with proper messages as requested
|
|
3937
|
+
if (credentialsResult.error) {
|
|
3938
|
+
if (credentialsResult.error === 'NO_CREDENTIALS_FOUND') {
|
|
3939
|
+
return res.status(404).json({
|
|
3940
|
+
success: false,
|
|
3941
|
+
error: 'No credential found',
|
|
3942
|
+
});
|
|
3943
|
+
}
|
|
3944
|
+
else if (credentialsResult.error === 'INVALID_ORIGIN') {
|
|
3945
|
+
return res.status(400).json({
|
|
3946
|
+
success: false,
|
|
3947
|
+
error: 'Invalid origin. OAuth credentials are only available for localhost origins.',
|
|
3948
|
+
});
|
|
3949
|
+
}
|
|
3950
|
+
else {
|
|
3951
|
+
return res.status(400).json({
|
|
3952
|
+
success: false,
|
|
3953
|
+
error: credentialsResult.error || 'Failed to get OAuth credentials',
|
|
3954
|
+
});
|
|
3955
|
+
}
|
|
3956
|
+
}
|
|
3957
|
+
// Check if result exists and has required fields
|
|
3958
|
+
if (!credentialsResult.result) {
|
|
3959
|
+
return res.status(404).json({
|
|
3960
|
+
success: false,
|
|
3961
|
+
error: 'No credential found',
|
|
3962
|
+
});
|
|
3963
|
+
}
|
|
3964
|
+
const { clientId, clientSecret } = credentialsResult.result;
|
|
3965
|
+
if (!clientId || !clientSecret) {
|
|
3966
|
+
return res.status(404).json({
|
|
3967
|
+
success: false,
|
|
3968
|
+
error: 'No credential found',
|
|
3969
|
+
});
|
|
3970
|
+
}
|
|
3971
|
+
res.json({
|
|
3972
|
+
success: true,
|
|
3973
|
+
clientId,
|
|
3974
|
+
clientSecret,
|
|
3975
|
+
});
|
|
3976
|
+
}
|
|
3977
|
+
catch (error) {
|
|
3978
|
+
console.error('Failed to fetch OAuth credentials:', error);
|
|
3979
|
+
res.status(500).json({
|
|
3980
|
+
success: false,
|
|
3981
|
+
error: 'Failed to fetch OAuth credentials',
|
|
3982
|
+
details: error instanceof Error ? error.message : String(error),
|
|
3983
|
+
});
|
|
3984
|
+
}
|
|
3985
|
+
});
|
|
3664
3986
|
router.post('/api/tools/oauth/test', async (req, res) => {
|
|
3665
3987
|
try {
|
|
3666
3988
|
const { provider } = req.body;
|