import json from paramiko import SSHClient from app.config import PROD_BEARER_TOKEN from app.dtos import User from app.permisions import get_ssh_client, get_pdp_permissions_for_identities from app.migrate_to_v2_permissions import NewRole def migrate_email_campaigns_role(user_uuid: str, tenant_uuid: str, ssh_client: SSHClient) -> bool: """ Migrate from fansifter_can_view_email_campaigns to fansifter_can_create_email_campaigns role Args: user_uuid: User identity UUID tenant_uuid: Tenant/vendor UUID ssh_client: SSH client for API calls Returns: bool: True if successful, False otherwise """ old_role = NewRole.FANSIFTER_CAN_VIEW_EMAIL_CAMPAIGNS.value new_role = NewRole.FANSIFTER_CAN_CREATE_EMAIL_CAMPAIGNS.value request = """ curl --location --request PUT 'https://prod-ows-pdp.theorchard.io/identity/%(identity_id)s/tenant/%(tenant_uuid)s/attach-and-detach/roles/' \ --header 'Authorization: Bearer %(token)s' \ --header 'Content-Type: application/json' \ --data '{ "tenant_uuid": "%(tenant_uuid)s", "tenant_type": "account", "roles_to_attach": [{"role": "%(new_role)s"}], "roles_to_detach": [{"role": "%(old_role)s"}] }' """ % { "token": PROD_BEARER_TOKEN, "identity_id": user_uuid, "old_role": old_role, "new_role": new_role, "tenant_uuid": tenant_uuid } try: stdin, stdout, stderr = ssh_client.exec_command(request) output = stdout.read().decode('ascii').strip("\n") output = json.loads(output) if output.get("code") == "invalid_token": raise Exception("Invalid token - {}".format(output.get("message"))) return True except Exception as e: print(f"Error migrating role for user {user_uuid} in tenant {tenant_uuid}: {e}") return False def perform_email_campaigns_migration(users: list[User]) -> bool: """ Main function to migrate users from fansifter_can_view_email_campaigns to fansifter_can_create_email_campaigns role Args: users: List of users to process Returns: bool: True if migration successful, False otherwise """ # Get user identities identities = [user.identity for user in users] try: # Get current permissions print("Fetching current permissions...") users_permissions = get_pdp_permissions_for_identities(identities, PROD_BEARER_TOKEN) if not users_permissions: print("No permissions found for provided users") return True except Exception as e: print(f"Error fetching permissions: {e}") return False # Find users with fansifter_can_view_email_campaigns role to migrate to fansifter_can_create_email_campaigns users_to_migrate = {} old_role = NewRole.FANSIFTER_CAN_VIEW_EMAIL_CAMPAIGNS.value new_role = NewRole.FANSIFTER_CAN_CREATE_EMAIL_CAMPAIGNS.value # Create user lookup user_lookup = {user.identity: user for user in users} print(f"\nLooking for users with {old_role} role to migrate to {new_role}...") for user_id, user_tenants in users_permissions.items(): user = user_lookup.get(user_id) if not user: continue tenants_with_role = [] for tenant_uuid, roles in user_tenants.items(): if old_role in roles: tenants_with_role.append(tenant_uuid) if tenants_with_role: users_to_migrate[user_id] = (tenants_with_role, user) print(f"Found user {user.email} with {old_role} in {len(tenants_with_role)} tenant(s)") if not users_to_migrate: print(f"No users found with {old_role} role") return True print(f"\nFound {len(users_to_migrate)} users to migrate") # Execute migration try: ssh = get_ssh_client() for user_id, (tenant_uuids, user) in users_to_migrate.items(): print(f"Migrating {user.email} from {old_role} to {new_role}...") for tenant_uuid in tenant_uuids: # Find vendor name for logging vendor_name = "unknown" if hasattr(user, 'vendors') and user.vendors: vendor = next((v for v in user.vendors if v.uuid == tenant_uuid), None) if vendor: vendor_name = vendor.name print(f" Migrating role in tenant {vendor_name} ({tenant_uuid})") success = migrate_email_campaigns_role(user_id, tenant_uuid, ssh) if not success: print(f" Failed to migrate role for {user.email} in tenant {tenant_uuid}") return False print(f" Successfully migrated: {old_role} → {new_role}") print("All email campaigns roles migrated successfully!") return True except Exception as e: print(f"Error during migration: {e}") return False