f: F
) -> ExecuteGameInsnResults
{
- let ig = cs.check_acl(p)?;
+ let ig = cs.check_acl(ig, PCH::InstanceOnly, p)?;
let resp = f(ig);
(U{ pcs: vec![], log: vec![], raw: None }, resp)
}
let (ig, auth) = cs.check_acl_manip_player_access
(ig, player, TP::RedeliverOthersAccess)?;
- let token = ig.player_access_redeliver(player)?;
+ let token = ig.player_access_redeliver(player, auth)?;
(U{ pcs: vec![],
log: vec![],
raw: None },
*/
DeletePiece(piece) => {
- let modperm = ig.modify_pieces();
- let p = ig.pieces.as_mut(modperm)
+ let (ig, modperm, _) = cs.check_acl_modify_pieces(ig)?;
+ let p = ig.ipieces.as_mut(modperm)
.remove(piece).ok_or(ME::PieceNotFound)?;
let gs = &mut ig.gs;
let pc = gs.pieces.as_mut(modperm).remove(piece);
},
AddPieces(PiecesSpec{ pos,posd,count,face,pinned,info }) => {
- let modperm = ig.modify_pieces();
+ let (ig, modperm, _) = cs.check_acl_modify_pieces(ig)?;
let ig = &mut **ig;
let gs = &mut ig.gs;
let count = count.unwrap_or(1);
throw!(SpecError::PosOffTable);
}
let piece = gs.pieces.as_mut(modperm).insert(pc);
- ig.pieces.as_mut(modperm).insert(piece, p);
+ ig.ipieces.as_mut(modperm).insert(piece, p);
updates.push((piece, PieceUpdateOp::Insert(())));
pos += posd;
}
impl CommandStream<'_> {
+ #[throws(MgmtError)]
+ pub fn check_acl_modify_pieces(
+ &mut self,
+ ig: &mut Unauthorised<InstanceGuard, InstanceName>,
+ ) -> (&mut InstanceGuard, ModifyingPieces, Authorisation<InstanceName>)
+ {
+ let p = &[TP::ChangePieces];
+ let (ig, auth) = self.check_acl(self, PCH::Instance, p)?;
+ let modperm = ig.modify_pieces();
+ (ig, modperm, auth)
+ }
+
#[throws(MgmtError)]
pub fn check_acl<P: Into<PermSet<TablePermission>>>(
&mut self,
ig: &mut Unauthorised<InstanceGuard, InstanceName>,
how: PermissionCheckHow<'_>,
p: P,
- ) -> (&mut InstanceGuard, Authorisation<InstanceName>) {
-
+ ) -> (&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 {
use std::sync::PoisonError;
use slotmap::dense as sm;
+type ME = MgmtError;
+
// ---------- newtypes and type aliases ----------
visible_slotmap_key!{ ClientId('C') }
}
#[throws(MgmtError)]
- pub fn player_access_reset(&mut self, player: PlayerId,
- authorised: Authorisation<AccountName>)
- -> Option<AccessTokenReport> {
- // xxx call this function when access changes
-
+ fn player_access_reset_redeliver(&mut self, player: PlayerId,
+ authorised: Authorisation<AccountName>,
+ reset: bool)
+ -> Option<AccessTokenReport> {
let pst = self.c.g.iplayers.get(player)
.ok_or(MgmtError::PlayerNotFound)?
.pst;
- self.save_access_now()?;
let access = AccountRecord::with_entry_mut(
&pst.account, authorised,
Ok::<_,MgmtError>(access.clone())
}).map_err(|(e,_)|e)??;
- let token = access
- .override_token()
- .cloned()
- .unwrap_or_else(||{
- RawToken::new_random()
- // xxx disconnect everyone else
- });
+ if reset {
+ self.save_access_now()?;
+ }
- let iad = InstanceAccessDetails {
- gref : self.gref.clone(),
- ident : player
+ let token : RawToken = if reset {
+
+ let token = access
+ .override_token()
+ .cloned()
+ .unwrap_or_else(||{
+ RawToken::new_random()
+ // xxx disconnect everyone else
+ });
+
+ let iad = InstanceAccessDetails {
+ gref : self.gref.clone(),
+ ident : player
+ };
+ self.token_register(token.clone(), iad);
+
+ token
+
+ } else {
+
+ let tokens : ArrayVec<[&RawToken;2]> = {
+ let players = GLOBAL.players.read().unwrap();
+ self.tokens_players.tr.iter().
+ filter(|&token| (||{
+ let iad = players.get(token)?;
+ if iad.ident != player { return None }
+ if ! Arc::ptr_eq(&iad.gref.0, &self.gref.0) { return None }
+ Some(())
+ })() == Some(()))
+ .take(2)
+ .collect()
+ };
+
+ let token = match tokens.as_slice() {
+ [] => throw!(ME::AuthorisationUninitialised),
+ [&token] => token,
+ _ => {
+ warn!("duplicate token for {}", player);
+ throw!(ME::ServerFailure("duplicate token".to_string()));
+ },
+ };
+
+ token.clone()
};
- 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 player_access_reset(&mut self, player: PlayerId,
+ auth: Authorisation<AccountName>)
+ -> Option<AccessTokenReport> {
+ // xxx call this function when access method changes
+ self.player_access_reset_redeliver(player, auth, true)?
+ }
+
+ #[throws(MgmtError)]
+ pub fn player_access_redeliver(&mut self, player: PlayerId,
+ auth: Authorisation<AccountName>)
+ -> Option<AccessTokenReport> {
+ self.player_access_reset_redeliver(player, auth, false)?
+ }
+
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