feat: migrate auth from supabase to better auth (#596)

* feat: add README for @cio/db package and remove existingAccounts.json

* load session, load profile and organization, add create profile hook

* chore: cache session request

The trick was passing all the cookies to the backend. Previously I was only passing the better-auth.session_token and not better-auth.session_data. Read about the difference here https://www.better-auth.com/docs/concepts/cookies#custom-cookies

* feat: login, logout, onboarding, verify email, reset password.

* feat: complete change email and email verification

* feat: standardise how we make rpc calls and create org endpoints

* fix ui errors

* fix: handle potential undefined customerId and standardize avatar URL property

* refactor: standardize custom domain handling and update telegram chat ID references

* chore: add tailwind prefix to @cio/ui

this fixed the media query issues because  @cio/ui classes were overriding this dashboard tailwind build

* chore: clean up org sidebar

* chore: persist mode state

* feat: implement order breadcrumbs

* chore: upgrade to better auth 1.4

* chore: address common auth flow bugs and setup app for others to setup locally.
This commit is contained in:
Rotimi Best
2025-11-24 01:00:50 +01:00
committed by GitHub
parent 24741644d6
commit a3924100dd
567 changed files with 22364 additions and 13437 deletions
+42 -6
View File
@@ -1,12 +1,18 @@
import 'dotenv/config';
import { Hono } from 'hono';
import { API_SERVER_URL, TRUSTED_ORIGINS } from '@api/constants';
import { Hono } from '@api/utils/hono';
import { accountRouter } from '@api/routes/account';
import { auth } from '@cio/db/auth';
import { cors } from 'hono/cors';
import { courseRouter } from '@api/routes/course/course';
import { courseRouter } from '@api/routes/course';
import { logger } from 'hono/logger';
import { mailRouter } from '@api/routes/mail';
import { onboardingRouter } from '@api/routes/onboarding';
import { organizationRouter } from '@api/routes/organization';
import { prettyJSON } from 'hono/pretty-json';
import { rateLimiterMiddleware } from '@api/middlewares/rate-limiter';
import rateLimiter from '@api/middlewares/rate-limiter';
import { secureHeaders } from 'hono/secure-headers';
// Create Hono app with chaining for RPC support
@@ -18,7 +24,7 @@ export const app = new Hono()
.use(
'*',
cors({
origin: '*',
origin: TRUSTED_ORIGINS,
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization'],
exposeHeaders: ['Content-Length', 'X-Kuma-Revision'],
@@ -26,16 +32,46 @@ export const app = new Hono()
credentials: true
})
)
.use('*', rateLimiterMiddleware)
.use('*', rateLimiter)
.use('*', async (c, next) => {
const session = await auth.api.getSession({ headers: c.req.raw.headers });
if (!session) {
c.set('user', null);
c.set('session', null);
await next();
return;
}
c.set('user', session.user);
c.set('session', session.session);
await next();
})
// Routes
.get('/', (c) =>
c.json({
message: '"Welcome to Classroomio.com API - docs are at https://api.classroomio.com/docs"'
message: `"Welcome to Classroomio.com API - docs are at ${API_SERVER_URL}/docs"`
})
)
.on(['POST', 'GET'], '/api/auth/*', (c) => auth.handler(c.req.raw))
.get('/session', async (c) => {
const session = c.get('session');
const user = c.get('user');
if (!user) return c.body(null, 401);
return c.json({
session,
user
});
})
.route('/onboarding', onboardingRouter)
.route('/account', accountRouter)
.route('/course', courseRouter)
.route('/mail', mailRouter)
.route('/organization', organizationRouter)
// Error handling
.onError((err, c) => {