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
31pub async fn log_delegation_action(
32 pool: &PgPool,
33 delegated_did: &str,
34 actor_did: &str,
35 controller_did: Option<&str>,
36 action_type: DelegationActionType,
37 action_details: Option<serde_json::Value>,
38 ip_address: Option<&str>,
39 user_agent: Option<&str>,
40) -> Result<Uuid, sqlx::Error> {
41 let id = sqlx::query_scalar!(
42 r#"
43 INSERT INTO delegation_audit_log
44 (delegated_did, actor_did, controller_did, action_type, action_details, ip_address, user_agent)
45 VALUES ($1, $2, $3, $4, $5, $6, $7)
46 RETURNING id
47 "#,
48 delegated_did,
49 actor_did,
50 controller_did,
51 action_type as DelegationActionType,
52 action_details,
53 ip_address,
54 user_agent
55 )
56 .fetch_one(pool)
57 .await?;
58
59 Ok(id)
60}
61
62pub async fn get_audit_log_for_account(
63 pool: &PgPool,
64 delegated_did: &str,
65 limit: i64,
66 offset: i64,
67) -> Result<Vec<AuditLogEntry>, sqlx::Error> {
68 let entries = sqlx::query_as!(
69 AuditLogEntry,
70 r#"
71 SELECT
72 id,
73 delegated_did,
74 actor_did,
75 controller_did,
76 action_type as "action_type: DelegationActionType",
77 action_details,
78 ip_address,
79 user_agent,
80 created_at
81 FROM delegation_audit_log
82 WHERE delegated_did = $1
83 ORDER BY created_at DESC
84 LIMIT $2 OFFSET $3
85 "#,
86 delegated_did,
87 limit,
88 offset
89 )
90 .fetch_all(pool)
91 .await?;
92
93 Ok(entries)
94}
95
96pub async fn get_audit_log_by_controller(
97 pool: &PgPool,
98 controller_did: &str,
99 limit: i64,
100 offset: i64,
101) -> Result<Vec<AuditLogEntry>, sqlx::Error> {
102 let entries = sqlx::query_as!(
103 AuditLogEntry,
104 r#"
105 SELECT
106 id,
107 delegated_did,
108 actor_did,
109 controller_did,
110 action_type as "action_type: DelegationActionType",
111 action_details,
112 ip_address,
113 user_agent,
114 created_at
115 FROM delegation_audit_log
116 WHERE controller_did = $1
117 ORDER BY created_at DESC
118 LIMIT $2 OFFSET $3
119 "#,
120 controller_did,
121 limit,
122 offset
123 )
124 .fetch_all(pool)
125 .await?;
126
127 Ok(entries)
128}
129
130pub async fn count_audit_log_entries(
131 pool: &PgPool,
132 delegated_did: &str,
133) -> Result<i64, sqlx::Error> {
134 let count = sqlx::query_scalar!(
135 r#"SELECT COUNT(*) as "count!" FROM delegation_audit_log WHERE delegated_did = $1"#,
136 delegated_did
137 )
138 .fetch_one(pool)
139 .await?;
140
141 Ok(count)
142}