this repo has no description
1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use sqlx::PgPool;
4use uuid::Uuid;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
7#[sqlx(type_name = "delegation_action_type", rename_all = "snake_case")]
8pub enum DelegationActionType {
9 GrantCreated,
10 GrantRevoked,
11 ScopesModified,
12 TokenIssued,
13 RepoWrite,
14 BlobUpload,
15 AccountAction,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct AuditLogEntry {
20 pub id: Uuid,
21 pub delegated_did: String,
22 pub actor_did: String,
23 pub controller_did: Option<String>,
24 pub action_type: DelegationActionType,
25 pub action_details: Option<serde_json::Value>,
26 pub ip_address: Option<String>,
27 pub user_agent: Option<String>,
28 pub created_at: DateTime<Utc>,
29}
30
31#[allow(clippy::too_many_arguments)]
32pub async fn log_delegation_action(
33 pool: &PgPool,
34 delegated_did: &str,
35 actor_did: &str,
36 controller_did: Option<&str>,
37 action_type: DelegationActionType,
38 action_details: Option<serde_json::Value>,
39 ip_address: Option<&str>,
40 user_agent: Option<&str>,
41) -> Result<Uuid, sqlx::Error> {
42 let id = sqlx::query_scalar!(
43 r#"
44 INSERT INTO delegation_audit_log
45 (delegated_did, actor_did, controller_did, action_type, action_details, ip_address, user_agent)
46 VALUES ($1, $2, $3, $4, $5, $6, $7)
47 RETURNING id
48 "#,
49 delegated_did,
50 actor_did,
51 controller_did,
52 action_type as DelegationActionType,
53 action_details,
54 ip_address,
55 user_agent
56 )
57 .fetch_one(pool)
58 .await?;
59
60 Ok(id)
61}
62
63pub async fn get_audit_log_for_account(
64 pool: &PgPool,
65 delegated_did: &str,
66 limit: i64,
67 offset: i64,
68) -> Result<Vec<AuditLogEntry>, sqlx::Error> {
69 let entries = sqlx::query_as!(
70 AuditLogEntry,
71 r#"
72 SELECT
73 id,
74 delegated_did,
75 actor_did,
76 controller_did,
77 action_type as "action_type: DelegationActionType",
78 action_details,
79 ip_address,
80 user_agent,
81 created_at
82 FROM delegation_audit_log
83 WHERE delegated_did = $1
84 ORDER BY created_at DESC
85 LIMIT $2 OFFSET $3
86 "#,
87 delegated_did,
88 limit,
89 offset
90 )
91 .fetch_all(pool)
92 .await?;
93
94 Ok(entries)
95}
96
97pub async fn get_audit_log_by_controller(
98 pool: &PgPool,
99 controller_did: &str,
100 limit: i64,
101 offset: i64,
102) -> Result<Vec<AuditLogEntry>, sqlx::Error> {
103 let entries = sqlx::query_as!(
104 AuditLogEntry,
105 r#"
106 SELECT
107 id,
108 delegated_did,
109 actor_did,
110 controller_did,
111 action_type as "action_type: DelegationActionType",
112 action_details,
113 ip_address,
114 user_agent,
115 created_at
116 FROM delegation_audit_log
117 WHERE controller_did = $1
118 ORDER BY created_at DESC
119 LIMIT $2 OFFSET $3
120 "#,
121 controller_did,
122 limit,
123 offset
124 )
125 .fetch_all(pool)
126 .await?;
127
128 Ok(entries)
129}
130
131pub async fn count_audit_log_entries(
132 pool: &PgPool,
133 delegated_did: &str,
134) -> Result<i64, sqlx::Error> {
135 let count = sqlx::query_scalar!(
136 r#"SELECT COUNT(*) as "count!" FROM delegation_audit_log WHERE delegated_did = $1"#,
137 delegated_did
138 )
139 .fetch_one(pool)
140 .await?;
141
142 Ok(count)
143}