Skip to content

Commit b78fca8

Browse files
committed
Merge branch 'master' of github.com:profullstack/generate-pdf-api
2 parents b0c2764 + 0680751 commit b78fca8

19 files changed

+1049
-74
lines changed

bin/setup-auth-integration.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/bash
2+
3+
# Script to set up auth integration between auth.users and public.users
4+
5+
echo "This script will set up proper integration between auth.users and public.users tables."
6+
echo "It will create a trigger to automatically create a public user when an auth user is created."
7+
echo ""
8+
echo "Press Ctrl+C to cancel or Enter to continue..."
9+
read
10+
11+
# Get the directory of the script
12+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
13+
14+
# Change to the project root directory
15+
cd "$SCRIPT_DIR/.."
16+
17+
# Check if supabase CLI is installed
18+
if ! command -v supabase &> /dev/null; then
19+
echo "Error: Supabase CLI is not installed. Please install it first."
20+
echo "See: https://supabase.com/docs/guides/cli"
21+
exit 1
22+
fi
23+
24+
# Apply the migration using the existing supabase-db.sh script
25+
./bin/supabase-db.sh
26+
27+
echo "Migration applied successfully!"
28+
echo "Auth integration has been set up."
29+
echo ""
30+
echo "Next steps:"
31+
echo "1. Register a new user through the application"
32+
echo "2. The user will be created in both auth.users and public.users tables"
33+
echo "3. JWT authentication should now work correctly"
34+
35+
exit 0

