Skip to content

Commit

Permalink
✨ feat: change password api
Browse files Browse the repository at this point in the history
  • Loading branch information
rustin01 committed Jul 31, 2024
1 parent 323b1ec commit 195bf2f
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 19 deletions.
14 changes: 14 additions & 0 deletions apps/wallet/src/apis/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,17 @@ export class GetMnemonicResult {
export class GetPublicKeyResult {
publicKeyBase64!: string
}

export class UpdateMnemonicInput {
aesKey!: string
oldMnemonicContent!: string
oldVersion!: number
newMnemonicContent!: string
newVersion!: number

public constructor(init?: Partial<UpdateMnemonicInput>) {
Object.assign(this, init);
}
}

export class UpdateMnemonicResult extends GetMnemonicResult {}
13 changes: 11 additions & 2 deletions apps/wallet/src/apis/services/auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { sendAuthRequest } from "..";
import { CreateMnemonicInput, GetMnemonicInput, GetMnemonicResult, GetPublicKeyResult } from "../models";
import { CreateMnemonicInput, GetMnemonicInput, GetMnemonicResult, GetPublicKeyResult, UpdateMnemonicInput, UpdateMnemonicResult } from "../models";

export const CreateMnemonicAsync = async (input: CreateMnemonicInput) => {
await sendAuthRequest(
Expand All @@ -26,7 +26,16 @@ export const DeleteMnemonicAsync = async () => {
export const GetPublicKeyAsync = async () => {
const result = await sendAuthRequest<null, GetPublicKeyResult>(
null,
'/api/app/mnemonic/get'
'/api/app/mnemonic/public-key',
'GET',
);
return result
}

export const UpdateMnemonicAsync = async (input: UpdateMnemonicInput) => {
const result = await sendAuthRequest<UpdateMnemonicInput, UpdateMnemonicResult>(
input,
'/api/app/mnemonic/update'
);
return result
}
2 changes: 1 addition & 1 deletion apps/wallet/src/pages/password/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const CreatePasswordPage: FC = observer(() => {
}
const pwd = MD5(`${password}${hibitIdSession.userId}`).toString()
const phrase = HDNodeWallet.createRandom().mnemonic!.phrase
const encryptedPhrase = AES.encrypt(phrase, pwd).toString(format.Hex)
const encryptedPhrase = AES.encrypt(phrase, pwd).toString()
await CreateMnemonicAsync(new CreateMnemonicInput({
aesKey: '', // TODO: aesKey
mnemonicContent: encryptedPhrase,
Expand Down
36 changes: 25 additions & 11 deletions apps/wallet/src/pages/password/reset.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, useEffect } from "react";
import { FC } from "react";
import SvgGo from '../../assets/right-arrow.svg?react'
import { useNavigate } from "react-router-dom";
import { object, string, ref } from 'yup'
Expand All @@ -9,6 +9,9 @@ import { observer } from "mobx-react";
import { useMutation } from "@tanstack/react-query";
import toaster from "../../components/Toaster";
import LoaderButton from "../../components/LoaderButton";
import hibitIdSession from "../../stores/session";
import { getErrorMessage, HibitIDError, HibitIDErrorCode } from "../../utils/error-code";
import { useTranslation } from "react-i18next";

const formSchema = object({
password: string()
Expand All @@ -23,7 +26,9 @@ const formSchema = object({

const ResetPasswordPage: FC = observer(() => {
const navigate = useNavigate()
const { t } = useTranslation()
const {
setError,
register,
handleSubmit,
formState: { errors },
Expand All @@ -33,20 +38,29 @@ const ResetPasswordPage: FC = observer(() => {
})

const submitMutation = useMutation({
mutationFn: async () => {
// TODO:
await new Promise((resolve) => {
setTimeout(() => {
resolve(true)
}, 2000)
})
mutationFn: async ({ oldPassword, newPassword }: {
oldPassword: string
newPassword: string
}) => {
try {
await hibitIdSession.updatePassword(oldPassword, newPassword)
toaster.success('Password changed')
navigate('/')
} catch (e) {
if (e instanceof HibitIDError && e.code === HibitIDErrorCode.INVALID_PASSWORD) {
setError('password', { message: 'Password incorrect' })
} else {
toaster.error(getErrorMessage(e, t))
}
}
}
})

const handleConfirm = handleSubmit(async (values) => {
await submitMutation.mutateAsync()
toaster.success('Password changed')
navigate('/')
await submitMutation.mutateAsync({
oldPassword: values.password,
newPassword: values.newPassword
})
})

return (
Expand Down
33 changes: 28 additions & 5 deletions apps/wallet/src/stores/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import rpcManager from "./rpc";
import { WalletAccount } from "@deland-labs/hibit-id-sdk";
import { TonChainWallet } from "../utils/chain/chain-wallets/ton";
import { Oidc } from "oidc-spa/oidc";
import { GetMnemonicAsync } from "../apis/services/auth";
import { GetMnemonicAsync, UpdateMnemonicAsync } from "../apis/services/auth";
import { HibitIDError, HibitIDErrorCode } from "../utils/error-code";
import { GetMnemonicInput, GetMnemonicResult } from "../apis/models";
import { AES, enc } from "crypto-js";
import { GetMnemonicInput, GetMnemonicResult, UpdateMnemonicInput } from "../apis/models";
import { AES, enc, MD5 } from "crypto-js";

export class HibitIdSession {
public wallet: ChainWallet | null = null
Expand Down Expand Up @@ -137,12 +137,35 @@ export class HibitIdSession {
this._mnemonic = mnemonicRes
}

public updatePassword = async (oldPasswordRaw: string, newPasswordRaw: string) => {
if (!this._mnemonic?.mnemonicContent) {
throw new HibitIDError(HibitIDErrorCode.MNEMONIC_NOT_CREATED)
}
if (!this._password) {
throw new HibitIDError(HibitIDErrorCode.WALLET_LOCKED)
}
const oldPwd = MD5(`${oldPasswordRaw}${this.userId}`).toString()
if (oldPwd !== this._password) {
throw new HibitIDError(HibitIDErrorCode.INVALID_PASSWORD)
}
const newPwd = MD5(`${newPasswordRaw}${this.userId}`).toString()
const phrase = AES.decrypt(this._mnemonic.mnemonicContent, oldPwd).toString(enc.Utf8);
const encryptedContent = AES.encrypt(phrase, newPwd).toString()
await UpdateMnemonicAsync(new UpdateMnemonicInput({
aesKey: '', // TODO:
oldMnemonicContent: this._mnemonic.mnemonicContent,
oldVersion: 0, // TODO:
newMnemonicContent: encryptedContent,
newVersion: 0, // TODO:
}))
await this.fetchMnemonic()
}

private initWallet = async (chainInfo: ChainInfo, password: string): Promise<ChainWallet> => {
if (!this._mnemonic?.id || !this._mnemonic?.mnemonicContent) {
throw new HibitIDError(HibitIDErrorCode.MNEMONIC_NOT_CREATED)
}
const utf8Content = Buffer.from(this._mnemonic.mnemonicContent, 'hex').toString('utf8')
const phrase = AES.decrypt(utf8Content, password).toString(enc.Utf8);
const phrase = AES.decrypt(this._mnemonic.mnemonicContent, password).toString(enc.Utf8);
if (!phrase) {
throw new HibitIDError(HibitIDErrorCode.INVALID_PASSWORD)
}
Expand Down

0 comments on commit 195bf2f

Please sign in to comment.