Kevin Hu
commited on
Commit
·
e6cd231
1
Parent(s):
9aadaa2
add owner check for team work (#2892)
Browse files### What problem does this PR solve?
#2834
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
- agent/component/exesql.py +3 -0
- api/apps/document_app.py +44 -1
- api/apps/kb_app.py +16 -7
- api/db/services/document_service.py +28 -1
- api/db/services/knowledgebase_service.py +23 -1
- api/settings.py +3 -3
agent/component/exesql.py
CHANGED
|
@@ -45,6 +45,9 @@ class ExeSQLParam(ComponentParamBase):
|
|
| 45 |
self.check_positive_integer(self.port, "IP Port")
|
| 46 |
self.check_empty(self.password, "Database password")
|
| 47 |
self.check_positive_integer(self.top_n, "Number of records")
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
|
| 50 |
class ExeSQL(ComponentBase, ABC):
|
|
|
|
| 45 |
self.check_positive_integer(self.port, "IP Port")
|
| 46 |
self.check_empty(self.password, "Database password")
|
| 47 |
self.check_positive_integer(self.top_n, "Number of records")
|
| 48 |
+
if self.database == "rag_flow":
|
| 49 |
+
if self.host == "ragflow-mysql": raise ValueError("The host is not accessible.")
|
| 50 |
+
if self.password == "infini_rag_flow": raise ValueError("The host is not accessible.")
|
| 51 |
|
| 52 |
|
| 53 |
class ExeSQL(ComponentBase, ABC):
|
api/apps/document_app.py
CHANGED
|
@@ -209,9 +209,17 @@ def list_docs():
|
|
| 209 |
|
| 210 |
|
| 211 |
@manager.route('/infos', methods=['POST'])
|
|
|
|
| 212 |
def docinfos():
|
| 213 |
req = request.json
|
| 214 |
doc_ids = req["doc_ids"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
docs = DocumentService.get_by_ids(doc_ids)
|
| 216 |
return get_json_result(data=list(docs.dicts()))
|
| 217 |
|
|
@@ -242,11 +250,17 @@ def thumbnails():
|
|
| 242 |
def change_status():
|
| 243 |
req = request.json
|
| 244 |
if str(req["status"]) not in ["0", "1"]:
|
| 245 |
-
get_json_result(
|
| 246 |
data=False,
|
| 247 |
retmsg='"Status" must be either 0 or 1!',
|
| 248 |
retcode=RetCode.ARGUMENT_ERROR)
|
| 249 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
try:
|
| 251 |
e, doc = DocumentService.get_by_id(req["doc_id"])
|
| 252 |
if not e:
|
|
@@ -285,6 +299,15 @@ def rm():
|
|
| 285 |
req = request.json
|
| 286 |
doc_ids = req["doc_id"]
|
| 287 |
if isinstance(doc_ids, str): doc_ids = [doc_ids]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
root_folder = FileService.get_root_folder(current_user.id)
|
| 289 |
pf_id = root_folder["id"]
|
| 290 |
FileService.init_knowledgebase_docs(pf_id, current_user.id)
|
|
@@ -323,6 +346,13 @@ def rm():
|
|
| 323 |
@validate_request("doc_ids", "run")
|
| 324 |
def run():
|
| 325 |
req = request.json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 326 |
try:
|
| 327 |
for id in req["doc_ids"]:
|
| 328 |
info = {"run": str(req["run"]), "progress": 0}
|
|
@@ -356,6 +386,12 @@ def run():
|
|
| 356 |
@validate_request("doc_id", "name")
|
| 357 |
def rename():
|
| 358 |
req = request.json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 359 |
try:
|
| 360 |
e, doc = DocumentService.get_by_id(req["doc_id"])
|
| 361 |
if not e:
|
|
@@ -416,6 +452,13 @@ def get(doc_id):
|
|
| 416 |
@validate_request("doc_id", "parser_id")
|
| 417 |
def change_parser():
|
| 418 |
req = request.json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 419 |
try:
|
| 420 |
e, doc = DocumentService.get_by_id(req["doc_id"])
|
| 421 |
if not e:
|
|
|
|
| 209 |
|
| 210 |
|
| 211 |
@manager.route('/infos', methods=['POST'])
|
| 212 |
+
@login_required
|
| 213 |
def docinfos():
|
| 214 |
req = request.json
|
| 215 |
doc_ids = req["doc_ids"]
|
| 216 |
+
for doc_id in doc_ids:
|
| 217 |
+
if not DocumentService.accessible(doc_id, current_user.id):
|
| 218 |
+
return get_json_result(
|
| 219 |
+
data=False,
|
| 220 |
+
retmsg='No authorization.',
|
| 221 |
+
retcode=RetCode.AUTHENTICATION_ERROR
|
| 222 |
+
)
|
| 223 |
docs = DocumentService.get_by_ids(doc_ids)
|
| 224 |
return get_json_result(data=list(docs.dicts()))
|
| 225 |
|
|
|
|
| 250 |
def change_status():
|
| 251 |
req = request.json
|
| 252 |
if str(req["status"]) not in ["0", "1"]:
|
| 253 |
+
return get_json_result(
|
| 254 |
data=False,
|
| 255 |
retmsg='"Status" must be either 0 or 1!',
|
| 256 |
retcode=RetCode.ARGUMENT_ERROR)
|
| 257 |
|
| 258 |
+
if not DocumentService.accessible(req["doc_id"], current_user.id):
|
| 259 |
+
return get_json_result(
|
| 260 |
+
data=False,
|
| 261 |
+
retmsg='No authorization.',
|
| 262 |
+
retcode=RetCode.AUTHENTICATION_ERROR)
|
| 263 |
+
|
| 264 |
try:
|
| 265 |
e, doc = DocumentService.get_by_id(req["doc_id"])
|
| 266 |
if not e:
|
|
|
|
| 299 |
req = request.json
|
| 300 |
doc_ids = req["doc_id"]
|
| 301 |
if isinstance(doc_ids, str): doc_ids = [doc_ids]
|
| 302 |
+
|
| 303 |
+
for doc_id in doc_ids:
|
| 304 |
+
if not DocumentService.accessible4deletion(doc_id, current_user.id):
|
| 305 |
+
return get_json_result(
|
| 306 |
+
data=False,
|
| 307 |
+
retmsg='No authorization.',
|
| 308 |
+
retcode=RetCode.AUTHENTICATION_ERROR
|
| 309 |
+
)
|
| 310 |
+
|
| 311 |
root_folder = FileService.get_root_folder(current_user.id)
|
| 312 |
pf_id = root_folder["id"]
|
| 313 |
FileService.init_knowledgebase_docs(pf_id, current_user.id)
|
|
|
|
| 346 |
@validate_request("doc_ids", "run")
|
| 347 |
def run():
|
| 348 |
req = request.json
|
| 349 |
+
for doc_id in req["doc_ids"]:
|
| 350 |
+
if not DocumentService.accessible(doc_id, current_user.id):
|
| 351 |
+
return get_json_result(
|
| 352 |
+
data=False,
|
| 353 |
+
retmsg='No authorization.',
|
| 354 |
+
retcode=RetCode.AUTHENTICATION_ERROR
|
| 355 |
+
)
|
| 356 |
try:
|
| 357 |
for id in req["doc_ids"]:
|
| 358 |
info = {"run": str(req["run"]), "progress": 0}
|
|
|
|
| 386 |
@validate_request("doc_id", "name")
|
| 387 |
def rename():
|
| 388 |
req = request.json
|
| 389 |
+
if not DocumentService.accessible(req["doc_id"], current_user.id):
|
| 390 |
+
return get_json_result(
|
| 391 |
+
data=False,
|
| 392 |
+
retmsg='No authorization.',
|
| 393 |
+
retcode=RetCode.AUTHENTICATION_ERROR
|
| 394 |
+
)
|
| 395 |
try:
|
| 396 |
e, doc = DocumentService.get_by_id(req["doc_id"])
|
| 397 |
if not e:
|
|
|
|
| 452 |
@validate_request("doc_id", "parser_id")
|
| 453 |
def change_parser():
|
| 454 |
req = request.json
|
| 455 |
+
|
| 456 |
+
if not DocumentService.accessible(req["doc_id"], current_user.id):
|
| 457 |
+
return get_json_result(
|
| 458 |
+
data=False,
|
| 459 |
+
retmsg='No authorization.',
|
| 460 |
+
retcode=RetCode.AUTHENTICATION_ERROR
|
| 461 |
+
)
|
| 462 |
try:
|
| 463 |
e, doc = DocumentService.get_by_id(req["doc_id"])
|
| 464 |
if not e:
|
api/apps/kb_app.py
CHANGED
|
@@ -13,7 +13,6 @@
|
|
| 13 |
# See the License for the specific language governing permissions and
|
| 14 |
# limitations under the License.
|
| 15 |
#
|
| 16 |
-
from elasticsearch_dsl import Q
|
| 17 |
from flask import request
|
| 18 |
from flask_login import login_required, current_user
|
| 19 |
|
|
@@ -23,14 +22,12 @@ from api.db.services.file2document_service import File2DocumentService
|
|
| 23 |
from api.db.services.file_service import FileService
|
| 24 |
from api.db.services.user_service import TenantService, UserTenantService
|
| 25 |
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
|
| 26 |
-
from api.utils import get_uuid
|
| 27 |
-
from api.db import StatusEnum,
|
| 28 |
from api.db.services.knowledgebase_service import KnowledgebaseService
|
| 29 |
-
from api.db.db_models import
|
| 30 |
-
from api.settings import
|
| 31 |
from api.utils.api_utils import get_json_result
|
| 32 |
-
from rag.nlp import search
|
| 33 |
-
from rag.utils.es_conn import ELASTICSEARCH
|
| 34 |
|
| 35 |
|
| 36 |
@manager.route('/create', methods=['post'])
|
|
@@ -65,6 +62,12 @@ def create():
|
|
| 65 |
def update():
|
| 66 |
req = request.json
|
| 67 |
req["name"] = req["name"].strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
try:
|
| 69 |
if not KnowledgebaseService.query(
|
| 70 |
created_by=current_user.id, id=req["kb_id"]):
|
|
@@ -139,6 +142,12 @@ def list_kbs():
|
|
| 139 |
@validate_request("kb_id")
|
| 140 |
def rm():
|
| 141 |
req = request.json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
try:
|
| 143 |
kbs = KnowledgebaseService.query(
|
| 144 |
created_by=current_user.id, id=req["kb_id"])
|
|
|
|
| 13 |
# See the License for the specific language governing permissions and
|
| 14 |
# limitations under the License.
|
| 15 |
#
|
|
|
|
| 16 |
from flask import request
|
| 17 |
from flask_login import login_required, current_user
|
| 18 |
|
|
|
|
| 22 |
from api.db.services.file_service import FileService
|
| 23 |
from api.db.services.user_service import TenantService, UserTenantService
|
| 24 |
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
|
| 25 |
+
from api.utils import get_uuid
|
| 26 |
+
from api.db import StatusEnum, FileSource
|
| 27 |
from api.db.services.knowledgebase_service import KnowledgebaseService
|
| 28 |
+
from api.db.db_models import File
|
| 29 |
+
from api.settings import RetCode
|
| 30 |
from api.utils.api_utils import get_json_result
|
|
|
|
|
|
|
| 31 |
|
| 32 |
|
| 33 |
@manager.route('/create', methods=['post'])
|
|
|
|
| 62 |
def update():
|
| 63 |
req = request.json
|
| 64 |
req["name"] = req["name"].strip()
|
| 65 |
+
if not KnowledgebaseService.accessible4deletion(req["kb_id"], current_user.id):
|
| 66 |
+
return get_json_result(
|
| 67 |
+
data=False,
|
| 68 |
+
retmsg='No authorization.',
|
| 69 |
+
retcode=RetCode.AUTHENTICATION_ERROR
|
| 70 |
+
)
|
| 71 |
try:
|
| 72 |
if not KnowledgebaseService.query(
|
| 73 |
created_by=current_user.id, id=req["kb_id"]):
|
|
|
|
| 142 |
@validate_request("kb_id")
|
| 143 |
def rm():
|
| 144 |
req = request.json
|
| 145 |
+
if not KnowledgebaseService.accessible4deletion(req["kb_id"], current_user.id):
|
| 146 |
+
return get_json_result(
|
| 147 |
+
data=False,
|
| 148 |
+
retmsg='No authorization.',
|
| 149 |
+
retcode=RetCode.AUTHENTICATION_ERROR
|
| 150 |
+
)
|
| 151 |
try:
|
| 152 |
kbs = KnowledgebaseService.query(
|
| 153 |
created_by=current_user.id, id=req["kb_id"])
|
api/db/services/document_service.py
CHANGED
|
@@ -38,7 +38,7 @@ from rag.utils.storage_factory import STORAGE_IMPL
|
|
| 38 |
from rag.nlp import search, rag_tokenizer
|
| 39 |
|
| 40 |
from api.db import FileType, TaskStatus, ParserType, LLMType
|
| 41 |
-
from api.db.db_models import DB, Knowledgebase, Tenant, Task
|
| 42 |
from api.db.db_models import Document
|
| 43 |
from api.db.services.common_service import CommonService
|
| 44 |
from api.db.services.knowledgebase_service import KnowledgebaseService
|
|
@@ -263,6 +263,33 @@ class DocumentService(CommonService):
|
|
| 263 |
return
|
| 264 |
return docs[0]["tenant_id"]
|
| 265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
@classmethod
|
| 267 |
@DB.connection_context()
|
| 268 |
def get_embd_id(cls, doc_id):
|
|
|
|
| 38 |
from rag.nlp import search, rag_tokenizer
|
| 39 |
|
| 40 |
from api.db import FileType, TaskStatus, ParserType, LLMType
|
| 41 |
+
from api.db.db_models import DB, Knowledgebase, Tenant, Task, UserTenant
|
| 42 |
from api.db.db_models import Document
|
| 43 |
from api.db.services.common_service import CommonService
|
| 44 |
from api.db.services.knowledgebase_service import KnowledgebaseService
|
|
|
|
| 263 |
return
|
| 264 |
return docs[0]["tenant_id"]
|
| 265 |
|
| 266 |
+
@classmethod
|
| 267 |
+
@DB.connection_context()
|
| 268 |
+
def accessible(cls, doc_id, user_id):
|
| 269 |
+
docs = cls.model.select(
|
| 270 |
+
cls.model.id).join(
|
| 271 |
+
Knowledgebase, on=(
|
| 272 |
+
Knowledgebase.id == cls.model.kb_id)
|
| 273 |
+
).join(UserTenant, on=(UserTenant.tenant_id == Knowledgebase.tenant_id)
|
| 274 |
+
).where(cls.model.id == doc_id, UserTenant.user_id == user_id).paginate(0, 1)
|
| 275 |
+
docs = docs.dicts()
|
| 276 |
+
if not docs:
|
| 277 |
+
return False
|
| 278 |
+
return True
|
| 279 |
+
|
| 280 |
+
@classmethod
|
| 281 |
+
@DB.connection_context()
|
| 282 |
+
def accessible4deletion(cls, doc_id, user_id):
|
| 283 |
+
docs = cls.model.select(
|
| 284 |
+
cls.model.id).join(
|
| 285 |
+
Knowledgebase, on=(
|
| 286 |
+
Knowledgebase.id == cls.model.kb_id)
|
| 287 |
+
).where(cls.model.id == doc_id, Knowledgebase.created_by == user_id).paginate(0, 1)
|
| 288 |
+
docs = docs.dicts()
|
| 289 |
+
if not docs:
|
| 290 |
+
return False
|
| 291 |
+
return True
|
| 292 |
+
|
| 293 |
@classmethod
|
| 294 |
@DB.connection_context()
|
| 295 |
def get_embd_id(cls, doc_id):
|
api/db/services/knowledgebase_service.py
CHANGED
|
@@ -14,7 +14,7 @@
|
|
| 14 |
# limitations under the License.
|
| 15 |
#
|
| 16 |
from api.db import StatusEnum, TenantPermission
|
| 17 |
-
from api.db.db_models import Knowledgebase, DB, Tenant, User
|
| 18 |
from api.db.services.common_service import CommonService
|
| 19 |
|
| 20 |
|
|
@@ -182,3 +182,25 @@ class KnowledgebaseService(CommonService):
|
|
| 182 |
kbs = kbs.paginate(page_number, items_per_page)
|
| 183 |
|
| 184 |
return list(kbs.dicts())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
# limitations under the License.
|
| 15 |
#
|
| 16 |
from api.db import StatusEnum, TenantPermission
|
| 17 |
+
from api.db.db_models import Knowledgebase, DB, Tenant, User, UserTenant
|
| 18 |
from api.db.services.common_service import CommonService
|
| 19 |
|
| 20 |
|
|
|
|
| 182 |
kbs = kbs.paginate(page_number, items_per_page)
|
| 183 |
|
| 184 |
return list(kbs.dicts())
|
| 185 |
+
|
| 186 |
+
@classmethod
|
| 187 |
+
@DB.connection_context()
|
| 188 |
+
def accessible(cls, kb_id, user_id):
|
| 189 |
+
docs = cls.model.select(
|
| 190 |
+
cls.model.id).join(UserTenant, on=(UserTenant.tenant_id == Knowledgebase.tenant_id)
|
| 191 |
+
).where(cls.model.id == kb_id, UserTenant.user_id == user_id).paginate(0, 1)
|
| 192 |
+
docs = docs.dicts()
|
| 193 |
+
if not docs:
|
| 194 |
+
return False
|
| 195 |
+
return True
|
| 196 |
+
|
| 197 |
+
@classmethod
|
| 198 |
+
@DB.connection_context()
|
| 199 |
+
def accessible4deletion(cls, kb_id, user_id):
|
| 200 |
+
docs = cls.model.select(
|
| 201 |
+
cls.model.id).where(cls.model.id == kb_id, cls.model.created_by == user_id).paginate(0, 1)
|
| 202 |
+
docs = docs.dicts()
|
| 203 |
+
if not docs:
|
| 204 |
+
return False
|
| 205 |
+
return True
|
| 206 |
+
|
api/settings.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
| 14 |
# limitations under the License.
|
| 15 |
#
|
| 16 |
import os
|
|
|
|
| 17 |
from enum import IntEnum, Enum
|
| 18 |
from api.utils.file_utils import get_project_base_directory
|
| 19 |
from api.utils.log_utils import LoggerFactory, getLogger
|
|
@@ -143,9 +144,8 @@ HTTP_PORT = get_base_config(RAG_FLOW_SERVICE_NAME, {}).get("http_port")
|
|
| 143 |
|
| 144 |
SECRET_KEY = get_base_config(
|
| 145 |
RAG_FLOW_SERVICE_NAME,
|
| 146 |
-
{}).get(
|
| 147 |
-
|
| 148 |
-
"infiniflow")
|
| 149 |
TOKEN_EXPIRE_IN = get_base_config(
|
| 150 |
RAG_FLOW_SERVICE_NAME, {}).get(
|
| 151 |
"token_expires_in", 3600)
|
|
|
|
| 14 |
# limitations under the License.
|
| 15 |
#
|
| 16 |
import os
|
| 17 |
+
from datetime import date
|
| 18 |
from enum import IntEnum, Enum
|
| 19 |
from api.utils.file_utils import get_project_base_directory
|
| 20 |
from api.utils.log_utils import LoggerFactory, getLogger
|
|
|
|
| 144 |
|
| 145 |
SECRET_KEY = get_base_config(
|
| 146 |
RAG_FLOW_SERVICE_NAME,
|
| 147 |
+
{}).get("secret_key", str(date.today()))
|
| 148 |
+
|
|
|
|
| 149 |
TOKEN_EXPIRE_IN = get_base_config(
|
| 150 |
RAG_FLOW_SERVICE_NAME, {}).get(
|
| 151 |
"token_expires_in", 3600)
|