Made great progress on monorepo & auth for next. Very happy with work!
This commit is contained in:
File diff suppressed because one or more lines are too long
4
packages/backend/convex/_generated/api.d.ts
vendored
4
packages/backend/convex/_generated/api.d.ts
vendored
@@ -9,9 +9,11 @@
|
||||
*/
|
||||
|
||||
import type * as auth from "../auth.js";
|
||||
import type * as crons from "../crons.js";
|
||||
import type * as custom_auth_index from "../custom/auth/index.js";
|
||||
import type * as custom_auth_providers_password from "../custom/auth/providers/password.js";
|
||||
import type * as custom_auth_providers_usesend from "../custom/auth/providers/usesend.js";
|
||||
import type * as files from "../files.js";
|
||||
import type * as http from "../http.js";
|
||||
import type * as utils from "../utils.js";
|
||||
|
||||
@@ -31,9 +33,11 @@ import type {
|
||||
*/
|
||||
declare const fullApi: ApiFromModules<{
|
||||
auth: typeof auth;
|
||||
crons: typeof crons;
|
||||
"custom/auth/index": typeof custom_auth_index;
|
||||
"custom/auth/providers/password": typeof custom_auth_providers_password;
|
||||
"custom/auth/providers/usesend": typeof custom_auth_providers_usesend;
|
||||
files: typeof files;
|
||||
http: typeof http;
|
||||
utils: typeof utils;
|
||||
}>;
|
||||
|
||||
@@ -14,10 +14,7 @@ import { action, mutation, query } from './_generated/server';
|
||||
import { Password, validatePassword } from './custom/auth';
|
||||
|
||||
export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
|
||||
providers: [
|
||||
Authentik({ allowDangerousEmailAccountLinking: true }),
|
||||
Password,
|
||||
],
|
||||
providers: [Authentik({ allowDangerousEmailAccountLinking: true }), Password],
|
||||
});
|
||||
|
||||
const getUserById = async (
|
||||
@@ -39,9 +36,8 @@ const isSignedIn = async (ctx: QueryCtx): Promise<Doc<'users'> | null> => {
|
||||
export const getUser = query({
|
||||
args: { userId: v.optional(v.id('users')) },
|
||||
handler: async (ctx, args) => {
|
||||
const user = await isSignedIn(ctx);
|
||||
const userId = args.userId ?? user?._id;
|
||||
if (!userId) throw new ConvexError('Not authenticated or no ID provided.');
|
||||
const userId = args.userId ?? (await getAuthUserId(ctx));
|
||||
if (!userId) return null;
|
||||
return getUserById(ctx, userId);
|
||||
},
|
||||
});
|
||||
|
||||
23
packages/backend/convex/crons.ts
Normal file
23
packages/backend/convex/crons.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { cronJobs } from 'convex/server';
|
||||
|
||||
import { api } from './_generated/api';
|
||||
|
||||
// Cron order: Minute Hour DayOfMonth Month DayOfWeek
|
||||
const crons = cronJobs();
|
||||
/* Example cron jobs
|
||||
crons.cron(
|
||||
// Run at 7:00 AM CST / 8:00 AM CDT
|
||||
// Only on weekdays
|
||||
'Schedule Automatic Lunches',
|
||||
'0 13 * * 1-5',
|
||||
api.statuses.automaticLunch,
|
||||
);
|
||||
crons.cron(
|
||||
// Run at 4:00 PM CST / 5:00 PM CDT
|
||||
// Only on weekdays
|
||||
'End of shift (weekdays 5pm CT)',
|
||||
'0 22 * * 1-5',
|
||||
api.statuses.endOfShiftUpdate,
|
||||
);
|
||||
*/
|
||||
export default crons;
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Password as DefaultPassword } from '@convex-dev/auth/providers/Password';
|
||||
import { ConvexError } from 'convex/values';
|
||||
|
||||
import { UseSendOTP, UseSendOTPPasswordReset } from '..';
|
||||
import { DataModel } from '../../../_generated/dataModel';
|
||||
|
||||
|
||||
18
packages/backend/convex/files.ts
Normal file
18
packages/backend/convex/files.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { getAuthUserId } from '@convex-dev/auth/server';
|
||||
import { ConvexError, v } from 'convex/values';
|
||||
|
||||
import { mutation, query } from './_generated/server';
|
||||
|
||||
export const generateUploadUrl = mutation(async (ctx) => {
|
||||
const userId = await getAuthUserId(ctx);
|
||||
if (!userId) throw new ConvexError('Not authenticated.');
|
||||
return await ctx.storage.generateUploadUrl();
|
||||
});
|
||||
|
||||
export const getImageUrl = query({
|
||||
args: { storageId: v.id('_storage') },
|
||||
handler: async (ctx, { storageId }) => {
|
||||
const url = await ctx.storage.getUrl(storageId);
|
||||
return url ?? null;
|
||||
},
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import { authTables } from '@convex-dev/auth/server';
|
||||
import { defineSchema, defineTable } from 'convex/server';
|
||||
import { v } from 'convex/values';
|
||||
import { authTables } from '@convex-dev/auth/server';
|
||||
|
||||
const applicationTables = {
|
||||
// Users contains name image & email.
|
||||
@@ -10,8 +10,7 @@ const applicationTables = {
|
||||
profiles: defineTable({
|
||||
userId: v.id('users'),
|
||||
theme_preference: v.optional(v.string()),
|
||||
})
|
||||
.index('userId', ['userId'])
|
||||
}).index('userId', ['userId']),
|
||||
};
|
||||
|
||||
export default defineSchema({
|
||||
@@ -29,8 +28,8 @@ export default defineSchema({
|
||||
phoneVerificationTime: v.optional(v.number()),
|
||||
isAnonymous: v.optional(v.boolean()),
|
||||
})
|
||||
.index("email", ["email"])
|
||||
.index('email', ['email'])
|
||||
.index('name', ['name'])
|
||||
.index("phone", ["phone"]),
|
||||
.index('phone', ['phone']),
|
||||
...applicationTables,
|
||||
});
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
"author": "Gib",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
"./types" : "./types/index.ts"
|
||||
"./convex": "./convex/",
|
||||
"./convex/*": "./convex/*",
|
||||
"./types": "./types/index.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "bun with-env convex dev",
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
#!/usr/bin/env node
|
||||
import { exportJWK, exportPKCS8, generateKeyPair } from 'jose';
|
||||
|
||||
import { exportJWK, exportPKCS8, generateKeyPair } from "jose";
|
||||
|
||||
const keys = await generateKeyPair("RS256", {
|
||||
const keys = await generateKeyPair('RS256', {
|
||||
extractable: true,
|
||||
});
|
||||
const privateKey = await exportPKCS8(keys.privateKey);
|
||||
const publicKey = await exportJWK(keys.publicKey);
|
||||
const jwks = JSON.stringify({ keys: [{ use: "sig", ...publicKey }] });
|
||||
const jwks = JSON.stringify({ keys: [{ use: 'sig', ...publicKey }] });
|
||||
|
||||
process.stdout.write(
|
||||
`JWT_PRIVATE_KEY="${privateKey.trimEnd().replace(/\n/g, " ")}"`,
|
||||
`JWT_PRIVATE_KEY="${privateKey.trimEnd().replace(/\n/g, ' ')}"`,
|
||||
);
|
||||
process.stdout.write("\n");
|
||||
process.stdout.write('\n');
|
||||
process.stdout.write(`JWKS=${jwks}`);
|
||||
process.stdout.write("\n");
|
||||
process.stdout.write('\n');
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
export {
|
||||
PASSWORD_MIN,
|
||||
PASSWORD_MAX,
|
||||
PASSWORD_REGEX,
|
||||
} from './auth';
|
||||
export { PASSWORD_MIN, PASSWORD_MAX, PASSWORD_REGEX } from './auth';
|
||||
|
||||
Reference in New Issue
Block a user