Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. #
  2. # Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. import json
  17. import logging
  18. import re
  19. from datetime import datetime
  20. from flask import redirect, request, session
  21. from flask_login import current_user, login_required, login_user, logout_user
  22. from werkzeug.security import check_password_hash, generate_password_hash
  23. from api import settings
  24. from api.apps.auth import get_auth_client
  25. from api.db import FileType, UserTenantRole
  26. from api.db.db_models import TenantLLM
  27. from api.db.services.file_service import FileService
  28. from api.db.services.llm_service import LLMService, TenantLLMService
  29. from api.db.services.user_service import TenantService, UserService, UserTenantService
  30. from api.utils import (
  31. current_timestamp,
  32. datetime_format,
  33. decrypt,
  34. download_img,
  35. get_format_time,
  36. get_uuid,
  37. )
  38. from api.utils.api_utils import (
  39. construct_response,
  40. get_data_error_result,
  41. get_json_result,
  42. server_error_response,
  43. validate_request,
  44. )
  45. @manager.route("/login", methods=["POST", "GET"]) # noqa: F821
  46. def login():
  47. """
  48. User login endpoint.
  49. ---
  50. tags:
  51. - User
  52. parameters:
  53. - in: body
  54. name: body
  55. description: Login credentials.
  56. required: true
  57. schema:
  58. type: object
  59. properties:
  60. email:
  61. type: string
  62. description: User email.
  63. password:
  64. type: string
  65. description: User password.
  66. responses:
  67. 200:
  68. description: Login successful.
  69. schema:
  70. type: object
  71. 401:
  72. description: Authentication failed.
  73. schema:
  74. type: object
  75. """
  76. if not request.json:
  77. return get_json_result(data=False, code=settings.RetCode.AUTHENTICATION_ERROR, message="Unauthorized!")
  78. email = request.json.get("email", "")
  79. users = UserService.query(email=email)
  80. if not users:
  81. return get_json_result(
  82. data=False,
  83. code=settings.RetCode.AUTHENTICATION_ERROR,
  84. message=f"Email: {email} is not registered!",
  85. )
  86. password = request.json.get("password")
  87. try:
  88. password = decrypt(password)
  89. except BaseException:
  90. return get_json_result(data=False, code=settings.RetCode.SERVER_ERROR, message="Fail to crypt password")
  91. user = UserService.query_user(email, password)
  92. if user:
  93. response_data = user.to_json()
  94. user.access_token = get_uuid()
  95. login_user(user)
  96. user.update_time = (current_timestamp(),)
  97. user.update_date = (datetime_format(datetime.now()),)
  98. user.save()
  99. msg = "Welcome back!"
  100. return construct_response(data=response_data, auth=user.get_id(), message=msg)
  101. else:
  102. return get_json_result(
  103. data=False,
  104. code=settings.RetCode.AUTHENTICATION_ERROR,
  105. message="Email and password do not match!",
  106. )
  107. @manager.route("/login/channels", methods=["GET"]) # noqa: F821
  108. def get_login_channels():
  109. """
  110. Get all supported authentication channels.
  111. """
  112. try:
  113. channels = []
  114. for channel, config in settings.OAUTH_CONFIG.items():
  115. channels.append(
  116. {
  117. "channel": channel,
  118. "display_name": config.get("display_name", channel.title()),
  119. "icon": config.get("icon", "sso"),
  120. }
  121. )
  122. return get_json_result(data=channels)
  123. except Exception as e:
  124. logging.exception(e)
  125. return get_json_result(data=[], message=f"Load channels failure, error: {str(e)}", code=settings.RetCode.EXCEPTION_ERROR)
  126. @manager.route("/login/<channel>", methods=["GET"]) # noqa: F821
  127. def oauth_login(channel):
  128. channel_config = settings.OAUTH_CONFIG.get(channel)
  129. if not channel_config:
  130. raise ValueError(f"Invalid channel name: {channel}")
  131. auth_cli = get_auth_client(channel_config)
  132. state = get_uuid()
  133. session["oauth_state"] = state
  134. auth_url = auth_cli.get_authorization_url(state)
  135. return redirect(auth_url)
  136. @manager.route("/oauth/callback/<channel>", methods=["GET"]) # noqa: F821
  137. def oauth_callback(channel):
  138. """
  139. Handle the OAuth/OIDC callback for various channels dynamically.
  140. """
  141. try:
  142. channel_config = settings.OAUTH_CONFIG.get(channel)
  143. if not channel_config:
  144. raise ValueError(f"Invalid channel name: {channel}")
  145. auth_cli = get_auth_client(channel_config)
  146. # Check the state
  147. state = request.args.get("state")
  148. if not state or state != session.get("oauth_state"):
  149. return redirect("/?error=invalid_state")
  150. session.pop("oauth_state", None)
  151. # Obtain the authorization code
  152. code = request.args.get("code")
  153. if not code:
  154. return redirect("/?error=missing_code")
  155. # Exchange authorization code for access token
  156. token_info = auth_cli.exchange_code_for_token(code)
  157. access_token = token_info.get("access_token")
  158. if not access_token:
  159. return redirect("/?error=token_failed")
  160. id_token = token_info.get("id_token")
  161. # Fetch user info
  162. user_info = auth_cli.fetch_user_info(access_token, id_token=id_token)
  163. if not user_info.email:
  164. return redirect("/?error=email_missing")
  165. # Login or register
  166. users = UserService.query(email=user_info.email)
  167. user_id = get_uuid()
  168. if not users:
  169. try:
  170. try:
  171. avatar = download_img(user_info.avatar_url)
  172. except Exception as e:
  173. logging.exception(e)
  174. avatar = ""
  175. users = user_register(
  176. user_id,
  177. {
  178. "access_token": get_uuid(),
  179. "email": user_info.email,
  180. "avatar": avatar,
  181. "nickname": user_info.nickname,
  182. "login_channel": channel,
  183. "last_login_time": get_format_time(),
  184. "is_superuser": False,
  185. },
  186. )
  187. if not users:
  188. raise Exception(f"Failed to register {user_info.email}")
  189. if len(users) > 1:
  190. raise Exception(f"Same email: {user_info.email} exists!")
  191. # Try to log in
  192. user = users[0]
  193. login_user(user)
  194. return redirect(f"/?auth={user.get_id()}")
  195. except Exception as e:
  196. rollback_user_registration(user_id)
  197. logging.exception(e)
  198. return redirect(f"/?error={str(e)}")
  199. # User exists, try to log in
  200. user = users[0]
  201. user.access_token = get_uuid()
  202. login_user(user)
  203. user.save()
  204. return redirect(f"/?auth={user.get_id()}")
  205. except Exception as e:
  206. logging.exception(e)
  207. return redirect(f"/?error={str(e)}")
  208. @manager.route("/github_callback", methods=["GET"]) # noqa: F821
  209. def github_callback():
  210. """
  211. **Deprecated**, Use `/oauth/callback/<channel>` instead.
  212. GitHub OAuth callback endpoint.
  213. ---
  214. tags:
  215. - OAuth
  216. parameters:
  217. - in: query
  218. name: code
  219. type: string
  220. required: true
  221. description: Authorization code from GitHub.
  222. responses:
  223. 200:
  224. description: Authentication successful.
  225. schema:
  226. type: object
  227. """
  228. import requests
  229. res = requests.post(
  230. settings.GITHUB_OAUTH.get("url"),
  231. data={
  232. "client_id": settings.GITHUB_OAUTH.get("client_id"),
  233. "client_secret": settings.GITHUB_OAUTH.get("secret_key"),
  234. "code": request.args.get("code"),
  235. },
  236. headers={"Accept": "application/json"},
  237. )
  238. res = res.json()
  239. if "error" in res:
  240. return redirect("/?error=%s" % res["error_description"])
  241. if "user:email" not in res["scope"].split(","):
  242. return redirect("/?error=user:email not in scope")
  243. session["access_token"] = res["access_token"]
  244. session["access_token_from"] = "github"
  245. user_info = user_info_from_github(session["access_token"])
  246. email_address = user_info["email"]
  247. users = UserService.query(email=email_address)
  248. user_id = get_uuid()
  249. if not users:
  250. # User isn't try to register
  251. try:
  252. try:
  253. avatar = download_img(user_info["avatar_url"])
  254. except Exception as e:
  255. logging.exception(e)
  256. avatar = ""
  257. users = user_register(
  258. user_id,
  259. {
  260. "access_token": session["access_token"],
  261. "email": email_address,
  262. "avatar": avatar,
  263. "nickname": user_info["login"],
  264. "login_channel": "github",
  265. "last_login_time": get_format_time(),
  266. "is_superuser": False,
  267. },
  268. )
  269. if not users:
  270. raise Exception(f"Fail to register {email_address}.")
  271. if len(users) > 1:
  272. raise Exception(f"Same email: {email_address} exists!")
  273. # Try to log in
  274. user = users[0]
  275. login_user(user)
  276. return redirect("/?auth=%s" % user.get_id())
  277. except Exception as e:
  278. rollback_user_registration(user_id)
  279. logging.exception(e)
  280. return redirect("/?error=%s" % str(e))
  281. # User has already registered, try to log in
  282. user = users[0]
  283. user.access_token = get_uuid()
  284. login_user(user)
  285. user.save()
  286. return redirect("/?auth=%s" % user.get_id())
  287. @manager.route("/feishu_callback", methods=["GET"]) # noqa: F821
  288. def feishu_callback():
  289. """
  290. Feishu OAuth callback endpoint.
  291. ---
  292. tags:
  293. - OAuth
  294. parameters:
  295. - in: query
  296. name: code
  297. type: string
  298. required: true
  299. description: Authorization code from Feishu.
  300. responses:
  301. 200:
  302. description: Authentication successful.
  303. schema:
  304. type: object
  305. """
  306. import requests
  307. app_access_token_res = requests.post(
  308. settings.FEISHU_OAUTH.get("app_access_token_url"),
  309. data=json.dumps(
  310. {
  311. "app_id": settings.FEISHU_OAUTH.get("app_id"),
  312. "app_secret": settings.FEISHU_OAUTH.get("app_secret"),
  313. }
  314. ),
  315. headers={"Content-Type": "application/json; charset=utf-8"},
  316. )
  317. app_access_token_res = app_access_token_res.json()
  318. if app_access_token_res["code"] != 0:
  319. return redirect("/?error=%s" % app_access_token_res)
  320. res = requests.post(
  321. settings.FEISHU_OAUTH.get("user_access_token_url"),
  322. data=json.dumps(
  323. {
  324. "grant_type": settings.FEISHU_OAUTH.get("grant_type"),
  325. "code": request.args.get("code"),
  326. }
  327. ),
  328. headers={
  329. "Content-Type": "application/json; charset=utf-8",
  330. "Authorization": f"Bearer {app_access_token_res['app_access_token']}",
  331. },
  332. )
  333. res = res.json()
  334. if res["code"] != 0:
  335. return redirect("/?error=%s" % res["message"])
  336. if "contact:user.email:readonly" not in res["data"]["scope"].split():
  337. return redirect("/?error=contact:user.email:readonly not in scope")
  338. session["access_token"] = res["data"]["access_token"]
  339. session["access_token_from"] = "feishu"
  340. user_info = user_info_from_feishu(session["access_token"])
  341. email_address = user_info["email"]
  342. users = UserService.query(email=email_address)
  343. user_id = get_uuid()
  344. if not users:
  345. # User isn't try to register
  346. try:
  347. try:
  348. avatar = download_img(user_info["avatar_url"])
  349. except Exception as e:
  350. logging.exception(e)
  351. avatar = ""
  352. users = user_register(
  353. user_id,
  354. {
  355. "access_token": session["access_token"],
  356. "email": email_address,
  357. "avatar": avatar,
  358. "nickname": user_info["en_name"],
  359. "login_channel": "feishu",
  360. "last_login_time": get_format_time(),
  361. "is_superuser": False,
  362. },
  363. )
  364. if not users:
  365. raise Exception(f"Fail to register {email_address}.")
  366. if len(users) > 1:
  367. raise Exception(f"Same email: {email_address} exists!")
  368. # Try to log in
  369. user = users[0]
  370. login_user(user)
  371. return redirect("/?auth=%s" % user.get_id())
  372. except Exception as e:
  373. rollback_user_registration(user_id)
  374. logging.exception(e)
  375. return redirect("/?error=%s" % str(e))
  376. # User has already registered, try to log in
  377. user = users[0]
  378. user.access_token = get_uuid()
  379. login_user(user)
  380. user.save()
  381. return redirect("/?auth=%s" % user.get_id())
  382. def user_info_from_feishu(access_token):
  383. import requests
  384. headers = {
  385. "Content-Type": "application/json; charset=utf-8",
  386. "Authorization": f"Bearer {access_token}",
  387. }
  388. res = requests.get("https://open.feishu.cn/open-apis/authen/v1/user_info", headers=headers)
  389. user_info = res.json()["data"]
  390. user_info["email"] = None if user_info.get("email") == "" else user_info["email"]
  391. return user_info
  392. def user_info_from_github(access_token):
  393. import requests
  394. headers = {"Accept": "application/json", "Authorization": f"token {access_token}"}
  395. res = requests.get(f"https://api.github.com/user?access_token={access_token}", headers=headers)
  396. user_info = res.json()
  397. email_info = requests.get(
  398. f"https://api.github.com/user/emails?access_token={access_token}",
  399. headers=headers,
  400. ).json()
  401. user_info["email"] = next((email for email in email_info if email["primary"]), None)["email"]
  402. return user_info
  403. @manager.route("/logout", methods=["GET"]) # noqa: F821
  404. @login_required
  405. def log_out():
  406. """
  407. User logout endpoint.
  408. ---
  409. tags:
  410. - User
  411. security:
  412. - ApiKeyAuth: []
  413. responses:
  414. 200:
  415. description: Logout successful.
  416. schema:
  417. type: object
  418. """
  419. current_user.access_token = ""
  420. current_user.save()
  421. logout_user()
  422. return get_json_result(data=True)
  423. @manager.route("/setting", methods=["POST"]) # noqa: F821
  424. @login_required
  425. def setting_user():
  426. """
  427. Update user settings.
  428. ---
  429. tags:
  430. - User
  431. security:
  432. - ApiKeyAuth: []
  433. parameters:
  434. - in: body
  435. name: body
  436. description: User settings to update.
  437. required: true
  438. schema:
  439. type: object
  440. properties:
  441. nickname:
  442. type: string
  443. description: New nickname.
  444. email:
  445. type: string
  446. description: New email.
  447. responses:
  448. 200:
  449. description: Settings updated successfully.
  450. schema:
  451. type: object
  452. """
  453. update_dict = {}
  454. request_data = request.json
  455. if request_data.get("password"):
  456. new_password = request_data.get("new_password")
  457. if not check_password_hash(current_user.password, decrypt(request_data["password"])):
  458. return get_json_result(
  459. data=False,
  460. code=settings.RetCode.AUTHENTICATION_ERROR,
  461. message="Password error!",
  462. )
  463. if new_password:
  464. update_dict["password"] = generate_password_hash(decrypt(new_password))
  465. for k in request_data.keys():
  466. if k in [
  467. "password",
  468. "new_password",
  469. "email",
  470. "status",
  471. "is_superuser",
  472. "login_channel",
  473. "is_anonymous",
  474. "is_active",
  475. "is_authenticated",
  476. "last_login_time",
  477. ]:
  478. continue
  479. update_dict[k] = request_data[k]
  480. try:
  481. UserService.update_by_id(current_user.id, update_dict)
  482. return get_json_result(data=True)
  483. except Exception as e:
  484. logging.exception(e)
  485. return get_json_result(data=False, message="Update failure!", code=settings.RetCode.EXCEPTION_ERROR)
  486. @manager.route("/info", methods=["GET"]) # noqa: F821
  487. @login_required
  488. def user_profile():
  489. """
  490. Get user profile information.
  491. ---
  492. tags:
  493. - User
  494. security:
  495. - ApiKeyAuth: []
  496. responses:
  497. 200:
  498. description: User profile retrieved successfully.
  499. schema:
  500. type: object
  501. properties:
  502. id:
  503. type: string
  504. description: User ID.
  505. nickname:
  506. type: string
  507. description: User nickname.
  508. email:
  509. type: string
  510. description: User email.
  511. """
  512. return get_json_result(data=current_user.to_dict())
  513. def rollback_user_registration(user_id):
  514. try:
  515. UserService.delete_by_id(user_id)
  516. except Exception:
  517. pass
  518. try:
  519. TenantService.delete_by_id(user_id)
  520. except Exception:
  521. pass
  522. try:
  523. u = UserTenantService.query(tenant_id=user_id)
  524. if u:
  525. UserTenantService.delete_by_id(u[0].id)
  526. except Exception:
  527. pass
  528. try:
  529. TenantLLM.delete().where(TenantLLM.tenant_id == user_id).execute()
  530. except Exception:
  531. pass
  532. def user_register(user_id, user):
  533. user["id"] = user_id
  534. tenant = {
  535. "id": user_id,
  536. "name": user["nickname"] + "‘s Kingdom",
  537. "llm_id": settings.CHAT_MDL,
  538. "embd_id": settings.EMBEDDING_MDL,
  539. "asr_id": settings.ASR_MDL,
  540. "parser_ids": settings.PARSERS,
  541. "img2txt_id": settings.IMAGE2TEXT_MDL,
  542. "rerank_id": settings.RERANK_MDL,
  543. }
  544. usr_tenant = {
  545. "tenant_id": user_id,
  546. "user_id": user_id,
  547. "invited_by": user_id,
  548. "role": UserTenantRole.OWNER,
  549. }
  550. file_id = get_uuid()
  551. file = {
  552. "id": file_id,
  553. "parent_id": file_id,
  554. "tenant_id": user_id,
  555. "created_by": user_id,
  556. "name": "/",
  557. "type": FileType.FOLDER.value,
  558. "size": 0,
  559. "location": "",
  560. }
  561. tenant_llm = []
  562. for llm in LLMService.query(fid=settings.LLM_FACTORY):
  563. tenant_llm.append(
  564. {
  565. "tenant_id": user_id,
  566. "llm_factory": settings.LLM_FACTORY,
  567. "llm_name": llm.llm_name,
  568. "model_type": llm.model_type,
  569. "api_key": settings.API_KEY,
  570. "api_base": settings.LLM_BASE_URL,
  571. "max_tokens": llm.max_tokens if llm.max_tokens else 8192,
  572. }
  573. )
  574. if settings.LIGHTEN != 1:
  575. for buildin_embedding_model in settings.BUILTIN_EMBEDDING_MODELS:
  576. mdlnm, fid = TenantLLMService.split_model_name_and_factory(buildin_embedding_model)
  577. tenant_llm.append(
  578. {
  579. "tenant_id": user_id,
  580. "llm_factory": fid,
  581. "llm_name": mdlnm,
  582. "model_type": "embedding",
  583. "api_key": "",
  584. "api_base": "",
  585. "max_tokens": 1024 if buildin_embedding_model == "BAAI/bge-large-zh-v1.5@BAAI" else 512,
  586. }
  587. )
  588. if not UserService.save(**user):
  589. return
  590. TenantService.insert(**tenant)
  591. UserTenantService.insert(**usr_tenant)
  592. TenantLLMService.insert_many(tenant_llm)
  593. FileService.insert(file)
  594. return UserService.query(email=user["email"])
  595. @manager.route("/register", methods=["POST"]) # noqa: F821
  596. @validate_request("nickname", "email", "password")
  597. def user_add():
  598. """
  599. Register a new user.
  600. ---
  601. tags:
  602. - User
  603. parameters:
  604. - in: body
  605. name: body
  606. description: Registration details.
  607. required: true
  608. schema:
  609. type: object
  610. properties:
  611. nickname:
  612. type: string
  613. description: User nickname.
  614. email:
  615. type: string
  616. description: User email.
  617. password:
  618. type: string
  619. description: User password.
  620. responses:
  621. 200:
  622. description: Registration successful.
  623. schema:
  624. type: object
  625. """
  626. if not settings.REGISTER_ENABLED:
  627. return get_json_result(
  628. data=False,
  629. message="User registration is disabled!",
  630. code=settings.RetCode.OPERATING_ERROR,
  631. )
  632. req = request.json
  633. email_address = req["email"]
  634. # Validate the email address
  635. if not re.match(r"^[\w\._-]+@([\w_-]+\.)+[\w-]{2,}$", email_address):
  636. return get_json_result(
  637. data=False,
  638. message=f"Invalid email address: {email_address}!",
  639. code=settings.RetCode.OPERATING_ERROR,
  640. )
  641. # Check if the email address is already used
  642. if UserService.query(email=email_address):
  643. return get_json_result(
  644. data=False,
  645. message=f"Email: {email_address} has already registered!",
  646. code=settings.RetCode.OPERATING_ERROR,
  647. )
  648. # Construct user info data
  649. nickname = req["nickname"]
  650. user_dict = {
  651. "access_token": get_uuid(),
  652. "email": email_address,
  653. "nickname": nickname,
  654. "password": decrypt(req["password"]),
  655. "login_channel": "password",
  656. "last_login_time": get_format_time(),
  657. "is_superuser": False,
  658. }
  659. user_id = get_uuid()
  660. try:
  661. users = user_register(user_id, user_dict)
  662. if not users:
  663. raise Exception(f"Fail to register {email_address}.")
  664. if len(users) > 1:
  665. raise Exception(f"Same email: {email_address} exists!")
  666. user = users[0]
  667. login_user(user)
  668. return construct_response(
  669. data=user.to_json(),
  670. auth=user.get_id(),
  671. message=f"{nickname}, welcome aboard!",
  672. )
  673. except Exception as e:
  674. rollback_user_registration(user_id)
  675. logging.exception(e)
  676. return get_json_result(
  677. data=False,
  678. message=f"User registration failure, error: {str(e)}",
  679. code=settings.RetCode.EXCEPTION_ERROR,
  680. )
  681. @manager.route("/tenant_info", methods=["GET"]) # noqa: F821
  682. @login_required
  683. def tenant_info():
  684. """
  685. Get tenant information.
  686. ---
  687. tags:
  688. - Tenant
  689. security:
  690. - ApiKeyAuth: []
  691. responses:
  692. 200:
  693. description: Tenant information retrieved successfully.
  694. schema:
  695. type: object
  696. properties:
  697. tenant_id:
  698. type: string
  699. description: Tenant ID.
  700. name:
  701. type: string
  702. description: Tenant name.
  703. llm_id:
  704. type: string
  705. description: LLM ID.
  706. embd_id:
  707. type: string
  708. description: Embedding model ID.
  709. """
  710. try:
  711. tenants = TenantService.get_info_by(current_user.id)
  712. if not tenants:
  713. return get_data_error_result(message="Tenant not found!")
  714. return get_json_result(data=tenants[0])
  715. except Exception as e:
  716. return server_error_response(e)
  717. @manager.route("/set_tenant_info", methods=["POST"]) # noqa: F821
  718. @login_required
  719. @validate_request("tenant_id", "asr_id", "embd_id", "img2txt_id", "llm_id")
  720. def set_tenant_info():
  721. """
  722. Update tenant information.
  723. ---
  724. tags:
  725. - Tenant
  726. security:
  727. - ApiKeyAuth: []
  728. parameters:
  729. - in: body
  730. name: body
  731. description: Tenant information to update.
  732. required: true
  733. schema:
  734. type: object
  735. properties:
  736. tenant_id:
  737. type: string
  738. description: Tenant ID.
  739. llm_id:
  740. type: string
  741. description: LLM ID.
  742. embd_id:
  743. type: string
  744. description: Embedding model ID.
  745. asr_id:
  746. type: string
  747. description: ASR model ID.
  748. img2txt_id:
  749. type: string
  750. description: Image to Text model ID.
  751. responses:
  752. 200:
  753. description: Tenant information updated successfully.
  754. schema:
  755. type: object
  756. """
  757. req = request.json
  758. try:
  759. tid = req.pop("tenant_id")
  760. TenantService.update_by_id(tid, req)
  761. return get_json_result(data=True)
  762. except Exception as e:
  763. return server_error_response(e)