fix: set and unset acting usr based on actor
This commit is contained in:
parent
dc27262328
commit
7e89edc30f
@ -161,7 +161,9 @@ fn handle_request<A>(app: &A, req: Addrd<Req<ToadT>>) -> Addrd<Message>
|
||||
let actor = dbg!(actor);
|
||||
|
||||
let not_found = || {
|
||||
log::info!("{:?} {} not found", req.data().msg().code, req.data().msg().path_string().unwrap());
|
||||
log::info!("{:?} {} not found",
|
||||
req.data().msg().code,
|
||||
req.data().msg().path_string().unwrap());
|
||||
Message::builder(Type::Ack, toad::resp::code::NOT_FOUND).token(req.data().msg().token)
|
||||
.build()
|
||||
};
|
||||
|
@ -99,20 +99,20 @@ impl<Db> GroupRepo<DbError<Db>> for GroupRepoImpl<Db> where Db: Postgres + 'stat
|
||||
static QUERY: &'static str = "select g.tag :: text, g.uid :: text from public.usr_groups(($1 :: text) :: human_uuid.huid) as g";
|
||||
|
||||
let grps = self.0
|
||||
.with_client(|c| c.query(QUERY, &[&id.as_ref()]))
|
||||
.and_then(|rows| {
|
||||
rows.iter()
|
||||
.map(Group::unmarshal)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.map_err(GroupRepoError::Other)?;
|
||||
.with_client(actor, |c| c.query(QUERY, &[&id.as_ref()]))
|
||||
.and_then(|rows| {
|
||||
rows.iter()
|
||||
.map(Group::unmarshal)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.map_err(GroupRepoError::Other)?;
|
||||
|
||||
let paths = grps.iter().map(|g| Path::parse(format!("/groups/{}/members", g.uid))).collect::<Vec<_>>();
|
||||
let paths = grps.iter()
|
||||
.map(|g| Path::parse(format!("/groups/{}/members", g.uid)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !self.0
|
||||
.authorized_all(&paths,
|
||||
Mode::Read,
|
||||
actor)
|
||||
.authorized_all(&paths, Mode::Read, actor)
|
||||
.map_err(GroupRepoError::Other)?
|
||||
{
|
||||
return Err(GroupRepoError::Unauthorized);
|
||||
@ -134,7 +134,7 @@ impl<Db> GroupRepo<DbError<Db>> for GroupRepoImpl<Db> where Db: Postgres + 'stat
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| c.query(QUERY, &[&id.as_ref()]))
|
||||
.with_client(actor, |c| c.query(QUERY, &[&id.as_ref()]))
|
||||
.and_then(|rows| {
|
||||
rows.into_iter()
|
||||
.map(|row| row.try_get::<_, String>("u.uid").map(UserId::from))
|
||||
@ -167,7 +167,7 @@ impl<Db> ReadOne for GroupRepoImpl<Db> where Db: Postgres + 'static
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| c.query_opt(QUERY, &[&id.as_ref()]))
|
||||
.with_client(actor, |c| c.query_opt(QUERY, &[&id.as_ref()]))
|
||||
.and_then(|opt| {
|
||||
opt.as_ref()
|
||||
.map(Group::unmarshal)
|
||||
@ -204,7 +204,7 @@ impl<Db> ReadMany for GroupRepoImpl<Db> where Db: Postgres + 'static
|
||||
|
||||
let grps: Vec<Group> =
|
||||
self.0
|
||||
.with_client(|c| match page.after {
|
||||
.with_client(actor, |c| match page.after {
|
||||
| Some(after) => {
|
||||
c.query(&QUERY_AFTER_LINES.iter()
|
||||
.fold(String::new(), |b, a| format!("{b}{a}\n")),
|
||||
@ -252,9 +252,9 @@ impl<Db> Patch for GroupRepoImpl<Db> where Db: Postgres + 'static
|
||||
|
||||
let paths =
|
||||
vec![Some(format!("/groups/{id}/name")).filter(|_| state.name.is_some())].into_iter()
|
||||
.filter_map(identity)
|
||||
.map(Path::parse)
|
||||
.collect::<Vec<_>>();
|
||||
.filter_map(identity)
|
||||
.map(Path::parse)
|
||||
.collect::<Vec<_>>();
|
||||
if !self.0
|
||||
.authorized_all(&paths, Mode::Write, actor)
|
||||
.map_err(GroupRepoError::Other)?
|
||||
@ -263,7 +263,7 @@ impl<Db> Patch for GroupRepoImpl<Db> where Db: Postgres + 'static
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| {
|
||||
.with_client(actor, |c| {
|
||||
c.execute(&QUERY_LINES.iter()
|
||||
.fold(String::new(), |b, a| format!("{b}{a}\n")),
|
||||
&[&id.as_ref(), &state.name.as_ref().map(|n| n.as_ref())])
|
||||
@ -292,7 +292,7 @@ impl<Db> Insert for GroupRepoImpl<Db> where Db: Postgres + 'static
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| {
|
||||
.with_client(actor, |c| {
|
||||
c.query_one(&QUERY_LINES.iter()
|
||||
.fold(String::new(), |b, a| format!("{b}{a}\n")),
|
||||
&[&insert.name.as_ref()])
|
||||
@ -318,7 +318,7 @@ impl<Db> Del for GroupRepoImpl<Db> where Db: Postgres + 'static
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| c.execute(QUERY, &[&id.as_ref()]))
|
||||
.with_client(actor, |c| c.execute(QUERY, &[&id.as_ref()]))
|
||||
.map(|n| n == 1)
|
||||
.map_err(GroupRepoError::Other)
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use postgres::{GenericClient, GenericRow};
|
||||
|
||||
use super::Actor;
|
||||
use crate::newtype;
|
||||
use crate::postgres::{DbError, Postgres};
|
||||
use crate::repo::Ext;
|
||||
@ -10,7 +11,11 @@ newtype!(
|
||||
);
|
||||
|
||||
pub trait HashedTextExt: Ext {
|
||||
fn matches<S: AsRef<str>>(&self, this: &HashedText, other: S) -> Result<bool, Self::Error>;
|
||||
fn matches<S: AsRef<str>>(&self,
|
||||
actor: &Actor,
|
||||
this: &HashedText,
|
||||
other: S)
|
||||
-> Result<bool, Self::Error>;
|
||||
}
|
||||
|
||||
pub struct HashedTextExtImpl<Db: Postgres>(pub &'static Db);
|
||||
@ -22,11 +27,17 @@ impl<Db> Ext for HashedTextExtImpl<Db> where Db: Postgres
|
||||
|
||||
impl<Db> HashedTextExt for HashedTextExtImpl<Db> where Db: Postgres
|
||||
{
|
||||
fn matches<S: AsRef<str>>(&self, this: &HashedText, other: S) -> Result<bool, DbError<Db>> {
|
||||
fn matches<S: AsRef<str>>(&self,
|
||||
actor: &Actor,
|
||||
this: &HashedText,
|
||||
other: S)
|
||||
-> Result<bool, DbError<Db>> {
|
||||
static QUERY: &str = "select public.hashed_text_matches($1, public.hashed_text_of_string($2))";
|
||||
|
||||
self.0
|
||||
.with_client(|client| client.query_one(QUERY, &[&other.as_ref(), &this.0.as_str()]))
|
||||
.with_client(actor, |client| {
|
||||
client.query_one(QUERY, &[&other.as_ref(), &this.0.as_str()])
|
||||
})
|
||||
.and_then(|row| row.try_get(0))
|
||||
}
|
||||
}
|
||||
@ -36,13 +47,18 @@ mod test {
|
||||
use postgres::types::Type;
|
||||
|
||||
use super::{HashedText, HashedTextExt, HashedTextExtImpl};
|
||||
use crate::model::Actor;
|
||||
use crate::postgres::test::{from_sql_owned, Client, Row};
|
||||
use crate::postgres::{Postgres, PostgresImpl};
|
||||
|
||||
#[test]
|
||||
fn hashed_text_matches_fn_call() {
|
||||
let client = || Client { query_one: Box::new(|_, q, ps| {
|
||||
assert_eq!(q.unwrap_str(), "select public.hashed_text_matches($1, public.hashed_text_of_string($2))");
|
||||
let q = q.unwrap_str();
|
||||
if q.contains("set_acting_usr") {
|
||||
return Ok(Row::new(vec![]));
|
||||
}
|
||||
assert_eq!(q, "select public.hashed_text_matches($1, public.hashed_text_of_string($2))");
|
||||
assert_eq!(from_sql_owned::<String>(ps[1]), String::from("XXX"));
|
||||
|
||||
Ok(Row::new(vec![("",
|
||||
@ -57,9 +73,9 @@ mod test {
|
||||
std::mem::transmute::<_, &'static PostgresImpl<Client<()>>>(&pg)
|
||||
});
|
||||
|
||||
assert!(htext.matches(&HashedText(String::from("XXX")), "foo")
|
||||
assert!(htext.matches(&Actor::default(), &HashedText(String::from("XXX")), "foo")
|
||||
.unwrap());
|
||||
assert!(!htext.matches(&HashedText(String::from("XXX")), "foob")
|
||||
assert!(!htext.matches(&Actor::default(), &HashedText(String::from("XXX")), "foob")
|
||||
.unwrap());
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ impl<Db> ReadOne for UserRepoImpl<Db> where Db: Postgres + 'static
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| {
|
||||
.with_client(actor, |c| {
|
||||
c.query_opt(&QUERY_LINES.iter()
|
||||
.fold(String::new(), |b, a| format!("{b}{a}\n")),
|
||||
&[&id.as_ref()])
|
||||
@ -177,7 +177,7 @@ impl<Db> ReadMany for UserRepoImpl<Db> where Db: Postgres + 'static
|
||||
|
||||
let usrs: Vec<User> =
|
||||
self.0
|
||||
.with_client(|c| match page.after {
|
||||
.with_client(actor, |c| match page.after {
|
||||
| Some(after) => {
|
||||
c.query(&QUERY_AFTER_LINES.iter()
|
||||
.fold(String::new(), |b, a| format!("{b}{a}\n")),
|
||||
@ -238,7 +238,7 @@ impl<Db> Patch for UserRepoImpl<Db> where Db: Postgres + 'static
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| {
|
||||
.with_client(actor, |c| {
|
||||
c.execute(&QUERY_LINES.iter()
|
||||
.fold(String::new(), |b, a| format!("{b}{a}\n")),
|
||||
&[&id.as_ref(),
|
||||
@ -272,7 +272,7 @@ impl<Db> Insert for UserRepoImpl<Db> where Db: Postgres + 'static
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| {
|
||||
.with_client(actor, |c| {
|
||||
c.query_one(&QUERY_LINES.iter()
|
||||
.fold(String::new(), |b, a| format!("{b}{a}\n")),
|
||||
&[&insert.tag,
|
||||
@ -302,7 +302,7 @@ impl<Db> Del for UserRepoImpl<Db> where Db: Postgres + 'static
|
||||
}
|
||||
|
||||
self.0
|
||||
.with_client(|c| c.execute(QUERY, &[&id.as_ref()]))
|
||||
.with_client(actor, |c| c.execute(QUERY, &[&id.as_ref()]))
|
||||
.map(|n| n == 1)
|
||||
.map_err(Other)
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ impl<Db, G> UserSessionExt for UserSessionExtImpl<Db, G>
|
||||
let expr = "public.usr_session_touch(public.usr_session_key_of_string($1))";
|
||||
let query = format!("select {cols} from {expr} as u");
|
||||
self.0
|
||||
.with_client(|c| {
|
||||
.with_client(&Actor::default(), |c| {
|
||||
c.query_one(&query, &[&session.as_ref()])
|
||||
.and_then(|r| User::unmarshal(&r))
|
||||
})
|
||||
@ -118,7 +118,7 @@ impl<Db, G> UserSessionExt for UserSessionExtImpl<Db, G>
|
||||
" ) s"];
|
||||
|
||||
self.0
|
||||
.with_client(|c| {
|
||||
.with_client(&Actor::default(), |c| {
|
||||
c.query_one(&QUERY_LINES.iter()
|
||||
.fold(String::new(), |b, a| format!("{b}{a}\n")),
|
||||
&[&tag_or_email.as_str(),
|
||||
|
@ -6,7 +6,7 @@ use postgres::types::FromSql;
|
||||
use postgres::{GenericClient, GenericRow};
|
||||
use rand::Rng;
|
||||
|
||||
use crate::model::{Actor, Mode, Path, Perm};
|
||||
use crate::model::{Actor, Mode, Path, Perm, UserId};
|
||||
|
||||
pub type DbError<Pg> = <<Pg as Postgres>::Client as postgres::GenericClient>::Error;
|
||||
|
||||
@ -76,7 +76,7 @@ pub trait Postgres
|
||||
fn try_new<F>(connect: F, pool_size: usize) -> Result<Self, DbError<Self>>
|
||||
where F: Fn() -> Result<Self::Client, DbError<Self>>;
|
||||
|
||||
fn with_client<F, R>(&self, f: F) -> Result<R, DbError<Self>>
|
||||
fn with_client<F, R>(&self, a: &Actor, f: F) -> Result<R, DbError<Self>>
|
||||
where F: FnOnce(&mut Self::Client) -> Result<R, DbError<Self>>;
|
||||
|
||||
fn authorized(&self, path: &Path, wants_to: Mode, actor: &Actor) -> Result<bool, DbError<Self>> {
|
||||
@ -91,7 +91,7 @@ pub trait Postgres
|
||||
"inner join public.usr ou on ou.id = p.owner_user",
|
||||
"where path = $1 :: text",].into_iter()
|
||||
.fold(String::new(), |b, a| format!("{b}\n{a}"));
|
||||
let got_perm = self.with_client(|c| c.query_opt(&q, &[&path.to_string()]))?;
|
||||
let got_perm = self.with_client(actor, |c| c.query_opt(&q, &[&path.to_string()]))?;
|
||||
Ok(match got_perm {
|
||||
| None => {
|
||||
log::debug!("no such perm: {}", path);
|
||||
@ -133,9 +133,11 @@ pub trait Postgres
|
||||
"inner join public.grp og on og.id = p.owner_group",
|
||||
"inner join public.usr ou on ou.id = p.owner_user",
|
||||
format!("where path in ({set})").as_str(),].into_iter()
|
||||
.fold(String::new(), |b, a| format!("{b}\n{a}"));
|
||||
.fold(String::new(), |b, a| {
|
||||
format!("{b}\n{a}")
|
||||
});
|
||||
|
||||
let pass = self.with_client(|c| c.query(&q, &[]))?
|
||||
let pass = self.with_client(actor, |c| c.query(&q, &[]))?
|
||||
.iter()
|
||||
.map(Perm::unmarshal)
|
||||
.collect::<Result<Vec<Perm>, _>>()?
|
||||
@ -189,13 +191,22 @@ impl<C> Postgres for PostgresImpl<C>
|
||||
pool: Box::pin(pool) })
|
||||
}
|
||||
|
||||
fn with_client<F, R>(&self, f: F) -> Result<R, C::Error>
|
||||
fn with_client<F, R>(&self, a: &Actor, f: F) -> Result<R, C::Error>
|
||||
where F: FnOnce(&mut Self::Client) -> Result<R, C::Error>
|
||||
{
|
||||
match self.unused_lock() {
|
||||
| Some(mut lock) => f(lock.deref_mut()),
|
||||
| None => f(self.block_for_next().deref_mut()),
|
||||
}
|
||||
let mut c = match self.unused_lock() {
|
||||
| Some(lock) => lock,
|
||||
| None => self.block_for_next(),
|
||||
};
|
||||
|
||||
c.query_one("select public.set_acting_usr($1)",
|
||||
&[&a.uid.as_ref().map(UserId::as_ref)])?;
|
||||
|
||||
let r = f(c.deref_mut())?;
|
||||
|
||||
c.query_one("select public.unset_acting_usr()", &[])?;
|
||||
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,7 +375,7 @@ pub mod test {
|
||||
perms: vec![] })
|
||||
}
|
||||
|
||||
fn with_client<F, R>(&self, f: F) -> Result<R, super::DbError<Self>>
|
||||
fn with_client<F, R>(&self, a: &Actor, f: F) -> Result<R, super::DbError<Self>>
|
||||
where F: FnOnce(&mut Self::Client) -> Result<R, super::DbError<Self>>
|
||||
{
|
||||
f(self.client.lock().unwrap().deref_mut())
|
||||
@ -598,7 +609,8 @@ pub mod test {
|
||||
assert!(pg.unused_lock().is_some());
|
||||
|
||||
// with_client does not block when there are available clients
|
||||
let row = pg.with_client(|c| c.query_one("", &[])).unwrap();
|
||||
let row = pg.with_client(&Actor::default(), |c| c.query_one("", &[]))
|
||||
.unwrap();
|
||||
assert_eq!(row.get::<_, String>("foo"), String::from("bar"));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user