ready for user test 1.00
This commit is contained in:
parent
30e539a49b
commit
237d9b5752
2 changed files with 120 additions and 5 deletions
|
|
@ -156,6 +156,25 @@ class UserConnection(BaseModel, ModelMixin):
|
||||||
frontend_readonly=True,
|
frontend_readonly=True,
|
||||||
frontend_required=False
|
frontend_required=False
|
||||||
)
|
)
|
||||||
|
tokenStatus: Optional[str] = Field(
|
||||||
|
None,
|
||||||
|
description="Current token status: active, expired, none",
|
||||||
|
frontend_type="select",
|
||||||
|
frontend_readonly=True,
|
||||||
|
frontend_required=False,
|
||||||
|
frontend_options=[
|
||||||
|
{"value": "active", "label": {"en": "Active", "fr": "Actif"}},
|
||||||
|
{"value": "expired", "label": {"en": "Expired", "fr": "Expiré"}},
|
||||||
|
{"value": "none", "label": {"en": "None", "fr": "Aucun"}}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
tokenExpiresAt: Optional[float] = Field(
|
||||||
|
None,
|
||||||
|
description="When the current token expires (UTC timestamp in seconds)",
|
||||||
|
frontend_type="timestamp",
|
||||||
|
frontend_readonly=True,
|
||||||
|
frontend_required=False
|
||||||
|
)
|
||||||
|
|
||||||
# Register labels for UserConnection
|
# Register labels for UserConnection
|
||||||
register_model_labels(
|
register_model_labels(
|
||||||
|
|
@ -171,7 +190,9 @@ register_model_labels(
|
||||||
"status": {"en": "Status", "fr": "Statut"},
|
"status": {"en": "Status", "fr": "Statut"},
|
||||||
"connectedAt": {"en": "Connected At", "fr": "Connecté le"},
|
"connectedAt": {"en": "Connected At", "fr": "Connecté le"},
|
||||||
"lastChecked": {"en": "Last Checked", "fr": "Dernière vérification"},
|
"lastChecked": {"en": "Last Checked", "fr": "Dernière vérification"},
|
||||||
"expiresAt": {"en": "Expires At", "fr": "Expire le"}
|
"expiresAt": {"en": "Expires At", "fr": "Expire le"},
|
||||||
|
"tokenStatus": {"en": "Connection Status", "fr": "Statut de connexion"},
|
||||||
|
"tokenExpiresAt": {"en": "Expires At", "fr": "Expire le"}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from modules.interfaces.interfaceAppModel import User, UserConnection, AuthAuthority, ConnectionStatus
|
from modules.interfaces.interfaceAppModel import User, UserConnection, AuthAuthority, ConnectionStatus, Token
|
||||||
from modules.security.auth import getCurrentUser, limiter
|
from modules.security.auth import getCurrentUser, limiter
|
||||||
from modules.interfaces.interfaceAppObjects import getInterface, getRootInterface
|
from modules.interfaces.interfaceAppObjects import getInterface, getRootInterface
|
||||||
from modules.shared.timezoneUtils import get_utc_timestamp
|
from modules.shared.timezoneUtils import get_utc_timestamp
|
||||||
|
|
@ -23,6 +23,57 @@ from modules.shared.timezoneUtils import get_utc_timestamp
|
||||||
# Configure logger
|
# Configure logger
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def get_token_status_for_connection(interface, connection_id: str) -> tuple[str, Optional[float]]:
|
||||||
|
"""
|
||||||
|
Get token status and expiration for a connection.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interface: The database interface
|
||||||
|
connection_id: The connection ID to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: (token_status, token_expires_at)
|
||||||
|
- token_status: 'active', 'expired', or 'none'
|
||||||
|
- token_expires_at: UTC timestamp or None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Query tokens table for the latest token for this connection
|
||||||
|
tokens = interface.db.getRecordset(
|
||||||
|
table="tokens",
|
||||||
|
recordFilter={"connectionId": connection_id}
|
||||||
|
)
|
||||||
|
|
||||||
|
if not tokens:
|
||||||
|
return "none", None
|
||||||
|
|
||||||
|
# Find the most recent token (highest createdAt timestamp)
|
||||||
|
latest_token = None
|
||||||
|
latest_created_at = 0
|
||||||
|
|
||||||
|
for token_data in tokens:
|
||||||
|
created_at = token_data.get("createdAt", 0)
|
||||||
|
if created_at > latest_created_at:
|
||||||
|
latest_created_at = created_at
|
||||||
|
latest_token = token_data
|
||||||
|
|
||||||
|
if not latest_token:
|
||||||
|
return "none", None
|
||||||
|
|
||||||
|
# Check if token is expired
|
||||||
|
expires_at = latest_token.get("expiresAt")
|
||||||
|
if not expires_at:
|
||||||
|
return "none", None
|
||||||
|
|
||||||
|
current_time = get_utc_timestamp()
|
||||||
|
if expires_at <= current_time:
|
||||||
|
return "expired", expires_at
|
||||||
|
else:
|
||||||
|
return "active", expires_at
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting token status for connection {connection_id}: {str(e)}")
|
||||||
|
return "none", None
|
||||||
|
|
||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
prefix="/api/connections",
|
prefix="/api/connections",
|
||||||
tags=["Manage Connections"],
|
tags=["Manage Connections"],
|
||||||
|
|
@ -47,7 +98,32 @@ async def get_connections(
|
||||||
|
|
||||||
# SECURITY FIX: All users (including admins) can only see their own connections
|
# SECURITY FIX: All users (including admins) can only see their own connections
|
||||||
# This prevents admin from seeing other users' connections and causing confusion
|
# This prevents admin from seeing other users' connections and causing confusion
|
||||||
return interface.getUserConnections(currentUser.id)
|
connections = interface.getUserConnections(currentUser.id)
|
||||||
|
|
||||||
|
# Enhance each connection with token status information
|
||||||
|
enhanced_connections = []
|
||||||
|
for connection in connections:
|
||||||
|
# Get token status for this connection
|
||||||
|
token_status, token_expires_at = get_token_status_for_connection(interface, connection.id)
|
||||||
|
|
||||||
|
# Create enhanced connection with token status
|
||||||
|
enhanced_connection = UserConnection(
|
||||||
|
id=connection.id,
|
||||||
|
userId=connection.userId,
|
||||||
|
authority=connection.authority,
|
||||||
|
externalId=connection.externalId,
|
||||||
|
externalUsername=connection.externalUsername,
|
||||||
|
externalEmail=connection.externalEmail,
|
||||||
|
status=connection.status,
|
||||||
|
connectedAt=connection.connectedAt,
|
||||||
|
lastChecked=connection.lastChecked,
|
||||||
|
expiresAt=connection.expiresAt,
|
||||||
|
tokenStatus=token_status,
|
||||||
|
tokenExpiresAt=token_expires_at
|
||||||
|
)
|
||||||
|
enhanced_connections.append(enhanced_connection)
|
||||||
|
|
||||||
|
return enhanced_connections
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error getting connections: {str(e)}")
|
logger.error(f"Error getting connections: {str(e)}")
|
||||||
|
|
@ -164,8 +240,26 @@ async def update_connection(
|
||||||
# Clear cache to ensure fresh data
|
# Clear cache to ensure fresh data
|
||||||
interface.db.clearTableCache("connections")
|
interface.db.clearTableCache("connections")
|
||||||
|
|
||||||
# Get updated connection
|
# Get token status for the updated connection
|
||||||
return connection
|
token_status, token_expires_at = get_token_status_for_connection(interface, connectionId)
|
||||||
|
|
||||||
|
# Create enhanced connection with token status
|
||||||
|
enhanced_connection = UserConnection(
|
||||||
|
id=connection.id,
|
||||||
|
userId=connection.userId,
|
||||||
|
authority=connection.authority,
|
||||||
|
externalId=connection.externalId,
|
||||||
|
externalUsername=connection.externalUsername,
|
||||||
|
externalEmail=connection.externalEmail,
|
||||||
|
status=connection.status,
|
||||||
|
connectedAt=connection.connectedAt,
|
||||||
|
lastChecked=connection.lastChecked,
|
||||||
|
expiresAt=connection.expiresAt,
|
||||||
|
tokenStatus=token_status,
|
||||||
|
tokenExpiresAt=token_expires_at
|
||||||
|
)
|
||||||
|
|
||||||
|
return enhanced_connection
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue