|
@@ -11,7 +11,7 @@ from typing import Any, Dict, Optional
|
|
|
from constants.languages import language_timezone_mapping, languages
|
|
|
from events.tenant_event import tenant_was_created
|
|
|
from extensions.ext_redis import redis_client
|
|
|
-from flask import current_app, session
|
|
|
+from flask import current_app
|
|
|
from libs.helper import get_remote_ip
|
|
|
from libs.passport import PassportService
|
|
|
from libs.password import compare_password, hash_password
|
|
@@ -23,7 +23,8 @@ from services.errors.account import (AccountAlreadyInTenantError, AccountLoginEr
|
|
|
NoPermissionError, RoleAlreadyAssignedError, TenantNotFound)
|
|
|
from sqlalchemy import func
|
|
|
from tasks.mail_invite_member_task import send_invite_member_mail_task
|
|
|
-from werkzeug.exceptions import Forbidden, Unauthorized
|
|
|
+from werkzeug.exceptions import Forbidden
|
|
|
+from sqlalchemy import exc
|
|
|
|
|
|
|
|
|
def _create_tenant_for_account(account) -> Tenant:
|
|
@@ -39,54 +40,33 @@ class AccountService:
|
|
|
|
|
|
@staticmethod
|
|
|
def load_user(user_id: str) -> Account:
|
|
|
- # todo: used by flask_login
|
|
|
- if '.' in user_id:
|
|
|
- tenant_id, account_id = user_id.split('.')
|
|
|
- else:
|
|
|
- account_id = user_id
|
|
|
-
|
|
|
- account = db.session.query(Account).filter(Account.id == account_id).first()
|
|
|
-
|
|
|
- if account:
|
|
|
- if account.status == AccountStatus.BANNED.value or account.status == AccountStatus.CLOSED.value:
|
|
|
- raise Forbidden('Account is banned or closed.')
|
|
|
-
|
|
|
- workspace_id = session.get('workspace_id')
|
|
|
- if workspace_id:
|
|
|
- tenant_account_join = db.session.query(TenantAccountJoin).filter(
|
|
|
- TenantAccountJoin.account_id == account.id,
|
|
|
- TenantAccountJoin.tenant_id == workspace_id
|
|
|
- ).first()
|
|
|
-
|
|
|
- if not tenant_account_join:
|
|
|
- tenant_account_join = db.session.query(TenantAccountJoin).filter(
|
|
|
- TenantAccountJoin.account_id == account.id).first()
|
|
|
-
|
|
|
- if tenant_account_join:
|
|
|
- account.current_tenant_id = tenant_account_join.tenant_id
|
|
|
- else:
|
|
|
- _create_tenant_for_account(account)
|
|
|
- session['workspace_id'] = account.current_tenant_id
|
|
|
- else:
|
|
|
- account.current_tenant_id = workspace_id
|
|
|
- else:
|
|
|
- tenant_account_join = db.session.query(TenantAccountJoin).filter(
|
|
|
- TenantAccountJoin.account_id == account.id).first()
|
|
|
- if tenant_account_join:
|
|
|
- account.current_tenant_id = tenant_account_join.tenant_id
|
|
|
- else:
|
|
|
- _create_tenant_for_account(account)
|
|
|
- session['workspace_id'] = account.current_tenant_id
|
|
|
-
|
|
|
- current_time = datetime.utcnow()
|
|
|
+ account = Account.query.filter_by(id=user_id).first()
|
|
|
+ if not account:
|
|
|
+ return None
|
|
|
|
|
|
- # update last_active_at when last_active_at is more than 10 minutes ago
|
|
|
- if current_time - account.last_active_at > timedelta(minutes=10):
|
|
|
- account.last_active_at = current_time
|
|
|
- db.session.commit()
|
|
|
+ if account.status in [AccountStatus.BANNED.value, AccountStatus.CLOSED.value]:
|
|
|
+ raise Forbidden('Account is banned or closed.')
|
|
|
+
|
|
|
+ # init owner's tenant
|
|
|
+ tenant_owner = TenantAccountJoin.query.filter_by(account_id=account.id, role='owner').first()
|
|
|
+ if not tenant_owner:
|
|
|
+ _create_tenant_for_account(account)
|
|
|
+
|
|
|
+ current_tenant = TenantAccountJoin.query.filter_by(account_id=account.id, current=True).first()
|
|
|
+ if current_tenant:
|
|
|
+ account.current_tenant_id = current_tenant.tenant_id
|
|
|
+ else:
|
|
|
+ account.current_tenant_id = tenant_owner.tenant_id
|
|
|
+ tenant_owner.current = True
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ if datetime.utcnow() - account.last_active_at > timedelta(minutes=10):
|
|
|
+ account.last_active_at = datetime.utcnow()
|
|
|
+ db.session.commit()
|
|
|
|
|
|
return account
|
|
|
|
|
|
+
|
|
|
@staticmethod
|
|
|
def get_account_jwt_token(account):
|
|
|
payload = {
|
|
@@ -277,18 +257,21 @@ class TenantService:
|
|
|
@staticmethod
|
|
|
def switch_tenant(account: Account, tenant_id: int = None) -> None:
|
|
|
"""Switch the current workspace for the account"""
|
|
|
- if not tenant_id:
|
|
|
- tenant_account_join = TenantAccountJoin.query.filter_by(account_id=account.id).first()
|
|
|
- else:
|
|
|
- tenant_account_join = TenantAccountJoin.query.filter_by(account_id=account.id, tenant_id=tenant_id).first()
|
|
|
|
|
|
- # Check if the tenant exists and the account is a member of the tenant
|
|
|
+ tenant_account_join = TenantAccountJoin.query.filter_by(account_id=account.id, tenant_id=tenant_id).first()
|
|
|
if not tenant_account_join:
|
|
|
raise AccountNotLinkTenantError("Tenant not found or account is not a member of the tenant.")
|
|
|
-
|
|
|
- # Set the current tenant for the account
|
|
|
- account.current_tenant_id = tenant_account_join.tenant_id
|
|
|
- session['workspace_id'] = account.current_tenant.id
|
|
|
+ else:
|
|
|
+ with db.session.begin():
|
|
|
+ try:
|
|
|
+ TenantAccountJoin.query.filter_by(account_id=account.id).update({'current': False})
|
|
|
+ tenant_account_join.current = True
|
|
|
+ db.session.commit()
|
|
|
+ # Set the current tenant for the account
|
|
|
+ account.current_tenant_id = tenant_account_join.tenant_id
|
|
|
+ except exc.SQLAlchemyError:
|
|
|
+ db.session.rollback()
|
|
|
+ raise
|
|
|
|
|
|
@staticmethod
|
|
|
def get_tenant_members(tenant: Tenant) -> List[Account]:
|