Skip to content

Commit ef45536

Browse files
committed
DB table for claude approval requests
1 parent bd2a3f4 commit ef45536

File tree

7 files changed

+143
-1
lines changed

7 files changed

+143
-1
lines changed

crates/but-claude/src/db.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,31 @@ impl TryFrom<crate::ClaudeMessage> for but_db::ClaudeMessage {
183183
})
184184
}
185185
}
186+
187+
impl TryFrom<but_db::ClaudePermissionRequest> for crate::ClaudePermissionRequest {
188+
type Error = anyhow::Error;
189+
fn try_from(value: but_db::ClaudePermissionRequest) -> Result<Self, Self::Error> {
190+
Ok(crate::ClaudePermissionRequest {
191+
id: value.id.to_string(),
192+
created_at: value.created_at,
193+
updated_at: value.updated_at,
194+
tool_name: value.tool_name,
195+
input: serde_json::from_str(&value.input)?,
196+
approved: value.approved,
197+
})
198+
}
199+
}
200+
201+
impl TryFrom<crate::ClaudePermissionRequest> for but_db::ClaudePermissionRequest {
202+
type Error = anyhow::Error;
203+
fn try_from(value: crate::ClaudePermissionRequest) -> Result<Self, Self::Error> {
204+
Ok(but_db::ClaudePermissionRequest {
205+
id: value.id,
206+
created_at: value.created_at,
207+
updated_at: value.updated_at,
208+
tool_name: value.tool_name,
209+
input: serde_json::to_string(&value.input)?,
210+
approved: value.approved,
211+
})
212+
}
213+
}

