mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-06-18 03:50:58 +02:00
Prepare EE to merge with MIT
This commit is contained in:
parent
f0b2b57d81
commit
1ee8ee9e8b
@ -5,6 +5,9 @@ on:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
REGISTRY_IMAGE: danswer/danswer-backend
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
# for EE, run on special image-builders runners
|
||||
@ -33,8 +36,8 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
danswer/danswer-ee-backend:${{ github.ref_name }}
|
||||
danswer/danswer-ee-backend:latest
|
||||
${{ env.REGISTRY_IMAGE }}:${{ github.ref_name }}
|
||||
${{ env.REGISTRY_IMAGE }}:latest
|
||||
build-args: |
|
||||
DANSWER_VERSION=${{ github.ref_name }}
|
||||
|
||||
@ -42,6 +45,6 @@ jobs:
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
# To run locally: trivy image --severity HIGH,CRITICAL danswer/danswer-backend
|
||||
image-ref: docker.io/danswer/danswer-backend:${{ github.ref_name }}
|
||||
image-ref: docker.io/${{ env.REGISTRY_IMAGE }}:${{ github.ref_name }}
|
||||
severity: 'CRITICAL,HIGH'
|
||||
trivyignores: ./backend/.trivyignore
|
||||
|
@ -6,7 +6,7 @@ on:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
REGISTRY_IMAGE: danswer/danswer-ee-web-server
|
||||
REGISTRY_IMAGE: danswer/danswer-web-server
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@ -34,8 +34,8 @@ jobs:
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: |
|
||||
type=raw,value=danswer/danswer-ee-web-server:${{ github.ref_name }}
|
||||
type=raw,value=danswer/danswer-ee-web-server:latest
|
||||
type=raw,value=${{ env.REGISTRY_IMAGE }}:${{ github.ref_name }}
|
||||
type=raw,value=${{ env.REGISTRY_IMAGE }}:latest
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@ -56,7 +56,6 @@ jobs:
|
||||
push: true
|
||||
build-args: |
|
||||
DANSWER_VERSION=${{ github.ref_name }}
|
||||
NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES=true
|
||||
# needed due to weird interactions with the builds for different platforms
|
||||
no-cache: true
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
4
.github/workflows/docker-tag-latest.yml
vendored
4
.github/workflows/docker-tag-latest.yml
vendored
@ -25,8 +25,8 @@ jobs:
|
||||
|
||||
- name: Pull, Tag and Push Web Server Image
|
||||
run: |
|
||||
docker buildx imagetools create -t danswer/danswer-ee-web-server:latest danswer/danswer-ee-web-server:${{ github.event.inputs.version }}
|
||||
docker buildx imagetools create -t danswer/danswer-web-server:latest danswer/danswer-web-server:${{ github.event.inputs.version }}
|
||||
|
||||
- name: Pull, Tag and Push API Server Image
|
||||
run: |
|
||||
docker buildx imagetools create -t danswer/danswer-ee-backend:latest danswer/danswer-ee-backend:${{ github.event.inputs.version }}
|
||||
docker buildx imagetools create -t danswer/danswer-backend:latest danswer/danswer-backend:${{ github.event.inputs.version }}
|
||||
|
2
.vscode/env_template.txt
vendored
2
.vscode/env_template.txt
vendored
@ -23,7 +23,7 @@ REQUIRE_EMAIL_VERIFICATION=False
|
||||
|
||||
|
||||
# Toggles on/off the EE Features
|
||||
NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES=False
|
||||
ENABLE_PAID_EE_FEATURES=False
|
||||
|
||||
|
||||
# Set these so if you wipe the DB, you don't end up having to go through the UI every time
|
||||
|
@ -152,13 +152,13 @@ python ./scripts/dev_run_background_jobs.py
|
||||
|
||||
To run the backend API server, navigate back to `danswer/backend` and run:
|
||||
```bash
|
||||
AUTH_TYPE=disabled uvicorn ee.danswer.main:app --reload --port 8080
|
||||
AUTH_TYPE=disabled uvicorn danswer.main:app --reload --port 8080
|
||||
```
|
||||
_For Windows (for compatibility with both PowerShell and Command Prompt):_
|
||||
```bash
|
||||
powershell -Command "
|
||||
$env:AUTH_TYPE='disabled'
|
||||
uvicorn ee.danswer.main:app --reload --port 8080
|
||||
uvicorn danswer.main:app --reload --port 8080
|
||||
"
|
||||
```
|
||||
|
||||
|
4
LICENSE
4
LICENSE
@ -1,8 +1,8 @@
|
||||
Copyright (c) 2023 DanswerAI, Inc.
|
||||
Copyright (c) 2023-present DanswerAI, Inc.
|
||||
|
||||
Portions of this software are licensed as follows:
|
||||
|
||||
* All content that resides under "ee" directories of this repository, if that directory exists, is licensed under the license defined in "backend/ee/LICENSE".
|
||||
* All content that resides under "ee" directories of this repository, if that directory exists, is licensed under the license defined in "backend/ee/LICENSE". Specifically all content under "backend/ee" and "web/src/app/ee" is licensed under the license defined in "backend/ee/LICENSE".
|
||||
* All third party components incorporated into the Danswer Software are licensed under the original license provided by the owner of the applicable component.
|
||||
* Content outside of the above mentioned directories or restrictions above is available under the "MIT Expat" license as defined below.
|
||||
|
||||
|
20
README.md
20
README.md
@ -105,5 +105,25 @@ Efficiently pulls the latest changes from:
|
||||
* Websites
|
||||
* And more ...
|
||||
|
||||
## 📚 Editions
|
||||
|
||||
There are two editions of Danswer:
|
||||
|
||||
* Danswer Community Edition (CE) is available freely under the MIT Expat license. This version has ALL the core features discussed above. This is the version of Danswer you will get if you follow the Deployment guide above.
|
||||
* Danswer Enterprise Edition (EE) includes extra features that are primarily useful for larger organizations. Specifically, this includes:
|
||||
* Single Sign-On (SSO), with support for both SAML and OIDC
|
||||
* Role-based access control
|
||||
* Document permission inheritance from connected sources
|
||||
* Admin usage analytics / global query history
|
||||
* Whitelabeling
|
||||
* API key authentication
|
||||
* Encryption of secrets
|
||||
* Any many more! Checkout [our website](https://www.danswer.ai/) for the latest.
|
||||
|
||||
To try the Danswer Enterprise Edition:
|
||||
|
||||
1. Checkout our [Cloud product](https://app.danswer.ai/signup).
|
||||
2. For self-hosting, contact us at [founders@danswer.ai](mailto:founders@danswer.ai) or book a call with us on our [Cal](https://cal.com/team/danswer/founders).
|
||||
|
||||
## 💡 Contributing
|
||||
Looking to contribute? Please check out the [Contribution Guide](CONTRIBUTING.md) for more details.
|
||||
|
@ -1,11 +1,11 @@
|
||||
FROM python:3.11.7-slim-bookworm
|
||||
|
||||
LABEL com.danswer.maintainer="founders@danswer.ai"
|
||||
LABEL com.danswer.description="This image is the Enterprise Edition (Paid Edition) backend of \
|
||||
Danswer. If you do not have a contract or agreement with DanswerAI, you are not permitted to use \
|
||||
this container outside of personal development or testing purposes. Please reach out to \
|
||||
founders@danswer.ai for more information. You can access the MIT version of Danswer at \
|
||||
https://github.com/danswer-ai/danswer"
|
||||
LABEL com.danswer.description="This image is the web/frontend container of Danswer which \
|
||||
contains code for both the Community and Enterprise editions of Danswer. If you do not \
|
||||
have a contract or agreement with DanswerAI, you are not permitted to use the Enterprise \
|
||||
Edition features outside of personal development or testing purposes. Please reach out to \
|
||||
founders@danswer.ai for more information. Please visit https://github.com/danswer-ai/danswer"
|
||||
|
||||
# Default DANSWER_VERSION, typically overriden during builds by GitHub Actions.
|
||||
ARG DANSWER_VERSION=0.3-dev
|
||||
@ -18,20 +18,33 @@ RUN echo "DANSWER_VERSION: ${DANSWER_VERSION}"
|
||||
# curl included just for users' convenience
|
||||
# zip for Vespa step futher down
|
||||
# ca-certificates for HTTPS
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y cmake curl zip ca-certificates libgnutls30=3.7.9-2+deb12u2 \
|
||||
libblkid1=2.38.1-5+deb12u1 libmount1=2.38.1-5+deb12u1 libsmartcols1=2.38.1-5+deb12u1 \
|
||||
libuuid1=2.38.1-5+deb12u1 && \
|
||||
apt-get install -y \
|
||||
cmake \
|
||||
curl \
|
||||
zip \
|
||||
ca-certificates \
|
||||
libgnutls30=3.7.9-2+deb12u2 \
|
||||
libblkid1=2.38.1-5+deb12u1 \
|
||||
libmount1=2.38.1-5+deb12u1 \
|
||||
libsmartcols1=2.38.1-5+deb12u1 \
|
||||
libuuid1=2.38.1-5+deb12u1 \
|
||||
libxmlsec1-dev \
|
||||
pkg-config \
|
||||
gcc && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
apt-get clean
|
||||
|
||||
# Install Python dependencies
|
||||
# Remove py which is pulled in by retry, py is not needed and is a CVE
|
||||
COPY ./requirements/default.txt /tmp/requirements.txt
|
||||
RUN pip install --no-cache-dir --upgrade -r /tmp/requirements.txt && \
|
||||
COPY ./requirements/ee.txt /tmp/ee-requirements.txt
|
||||
RUN pip install --no-cache-dir --upgrade \
|
||||
-r /tmp/requirements.txt \
|
||||
-r /tmp/ee-requirements.txt && \
|
||||
pip uninstall -y py && \
|
||||
playwright install chromium && playwright install-deps chromium && \
|
||||
playwright install chromium && \
|
||||
playwright install-deps chromium && \
|
||||
ln -s /usr/local/bin/supervisord /usr/bin/supervisord
|
||||
|
||||
# Cleanup for CVEs and size reduction
|
||||
@ -39,21 +52,20 @@ RUN pip install --no-cache-dir --upgrade -r /tmp/requirements.txt && \
|
||||
# xserver-common and xvfb included by playwright installation but not needed after
|
||||
# perl-base is part of the base Python Debian image but not needed for Danswer functionality
|
||||
# perl-base could only be removed with --allow-remove-essential
|
||||
RUN apt-get remove -y --allow-remove-essential perl-base xserver-common xvfb cmake \
|
||||
libldap-2.5-0 libldap-2.5-0 && \
|
||||
RUN apt-get update && \
|
||||
apt-get remove -y --allow-remove-essential \
|
||||
perl-base \
|
||||
xserver-common \
|
||||
xvfb \
|
||||
cmake \
|
||||
libldap-2.5-0 \
|
||||
libxmlsec1-dev \
|
||||
pkg-config \
|
||||
gcc && \
|
||||
apt-get install -y libxmlsec1-openssl && \
|
||||
apt-get autoremove -y && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
rm /usr/local/lib/python3.11/site-packages/tornado/test/test.key
|
||||
|
||||
# Enterprise Install
|
||||
RUN apt-get update && apt-get install -y libxmlsec1-dev pkg-config gcc
|
||||
COPY ./requirements/ee.txt /tmp/ee-requirements.txt
|
||||
RUN pip install --no-cache-dir --upgrade -r /tmp/ee-requirements.txt
|
||||
|
||||
# Enterprise lib removal for security reasons
|
||||
RUN apt-get remove -y libxmlsec1-dev pkg-config gcc && \
|
||||
apt-get update && apt-get install -y libxmlsec1-openssl && \
|
||||
apt-get autoremove -y
|
||||
rm -f /usr/local/lib/python3.11/site-packages/tornado/test/test.key
|
||||
|
||||
# Pre-downloading models for setups with limited egress
|
||||
RUN python -c "from transformers import AutoTokenizer; AutoTokenizer.from_pretrained('intfloat/e5-base-v2')"
|
||||
@ -69,7 +81,7 @@ WORKDIR /app
|
||||
|
||||
# Enterprise Version Files
|
||||
COPY ./ee /app/ee
|
||||
COPY ee.supervisord.conf /etc/supervisor/conf.d/ee.supervisord.conf
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# Set up application files
|
||||
COPY ./danswer /app/danswer
|
||||
|
9
backend/danswer/background/celery/celery_run.py
Normal file
9
backend/danswer/background/celery/celery_run.py
Normal file
@ -0,0 +1,9 @@
|
||||
"""Entry point for running celery worker / celery beat."""
|
||||
from danswer.utils.variable_functionality import fetch_versioned_implementation
|
||||
from danswer.utils.variable_functionality import set_is_ee_based_on_env_variable
|
||||
|
||||
|
||||
set_is_ee_based_on_env_variable()
|
||||
celery_app = fetch_versioned_implementation(
|
||||
"danswer.background.celery.celery_app", "celery_app"
|
||||
)
|
@ -36,6 +36,7 @@ from danswer.db.swap_index import check_index_swap
|
||||
from danswer.search.search_nlp_models import warm_up_encoders
|
||||
from danswer.utils.logger import setup_logger
|
||||
from danswer.utils.variable_functionality import global_version
|
||||
from danswer.utils.variable_functionality import set_is_ee_based_on_env_variable
|
||||
from shared_configs.configs import INDEXING_MODEL_SERVER_HOST
|
||||
from shared_configs.configs import LOG_LEVEL
|
||||
from shared_configs.configs import MODEL_SERVER_PORT
|
||||
@ -407,6 +408,8 @@ def update_loop(delay: int = 10, num_workers: int = NUM_INDEXING_WORKERS) -> Non
|
||||
|
||||
|
||||
def update__main() -> None:
|
||||
set_is_ee_based_on_env_variable()
|
||||
|
||||
logger.info("Starting Indexing Loop")
|
||||
update_loop()
|
||||
|
||||
|
@ -279,3 +279,15 @@ TOKEN_BUDGET_GLOBALLY_ENABLED = (
|
||||
CUSTOM_ANSWER_VALIDITY_CONDITIONS = json.loads(
|
||||
os.environ.get("CUSTOM_ANSWER_VALIDITY_CONDITIONS", "[]")
|
||||
)
|
||||
|
||||
|
||||
#####
|
||||
# Enterprise Edition Configs
|
||||
#####
|
||||
# NOTE: this should only be enabled if you have purchased an enterprise license.
|
||||
# if you're interested in an enterprise license, please reach out to us at
|
||||
# founders@danswer.ai OR message Chris Weaver or Yuhong Sun in the Danswer
|
||||
# Slack community (https://join.slack.com/t/danswer/shared_invite/zt-1w76msxmd-HJHLe3KNFIAIzk_0dSOKaQ)
|
||||
ENTERPRISE_EDITION_ENABLED = (
|
||||
os.environ.get("ENABLE_PAID_EE_FEATURES", "").lower() == "true"
|
||||
)
|
||||
|
@ -90,6 +90,8 @@ from danswer.utils.logger import setup_logger
|
||||
from danswer.utils.telemetry import optional_telemetry
|
||||
from danswer.utils.telemetry import RecordType
|
||||
from danswer.utils.variable_functionality import fetch_versioned_implementation
|
||||
from danswer.utils.variable_functionality import global_version
|
||||
from danswer.utils.variable_functionality import set_is_ee_based_on_env_variable
|
||||
from shared_configs.configs import ENABLE_RERANKING_REAL_TIME_FLOW
|
||||
from shared_configs.configs import MODEL_SERVER_HOST
|
||||
from shared_configs.configs import MODEL_SERVER_PORT
|
||||
@ -369,11 +371,18 @@ def get_application() -> FastAPI:
|
||||
return application
|
||||
|
||||
|
||||
app = get_application()
|
||||
# NOTE: needs to be outside of the `if __name__ == "__main__"` block so that the
|
||||
# app is exportable
|
||||
set_is_ee_based_on_env_variable()
|
||||
app = fetch_versioned_implementation(module="danswer.main", attribute="get_application")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info(
|
||||
f"Starting Danswer Backend version {__version__} on http://{APP_HOST}:{str(APP_PORT)}/"
|
||||
)
|
||||
|
||||
if global_version.get_is_ee_version():
|
||||
logger.info("Running Enterprise Edition")
|
||||
|
||||
uvicorn.run(app, host=APP_HOST, port=APP_PORT)
|
||||
|
@ -145,7 +145,9 @@ def create_deletion_attempt_for_connector_id(
|
||||
_: User = Depends(current_admin_user),
|
||||
db_session: Session = Depends(get_session),
|
||||
) -> None:
|
||||
from danswer.background.celery.celery import cleanup_connector_credential_pair_task
|
||||
from danswer.background.celery.celery_app import (
|
||||
cleanup_connector_credential_pair_task,
|
||||
)
|
||||
|
||||
connector_id = connector_credential_pair_identifier.connector_id
|
||||
credential_id = connector_credential_pair_identifier.credential_id
|
||||
|
@ -3,9 +3,9 @@ import importlib
|
||||
from typing import Any
|
||||
from typing import TypeVar
|
||||
|
||||
from danswer.configs.app_configs import ENTERPRISE_EDITION_ENABLED
|
||||
from danswer.utils.logger import setup_logger
|
||||
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
@ -23,6 +23,12 @@ class DanswerVersion:
|
||||
global_version = DanswerVersion()
|
||||
|
||||
|
||||
def set_is_ee_based_on_env_variable() -> None:
|
||||
if ENTERPRISE_EDITION_ENABLED and not global_version.get_is_ee_version():
|
||||
logger.info("Enterprise Edition enabled")
|
||||
global_version.set_ee()
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=128)
|
||||
def fetch_versioned_implementation(module: str, attribute: str) -> Any:
|
||||
logger.debug("Fetching versioned implementation for %s.%s", module, attribute)
|
||||
|
@ -1,57 +0,0 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/stdout
|
||||
logfile_maxbytes=0
|
||||
|
||||
[program:indexing]
|
||||
environment=CURRENT_PROCESS_IS_AN_INDEXING_JOB=true
|
||||
command=python ee/danswer/background/update.py
|
||||
stdout_logfile=/var/log/update.log
|
||||
stdout_logfile_maxbytes=52428800
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
||||
|
||||
# Automatic sync-ing of access to documents from sources
|
||||
[program:permission_syncing]
|
||||
command=python ee/danswer/background/permission_sync.py
|
||||
stdout_logfile=/var/log/permission_sync.log
|
||||
stdout_logfile_maxbytes=52428800
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
||||
|
||||
# Background jobs that must be run async due to long time to completion
|
||||
[program:celery_worker]
|
||||
command=celery -A ee.danswer.background.celery worker --loglevel=INFO --logfile=/var/log/celery_worker.log
|
||||
stdout_logfile=/var/log/celery_worker_supervisor.log
|
||||
stdout_logfile_maxbytes=52428800
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
||||
|
||||
# Job scheduler for periodic tasks
|
||||
[program:celery_beat]
|
||||
command=celery -A ee.danswer.background.celery beat --loglevel=INFO --logfile=/var/log/celery_beat.log
|
||||
stdout_logfile=/var/log/celery_beat_supervisor.log
|
||||
stdout_logfile_maxbytes=52428800
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
||||
|
||||
# Listens for Slack messages and responds with answers
|
||||
# for all channels that the DanswerBot has been added to.
|
||||
# If not setup, this will just fail 5 times and then stop.
|
||||
# More details on setup here: https://docs.danswer.dev/slack_bot_setup
|
||||
[program:slack_bot_listener]
|
||||
command=python danswer/danswerbot/slack/listener.py
|
||||
stdout_logfile=/var/log/slack_bot_listener.log
|
||||
stdout_logfile_maxbytes=52428800
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
||||
startretries=5
|
||||
startsecs=60
|
||||
|
||||
# Pushes all logs from the above programs to stdout
|
||||
[program:log-redirect-handler]
|
||||
command=tail -qF /var/log/update.log /var/log/celery_worker.log /var/log/celery_worker_supervisor.log /var/log/celery_beat.log /var/log/celery_beat_supervisor.log /var/log/slack_bot_listener.log
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
redirect_stderr=true
|
||||
autorestart=true
|
@ -1,5 +1,5 @@
|
||||
The DanswerAI Enterprise license (the “Enterprise License”)
|
||||
Copyright (c) 2023 DanswerAI, Inc.
|
||||
Copyright (c) 2023-present DanswerAI, Inc.
|
||||
|
||||
With regard to the Danswer Software:
|
||||
|
||||
|
@ -2,7 +2,7 @@ from datetime import timedelta
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from danswer.background.celery.celery import celery_app
|
||||
from danswer.background.celery.celery_app import celery_app
|
||||
from danswer.configs.app_configs import JOB_TIMEOUT
|
||||
from danswer.db.engine import get_sqlalchemy_engine
|
||||
from danswer.db.tasks import check_live_task_not_timed_out
|
@ -1,10 +0,0 @@
|
||||
from danswer.background.update import update__main
|
||||
from danswer.utils.variable_functionality import global_version
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# mark this as the EE-enabled indexing job
|
||||
global_version.set_ee()
|
||||
# run the usual flow, any future branching will be done with a
|
||||
# call to `global_version.get_is_ee_version()`
|
||||
update__main()
|
@ -1,18 +1,15 @@
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from httpx_oauth.clients.openid import OpenID
|
||||
|
||||
from danswer.auth.users import auth_backend
|
||||
from danswer.auth.users import fastapi_users
|
||||
from danswer.configs.app_configs import APP_HOST
|
||||
from danswer.configs.app_configs import APP_PORT
|
||||
from danswer.configs.app_configs import AUTH_TYPE
|
||||
from danswer.configs.app_configs import OAUTH_CLIENT_ID
|
||||
from danswer.configs.app_configs import OAUTH_CLIENT_SECRET
|
||||
from danswer.configs.app_configs import USER_AUTH_SECRET
|
||||
from danswer.configs.app_configs import WEB_DOMAIN
|
||||
from danswer.configs.constants import AuthType
|
||||
from danswer.main import get_application
|
||||
from danswer.main import get_application as get_application_base
|
||||
from danswer.main import include_router_with_global_prefix_prepended
|
||||
from danswer.utils.logger import setup_logger
|
||||
from danswer.utils.variable_functionality import global_version
|
||||
@ -45,14 +42,14 @@ from ee.danswer.utils.encryption import test_encryption
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
def get_ee_application() -> FastAPI:
|
||||
def get_application() -> FastAPI:
|
||||
# Anything that happens at import time is not guaranteed to be running ee-version
|
||||
# Anything after the server startup will be running ee version
|
||||
global_version.set_ee()
|
||||
|
||||
test_encryption()
|
||||
|
||||
application = get_application()
|
||||
application = get_application_base()
|
||||
|
||||
if AUTH_TYPE == AuthType.OIDC:
|
||||
include_router_with_global_prefix_prepended(
|
||||
@ -108,13 +105,3 @@ def get_ee_application() -> FastAPI:
|
||||
seed_db()
|
||||
|
||||
return application
|
||||
|
||||
|
||||
app = get_ee_application()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info(
|
||||
f"Running Enterprise Danswer API Service on http://{APP_HOST}:{str(APP_PORT)}/"
|
||||
)
|
||||
uvicorn.run(app, host=APP_HOST, port=APP_PORT)
|
||||
|
@ -25,7 +25,7 @@ autorestart=true
|
||||
# relatively compute-light (e.g. they tend to just make a bunch of requests to
|
||||
# Vespa / Postgres)
|
||||
[program:celery_worker]
|
||||
command=celery -A danswer.background.celery worker --pool=threads --autoscale=3,10 --loglevel=INFO --logfile=/var/log/celery_worker.log
|
||||
command=celery -A danswer.background.celery.celery_run:celery_app worker --pool=threads --autoscale=3,10 --loglevel=INFO --logfile=/var/log/celery_worker.log
|
||||
stdout_logfile=/var/log/celery_worker_supervisor.log
|
||||
stdout_logfile_maxbytes=52428800
|
||||
redirect_stderr=true
|
||||
@ -33,7 +33,7 @@ autorestart=true
|
||||
|
||||
# Job scheduler for periodic tasks
|
||||
[program:celery_beat]
|
||||
command=celery -A danswer.background.celery beat --loglevel=INFO --logfile=/var/log/celery_beat.log
|
||||
command=celery -A danswer.background.celery.celery_run:celery_app beat --loglevel=INFO --logfile=/var/log/celery_beat.log
|
||||
stdout_logfile=/var/log/celery_beat_supervisor.log
|
||||
stdout_logfile_maxbytes=52428800
|
||||
redirect_stderr=true
|
||||
|
@ -1,14 +1,14 @@
|
||||
version: '3'
|
||||
services:
|
||||
api_server:
|
||||
image: danswer/danswer-ee-backend:latest
|
||||
image: danswer/danswer-backend:latest
|
||||
build:
|
||||
context: ../../backend
|
||||
dockerfile: Dockerfile
|
||||
command: >
|
||||
/bin/sh -c "alembic upgrade head &&
|
||||
echo \"Starting Danswer Api Server\" &&
|
||||
uvicorn ee.danswer.main:app --host 0.0.0.0 --port 8080"
|
||||
uvicorn danswer.main:app --host 0.0.0.0 --port 8080"
|
||||
depends_on:
|
||||
- relational_db
|
||||
- index
|
||||
@ -86,7 +86,9 @@ services:
|
||||
# (time spent on finding the right docs + time spent fetching summaries from disk)
|
||||
- LOG_VESPA_TIMING_INFORMATION=${LOG_VESPA_TIMING_INFORMATION:-}
|
||||
- LOG_ENDPOINT_LATENCY=${LOG_ENDPOINT_LATENCY:-}
|
||||
|
||||
# Enterprise Edition only
|
||||
- ENABLE_PAID_EE_FEATURES=${ENABLE_PAID_EE_FEATURES:-false}
|
||||
- API_KEY_HASH_ROUNDS=${API_KEY_HASH_ROUNDS:-}
|
||||
# Seeding configuration
|
||||
- ENV_SEED_CONFIGURATION=${ENV_SEED_CONFIGURATION:-}
|
||||
@ -100,11 +102,11 @@ services:
|
||||
|
||||
|
||||
background:
|
||||
image: danswer/danswer-ee-backend:latest
|
||||
image: danswer/danswer-backend:latest
|
||||
build:
|
||||
context: ../../backend
|
||||
dockerfile: Dockerfile
|
||||
command: /usr/bin/supervisord -c /etc/supervisor/conf.d/ee.supervisord.conf
|
||||
command: /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
||||
depends_on:
|
||||
- relational_db
|
||||
- index
|
||||
@ -187,6 +189,9 @@ services:
|
||||
- LOG_LEVEL=${LOG_LEVEL:-info} # Set to debug to get more fine-grained logs
|
||||
- LOG_ALL_MODEL_INTERACTIONS=${LOG_ALL_MODEL_INTERACTIONS:-} # Log all of the prompts to the LLM
|
||||
- LOG_VESPA_TIMING_INFORMATION=${LOG_VESPA_TIMING_INFORMATION:-}
|
||||
|
||||
# Enterprise Edition stuff
|
||||
- ENABLE_PAID_EE_FEATURES=${ENABLE_PAID_EE_FEATURES:-false}
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
logging:
|
||||
@ -197,7 +202,7 @@ services:
|
||||
|
||||
|
||||
web_server:
|
||||
image: danswer/danswer-ee-web-server:latest
|
||||
image: danswer/danswer-web-server:latest
|
||||
build:
|
||||
context: ../../web
|
||||
dockerfile: Dockerfile
|
||||
@ -207,8 +212,9 @@ services:
|
||||
- NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
|
||||
- NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
|
||||
- NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT:-}
|
||||
|
||||
# Enterprise Edition only
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
- NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES=${NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES:-true}
|
||||
# DO NOT TURN ON unless you have EXPLICIT PERMISSION from Danswer.
|
||||
- NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
|
||||
depends_on:
|
||||
@ -219,6 +225,9 @@ services:
|
||||
- WEB_DOMAIN=${WEB_DOMAIN:-}
|
||||
- THEME_IS_DARK=${THEME_IS_DARK:-}
|
||||
|
||||
# Enterprise Edition only
|
||||
- ENABLE_PAID_EE_FEATURES=${ENABLE_PAID_EE_FEATURES:-false}
|
||||
|
||||
|
||||
inference_model_server:
|
||||
image: danswer/danswer-model-server:latest
|
||||
|
@ -81,6 +81,10 @@ services:
|
||||
# If set to `true` will enable additional logs about Vespa query performance
|
||||
# (time spent on finding the right docs + time spent fetching summaries from disk)
|
||||
- LOG_VESPA_TIMING_INFORMATION=${LOG_VESPA_TIMING_INFORMATION:-}
|
||||
|
||||
# Enterprise Edition only
|
||||
- API_KEY_HASH_ROUNDS=${API_KEY_HASH_ROUNDS:-}
|
||||
- ENABLE_PAID_EE_FEATURES=${ENABLE_PAID_EE_FEATURES:-false}
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
logging:
|
||||
@ -177,6 +181,10 @@ services:
|
||||
- LOG_LEVEL=${LOG_LEVEL:-info} # Set to debug to get more fine-grained logs
|
||||
- LOG_ALL_MODEL_INTERACTIONS=${LOG_ALL_MODEL_INTERACTIONS:-} # Log all of the prompts to the LLM
|
||||
- LOG_VESPA_TIMING_INFORMATION=${LOG_VESPA_TIMING_INFORMATION:-}
|
||||
|
||||
# Enterprise Edition only
|
||||
- API_KEY_HASH_ROUNDS=${API_KEY_HASH_ROUNDS:-}
|
||||
- ENABLE_PAID_EE_FEATURES=${ENABLE_PAID_EE_FEATURES:-false}
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
logging:
|
||||
@ -197,12 +205,17 @@ services:
|
||||
- NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
|
||||
- NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
|
||||
- NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT:-}
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
depends_on:
|
||||
- api_server
|
||||
restart: always
|
||||
environment:
|
||||
- INTERNAL_URL=http://api_server:8080
|
||||
- WEB_DOMAIN=${WEB_DOMAIN:-}
|
||||
- THEME_IS_DARK=${THEME_IS_DARK:-}
|
||||
|
||||
# Enterprise Edition only
|
||||
- ENABLE_PAID_EE_FEATURES=${ENABLE_PAID_EE_FEATURES:-false}
|
||||
|
||||
|
||||
inference_model_server:
|
||||
|
@ -1,14 +1,14 @@
|
||||
version: '3'
|
||||
services:
|
||||
api_server:
|
||||
image: danswer/danswer-ee-backend:latest
|
||||
image: danswer/danswer-backend:latest
|
||||
build:
|
||||
context: ../../backend
|
||||
dockerfile: Dockerfile
|
||||
command: >
|
||||
/bin/sh -c "alembic upgrade head &&
|
||||
echo \"Starting Danswer Api Server\" &&
|
||||
uvicorn ee.danswer.main:app --host 0.0.0.0 --port 8080"
|
||||
uvicorn danswer.main:app --host 0.0.0.0 --port 8080"
|
||||
depends_on:
|
||||
- relational_db
|
||||
- index
|
||||
@ -31,11 +31,11 @@ services:
|
||||
|
||||
|
||||
background:
|
||||
image: danswer/danswer-ee-backend:latest
|
||||
image: danswer/danswer-backend:latest
|
||||
build:
|
||||
context: ../../backend
|
||||
dockerfile: Dockerfile
|
||||
command: /usr/bin/supervisord -c /etc/supervisor/conf.d/ee.supervisord.conf
|
||||
command: /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
||||
depends_on:
|
||||
- relational_db
|
||||
- index
|
||||
@ -60,7 +60,7 @@ services:
|
||||
|
||||
|
||||
web_server:
|
||||
image: danswer/danswer-ee-web-server:latest
|
||||
image: danswer/danswer-web-server:latest
|
||||
build:
|
||||
context: ../../web
|
||||
dockerfile: Dockerfile
|
||||
@ -71,7 +71,6 @@ services:
|
||||
- NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
|
||||
- NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT:-}
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
- NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES=${NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES:-true}
|
||||
depends_on:
|
||||
- api_server
|
||||
restart: always
|
||||
|
@ -1,14 +1,14 @@
|
||||
version: '3'
|
||||
services:
|
||||
api_server:
|
||||
image: danswer/danswer-ee-backend:latest
|
||||
image: danswer/danswer-backend:latest
|
||||
build:
|
||||
context: ../../backend
|
||||
dockerfile: Dockerfile
|
||||
command: >
|
||||
/bin/sh -c "alembic upgrade head &&
|
||||
echo \"Starting Danswer Api Server\" &&
|
||||
uvicorn ee.danswer.main:app --host 0.0.0.0 --port 8080"
|
||||
uvicorn danswer.main:app --host 0.0.0.0 --port 8080"
|
||||
depends_on:
|
||||
- relational_db
|
||||
- index
|
||||
@ -31,11 +31,11 @@ services:
|
||||
|
||||
|
||||
background:
|
||||
image: danswer/danswer-ee-backend:latest
|
||||
image: danswer/danswer-backend:latest
|
||||
build:
|
||||
context: ../../backend
|
||||
dockerfile: Dockerfile
|
||||
command: /usr/bin/supervisord -c /etc/supervisor/conf.d/ee.supervisord.conf
|
||||
command: /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
||||
depends_on:
|
||||
- relational_db
|
||||
- index
|
||||
@ -59,7 +59,7 @@ services:
|
||||
max-file: "6"
|
||||
|
||||
web_server:
|
||||
image: danswer/danswer-ee-web-server:latest
|
||||
image: danswer/danswer-web-server:latest
|
||||
build:
|
||||
context: ../../web
|
||||
dockerfile: Dockerfile
|
||||
@ -70,7 +70,6 @@ services:
|
||||
- NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
|
||||
- NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT:-}
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
- NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES=${NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES:-true}
|
||||
depends_on:
|
||||
- api_server
|
||||
restart: always
|
||||
|
@ -28,7 +28,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: api-server
|
||||
image: danswer/danswer-ee-backend:latest
|
||||
image: danswer/danswer-backend:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- "/bin/sh"
|
||||
@ -36,7 +36,7 @@ spec:
|
||||
- |
|
||||
alembic upgrade head &&
|
||||
echo "Starting Danswer Api Server" &&
|
||||
uvicorn ee.danswer.main:app --host 0.0.0.0 --port 8080
|
||||
uvicorn danswer.main:app --host 0.0.0.0 --port 8080
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
# There are some extra values since this is shared between services
|
||||
|
@ -14,9 +14,9 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: background
|
||||
image: danswer/danswer-ee-backend:latest
|
||||
image: danswer/danswer-backend:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/ee.supervisord.conf"]
|
||||
command: ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
|
||||
# There are some extra values since this is shared between services
|
||||
# There are no conflicts though, extra env variables are simply ignored
|
||||
envFrom:
|
||||
|
@ -27,7 +27,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: web-server
|
||||
image: danswer/danswer-ee-web-server:latest
|
||||
image: danswer/danswer-web-server:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
@ -36,5 +36,3 @@ spec:
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: env-configmap
|
||||
args:
|
||||
- "NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES=true"
|
||||
|
@ -1,11 +1,11 @@
|
||||
FROM node:20-alpine AS base
|
||||
|
||||
LABEL com.danswer.maintainer="founders@danswer.ai"
|
||||
LABEL com.danswer.description="This image is the Enterprise Edition (Paid Edition) \
|
||||
frontend/webserver of Danswer. If you do not have a contract or agreement with DanswerAI, you are \
|
||||
not permitted to use this container outside of personal development or testing purposes. Please \
|
||||
reach out to founders@danswer.ai for more information. You can access the MIT version of Danswer \
|
||||
at https://github.com/danswer-ai/danswer"
|
||||
LABEL com.danswer.description="This image is the web/frontend container of Danswer which \
|
||||
contains code for both the Community and Enterprise editions of Danswer. If you do not \
|
||||
have a contract or agreement with DanswerAI, you are not permitted to use the Enterprise \
|
||||
Edition features outside of personal development or testing purposes. Please reach out to \
|
||||
founders@danswer.ai for more information. Please visit https://github.com/danswer-ai/danswer"
|
||||
|
||||
# Default DANSWER_VERSION, typically overriden during builds by GitHub Actions.
|
||||
ARG DANSWER_VERSION=0.3-dev
|
||||
|
@ -9,64 +9,17 @@ const nextConfig = {
|
||||
output: "standalone",
|
||||
swcMinify: true,
|
||||
rewrites: async () => {
|
||||
const eeRedirects =
|
||||
process.env.NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES?.toLowerCase() === "true"
|
||||
? [
|
||||
// user group pages
|
||||
{
|
||||
source: "/admin/groups",
|
||||
destination: "/ee/admin/groups",
|
||||
},
|
||||
{
|
||||
source: "/admin/groups/:path*",
|
||||
destination: "/ee/admin/groups/:path*",
|
||||
},
|
||||
{
|
||||
source: "/admin/api-key",
|
||||
destination: "/ee/admin/api-key",
|
||||
},
|
||||
// analytics / audit log pages
|
||||
{
|
||||
source: "/admin/performance/usage",
|
||||
destination: "/ee/admin/performance/usage",
|
||||
},
|
||||
{
|
||||
source: "/admin/performance/query-history",
|
||||
destination: "/ee/admin/performance/query-history",
|
||||
},
|
||||
{
|
||||
source: "/admin/performance/query-history/:path*",
|
||||
destination: "/ee/admin/performance/query-history/:path*",
|
||||
},
|
||||
// whitelabeling
|
||||
{
|
||||
source: "/admin/whitelabeling",
|
||||
destination: "/ee/admin/whitelabeling",
|
||||
},
|
||||
// custom analytics/tracking
|
||||
{
|
||||
source: "/admin/performance/custom-analytics",
|
||||
destination: "/ee/admin/performance/custom-analytics",
|
||||
},
|
||||
// token rate limits
|
||||
{
|
||||
source: "/admin/token-rate-limits",
|
||||
destination: "/ee/admin/token-rate-limits",
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
// In production, something else (nginx in the one box setup) should take
|
||||
// care of this rewrite. TODO (chris): better support setups where
|
||||
// web_server and api_server are on different machines.
|
||||
if (process.env.NODE_ENV === "production") return eeRedirects;
|
||||
if (process.env.NODE_ENV === "production") return [];
|
||||
|
||||
return [
|
||||
{
|
||||
source: "/api/:path*",
|
||||
destination: "http://127.0.0.1:8080/:path*", // Proxy to Backend
|
||||
},
|
||||
].concat(eeRedirects);
|
||||
];
|
||||
},
|
||||
redirects: async () => {
|
||||
// In production, something else (nginx in the one box setup) should take
|
||||
|
@ -25,7 +25,6 @@ import {
|
||||
} from "@/components/admin/connectors/Field";
|
||||
import { HidableSection } from "./HidableSection";
|
||||
import { FiPlus, FiX } from "react-icons/fi";
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
import { useUserGroups } from "@/lib/hooks";
|
||||
import { Bubble } from "@/components/Bubble";
|
||||
import { GroupsIcon } from "@/components/icons/icons";
|
||||
@ -37,6 +36,8 @@ import { ToolSnapshot } from "@/lib/tools/interfaces";
|
||||
import { checkUserIsNoAuthUser } from "@/lib/user";
|
||||
import { addAssistantToList } from "@/lib/assistants/updateAssistantPreferences";
|
||||
import { checkLLMSupportsImageInput } from "@/lib/llm/utils";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
||||
|
||||
function findSearchTool(tools: ToolSnapshot[]) {
|
||||
return tools.find((tool) => tool.in_code_tool_id === "SearchTool");
|
||||
@ -80,6 +81,8 @@ export function AssistantEditor({
|
||||
const router = useRouter();
|
||||
const { popup, setPopup } = usePopup();
|
||||
|
||||
const isPaidEnterpriseFeaturesEnabled = usePaidEnterpriseFeaturesEnabled();
|
||||
|
||||
// EE only
|
||||
const { data: userGroups, isLoading: userGroupsIsLoading } = useUserGroups();
|
||||
|
||||
@ -868,7 +871,7 @@ export function AssistantEditor({
|
||||
|
||||
<Divider />
|
||||
|
||||
{EE_ENABLED &&
|
||||
{isPaidEnterpriseFeaturesEnabled &&
|
||||
userGroups &&
|
||||
(!user || user.role === "admin") && (
|
||||
<>
|
||||
|
@ -25,13 +25,15 @@ import { getNameFromPath } from "@/lib/fileUtils";
|
||||
import { Button, Card, Divider, Text } from "@tremor/react";
|
||||
import { AdminPageTitle } from "@/components/admin/Title";
|
||||
import IsPublicField from "@/components/admin/connectors/IsPublicField";
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
||||
|
||||
const Main = () => {
|
||||
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
||||
const [filesAreUploading, setFilesAreUploading] = useState<boolean>(false);
|
||||
const { popup, setPopup } = usePopup();
|
||||
|
||||
const isPaidEnterpriseFeaturesEnabled = usePaidEnterpriseFeaturesEnabled();
|
||||
|
||||
const { mutate } = useSWRConfig();
|
||||
|
||||
const {
|
||||
@ -90,13 +92,13 @@ const Main = () => {
|
||||
initialValues={{
|
||||
name: "",
|
||||
selectedFiles: [],
|
||||
is_public: EE_ENABLED ? false : undefined,
|
||||
is_public: isPaidEnterpriseFeaturesEnabled ? false : undefined,
|
||||
}}
|
||||
validationSchema={Yup.object().shape({
|
||||
name: Yup.string().required(
|
||||
"Please enter a descriptive name for the files"
|
||||
),
|
||||
...(EE_ENABLED && {
|
||||
...(isPaidEnterpriseFeaturesEnabled && {
|
||||
is_public: Yup.boolean().required(),
|
||||
}),
|
||||
})}
|
||||
@ -226,7 +228,7 @@ const Main = () => {
|
||||
setSelectedFiles={setSelectedFiles}
|
||||
/>
|
||||
|
||||
{EE_ENABLED && (
|
||||
{isPaidEnterpriseFeaturesEnabled && (
|
||||
<>
|
||||
<Divider />
|
||||
<IsPublicField />
|
||||
|
@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { ArrayHelpers, FieldArray, Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import { PopupSpec } from "@/components/admin/connectors/Popup";
|
||||
@ -9,8 +11,8 @@ import {
|
||||
} from "@/components/admin/connectors/Field";
|
||||
import { ConnectorTitle } from "@/components/admin/connectors/ConnectorTitle";
|
||||
import { Button, Divider, Text } from "@tremor/react";
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
import { FiUsers } from "react-icons/fi";
|
||||
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
||||
|
||||
interface SetCreationPopupProps {
|
||||
ccPairs: ConnectorIndexingStatus<any, any>[];
|
||||
@ -27,6 +29,8 @@ export const DocumentSetCreationForm = ({
|
||||
setPopup,
|
||||
existingDocumentSet,
|
||||
}: SetCreationPopupProps) => {
|
||||
const isPaidEnterpriseFeaturesEnabled = usePaidEnterpriseFeaturesEnabled();
|
||||
|
||||
const isUpdate = existingDocumentSet !== undefined;
|
||||
|
||||
return (
|
||||
@ -167,46 +171,48 @@ export const DocumentSetCreationForm = ({
|
||||
)}
|
||||
/>
|
||||
|
||||
{EE_ENABLED && userGroups && userGroups.length > 0 && (
|
||||
<div>
|
||||
<Divider />
|
||||
{isPaidEnterpriseFeaturesEnabled &&
|
||||
userGroups &&
|
||||
userGroups.length > 0 && (
|
||||
<div>
|
||||
<Divider />
|
||||
|
||||
<BooleanFormField
|
||||
name="is_public"
|
||||
label="Is Public?"
|
||||
subtext={
|
||||
<BooleanFormField
|
||||
name="is_public"
|
||||
label="Is Public?"
|
||||
subtext={
|
||||
<>
|
||||
If the document set is public, then it will be visible
|
||||
to <b>all users</b>. If it is not public, then only
|
||||
users in the specified groups will be able to see it.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<Divider />
|
||||
<h2 className="mb-1 font-medium text-base">
|
||||
Groups with Access
|
||||
</h2>
|
||||
{!values.is_public ? (
|
||||
<>
|
||||
If the document set is public, then it will be visible to{" "}
|
||||
<b>all users</b>. If it is not public, then only users in
|
||||
the specified groups will be able to see it.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<Divider />
|
||||
<h2 className="mb-1 font-medium text-base">
|
||||
Groups with Access
|
||||
</h2>
|
||||
{!values.is_public ? (
|
||||
<>
|
||||
<Text className="mb-3">
|
||||
If any groups are specified, then this Document Set will
|
||||
only be visible to the specified groups. If no groups are
|
||||
specified, then the Document Set will be visible to all
|
||||
users.
|
||||
</Text>
|
||||
<FieldArray
|
||||
name="groups"
|
||||
render={(arrayHelpers: ArrayHelpers) => (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
{userGroups.map((userGroup) => {
|
||||
const ind = values.groups.indexOf(userGroup.id);
|
||||
let isSelected = ind !== -1;
|
||||
return (
|
||||
<div
|
||||
key={userGroup.id}
|
||||
className={
|
||||
`
|
||||
<Text className="mb-3">
|
||||
If any groups are specified, then this Document Set will
|
||||
only be visible to the specified groups. If no groups
|
||||
are specified, then the Document Set will be visible to
|
||||
all users.
|
||||
</Text>
|
||||
<FieldArray
|
||||
name="groups"
|
||||
render={(arrayHelpers: ArrayHelpers) => (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
{userGroups.map((userGroup) => {
|
||||
const ind = values.groups.indexOf(userGroup.id);
|
||||
let isSelected = ind !== -1;
|
||||
return (
|
||||
<div
|
||||
key={userGroup.id}
|
||||
className={
|
||||
`
|
||||
px-3
|
||||
py-1
|
||||
rounded-lg
|
||||
@ -215,38 +221,38 @@ export const DocumentSetCreationForm = ({
|
||||
w-fit
|
||||
flex
|
||||
cursor-pointer ` +
|
||||
(isSelected
|
||||
? " bg-background-strong"
|
||||
: " hover:bg-hover")
|
||||
}
|
||||
onClick={() => {
|
||||
if (isSelected) {
|
||||
arrayHelpers.remove(ind);
|
||||
} else {
|
||||
arrayHelpers.push(userGroup.id);
|
||||
(isSelected
|
||||
? " bg-background-strong"
|
||||
: " hover:bg-hover")
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="my-auto flex">
|
||||
<FiUsers className="my-auto mr-2" />{" "}
|
||||
{userGroup.name}
|
||||
onClick={() => {
|
||||
if (isSelected) {
|
||||
arrayHelpers.remove(ind);
|
||||
} else {
|
||||
arrayHelpers.push(userGroup.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="my-auto flex">
|
||||
<FiUsers className="my-auto mr-2" />{" "}
|
||||
{userGroup.name}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Text>
|
||||
This Document Set is public, so this does not apply. If you
|
||||
want to control which user groups see this Document Set,
|
||||
mark it as non-public!
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Text>
|
||||
This Document Set is public, so this does not apply. If
|
||||
you want to control which user groups see this Document
|
||||
Set, mark it as non-public!
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex mt-6">
|
||||
<Button
|
||||
type="submit"
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
import { errorHandlingFetcher } from "@/lib/fetcher";
|
||||
import { DocumentSet } from "@/lib/types";
|
||||
import useSWR, { mutate } from "swr";
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { NotebookIcon } from "@/components/icons/icons";
|
||||
import { getWebVersion, getBackendVersion } from "@/lib/version";
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
|
||||
const Page = async () => {
|
||||
let web_version: string | null = null;
|
||||
@ -22,9 +21,6 @@ const Page = async () => {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="font-bold text-lg my-auto mb-2">
|
||||
{EE_ENABLED ? "Danswer Enterprise Edition" : "Danswer MIT"}
|
||||
</p>
|
||||
<div className="flex mb-2">
|
||||
<p className="my-auto mr-1">Backend Version: </p>
|
||||
<p className="text-base my-auto text-slate-400 italic">
|
||||
|
@ -22,7 +22,7 @@ import { GenericTokenRateLimitTable } from "./TokenRateLimitTables";
|
||||
import { mutate } from "swr";
|
||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||
import { CreateRateLimitModal } from "./CreateRateLimitModal";
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
||||
|
||||
const BASE_URL = "/api/admin/token-rate-limits";
|
||||
const GLOBAL_TOKEN_FETCH_URL = `${BASE_URL}/global`;
|
||||
@ -69,6 +69,8 @@ function Main() {
|
||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||
const { popup, setPopup } = usePopup();
|
||||
|
||||
const isPaidEnterpriseFeaturesEnabled = usePaidEnterpriseFeaturesEnabled();
|
||||
|
||||
const updateTable = (target_scope: Scope) => {
|
||||
if (target_scope === Scope.GLOBAL) {
|
||||
mutate(GLOBAL_TOKEN_FETCH_URL);
|
||||
@ -120,7 +122,7 @@ function Main() {
|
||||
token spend.
|
||||
</Text>
|
||||
</li>
|
||||
{EE_ENABLED && (
|
||||
{isPaidEnterpriseFeaturesEnabled && (
|
||||
<>
|
||||
<li>
|
||||
<Text>
|
||||
@ -150,7 +152,7 @@ function Main() {
|
||||
Create a Token Rate Limit
|
||||
</Button>
|
||||
|
||||
{EE_ENABLED && (
|
||||
{isPaidEnterpriseFeaturesEnabled && (
|
||||
<TabGroup className="mt-6" index={tabIndex} onIndexChange={setTabIndex}>
|
||||
<TabList variant="line">
|
||||
<Tab icon={FiGlobe}>Global</Tab>
|
||||
@ -191,7 +193,7 @@ function Main() {
|
||||
</TabGroup>
|
||||
)}
|
||||
|
||||
{!EE_ENABLED && (
|
||||
{!isPaidEnterpriseFeaturesEnabled && (
|
||||
<div className="mt-6">
|
||||
<GenericTokenRateLimitTable
|
||||
fetchUrl={GLOBAL_TOKEN_FETCH_URL}
|
||||
@ -206,7 +208,9 @@ function Main() {
|
||||
setIsOpen={() => setModalIsOpen(false)}
|
||||
setPopup={setPopup}
|
||||
onSubmit={handleSubmit}
|
||||
forSpecificScope={EE_ENABLED ? undefined : Scope.GLOBAL}
|
||||
forSpecificScope={
|
||||
isPaidEnterpriseFeaturesEnabled ? undefined : Scope.GLOBAL
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
The DanswerAI Enterprise license (the “Enterprise License”)
|
||||
Copyright (c) 2023 DanswerAI, Inc.
|
||||
Copyright (c) 2023-present DanswerAI, Inc.
|
||||
|
||||
With regard to the Danswer Software:
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
import { SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED } from "@/lib/constants";
|
||||
|
||||
export default async function AdminLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
if (!EE_ENABLED) {
|
||||
if (!SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED) {
|
||||
return (
|
||||
<div className="flex h-screen">
|
||||
<div className="mx-auto my-auto text-lg font-bold text-red-500">
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
getAuthTypeMetadataSS,
|
||||
getCurrentUserSS,
|
||||
} from "@/lib/userSS";
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
import { SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED } from "@/lib/constants";
|
||||
import { redirect } from "next/navigation";
|
||||
import {
|
||||
FiActivity,
|
||||
@ -194,7 +194,7 @@ export async function Layout({ children }: { children: React.ReactNode }) {
|
||||
),
|
||||
link: "/admin/users",
|
||||
},
|
||||
...(EE_ENABLED
|
||||
...(SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED
|
||||
? [
|
||||
{
|
||||
name: (
|
||||
@ -227,7 +227,7 @@ export async function Layout({ children }: { children: React.ReactNode }) {
|
||||
},
|
||||
],
|
||||
},
|
||||
...(EE_ENABLED
|
||||
...(SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED
|
||||
? [
|
||||
{
|
||||
name: "Performance",
|
||||
@ -275,7 +275,7 @@ export async function Layout({ children }: { children: React.ReactNode }) {
|
||||
),
|
||||
link: "/admin/settings",
|
||||
},
|
||||
...(EE_ENABLED
|
||||
...(SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED
|
||||
? [
|
||||
{
|
||||
name: (
|
||||
|
@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { Formik, Form } from "formik";
|
||||
import * as Yup from "yup";
|
||||
@ -14,8 +16,8 @@ import { BooleanFormField, TextFormField } from "./Field";
|
||||
import { createCredential, linkCredential } from "@/lib/credential";
|
||||
import { useSWRConfig } from "swr";
|
||||
import { Button, Divider } from "@tremor/react";
|
||||
import { EE_ENABLED } from "@/lib/constants";
|
||||
import IsPublicField from "./IsPublicField";
|
||||
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
||||
|
||||
const BASE_CONNECTOR_URL = "/api/manage/admin/connector";
|
||||
|
||||
@ -76,7 +78,6 @@ interface BaseProps<T extends Yup.AnyObject> {
|
||||
// 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;
|
||||
showNonPublicOption?: boolean;
|
||||
}
|
||||
|
||||
type ConnectorFormProps<T extends Yup.AnyObject> = RequireAtLeastOne<
|
||||
@ -98,12 +99,13 @@ export function ConnectorForm<T extends Yup.AnyObject>({
|
||||
pruneFreq,
|
||||
onSubmit,
|
||||
shouldCreateEmptyCredentialForConnector,
|
||||
// only show this option for EE, since groups are not supported in CE
|
||||
showNonPublicOption = EE_ENABLED,
|
||||
}: ConnectorFormProps<T>): JSX.Element {
|
||||
const { mutate } = useSWRConfig();
|
||||
const { popup, setPopup } = usePopup();
|
||||
|
||||
// only show this option for EE, since groups are not supported in CE
|
||||
const showNonPublicOption = usePaidEnterpriseFeaturesEnabled();
|
||||
|
||||
const shouldHaveNameInput = credentialId !== undefined && !ccPairNameBuilder;
|
||||
|
||||
const ccPairNameInitialValue = shouldHaveNameInput
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { EnterpriseSettings, Settings } from "@/app/admin/settings/interfaces";
|
||||
import { CUSTOM_ANALYTICS_ENABLED, EE_ENABLED } from "@/lib/constants";
|
||||
import {
|
||||
CUSTOM_ANALYTICS_ENABLED,
|
||||
SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED,
|
||||
} from "@/lib/constants";
|
||||
import { fetchSS } from "@/lib/utilsSS";
|
||||
|
||||
export async function fetchSettingsSS() {
|
||||
const tasks = [fetchSS("/settings")];
|
||||
if (EE_ENABLED) {
|
||||
if (SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED) {
|
||||
tasks.push(fetchSS("/enterprise-settings"));
|
||||
if (CUSTOM_ANALYTICS_ENABLED) {
|
||||
tasks.push(fetchSS("/enterprise-settings/custom-analytics-script"));
|
||||
|
@ -0,0 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { useContext } from "react";
|
||||
import { SettingsContext } from "./SettingsProvider";
|
||||
|
||||
export function usePaidEnterpriseFeaturesEnabled() {
|
||||
const combinedSettings = useContext(SettingsContext);
|
||||
if (!combinedSettings) {
|
||||
return null;
|
||||
}
|
||||
return combinedSettings.enterpriseSettings !== null;
|
||||
}
|
@ -25,14 +25,13 @@ export const HEADER_PADDING = `pt-[64px]`;
|
||||
export const LOGOUT_DISABLED =
|
||||
process.env.NEXT_PUBLIC_DISABLE_LOGOUT?.toLowerCase() === "true";
|
||||
|
||||
// NOTE: since this is a `NEXT_PUBLIC_` variable, it will be set at
|
||||
// build-time
|
||||
// TODO: consider moving this to an API call so that the api_server
|
||||
// can be the single source of truth
|
||||
export const EE_ENABLED =
|
||||
process.env.NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES?.toLowerCase() === "true";
|
||||
/* Enterprise-only settings */
|
||||
|
||||
// NOTE: this should ONLY be used on the server-side. If used client side,
|
||||
// it will not be accurate (will always be false).
|
||||
export const SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED =
|
||||
process.env.ENABLE_PAID_EE_FEATURES?.toLowerCase() === "true";
|
||||
|
||||
// Enterprise-only settings
|
||||
export const CUSTOM_ANALYTICS_ENABLED = process.env.CUSTOM_ANALYTICS_SECRET_KEY
|
||||
? true
|
||||
: false;
|
||||
|
@ -11,10 +11,10 @@ import { errorHandlingFetcher } from "./fetcher";
|
||||
import { useState } from "react";
|
||||
import { DateRangePickerValue } from "@tremor/react";
|
||||
import { SourceMetadata } from "./search/interfaces";
|
||||
import { EE_ENABLED } from "./constants";
|
||||
import { destructureValue } from "./llm/utils";
|
||||
import { ChatSession } from "@/app/chat/interfaces";
|
||||
import { UsersResponse } from "./users/interfaces";
|
||||
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
||||
|
||||
const CREDENTIAL_URL = "/api/manage/admin/credential";
|
||||
|
||||
@ -192,8 +192,9 @@ export const useUserGroups = (): {
|
||||
refreshUserGroups: () => void;
|
||||
} => {
|
||||
const swrResponse = useSWR<UserGroup[]>(USER_GROUP_URL, errorHandlingFetcher);
|
||||
const isPaidEnterpriseFeaturesEnabled = usePaidEnterpriseFeaturesEnabled();
|
||||
|
||||
if (!EE_ENABLED) {
|
||||
if (!isPaidEnterpriseFeaturesEnabled) {
|
||||
return {
|
||||
...{
|
||||
data: [],
|
||||
|
39
web/src/middleware.ts
Normal file
39
web/src/middleware.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED } from "./lib/constants";
|
||||
|
||||
const eePaths = [
|
||||
"/admin/groups",
|
||||
"/admin/api-key",
|
||||
"/admin/performance/usage",
|
||||
"/admin/performance/query-history",
|
||||
"/admin/whitelabeling",
|
||||
"/admin/performance/custom-analytics",
|
||||
];
|
||||
const eePathsForMatcher = eePaths.map((path) => `${path}/:path*`);
|
||||
|
||||
export async function middleware(request: NextRequest) {
|
||||
if (SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED) {
|
||||
const pathname = request.nextUrl.pathname;
|
||||
|
||||
// Check if the current path is in the eePaths list
|
||||
if (eePaths.some((path) => pathname.startsWith(path))) {
|
||||
// Add '/ee' to the beginning of the pathname
|
||||
const newPathname = `/ee${pathname}`;
|
||||
|
||||
// Create a new URL with the modified pathname
|
||||
const newUrl = new URL(newPathname, request.url);
|
||||
|
||||
// Rewrite to the new URL
|
||||
return NextResponse.rewrite(newUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// Continue with the response if no rewrite is needed
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
// Specify the paths that the middleware should run for
|
||||
export const config = {
|
||||
matcher: eePathsForMatcher,
|
||||
};
|
@ -1,13 +1,11 @@
|
||||
var merge = require("lodash/merge");
|
||||
|
||||
const baseThemes = require("./tailwind-themes/tailwind.config.js");
|
||||
const customThemes =
|
||||
process.env.NEXT_PUBLIC_ENABLE_PAID_EE_FEATURES &&
|
||||
process.env.NEXT_PUBLIC_THEME
|
||||
? require(
|
||||
`./tailwind-themes/custom/${process.env.NEXT_PUBLIC_THEME}/tailwind.config.js`
|
||||
)
|
||||
: null;
|
||||
const customThemes = process.env.NEXT_PUBLIC_THEME
|
||||
? require(
|
||||
`./tailwind-themes/custom/${process.env.NEXT_PUBLIC_THEME}/tailwind.config.js`
|
||||
)
|
||||
: null;
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = customThemes ? merge(baseThemes, customThemes) : baseThemes;
|
||||
|
Loading…
x
Reference in New Issue
Block a user