support can look up users by email, not just name
This commit is contained in:
parent
7c9313f4a6
commit
d219750ea1
3 changed files with 90 additions and 3 deletions
|
@ -265,10 +265,12 @@ function UserItemsPage() {
|
|||
|
||||
function UserSearchForm() {
|
||||
const [query, setQuery] = React.useState("");
|
||||
|
||||
const { isSupportUser, supportSecret } = useSupport();
|
||||
const history = useHistory();
|
||||
const toast = useToast();
|
||||
|
||||
const [loadUserSearch, { loading }] = useLazyQuery(
|
||||
const [loadUserSearch, { loading: loading1 }] = useLazyQuery(
|
||||
gql`
|
||||
query UserSearchForm($name: String!) {
|
||||
userByName(name: $name) {
|
||||
|
@ -302,11 +304,58 @@ function UserSearchForm() {
|
|||
}
|
||||
);
|
||||
|
||||
const [loadUserByEmail, { loading: loading2 }] = useLazyQuery(
|
||||
gql`
|
||||
query UserSearchFormByEmail($email: String!, $supportSecret: String!) {
|
||||
userByEmail(email: $email, supportSecret: $supportSecret) {
|
||||
id
|
||||
# Consider preloading UserItemsPage fields here, too?
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
onCompleted: (data) => {
|
||||
const user = data.userByEmail;
|
||||
if (!user) {
|
||||
toast({
|
||||
status: "warning",
|
||||
title: "We couldn't find that email address!",
|
||||
description: "Check the spelling and try again?",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
history.push(`/user/${user.id}/items`);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(error);
|
||||
toast({
|
||||
status: "error",
|
||||
title: "Error loading user by email!",
|
||||
description: "Check your connection and try again?",
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<Box
|
||||
as="form"
|
||||
onSubmit={(e) => {
|
||||
loadUserSearch({ variables: { name: query } });
|
||||
const isSupportOnlyEmailSearch =
|
||||
isSupportUser && query.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
|
||||
|
||||
if (isSupportOnlyEmailSearch) {
|
||||
toast({
|
||||
status: "info",
|
||||
title: "Searching by email! (💖 Support-only)",
|
||||
description: "The email field is protected from most users.",
|
||||
});
|
||||
loadUserByEmail({ variables: { email: query, supportSecret } });
|
||||
} else {
|
||||
loadUserSearch({ variables: { name: query } });
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
|
@ -326,7 +375,7 @@ function UserSearchForm() {
|
|||
variant="ghost"
|
||||
icon={<ArrowForwardIcon />}
|
||||
aria-label="Search"
|
||||
isLoading={loading}
|
||||
isLoading={loading1 || loading2}
|
||||
minWidth="1.5rem"
|
||||
minHeight="1.5rem"
|
||||
width="1.5rem"
|
||||
|
|
|
@ -774,6 +774,29 @@ const buildUserByNameLoader = (db) =>
|
|||
);
|
||||
});
|
||||
|
||||
const buildUserByEmailLoader = (db) =>
|
||||
new DataLoader(async (emails) => {
|
||||
const qs = emails.map((_) => "?").join(",");
|
||||
const [rows, _] = await db.execute(
|
||||
{
|
||||
sql: `
|
||||
SELECT users.*, id_users.email FROM users
|
||||
INNER JOIN openneo_id.users id_users ON id_users.id = users.remote_id
|
||||
WHERE id_users.email IN (${qs})
|
||||
`,
|
||||
nestTables: true,
|
||||
},
|
||||
emails
|
||||
);
|
||||
|
||||
const entities = rows.map((row) => ({
|
||||
user: normalizeRow(row.users),
|
||||
email: row.id_users.email,
|
||||
}));
|
||||
|
||||
return emails.map((email) => entities.find((e) => e.email === email).user);
|
||||
});
|
||||
|
||||
const buildUserClosetHangersLoader = (db) =>
|
||||
new DataLoader(async (userIds) => {
|
||||
const qs = userIds.map((_) => "?").join(",");
|
||||
|
@ -907,6 +930,7 @@ function buildLoaders(db) {
|
|||
loaders.speciesTranslationLoader = buildSpeciesTranslationLoader(db);
|
||||
loaders.userLoader = buildUserLoader(db);
|
||||
loaders.userByNameLoader = buildUserByNameLoader(db);
|
||||
loaders.userByEmailLoader = buildUserByEmailLoader(db);
|
||||
loaders.userClosetHangersLoader = buildUserClosetHangersLoader(db);
|
||||
loaders.userClosetListsLoader = buildUserClosetListsLoader(db);
|
||||
loaders.zoneLoader = buildZoneLoader(db);
|
||||
|
|
|
@ -41,6 +41,7 @@ const typeDefs = gql`
|
|||
extend type Query {
|
||||
user(id: ID!): User
|
||||
userByName(name: String!): User
|
||||
userByEmail(email: String!, supportSecret: String!): User
|
||||
currentUser: User
|
||||
}
|
||||
`;
|
||||
|
@ -224,6 +225,19 @@ const resolvers = {
|
|||
return { id: user.id };
|
||||
},
|
||||
|
||||
userByEmail: async (_, { email, supportSecret }, { userByEmailLoader }) => {
|
||||
if (supportSecret !== process.env["SUPPORT_SECRET"]) {
|
||||
throw new Error(`Support secret is incorrect. Try setting up again?`);
|
||||
}
|
||||
|
||||
const user = await userByEmailLoader.load(email);
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { id: user.id };
|
||||
},
|
||||
|
||||
currentUser: async (_, __, { currentUserId, userLoader }) => {
|
||||
if (currentUserId == null) {
|
||||
return null;
|
||||
|
|
Loading…
Reference in a new issue