Ver Fonte

fix: account has no owner workspace by member inviting (#2435)

takatost há 1 ano atrás
pai
commit
e6d22fc3a0

+ 3 - 1
api/controllers/console/auth/login.py

@@ -7,7 +7,7 @@ from controllers.console import api
 from controllers.console.setup import setup_required
 from libs.helper import email
 from libs.password import valid_password
-from services.account_service import AccountService
+from services.account_service import AccountService, TenantService
 
 
 class LoginApi(Resource):
@@ -29,6 +29,8 @@ class LoginApi(Resource):
         except services.errors.account.AccountLoginError:
             return {'code': 'unauthorized', 'message': 'Invalid email or password'}, 401
 
+        TenantService.create_owner_tenant_if_not_exist(account)
+
         AccountService.update_last_login(account, request)
 
         # todo: return the user info

+ 3 - 1
api/controllers/console/auth/oauth.py

@@ -10,7 +10,7 @@ from constants.languages import languages
 from extensions.ext_database import db
 from libs.oauth import GitHubOAuth, GoogleOAuth, OAuthUserInfo
 from models.account import Account, AccountStatus
-from services.account_service import AccountService, RegisterService
+from services.account_service import AccountService, RegisterService, TenantService
 
 from .. import api
 
@@ -76,6 +76,8 @@ class OAuthCallback(Resource):
             account.initialized_at = datetime.utcnow()
             db.session.commit()
 
+        TenantService.create_owner_tenant_if_not_exist(account)
+
         AccountService.update_last_login(account, request)
 
         token = AccountService.get_account_jwt_token(account)

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

@@ -11,6 +11,7 @@ from libs.helper import TimestampField
 from libs.login import login_required
 from models.account import Account
 from services.account_service import RegisterService, TenantService
+from services.errors.account import AccountAlreadyInTenantError
 
 account_fields = {
     'id': fields.String,
@@ -71,6 +72,13 @@ class MemberInviteEmailApi(Resource):
                     'email': invitee_email,
                     'url': f'{console_web_url}/activate?email={invitee_email}&token={token}'
                 })
+            except AccountAlreadyInTenantError:
+                invitation_results.append({
+                    'status': 'success',
+                    'email': invitee_email,
+                    'url': f'{console_web_url}/signin'
+                })
+                break
             except Exception as e:
                 invitation_results.append({
                     'status': 'failed',

+ 33 - 28
api/services/account_service.py

@@ -1,5 +1,4 @@
 import base64
-import json
 import logging
 import secrets
 import uuid
@@ -36,15 +35,6 @@ from services.errors.account import (
 from tasks.mail_invite_member_task import send_invite_member_mail_task
 
 
-def _create_tenant_for_account(account) -> Tenant:
-    tenant = TenantService.create_tenant(f"{account.name}'s Workspace")
-
-    TenantService.create_tenant_member(tenant, account, role='owner')
-    account.current_tenant = tenant
-
-    return tenant
-
-
 class AccountService:
 
     @staticmethod
@@ -59,15 +49,14 @@ class AccountService:
         current_tenant = TenantAccountJoin.query.filter_by(account_id=account.id, current=True).first()
         if current_tenant:
             account.current_tenant_id = current_tenant.tenant_id
-            account.current_tenant_id = current_tenant.tenant_id
         else:
-            available_tenant = TenantAccountJoin.query.filter_by(account_id=account.id) \
+            available_ta = TenantAccountJoin.query.filter_by(account_id=account.id) \
                 .order_by(TenantAccountJoin.id.asc()).first()
-            if not available_tenant:
-                raise Forbidden('No available tenant for the user.')
+            if not available_ta:
+                return None
 
-            account.current_tenant_id = available_tenant.tenant_id
-            available_tenant.current = True
+            account.current_tenant_id = available_ta.tenant_id
+            available_ta.current = True
             db.session.commit()
        
         if datetime.utcnow() - account.last_active_at > timedelta(minutes=10):
@@ -226,6 +215,21 @@ class TenantService:
         db.session.commit()
         return tenant
 
+    @staticmethod
+    def create_owner_tenant_if_not_exist(account: Account):
+        """Create owner tenant if not exist"""
+        available_ta = TenantAccountJoin.query.filter_by(account_id=account.id) \
+            .order_by(TenantAccountJoin.id.asc()).first()
+
+        if available_ta:
+            return
+
+        tenant = TenantService.create_tenant(f"{account.name}'s Workspace")
+        TenantService.create_tenant_member(tenant, account, role='owner')
+        account.current_tenant = tenant
+        db.session.commit()
+        tenant_was_created.send(tenant)
+
     @staticmethod
     def create_tenant_member(tenant: Tenant, account: Account, role: str = 'normal') -> TenantAccountJoin:
         """Create tenant member"""
@@ -362,12 +366,6 @@ class TenantService:
             raise MemberNotInTenantError("Member not in tenant.")
 
         db.session.delete(ta)
-
-        account.initialized_at = None
-        account.status = AccountStatus.PENDING.value
-        account.password = None
-        account.password_salt = None
-
         db.session.commit()
 
     @staticmethod
@@ -418,12 +416,18 @@ class RegisterService:
         return f'member_invite:token:{token}'
 
     @classmethod
-    def register(cls, email, name, password: str = None, open_id: str = None, provider: str = None) -> Account:
+    def register(cls, email, name, password: str = None, open_id: str = None, provider: str = None,
+                 language: str = None, status: AccountStatus = None) -> Account:
         db.session.begin_nested()
         """Register account"""
         try:
-            account = AccountService.create_account(email, name, interface_language=languages[0], password=password)
-            account.status = AccountStatus.ACTIVE.value
+            account = AccountService.create_account(
+                email=email,
+                name=name,
+                interface_language=language if language else languages[0],
+                password=password
+            )
+            account.status = AccountStatus.ACTIVE.value if not status else status.value
             account.initialized_at = datetime.utcnow()
 
             if open_id is not None or provider is not None:
@@ -452,11 +456,12 @@ class RegisterService:
         if not account:
             TenantService.check_member_permission(tenant, inviter, None, 'add')
             name = email.split('@')[0]
-            account = AccountService.create_account(email, name, interface_language=language)
-            account.status = AccountStatus.PENDING.value
-            db.session.commit()
 
+            account = cls.register(email=email, name=name, language=language, status=AccountStatus.PENDING)
+
+            # Create new tenant member for invited tenant
             TenantService.create_tenant_member(tenant, account, role)
+            TenantService.switch_tenant(account, tenant.id)
         else:
             TenantService.check_member_permission(tenant, inviter, account, 'add')
             ta = TenantAccountJoin.query.filter_by(