浏览代码

suhh-暂存

‘suhuihui’ 3 月之前
父节点
当前提交
901a14d72b

+ 37 - 1
api/controllers/console/app/app.py

@@ -1,11 +1,12 @@
 import uuid
 import uuid
 from typing import cast
 from typing import cast
 
 
+from flask import jsonify, request
 from flask_login import current_user  # type: ignore
 from flask_login import current_user  # type: ignore
 from flask_restful import Resource, inputs, marshal, marshal_with, reqparse  # type: ignore
 from flask_restful import Resource, inputs, marshal, marshal_with, reqparse  # type: ignore
 from sqlalchemy import select
 from sqlalchemy import select
 from sqlalchemy.orm import Session
 from sqlalchemy.orm import Session
-from werkzeug.exceptions import BadRequest, Forbidden, abort
+from werkzeug.exceptions import BadRequest, Forbidden, NotFound, abort
 
 
 from controllers.console import api
 from controllers.console import api
 from controllers.console.app.wraps import get_app_model
 from controllers.console.app.wraps import get_app_model
@@ -339,6 +340,40 @@ class AppTraceApi(Resource):
         return {"result": "success"}
         return {"result": "success"}
 
 
 
 
+class AppPermissionApi(Resource):
+    @setup_required
+    @login_required
+    @account_initialization_required
+    def post(self, app_id):
+        # add app permission
+        app_id = str(app_id)
+        app = AppService.get_app_by_id(app_id)
+        if not app:
+            raise NotFound("App not found.")
+        if not current_user.is_dataset_editor:
+            raise Forbidden()
+
+        # 解析表单数据
+        data = request.get_json()
+        if not data:
+            raise NotFound("Invalid JSON")
+
+        edit_auth = data.get("edit_auth")
+        if edit_auth is None:
+            return jsonify({"error": "Missing 'edit_auth' field"}), 400
+
+        read_permission_list = data.get("read_permission")
+        if read_permission_list is None:
+            return jsonify({"error": "Missing 'read_permission' field"}), 400
+        if not isinstance(read_permission_list, list):
+            return jsonify({"error": "'read_permission' should be a list"}), 400
+        # 更新知识库的编辑权限
+        AppService.update_app_edit_auth(app_id, edit_auth, current_user)
+        # 更新知识库的编辑、可见授权
+        AppService.update_app_read_permission(app_id, current_user, read_permission_list)
+        return {"result": "success"}, 204
+
+
 api.add_resource(AppListApi, "/apps")
 api.add_resource(AppListApi, "/apps")
 api.add_resource(AppApi, "/apps/<uuid:app_id>")
 api.add_resource(AppApi, "/apps/<uuid:app_id>")
 api.add_resource(AppCopyApi, "/apps/<uuid:app_id>/copy")
 api.add_resource(AppCopyApi, "/apps/<uuid:app_id>/copy")
@@ -348,3 +383,4 @@ api.add_resource(AppIconApi, "/apps/<uuid:app_id>/icon")
 api.add_resource(AppSiteStatus, "/apps/<uuid:app_id>/site-enable")
 api.add_resource(AppSiteStatus, "/apps/<uuid:app_id>/site-enable")
 api.add_resource(AppApiStatus, "/apps/<uuid:app_id>/api-enable")
 api.add_resource(AppApiStatus, "/apps/<uuid:app_id>/api-enable")
 api.add_resource(AppTraceApi, "/apps/<uuid:app_id>/trace")
 api.add_resource(AppTraceApi, "/apps/<uuid:app_id>/trace")
+api.add_resource(AppPermissionApi, "/apps/<uuid:app_id>/permission")

+ 2 - 0
api/controllers/console/workspace/members.py

@@ -53,8 +53,10 @@ class MemberInviteEmailApi(Resource):
 
 
         inviter = current_user
         inviter = current_user
         invitation_results = []
         invitation_results = []
+        print("打印1:")
         console_web_url = dify_config.CONSOLE_WEB_URL
         console_web_url = dify_config.CONSOLE_WEB_URL
         for invitee_email in invitee_emails:
         for invitee_email in invitee_emails:
+            print("打印5:")
             try:
             try:
                 token = RegisterService.invite_new_member(
                 token = RegisterService.invite_new_member(
                     inviter.current_tenant, invitee_email, interface_language, role=invitee_role, inviter=inviter
                     inviter.current_tenant, invitee_email, interface_language, role=invitee_role, inviter=inviter

+ 22 - 0
api/models/model.py

@@ -103,6 +103,8 @@ class App(Base):
     updated_by = db.Column(StringUUID, nullable=True)
     updated_by = db.Column(StringUUID, nullable=True)
     updated_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
     updated_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
     use_icon_as_answer_icon = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
     use_icon_as_answer_icon = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
+    dept_id = db.Column(StringUUID, nullable=True)
+    edit_auth = db.Column(db.Integer, nullable=False)
 
 
     @property
     @property
     def desc_or_prompt(self):
     def desc_or_prompt(self):
@@ -1827,3 +1829,23 @@ class TraceAppConfig(Base):
             "created_at": str(self.created_at) if self.created_at else None,
             "created_at": str(self.created_at) if self.created_at else None,
             "updated_at": str(self.updated_at) if self.updated_at else None,
             "updated_at": str(self.updated_at) if self.updated_at else None,
         }
         }