public/js/api-client.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,21 @@ export class ApiClient {
162162
*/
163163
static async createSubscription(email, plan, coin) {
164164
try {
165+
// Get JWT token from localStorage
166+
const jwtToken = localStorage.getItem('jwt_token');
167+
168+
const headers = {
169+
'Content-Type': 'application/json'
170+
};
171+
172+
// Add Authorization header with JWT token if available
173+
if (jwtToken) {
174+
headers['Authorization'] = `Bearer ${jwtToken}`;
175+
}
176+
165177
const response = await fetch(`${this.baseUrl}/subscription`, {
166178
method: 'POST',
167-
headers: {
168-
'Content-Type': 'application/json'
169-
},
179+
headers,
170180
body: JSON.stringify({
171181
email,
172182
plan,
@@ -192,9 +202,21 @@ export class ApiClient {
192202
* @returns {Promise<Object>} - Subscription status
193203
*/
194204
static async checkSubscriptionStatus(email) {
195-
return this.fetchJsonResponse(`${this.baseUrl}/subscription-status`, {
196-
email
205+
// This is a public endpoint that doesn't require authentication
206+
const response = await fetch(`${this.baseUrl}/subscription-status`, {
207+
method: 'POST',
208+
headers: {
209+
'Content-Type': 'application/json',
210+
},
211+
body: JSON.stringify({ email })
197212
});
213+
214+
if (!response.ok) {
215+
const errorData = await response.json();
216+
throw new Error(errorData.error || response.statusText);
217+
}
218+
219+
return await response.json();
198220
}
199221

200222
/**

public/js/auth-ui.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ document.addEventListener('DOMContentLoaded', () => {
55
});
66

77
function updateNavbar() {
8-
const apiKey = localStorage.getItem('api_key');
9-
const username = localStorage.getItem('username') || apiKey;
10-
const isLoggedIn = !!apiKey;
8+
const jwtToken = localStorage.getItem('jwt_token');
9+
const username = localStorage.getItem('username');
10+
const isLoggedIn = !!jwtToken;
1111

1212
const navLinks = document.querySelector('.nav-links');
1313
if (!navLinks) return;
@@ -85,13 +85,16 @@ function logout() {
8585
// Clear authentication data
8686
localStorage.removeItem('username');
8787
localStorage.removeItem('jwt_token');
88+
localStorage.removeItem('api_key'); // Remove any legacy API key
89+
localStorage.removeItem('user'); // Remove user object
90+
localStorage.removeItem('subscription_data'); // Remove subscription data
8891

8992
// Update UI
9093
updateNavbar();
9194

9295
// Redirect to home page if on a protected page
9396
const currentPath = window.location.pathname;
94-
const protectedPages = ['/api-keys.html', '/settings.html'];
97+
const protectedPages = ['/api-keys.html', '/settings.html', '/dashboard.html'];
9598

9699
if (protectedPages.includes(currentPath)) {
97100
window.location.href = '/';

public/js/components/subscription-form.js

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -419,14 +419,17 @@ export class SubscriptionForm extends BaseComponent {
419419
this._error = null;
420420
this.render();
421421

422+
// Use subscription id if available, otherwise use email
423+
const requestBody = this._subscription ?
424+
{ id: this._subscription.id } :
425+
{ email: this._email };
426+
422427
const response = await fetch('/api/1/subscription-status', {
423428
method: 'POST',
424429
headers: {
425430
'Content-Type': 'application/json'
426431
},
427-
body: JSON.stringify({
428-
email: this._email
429-
})
432+
body: JSON.stringify(requestBody)
430433
});
431434

432435
if (!response.ok) {
@@ -436,7 +439,7 @@ export class SubscriptionForm extends BaseComponent {
436439

437440
const data = await response.json();
438441

439-
if (data.has_subscription) {
442+
if (data.has_subscription || data.payment_verified) {
440443
// Subscription is active, show success message
441444
this._subscription = data.subscription;
442445
this._paymentInfo = null;
@@ -445,6 +448,36 @@ export class SubscriptionForm extends BaseComponent {
445448
// Show success message
446449
this.render();
447450
this.showSuccessMessage();
451+
452+
// Generate fresh JWT token and redirect after 5 seconds
453+
if (data.payment_verified) {
454+
console.log('Payment verified, will redirect to API keys page in 5 seconds');
455+
this._showRedirectCountdown();
456+
457+
try {
458+
// Request a fresh JWT token
459+
const tokenResponse = await fetch('/api/1/auth/refresh-token', {
460+
method: 'POST',
461+
headers: {
462+
'Content-Type': 'application/json'
463+
},
464+
body: JSON.stringify({
465+
email: this._subscription.email
466+
})
467+
});
468+
469+
if (tokenResponse.ok) {
470+
console.log('JWT token refreshed successfully');
471+
}
472+
} catch (tokenError) {
473+
console.error('Error refreshing JWT token:', tokenError);
474+
}
475+
476+
// Redirect after 5 seconds
477+
setTimeout(() => {
478+
window.location.href = '/views/api-keys.html';
479+
}, 5000);
480+
}
448481
} else {
449482
// Subscription is not active yet
450483
this._loading = false;
@@ -475,6 +508,7 @@ export class SubscriptionForm extends BaseComponent {
475508
<p><strong>Plan:</strong> ${this._subscription.plan === 'monthly' ? 'Monthly' : 'Yearly'}</p>
476509
<p><strong>Expiration Date:</strong> ${new Date(this._subscription.expiration_date).toLocaleDateString()}</p>
477510
<p>You can view your API usage and manage your subscription in your account dashboard.</p>
511+
<p id="redirect-message" style="margin-top: 15px; font-weight: bold;"></p>
478512
</div>
479513
</div>
480514
`);
@@ -500,6 +534,25 @@ export class SubscriptionForm extends BaseComponent {
500534
this.render();
501535
}
502536

537+
/**
538+
* Display redirect countdown message
539+
* @private
540+
*/
541+
_showRedirectCountdown() {
542+
let seconds = 5;
543+
const updateCountdown = () => {
544+
const redirectMessage = this.$('#redirect-message');
545+
if (redirectMessage) {
546+
redirectMessage.textContent = `Redirecting to API keys page in ${seconds} seconds...`;
547+
if (seconds > 0) {
548+
seconds--;
549+
setTimeout(updateCountdown, 1000);
550+
}
551+
}
552+
};
553+
updateCountdown();
554+
}
555+
503556
/**
504557
* Generate QR code for payment
505558
* @private

0 commit comments

Comments
 (0)