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