feat: instance invites
This commit is contained in:
+33
-7
@@ -1,6 +1,6 @@
|
||||
import { drizzleAdapter } from "@better-auth/drizzle-adapter/relations-v2";
|
||||
import { db } from "../server/lib/db";
|
||||
import { APIError, createAuthMiddleware, getSessionFromCtx } from 'better-auth/api';
|
||||
import { APIError, createAuthMiddleware, getSessionFromCtx, isAPIError } from 'better-auth/api';
|
||||
import { betterAuth } from 'better-auth/minimal';
|
||||
import { createAccessControl } from 'better-auth/plugins/access';
|
||||
import { admin } from 'better-auth/plugins/admin';
|
||||
@@ -8,6 +8,7 @@ import { defaultStatements } from 'better-auth/plugins/admin/access';
|
||||
import { twoFactor } from 'better-auth/plugins/two-factor';
|
||||
import * as schema from '../drizzle/schema';
|
||||
import { getRegistrationMode } from '../server/utils/instance';
|
||||
import { claimInvite, INVITE_TOKEN_HEADER, releaseInvite } from '../server/utils/invites';
|
||||
|
||||
const MIN_PASSWORD_LENGTH = 8;
|
||||
|
||||
@@ -51,12 +52,26 @@ export const auth = betterAuth({
|
||||
hooks: {
|
||||
before: createAuthMiddleware(async (ctx) => {
|
||||
// Who may register is an instance setting admins change at runtime.
|
||||
// Invite links do not exist yet, so only open instances take sign ups.
|
||||
if (ctx.path === '/sign-up/email' && await getRegistrationMode() !== 'open') {
|
||||
throw new APIError('FORBIDDEN', {
|
||||
message: 'Registration is closed on this instance',
|
||||
code: 'REGISTRATION_CLOSED',
|
||||
});
|
||||
if (ctx.path === '/sign-up/email') {
|
||||
const mode = await getRegistrationMode();
|
||||
|
||||
if (mode === 'closed') {
|
||||
throw new APIError('FORBIDDEN', {
|
||||
message: 'Registration is closed on this instance',
|
||||
code: 'REGISTRATION_CLOSED',
|
||||
});
|
||||
}
|
||||
|
||||
if (mode === 'invite') {
|
||||
const token = ctx.headers?.get(INVITE_TOKEN_HEADER);
|
||||
|
||||
if (!token || !await claimInvite(token)) {
|
||||
throw new APIError('FORBIDDEN', {
|
||||
message: 'This invite link is not valid anymore',
|
||||
code: 'INVITE_INVALID',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// creating a user as an admin skips the sign up password rules
|
||||
@@ -89,6 +104,17 @@ export const auth = betterAuth({
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
// The invite was claimed before the account was made. When making it
|
||||
// then fails, say because the email is taken, the use is given back.
|
||||
after: createAuthMiddleware(async (ctx) => {
|
||||
if (ctx.path !== '/sign-up/email' || !isAPIError(ctx.context.returned)) return;
|
||||
|
||||
const token = ctx.headers?.get(INVITE_TOKEN_HEADER);
|
||||
if (token && await getRegistrationMode() === 'invite') {
|
||||
await releaseInvite(token);
|
||||
}
|
||||
}),
|
||||
},
|
||||
|
||||
plugins: [
|
||||
|
||||
Reference in New Issue
Block a user