Add PBandGraphOauth scaffold and auth UI
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { Hono } from 'hono';
|
||||
import { serveStatic } from 'hono/bun';
|
||||
import { cors } from 'hono/cors';
|
||||
import PocketBase from 'pocketbase';
|
||||
import { ConfidentialClientApplication } from '@azure/msal-node';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
// Load env from Estimator/.env
|
||||
const envPath = join(import.meta.dir, 'Estimator', '.env');
|
||||
try {
|
||||
const envContent = readFileSync(envPath, 'utf-8');
|
||||
envContent.split('\n').forEach(line => {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed && !trimmed.startsWith('#')) {
|
||||
const [key, ...valueParts] = trimmed.split('=');
|
||||
if (key && valueParts.length > 0) {
|
||||
process.env[key.trim()] = valueParts.join('=').trim();
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log('✓ Loaded env from Estimator/.env');
|
||||
} catch (e) {
|
||||
console.warn('⚠ Could not load Estimator/.env:', (e as Error).message);
|
||||
}
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
// Enable CORS
|
||||
app.use('/*', cors({
|
||||
origin: '*',
|
||||
credentials: true
|
||||
}));
|
||||
|
||||
// PocketBase client
|
||||
const pb = new PocketBase(process.env.PB_DB || 'https://pocketbase.ccllc.pro');
|
||||
|
||||
// Use user's PocketBase token
|
||||
function setUserPocketBaseAuth(token: string) {
|
||||
pb.authStore.save(token, null);
|
||||
}
|
||||
|
||||
// MSAL config for Graph token (client credentials)
|
||||
const msalConfig = {
|
||||
auth: {
|
||||
clientId: process.env.CLIENT_ID || '',
|
||||
authority: `https://login.microsoftonline.com/${process.env.TENANT_ID}`,
|
||||
clientSecret: process.env.CLIENT_SECRET || ''
|
||||
}
|
||||
};
|
||||
const cca = new ConfidentialClientApplication(msalConfig);
|
||||
|
||||
async function getGraphToken(): Promise<string> {
|
||||
const result = await cca.acquireTokenByClientCredential({
|
||||
scopes: ['https://graph.microsoft.com/.default']
|
||||
});
|
||||
if (!result || !result.accessToken) {
|
||||
throw new Error('Failed to acquire Graph token');
|
||||
}
|
||||
return result.accessToken;
|
||||
}
|
||||
|
||||
// Health check
|
||||
app.get('/health', (c) => {
|
||||
return c.json({ ok: true, pbDB: process.env.PB_DB });
|
||||
});
|
||||
|
||||
// Submit endpoint
|
||||
app.post('/api/submit', async (c) => {
|
||||
try {
|
||||
const body = await c.req.json();
|
||||
const pbToken = body.pbToken;
|
||||
|
||||
if (!pbToken) {
|
||||
return c.json({ success: false, message: 'Missing pbToken' }, 401);
|
||||
}
|
||||
|
||||
// Validate user token
|
||||
setUserPocketBaseAuth(pbToken);
|
||||
try {
|
||||
await pb.collection(process.env.PB_AUTH_COLLECTION || 'Users').authRefresh();
|
||||
} catch (e) {
|
||||
console.error('auth_validation_failed', { message: (e as Error)?.message });
|
||||
return c.json({ success: false, message: 'Invalid token' }, 401);
|
||||
}
|
||||
|
||||
// Store in PocketBase collection
|
||||
const record = await pb.collection(process.env.PB_COLLECTION || 'Job_Info_TestEnv').create({
|
||||
...body,
|
||||
submittedBy: pb.authStore.model?.email || 'unknown',
|
||||
submittedAt: new Date().toISOString()
|
||||
});
|
||||
|
||||
console.log('submission_success', { recordId: record.id });
|
||||
return c.json({ success: true, message: 'Feedback submitted successfully', recordId: record.id });
|
||||
} catch (err) {
|
||||
console.error('submit_error', { message: (err as Error)?.message });
|
||||
return c.json({ success: false, message: 'Internal error' }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// Serve static index.html
|
||||
app.get('/', async (c) => {
|
||||
const html = await Bun.file('index.html').text();
|
||||
return c.html(html);
|
||||
});
|
||||
|
||||
const PORT = Number(process.env.PORT || 7500);
|
||||
|
||||
console.log(`Idea & Feedback Form server running at http://localhost:${PORT}`);
|
||||
|
||||
export default {
|
||||
port: PORT,
|
||||
fetch: app.fetch,
|
||||
};
|
||||
Reference in New Issue
Block a user