crates/but-claude/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,20 @@ pub struct ClaudeSessionDetails {
6464
pub summary: Option<String>,
6565
pub last_prompt: Option<String>,
6666
}
67+
68+
/// Represents a request for permission to use a tool in the Claude MCP.
69+
#[derive(Serialize, Deserialize, Debug, Clone)]
70+
pub struct ClaudePermissionRequest {
71+
/// Maps to the tool_use_id from the MCP request
72+
pub id: String,
73+
/// When the requst was made.
74+
pub created_at: chrono::NaiveDateTime,
75+
/// When the request was updated.
76+
pub updated_at: chrono::NaiveDateTime,
77+
/// The tool for which permission is requested
78+
pub tool_name: String,
79+
/// The input for the tool
80+
pub input: serde_json::Value,
81+
/// The status of the request or None if not yet handled
82+
pub approved: Option<bool>,
83+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- This file should undo anything in `up.sql`
2+
DROP TABLE IF EXISTS `claude_permission_requests`;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- Your SQL goes here
2+
CREATE TABLE `claude_permission_requests`(
3+
`id` TEXT NOT NULL PRIMARY KEY,
4+
`created_at` TIMESTAMP NOT NULL,
5+
`updated_at` TIMESTAMP NOT NULL,
6+
`tool_name` TEXT NOT NULL,
7+
`input` TEXT NOT NULL,
8+
`approved` BOOL
9+
);

crates/but-db/src/claude.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ pub struct ClaudeMessage {
4343
pub content: String,
4444
}
4545

46+
#[derive(
47+
Debug, Clone, PartialEq, Serialize, Deserialize, Queryable, Selectable, Insertable, Identifiable,
48+
)]
49+
#[diesel(table_name = crate::schema::claude_permission_requests)]
50+
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
51+
pub struct ClaudePermissionRequest {
52+
pub id: String,
53+
pub created_at: chrono::NaiveDateTime,
54+
pub updated_at: chrono::NaiveDateTime,
55+
pub tool_name: String,
56+
pub input: String,
57+
pub approved: Option<bool>,
58+
}
59+
4660
impl DbHandle {
4761
pub fn claude_sessions(&mut self) -> ClaudeSessionsHandle {
4862
ClaudeSessionsHandle { db: self }
@@ -51,6 +65,11 @@ impl DbHandle {
5165
pub fn claude_messages(&mut self) -> ClaudeMessagesHandle {
5266
ClaudeMessagesHandle { db: self }
5367
}
68+
69+
pub fn claude_permission_requests(&mut self) -> ClaudePermissionRequestsHandle {
70+
ClaudePermissionRequestsHandle { db: self }
71+
}
72+
5473
pub fn delete_session_and_messages(
5574
&mut self,
5675
session_id: &str,
@@ -79,6 +98,62 @@ pub struct ClaudeMessagesHandle<'a> {
7998
db: &'a mut DbHandle,
8099
}
81100

101+
pub struct ClaudePermissionRequestsHandle<'a> {
102+
db: &'a mut DbHandle,
103+
}
104+
105+
impl ClaudePermissionRequestsHandle<'_> {
106+
pub fn insert(
107+
&mut self,
108+
request: ClaudePermissionRequest,
109+
) -> Result<(), diesel::result::Error> {
110+
diesel::insert_into(crate::schema::claude_permission_requests::table)
111+
.values(request)
112+
.execute(&mut self.db.conn)?;
113+
Ok(())
114+
}
115+
116+
pub fn set_approval(&mut self, id: &str, approved: bool) -> Result<(), diesel::result::Error> {
117+
diesel::update(
118+
crate::schema::claude_permission_requests::table
119+
.filter(crate::schema::claude_permission_requests::id.eq(id)),
120+
)
121+
.set((
122+
crate::schema::claude_permission_requests::approved.eq(approved),
123+
crate::schema::claude_permission_requests::updated_at
124+
.eq(chrono::Local::now().naive_local()),
125+
))
126+
.execute(&mut self.db.conn)?;
127+
Ok(())
128+
}
129+
130+
pub fn get(
131+
&mut self,
132+
id: &str,
133+
) -> Result<Option<ClaudePermissionRequest>, diesel::result::Error> {
134+
let request = crate::schema::claude_permission_requests::table
135+
.filter(crate::schema::claude_permission_requests::id.eq(id))
136+
.first::<ClaudePermissionRequest>(&mut self.db.conn)
137+
.optional()?;
138+
Ok(request)
139+
}
140+
141+
pub fn delete(&mut self, id: &str) -> Result<(), diesel::result::Error> {
142+
diesel::delete(
143+
crate::schema::claude_permission_requests::table
144+
.filter(crate::schema::claude_permission_requests::id.eq(id)),
145+
)
146+
.execute(&mut self.db.conn)?;
147+
Ok(())
148+
}
149+
150+
pub fn list(&mut self) -> Result<Vec<ClaudePermissionRequest>, diesel::result::Error> {
151+
let requests = crate::schema::claude_permission_requests::table
152+
.load::<ClaudePermissionRequest>(&mut self.db.conn)?;
153+
Ok(requests)
154+
}
155+
}
156+
82157
impl ClaudeSessionsHandle<'_> {
83158
pub fn insert(&mut self, session: ClaudeSession) -> Result<(), diesel::result::Error> {
84159
diesel::insert_into(claude_sessions)

crates/but-db/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod schema;
1414
mod workflows;
1515
pub use workflows::Workflow;
1616
mod claude;
17-
pub use claude::{ClaudeMessage, ClaudeSession};
17+
pub use claude::{ClaudeMessage, ClaudePermissionRequest, ClaudeSession};
1818
mod file_write_locks;
1919
pub use file_write_locks::FileWriteLock;
2020
mod workspace_rules;

crates/but-db/src/schema.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,14 @@ diesel::table! {
7373
content -> Text,
7474
}
7575
}
76+
77+
diesel::table! {
78+
claude_permission_requests (id) {
79+
id -> Text,
80+
created_at -> Timestamp,
81+
updated_at -> Timestamp,
82+
tool_name -> Text,
83+
input -> Text,
84+
approved -> Nullable<Bool>,
85+
}
86+
}

0 commit comments

Comments
 (0)