From 6cac8f5a0647e9ba3e2d46e4478421f6cb7d05f8 Mon Sep 17 00:00:00 2001 From: Andrey Cizov Date: Thu, 1 Aug 2019 17:52:42 +0100 Subject: [PATCH 1/2] enable storage to only partially reference namespaces available for tokens --- src/storage.rs | 108 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 33 deletions(-) diff --git a/src/storage.rs b/src/storage.rs index 30eabe9..480cee2 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -4,7 +4,6 @@ // use std::collections::hash_map::DefaultHasher; -use std::collections::HashMap; use std::error::Error; use std::fmt; use std::fs; @@ -13,6 +12,7 @@ use std::io; use std::io::{Read, Write}; use crate::types::Token; +use itertools::Itertools; /// Implements a specialized storage to set and retrieve `Token` instances. /// The `scope_hash` represents the signature of the scopes for which the given token @@ -54,6 +54,7 @@ where /// A storage that remembers nothing. #[derive(Default)] pub struct NullStorage; + #[derive(Debug)] pub struct NullError; @@ -82,7 +83,7 @@ impl TokenStorage for NullStorage { /// A storage that remembers values for one session only. #[derive(Debug, Default)] pub struct MemoryStorage { - pub tokens: HashMap, + tokens: Vec, } impl MemoryStorage { @@ -94,31 +95,54 @@ impl MemoryStorage { impl TokenStorage for MemoryStorage { type Error = NullError; - fn set( - &mut self, - scope_hash: u64, - _: &Vec<&str>, - token: Option, - ) -> Result<(), NullError> { + fn set(&mut self, + scope_hash: u64, + scopes: &Vec<&str>, + token: Option) + -> Result<(), NullError> { match token { - Some(t) => self.tokens.insert(scope_hash, t), - None => self.tokens.remove(&scope_hash), + Some(t) => { + self.tokens.push( + JSONToken { + hash: scope_hash, + scopes: Some(scopes.iter().map(|x| x.to_string()).collect()), + token: t.clone(), + } + ); + () + }, + None => { + let matched = self.tokens.iter().find_position(|x| x.hash == scope_hash); + if let Some((idx, _)) = matched { + self.tokens.remove(idx); + } + } }; Ok(()) } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, NullError> { - match self.tokens.get(&scope_hash) { - Some(t) => Ok(Some(t.clone())), - None => Ok(None), + fn get(&self, scope_hash: u64, scopes: &Vec<&str>) -> Result, NullError> { + let scopes: Vec<_> = scopes.iter().sorted().unique().collect(); + + for t in &self.tokens { + if let Some(token_scopes) = &t.scopes { + let matched = token_scopes.iter().filter(|x| scopes.contains(&&&x[..])).count(); + if matched >= scopes.len() { + return Result::Ok(Some(t.token.clone())); + } + } else if scope_hash == t.hash { + return Result::Ok(Some(t.token.clone())); + } } + Result::Ok(None) } } /// A single stored token. -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] struct JSONToken { pub hash: u64, + pub scopes: Option>, pub token: Token, } @@ -132,14 +156,14 @@ struct JSONTokens { #[derive(Default)] pub struct DiskTokenStorage { location: String, - tokens: HashMap, + tokens: Vec, } impl DiskTokenStorage { pub fn new>(location: S) -> Result { let mut dts = DiskTokenStorage { location: location.as_ref().to_owned(), - tokens: HashMap::new(), + tokens: Vec::new(), }; // best-effort @@ -173,7 +197,7 @@ impl DiskTokenStorage { } for t in tokens.tokens { - self.tokens.insert(t.hash, t.token); + self.tokens.push(t); } return Result::Ok(()); } @@ -181,11 +205,8 @@ impl DiskTokenStorage { pub fn dump_to_file(&mut self) -> Result<(), io::Error> { let mut jsontokens = JSONTokens { tokens: Vec::new() }; - for (hash, token) in self.tokens.iter() { - jsontokens.tokens.push(JSONToken { - hash: *hash, - token: token.clone(), - }); + for token in self.tokens.iter() { + jsontokens.tokens.push((*token).clone()); } let serialized;; @@ -206,25 +227,46 @@ impl DiskTokenStorage { impl TokenStorage for DiskTokenStorage { type Error = io::Error; - fn set( - &mut self, - scope_hash: u64, - _: &Vec<&str>, - token: Option, - ) -> Result<(), Self::Error> { + fn set(&mut self, + scope_hash: u64, + scopes: &Vec<&str>, + token: Option) + -> Result<(), Self::Error> { match token { None => { - self.tokens.remove(&scope_hash); + let matched = self.tokens.iter().find_position(|x| x.hash == scope_hash); + if let Some((idx, _)) = matched { + self.tokens.remove(idx); + } () } Some(t) => { - self.tokens.insert(scope_hash, t.clone()); + self.tokens.push( + JSONToken { + hash: scope_hash, + scopes: Some(scopes.iter().map(|x| x.to_string()).collect()), + token: t.clone(), + } + ); () } } self.dump_to_file() } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, Self::Error> { - Result::Ok(self.tokens.get(&scope_hash).map(|tok| tok.clone())) + fn get(&self, scope_hash: u64, scopes: &Vec<&str>) -> Result, Self::Error> { + let scopes: Vec<_> = scopes.iter().sorted().unique().collect(); + + for t in &self.tokens { + if let Some(token_scopes) = &t.scopes { + let matched = token_scopes.iter().filter(|x| scopes.contains(&&&x[..])).count(); + // we may have some of the tokens as denormalized (many namespaces repeated) + if matched >= scopes.len() { + return Result::Ok(Some(t.token.clone())); + } + } else if scope_hash == t.hash { + return Result::Ok(Some(t.token.clone())); + } + } + Result::Ok(None) } } From 9b4a3ad3f47e72a03a7592e2b64b59f35b7b74b7 Mon Sep 17 00:00:00 2001 From: Andrey Cizov Date: Thu, 1 Aug 2019 19:56:28 +0100 Subject: [PATCH 2/2] rustfmt not passing --- src/storage.rs | 58 +++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/storage.rs b/src/storage.rs index 480cee2..4d945ad 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -95,22 +95,21 @@ impl MemoryStorage { impl TokenStorage for MemoryStorage { type Error = NullError; - fn set(&mut self, - scope_hash: u64, - scopes: &Vec<&str>, - token: Option) - -> Result<(), NullError> { + fn set( + &mut self, + scope_hash: u64, + scopes: &Vec<&str>, + token: Option, + ) -> Result<(), NullError> { match token { Some(t) => { - self.tokens.push( - JSONToken { - hash: scope_hash, - scopes: Some(scopes.iter().map(|x| x.to_string()).collect()), - token: t.clone(), - } - ); + self.tokens.push(JSONToken { + hash: scope_hash, + scopes: Some(scopes.iter().map(|x| x.to_string()).collect()), + token: t.clone(), + }); () - }, + } None => { let matched = self.tokens.iter().find_position(|x| x.hash == scope_hash); if let Some((idx, _)) = matched { @@ -126,7 +125,10 @@ impl TokenStorage for MemoryStorage { for t in &self.tokens { if let Some(token_scopes) = &t.scopes { - let matched = token_scopes.iter().filter(|x| scopes.contains(&&&x[..])).count(); + let matched = token_scopes + .iter() + .filter(|x| scopes.contains(&&&x[..])) + .count(); if matched >= scopes.len() { return Result::Ok(Some(t.token.clone())); } @@ -227,11 +229,12 @@ impl DiskTokenStorage { impl TokenStorage for DiskTokenStorage { type Error = io::Error; - fn set(&mut self, - scope_hash: u64, - scopes: &Vec<&str>, - token: Option) - -> Result<(), Self::Error> { + fn set( + &mut self, + scope_hash: u64, + scopes: &Vec<&str>, + token: Option, + ) -> Result<(), Self::Error> { match token { None => { let matched = self.tokens.iter().find_position(|x| x.hash == scope_hash); @@ -241,13 +244,11 @@ impl TokenStorage for DiskTokenStorage { () } Some(t) => { - self.tokens.push( - JSONToken { - hash: scope_hash, - scopes: Some(scopes.iter().map(|x| x.to_string()).collect()), - token: t.clone(), - } - ); + self.tokens.push(JSONToken { + hash: scope_hash, + scopes: Some(scopes.iter().map(|x| x.to_string()).collect()), + token: t.clone(), + }); () } } @@ -258,7 +259,10 @@ impl TokenStorage for DiskTokenStorage { for t in &self.tokens { if let Some(token_scopes) = &t.scopes { - let matched = token_scopes.iter().filter(|x| scopes.contains(&&&x[..])).count(); + let matched = token_scopes + .iter() + .filter(|x| scopes.contains(&&&x[..])) + .count(); // we may have some of the tokens as denormalized (many namespaces repeated) if matched >= scopes.len() { return Result::Ok(Some(t.token.clone()));