+
+
+class AppPermissionAll(db.Model):  # type: ignore[name-defined]
+    __tablename__ = "app_permissions_all"
+    __table_args__ = (
+        db.PrimaryKeyConstraint("id", name="app_permission_pkey"),
+        db.Index("idx_app_permissions_dataset_id", "app_id"),
+        db.Index("idx_app_permissions_account_id", "account_id"),
+    )
+
+    id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"), primary_key=True)
+    app_id = db.Column(StringUUID, nullable=False)
+    account_id = db.Column(StringUUID, nullable=False)
+    tenant_id = db.Column(StringUUID, nullable=False)
+    has_read_permission = db.Column(db.Boolean, nullable=False, server_default=db.text("true"))
+    created_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
+    created_by = db.Column(StringUUID, nullable=False)
+    updated_by = db.Column(StringUUID, nullable=True)
+    updated_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
+    email = db.Column(db.String(255), nullable=False)

+ 15 - 9
api/services/account_service.py

@@ -3,6 +3,7 @@ import json
 import logging
 import logging
 import random
 import random
 import secrets
 import secrets
+import uuid
 from datetime import UTC, datetime, timedelta
 from datetime import UTC, datetime, timedelta
 from hashlib import sha256
 from hashlib import sha256
 from typing import Any, Optional, cast
 from typing import Any, Optional, cast
@@ -224,19 +225,19 @@ class AccountService:
         account = Account()
         account = Account()
         account.email = email
         account.email = email
         account.name = name
         account.name = name
-
-        if password:
+        password = email
+        if account.password is None:
             # generate password salt
             # generate password salt
             salt = secrets.token_bytes(16)
             salt = secrets.token_bytes(16)
             base64_salt = base64.b64encode(salt).decode()
             base64_salt = base64.b64encode(salt).decode()
-
             # encrypt password with salt
             # encrypt password with salt
             password_hashed = hash_password(password, salt)
             password_hashed = hash_password(password, salt)
             base64_password_hashed = base64.b64encode(password_hashed).decode()
             base64_password_hashed = base64.b64encode(password_hashed).decode()
 
 
             account.password = base64_password_hashed
             account.password = base64_password_hashed
             account.password_salt = base64_salt
             account.password_salt = base64_salt
-
+        print("新注册账号密码:" + account.password)
+        print("新注册账号密码:" + account.password_salt)
         account.interface_language = interface_language
         account.interface_language = interface_language
         account.interface_theme = interface_theme
         account.interface_theme = interface_theme
 
 
@@ -661,6 +662,7 @@ class TenantService:
     @staticmethod
     @staticmethod
     def create_tenant_member(tenant: Tenant, account: Account, role: str = "normal") -> TenantAccountJoin:
     def create_tenant_member(tenant: Tenant, account: Account, role: str = "normal") -> TenantAccountJoin:
         """Create tenant member"""
         """Create tenant member"""
+        print("打印4:")
         if role == TenantAccountRole.OWNER.value:
         if role == TenantAccountRole.OWNER.value:
             if TenantService.has_roles(tenant, [TenantAccountRole.OWNER]):
             if TenantService.has_roles(tenant, [TenantAccountRole.OWNER]):
                 logging.error(f"Tenant {tenant.id} has already an owner.")
                 logging.error(f"Tenant {tenant.id} has already an owner.")
@@ -707,7 +709,7 @@ class TenantService:
         # Ensure tenant_id is provided
         # Ensure tenant_id is provided
         if tenant_id is None:
         if tenant_id is None:
             raise ValueError("Tenant ID must be provided.")
             raise ValueError("Tenant ID must be provided.")
