-
Notifications
You must be signed in to change notification settings - Fork 1
start work on settings sync #524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
60347be
add users table
ingoau 477aab4
move to another file
ingoau 6a3b907
add jwt payload type
ingoau 85ccbf4
add clerkid to schema
ingoau 69e555b
add indexing by clerk id
ingoau 6a73f04
add code to get and update user
ingoau 9a7663d
make user an id
ingoau 31452da
change some stuff
ingoau af0e474
use userid
ingoau 71337a5
add get user info function
ingoau a2996e9
use new function and stuff
ingoau 372da0e
add optional fields
ingoau caf4512
change some settings for clerk
ingoau 7c5e643
create account route
ingoau 7989196
remove dialog
ingoau a455402
add active state for profile button
ingoau a1b827f
add sync settings store
ingoau 78a0f32
add sync item
ingoau 9534846
grey out icon when disabled
ingoau 5909522
add syncing state
ingoau 1302f57
add sync state to sidebar
ingoau dd67dc4
add animation when syncing
ingoau 36ac954
add checkboxes
ingoau 9a20581
add more sync settings
ingoau 2ab1a0c
add more sync settings
ingoau a36b95b
bind settings to local storage
ingoau be88fa9
transition no matter the state
ingoau abf8599
disabled settings when sync is disabled
ingoau 52f81b4
fix non existent user handling
ingoau 7447775
fix verification
ingoau 231edf8
remove unused analytics setting
ingoau 54adb8c
add schema for settings
ingoau 449944a
add favourites and history
ingoau 969fb22
make sync things optional
ingoau 289447b
add sync get query
ingoau ec2a7bc
add mutation for sync update
ingoau b01637f
change branch name thing
ingoau 7268603
add functions for sync
ingoau 25b7685
make functions async and change syncstate
ingoau f0b393c
change some stuff
ingoau ec742fa
move everything to one sync function
ingoau 21ddbf6
fix issue with svelte
ingoau 135a72e
fix issue with users that still have analytics key in local stoarge
ingoau 8235588
add slightly better error handling
ingoau c5c6a88
add code to sync settings
ingoau 450215d
add handler for settings change
ingoau bd34242
move analytics and sync to settings change function
ingoau 74f308e
pass convex client down
ingoau 8a84cde
disable sync for now
ingoau da14aa9
fix issue
ingoau File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| import { v } from 'convex/values'; | ||
| import { mutation, query } from './_generated/server'; | ||
| import { getAndUpdateUser, getUser, verifyJwtAndGetPayload } from './utils'; | ||
|
|
||
| export const get = query({ | ||
| args: { | ||
| jwt: v.string() | ||
| }, | ||
| handler: async (ctx, args) => { | ||
| const payload = await verifyJwtAndGetPayload(args.jwt); | ||
| const userInfo = await getUser(ctx, payload); | ||
| if (!userInfo) { | ||
| return null; | ||
| } | ||
| return { | ||
| settings: userInfo.settings, | ||
| favourites: userInfo.favourites, | ||
| history: userInfo.history | ||
| }; | ||
| } | ||
| }); | ||
|
|
||
| export const update = mutation({ | ||
| args: { | ||
| jwt: v.string(), | ||
| settings: v.optional( | ||
| v.object({ | ||
| experimentalFeatures: v.boolean(), | ||
| open: v.string(), | ||
| theme: v.string(), | ||
| panic: v.object({ | ||
| enabled: v.boolean(), | ||
| key: v.string(), | ||
| url: v.string(), | ||
| disableExperimentalMode: v.boolean() | ||
| }), | ||
| cloak: v.object({ | ||
| mode: v.string(), | ||
| name: v.string(), | ||
| icon: v.string() | ||
| }), | ||
| history: v.boolean() | ||
| }) | ||
| ), | ||
| favourites: v.optional(v.array(v.string())), | ||
| history: v.optional(v.array(v.string())) | ||
| }, | ||
| handler: async (ctx, args) => { | ||
| const payload = await verifyJwtAndGetPayload(args.jwt); | ||
| if (!payload.sub) { | ||
| throw new Error('Invalid JWT: missing subject'); | ||
| } | ||
| const userInfo = await getAndUpdateUser(ctx, payload); | ||
| if (!userInfo?._id) { | ||
| throw new Error('Something went wrong'); | ||
| } | ||
|
|
||
| if (args.favourites) { | ||
| await ctx.db.patch(userInfo._id, { | ||
| favourites: args.favourites | ||
| }); | ||
| } | ||
| if (args.history) { | ||
| await ctx.db.patch(userInfo._id, { | ||
| history: args.history | ||
| }); | ||
| } | ||
| if (args.settings) { | ||
| await ctx.db.patch(userInfo._id, { | ||
| settings: args.settings | ||
| }); | ||
| } | ||
| } | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| export interface JWTPayload { | ||
| email: string; | ||
| avatar: string; | ||
| lastname: string; | ||
| username: string; | ||
| verified: boolean; | ||
| firstname: string; | ||
| azp: string; | ||
| exp: number; | ||
| fva: number[]; | ||
| iat: number; | ||
| iss: string; | ||
| nbf: number; | ||
| sid: string; | ||
| sub: string; | ||
| v: string; | ||
| fea: string; | ||
| } | ||
ingoau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| import * as jose from 'jose'; | ||
| import type { MutationCtx, QueryCtx } from './_generated/server'; | ||
| import type { JwtPayload } from 'jsonwebtoken'; | ||
|
|
||
ingoau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Shared helper function to verify JWT and return payload | ||
| export async function verifyJwtAndGetPayload(jwt: string) { | ||
| if (!process.env.CLERK_JWT_KEY) { | ||
| throw new Error('Missing CLERK_JWT_KEY environment variable'); | ||
| } | ||
| const publicKey = await jose.importSPKI(process.env.CLERK_JWT_KEY, 'RS256'); | ||
| if (jwt.length === 0) { | ||
| throw new Error('Missing JWT'); | ||
| } | ||
| const { payload } = await jose.jwtVerify(jwt, publicKey, {}); | ||
| if (!payload.sub) { | ||
| throw new Error('Invalid JWT'); | ||
| } | ||
| return payload; | ||
| } | ||
|
|
||
| export async function getUser(ctx: QueryCtx, payload: JwtPayload) { | ||
| if (!payload.sub) { | ||
| throw new Error('Invalid JWT'); | ||
| } | ||
| let user = await ctx.db | ||
| .query('users') | ||
| .withIndex('clerkid', (q) => q.eq('clerkId', payload.sub || '')) | ||
| .first(); | ||
|
|
||
| if (!user) { | ||
| return null; | ||
| } | ||
|
|
||
| return user; | ||
| } | ||
ingoau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| export async function getAndUpdateUser(ctx: MutationCtx, payload: JwtPayload) { | ||
| if (!payload.sub) { | ||
| throw new Error('Invalid JWT'); | ||
| } | ||
| let user = await ctx.db | ||
| .query('users') | ||
| .withIndex('clerkid', (q) => q.eq('clerkId', payload.sub || '')) | ||
| .first(); | ||
| if (user) { | ||
| await ctx.db.patch(user._id, { | ||
| avatar: payload.avatar, | ||
| email: payload.email, | ||
| firstName: payload.firstname, | ||
| lastName: payload.lastname, | ||
| username: payload.username, | ||
| verified: payload.verified, | ||
| clerkId: payload.sub | ||
| }); | ||
| user = await ctx.db.get(user._id); | ||
| } else { | ||
| const userId = await ctx.db.insert('users', { | ||
| avatar: payload.avatar, | ||
| email: payload.email, | ||
| firstName: payload.firstname, | ||
| lastName: payload.firstname, | ||
| username: payload.username, | ||
| verified: payload.verified, | ||
| clerkId: payload.sub | ||
| }); | ||
| user = await ctx.db.get(userId); | ||
| } | ||
| return user; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.