-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Alternative login flow (magic link via bot) (#1488)
* Log in link creation initial * Add global name to update all command * Remove left over log * Login command * Update command * Add todos * TODOs * Migration file fix order
- Loading branch information
Showing
44 changed files
with
539 additions
and
420 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
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,22 @@ | ||
insert into | ||
"User" ( | ||
"discordId", | ||
"discordName", | ||
"discordDiscriminator", | ||
"discordAvatar", | ||
"discordUniqueName" | ||
) | ||
values | ||
( | ||
@discordId, | ||
@discordName, | ||
@discordDiscriminator, | ||
@discordAvatar, | ||
@discordUniqueName | ||
) on conflict("discordId") do | ||
update | ||
set | ||
"discordName" = excluded."discordName", | ||
"discordDiscriminator" = excluded."discordDiscriminator", | ||
"discordAvatar" = excluded."discordAvatar", | ||
"discordUniqueName" = excluded."discordUniqueName" returning * |
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,30 @@ | ||
import { nanoid } from "nanoid"; | ||
import { sql } from "~/db/sql"; | ||
import type { LogInLink } from "~/db/types"; | ||
import { dateToDatabaseTimestamp } from "~/utils/dates"; | ||
|
||
const stm = sql.prepare(/* sql */ ` | ||
insert into "LogInLink" ( | ||
"userId", | ||
"expiresAt", | ||
"code" | ||
) values ( | ||
@userId, | ||
@expiresAt, | ||
@code | ||
) returning * | ||
`); | ||
|
||
// 10 minutes | ||
const LOG_IN_LINK_VALID_FOR = 10 * 60 * 1000; | ||
const LOG_IN_LINK_LENGTH = 12; | ||
|
||
export function createLogInLink(userId: number) { | ||
return stm.get({ | ||
userId, | ||
expiresAt: dateToDatabaseTimestamp( | ||
new Date(Date.now() + LOG_IN_LINK_VALID_FOR), | ||
), | ||
code: nanoid(LOG_IN_LINK_LENGTH), | ||
}) as LogInLink; | ||
} |
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,10 @@ | ||
import { sql } from "~/db/sql"; | ||
|
||
const stm = sql.prepare(/* sql */ ` | ||
delete from "LogInLink" | ||
where "code" = @code | ||
`); | ||
|
||
export function deleteLogInLinkByCode(code: string) { | ||
return stm.run({ code }); | ||
} |
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,18 @@ | ||
import { sql } from "~/db/sql"; | ||
import { dateToDatabaseTimestamp } from "~/utils/dates"; | ||
|
||
const stm = sql.prepare(/* sql */ ` | ||
select "userId" | ||
from "LogInLink" | ||
where "code" = @code | ||
and "expiresAt" > @now | ||
`); | ||
|
||
export function userIdByLogInLinkCode(code: string) { | ||
return ( | ||
stm.get({ | ||
code, | ||
now: dateToDatabaseTimestamp(new Date()), | ||
}) as any | ||
)?.userId as number | undefined; | ||
} |
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 @@ | ||
export { createLogInLinkAction as action } from "~/modules/auth"; |
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 @@ | ||
export { logInViaLinkLoader as loader } from "~/modules/auth"; |
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,96 @@ | ||
import { SlashCommandBuilder } from "@discordjs/builders"; | ||
import type { CommandInteraction, User } from "discord.js"; | ||
import ids from "../ids"; | ||
import type { BotCommand } from "../types"; | ||
import { sendouInkFetch } from "../utils"; | ||
|
||
const LOGIN_COMMAND_NAME = "login"; | ||
const UPDATE_PROFILE_COMMAND_NAME = "update-profile"; | ||
|
||
export const loginCommand: BotCommand = { | ||
guilds: [ids.guilds.plusServer, ids.guilds.sendou], | ||
name: LOGIN_COMMAND_NAME, | ||
builder: new SlashCommandBuilder() | ||
.setName(LOGIN_COMMAND_NAME) | ||
.setDescription("Get log in link for sendou.ink"), | ||
execute: async ({ interaction }) => { | ||
await execute(interaction, false); | ||
}, | ||
}; | ||
|
||
export const updateProfileCommand: BotCommand = { | ||
guilds: [ids.guilds.plusServer, ids.guilds.sendou], | ||
name: UPDATE_PROFILE_COMMAND_NAME, | ||
builder: new SlashCommandBuilder() | ||
.setName(UPDATE_PROFILE_COMMAND_NAME) | ||
.setDescription("Update your username and profile picture on sendou.ink"), | ||
execute: async ({ interaction }) => { | ||
await execute(interaction, true); | ||
}, | ||
}; | ||
|
||
async function execute( | ||
interaction: CommandInteraction<any>, | ||
updateOnly: boolean, | ||
) { | ||
const user = interaction.member?.user as User; | ||
if (!user) { | ||
return interaction.reply({ | ||
content: "Something went wrong", | ||
}); | ||
} | ||
|
||
const hasUniqueUsername = user.discriminator === "0"; | ||
|
||
const discordName = hasUniqueUsername ? user.globalName : user.username; | ||
const discordUniqueName = hasUniqueUsername ? user.username : null; | ||
if (!discordName || !discordUniqueName) { | ||
return interaction.reply({ | ||
content: | ||
"Can't do this with an account that is missing the new kind of Discord username", | ||
}); | ||
} | ||
|
||
const searchParams = new URLSearchParams( | ||
user.avatar | ||
? { | ||
discordAvatar: user.avatar, | ||
discordId: user.id, | ||
discordName, | ||
discordUniqueName, | ||
updateOnly: String(updateOnly), | ||
} | ||
: { | ||
discordId: user.id, | ||
discordName, | ||
discordUniqueName, | ||
updateOnly: String(updateOnly), | ||
}, | ||
); | ||
|
||
const response = await sendouInkFetch(`/auth/create-link?${searchParams}`, { | ||
method: "post", | ||
}); | ||
|
||
if (updateOnly) { | ||
if (!response.ok) { | ||
return interaction.reply({ | ||
content: "Something went wrong when updating", | ||
ephemeral: true, | ||
}); | ||
} | ||
|
||
return interaction.reply({ | ||
content: "Updated your profile on sendou.ink", | ||
ephemeral: true, | ||
}); | ||
} | ||
|
||
const { code } = await response.json(); | ||
|
||
return interaction.reply({ | ||
content: | ||
"Use the link below to log in to sendou.ink. It's active for 10 minutes. ⚠️ Don't share this link with others as it will allow them to log in to your account.\n\n[log in link](https://sendou.ink/auth/login?code=${code})", | ||
ephemeral: true, | ||
}); | ||
} |
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
Oops, something went wrong.