risingwave_frontend/handler/
drop_user.rs1use pgwire::pg_response::{PgResponse, StatementType};
16use risingwave_sqlparser::ast::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) -> Result<RwPgResponse> {
29 let session = handler_args.session;
30
31 let user_name = Binder::resolve_user_name(user_name)?;
32 let user_info_reader = session.env().user_info_reader();
33 let user_info = user_info_reader
34 .read_guard()
35 .get_user_by_name(&user_name)
36 .map(|u| (u.id, u.is_super, u.is_admin));
37 match user_info {
38 Some((user_id, is_super, is_admin)) => {
39 if session.user_id() == user_id {
40 return Err(ErrorCode::PermissionDenied(
41 "current user cannot be dropped".to_owned(),
42 )
43 .into());
44 }
45 if let Some(current_user) = user_info_reader
46 .read_guard()
47 .get_user_by_name(&session.user_name())
48 {
49 if !current_user.is_super {
50 if is_super {
51 return Err(ErrorCode::PermissionDenied(
52 "must be superuser to drop superusers".to_owned(),
53 )
54 .into());
55 }
56 if !current_user.can_create_user {
57 return Err(ErrorCode::PermissionDenied(
58 "permission denied to drop user".to_owned(),
59 )
60 .into());
61 }
62 }
63
64 if is_admin && !current_user.is_admin {
66 return Err(ErrorCode::PermissionDenied(
67 "only admin users can drop admin users".to_owned(),
68 )
69 .into());
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}