diff --git a/functions/src/admin/getUserEmail.ts b/functions/src/admin/getUserEmail.ts new file mode 100644 index 0000000000..192bf1711d --- /dev/null +++ b/functions/src/admin/getUserEmail.ts @@ -0,0 +1,26 @@ +import * as functions from 'firebase-functions' +import { auth } from 'firebase-admin' + +/** + * For requests coming from authenticated admins, request the email + * for another user (not stored in DB so pulled from auth system) + */ +export const getUserEmail = functions.https.onCall(async (data, context) => { + if (!context.auth) { + // Throwing an HttpsError so that the client gets the error details. + throw new functions.https.HttpsError( + 'failed-precondition', + 'The function must be called ' + 'while authenticated.', + ) + } + const { uid } = data + // TODO - add server-side auth to check request coming from admin + // (does still check clientside) + try { + const { email } = await auth().getUser(uid) + return email + } catch (error) { + console.error(error) + throw new functions.https.HttpsError('not-found', JSON.stringify(error)) + } +}) diff --git a/functions/src/admin/index.ts b/functions/src/admin/index.ts new file mode 100644 index 0000000000..b9f1c6592c --- /dev/null +++ b/functions/src/admin/index.ts @@ -0,0 +1,6 @@ +/* +Admin functions are designed to be called from the frontend by +administrators +*/ + +export * from './getUserEmail' diff --git a/functions/src/index.ts b/functions/src/index.ts index ff3c29061c..fa9c8b086e 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -5,6 +5,7 @@ import * as IntegrationsSlack from './Integrations/firebase-slack' import * as IntegrationsDiscord from './Integrations/firebase-discord' import { FirebaseUserBackup } from './Integrations/firebase-userBackup' import * as IntegrationsEmail from './Integrations/firebase-email' +import * as Admin from './admin' // the following endpoints are exposed for use by various triggers // see individual files for more informaiton @@ -22,3 +23,6 @@ exports.notifyHowToAccepted = IntegrationsDiscord.notifyHowToAccepted exports.notifyEventAccepted = IntegrationsDiscord.notifyEventAccepted exports.firebaseUserBackup = FirebaseUserBackup exports.emailNotificationDemo = IntegrationsEmail.notifyEmailDemo +// CC Note, 2020-04-40 +// folder-based naming conventions should be encourage from now on +exports.adminGetUserEmail = Admin.getUserEmail diff --git a/src/components/AdminContact/AdminContact.tsx b/src/components/AdminContact/AdminContact.tsx new file mode 100644 index 0000000000..fa6b7313f1 --- /dev/null +++ b/src/components/AdminContact/AdminContact.tsx @@ -0,0 +1,38 @@ +import * as React from 'react' +import { inject, observer } from 'mobx-react' +import { Button } from 'src/components/Button' +import { AdminStore } from 'src/stores/Admin/admin.store' +import { IUser } from 'src/models/user.models' + +/* + Button to request a user's email from the firebase auth database and open in default mail client +*/ + +interface IProps { + user: IUser + adminStore?: AdminStore +} +interface IState { + disabled: boolean +} +@inject('adminStore') +@observer +export class AdminContact extends React.Component { + constructor(props: IProps) { + super(props) + this.state = { disabled: false } + } + getUserEmail = async () => { + this.setState({ disabled: true }) + const email = await this.props.adminStore!.getUserEmail(this.props.user) + this.setState({ disabled: false }) + window.location.href = `mailto:${email}` + } + public render() { + return ( + + ) + } +} diff --git a/src/pages/User/content/UserPage/UserPage.tsx b/src/pages/User/content/UserPage/UserPage.tsx index a919f27a43..bf96c34496 100644 --- a/src/pages/User/content/UserPage/UserPage.tsx +++ b/src/pages/User/content/UserPage/UserPage.tsx @@ -53,6 +53,8 @@ import PPLogo from 'src/assets/images/precious-plastic-logo-official.svg' import { IUploadedFileMeta } from 'src/stores/storage' import { IConvertedFileMeta } from 'src/components/ImageInput/ImageInput' import { Loader } from 'src/components/Loader' +import { AuthWrapper } from 'src/components/Auth/AuthWrapper' +import { AdminContact } from 'src/components/AdminContact/AdminContact' interface IRouterCustomParams { id: string @@ -550,6 +552,11 @@ export class UserPage extends React.Component< {this.renderLinks(user.links)} )} + + + + + ('v3_users')