Add `auth listuser` subaction

next
Sayan Nandan 3 years ago
parent 37ba222428
commit ad2f87de7a
No known key found for this signature in database
GPG Key ID: 8BC07A0A4D41DD52

@ -14,6 +14,7 @@ All changes in this project will be noted in this file.
- `auth deluser <username>` - `auth deluser <username>`
- `auth restore <username>` - `auth restore <username>`
- `auth restore <origin key> <username>` - `auth restore <origin key> <username>`
- `auth listuser`
- Shell now supports multiple `--eval` expressions - Shell now supports multiple `--eval` expressions
- Partial entity syntax: `:table` can be used for referring to the current table. For example - Partial entity syntax: `:table` can be used for referring to the current table. For example
you can use `use :default` instead of `use default:default` you can use `use :default` instead of `use default:default`

4
Cargo.lock generated

@ -1209,7 +1209,7 @@ dependencies = [
[[package]] [[package]]
name = "skytable" name = "skytable"
version = "0.7.0-alpha.4" version = "0.7.0-alpha.4"
source = "git+https://github.com/skytable/client-rust?branch=next#bea0bb07d6a8af8650fa445744b9a77eae413fcb" source = "git+https://github.com/skytable/client-rust?branch=next#6d1affbc5a0ec9c9d4a1cb98f6542962fef6aac1"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"bb8", "bb8",
@ -1223,7 +1223,7 @@ dependencies = [
[[package]] [[package]]
name = "skytable" name = "skytable"
version = "0.7.0-alpha.4" version = "0.7.0-alpha.4"
source = "git+https://github.com/skytable/client-rust.git#bea0bb07d6a8af8650fa445744b9a77eae413fcb" source = "git+https://github.com/skytable/client-rust.git#6d1affbc5a0ec9c9d4a1cb98f6542962fef6aac1"
dependencies = [ dependencies = [
"r2d2", "r2d2",
] ]

@ -38,6 +38,7 @@
mod keys; mod keys;
pub mod provider; pub mod provider;
use crate::resp::{writer::NonNullArrayWriter, TSYMBOL_UNICODE_STRING};
pub use provider::{AuthProvider, AuthResult, Authmap}; pub use provider::{AuthProvider, AuthResult, Authmap};
pub mod errors; pub mod errors;
pub use errors::AuthError; pub use errors::AuthError;
@ -53,6 +54,7 @@ const AUTH_LOGOUT: &[u8] = b"logout";
const AUTH_ADDUSER: &[u8] = b"adduser"; const AUTH_ADDUSER: &[u8] = b"adduser";
const AUTH_DELUSER: &[u8] = b"deluser"; const AUTH_DELUSER: &[u8] = b"deluser";
const AUTH_RESTORE: &[u8] = b"restore"; const AUTH_RESTORE: &[u8] = b"restore";
const AUTH_LISTUSER: &[u8] = b"listuser";
action! { action! {
/// Handle auth. Should have passed the `auth` token /// Handle auth. Should have passed the `auth` token
@ -86,9 +88,22 @@ action! {
Ok(()) Ok(())
} }
AUTH_RESTORE => self::auth_restore(con, auth, &mut iter).await, AUTH_RESTORE => self::auth_restore(con, auth, &mut iter).await,
AUTH_LISTUSER => self::auth_listuser(con, auth, &mut iter).await,
_ => util::err(groups::UNKNOWN_ACTION), _ => util::err(groups::UNKNOWN_ACTION),
} }
} }
fn auth_listuser(con: &mut T, auth: &mut AuthProviderHandle<'_, T, Strm>, iter: &mut ActionIter<'_>) {
ensure_boolean_or_aerr(iter.len() == 0)?;
let usernames = auth.provider().collect_usernames()?;
let mut array_writer = unsafe {
// The symbol is definitely correct, obvious from this context
NonNullArrayWriter::new(con, TSYMBOL_UNICODE_STRING, usernames.len())
}.await?;
for username in usernames {
array_writer.write_element(username).await?;
}
Ok(())
}
fn auth_restore(con: &mut T, auth: &mut AuthProviderHandle<'_, T, Strm>, iter: &mut ActionIter<'_>) { fn auth_restore(con: &mut T, auth: &mut AuthProviderHandle<'_, T, Strm>, iter: &mut ActionIter<'_>) {
let newkey = match iter.len() { let newkey = match iter.len() {
1 => { 1 => {

@ -233,6 +233,15 @@ impl AuthProvider {
Err(AuthError::BadCredentials) Err(AuthError::BadCredentials)
} }
} }
/// List all the users
pub fn collect_usernames(&self) -> AuthResult<Vec<String>> {
self.ensure_root()?;
Ok(self
.authmap
.iter()
.map(|kv| String::from_utf8_lossy(kv.key()).to_string())
.collect())
}
} }
impl Clone for AuthProvider { impl Clone for AuthProvider {

@ -35,6 +35,8 @@ use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
pub mod writer; pub mod writer;
pub const TSYMBOL_UNICODE_STRING: u8 = b'+';
type FutureIoResult<'s> = FutureResult<'s, Result<(), IoError>>; type FutureIoResult<'s> = FutureResult<'s, Result<(), IoError>>;
/// # The `Writable` trait /// # The `Writable` trait
@ -88,7 +90,7 @@ pub struct StringWrapper(pub String);
impl Writable for StringWrapper { impl Writable for StringWrapper {
fn write<'s>(self, con: &'s mut impl IsConnection) -> FutureIoResult<'s> { fn write<'s>(self, con: &'s mut impl IsConnection) -> FutureIoResult<'s> {
Box::pin(async move { Box::pin(async move {
con.write_lowlevel(&[b'+']).await?; con.write_lowlevel(&[TSYMBOL_UNICODE_STRING]).await?;
// Now get the size of the Bytes object as bytes // Now get the size of the Bytes object as bytes
let size = Integer64::from(self.0.len()); let size = Integer64::from(self.0.len());
// Write this to the stream // Write this to the stream
@ -129,7 +131,7 @@ impl Writable for &'static str {
// string (we represent `String`s as `Byte` objects internally) // string (we represent `String`s as `Byte` objects internally)
// and since `Bytes` are effectively `String`s we will append the // and since `Bytes` are effectively `String`s we will append the
// type operator `+` to the stream // type operator `+` to the stream
con.write_lowlevel(&[b'+']).await?; con.write_lowlevel(&[TSYMBOL_UNICODE_STRING]).await?;
// Now get the size of the Bytes object as bytes // Now get the size of the Bytes object as bytes
let size = Integer64::from(self.len()); let size = Integer64::from(self.len());
// Write this to the stream // Write this to the stream
@ -153,7 +155,7 @@ impl Writable for BytesWrapper {
// and since `Bytes` are effectively `String`s we will append the // and since `Bytes` are effectively `String`s we will append the
// type operator `+` to the stream // type operator `+` to the stream
let bytes = self.finish_into_bytes(); let bytes = self.finish_into_bytes();
con.write_lowlevel(&[b'+']).await?; con.write_lowlevel(&[TSYMBOL_UNICODE_STRING]).await?;
// Now get the size of the Bytes object as bytes // Now get the size of the Bytes object as bytes
let size = Integer64::from(bytes.len()); let size = Integer64::from(bytes.len());
// Write this to the stream // Write this to the stream
@ -206,7 +208,7 @@ impl Writable for ObjectID {
// string (we represent `String`s as `Byte` objects internally) // string (we represent `String`s as `Byte` objects internally)
// and since `Bytes` are effectively `String`s we will append the // and since `Bytes` are effectively `String`s we will append the
// type operator `+` to the stream // type operator `+` to the stream
con.write_lowlevel(&[b'+']).await?; con.write_lowlevel(&[TSYMBOL_UNICODE_STRING]).await?;
// Now get the size of the Bytes object as bytes // Now get the size of the Bytes object as bytes
let size = Integer64::from(self.len()); let size = Integer64::from(self.len());
// Write this to the stream // Write this to the stream

@ -43,13 +43,13 @@ macro_rules! assert_auth_disabled {
macro_rules! assert_auth_perm_error { macro_rules! assert_auth_perm_error {
($con:expr, $query:expr) => { ($con:expr, $query:expr) => {
assert_autherror!($con, $query, RespCode::ErrorString("11".to_owned())) assert_autherror!($con, $query, RespCode::AuthPermissionError)
}; };
} }
macro_rules! assert_auth_bad_credentials { macro_rules! assert_auth_bad_credentials {
($con:expr, $query:expr) => { ($con:expr, $query:expr) => {
assert_autherror!($con, $query, RespCode::ErrorString("10".to_owned())) assert_autherror!($con, $query, RespCode::AuthBadCredentials)
}; };
} }
@ -241,6 +241,22 @@ async fn restore_okay_with_origin_key() {
); );
} }
// auth listuser
#[sky_macros::dbtest_func]
async fn listuser_fail_because_disabled() {
assert_auth_disabled!(con, query!("auth", "listuser"));
}
#[sky_macros::dbtest_func(port = 2005, auth_testuser = true)]
async fn listuser_fail_because_not_root() {
assert_auth_perm_error!(con, query!("auth", "listuser"))
}
#[sky_macros::dbtest_func(port = 2005, auth_rootuser = true)]
async fn listuser_okay_because_root() {
let ret: Vec<String> = con.run_query(query!("auth", "listuser")).await.unwrap();
assert!(ret.contains(&"root".to_owned()));
assert!(ret.contains(&"testuser".to_owned()));
}
mod syntax_checks { mod syntax_checks {
use super::{NOAUTH, ONLYAUTH}; use super::{NOAUTH, ONLYAUTH};
use crate::auth::provider::testsuite_data::{ use crate::auth::provider::testsuite_data::{
@ -313,6 +329,10 @@ mod syntax_checks {
query!("auth", "restore", "someuser", "origin", "but extra data") query!("auth", "restore", "someuser", "origin", "but extra data")
); );
} }
#[sky_macros::dbtest_func(port = 2005, norun = true)]
async fn listuser_aerr() {
assert_authn_aerr!(con, query!("auth", "listuser", "extra argument"), ONLYAUTH);
}
#[sky_macros::dbtest_func(port = 2005, norun = true, auth_testuser = true)] #[sky_macros::dbtest_func(port = 2005, norun = true, auth_testuser = true)]
async fn unknown_auth_action() { async fn unknown_auth_action() {
runeq!( runeq!(

Loading…
Cancel
Save