Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3369669
D7867.id26664.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
D7867.id26664.diff
View Options
diff --git a/keyserver/src/endpoints.js b/keyserver/src/endpoints.js
--- a/keyserver/src/endpoints.js
+++ b/keyserver/src/endpoints.js
@@ -38,7 +38,10 @@
reportMultiCreationResponder,
errorReportFetchInfosResponder,
} from './responders/report-responders.js';
-import { userSearchResponder } from './responders/search-responders.js';
+import {
+ userSearchResponder,
+ exactUserSearchResponder,
+} from './responders/search-responders.js';
import { siweNonceResponder } from './responders/siwe-nonce-responders.js';
import {
threadDeletionResponder,
@@ -133,6 +136,10 @@
responder: uploadDeletionResponder,
requiredPolicies: baseLegalPolicies,
},
+ exact_search_user: {
+ responder: exactUserSearchResponder,
+ requiredPolicies: [],
+ },
fetch_entries: {
responder: entryFetchResponder,
requiredPolicies: baseLegalPolicies,
diff --git a/keyserver/src/responders/search-responders.js b/keyserver/src/responders/search-responders.js
--- a/keyserver/src/responders/search-responders.js
+++ b/keyserver/src/responders/search-responders.js
@@ -5,11 +5,13 @@
import type {
UserSearchRequest,
UserSearchResult,
+ ExactUserSearchRequest,
+ ExactUserSearchResult,
} from 'lib/types/search-types.js';
import { globalAccountUserInfoValidator } from 'lib/types/user-types.js';
import { tShape } from 'lib/utils/validation-utils.js';
-import { searchForUsers } from '../search/users.js';
+import { searchForUsers, searchForUser } from '../search/users.js';
import type { Viewer } from '../session/viewer.js';
import { validateInput, validateOutput } from '../utils/validation-utils.js';
@@ -40,4 +42,30 @@
);
}
-export { userSearchResponder };
+const exactUserSearchRequestInputValidator = tShape<ExactUserSearchRequest>({
+ username: t.String,
+});
+
+const exactUserSearchResultValidator = tShape<ExactUserSearchResult>({
+ userInfo: t.maybe(globalAccountUserInfoValidator),
+});
+
+async function exactUserSearchResponder(
+ viewer: Viewer,
+ input: mixed,
+): Promise<ExactUserSearchResult> {
+ const request = await validateInput(
+ viewer,
+ exactUserSearchRequestInputValidator,
+ input,
+ );
+ const searchResult = await searchForUser(request.username);
+ const result = { userInfo: searchResult };
+ return validateOutput(
+ viewer.platformDetails,
+ exactUserSearchResultValidator,
+ result,
+ );
+}
+
+export { userSearchResponder, exactUserSearchResponder };
diff --git a/keyserver/src/search/users.js b/keyserver/src/search/users.js
--- a/keyserver/src/search/users.js
+++ b/keyserver/src/search/users.js
@@ -27,4 +27,21 @@
return userInfos;
}
-export { searchForUsers };
+async function searchForUser(
+ usernameQuery: string,
+): Promise<?GlobalAccountUserInfo> {
+ const query = SQL`
+ SELECT id, username
+ FROM users
+ WHERE LOWER(username) = LOWER(${usernameQuery})
+ `;
+ const [result] = await dbQuery(query);
+
+ if (result.length === 0) {
+ return null;
+ }
+ const { id, username } = result[0];
+ return { id, username };
+}
+
+export { searchForUsers, searchForUser };
diff --git a/lib/actions/user-actions.js b/lib/actions/user-actions.js
--- a/lib/actions/user-actions.js
+++ b/lib/actions/user-actions.js
@@ -15,7 +15,10 @@
UpdateUserAvatarResponse,
} from '../types/avatar-types.js';
import type { GetSessionPublicKeysArgs } from '../types/request-types.js';
-import type { UserSearchResult } from '../types/search-types.js';
+import type {
+ UserSearchResult,
+ ExactUserSearchResult,
+} from '../types/search-types.js';
import type {
SessionPublicKeys,
PreRequestUserState,
@@ -191,6 +194,24 @@
};
};
+const exactSearchUserActionTypes = Object.freeze({
+ started: 'EXACT_SEARCH_USER_STARTED',
+ success: 'EXACT_SEARCH_USER_SUCCESS',
+ failed: 'EXACT_SEARCH_USER_FAILED',
+});
+const exactSearchUser =
+ (
+ callServerEndpoint: CallServerEndpoint,
+ ): ((username: string) => Promise<ExactUserSearchResult>) =>
+ async username => {
+ const response = await callServerEndpoint('exact_search_user', {
+ username,
+ });
+ return {
+ userInfo: response.userInfo,
+ };
+ };
+
const updateSubscriptionActionTypes = Object.freeze({
started: 'UPDATE_SUBSCRIPTION_STARTED',
success: 'UPDATE_SUBSCRIPTION_SUCCESS',
@@ -282,6 +303,8 @@
registerActionTypes,
searchUsers,
searchUsersActionTypes,
+ exactSearchUser,
+ exactSearchUserActionTypes,
setUserSettings,
setUserSettingsActionTypes,
updateSubscription,
diff --git a/lib/types/endpoints.js b/lib/types/endpoints.js
--- a/lib/types/endpoints.js
+++ b/lib/types/endpoints.js
@@ -58,6 +58,7 @@
DELETE_ENTRY: 'delete_entry',
DELETE_THREAD: 'delete_thread',
DELETE_UPLOAD: 'delete_upload',
+ EXACT_SEARCH_USER: 'exact_search_user',
FETCH_ENTRIES: 'fetch_entries',
FETCH_ENTRY_REVISIONS: 'fetch_entry_revisions',
FETCH_ERROR_REPORT_INFOS: 'fetch_error_report_infos',
diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js
--- a/lib/types/redux-types.js
+++ b/lib/types/redux-types.js
@@ -74,7 +74,10 @@
ReportStore,
} from './report-types.js';
import type { ProcessServerRequestsPayload } from './request-types.js';
-import type { UserSearchResult } from './search-types.js';
+import type {
+ UserSearchResult,
+ ExactUserSearchResult,
+} from './search-types.js';
import type { SetSessionPayload } from './session-types.js';
import type {
ConnectionInfo,
@@ -583,6 +586,22 @@
+payload: UserSearchResult,
+loadingInfo: LoadingInfo,
}
+ | {
+ +type: 'EXACT_SEARCH_USER_STARTED',
+ +payload?: void,
+ +loadingInfo: LoadingInfo,
+ }
+ | {
+ +type: 'EXACT_SEARCH_USER_FAILED',
+ +error: true,
+ +payload: Error,
+ +loadingInfo: LoadingInfo,
+ }
+ | {
+ +type: 'EXACT_SEARCH_USER_SUCCESS',
+ +payload: ExactUserSearchResult,
+ +loadingInfo: LoadingInfo,
+ }
| {
+type: 'UPDATE_DRAFT',
+payload: {
diff --git a/lib/types/search-types.js b/lib/types/search-types.js
--- a/lib/types/search-types.js
+++ b/lib/types/search-types.js
@@ -3,8 +3,15 @@
import type { GlobalAccountUserInfo } from './user-types.js';
export type UserSearchRequest = {
- prefix?: string,
+ +prefix?: string,
};
export type UserSearchResult = {
- userInfos: $ReadOnlyArray<GlobalAccountUserInfo>,
+ +userInfos: $ReadOnlyArray<GlobalAccountUserInfo>,
+};
+
+export type ExactUserSearchRequest = {
+ +username: string,
+};
+export type ExactUserSearchResult = {
+ +userInfo: ?GlobalAccountUserInfo,
};
diff --git a/native/account/registration/connect-ethereum.react.js b/native/account/registration/connect-ethereum.react.js
--- a/native/account/registration/connect-ethereum.react.js
+++ b/native/account/registration/connect-ethereum.react.js
@@ -3,6 +3,16 @@
import * as React from 'react';
import { Text, View } from 'react-native';
+import {
+ exactSearchUser,
+ exactSearchUserActionTypes,
+} from 'lib/actions/user-actions.js';
+import type { SIWEResult } from 'lib/types/siwe-types.js';
+import {
+ useServerCall,
+ useDispatchActionPromise,
+} from 'lib/utils/action-utils.js';
+
import RegistrationButtonContainer from './registration-button-container.react.js';
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
@@ -94,8 +104,27 @@
[panelState],
);
- const onSkip = React.useCallback(() => {}, []);
- const onSuccessfulWalletSignature = React.useCallback(() => {}, []);
+ const onSkip = React.useCallback(() => {
+ // show username selection screen
+ }, []);
+
+ const exactSearchUserCall = useServerCall(exactSearchUser);
+ const dispatchActionPromise = useDispatchActionPromise();
+
+ const onSuccessfulWalletSignature = React.useCallback(
+ async (result: SIWEResult) => {
+ const searchPromise = exactSearchUserCall(result.address);
+ dispatchActionPromise(exactSearchUserActionTypes, searchPromise);
+ const { userInfo } = await searchPromise;
+
+ if (userInfo) {
+ // show duplicate account screen
+ } else {
+ // show avatar selection screen
+ }
+ },
+ [exactSearchUserCall, dispatchActionPromise],
+ );
let siwePanel;
if (panelState !== 'closed') {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Nov 26, 11:06 PM (20 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2586798
Default Alt Text
D7867.id26664.diff (8 KB)
Attached To
Mode
D7867: [keyserver][lib] Plumbing for new exact user search endpoint
Attached
Detach File
Event Timeline
Log In to Comment