"regex",
"rmp",
"rmp-serde 0.15.0",
- "rocket",
- "rocket_contrib",
- "rocket_cors",
"serde",
"serde_json",
"serde_with",
"slotmap",
"strum",
"tempfile",
+ "tera",
"thiserror",
"toml 0.5.8",
"typetag",
strum = { version = "0.20", features = ['derive'] }
thiserror = "1"
tempfile = "3"
+tera = "0.11"
toml = "0.5"
typetag = "0.1.6"
uds = "0.2"
vecdeque-stableix = "1"
-
-rocket = { version = "^0.4.6", features=["sse"] }
-rocket_cors = "0.5"
-
-[dependencies.rocket_contrib]
-version = "0.4"
-default-features = false
-features = ["tera_templates","helmet","json","serve"]
// SPDX-License-Identifier: AGPL-3.0-or-later
// There is NO WARRANTY.
-use crate::imports::*;
+use super::*;
type WRC = WhatResponseToClientOp;
-#[derive(Clone,Copy,Debug,Eq,PartialEq,Serialize,Deserialize,EnumString)]
-pub enum PresentationLayout {
- Portrait,
- Landscape,
-}
-
type PL = PresentationLayout;
-impl<'r> FromParam<'r> for PresentationLayout {
+pub struct AbbrevPresentationLayout(pub PresentationLayout);
+
+impl<'r> FromParam<'r> for AbbrevPresentationLayout {
type Error = strum::ParseError;
fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
- param.as_str().parse()
+ AbbrevPresentationLayout(param.as_str().parse())
}
}
-impl PresentationLayout {
- pub fn template(self) -> &'static str {
- match self {
- PL::Portrait => "session",
- PL::Landscape => "landscape",
- }
- }
- pub fn abbreviate_timestamps(self) -> bool {
- match self {
- PL::Portrait => false,
- PL::Landscape => true,
- }
- }
-}
-
-impl Default for PresentationLayout {
- fn default() -> Self { PL::Portrait }
-}
-
-pub struct AbbrevPresentationLayout(pub PresentationLayout);
-
impl<'r> FromParam<'r> for AbbrevPresentationLayout {
type Error = ();
#[throws(Self::Error)]
}
}
+#[derive(Clone,Debug)]
+pub struct InstanceAccess<'i, Id> {
+ pub raw_token: &'i RawTokenVal,
+ pub i: InstanceAccessDetails<Id>,
+}
+
+impl<'r, Id> FromFormValue<'r> for InstanceAccess<'r, Id>
+ where Id : AccessId, OE : From<Id::Error>
+{
+ type Error = OE;
+ #[throws(OE)]
+ fn from_form_value(param: &'r RawStr) -> Self {
+ let g = Id::global_tokens(PRIVATE_Y).read().unwrap();
+ let token = RawTokenVal::from_str(param.as_str());
+ let i = g.get(token).ok_or(Id::ERROR)?;
+ InstanceAccess { raw_token : token, i : i.clone() }
+ }
+}
+
+
#[derive(Debug,Serialize,Deserialize)]
struct ApiPiece<O : ApiPieceOp> {
ctoken : RawToken,
}
}
-#[derive(Error,Debug)]
-pub enum ApiPieceOpError {
- ReportViaResponse(#[from] OnlineError),
- ReportViaUpdate(#[from] PieceOpError),
- PartiallyProcessed(PieceOpError, Vec<LogEntry>),
-}
-display_as_debug!(ApiPieceOpError);
-
-impl From<PlayerNotFound> for ApiPieceOpError {
- fn from(x: PlayerNotFound) -> ApiPieceOpError {
- ApiPieceOpError::ReportViaResponse(x.into())
- }
-}
-
-pub trait Lens : Debug {
- fn pieceid2visible(&self, piece: PieceId) -> VisiblePieceId;
- fn log_pri(&self, piece: PieceId, pc: &PieceState)
- -> PieceRenderInstructions;
- fn svg_pri(&self, piece: PieceId, pc: &PieceState, player: PlayerId)
- -> PieceRenderInstructions;
- fn massage_prep_piecestate(&self, ns : &mut PreparedPieceState);
- fn decode_visible_pieceid(&self, vpiece: VisiblePieceId, player: PlayerId)
- -> PieceId;
-}
-#[derive(Debug)]
-pub struct TransparentLens {
- // when lenses become nontrivial, make this nonconstructable
- // to find all the places where a TransparentLens was bodged
-}
-impl Lens for TransparentLens {
- fn pieceid2visible(&self, piece: PieceId) -> VisiblePieceId {
- let kd : slotmap::KeyData = piece.into();
- VisiblePieceId(kd)
- }
- fn log_pri(&self, piece: PieceId, pc: &PieceState)
- -> PieceRenderInstructions {
- let id = self.pieceid2visible(piece);
- PieceRenderInstructions { id, face : pc.face }
- }
- fn svg_pri(&self, piece: PieceId, pc: &PieceState, _player: PlayerId)
- -> PieceRenderInstructions {
- self.log_pri(piece, pc)
- }
- fn decode_visible_pieceid(&self, vpiece: VisiblePieceId, _player: PlayerId)
- -> PieceId {
- let kd : slotmap::KeyData = vpiece.into();
- PieceId::from(kd)
- }
- fn massage_prep_piecestate(&self, _ns : &mut PreparedPieceState) { }
-}
-
impl From<&OnlineError> for rocket::http::Status {
fn from(oe: &OnlineError) -> rocket::http::Status {
use OnlineError::*;
// management API implementation
-use crate::imports::*;
+use super::*;
+
+use authproofs::*;
// ---------- newtypes, type aliases, basic definitions ----------
use std::os::unix::net::UnixListener;
use uds::UnixStreamExt;
-pub use crate::from_instance_lock_error;
-pub use std::os::unix::net::UnixStream;
-
type SE = SpecError;
type CSE = anyhow::Error;
use MgmtResponse::*;
type ME = MgmtError;
-from_instance_lock_error!{MgmtError}
type AS = AccountScope;
type TP = TablePermission;
const DEFAULT_POS_START: Pos = PosC([20,20]);
const DEFAULT_POS_DELTA: Pos = PosC([5,5]);
-pub type AuthorisationSuperuser = Authorisation<authproofs::Global>;
-
pub struct CommandListener {
listener: UnixListener,
}
let mut games = games_lock();
let auth = authorise_by_account(cs, &ag, &game)?;
- let gs = crate::gamestate::GameState {
+ let gs = otter::gamestate::GameState {
table_colour: Html::lit("green"),
table_size: DEFAULT_TABLE_SIZE,
pieces: default(),
#[error("connection euid lookup failed (at connection initiation): {0}")]
pub struct ConnectionEuidDiscoverEerror(String);
+impl From<ConnectionEuidDiscoverEerror> for AuthorisationError {
+ fn from(e: ConnectionEuidDiscoverEerror) -> AuthorisationError {
+ AuthorisationError(format!("{}", e))
+ }
+}
+
impl CommandStream<'_> {
#[throws(AuthorisationError)]
fn authorised_uid(&self, wanted: Option<Uid>, xinfo: Option<&str>)
}
}
-
-use authproofs::*;
-use authproofs::AuthorisationError;
-
-pub use authproofs::Authorisation;
-pub use authproofs::Unauthorised;
-
-mod authproofs {
- use crate::imports::*;
-
- #[derive(Copy,Clone,Debug)]
- pub struct Global;
-
- #[derive(Debug,Copy,Clone)]
- pub struct Unauthorised<T,A> (T, PhantomData<A>);
- impl<T,A> Unauthorised<T,A> {
- pub fn of(t: T) -> Self { Unauthorised(t, PhantomData) }
- pub fn by(self, _auth: Authorisation<A>) -> T { self.0 }
- pub fn by_ref(&self, _auth: Authorisation<A>) -> & T { & self.0 }
- pub fn by_mut(&mut self, _auth: Authorisation<A>) -> &mut T { &mut self.0 }
- }
- impl<T,A> From<T> for Unauthorised<T,A> {
- fn from(t: T) -> Self { Self::of(t) }
- }
-
- #[derive(Error,Debug)]
- #[error("internal AuthorisationError {0}")]
- pub struct AuthorisationError(pub String);
-
- #[derive(Debug)]
- pub struct Authorisation<A> (PhantomData<*const A>);
- impl<A> Clone for Authorisation<A> { fn clone(&self) -> Self { *self } }
- impl<A> Copy for Authorisation<A> { }
-
- impl<T> Authorisation<T> {
- pub const fn authorised(_v: &T) -> Authorisation<T> {
- Authorisation(PhantomData)
- }
- pub fn map<U>(self, _f: fn(&T) -> &U) -> Authorisation<U> {
- self.therefore_ok()
- }
- pub fn therefore_ok<U>(self) -> Authorisation<U> {
- Authorisation(PhantomData)
- }
- pub const fn authorise_any() -> Authorisation<T> {
- Authorisation(PhantomData)
- }
- }
-
- impl<T:Serialize> From<Authorisation<Global>> for Authorisation<T> {
- // ^ we need a bound not met by Global or we conflict with From<T> for T
- fn from(global: Authorisation<Global>) -> Self {
- global.therefore_ok()
- }
- }
-
- impl From<anyhow::Error> for AuthorisationError {
- fn from(a: anyhow::Error) -> AuthorisationError {
- AuthorisationError(format!("{}", a))
- }
- }
- impl From<ConnectionEuidDiscoverEerror> for AuthorisationError {
- fn from(e: ConnectionEuidDiscoverEerror) -> AuthorisationError {
- AuthorisationError(format!("{}", e))
- }
- }
-
- pub trait AuthorisationCombine: Sized {
- type Output;
- fn combine(self) -> Authorisation<Self::Output> {
- Authorisation(PhantomData)
- }
- }
- impl<A,B> AuthorisationCombine
- for (Authorisation<A>, Authorisation<B>) {
- type Output = (A, B);
- }
- impl<A,B,C> AuthorisationCombine
- for (Authorisation<A>, Authorisation<B>, Authorisation<C>) {
- type Output = (A, B, C);
- }
-}
-
-
#![feature(proc_macro_hygiene, decl_macro)]
+pub mod api;
+pub mod cmdlistener;
+pub mod session;
+
+pub use rocket::http::Status;
+pub use rocket::http::{ContentType, RawStr};
+pub use rocket::request::Request;
+pub use rocket::request::{FromFormValue, FromParam, FromRequest, LenientForm};
+pub use rocket::response;
+pub use rocket::response::NamedFile;
+pub use rocket::response::{Responder, Response};
+pub use rocket::{get, post, routes};
+pub use rocket::{Rocket, State};
+pub use rocket_contrib::helmet::*;
+pub use rocket_contrib::json::Json;
+pub use rocket_contrib::templates::tera::{self, Value};
+pub use rocket_contrib::templates::Engines;
+pub use rocket_contrib::templates::Template;
+
+pub use crate::api::{AbbrevPresentationLayout};
+pub use crate::api::{ApiPieceOpError, Lens, TransparentLens};
+pub use crate::cmdlistener::*;
+
use rocket::fairing;
-use rocket::{get, routes};
use rocket::response::Content;
use rocket_contrib::serve::StaticFiles;
r = r.attach(ReportStartup);
}
- let r = otter::session::mount(r);
- let r = otter::api::mount(r);
+ let r = crate::session::mount(r);
+ let r = crate::api::mount(r);
thread::spawn(client_periodic_expiry);
thread::spawn(logs_periodic_expiry);
// SPDX-License-Identifier: AGPL-3.0-or-later
// There is NO WARRANTY.
-use crate::imports::*;
+use super::*;
#[derive(Serialize,Debug)]
struct SessionRenderContext {
use parking_lot::{Mutex, const_mutex, MutexGuard};
+use authproofs::*;
+
//---------- simple types ----------
slotmap::new_key_type!{
pub mod loaded_acl {
use crate::imports::*;
+ use authproofs::*;
pub trait Perm : FromPrimitive + ToPrimitive +
Copy + Eq + Hash + Sync + Send + 'static
--- /dev/null
+// Copyright 2020 Ian Jackson
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// There is NO WARRANTY.
+
+use crate::imports::*;
+
+#[derive(Copy,Clone,Debug)]
+pub struct Global;
+
+#[derive(Debug,Copy,Clone)]
+pub struct Unauthorised<T,A> (T, PhantomData<A>);
+impl<T,A> Unauthorised<T,A> {
+ pub fn of(t: T) -> Self { Unauthorised(t, PhantomData) }
+ pub fn by(self, _auth: Authorisation<A>) -> T { self.0 }
+ pub fn by_ref(&self, _auth: Authorisation<A>) -> & T { & self.0 }
+ pub fn by_mut(&mut self, _auth: Authorisation<A>) -> &mut T { &mut self.0 }
+}
+impl<T,A> From<T> for Unauthorised<T,A> {
+ fn from(t: T) -> Self { Self::of(t) }
+}
+
+#[derive(Error,Debug)]
+#[error("internal AuthorisationError {0}")]
+pub struct AuthorisationError(pub String);
+
+#[derive(Debug)]
+pub struct Authorisation<A> (PhantomData<*const A>);
+impl<A> Clone for Authorisation<A> { fn clone(&self) -> Self { *self } }
+impl<A> Copy for Authorisation<A> { }
+
+pub type AuthorisationSuperuser = Authorisation<Global>;
+
+impl<T> Authorisation<T> {
+ pub const fn authorised(_v: &T) -> Authorisation<T> {
+ Authorisation(PhantomData)
+ }
+ pub fn map<U>(self, _f: fn(&T) -> &U) -> Authorisation<U> {
+ self.therefore_ok()
+ }
+ pub fn therefore_ok<U>(self) -> Authorisation<U> {
+ Authorisation(PhantomData)
+ }
+ pub const fn authorise_any() -> Authorisation<T> {
+ Authorisation(PhantomData)
+ }
+}
+
+impl<T:Serialize> From<Authorisation<Global>> for Authorisation<T> {
+ // ^ we need a bound not met by Global or we conflict with From<T> for T
+ fn from(global: Authorisation<Global>) -> Self {
+ global.therefore_ok()
+ }
+}
+
+impl From<anyhow::Error> for AuthorisationError {
+ fn from(a: anyhow::Error) -> AuthorisationError {
+ AuthorisationError(format!("{}", a))
+ }
+}
+
+pub trait AuthorisationCombine: Sized {
+ type Output;
+ fn combine(self) -> Authorisation<Self::Output> {
+ Authorisation(PhantomData)
+ }
+}
+impl<A,B> AuthorisationCombine
+ for (Authorisation<A>, Authorisation<B>) {
+ type Output = (A, B);
+}
+impl<A,B,C> AuthorisationCombine
+ for (Authorisation<A>, Authorisation<B>, Authorisation<C>) {
+ type Output = (A, B, C);
+}
SpecError::InternalError(format!("{:?}", ie))
}
}
+
+#[derive(Error,Debug)]
+pub enum ApiPieceOpError {
+ ReportViaResponse(#[from] OnlineError),
+ ReportViaUpdate(#[from] PieceOpError),
+ PartiallyProcessed(PieceOpError, Vec<LogEntry>),
+}
+display_as_debug!(ApiPieceOpError);
+
+impl From<PlayerNotFound> for ApiPieceOpError {
+ fn from(x: PlayerNotFound) -> ApiPieceOpError {
+ ApiPieceOpError::ReportViaResponse(x.into())
+ }
+}
+
#[derive(Error,Debug,Serialize,Clone)]
pub enum ErrorSignaledViaUpdate {
InternalError,
pub acctid: AccountId,
}
-#[derive(Clone,Debug)]
-pub struct InstanceAccess<'i, Id> {
- pub raw_token: &'i RawTokenVal,
- pub i: InstanceAccessDetails<Id>,
-}
-
// ========== internal data structures ==========
lazy_static! {
impl<X> From<PoisonError<X>> for InstanceLockError {
fn from(_: PoisonError<X>) -> Self { Self::GameCorrupted }
}
+from_instance_lock_error!{MgmtError}
pub struct PrivateCaller(());
// outsiders cannot construct this
.ok_or(Id::ERROR)
}
-impl<'r, Id> FromFormValue<'r> for InstanceAccess<'r, Id>
- where Id : AccessId, OE : From<Id::Error>
-{
- type Error = OE;
- #[throws(OE)]
- fn from_form_value(param: &'r RawStr) -> Self {
- let g = Id::global_tokens(PRIVATE_Y).read().unwrap();
- let token = RawTokenVal::from_str(param.as_str());
- let i = g.get(token).ok_or(Id::ERROR)?;
- InstanceAccess { raw_token : token, i : i.clone() }
- }
-}
-
#[throws(OE)]
pub fn record_token<Id : AccessId> (
ig: &mut InstanceGuard,
pub use std::ops::{Deref, DerefMut};
pub use std::os::unix;
pub use std::os::unix::ffi::OsStrExt;
+pub use std::os::unix::net::UnixStream;
pub use std::os::unix::process::CommandExt;
pub use std::path::PathBuf;
pub use std::process::{exit, Command};
pub use rand::thread_rng;
pub use rand::Rng;
pub use regex::Regex;
-pub use rocket::http::Status;
-pub use rocket::http::{ContentType, RawStr};
-pub use rocket::request::Request;
-pub use rocket::request::{FromFormValue, FromParam, FromRequest, LenientForm};
-pub use rocket::response;
-pub use rocket::response::NamedFile;
-pub use rocket::response::{Responder, Response};
-pub use rocket::{get, post, routes};
-pub use rocket::{Rocket, State};
-pub use rocket_contrib::helmet::*;
-pub use rocket_contrib::json::Json;
-pub use rocket_contrib::templates::tera::{self, Value};
-pub use rocket_contrib::templates::Engines;
-pub use rocket_contrib::templates::Template;
pub use serde::ser::SerializeTuple;
pub use serde::{de::DeserializeOwned, Deserialize, Serialize};
pub use serde::{Deserializer, Serializer};
pub use vecdeque_stableix::Deque as StableIndexVecDeque;
pub use zcoord::{self, ZCoord};
+pub use crate::from_instance_lock_error;
+
pub use crate::accounts::loaded_acl::{self, EffectiveACL, LoadedAcl, PermSet};
pub use crate::accounts::*;
-pub use crate::api::{AbbrevPresentationLayout, PresentationLayout};
-pub use crate::api::{ApiPieceOpError, Lens, TransparentLens};
-pub use crate::cmdlistener::*;
+pub use crate::authproofs::{self, Authorisation, Unauthorised};
+pub use crate::authproofs::AuthorisationSuperuser;
pub use crate::commands::*;
pub use crate::config::*;
pub use crate::debugreader::DebugReader;
pub use crate::gamestate::*;
pub use crate::global::*;
pub use crate::keydata::*;
+pub use crate::lens::*;
pub use crate::mgmtchannel::*;
pub use crate::nwtemplates;
pub use crate::pieces::*;
pub use crate::tz::*;
pub use crate::updates::*;
pub use crate::utils::*;
+pub use crate::ui::*;
pub type SecondarySlotMap<K,V> = slotmap::secondary::SecondaryMap<K,V>;
pub type SvgData = Vec<u8>;
--- /dev/null
+// Copyright 2020 Ian Jackson
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// There is NO WARRANTY.
+
+use crate::imports::*;
+
+pub trait Lens : Debug {
+ fn pieceid2visible(&self, piece: PieceId) -> VisiblePieceId;
+ fn log_pri(&self, piece: PieceId, pc: &PieceState)
+ -> PieceRenderInstructions;
+ fn svg_pri(&self, piece: PieceId, pc: &PieceState, player: PlayerId)
+ -> PieceRenderInstructions;
+ fn massage_prep_piecestate(&self, ns : &mut PreparedPieceState);
+ fn decode_visible_pieceid(&self, vpiece: VisiblePieceId, player: PlayerId)
+ -> PieceId;
+}
+#[derive(Debug)]
+pub struct TransparentLens {
+ // when lenses become nontrivial, make this nonconstructable
+ // to find all the places where a TransparentLens was bodged
+}
+impl Lens for TransparentLens {
+ fn pieceid2visible(&self, piece: PieceId) -> VisiblePieceId {
+ let kd : slotmap::KeyData = piece.into();
+ VisiblePieceId(kd)
+ }
+ fn log_pri(&self, piece: PieceId, pc: &PieceState)
+ -> PieceRenderInstructions {
+ let id = self.pieceid2visible(piece);
+ PieceRenderInstructions { id, face : pc.face }
+ }
+ fn svg_pri(&self, piece: PieceId, pc: &PieceState, _player: PlayerId)
+ -> PieceRenderInstructions {
+ self.log_pri(piece, pc)
+ }
+ fn decode_visible_pieceid(&self, vpiece: VisiblePieceId, _player: PlayerId)
+ -> PieceId {
+ let kd : slotmap::KeyData = vpiece.into();
+ PieceId::from(kd)
+ }
+ fn massage_prep_piecestate(&self, _ns : &mut PreparedPieceState) { }
+}
+
#![allow(clippy::redundant_closure_call)]
pub mod accounts;
-pub mod api;
-pub mod cmdlistener;
+pub mod authproofs;
pub mod commands;
pub mod config;
pub mod debugreader;
pub mod global;
pub mod imports;
pub mod keydata;
+pub mod lens;
pub mod mgmtchannel;
pub mod nwtemplates;
pub mod pieces;
-pub mod session;
pub mod shapelib;
pub mod spec;
pub mod sse;
pub mod tz;
pub mod updates;
+pub mod ui;
pub mod utils;
#[path = "slotmap-slot-idx.rs"] pub mod slotmap_slot_idx;
--- /dev/null
+// Copyright 2020 Ian Jackson
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// There is NO WARRANTY.
+
+use crate::imports::*;
+
+#[derive(Clone,Copy,Debug,Eq,PartialEq,Serialize,Deserialize,EnumString)]
+pub enum PresentationLayout {
+ Portrait,
+ Landscape,
+}
+
+type PL = PresentationLayout;
+
+impl PresentationLayout {
+ pub fn template(self) -> &'static str {
+ match self {
+ PL::Portrait => "session",
+ PL::Landscape => "landscape",
+ }
+ }
+ pub fn abbreviate_timestamps(self) -> bool {
+ match self {
+ PL::Portrait => false,
+ PL::Landscape => true,
+ }
+ }
+}
+
+impl Default for PresentationLayout {
+ fn default() -> Self { PL::Portrait }
+}
+