-
+        print("打印4:")
         tenant_account_join = (
         tenant_account_join = (
             db.session.query(TenantAccountJoin)
             db.session.query(TenantAccountJoin)
             .join(Tenant, TenantAccountJoin.tenant_id == Tenant.id)
             .join(Tenant, TenantAccountJoin.tenant_id == Tenant.id)
@@ -971,8 +973,9 @@ class RegisterService:
         """Invite new member"""
         """Invite new member"""
         with Session(db.engine) as session:
         with Session(db.engine) as session:
             account = session.query(Account).filter_by(email=email).first()
             account = session.query(Account).filter_by(email=email).first()
-
+        print("打印2:")
         if not account:
         if not account:
+            print("打印3:")
             TenantService.check_member_permission(tenant, inviter, None, "add")
             TenantService.check_member_permission(tenant, inviter, None, "add")
             name = email.split("@")[0]
             name = email.split("@")[0]
 
 
@@ -983,18 +986,21 @@ class RegisterService:
             TenantService.create_tenant_member(tenant, account, role)
             TenantService.create_tenant_member(tenant, account, role)
             TenantService.switch_tenant(account, tenant.id)
             TenantService.switch_tenant(account, tenant.id)
         else:
         else:
+            print("打印6:")
             TenantService.check_member_permission(tenant, inviter, account, "add")
             TenantService.check_member_permission(tenant, inviter, account, "add")
             ta = TenantAccountJoin.query.filter_by(tenant_id=tenant.id, account_id=account.id).first()
             ta = TenantAccountJoin.query.filter_by(tenant_id=tenant.id, account_id=account.id).first()
 
 
             if not ta:
             if not ta:
+                print("打印7:")
                 TenantService.create_tenant_member(tenant, account, role)
                 TenantService.create_tenant_member(tenant, account, role)
 
 
             # Support resend invitation email when the account is pending status
             # Support resend invitation email when the account is pending status
             if account.status != AccountStatus.PENDING.value:
             if account.status != AccountStatus.PENDING.value:
+                print("打印8:")
                 raise AccountAlreadyInTenantError("Account already in tenant.")
                 raise AccountAlreadyInTenantError("Account already in tenant.")
-
+        print("打印9:")
         token = cls.generate_invite_token(tenant, account)
         token = cls.generate_invite_token(tenant, account)
-
+        print("打印10:")
         # send email
         # send email
         send_invite_member_mail_task.delay(
         send_invite_member_mail_task.delay(
             language=account.interface_language,
             language=account.interface_language,
@@ -1003,7 +1009,7 @@ class RegisterService:
             inviter_name=inviter.name if inviter else "Dify",
             inviter_name=inviter.name if inviter else "Dify",
             workspace_name=tenant.name,
             workspace_name=tenant.name,
         )
         )
-
+        print("打印11:")
         return token
         return token
 
 
     @classmethod
     @classmethod

+ 44 - 1
api/services/app_service.py

@@ -18,7 +18,7 @@ from core.tools.utils.configuration import ToolParameterConfigurationManager
 from events.app_event import app_was_created
 from events.app_event import app_was_created
 from extensions.ext_database import db
 from extensions.ext_database import db
 from models.account import Account
 from models.account import Account
-from models.model import App, AppMode, AppModelConfig
+from models.model import App, AppMode, AppModelConfig, AppPermissionAll
 from models.tools import ApiToolProvider
 from models.tools import ApiToolProvider
 from services.tag_service import TagService
 from services.tag_service import TagService
 from tasks.remove_app_and_related_data_task import remove_app_and_related_data_task
 from tasks.remove_app_and_related_data_task import remove_app_and_related_data_task
@@ -157,6 +157,10 @@ class AppService:
 
 
         return app
         return app
 
 
+    def get_app_by_id(self) -> App:
+        app = db.session.query(App).filter(App.id == self).all()
+        return app
+
     def get_app(self, app: App) -> App:
     def get_app(self, app: App) -> App:
         """
         """
         Get App
         Get App
@@ -373,3 +377,42 @@ class AppService:
                         meta["tool_icons"][tool_name] = {"background": "#252525", "content": "\ud83d\ude01"}
                         meta["tool_icons"][tool_name] = {"background": "#252525", "content": "\ud83d\ude01"}
 
 
         return meta
         return meta
+
+    def update_app_edit_auth(self, edit_auth, user):
+        app = AppService.get_app_by_id(self)
+        if not app:
+            raise ValueError("App not found")
+
+        if app.edit_auth != edit_auth:
+            app.query.filter_by(id=self).update(
+                {"edit_auth": edit_auth, "updated_by": user, "updated_at": datetime.datetime.now()}
+            )
+            db.session.commit()
+
+    def update_app_read_permission(self, user, read_permission_list):
+        for read_permission in read_permission_list:
+            print(f" 查看权限 ID: {read_permission.get('id')}, Email: {read_permission.get('email')}")
+            account_id = read_permission.get("id")
+            email = read_permission.get("email")
+            app_permission_all: Optional[AppPermissionAll] = AppPermissionAll.query.filter_by(
+                app_id=self, account_id=account_id
+            ).first()
+            if app_permission_all == None:
+                # 插入
+                print(f" 数据表无有查看权限 ID: {read_permission.get('id')}, Email: {read_permission.get('email')}")
+                new_app_permission_all = AppPermissionAll()
+                new_app_permission_all.dataset_id = self
+                new_app_permission_all.account_id = account_id
+                new_app_permission_all.created_by = user.id
+                new_app_permission_all.updated_by = user.id
+                new_app_permission_all.has_read_permission = True
+                new_app_permission_all.email = email
+                db.session.add(new_app_permission_all)
+                db.session.commit()
+                db.session.flush()
+            else:
+                if app_permission_all.has_read_permission == False:
+                    app_permission_all.query.filter_by(app_id=self, account_id=account_id).update(
+                        {"has_read_permission": True, "updated_by": user.id, "updated_at": datetime.now()}
+                    )
+                    db.session.commit()