auth: Authorisation<AccountName>,
}
+enum PermissionCheckHow<'p> {
+ Instance,
+ InstanceOrOnlyAffectedAccount(&'p AccountName),
+ InstanceOrOnlyAffectedPlayer(PlayerId),
+}
+
+type PCH<'p> = PermissionCheckHow<'p>;
+
// ========== management API ==========
// ---------- management command implementations
(U{ pcs: vec![], log: vec![], raw: None }, resp)
}
+ impl<'cs> CommandStream<'cs> {
+ #[throws(MgmtError)]
+ fn check_acl_manip_player_access(
+ &mut self,
+ ig: &mut Unauthorised<InstanceGuard, InstanceName>,
+ player: PlayerId,
+ perm: TablePermission,
+ ) -> (&mut InstanceGuard, Authorisation<AccountName>) {
+ let (ig, auth) = self.check_acl(ig,
+ PCH::InstanceOrOnlyAffectedPlayer(player),
+ &[perm])?;
+ fn auth_map(n: &InstanceName) -> &AccountName { &n.account }
+ let auth = auth.map(&auth_map);
+ (ig, auth)
+ }
+ }
+
let y = match update {
Noop { } => readonly(cs,ig, &[], |ig| Fine),
Insn::SetTableSize(size) => {
- let ig = cs.check_acl(ig, &[TP::ChangePieces])?;
+ let ig = cs.check_acl(ig, PCH::Instance, &[TP::ChangePieces])?.0;
ig.gs.table_size = size;
(U{ pcs: vec![],
log: vec![ LogEntry {
Insn::AddPlayer(add) => {
// todo some kind of permissions check for player too
- let ig = cs.check_acl(ig, &[TP::AddPlayer])?;
+ let ig = cs.check_acl(ig, PCH::Instance, &[TP::AddPlayer])?.0;
let nick = add.nick.ok_or(ME::ParameterMissing)?;
let logentry = LogEntry {
html: Html(format!("{} added a player: {}", &who,
RemovePlayer(account) => {
// todo let you remove yourself unconditionally
- let ig = cs.check_acl(ig, &[TP::RemovePlayer])?;
+ let ig = cs.check_acl(ig,
+ PCH::InstanceOrOnlyAffectedAccount(&account),
+ &[TP::RemovePlayer])?.0;
let player = ig.gs.players.iter()
.filter_map(|(k,v)| if v == &account { Some(k) } else { None })
.next()
}),
ResetPlayerAccess(player) => {
- let token = ig.player_access_reset(player)?;
+ let (ig, auth) = cs.check_acl_manip_player_access
+ (ig, player, TP::ResetOthersAccess)?;
+
+ let token = ig.player_access_reset(player, auth)?;
(U{ pcs: vec![],
log: vec![],
raw: None },
}
RedeliverPlayerAccess(player) => {
+ let (ig, auth) = cs.check_acl_manip_player_access
+ (ig, player, TP::RedeliverOthersAccess)?;
+
let token = ig.player_access_redeliver(player)?;
(U{ pcs: vec![],
log: vec![],
self.desc, ae.0);
MgmtError::AuthorisationError
}
+}
+impl CommandStream<'_> {
#[throws(MgmtError)]
pub fn check_acl<P: Into<PermSet<TablePermission>>>(
&mut self,
ig: &mut Unauthorised<InstanceGuard, InstanceName>,
+ how: PermissionCheckHow<'_>,
p: P,
- ) -> &mut InstanceGuard {
+ ) -> (&mut InstanceGuard, Authorisation<InstanceName>) {
+
+ let subject_is = |object_account|{
+ if let Some(ref subject_account_spec) = self.account {
+ if subject_account_spec.account == object_account {
+ let auth : Authorisation<InstanceName>
+ = Authorisation::authorise_any();
+ return auth;
+ }
+ }
+ return None;
+ };
+
+ if let Some(auth) = match how {
+ PCH::InstanceOrOnlyAffectedAccount(object_account) => {
+ subject_is(object_account)
+ },
+ PCH::InstanceOrOnlyAffectedPlayer(object_player) => {
+ if let Some(object_account) = ig.gs.players.get(object_player) {
+ subject_is(object_account)
+ } else {
+ None
+ }
+ },
+ } {
+ return self.by_mut(auth);
+ }
+
let p = p.into();
let auth = {
let subject = &self.account.as_ref()?.cooked;
};
eacl.check(subject, p)?
};
- self.by_mut(auth);
+ (self.by_mut(auth), auth)
}
}
pub fn therefore_ok<U>(self) -> Authorisation<U> {
Authorisation(PhantomData)
}
+
+ pub fn map<U>(self, f: &fn(&T) -> &U) -> Authorisation<U> {
+ }
}
impl From<anyhow::Error> for AuthorisationError {
ident : player
};
self.token_register(token.clone(), iad);
+ self.access_redeliver(player, token, authorised)?
+ }
+ #[throws(MgmtError)]
+ fn access_redeliver(&mut self, player: PlayerId,
+ token: &RawToken,
+ authorised: Authorisation<AccountName>)
+ -> Option<AccessTokenReport> {
let report = AccessTokenReport {
url: format!("http://localhost:8000/{}", token.0), // xxx
};
report.cloned()
}
- #[throws(MgmtError)]
- pub fn players_access_report(&mut self, players: &[PlayerId])
- -> Vec<Vec<RawToken>> {
- let mut wanted = {
- let mut wanted = SecondarySlotMap::new();
- for &player in players {
- wanted.insert(player, vec![]);
- }
- let global = GLOBAL.players.read().unwrap();
- for token in &self.tokens_players.tr {
- (||{
- let iad = global.get(token)?;
- let e = wanted.get_mut(iad.ident)?;
- e.push(token.clone());
- Some(())
- })();
- }
- wanted
- };
- #[allow(clippy::or_fun_call)]
- let out = players.iter().map(|&player| {
- let mut tokens = wanted.remove(player)
- .unwrap_or(vec![] /* dupe, somehow */);
- tokens.sort_unstable();
- tokens
- }).collect();
- out
- }
-
pub fn modify_pieces(&mut self) -> ModifyingPieces {
self.save_game_and_access_later();
// want this to be borrowed from self, so that we tie it properly