Coverage for src/cstlcore/admin/models.py: 100%

212 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2026-02-19 12:46 +0000

1""" 

2Admin dashboard and management response models 

3""" 

4 

5from datetime import datetime 

6from typing import List, Optional, Literal 

7from pydantic import BaseModel, Field 

8 

9 

10# Dashboard Models 

11class UserStats(BaseModel): 

12 total: int 

13 active: int 

14 new_today: int = Field(alias="newToday") 

15 growth: float # percentage 

16 

17 

18class ConstellationStats(BaseModel): 

19 total: int 

20 public: int 

21 new_today: int = Field(alias="newToday") 

22 growth: float # percentage 

23 

24 

25class EngagementStats(BaseModel): 

26 total_views: int = Field(alias="totalViews") 

27 total_likes: int = Field(alias="totalLikes") 

28 views_today: int = Field(alias="viewsToday") 

29 engagement_rate: float = Field(alias="engagementRate") # percentage 

30 

31 

32class SystemStats(BaseModel): 

33 storage_used: float = Field(alias="storageUsed") # GB 

34 uptime: float # percentage 

35 active_connections: int = Field(alias="activeConnections") 

36 response_time: float = Field(alias="responseTime") # ms 

37 

38 

39class DashboardStatsResponse(BaseModel): 

40 users: UserStats 

41 constellations: ConstellationStats 

42 engagement: EngagementStats 

43 system: SystemStats 

44 

45 

46class ActivityItem(BaseModel): 

47 id: str 

48 type: Literal["user_registered", "constellation_created", "constellation_shared", "user_verified"] 

49 description: str 

50 timestamp: datetime 

51 user: Optional[str] = None 

52 

53 

54class DashboardActivityResponse(BaseModel): 

55 activities: List[ActivityItem] 

56 

57 

58class AlertItem(BaseModel): 

59 id: str 

60 type: Literal["warning", "error", "info"] 

61 message: str 

62 timestamp: datetime 

63 

64 

65class DashboardAlertsResponse(BaseModel): 

66 alerts: List[AlertItem] 

67 

68 

69# User Management Models 

70class AdminUserItem(BaseModel): 

71 id: str 

72 email: str 

73 name: str 

74 created_at: datetime = Field(alias="createdAt") 

75 last_login_at: Optional[datetime] = Field(alias="lastLoginAt") 

76 is_active: bool = Field(alias="isActive") 

77 is_verified: bool = Field(alias="isVerified") 

78 subscription_type: Literal["free", "pro", "enterprise"] = Field(alias="subscriptionType") 

79 constellations_count: int = Field(alias="constellationsCount") 

80 total_elements: int = Field(alias="totalElements") 

81 total_links: int = Field(alias="totalLinks") 

82 storage_used: float = Field(alias="storageUsed") # in MB 

83 

84 

85class UsersListResponse(BaseModel): 

86 users: List[AdminUserItem] 

87 total: int 

88 page: int 

89 limit: int 

90 

91 

92class UserToggleStatusResponse(BaseModel): 

93 success: bool 

94 message: str 

95 user: dict 

96 

97 

98class UserSendVerificationResponse(BaseModel): 

99 success: bool 

100 message: str 

101 

102 

103class UserConstellationItem(BaseModel): 

104 id: str 

105 title: str 

106 is_public: bool = Field(alias="isPublic") 

107 elements_count: int = Field(alias="elementsCount") 

108 links_count: int = Field(alias="linksCount") 

109 created_at: datetime = Field(alias="createdAt") 

110 

111 

112class UserDetailResponse(BaseModel): 

113 user: dict 

114 

115 

116# Constellation Management Models 

117class AdminConstellationItem(BaseModel): 

118 id: str 

119 title: str 

120 description: str 

121 created_at: datetime = Field(alias="createdAt") 

122 updated_at: datetime = Field(alias="updatedAt") 

123 is_public: bool = Field(alias="isPublic") 

124 owner_name: str = Field(alias="ownerName") 

125 owner_email: str = Field(alias="ownerEmail") 

126 collaborators_count: int = Field(alias="collaboratorsCount") 

127 elements_count: int = Field(alias="elementsCount") 

128 links_count: int = Field(alias="linksCount") 

129 images_count: int = Field(alias="imagesCount") 

130 views_count: int = Field(alias="viewsCount") 

131 likes_count: int = Field(alias="likesCount") 

132 storage_used: float = Field(alias="storageUsed") # in MB 

133 last_activity: datetime = Field(alias="lastActivity") 

134 tags: List[str] 

135 

136 

137class ConstellationsListResponse(BaseModel): 

138 constellations: List[AdminConstellationItem] 

139 total: int 

140 page: int 

141 limit: int 

142 

143 

144class ConstellationToggleVisibilityResponse(BaseModel): 

145 success: bool 

146 message: str 

147 constellation: dict 

148 

149 

150class ConstellationDeleteResponse(BaseModel): 

151 success: bool 

152 message: str 

153 

154 

155class ConstellationDetailResponse(BaseModel): 

156 constellation: dict 

157 

158 

159# Permissions Management Models 

160class PermissionItem(BaseModel): 

161 id: str 

162 user_id: str = Field(alias="userId") 

163 user_name: str = Field(alias="userName") 

164 user_email: str = Field(alias="userEmail") 

165 constellation_id: str = Field(alias="constellationId") 

166 constellation_title: str = Field(alias="constellationTitle") 

167 role: Literal["owner", "admin", "editor", "viewer"] 

168 granted_at: datetime = Field(alias="grantedAt") 

169 granted_by: str = Field(alias="grantedBy") 

170 last_accessed: Optional[datetime] = Field(alias="lastAccessed") 

