-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add username claim and delete logic to redis and update DNS ser…
…ver with it.
- Loading branch information
Showing
9 changed files
with
197 additions
and
8 deletions.
There are no files selected for viewing
This file contains 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 |
---|---|---|
|
@@ -3,3 +3,4 @@ extend-exclude = ["src/lib/pow/wasm/*"] | |
|
||
[default.extend-words] | ||
ratatui = "ratatui" | ||
additionals = "additionals" |
This file contains 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 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 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 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,68 @@ | ||
import { redis } from '$lib/redis'; | ||
import { validUsernameRegex } from './utils/username'; | ||
|
||
const USER_NAMES_PREFIX = 'weird:users:names:'; | ||
const USER_RAUTHY_IDS_PREFIX = 'weird:users:rauthyIds:'; | ||
const USER_SUBSPACES_PREFIX = 'weird:users:subspaces:'; | ||
|
||
export async function claimUsername(username: string, rauthyId: string, subspace: string) { | ||
if (!username.match(validUsernameRegex)) { | ||
throw 'Username does not pass valid username check.'; | ||
} | ||
|
||
const usernameKey = USER_NAMES_PREFIX + username; | ||
const rauthyIdKey = USER_RAUTHY_IDS_PREFIX + rauthyId; | ||
const subspaceKey = USER_SUBSPACES_PREFIX + subspace; | ||
|
||
const TRIES = 3; | ||
const failures = 0; | ||
while (failures <= TRIES) { | ||
redis.watch([usernameKey, rauthyIdKey, subspaceKey]); | ||
|
||
if (await redis.exists(usernameKey)) { | ||
await redis.unwatch(); | ||
throw `Cannot claim username "${username}": username already claimed.`; | ||
} | ||
|
||
const multi = redis.multi(); | ||
|
||
multi.del(usernameKey); | ||
multi.hSet(usernameKey, 'subspace', subspace); | ||
multi.hSet(usernameKey, 'rauthyId', rauthyId); | ||
multi.del(rauthyIdKey); | ||
multi.hSet(rauthyIdKey, 'username', username); | ||
multi.hSet(rauthyIdKey, 'subspace', subspace); | ||
multi.del(subspaceKey); | ||
multi.hSet(subspaceKey, 'username', username); | ||
multi.hSet(subspaceKey, 'rauthyId', rauthyId); | ||
|
||
try { | ||
await multi.exec(); | ||
return; | ||
} catch (e) { | ||
console.warn( | ||
`Initial attempt to claim username ${username} failed will try ${TRIES - failures} more times: ${e}` | ||
); | ||
} | ||
} | ||
} | ||
|
||
export async function deleteUsername(username: string) { | ||
const usernameKey = USER_NAMES_PREFIX + username; | ||
|
||
await redis.watch(usernameKey); | ||
|
||
const user = await redis.hGetAll(usernameKey); | ||
|
||
const multi = redis.multi(); | ||
|
||
await multi.del(usernameKey); | ||
if (user.subspace) { | ||
await multi.del(USER_SUBSPACES_PREFIX + user.subspace); | ||
} | ||
if (user.rauthyId) { | ||
await multi.del(USER_RAUTHY_IDS_PREFIX + user.rauthyId); | ||
} | ||
|
||
await multi.exec(); | ||
} |
This file contains 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 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
33 changes: 33 additions & 0 deletions
33
src/routes/(internal)/__internal__/admin/usernames/+page.server.ts
This file contains 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,33 @@ | ||
import { claimUsername, deleteUsername } from '$lib/usernames'; | ||
import type { Actions } from './$types'; | ||
|
||
export const actions = { | ||
claimUsername: async ({ request }) => { | ||
const formData = await request.formData(); | ||
const username = formData.get('username')?.toString(); | ||
const rauthyId = formData.get('rauthyId')?.toString(); | ||
const subspace = formData.get('subspace')?.toString(); | ||
if (!(username && rauthyId && subspace)) return { error: 'You must fill in all fields' }; | ||
|
||
try { | ||
await claimUsername(username, rauthyId, subspace); | ||
} catch (e) { | ||
return { error: `Error claiming username: ${e}` }; | ||
} | ||
|
||
return { success: `Username ${username} claimed.` }; | ||
}, | ||
deleteUsername: async ({ request }) => { | ||
const formData = await request.formData(); | ||
const username = formData.get('username')?.toString(); | ||
if (!username) return { error: 'You must fill in all fields' }; | ||
|
||
try { | ||
await deleteUsername(username); | ||
} catch (e) { | ||
return { error: `Error deleting username: ${e}` }; | ||
} | ||
|
||
return { success: `Username ${username} deleted.` }; | ||
} | ||
} satisfies Actions; |
37 changes: 37 additions & 0 deletions
37
src/routes/(internal)/__internal__/admin/usernames/+page.svelte
This file contains 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,37 @@ | ||
<script lang="ts"> | ||
import type { ActionData } from './$types'; | ||
const { form }: { form: ActionData } = $props(); | ||
</script> | ||
|
||
{#if form?.error} | ||
<article class="pico-background-red-550"> | ||
{form.error} | ||
</article> | ||
{:else if form?.success} | ||
<article class="pico-background-green-550"> | ||
{form.success} | ||
</article> | ||
{/if} | ||
|
||
<h2>Claim Username</h2> | ||
|
||
<form method="post" action="?/claimUsername"> | ||
<!-- svelte-ignore a11y_no_redundant_roles --> | ||
<fieldset role="group"> | ||
<input name="username" placeholder="username" /> | ||
<input name="rauthyId" placeholder="rauthyId" /> | ||
<input name="subspace" placeholder="subspace" /> | ||
<button>Claim</button> | ||
</fieldset> | ||
</form> | ||
|
||
<h2>Delete Username</h2> | ||
|
||
<form method="post" action="?/deleteUsername"> | ||
<!-- svelte-ignore a11y_no_redundant_roles --> | ||
<fieldset role="group"> | ||
<input name="username" placeholder="username" /> | ||
<button>Delete</button> | ||
</fieldset> | ||
</form> |