Skip to content

Commit

Permalink
Merge pull request #614 from EdgeApp/william/fetch-captcha
Browse files Browse the repository at this point in the history
Fetch challenge
  • Loading branch information
swansontec authored Sep 6, 2024
2 parents 0e4a8b7 + e41eb1f commit dc1991a
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

- added: `EdgeContext.fetchChallenge`, to request an account-creation CAPTCHA.
- added: Accept a challengeId in `EdgeContext.usernameAvailable`

## 2.14.0 (2024-09-03)

- added: Log HTTP 409 errors from login server with breadcrumbs.
Expand Down
13 changes: 11 additions & 2 deletions src/core/context/context-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { bridgifyObject, onMethod, watchMethod } from 'yaob'

import { checkPasswordRules, fixUsername } from '../../client-side'
import {
asChallengeErrorPayload,
EdgeAccount,
EdgeAccountOptions,
EdgeContext,
Expand All @@ -17,6 +18,7 @@ import { findAppLogin, makeAccount } from '../account/account-init'
import { createLogin, usernameAvailable } from '../login/create'
import { requestEdgeLogin } from '../login/edge'
import { makeLoginTree, syncLogin } from '../login/login'
import { loginFetch } from '../login/login-fetch'
import { fetchLoginMessages } from '../login/login-messages'
import {
getEmptyStash,
Expand Down Expand Up @@ -70,9 +72,16 @@ export function makeContextApi(ai: ApiInput): EdgeContext {
await removeStash(ai, loginId)
},

async usernameAvailable(username: string): Promise<boolean> {
async fetchChallenge() {
const response = await loginFetch(ai, 'POST', '/v2/captcha/create', {})
const { challengeId, challengeUri } = asChallengeErrorPayload(response)
return { challengeId, challengeUri }
},

async usernameAvailable(username: string, opts = {}): Promise<boolean> {
const { challengeId } = opts
username = fixUsername(username)
return await usernameAvailable(ai, username)
return await usernameAvailable(ai, username, challengeId)
},

async createAccount(
Expand Down
10 changes: 6 additions & 4 deletions src/core/login/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ export interface LoginCreateOpts {
*/
export async function usernameAvailable(
ai: ApiInput,
username: string
username: string,
challengeId?: string
): Promise<boolean> {
const userId = await hashUsername(ai, username)
const request = {
challengeId,
userId
}
return await loginFetch(ai, 'POST', '/v2/login', request)
Expand Down Expand Up @@ -147,13 +149,13 @@ export async function createLogin(
accountOpts: EdgeAccountOptions,
opts: LoginCreateOpts
): Promise<LoginTree> {
const { challengeId, now = new Date() } = accountOpts

// For crash errors:
ai.props.log.breadcrumb('createLogin', {})

const { now = new Date() } = accountOpts

const kit = await makeCreateKit(ai, undefined, '', opts)
const request = { data: kit.server }
const request = { challengeId, data: kit.server }
await loginFetch(ai, 'POST', kit.serverPath, request)

kit.stash.lastLogin = now
Expand Down
10 changes: 10 additions & 0 deletions src/types/server-cleaners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
ChangeSecretPayload,
ChangeUsernamePayload,
ChangeVouchersPayload,
CreateChallengePayload,
CreateKeysPayload,
CreateLoginPayload,
EdgeBox,
Expand Down Expand Up @@ -257,6 +258,12 @@ export const asChallengeErrorPayload: Cleaner<ChallengeErrorPayload> = asObject(
}
)

export const asCreateChallengePayload: Cleaner<CreateChallengePayload> =
asObject({
challengeId: asString,
challengeUri: asOptional(asString)
})

export const asLobbyPayload: Cleaner<LobbyPayload> = asObject({
request: asEdgeLobbyRequest,
replies: asArray(asEdgeLobbyReply)
Expand Down Expand Up @@ -407,6 +414,9 @@ export const wasCreateLoginPayload =
export const wasChallengeErrorPayload = uncleaner<ChallengeErrorPayload>(
asChallengeErrorPayload
)
export const wasCreateChallengePayload = uncleaner<CreateChallengePayload>(
asCreateChallengePayload
)
export const wasLobbyPayload = uncleaner<LobbyPayload>(asLobbyPayload)
export const wasLoginPayload = uncleaner<LoginPayload>(asLoginPayload)
export const wasMessagesPayload = uncleaner<MessagesPayload>(asMessagesPayload)
Expand Down
8 changes: 8 additions & 0 deletions src/types/server-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ export interface ChallengeErrorPayload {
challengeUri: string
}

/**
* Data sent back when preemptively requesting a CAPTCHA.
*/
export interface CreateChallengePayload {
challengeId: string
challengeUri?: string
}

/**
* Data sent back when looking up a login barcode.
*/
Expand Down
11 changes: 10 additions & 1 deletion src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1840,8 +1840,17 @@ export interface EdgeContext {
readonly forgetAccount: (rootLoginId: string) => Promise<void>

// Account creation:
/** Preemptively requests a CAPTCHA for account creation. */
readonly fetchChallenge: () => Promise<{
challengeId: string
/** If this is missing, the challenge is already solved. */
challengeUri?: string
}>
readonly fixUsername: (username: string) => string
readonly usernameAvailable: (username: string) => Promise<boolean>
readonly usernameAvailable: (
username: string,
opts?: { challengeId?: string }
) => Promise<boolean>
readonly createAccount: (
opts: EdgeCreateAccountOptions & EdgeAccountOptions
) => Promise<EdgeAccount>
Expand Down

0 comments on commit dc1991a

Please sign in to comment.