171 permissions: dict 

172 

173 

174class PermissionsListResponse(BaseModel): 

175 permissions: List[PermissionItem] 

176 total: int 

177 page: int 

178 limit: int 

179 

180 

181class UpdateRoleRequest(BaseModel): 

182 role: Literal["admin", "editor", "viewer"] 

183 

184 

185class UpdateRoleResponse(BaseModel): 

186 success: bool 

187 message: str 

188 permission: dict 

189 

190 

191class RevokePermissionResponse(BaseModel): 

192 success: bool 

193 message: str 

194 

195 

196# Analytics Models 

197class AnalyticsUserStats(BaseModel): 

198 total_users: int = Field(alias="totalUsers") 

199 active_users: int = Field(alias="activeUsers") 

200 new_users_today: int = Field(alias="newUsersToday") 

201 new_users_this_week: int = Field(alias="newUsersThisWeek") 

202 new_users_this_month: int = Field(alias="newUsersThisMonth") 

203 user_growth_rate: float = Field(alias="userGrowthRate") # percentage 

204 average_session_duration: float = Field(alias="averageSessionDuration") # minutes 

205 

206 

207class AnalyticsConstellationStats(BaseModel): 

208 total_constellations: int = Field(alias="totalConstellations") 

209 public_constellations: int = Field(alias="publicConstellations") 

210 private_constellations: int = Field(alias="privateConstellations") 

211 new_constellations_today: int = Field(alias="newConstellationsToday") 

212 new_constellations_this_week: int = Field(alias="newConstellationsThisWeek") 

213 new_constellations_this_month: int = Field(alias="newConstellationsThisMonth") 

214 constellation_growth_rate: float = Field(alias="constellationGrowthRate") # percentage 

215 average_elements_per_constellation: float = Field(alias="averageElementsPerConstellation") 

216 average_links_per_constellation: float = Field(alias="averageLinksPerConstellation") 

217 

218 

219class AnalyticsEngagementStats(BaseModel): 

220 total_views: int = Field(alias="totalViews") 

221 total_likes: int = Field(alias="totalLikes") 

222 total_shares: int = Field(alias="totalShares") 

223 total_comments: int = Field(alias="totalComments") 

224 views_today: int = Field(alias="viewsToday") 

225 views_this_week: int = Field(alias="viewsThisWeek") 

226 views_this_month: int = Field(alias="viewsThisMonth") 

227 engagement_rate: float = Field(alias="engagementRate") # percentage 

228 

229 

230class AnalyticsSystemStats(BaseModel): 

231 total_storage_used: float = Field(alias="totalStorageUsed") # in GB 

232 average_storage_per_user: float = Field(alias="averageStoragePerUser") # in MB 

233 total_images: int = Field(alias="totalImages") 

234 total_elements: int = Field(alias="totalElements") 

235 total_links: int = Field(alias="totalLinks") 

236 database_size: float = Field(alias="databaseSize") # in GB 

237 active_connections: int = Field(alias="activeConnections") 

238 

239 

240class TopConstellationItem(BaseModel): 

241 id: str 

242 title: str 

243 owner: str 

244 views: int 

245 likes: int 

246 created_at: datetime = Field(alias="createdAt") 

247 

248 

249class TopUserItem(BaseModel): 

250 id: str 

251 name: str 

252 email: str 

253 constellations_count: int = Field(alias="constellationsCount") 

254 total_views: int = Field(alias="totalViews") 

255 joined_at: datetime = Field(alias="joinedAt") 

256 

257 

258class AnalyticsResponse(BaseModel): 

259 user_stats: AnalyticsUserStats = Field(alias="userStats") 

260 constellation_stats: AnalyticsConstellationStats = Field(alias="constellationStats") 

261 engagement_stats: AnalyticsEngagementStats = Field(alias="engagementStats") 

262 system_stats: AnalyticsSystemStats = Field(alias="systemStats") 

263 top_constellations: List[TopConstellationItem] = Field(alias="topConstellations") 

264 top_users: List[TopUserItem] = Field(alias="topUsers") 

265 

266 

267 

268class GraphMetricsResponse(BaseModel): 

269 """Graph theory metrics for a constellation's narrative structure""" 

270 

271 constellation_id: str = Field(alias="constellationId") 

272 element_count: int = Field(alias="elementCount", description="Number of nodes (N)") 

273 relation_count: int = Field( 

274 alias="relationCount", description="Number of unique undirected edges (M)" 

275 ) 

276 graph_density: float = Field( 

277 alias="graphDensity", description="Graph density D = 2M / N(N-1)" 

278 ) 

279 average_degree: float = Field( 

280 alias="averageDegree", description="Average degree k = 2M / N" 

281 ) 

282 interpretation_level: str = Field(alias="interpretationLevel") 

283 

284 

285class GraphMetricsSummaryItem(BaseModel): 

286 """Summary metrics for a single constellation""" 

287 

288 constellation_id: str = Field(alias="constellationId") 

289 constellation_name: str = Field(alias="constellationName") 

290 element_count: int = Field(alias="elementCount") 

291 relation_count: int = Field(alias="relationCount") 

292 graph_density: float = Field(alias="graphDensity") 

293 average_degree: float = Field(alias="averageDegree") 

294 interpretation_level: str = Field(alias="interpretationLevel") 

295 

296 

297class GraphMetricsBulkResponse(BaseModel): 

298 """Bulk graph metrics for all constellations""" 

299 

300 constellations: List[GraphMetricsSummaryItem] 

301 total: int 

302 average_density: float = Field(alias="averageDensity") 

303 average_elements: float = Field(alias="averageElements") 

304 average_relations: float = Field(alias="averageRelations")