From: Ian Jackson Date: Sat, 24 Oct 2020 00:30:24 +0000 (+0100) Subject: wip new account etc. X-Git-Tag: otter-0.2.0~600 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=66f416738ad05f9b084710aa46c4f62cf65d79c4;p=otter.git wip new account etc. Signed-off-by: Ian Jackson --- diff --git a/src/accounts.rs b/src/accounts.rs index 8540c47e..42399964 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -16,6 +16,7 @@ pub enum AccountScope { } type AS = AccountScope; +type ME = MgmtError; #[derive(Debug,Clone)] #[derive(Eq,PartialEq,Ord,PartialOrd,Hash)] @@ -188,9 +189,9 @@ impl AccountRecord { } #[throws(MgmtError)] - pub fn insert_entry(account: AccountName, - _auth: Authorisation, - data: AccountRecord) + pub fn insert_entry(account: AccountName, + _auth: Authorisation, + data: AccountRecord) { let entry = ACCOUNTS.write().unwrap_or_default().entry(account); use hash_map::Entry::*; diff --git a/src/cmdlistener.rs b/src/cmdlistener.rs index d5c2ce05..f39fd308 100644 --- a/src/cmdlistener.rs +++ b/src/cmdlistener.rs @@ -48,6 +48,7 @@ struct CommandStream<'d> { euid : Result, desc : &'d str, account : Option, + superuser: Option>, chan : MgmtChannel, who: Who, } @@ -78,6 +79,30 @@ fn execute(cs: &mut CommandStream, cmd: MgmtCommand) -> MgmtResponse { match cmd { Noop => Fine, + SetSuperuser(enable) => { + if !enable { + cs.superuser = None; + } else { + let auth = authorise_scope_direct(cs, &AccountScope::Server)?; + cs.superuser = Some(auth.therefore_ok()); + } + Fine + }, + + CreateAccont(AccountDetails { account, nick, timezone, access }) => { + let auth = authorise_for_account(cs, &account)?; + let access = access + .map(Into::into) + .unwrap_or_else(|| Arc::new(PlayerAccessUnset) as Arc<_>); + let record = AccountRecord { + nick, access, + timezone: timezone.unwrap_or_default(), + tokens_revealed: default(), + }; + AccountRecord::insert_entry(account, auth, record)?; + Fine + } + SetAccount(wanted_account) => { let auth = authorise_scope_direct(cs, &wanted_account.scope)?; cs.account = Some(AccountSpecified { @@ -88,10 +113,6 @@ fn execute(cs: &mut CommandStream, cmd: MgmtCommand) -> MgmtResponse { Fine }, - CreateAccont(AccountDetails) => { - let authorised = authorise_for_account(cs, &game)?; - } - CreateGame { game, insns } => { let authorised = authorise_by_account(cs, &game)?; @@ -620,6 +641,7 @@ impl CommandListener { let cs = CommandStream { account: None, desc: &desc, chan, euid: euid.map(Uid::from_raw), + superuser: None, who: Who, }; cs.mainloop()?; @@ -665,6 +687,10 @@ impl CommandStream<'_> { impl CommandStream<'_> { + pub fn is_superuser(&self) -> Option> { + self.superuser.map(Into::into) + } + #[throws(MgmtError)] pub fn check_acl_modify_pieces<'ig>( &mut self, @@ -746,15 +772,24 @@ impl CommandStream<'_> { } #[throws(MgmtError)] -fn authorise_by_account(cs: &CommandStream, wanted: &InstanceName) - -> Authorisation { +fn authorise_for_account(cs: &CommandStream, wanted: &AccountName) + -> Authorisation { + if let Some(y) = cs.is_superuser() { return y } + let currently = &cs.current_account()?; - if currently.account != wanted.account { + if ¤tly.account != wanted { throw!(MgmtError::AuthorisationError) } Authorisation::authorised(wanted) } +#[throws(MgmtError)] +fn authorise_by_account(cs: &CommandStream, wanted: &InstanceName) + -> Authorisation { + authorise_for_account(cs, &wanted.account)? + .therefore_ok() +} + #[throws(MgmtError)] fn authorise_scope_direct(cs: &CommandStream, wanted: &AccountScope) -> Authorisation { @@ -766,6 +801,8 @@ fn authorise_scope_direct(cs: &CommandStream, wanted: &AccountScope) #[throws(AuthorisationError)] fn do_authorise_scope(cs: &CommandStream, wanted: &AccountScope) -> Authorisation { + if let Some(y) = cs.is_superuser() { return y } + match &wanted { AccountScope::Server => { @@ -856,6 +893,9 @@ pub use authproofs::Unauthorised; mod authproofs { use crate::imports::*; + #[derive(Copy,Clone,Debug)] + pub struct Global; + #[derive(Debug,Copy,Clone)] pub struct Unauthorised (T, PhantomData); impl Unauthorised { @@ -890,6 +930,13 @@ mod authproofs { } } + impl From> for Authorisation { + // ^ we need a bound not met by Global or we conflict with From for T + fn from(global: Authorisation) -> Self { + global.therefore_ok() + } + } + impl From for AuthorisationError { fn from(a: anyhow::Error) -> AuthorisationError { AuthorisationError(format!("{}",a)) diff --git a/src/commands.rs b/src/commands.rs index 8f74fea5..6eb1a253 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -7,6 +7,7 @@ use crate::imports::*; #[derive(Debug,Serialize,Deserialize)] pub enum MgmtCommand { Noop, + SetSuperuser(bool), CreateAccont(AccountDetails), UpdateAccont(AccountDetails),