mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-09-26 20:08:38 +02:00
Associate a user with web/file connectors
This commit is contained in:
@@ -7,7 +7,7 @@ import { FileIcon } from "@/components/icons/icons";
|
|||||||
import { fetcher } from "@/lib/fetcher";
|
import { fetcher } from "@/lib/fetcher";
|
||||||
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
||||||
import { ConnectorIndexingStatus, FileConfig } from "@/lib/types";
|
import { ConnectorIndexingStatus, FileConfig } from "@/lib/types";
|
||||||
import { linkCredential } from "@/lib/credential";
|
import { createCredential, linkCredential } from "@/lib/credential";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { createConnector, runConnector } from "@/lib/connector";
|
import { createConnector, runConnector } from "@/lib/connector";
|
||||||
@@ -125,9 +125,28 @@ const Main = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since there is no "real" credential associated with a file connector
|
||||||
|
// we create a dummy one here so that we can associate the CC Pair with a
|
||||||
|
// user. This is needed since the user for a CC Pair is found via the credential
|
||||||
|
// associated with it.
|
||||||
|
const createCredentialResponse = await createCredential({
|
||||||
|
credential_json: {},
|
||||||
|
admin_public: true,
|
||||||
|
});
|
||||||
|
if (!createCredentialResponse.ok) {
|
||||||
|
const errorMsg = await createCredentialResponse.text();
|
||||||
|
setPopup({
|
||||||
|
message: `Error creating credential for CC Pair - ${errorMsg}`,
|
||||||
|
type: "error",
|
||||||
|
});
|
||||||
|
formikHelpers.setSubmitting(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const credentialId = (await createCredentialResponse.json()).id;
|
||||||
|
|
||||||
const credentialResponse = await linkCredential(
|
const credentialResponse = await linkCredential(
|
||||||
connector.id,
|
connector.id,
|
||||||
0,
|
credentialId,
|
||||||
values.name
|
values.name
|
||||||
);
|
);
|
||||||
if (!credentialResponse.ok) {
|
if (!credentialResponse.ok) {
|
||||||
|
@@ -18,6 +18,7 @@ import { HealthCheckBanner } from "@/components/health/healthcheck";
|
|||||||
import { ConnectorIndexingStatus, WebConfig } from "@/lib/types";
|
import { ConnectorIndexingStatus, WebConfig } from "@/lib/types";
|
||||||
import { ConnectorsTable } from "@/components/admin/connectors/table/ConnectorsTable";
|
import { ConnectorsTable } from "@/components/admin/connectors/table/ConnectorsTable";
|
||||||
import { ConnectorForm } from "@/components/admin/connectors/ConnectorForm";
|
import { ConnectorForm } from "@/components/admin/connectors/ConnectorForm";
|
||||||
|
import { createCredential, linkCredential } from "@/lib/credential";
|
||||||
|
|
||||||
const SCRAPE_TYPE_TO_PRETTY_NAME = {
|
const SCRAPE_TYPE_TO_PRETTY_NAME = {
|
||||||
recursive: "Recursive",
|
recursive: "Recursive",
|
||||||
@@ -62,7 +63,11 @@ export default function Web() {
|
|||||||
<ConnectorForm<WebConfig>
|
<ConnectorForm<WebConfig>
|
||||||
nameBuilder={(values) => `WebConnector-${values.base_url}`}
|
nameBuilder={(values) => `WebConnector-${values.base_url}`}
|
||||||
ccPairNameBuilder={(values) => values.base_url}
|
ccPairNameBuilder={(values) => values.base_url}
|
||||||
credentialId={0} // 0 is the ID of the default public credential
|
// Since there is no "real" credential associated with a web connector
|
||||||
|
// we create a dummy one here so that we can associate the CC Pair with a
|
||||||
|
// user. This is needed since the user for a CC Pair is found via the credential
|
||||||
|
// associated with it.
|
||||||
|
shouldCreateEmptyCredentialForConnector={true}
|
||||||
source="web"
|
source="web"
|
||||||
inputType="load_state"
|
inputType="load_state"
|
||||||
formBody={
|
formBody={
|
||||||
|
@@ -11,7 +11,7 @@ import {
|
|||||||
import { deleteConnectorIfExistsAndIsUnlinked } from "@/lib/connector";
|
import { deleteConnectorIfExistsAndIsUnlinked } from "@/lib/connector";
|
||||||
import { FormBodyBuilder, RequireAtLeastOne } from "./types";
|
import { FormBodyBuilder, RequireAtLeastOne } from "./types";
|
||||||
import { TextFormField } from "./Field";
|
import { TextFormField } from "./Field";
|
||||||
import { linkCredential } from "@/lib/credential";
|
import { createCredential, linkCredential } from "@/lib/credential";
|
||||||
import { useSWRConfig } from "swr";
|
import { useSWRConfig } from "swr";
|
||||||
|
|
||||||
const BASE_CONNECTOR_URL = "/api/manage/admin/connector";
|
const BASE_CONNECTOR_URL = "/api/manage/admin/connector";
|
||||||
@@ -57,7 +57,8 @@ interface BaseProps<T extends Yup.AnyObject> {
|
|||||||
ccPairNameBuilder?: (values: T) => string | null;
|
ccPairNameBuilder?: (values: T) => string | null;
|
||||||
source: ValidSources;
|
source: ValidSources;
|
||||||
inputType: ValidInputTypes;
|
inputType: ValidInputTypes;
|
||||||
credentialId?: number; // if specified, will automatically try and link the credential
|
// if specified, will automatically try and link the credential
|
||||||
|
credentialId?: number;
|
||||||
// If both are specified, will render formBody and then formBodyBuilder
|
// If both are specified, will render formBody and then formBodyBuilder
|
||||||
formBody?: JSX.Element | null;
|
formBody?: JSX.Element | null;
|
||||||
formBodyBuilder?: FormBodyBuilder<T>;
|
formBodyBuilder?: FormBodyBuilder<T>;
|
||||||
@@ -68,6 +69,9 @@ interface BaseProps<T extends Yup.AnyObject> {
|
|||||||
responseJson: Connector<T> | undefined
|
responseJson: Connector<T> | undefined
|
||||||
) => void;
|
) => void;
|
||||||
refreshFreq?: number;
|
refreshFreq?: number;
|
||||||
|
// If specified, then we will create an empty credential and associate
|
||||||
|
// the connector with it. If credentialId is specified, then this will be ignored
|
||||||
|
shouldCreateEmptyCredentialForConnector?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConnectorFormProps<T extends Yup.AnyObject> = RequireAtLeastOne<
|
type ConnectorFormProps<T extends Yup.AnyObject> = RequireAtLeastOne<
|
||||||
@@ -87,6 +91,7 @@ export function ConnectorForm<T extends Yup.AnyObject>({
|
|||||||
initialValues,
|
initialValues,
|
||||||
refreshFreq,
|
refreshFreq,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
shouldCreateEmptyCredentialForConnector,
|
||||||
}: ConnectorFormProps<T>): JSX.Element {
|
}: ConnectorFormProps<T>): JSX.Element {
|
||||||
const { mutate } = useSWRConfig();
|
const { mutate } = useSWRConfig();
|
||||||
const { popup, setPopup } = usePopup();
|
const { popup, setPopup } = usePopup();
|
||||||
@@ -147,13 +152,35 @@ export function ConnectorForm<T extends Yup.AnyObject>({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (credentialId !== undefined) {
|
let credentialIdToLinkTo = credentialId;
|
||||||
|
// create empty credential if specified
|
||||||
|
if (
|
||||||
|
shouldCreateEmptyCredentialForConnector &&
|
||||||
|
credentialIdToLinkTo === undefined
|
||||||
|
) {
|
||||||
|
const createCredentialResponse = await createCredential({
|
||||||
|
credential_json: {},
|
||||||
|
admin_public: true,
|
||||||
|
});
|
||||||
|
if (!createCredentialResponse.ok) {
|
||||||
|
const errorMsg = await createCredentialResponse.text();
|
||||||
|
setPopup({
|
||||||
|
message: `Error creating credential for CC Pair - ${errorMsg}`,
|
||||||
|
type: "error",
|
||||||
|
});
|
||||||
|
formikHelpers.setSubmitting(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
credentialIdToLinkTo = (await createCredentialResponse.json()).id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (credentialIdToLinkTo !== undefined) {
|
||||||
const ccPairName = ccPairNameBuilder
|
const ccPairName = ccPairNameBuilder
|
||||||
? ccPairNameBuilder(values)
|
? ccPairNameBuilder(values)
|
||||||
: values.cc_pair_name;
|
: values.cc_pair_name;
|
||||||
const linkCredentialResponse = await linkCredential(
|
const linkCredentialResponse = await linkCredential(
|
||||||
response.id,
|
response.id,
|
||||||
credentialId,
|
credentialIdToLinkTo,
|
||||||
ccPairName
|
ccPairName
|
||||||
);
|
);
|
||||||
if (!linkCredentialResponse.ok) {
|
if (!linkCredentialResponse.ok) {
|
||||||
|
@@ -3,20 +3,14 @@ import { Formik, Form } from "formik";
|
|||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { Popup } from "./Popup";
|
import { Popup } from "./Popup";
|
||||||
import { CredentialBase } from "@/lib/types";
|
import { CredentialBase } from "@/lib/types";
|
||||||
|
import { createCredential } from "@/lib/credential";
|
||||||
|
|
||||||
export async function submitCredential<T>(
|
export async function submitCredential<T>(
|
||||||
connector: CredentialBase<T>
|
credential: CredentialBase<T>
|
||||||
): Promise<{ message: string; isSuccess: boolean }> {
|
): Promise<{ message: string; isSuccess: boolean }> {
|
||||||
let isSuccess = false;
|
let isSuccess = false;
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/manage/credential`, {
|
const response = await createCredential(credential);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(connector),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
isSuccess = true;
|
isSuccess = true;
|
||||||
return { message: "Success!", isSuccess: true };
|
return { message: "Success!", isSuccess: true };
|
||||||
|
@@ -1,3 +1,15 @@
|
|||||||
|
import { CredentialBase } from "./types";
|
||||||
|
|
||||||
|
export async function createCredential(credential: CredentialBase<any>) {
|
||||||
|
return await fetch(`/api/manage/credential`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(credential),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function adminDeleteCredential<T>(credentialId: number) {
|
export async function adminDeleteCredential<T>(credentialId: number) {
|
||||||
return await fetch(`/api/manage/admin/credential/${credentialId}`, {
|
return await fetch(`/api/manage/admin/credential/${credentialId}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
|
Reference in New Issue
Block a user