Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.239.004"
VERSION = "0.239.013"

SECRET_KEY = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production')

Expand Down
329 changes: 329 additions & 0 deletions application/single_app/functions_activity_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -1393,3 +1393,332 @@ def log_retention_policy_force_push(
level=logging.ERROR
)
debug_print(f"⚠️ Warning: Failed to log retention policy force push: {str(e)}")


# === AGENT & ACTION ACTIVITY LOGGING ===

def log_agent_creation(
user_id: str,
agent_id: str,
agent_name: str,
agent_display_name: Optional[str] = None,
scope: str = 'personal',
group_id: Optional[str] = None
) -> None:
"""
Log an agent creation activity.

Args:
user_id: The ID of the user who created the agent
agent_id: The unique ID of the new agent
agent_name: The name of the agent
agent_display_name: The display name of the agent
scope: 'personal', 'group', or 'global'
group_id: The group ID (only for group scope)
"""
try:
activity_record = {
'id': str(uuid.uuid4()),
'user_id': user_id,
'activity_type': 'agent_creation',
'timestamp': datetime.utcnow().isoformat(),
'created_at': datetime.utcnow().isoformat(),
'entity_type': 'agent',
'operation': 'create',
'entity': {
'id': agent_id,
'name': agent_name,
'display_name': agent_display_name or agent_name
},
'workspace_type': scope,
'workspace_context': {}
}
if scope == 'group' and group_id:
activity_record['workspace_context']['group_id'] = group_id

cosmos_activity_logs_container.create_item(body=activity_record)
log_event(
message=f"Agent created: {agent_name} ({scope}) by user {user_id}",
extra=activity_record,
level=logging.INFO
)
debug_print(f"✅ Agent creation logged: {agent_name} ({scope})")
except Exception as e:
log_event(
message=f"Error logging agent creation: {str(e)}",
extra={'user_id': user_id, 'agent_id': agent_id, 'scope': scope, 'error': str(e)},
level=logging.ERROR
)
debug_print(f"⚠️ Warning: Failed to log agent creation: {str(e)}")


def log_agent_update(
user_id: str,
agent_id: str,
agent_name: str,
agent_display_name: Optional[str] = None,
scope: str = 'personal',
group_id: Optional[str] = None
) -> None:
"""
Log an agent update activity.

Args:
user_id: The ID of the user who updated the agent
agent_id: The unique ID of the agent
agent_name: The name of the agent
agent_display_name: The display name of the agent
scope: 'personal', 'group', or 'global'
group_id: The group ID (only for group scope)
"""
try:
activity_record = {
'id': str(uuid.uuid4()),
'user_id': user_id,
'activity_type': 'agent_update',
'timestamp': datetime.utcnow().isoformat(),
'created_at': datetime.utcnow().isoformat(),
'entity_type': 'agent',
'operation': 'update',
'entity': {
'id': agent_id,
'name': agent_name,
'display_name': agent_display_name or agent_name
},
'workspace_type': scope,
'workspace_context': {}
}
if scope == 'group' and group_id:
activity_record['workspace_context']['group_id'] = group_id

cosmos_activity_logs_container.create_item(body=activity_record)
log_event(
message=f"Agent updated: {agent_name} ({scope}) by user {user_id}",
extra=activity_record,
level=logging.INFO
)
debug_print(f"✅ Agent update logged: {agent_name} ({scope})")
except Exception as e:
log_event(
message=f"Error logging agent update: {str(e)}",
extra={'user_id': user_id, 'agent_id': agent_id, 'scope': scope, 'error': str(e)},
level=logging.ERROR
)
debug_print(f"⚠️ Warning: Failed to log agent update: {str(e)}")


def log_agent_deletion(
user_id: str,
agent_id: str,
agent_name: str,
scope: str = 'personal',
group_id: Optional[str] = None
) -> None:
"""
Log an agent deletion activity.

Args:
user_id: The ID of the user who deleted the agent
agent_id: The unique ID of the agent
agent_name: The name of the agent
scope: 'personal', 'group', or 'global'
group_id: The group ID (only for group scope)
"""
try:
activity_record = {
'id': str(uuid.uuid4()),
'user_id': user_id,
'activity_type': 'agent_deletion',
'timestamp': datetime.utcnow().isoformat(),
'created_at': datetime.utcnow().isoformat(),
'entity_type': 'agent',
'operation': 'delete',
'entity': {
'id': agent_id,
'name': agent_name
},
'workspace_type': scope,
'workspace_context': {}
}
if scope == 'group' and group_id:
activity_record['workspace_context']['group_id'] = group_id

cosmos_activity_logs_container.create_item(body=activity_record)
log_event(
message=f"Agent deleted: {agent_name} ({scope}) by user {user_id}",
extra=activity_record,
level=logging.INFO
)
debug_print(f"✅ Agent deletion logged: {agent_name} ({scope})")
except Exception as e:
log_event(
message=f"Error logging agent deletion: {str(e)}",
extra={'user_id': user_id, 'agent_id': agent_id, 'scope': scope, 'error': str(e)},
level=logging.ERROR
)
debug_print(f"⚠️ Warning: Failed to log agent deletion: {str(e)}")


def log_action_creation(
user_id: str,
action_id: str,
action_name: str,
action_type: Optional[str] = None,
scope: str = 'personal',
group_id: Optional[str] = None
) -> None:
"""
Log an action/plugin creation activity.

Args:
user_id: The ID of the user who created the action
action_id: The unique ID of the new action
action_name: The name of the action
action_type: The type of the action (e.g., 'openapi', 'sql_query')
scope: 'personal', 'group', or 'global'
group_id: The group ID (only for group scope)
"""
try:
activity_record = {
'id': str(uuid.uuid4()),
'user_id': user_id,
'activity_type': 'action_creation',
'timestamp': datetime.utcnow().isoformat(),
'created_at': datetime.utcnow().isoformat(),
'entity_type': 'action',
'operation': 'create',
'entity': {
'id': action_id,
'name': action_name,
'type': action_type
},
'workspace_type': scope,
'workspace_context': {}
}
if scope == 'group' and group_id:
activity_record['workspace_context']['group_id'] = group_id

