risingwave_frontend/handler/
drop_user.rs1use pgwire::pg_response::{PgResponse, StatementType};
16use risingwave_sqlparser::ast::{DropMode, ObjectName};
17
18use super::RwPgResponse;
19use crate::binder::Binder;
20use crate::catalog::CatalogError;
21use crate::error::{ErrorCode, Result};
22use crate::handler::HandlerArgs;
23
24pub async fn handle_drop_user(
25 handler_args: HandlerArgs,
26 user_name: ObjectName,
27 if_exists: bool,
28 mode: Option<DropMode>,
29) -> Result<RwPgResponse> {
30 let session = handler_args.session;
31 if mode.is_some() {
32 return Err(ErrorCode::BindError("Drop user not support drop mode".to_owned()).into());
33 }
34
35 let user_name = Binder::resolve_user_name(user_name)?;
36 let user_info_reader = session.env().user_info_reader();
37 let user_info = user_info_reader
38 .read_guard()
39 .get_user_by_name(&user_name)
40 .map(|u| (u.id, u.is_super));
41 match user_info {
42 Some((user_id, is_super)) => {
43 if session.user_id() == user_id {
44 return Err(ErrorCode::PermissionDenied(
45 "current user cannot be dropped".to_owned(),
46 )
47 .into());
48 }
49 if let Some(current_user) = user_info_reader
50 .read_guard()
51 .get_user_by_name(&session.user_name())
52 {
53 if !current_user.is_super {
54 if is_super {
55 return Err(ErrorCode::PermissionDenied(
56 "must be superuser to drop superusers".to_owned(),
57 )
58 .into());
59 }
60 if !current_user.can_create_user {
61 return Err(ErrorCode::PermissionDenied(
62 "permission denied to drop user".to_owned(),
63 )
64 .into());
65 }
66 }
67 } else {
68 return Err(
69 ErrorCode::PermissionDenied("Session user is invalid".to_owned()).into(),
70 );
71 }
72
73 let user_info_writer = session.user_info_writer()?;
74 user_info_writer.drop_user(user_id).await?;
75 }
76 None => {
77 return if if_exists {
78 Ok(PgResponse::builder(StatementType::DROP_USER)
79 .notice(format!("user \"{}\" does not exist, skipping", user_name))
80 .into())
81 } else {
82 Err(CatalogError::NotFound("user", user_name).into())
83 };
84 }
85 }
86
87 Ok(PgResponse::empty_result(StatementType::DROP_USER))
88}
89
90#[cfg(test)]
91mod tests {
92 use crate::test_utils::LocalFrontend;
93
94 #[tokio::test]
95 async fn test_drop_user() {
96 let frontend = LocalFrontend::new(Default::default()).await;
97 let session = frontend.session_ref();
98 let user_info_reader = session.env().user_info_reader();
99
100 frontend.run_sql("CREATE USER user").await.unwrap();
101 assert!(
102 user_info_reader
103 .read_guard()
104 .get_user_by_name("user")
105 .is_some()
106 );
107
108 frontend.run_sql("DROP USER user").await.unwrap();
109 assert!(
110 user_info_reader
111 .read_guard()
112 .get_user_by_name("user")
113 .is_none()
114 );
115 }
116}