mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Most changes for state validated modlist done, just need to write the validate!
This commit is contained in:
parent
108a097bd0
commit
658e409d90
|
@ -2,7 +2,7 @@
|
|||
use super::proto_v1::Entry as ProtoEntry;
|
||||
use error::SchemaError;
|
||||
use filter::{Filter, FilterValid};
|
||||
use modify::{Modify, ModifyList};
|
||||
use modify::{Modify, ModifyList, ModifyValid, ModifyInvalid};
|
||||
use schema::{SchemaAttribute, SchemaClass, SchemaReadTransaction};
|
||||
use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut};
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -503,7 +503,7 @@ impl<STATE> Entry<EntryValid, STATE> {
|
|||
pub fn gen_modlist_assert(
|
||||
&self,
|
||||
schema: &SchemaReadTransaction,
|
||||
) -> Result<ModifyList, SchemaError> {
|
||||
) -> Result<ModifyList<ModifyInvalid>, SchemaError> {
|
||||
// Create a modlist from this entry. We make this assuming we want the entry
|
||||
// to have this one as a subset of values. This means if we have single
|
||||
// values, we'll replace, if they are multivalue, we present them.
|
||||
|
@ -645,7 +645,7 @@ where
|
|||
}
|
||||
|
||||
// Should this be schemaless, relying on checks of the modlist, and the entry validate after?
|
||||
pub fn apply_modlist(&self, modlist: &ModifyList) -> Result<Entry<EntryInvalid, STATE>, ()> {
|
||||
pub fn apply_modlist(&self, modlist: &ModifyList<ModifyValid>) -> Result<Entry<EntryInvalid, STATE>, ()> {
|
||||
// Apply a modlist, generating a new entry that conforms to the changes.
|
||||
// This is effectively clone-and-transform
|
||||
|
||||
|
@ -658,7 +658,7 @@ where
|
|||
};
|
||||
|
||||
// mutate
|
||||
for modify in modlist.mods.iter() {
|
||||
for modify in modlist {
|
||||
match modify {
|
||||
Modify::Present(a, v) => ne.add_ava(a.clone(), v.clone()),
|
||||
Modify::Removed(a, v) => ne.remove_ava(a, v),
|
||||
|
@ -770,10 +770,12 @@ mod tests {
|
|||
let mut e: Entry<EntryInvalid, EntryNew> = Entry::new();
|
||||
e.add_ava(String::from("userid"), String::from("william"));
|
||||
|
||||
let mods = ModifyList::new_list(vec![Modify::Present(
|
||||
String::from("attr"),
|
||||
String::from("value"),
|
||||
)]);
|
||||
let mods = unsafe {
|
||||
ModifyList::new_valid_list(vec![Modify::Present(
|
||||
String::from("attr"),
|
||||
String::from("value"),
|
||||
)])
|
||||
};
|
||||
|
||||
let ne = e.apply_modlist(&mods).unwrap();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use super::proto_v1::{
|
|||
};
|
||||
use entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntryValid};
|
||||
// use error::OperationError;
|
||||
use modify::ModifyList;
|
||||
use modify::{ModifyList, ModifyInvalid};
|
||||
|
||||
use actix::prelude::*;
|
||||
|
||||
|
@ -189,7 +189,7 @@ impl DeleteEvent {
|
|||
#[derive(Debug)]
|
||||
pub struct ModifyEvent {
|
||||
pub filter: Filter<FilterInvalid>,
|
||||
pub modlist: ModifyList,
|
||||
pub modlist: ModifyList<ModifyInvalid>,
|
||||
pub internal: bool,
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ impl ModifyEvent {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn from_filter(filter: Filter<FilterInvalid>, modlist: ModifyList) -> Self {
|
||||
pub fn from_filter(filter: Filter<FilterInvalid>, modlist: ModifyList<ModifyInvalid>) -> Self {
|
||||
ModifyEvent {
|
||||
filter: filter,
|
||||
modlist: modlist,
|
||||
|
@ -211,7 +211,7 @@ impl ModifyEvent {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_internal(filter: Filter<FilterInvalid>, modlist: ModifyList) -> Self {
|
||||
pub fn new_internal(filter: Filter<FilterInvalid>, modlist: ModifyList<ModifyInvalid>) -> Self {
|
||||
ModifyEvent {
|
||||
filter: filter,
|
||||
modlist: modlist,
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
use proto_v1::Modify as ProtoModify;
|
||||
use proto_v1::ModifyList as ProtoModifyList;
|
||||
|
||||
use error::SchemaError;
|
||||
use schema::{SchemaAttribute, SchemaReadTransaction};
|
||||
|
||||
// Should this be std?
|
||||
use std::slice;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ModifyValid;
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ModifyInvalid;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub enum Modify {
|
||||
// This value *should* exist.
|
||||
|
@ -22,36 +33,79 @@ impl Modify {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ModifyList {
|
||||
// And ordered list of changes to apply. Should this be state based?
|
||||
pub mods: Vec<Modify>,
|
||||
pub struct ModifyList<VALID> {
|
||||
valid: VALID,
|
||||
// The order of this list matters. Each change must be done in order.
|
||||
mods: Vec<Modify>,
|
||||
}
|
||||
|
||||
// TODO: ModifyList should be like filter and have valid/invalid to schema.
|
||||
// Or do we not care because the entry will be invalid at the end?
|
||||
|
||||
impl ModifyList {
|
||||
impl<'a> IntoIterator for &'a ModifyList<ModifyValid> {
|
||||
type Item = &'a Modify;
|
||||
type IntoIter = slice::Iter<'a, Modify>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.mods.iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl ModifyList<ModifyInvalid> {
|
||||
pub fn new() -> Self {
|
||||
ModifyList { mods: Vec::new() }
|
||||
ModifyList {
|
||||
valid: ModifyInvalid,
|
||||
mods: Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_list(mods: Vec<Modify>) -> Self {
|
||||
ModifyList { mods: mods }
|
||||
ModifyList {
|
||||
valid: ModifyInvalid,
|
||||
mods: mods
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_mod(&mut self, modify: Modify) {
|
||||
self.mods.push(modify)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.mods.len()
|
||||
}
|
||||
|
||||
pub fn from(ml: &ProtoModifyList) -> Self {
|
||||
// For each ProtoModify, do a from.
|
||||
|
||||
ModifyList {
|
||||
valid: ModifyInvalid,
|
||||
mods: ml.mods.iter().map(|pm| Modify::from(pm)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate(&self,
|
||||
schema: &SchemaReadTransaction,
|
||||
) -> Result<ModifyList<ModifyValid>, SchemaError> {
|
||||
// Check that all attributes exist in the schema
|
||||
|
||||
// Normalise them
|
||||
|
||||
// Validate them
|
||||
|
||||
// Return new ModifyList!
|
||||
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl ModifyList<ModifyValid> {
|
||||
#[cfg(test)]
|
||||
pub unsafe fn new_valid_list(mods: Vec<Modify>) -> Self {
|
||||
ModifyList {
|
||||
valid: ModifyValid,
|
||||
mods: mods
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<VALID> ModifyList<VALID> {
|
||||
pub fn len(&self) -> usize {
|
||||
self.mods.len()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntryValid};
|
|||
use error::{OperationError, SchemaError};
|
||||
use event::{CreateEvent, DeleteEvent, ExistsEvent, ModifyEvent, ReviveRecycledEvent, SearchEvent};
|
||||
use filter::{Filter, FilterInvalid};
|
||||
use modify::{Modify, ModifyList};
|
||||
use modify::{Modify, ModifyList, ModifyInvalid};
|
||||
use plugins::Plugins;
|
||||
use schema::{Schema, SchemaReadTransaction, SchemaTransaction, SchemaWriteTransaction};
|
||||
|
||||
|
@ -448,11 +448,16 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
return Err(OperationError::NoMatchingEntries);
|
||||
};
|
||||
|
||||
let modlist = ModifyList::new_list(vec![Modify::Present(
|
||||
let modlist_inv = ModifyList::new_list(vec![Modify::Present(
|
||||
String::from("class"),
|
||||
String::from("recycled"),
|
||||
)]);
|
||||
|
||||
let modlist = match modlist_inv.validate(&self.schema) {
|
||||
Ok(ml) => ml,
|
||||
Err(e) => return Err(OperationError::SchemaViolation(e)),
|
||||
};
|
||||
|
||||
let candidates: Vec<Entry<EntryInvalid, EntryCommitted>> = pre_candidates
|
||||
.into_iter()
|
||||
.map(|er| {
|
||||
|
@ -647,6 +652,12 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
return Err(OperationError::EmptyRequest);
|
||||
}
|
||||
|
||||
// Is the modlist valid?
|
||||
let modlist = match me.modlist.validate(&self.schema) {
|
||||
Ok(ml) => ml,
|
||||
Err(e) => return Err(OperationError::SchemaViolation(e)),
|
||||
};
|
||||
|
||||
// Is the filter invalid to schema?
|
||||
|
||||
// WARNING! Check access controls here!!!!
|
||||
|
@ -675,7 +686,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
.into_iter()
|
||||
.map(|er| {
|
||||
// TODO: Deal with this properly william
|
||||
er.invalidate().apply_modlist(&me.modlist).unwrap()
|
||||
er.invalidate().apply_modlist(&modlist).unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -786,7 +797,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
&self,
|
||||
audit: &mut AuditScope,
|
||||
filter: Filter<FilterInvalid>,
|
||||
modlist: ModifyList,
|
||||
modlist: ModifyList<ModifyInvalid>,
|
||||
) -> Result<(), OperationError> {
|
||||
let mut audit_int = AuditScope::new("internal_modify");
|
||||
let me = ModifyEvent::new_internal(filter, modlist);
|
||||
|
@ -799,7 +810,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
&self,
|
||||
audit: &mut AuditScope,
|
||||
filter: Filter<FilterInvalid>,
|
||||
modlist: ModifyList,
|
||||
modlist: ModifyList<ModifyInvalid>,
|
||||
) -> Result<(), OperationError> {
|
||||
let mut audit_int = AuditScope::new("impersonate_modify");
|
||||
let me = ModifyEvent::new_internal(filter, modlist);
|
||||
|
|
Loading…
Reference in a new issue