cosmos_activity_logs_container.create_item(body=activity_record)
log_event(
message=f"Action created: {action_name} ({scope}) by user {user_id}",
extra=activity_record,
level=logging.INFO
)
debug_print(f"✅ Action creation logged: {action_name} ({scope})")
except Exception as e:
log_event(
message=f"Error logging action creation: {str(e)}",
extra={'user_id': user_id, 'action_id': action_id, 'scope': scope, 'error': str(e)},
level=logging.ERROR
)
debug_print(f"⚠️ Warning: Failed to log action creation: {str(e)}")


def log_action_update(
user_id: str,
action_id: str,
action_name: str,
action_type: Optional[str] = None,
scope: str = 'personal',
group_id: Optional[str] = None
) -> None:
"""
Log an action/plugin update activity.

Args:
user_id: The ID of the user who updated the action
action_id: The unique ID of the action
action_name: The name of the action
action_type: The type of the action
scope: 'personal', 'group', or 'global'
group_id: The group ID (only for group scope)
"""
try:
activity_record = {
'id': str(uuid.uuid4()),
'user_id': user_id,
'activity_type': 'action_update',
'timestamp': datetime.utcnow().isoformat(),
'created_at': datetime.utcnow().isoformat(),
'entity_type': 'action',
'operation': 'update',
'entity': {
'id': action_id,
'name': action_name,
'type': action_type
},
'workspace_type': scope,
'workspace_context': {}
}
if scope == 'group' and group_id:
activity_record['workspace_context']['group_id'] = group_id

cosmos_activity_logs_container.create_item(body=activity_record)
log_event(
message=f"Action updated: {action_name} ({scope}) by user {user_id}",
extra=activity_record,
level=logging.INFO
)
debug_print(f"✅ Action update logged: {action_name} ({scope})")
except Exception as e:
log_event(
message=f"Error logging action update: {str(e)}",
extra={'user_id': user_id, 'action_id': action_id, 'scope': scope, 'error': str(e)},
level=logging.ERROR
)
debug_print(f"⚠️ Warning: Failed to log action update: {str(e)}")


def log_action_deletion(
user_id: str,
action_id: str,
action_name: str,
action_type: Optional[str] = None,
scope: str = 'personal',
group_id: Optional[str] = None
) -> None:
"""
Log an action/plugin deletion activity.

Args:
user_id: The ID of the user who deleted the action
action_id: The unique ID of the action
action_name: The name of the action
action_type: The type of the action
scope: 'personal', 'group', or 'global'
group_id: The group ID (only for group scope)
"""
try:
activity_record = {
'id': str(uuid.uuid4()),
'user_id': user_id,
'activity_type': 'action_deletion',
'timestamp': datetime.utcnow().isoformat(),
'created_at': datetime.utcnow().isoformat(),
'entity_type': 'action',
'operation': 'delete',
'entity': {
'id': action_id,
'name': action_name,
'type': action_type
},
'workspace_type': scope,
'workspace_context': {}
}
if scope == 'group' and group_id:
activity_record['workspace_context']['group_id'] = group_id

cosmos_activity_logs_container.create_item(body=activity_record)
log_event(
message=f"Action deleted: {action_name} ({scope}) by user {user_id}",
extra=activity_record,
level=logging.INFO
)
debug_print(f"✅ Action deletion logged: {action_name} ({scope})")
except Exception as e:
log_event(
message=f"Error logging action deletion: {str(e)}",
extra={'user_id': user_id, 'action_id': action_id, 'scope': scope, 'error': str(e)},
level=logging.ERROR
)
debug_print(f"⚠️ Warning: Failed to log action deletion: {str(e)}")
26 changes: 23 additions & 3 deletions application/single_app/functions_global_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,13 @@ def get_global_action(action_id, return_type=SecretReturnType.TRIGGER):
return None


def save_global_action(action_data):
def save_global_action(action_data, user_id=None):
"""
Save or update a global action.

Args:
action_data (dict): Action data to save
user_id (str, optional): The user ID of the person performing the action

Returns:
dict: Saved action data or None if failed
Expand All @@ -76,8 +77,27 @@ def save_global_action(action_data):
action_data['id'] = str(uuid.uuid4())
# Add metadata
action_data['is_global'] = True
action_data['created_at'] = datetime.utcnow().isoformat()
action_data['updated_at'] = datetime.utcnow().isoformat()
now = datetime.utcnow().isoformat()

# Check if this is a new action or an update to preserve created_by/created_at
existing_action = None
try:
existing_action = cosmos_global_actions_container.read_item(
item=action_data['id'],
partition_key=action_data['id']
)
except Exception:
pass

if existing_action:
action_data['created_by'] = existing_action.get('created_by', user_id)
action_data['created_at'] = existing_action.get('created_at', now)
else:
action_data['created_by'] = user_id
action_data['created_at'] = now
action_data['modified_by'] = user_id
action_data['modified_at'] = now
action_data['updated_at'] = now
print(f"💾 Saving global action: {action_data.get('name', 'Unknown')}")
# Store secrets in Key Vault before upsert
action_data = keyvault_plugin_save_helper(action_data, scope_value=action_data.get('id'), scope="global")
Expand Down
Loading