mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-04-08 03:48:14 +02:00
wip
This commit is contained in:
parent
2f8f0f01be
commit
ae15f19924
@ -493,10 +493,11 @@ export const DriveAuthSection = ({
|
||||
label="Primary Admin Email:"
|
||||
subtext="Enter the email of an admin/owner of the Google Organization that owns the Google Drive(s) you want to index."
|
||||
/>
|
||||
ss
|
||||
<div className="flex">
|
||||
<TremorButton type="submit" disabled={isSubmitting}>
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
Create Credential
|
||||
</TremorButton>
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Button } from "@/components/Button";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { PopupSpec } from "@/components/admin/connectors/Popup";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useSWRConfig } from "swr";
|
||||
@ -8,7 +8,11 @@ import { adminDeleteCredential } from "@/lib/credential";
|
||||
import { setupGmailOAuth } from "@/lib/gmail";
|
||||
import { GMAIL_AUTH_IS_ADMIN_COOKIE_NAME } from "@/lib/constants";
|
||||
import Cookies from "js-cookie";
|
||||
import { TextFormField } from "@/components/admin/connectors/Field";
|
||||
import {
|
||||
TextFormField,
|
||||
SectionHeader,
|
||||
SubLabel,
|
||||
} from "@/components/admin/connectors/Field";
|
||||
import { Form, Formik } from "formik";
|
||||
import { User } from "@/lib/types";
|
||||
import CardSection from "@/components/admin/CardSection";
|
||||
@ -20,10 +24,19 @@ import {
|
||||
import { refreshAllGoogleData } from "@/lib/googleConnector";
|
||||
import { ValidSources } from "@/lib/types";
|
||||
import { buildSimilarCredentialInfoURL } from "@/app/admin/connector/[ccPairId]/lib";
|
||||
import {
|
||||
FiFile,
|
||||
FiUpload,
|
||||
FiTrash2,
|
||||
FiCheck,
|
||||
FiLink,
|
||||
FiAlertTriangle,
|
||||
} from "react-icons/fi";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type GmailCredentialJsonTypes = "authorized_user" | "service_account";
|
||||
|
||||
const DriveJsonUpload = ({
|
||||
const GmailCredentialUpload = ({
|
||||
setPopup,
|
||||
onSuccess,
|
||||
}: {
|
||||
@ -31,129 +44,152 @@ const DriveJsonUpload = ({
|
||||
onSuccess?: () => void;
|
||||
}) => {
|
||||
const { mutate } = useSWRConfig();
|
||||
const [credentialJsonStr, setCredentialJsonStr] = useState<
|
||||
string | undefined
|
||||
>();
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [fileName, setFileName] = useState<string | undefined>();
|
||||
|
||||
const handleFileUpload = async (file: File) => {
|
||||
setIsUploading(true);
|
||||
setFileName(file.name);
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (loadEvent) => {
|
||||
if (!loadEvent?.target?.result) {
|
||||
setIsUploading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const credentialJsonStr = loadEvent.target.result as string;
|
||||
|
||||
// Check credential type
|
||||
let credentialFileType: GmailCredentialJsonTypes;
|
||||
try {
|
||||
const appCredentialJson = JSON.parse(credentialJsonStr);
|
||||
if (appCredentialJson.web) {
|
||||
credentialFileType = "authorized_user";
|
||||
} else if (appCredentialJson.type === "service_account") {
|
||||
credentialFileType = "service_account";
|
||||
} else {
|
||||
throw new Error(
|
||||
"Unknown credential type, expected one of 'OAuth Web application' or 'Service Account'"
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
setPopup({
|
||||
message: `Invalid file provided - ${e}`,
|
||||
type: "error",
|
||||
});
|
||||
setIsUploading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (credentialFileType === "authorized_user") {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/app-credential",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: credentialJsonStr,
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
setPopup({
|
||||
message: "Successfully uploaded app credentials",
|
||||
type: "success",
|
||||
});
|
||||
mutate("/api/manage/admin/connector/gmail/app-credential");
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to upload app credentials - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (credentialFileType === "service_account") {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/service-account-key",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: credentialJsonStr,
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
setPopup({
|
||||
message: "Successfully uploaded service account key",
|
||||
type: "success",
|
||||
});
|
||||
mutate("/api/manage/admin/connector/gmail/service-account-key");
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to upload service account key - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}
|
||||
setIsUploading(false);
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
className={
|
||||
"mr-3 text-sm text-text-900 border border-background-300 overflow-visible " +
|
||||
"cursor-pointer bg-background dark:text-text-400 focus:outline-none " +
|
||||
"dark:bg-background-700 dark:border-background-600 dark:placeholder-text-400"
|
||||
}
|
||||
type="file"
|
||||
accept=".json"
|
||||
onChange={(event) => {
|
||||
if (!event.target.files) {
|
||||
return;
|
||||
}
|
||||
const file = event.target.files[0];
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = function (loadEvent) {
|
||||
if (!loadEvent?.target?.result) {
|
||||
return;
|
||||
}
|
||||
const fileContents = loadEvent.target.result;
|
||||
setCredentialJsonStr(fileContents as string);
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
disabled={!credentialJsonStr}
|
||||
onClick={async () => {
|
||||
// check if the JSON is a app credential or a service account credential
|
||||
let credentialFileType: GmailCredentialJsonTypes;
|
||||
try {
|
||||
const appCredentialJson = JSON.parse(credentialJsonStr!);
|
||||
if (appCredentialJson.web) {
|
||||
credentialFileType = "authorized_user";
|
||||
} else if (appCredentialJson.type === "service_account") {
|
||||
credentialFileType = "service_account";
|
||||
} else {
|
||||
throw new Error(
|
||||
"Unknown credential type, expected one of 'OAuth Web application' or 'Service Account'"
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
setPopup({
|
||||
message: `Invalid file provided - ${e}`,
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (credentialFileType === "authorized_user") {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/app-credential",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: credentialJsonStr,
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
setPopup({
|
||||
message: "Successfully uploaded app credentials",
|
||||
type: "success",
|
||||
});
|
||||
mutate("/api/manage/admin/connector/gmail/app-credential");
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to upload app credentials - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (credentialFileType === "service_account") {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/service-account-key",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: credentialJsonStr,
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
setPopup({
|
||||
message: "Successfully uploaded service account key",
|
||||
type: "success",
|
||||
});
|
||||
mutate("/api/manage/admin/connector/gmail/service-account-key");
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to upload service account key - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
</>
|
||||
<div className="flex flex-col mt-4">
|
||||
<div className="flex items-center">
|
||||
<div className="relative flex flex-1 items-center">
|
||||
<label
|
||||
className={cn(
|
||||
"flex h-10 items-center justify-center w-full px-4 py-2 border border-dashed rounded-md transition-colors",
|
||||
isUploading
|
||||
? "opacity-70 cursor-not-allowed border-background-400 bg-background-50/30"
|
||||
: "cursor-pointer hover:bg-background-50/30 hover:border-primary dark:hover:border-primary border-background-300 dark:border-background-600"
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
{isUploading ? (
|
||||
<div className="h-4 w-4 border-t-2 border-b-2 border-primary rounded-full animate-spin"></div>
|
||||
) : (
|
||||
<FiFile className="h-4 w-4 text-text-500" />
|
||||
)}
|
||||
<span className="text-sm text-text-500">
|
||||
{isUploading
|
||||
? `Uploading ${fileName || "file"}...`
|
||||
: fileName || "Select JSON credentials file..."}
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
className="sr-only"
|
||||
type="file"
|
||||
accept=".json"
|
||||
disabled={isUploading}
|
||||
onChange={(event) => {
|
||||
if (!event.target.files?.length) {
|
||||
return;
|
||||
}
|
||||
const file = event.target.files[0];
|
||||
handleFileUpload(file);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface DriveJsonUploadSectionProps {
|
||||
interface GmailJsonUploadSectionProps {
|
||||
setPopup: (popupSpec: PopupSpec | null) => void;
|
||||
appCredentialData?: { client_id: string };
|
||||
serviceAccountCredentialData?: { service_account_email: string };
|
||||
@ -167,7 +203,7 @@ export const GmailJsonUploadSection = ({
|
||||
serviceAccountCredentialData,
|
||||
isAdmin,
|
||||
onSuccess,
|
||||
}: DriveJsonUploadSectionProps) => {
|
||||
}: GmailJsonUploadSectionProps) => {
|
||||
const { mutate } = useSWRConfig();
|
||||
const router = useRouter();
|
||||
const [localServiceAccountData, setLocalServiceAccountData] = useState(
|
||||
@ -192,154 +228,198 @@ export const GmailJsonUploadSection = ({
|
||||
|
||||
if (localServiceAccountData?.service_account_email) {
|
||||
return (
|
||||
<div className="mt-2 text-sm">
|
||||
<div>
|
||||
Found existing service account key with the following <b>Email:</b>
|
||||
<p className="italic mt-1">
|
||||
{localServiceAccountData.service_account_email}
|
||||
</p>
|
||||
</div>
|
||||
{isAdmin ? (
|
||||
<>
|
||||
<div className="mt-4 mb-1">
|
||||
If you want to update these credentials, delete the existing
|
||||
credentials through the button below, and then upload a new
|
||||
credentials JSON.
|
||||
<div>
|
||||
<SectionHeader>Gmail Service Account Credentials</SectionHeader>
|
||||
<div className="mt-4">
|
||||
<div className="py-3 px-4 bg-background-50/30 dark:bg-background-900/20 rounded">
|
||||
<div>
|
||||
<span className="text-sm text-text-500 dark:text-text-400">
|
||||
Service Account Email:
|
||||
</span>
|
||||
<p className="font-medium text-text-900 dark:text-text-100">
|
||||
{localServiceAccountData.service_account_email}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/service-account-key",
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
mutate(
|
||||
"/api/manage/admin/connector/gmail/service-account-key"
|
||||
</div>
|
||||
|
||||
{isAdmin ? (
|
||||
<div className="mt-4">
|
||||
<p className="text-sm text-text-500 dark:text-text-400 mb-3">
|
||||
If you want to update these credentials, delete the existing
|
||||
credentials below, then upload new credentials.
|
||||
</p>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={async () => {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/service-account-key",
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
// Also mutate the credential endpoints to ensure Step 2 is reset
|
||||
mutate(buildSimilarCredentialInfoURL(ValidSources.Gmail));
|
||||
setPopup({
|
||||
message: "Successfully deleted service account key",
|
||||
type: "success",
|
||||
});
|
||||
// Immediately update local state
|
||||
setLocalServiceAccountData(undefined);
|
||||
handleSuccess();
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to delete service account key - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="mt-4 mb-1">
|
||||
To change these credentials, please contact an administrator.
|
||||
if (response.ok) {
|
||||
mutate(
|
||||
"/api/manage/admin/connector/gmail/service-account-key"
|
||||
);
|
||||
// Also mutate the credential endpoints to ensure Step 2 is reset
|
||||
mutate(buildSimilarCredentialInfoURL(ValidSources.Gmail));
|
||||
setPopup({
|
||||
message: "Successfully deleted service account key",
|
||||
type: "success",
|
||||
});
|
||||
// Immediately update local state
|
||||
setLocalServiceAccountData(undefined);
|
||||
handleSuccess();
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to delete service account key - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
Delete Credentials
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
) : (
|
||||
<p className="text-sm mt-4 text-text-500 dark:text-text-400">
|
||||
To change these credentials, please contact an administrator.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (localAppCredentialData?.client_id) {
|
||||
return (
|
||||
<div className="mt-2 text-sm">
|
||||
<div>
|
||||
Found existing app credentials with the following <b>Client ID:</b>
|
||||
<p className="italic mt-1">{localAppCredentialData.client_id}</p>
|
||||
</div>
|
||||
{isAdmin ? (
|
||||
<>
|
||||
<div className="mt-4 mb-1">
|
||||
If you want to update these credentials, delete the existing
|
||||
credentials through the button below, and then upload a new
|
||||
credentials JSON.
|
||||
<div>
|
||||
<SectionHeader>Gmail OAuth Application Credentials</SectionHeader>
|
||||
<div className="mt-4">
|
||||
<div className="py-3 px-4 bg-background-50/30 dark:bg-background-900/20 rounded">
|
||||
<div className="flex items-center">
|
||||
<FiCheck className="text-green-500 h-5 w-5 mr-2" />
|
||||
<span className="font-medium">
|
||||
Found existing OAuth credentials
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<span className="text-sm text-text-500 dark:text-text-400">
|
||||
Client ID:
|
||||
</span>
|
||||
<p className="font-medium text-text-900 dark:text-text-100">
|
||||
{localAppCredentialData.client_id}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/app-credential",
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
mutate("/api/manage/admin/connector/gmail/app-credential");
|
||||
// Also mutate the credential endpoints to ensure Step 2 is reset
|
||||
mutate(buildSimilarCredentialInfoURL(ValidSources.Gmail));
|
||||
setPopup({
|
||||
message: "Successfully deleted app credentials",
|
||||
type: "success",
|
||||
});
|
||||
// Immediately update local state
|
||||
setLocalAppCredentialData(undefined);
|
||||
handleSuccess();
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to delete app credential - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<div className="mt-4 mb-1">
|
||||
To change these credentials, please contact an administrator.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isAdmin ? (
|
||||
<div className="mt-4">
|
||||
<p className="text-sm text-text-500 dark:text-text-400 mb-3">
|
||||
If you want to update these credentials, delete the existing
|
||||
credentials below, then upload new credentials.
|
||||
</p>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={async () => {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/app-credential",
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
mutate("/api/manage/admin/connector/gmail/app-credential");
|
||||
// Also mutate the credential endpoints to ensure Step 2 is reset
|
||||
mutate(buildSimilarCredentialInfoURL(ValidSources.Gmail));
|
||||
setPopup({
|
||||
message: "Successfully deleted app credentials",
|
||||
type: "success",
|
||||
});
|
||||
// Immediately update local state
|
||||
setLocalAppCredentialData(undefined);
|
||||
handleSuccess();
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to delete app credential - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
Delete Credentials
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm mt-4 text-text-500 dark:text-text-400">
|
||||
To change these credentials, please contact an administrator.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!isAdmin) {
|
||||
return (
|
||||
<div className="mt-2">
|
||||
<p className="text-sm mb-2">
|
||||
Curators are unable to set up the Gmail credentials. To add a Gmail
|
||||
connector, please contact an administrator.
|
||||
</p>
|
||||
<div>
|
||||
<div className="flex items-start py-3 px-4 bg-yellow-50/30 dark:bg-yellow-900/5 rounded">
|
||||
<FiAlertTriangle className="text-yellow-500 h-5 w-5 mr-2 mt-0.5 flex-shrink-0" />
|
||||
<p className="text-sm">
|
||||
Curators are unable to set up the Gmail credentials. To add a Gmail
|
||||
connector, please contact an administrator.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-2">
|
||||
<p className="text-sm mb-2">
|
||||
Follow the guide{" "}
|
||||
<a
|
||||
className="text-link"
|
||||
target="_blank"
|
||||
href="https://docs.onyx.app/connectors/gmail#authorization"
|
||||
rel="noreferrer"
|
||||
>
|
||||
here
|
||||
</a>{" "}
|
||||
to either (1) setup a Google OAuth App in your company workspace or (2)
|
||||
create a Service Account.
|
||||
<br />
|
||||
<br />
|
||||
Download the credentials JSON if choosing option (1) or the Service
|
||||
Account key JSON if choosing option (2), and upload it here.
|
||||
</p>
|
||||
<DriveJsonUpload setPopup={setPopup} onSuccess={handleSuccess} />
|
||||
<div>
|
||||
<SectionHeader>Setup Gmail Credentials</SectionHeader>
|
||||
<div className="mt-4">
|
||||
<p className="text-sm mb-3">
|
||||
Follow these steps to connect your Gmail:
|
||||
</p>
|
||||
<ol className="list-decimal list-inside text-sm space-y-2">
|
||||
<li>
|
||||
<span className="font-medium">Create credentials</span> - You have
|
||||
two options:
|
||||
<ul className="list-disc list-inside ml-4 mt-1 text-text-500 dark:text-text-400">
|
||||
<li>Set up a Google OAuth App in your company workspace</li>
|
||||
<li>Create a Service Account with appropriate permissions</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-medium">Download credentials</span> - Save the
|
||||
JSON file to your computer
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-medium">Upload credentials</span> - Select the
|
||||
JSON file below to automatically upload
|
||||
</li>
|
||||
</ol>
|
||||
<div className="mt-3 mb-4">
|
||||
<a
|
||||
className="text-primary hover:text-primary/80 flex items-center gap-1 text-sm"
|
||||
target="_blank"
|
||||
href="https://docs.onyx.app/connectors/gmail#authorization"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<FiLink className="h-3 w-3" />
|
||||
View detailed setup instructions
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<GmailCredentialUpload setPopup={setPopup} onSuccess={handleSuccess} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface DriveCredentialSectionProps {
|
||||
interface GmailCredentialSectionProps {
|
||||
gmailPublicCredential?: Credential<GmailCredentialJson>;
|
||||
gmailServiceAccountCredential?: Credential<GmailServiceAccountCredentialJson>;
|
||||
serviceAccountKeyData?: { service_account_email: string };
|
||||
@ -387,7 +467,7 @@ export const GmailAuthSection = ({
|
||||
refreshCredentials,
|
||||
connectorExists,
|
||||
user,
|
||||
}: DriveCredentialSectionProps) => {
|
||||
}: GmailCredentialSectionProps) => {
|
||||
const router = useRouter();
|
||||
const [isAuthenticating, setIsAuthenticating] = useState(false);
|
||||
const [localServiceAccountData, setLocalServiceAccountData] = useState(
|
||||
@ -420,144 +500,179 @@ export const GmailAuthSection = ({
|
||||
localGmailPublicCredential || localGmailServiceAccountCredential;
|
||||
if (existingCredential) {
|
||||
return (
|
||||
<>
|
||||
<p className="mb-2 text-sm">
|
||||
<i>Uploaded and authenticated credential already exists!</i>
|
||||
</p>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
handleRevokeAccess(
|
||||
connectorExists,
|
||||
setPopup,
|
||||
existingCredential,
|
||||
refreshCredentials
|
||||
);
|
||||
}}
|
||||
>
|
||||
Revoke Access
|
||||
</Button>
|
||||
</>
|
||||
<div>
|
||||
<SectionHeader>Gmail Authentication Status</SectionHeader>
|
||||
<div className="mt-4">
|
||||
<div className="py-3 px-4 bg-green-50/30 dark:bg-green-900/5 rounded mb-4 flex items-start">
|
||||
<FiCheck className="text-green-500 h-5 w-5 mr-2 mt-0.5 flex-shrink-0" />
|
||||
<div>
|
||||
<span className="font-medium">Authentication Complete</span>
|
||||
<p className="text-sm mt-1 text-text-500 dark:text-text-400">
|
||||
Your Gmail credentials have been uploaded and authenticated
|
||||
successfully.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={async () => {
|
||||
handleRevokeAccess(
|
||||
connectorExists,
|
||||
setPopup,
|
||||
existingCredential,
|
||||
refreshCredentials
|
||||
);
|
||||
}}
|
||||
>
|
||||
Revoke Access
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (localServiceAccountData?.service_account_email) {
|
||||
return (
|
||||
<div>
|
||||
<Formik
|
||||
initialValues={{
|
||||
google_primary_admin: user?.email || "",
|
||||
}}
|
||||
validationSchema={Yup.object().shape({
|
||||
google_primary_admin: Yup.string()
|
||||
.email("Must be a valid email")
|
||||
.required("Required"),
|
||||
})}
|
||||
onSubmit={async (values, formikHelpers) => {
|
||||
formikHelpers.setSubmitting(true);
|
||||
try {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/service-account-credential",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
google_primary_admin: values.google_primary_admin,
|
||||
}),
|
||||
}
|
||||
);
|
||||
<SectionHeader>Complete Gmail Authentication</SectionHeader>
|
||||
<div className="mt-4">
|
||||
<div className="py-3 px-4 bg-background-50/30 dark:bg-background-900/20 rounded mb-4">
|
||||
<p className="text-sm">
|
||||
Enter the email of an admin/owner of the Google Organization that
|
||||
owns the Gmail account(s) you want to index.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
if (response.ok) {
|
||||
<Formik
|
||||
initialValues={{
|
||||
google_primary_admin: user?.email || "",
|
||||
}}
|
||||
validationSchema={Yup.object().shape({
|
||||
google_primary_admin: Yup.string()
|
||||
.email("Must be a valid email")
|
||||
.required("Required"),
|
||||
})}
|
||||
onSubmit={async (values, formikHelpers) => {
|
||||
formikHelpers.setSubmitting(true);
|
||||
try {
|
||||
const response = await fetch(
|
||||
"/api/manage/admin/connector/gmail/service-account-credential",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
google_primary_admin: values.google_primary_admin,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
if (response.ok) {
|
||||
setPopup({
|
||||
message: "Successfully created service account credential",
|
||||
type: "success",
|
||||
});
|
||||
refreshCredentials();
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to create service account credential - ${errorMsg}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
setPopup({
|
||||
message: "Successfully created service account credential",
|
||||
type: "success",
|
||||
});
|
||||
refreshCredentials();
|
||||
} else {
|
||||
const errorMsg = await response.text();
|
||||
setPopup({
|
||||
message: `Failed to create service account credential - ${errorMsg}`,
|
||||
message: `Failed to create service account credential - ${error}`,
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
formikHelpers.setSubmitting(false);
|
||||
}
|
||||
} catch (error) {
|
||||
setPopup({
|
||||
message: `Failed to create service account credential - ${error}`,
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
formikHelpers.setSubmitting(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting }) => (
|
||||
<Form>
|
||||
<TextFormField
|
||||
name="google_primary_admin"
|
||||
label="Primary Admin Email:"
|
||||
subtext="Enter the email of an admin/owner of the Google Organization that owns the Gmail account(s) you want to index."
|
||||
/>
|
||||
<div className="flex">
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
Create Credential
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting }) => (
|
||||
<Form className="space-y-4">
|
||||
<TextFormField
|
||||
name="google_primary_admin"
|
||||
label="Primary Admin Email:"
|
||||
subtext="Enter the email of an admin/owner of the Google Organization that owns the Gmail account(s) you want to index."
|
||||
/>
|
||||
<div className="flex">
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
{isSubmitting ? "Creating..." : "Create Credential"}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (localAppCredentialData?.client_id) {
|
||||
return (
|
||||
<div className="text-sm mb-4">
|
||||
<p className="mb-2">
|
||||
Next, you must provide credentials via OAuth. This gives us read
|
||||
access to the emails you have access to in your Gmail account.
|
||||
</p>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
setIsAuthenticating(true);
|
||||
try {
|
||||
Cookies.set(GMAIL_AUTH_IS_ADMIN_COOKIE_NAME, "true", {
|
||||
path: "/",
|
||||
});
|
||||
const [authUrl, errorMsg] = await setupGmailOAuth({
|
||||
isAdmin: true,
|
||||
});
|
||||
<div>
|
||||
<SectionHeader>Complete Gmail Authentication</SectionHeader>
|
||||
<div className="mt-4">
|
||||
<div className="py-3 px-4 bg-background-50/30 dark:bg-background-900/20 rounded mb-4">
|
||||
<p className="text-sm">
|
||||
Next, you need to authenticate with Gmail via OAuth. This gives us
|
||||
read access to the emails you have access to in your Gmail
|
||||
account.
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
disabled={isAuthenticating}
|
||||
onClick={async () => {
|
||||
setIsAuthenticating(true);
|
||||
try {
|
||||
Cookies.set(GMAIL_AUTH_IS_ADMIN_COOKIE_NAME, "true", {
|
||||
path: "/",
|
||||
});
|
||||
const [authUrl, errorMsg] = await setupGmailOAuth({
|
||||
isAdmin: true,
|
||||
});
|
||||
|
||||
if (authUrl) {
|
||||
router.push(authUrl);
|
||||
} else {
|
||||
if (authUrl) {
|
||||
router.push(authUrl);
|
||||
} else {
|
||||
setPopup({
|
||||
message: errorMsg,
|
||||
type: "error",
|
||||
});
|
||||
setIsAuthenticating(false);
|
||||
}
|
||||
} catch (error) {
|
||||
setPopup({
|
||||
message: errorMsg,
|
||||
message: `Failed to authenticate with Gmail - ${error}`,
|
||||
type: "error",
|
||||
});
|
||||
setIsAuthenticating(false);
|
||||
}
|
||||
} catch (error) {
|
||||
setPopup({
|
||||
message: `Failed to authenticate with Gmail - ${error}`,
|
||||
type: "error",
|
||||
});
|
||||
setIsAuthenticating(false);
|
||||
}
|
||||
}}
|
||||
disabled={isAuthenticating}
|
||||
>
|
||||
{isAuthenticating ? "Authenticating..." : "Authenticate with Gmail"}
|
||||
</Button>
|
||||
}}
|
||||
>
|
||||
{isAuthenticating ? "Authenticating..." : "Authenticate with Gmail"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// case where no keys have been uploaded in step 1
|
||||
return (
|
||||
<p className="text-sm">
|
||||
Please upload either a OAuth Client Credential JSON or a Gmail Service
|
||||
Account Key JSON in Step 1 before moving onto Step 2.
|
||||
</p>
|
||||
<div>
|
||||
<SectionHeader>Gmail Authentication</SectionHeader>
|
||||
<div className="mt-4">
|
||||
<div className="flex items-start py-3 px-4 bg-yellow-50/30 dark:bg-yellow-900/5 rounded">
|
||||
<FiAlertTriangle className="text-yellow-500 h-5 w-5 mr-2 mt-0.5 flex-shrink-0" />
|
||||
<p className="text-sm">
|
||||
Please upload either an OAuth Client Credential JSON or a Gmail
|
||||
Service Account Key JSON first before authenticating.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user