mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Add modify and entry transformers
This commit is contained in:
parent
6b4256cd98
commit
f858e6b5c4
|
@ -1,9 +1,10 @@
|
||||||
// use serde_json::{Error, Value};
|
// use serde_json::{Error, Value};
|
||||||
use super::proto_v1::Entry as ProtoEntry;
|
use super::proto_v1::Entry as ProtoEntry;
|
||||||
use error::SchemaError;
|
use error::{OperationError, SchemaError};
|
||||||
use filter::{Filter, FilterValid};
|
use filter::{Filter, FilterValid};
|
||||||
use modify::{Modify, ModifyInvalid, ModifyList, ModifyValid};
|
use modify::{Modify, ModifyInvalid, ModifyList, ModifyValid};
|
||||||
use schema::{SchemaAttribute, SchemaClass, SchemaReadTransaction};
|
use schema::{SchemaAttribute, SchemaClass, SchemaReadTransaction};
|
||||||
|
use server::{QueryServerReadTransaction, QueryServerWriteTransaction};
|
||||||
use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut};
|
use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -152,26 +153,42 @@ impl Entry<EntryInvalid, EntryNew> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Can we consume protoentry?
|
// FIXME: Can we consume protoentry?
|
||||||
pub fn from(e: &ProtoEntry) -> Self {
|
pub fn from(e: &ProtoEntry, qs: &QueryServerWriteTransaction) -> Result<Self, OperationError> {
|
||||||
// Why not the trait? In the future we may want to extend
|
// Why not the trait? In the future we may want to extend
|
||||||
// this with server aware functions for changes of the
|
// this with server aware functions for changes of the
|
||||||
// incoming data.
|
// incoming data.
|
||||||
Entry {
|
|
||||||
|
// Somehow we need to take the tree of e attrs, and convert
|
||||||
|
// all ref types to our types ...
|
||||||
|
|
||||||
|
let map2: Result<BTreeMap<String, Vec<String>>, OperationError> = e
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| {
|
||||||
|
let nv: Result<Vec<_>, _> = v.iter().map(|vr| qs.clone_value(&k, vr)).collect();
|
||||||
|
match nv {
|
||||||
|
Ok(mut nvi) => {
|
||||||
|
nvi.sort_unstable();
|
||||||
|
Ok((k.clone(), nvi))
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let x = match map2 {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Entry {
|
||||||
// For now, we do a straight move, and we sort the incoming data
|
// For now, we do a straight move, and we sort the incoming data
|
||||||
// sets so that BST works.
|
// sets so that BST works.
|
||||||
state: EntryNew,
|
state: EntryNew,
|
||||||
valid: EntryInvalid,
|
valid: EntryInvalid,
|
||||||
id: None,
|
id: None,
|
||||||
attrs: e
|
attrs: x,
|
||||||
.attrs
|
})
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| {
|
|
||||||
let mut nv = v.clone();
|
|
||||||
nv.sort_unstable();
|
|
||||||
(k.clone(), nv)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,9 +62,7 @@ impl SearchResult {
|
||||||
pub struct SearchEvent {
|
pub struct SearchEvent {
|
||||||
pub internal: bool,
|
pub internal: bool,
|
||||||
pub filter: Filter<FilterInvalid>,
|
pub filter: Filter<FilterInvalid>,
|
||||||
// TODO: Remove this
|
// TODO: Add list of attributes to request
|
||||||
class: (), // String
|
|
||||||
// TODO: Add list of attributes to request
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SearchEvent {
|
impl SearchEvent {
|
||||||
|
@ -76,7 +74,6 @@ impl SearchEvent {
|
||||||
Ok(f) => Ok(SearchEvent {
|
Ok(f) => Ok(SearchEvent {
|
||||||
internal: false,
|
internal: false,
|
||||||
filter: Filter::new_ignore_hidden(f),
|
filter: Filter::new_ignore_hidden(f),
|
||||||
class: (),
|
|
||||||
}),
|
}),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
|
@ -87,7 +84,6 @@ impl SearchEvent {
|
||||||
SearchEvent {
|
SearchEvent {
|
||||||
internal: false,
|
internal: false,
|
||||||
filter: filter,
|
filter: filter,
|
||||||
class: (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +95,6 @@ impl SearchEvent {
|
||||||
Ok(f) => Ok(SearchEvent {
|
Ok(f) => Ok(SearchEvent {
|
||||||
filter: Filter::new_recycled(f),
|
filter: Filter::new_recycled(f),
|
||||||
internal: false,
|
internal: false,
|
||||||
class: (),
|
|
||||||
}),
|
}),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
|
@ -109,7 +104,6 @@ impl SearchEvent {
|
||||||
SearchEvent {
|
SearchEvent {
|
||||||
internal: false,
|
internal: false,
|
||||||
filter: Filter::new_recycled(filter),
|
filter: Filter::new_recycled(filter),
|
||||||
class: (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +112,6 @@ impl SearchEvent {
|
||||||
SearchEvent {
|
SearchEvent {
|
||||||
internal: false,
|
internal: false,
|
||||||
filter: Filter::new_ignore_hidden(filter),
|
filter: Filter::new_ignore_hidden(filter),
|
||||||
class: (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +119,6 @@ impl SearchEvent {
|
||||||
SearchEvent {
|
SearchEvent {
|
||||||
internal: true,
|
internal: true,
|
||||||
filter: filter,
|
filter: filter,
|
||||||
class: (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,14 +138,21 @@ pub struct CreateEvent {
|
||||||
|
|
||||||
// FIXME: Should this actually be in createEvent handler?
|
// FIXME: Should this actually be in createEvent handler?
|
||||||
impl CreateEvent {
|
impl CreateEvent {
|
||||||
pub fn from_request(request: CreateRequest) -> Self {
|
pub fn from_request(
|
||||||
CreateEvent {
|
request: CreateRequest,
|
||||||
// From ProtoEntry -> Entry
|
qs: &QueryServerWriteTransaction,
|
||||||
// What is the correct consuming iterator here? Can we
|
) -> Result<Self, OperationError> {
|
||||||
// even do that?
|
let rentries: Result<Vec<_>, _> =
|
||||||
internal: false,
|
request.entries.iter().map(|e| Entry::from(e, qs)).collect();
|
||||||
// TODO: Transform references here.
|
match rentries {
|
||||||
entries: request.entries.iter().map(|e| Entry::from(e)).collect(),
|
Ok(entries) => Ok(CreateEvent {
|
||||||
|
// From ProtoEntry -> Entry
|
||||||
|
// What is the correct consuming iterator here? Can we
|
||||||
|
// even do that?
|
||||||
|
internal: false,
|
||||||
|
entries: entries,
|
||||||
|
}),
|
||||||
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +201,6 @@ impl DeleteEvent {
|
||||||
) -> Result<Self, OperationError> {
|
) -> Result<Self, OperationError> {
|
||||||
match Filter::from_rw(&request.filter, qs) {
|
match Filter::from_rw(&request.filter, qs) {
|
||||||
Ok(f) => Ok(DeleteEvent {
|
Ok(f) => Ok(DeleteEvent {
|
||||||
// TODO: Transform references here.
|
|
||||||
filter: Filter::new_ignore_hidden(f),
|
filter: Filter::new_ignore_hidden(f),
|
||||||
internal: false,
|
internal: false,
|
||||||
}),
|
}),
|
||||||
|
@ -239,13 +237,14 @@ impl ModifyEvent {
|
||||||
qs: &QueryServerWriteTransaction,
|
qs: &QueryServerWriteTransaction,
|
||||||
) -> Result<Self, OperationError> {
|
) -> Result<Self, OperationError> {
|
||||||
match Filter::from_rw(&request.filter, qs) {
|
match Filter::from_rw(&request.filter, qs) {
|
||||||
Ok(f) => Ok(ModifyEvent {
|
Ok(f) => match ModifyList::from(&request.modlist, qs) {
|
||||||
// TODO: Transform references here.
|
Ok(m) => Ok(ModifyEvent {
|
||||||
filter: Filter::new_ignore_hidden(f),
|
filter: Filter::new_ignore_hidden(f),
|
||||||
// TODO: Transform references here.
|
modlist: m,
|
||||||
modlist: ModifyList::from(&request.modlist),
|
internal: false,
|
||||||
internal: false,
|
}),
|
||||||
}),
|
Err(e) => Err(e),
|
||||||
|
},
|
||||||
|
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
|
@ -333,7 +332,6 @@ impl ReviveRecycledEvent {
|
||||||
) -> Result<Self, OperationError> {
|
) -> Result<Self, OperationError> {
|
||||||
match Filter::from_rw(&request.filter, qs) {
|
match Filter::from_rw(&request.filter, qs) {
|
||||||
Ok(f) => Ok(ReviveRecycledEvent {
|
Ok(f) => Ok(ReviveRecycledEvent {
|
||||||
// TODO: Transform references here (in theory should be none though)
|
|
||||||
filter: Filter::new_recycled(f),
|
filter: Filter::new_recycled(f),
|
||||||
internal: false,
|
internal: false,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -196,70 +196,44 @@ impl Filter<FilterInvalid> {
|
||||||
// monomorphise on the trait to call clone_value. An option is to make a fn that
|
// monomorphise on the trait to call clone_value. An option is to make a fn that
|
||||||
// takes "clone_value(t, a, v) instead, but that may have a similar issue.
|
// takes "clone_value(t, a, v) instead, but that may have a similar issue.
|
||||||
pub fn from_ro(f: &ProtoFilter, qs: &QueryServerTransaction) -> Result<Self, OperationError> {
|
pub fn from_ro(f: &ProtoFilter, qs: &QueryServerTransaction) -> Result<Self, OperationError> {
|
||||||
match f {
|
Ok(match f {
|
||||||
ProtoFilter::Eq(a, v) => match qs.clone_value(a, v) {
|
ProtoFilter::Eq(a, v) => Filter::Eq(a.clone(), qs.clone_value(a, v)?),
|
||||||
Ok(vc) => Ok(Filter::Eq(a.clone(), vc)),
|
ProtoFilter::Sub(a, v) => Filter::Sub(a.clone(), qs.clone_value(a, v)?),
|
||||||
Err(e) => Err(e),
|
ProtoFilter::Pres(a) => Filter::Pres(a.clone()),
|
||||||
},
|
ProtoFilter::Or(l) => Filter::Or(
|
||||||
ProtoFilter::Sub(a, v) => match qs.clone_value(a, v) {
|
l.iter()
|
||||||
Ok(vc) => Ok(Filter::Sub(a.clone(), vc)),
|
.map(|f| Self::from_ro(f, qs))
|
||||||
Err(e) => Err(e),
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
},
|
),
|
||||||
ProtoFilter::Pres(a) => Ok(Filter::Pres(a.clone())),
|
ProtoFilter::And(l) => Filter::And(
|
||||||
ProtoFilter::Or(l) => {
|
l.iter()
|
||||||
let inner: Result<Vec<_>, _> = l.iter().map(|f| Self::from_ro(f, qs)).collect();
|
.map(|f| Self::from_ro(f, qs))
|
||||||
match inner {
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
Ok(lc) => Ok(Filter::Or(lc)),
|
),
|
||||||
Err(e) => Err(e),
|
ProtoFilter::AndNot(l) => Filter::AndNot(Box::new(Self::from_ro(l, qs)?)),
|
||||||
}
|
})
|
||||||
}
|
|
||||||
ProtoFilter::And(l) => {
|
|
||||||
let inner: Result<Vec<_>, _> = l.iter().map(|f| Self::from_ro(f, qs)).collect();
|
|
||||||
match inner {
|
|
||||||
Ok(lc) => Ok(Filter::And(lc)),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ProtoFilter::AndNot(l) => match Self::from_ro(l, qs) {
|
|
||||||
Ok(f) => Ok(Filter::AndNot(Box::new(f))),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_rw(
|
pub fn from_rw(
|
||||||
f: &ProtoFilter,
|
f: &ProtoFilter,
|
||||||
qs: &QueryServerWriteTransaction,
|
qs: &QueryServerWriteTransaction,
|
||||||
) -> Result<Self, OperationError> {
|
) -> Result<Self, OperationError> {
|
||||||
match f {
|
Ok(match f {
|
||||||
ProtoFilter::Eq(a, v) => match qs.clone_value(a, v) {
|
ProtoFilter::Eq(a, v) => Filter::Eq(a.clone(), qs.clone_value(a, v)?),
|
||||||
Ok(vc) => Ok(Filter::Eq(a.clone(), vc)),
|
ProtoFilter::Sub(a, v) => Filter::Sub(a.clone(), qs.clone_value(a, v)?),
|
||||||
Err(e) => Err(e),
|
ProtoFilter::Pres(a) => Filter::Pres(a.clone()),
|
||||||
},
|
ProtoFilter::Or(l) => Filter::Or(
|
||||||
ProtoFilter::Sub(a, v) => match qs.clone_value(a, v) {
|
l.iter()
|
||||||
Ok(vc) => Ok(Filter::Sub(a.clone(), vc)),
|
.map(|f| Self::from_rw(f, qs))
|
||||||
Err(e) => Err(e),
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
},
|
),
|
||||||
ProtoFilter::Pres(a) => Ok(Filter::Pres(a.clone())),
|
ProtoFilter::And(l) => Filter::And(
|
||||||
ProtoFilter::Or(l) => {
|
l.iter()
|
||||||
let inner: Result<Vec<_>, _> = l.iter().map(|f| Self::from_rw(f, qs)).collect();
|
.map(|f| Self::from_rw(f, qs))
|
||||||
match inner {
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
Ok(lc) => Ok(Filter::Or(lc)),
|
),
|
||||||
Err(e) => Err(e),
|
ProtoFilter::AndNot(l) => Filter::AndNot(Box::new(Self::from_rw(l, qs)?)),
|
||||||
}
|
})
|
||||||
}
|
|
||||||
ProtoFilter::And(l) => {
|
|
||||||
let inner: Result<Vec<_>, _> = l.iter().map(|f| Self::from_rw(f, qs)).collect();
|
|
||||||
match inner {
|
|
||||||
Ok(lc) => Ok(Filter::And(lc)),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ProtoFilter::AndNot(l) => match Self::from_rw(l, qs) {
|
|
||||||
Ok(f) => Ok(Filter::AndNot(Box::new(f))),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use proto_v1::Modify as ProtoModify;
|
use proto_v1::Modify as ProtoModify;
|
||||||
use proto_v1::ModifyList as ProtoModifyList;
|
use proto_v1::ModifyList as ProtoModifyList;
|
||||||
|
|
||||||
use error::SchemaError;
|
use error::{OperationError, SchemaError};
|
||||||
use schema::{SchemaAttribute, SchemaReadTransaction};
|
use schema::{SchemaAttribute, SchemaReadTransaction};
|
||||||
|
use server::{QueryServerReadTransaction, QueryServerWriteTransaction};
|
||||||
|
|
||||||
// Should this be std?
|
// Should this be std?
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
@ -23,12 +24,12 @@ pub enum Modify {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Modify {
|
impl Modify {
|
||||||
pub fn from(m: &ProtoModify) -> Self {
|
pub fn from(m: &ProtoModify, qs: &QueryServerWriteTransaction) -> Result<Self, OperationError> {
|
||||||
match m {
|
Ok(match m {
|
||||||
ProtoModify::Present(a, v) => Modify::Present(a.clone(), v.clone()),
|
ProtoModify::Present(a, v) => Modify::Present(a.clone(), qs.clone_value(a, v)?),
|
||||||
ProtoModify::Removed(a, v) => Modify::Removed(a.clone(), v.clone()),
|
ProtoModify::Removed(a, v) => Modify::Removed(a.clone(), qs.clone_value(a, v)?),
|
||||||
ProtoModify::Purged(a) => Modify::Purged(a.clone()),
|
ProtoModify::Purged(a) => Modify::Purged(a.clone()),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,11 +71,18 @@ impl ModifyList<ModifyInvalid> {
|
||||||
self.mods.push(modify)
|
self.mods.push(modify)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from(ml: &ProtoModifyList) -> Self {
|
pub fn from(
|
||||||
|
ml: &ProtoModifyList,
|
||||||
|
qs: &QueryServerWriteTransaction,
|
||||||
|
) -> Result<Self, OperationError> {
|
||||||
// For each ProtoModify, do a from.
|
// For each ProtoModify, do a from.
|
||||||
ModifyList {
|
let inner: Result<Vec<_>, _> = ml.mods.iter().map(|pm| Modify::from(pm, qs)).collect();
|
||||||
valid: ModifyInvalid,
|
match inner {
|
||||||
mods: ml.mods.iter().map(|pm| Modify::from(pm)).collect(),
|
Ok(m) => Ok(ModifyList {
|
||||||
|
valid: ModifyInvalid,
|
||||||
|
mods: m,
|
||||||
|
}),
|
||||||
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,12 +167,18 @@ impl Handler<CreateRequest> for QueryServerV1 {
|
||||||
fn handle(&mut self, msg: CreateRequest, _: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: CreateRequest, _: &mut Self::Context) -> Self::Result {
|
||||||
let mut audit = AuditScope::new("create");
|
let mut audit = AuditScope::new("create");
|
||||||
let res = audit_segment!(&mut audit, || {
|
let res = audit_segment!(&mut audit, || {
|
||||||
let crt = CreateEvent::from_request(msg);
|
let qs_write = self.qs.write();
|
||||||
|
|
||||||
|
let crt = match CreateEvent::from_request(msg, &qs_write) {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => {
|
||||||
|
audit_log!(audit, "Failed to begin create: {:?}", e);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
audit_log!(audit, "Begin create event {:?}", crt);
|
audit_log!(audit, "Begin create event {:?}", crt);
|
||||||
|
|
||||||
let qs_write = self.qs.write();
|
|
||||||
|
|
||||||
qs_write
|
qs_write
|
||||||
.create(&mut audit, &crt)
|
.create(&mut audit, &crt)
|
||||||
.and_then(|_| qs_write.commit(&mut audit).map(|_| OperationResponse {}))
|
.and_then(|_| qs_write.commit(&mut audit).map(|_| OperationResponse {}))
|
||||||
|
|
Loading…
Reference in a new issue