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() {
|
function UserSearchForm() {
|
||||||
const [query, setQuery] = React.useState("");
|
const [query, setQuery] = React.useState("");
|
||||||
|
|
||||||
|
const { isSupportUser, supportSecret } = useSupport();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
const [loadUserSearch, { loading }] = useLazyQuery(
|
const [loadUserSearch, { loading: loading1 }] = useLazyQuery(
|
||||||
gql`
|
gql`
|
||||||
query UserSearchForm($name: String!) {
|
query UserSearchForm($name: String!) {
|
||||||
userByName(name: $name) {
|
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 (
|
return (
|
||||||
<Box
|
<Box
|
||||||
as="form"
|
as="form"
|
||||||
onSubmit={(e) => {
|
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();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -326,7 +375,7 @@ function UserSearchForm() {
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
icon={<ArrowForwardIcon />}
|
icon={<ArrowForwardIcon />}
|
||||||
aria-label="Search"
|
aria-label="Search"
|
||||||
isLoading={loading}
|
isLoading={loading1 || loading2}
|
||||||
minWidth="1.5rem"
|
minWidth="1.5rem"
|
||||||
minHeight="1.5rem"
|
minHeight="1.5rem"
|
||||||
width="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) =>
|
const buildUserClosetHangersLoader = (db) =>
|
||||||
new DataLoader(async (userIds) => {
|
new DataLoader(async (userIds) => {
|
||||||
const qs = userIds.map((_) => "?").join(",");
|
const qs = userIds.map((_) => "?").join(",");
|
||||||
|
@ -907,6 +930,7 @@ function buildLoaders(db) {
|
||||||
loaders.speciesTranslationLoader = buildSpeciesTranslationLoader(db);
|
loaders.speciesTranslationLoader = buildSpeciesTranslationLoader(db);
|
||||||
loaders.userLoader = buildUserLoader(db);
|
loaders.userLoader = buildUserLoader(db);
|
||||||
loaders.userByNameLoader = buildUserByNameLoader(db);
|
loaders.userByNameLoader = buildUserByNameLoader(db);
|
||||||
|
loaders.userByEmailLoader = buildUserByEmailLoader(db);
|
||||||
loaders.userClosetHangersLoader = buildUserClosetHangersLoader(db);
|
loaders.userClosetHangersLoader = buildUserClosetHangersLoader(db);
|
||||||
loaders.userClosetListsLoader = buildUserClosetListsLoader(db);
|
loaders.userClosetListsLoader = buildUserClosetListsLoader(db);
|
||||||
loaders.zoneLoader = buildZoneLoader(db);
|
loaders.zoneLoader = buildZoneLoader(db);
|
||||||
|
|
|
@ -41,6 +41,7 @@ const typeDefs = gql`
|
||||||
extend type Query {
|
extend type Query {
|
||||||
user(id: ID!): User
|
user(id: ID!): User
|
||||||
userByName(name: String!): User
|
userByName(name: String!): User
|
||||||
|
userByEmail(email: String!, supportSecret: String!): User
|
||||||
currentUser: User
|
currentUser: User
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -224,6 +225,19 @@ const resolvers = {
|
||||||
return { id: user.id };
|
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 }) => {
|
currentUser: async (_, __, { currentUserId, userLoader }) => {
|
||||||
if (currentUserId == null) {
|
if (currentUserId == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in a new issue