structured_xades/material/credentials/
scope.rs1use super::{Error, Missing};
4use crate::Xades;
5use crate::binary::Location;
6use crate::material::{Archived, Index};
7use crate::xml::{Access, Xml};
8use structured_asn1::memory::{HashWork, Memory, Work};
9use structured_ltv::material::{ArchiveError, ArtifactRef, Coverage};
10use structured_ltv::timestamp::{Purpose, TimestampRequirements, TimestampScope, Verified};
11
12pub struct Scope<'a, N: HashWork, D, G, C: Work = Memory> {
16 archive: Option<Archive<'a, N, D, G, C>>,
17}
18
19type Archive<'a, N, D, G, C> = (
20 &'a Coverage<N, D, G, C, Xades>,
21 &'a Verified<N, D, G, Xades>,
22);
23
24impl<N: HashWork, D, G> Scope<'_, N, D, G> {
25 #[must_use]
27 pub fn whole() -> Self {
28 Self { archive: None }
29 }
30}
31
32impl<'a, N: HashWork, D, G, C: Work> Scope<'a, N, D, G, C> {
33 #[must_use]
35 pub fn before_archive(
36 coverage: &'a Coverage<N, D, G, C, Xades>,
37 evidence: &'a Verified<N, D, G, Xades>,
38 ) -> Self {
39 Self {
40 archive: Some((coverage, evidence)),
41 }
42 }
43}
44
45impl<N: Copy + Eq + HashWork, D: Copy + Eq, G: Copy + Eq, C: Work> Scope<'_, N, D, G, C> {
46 pub(super) fn require<X: Xml<Id = N, Document = D, Generation = G>, W: Work, Q: Work, PE>(
47 &self,
48 required: &TimestampRequirements<N, D, G, Xades>,
49 index: &Index<'_, N, D, G, W>,
50 access: &Access<'_, X, Q>,
51 ) -> Result<(), Error<X::Error, PE, N>> {
52 let location = required.scope().location();
53 let node = location.node;
54 if location.snapshot != access.snapshot() {
55 return Err(Error::Foreign { node });
56 }
57 index
58 .require_signature(required.signature(), access)
59 .map_err(Error::Index)?;
60 match (required.scope(), self.archive) {
61 (TimestampScope::All(_), None) => Ok(()),
62 (TimestampScope::BeforeArchive(_), Some((coverage, evidence))) => {
63 if evidence.purpose() != Purpose::Archive
64 || evidence.token().snapshot != location.snapshot
65 || !access
66 .equal_id(evidence.signature(), required.signature())
67 .map_err(|cause| Error::Resource { node, cause })?
68 || !access
69 .equal_id(evidence.property(), node)
70 .map_err(|cause| Error::Resource { node, cause })?
71 {
72 return Err(Error::Foreign { node });
73 }
74 coverage
75 .require_evidence(evidence, node, access)
76 .map_err(|cause| Error::Archive(ArchiveError::Coverage(cause)))
77 }
78 _ => Err(Error::Foreign { node }),
79 }
80 }
81
82 pub(super) fn known<X: Xml<Id = N, Document = D, Generation = G>, W: Work, Q: Work, PE>(
83 &self,
84 need: ArtifactRef<'_, '_>,
85 index: &Index<'_, N, D, G, W>,
86 access: &Access<'_, X, Q>,
87 ) -> Result<Option<Missing>, Error<X::Error, PE, N>> {
88 if let Some((coverage, evidence)) = self.archive {
89 return index
90 .archived(need, coverage, evidence, access)
91 .map(|value| match value {
92 Archived::Present(_) => None,
93 Archived::Missing => Some(Missing::Absent),
94 Archived::Uncovered => Some(Missing::Uncovered),
95 })
96 .map_err(Error::Archive);
97 }
98 let mut copies = index.artifact(need, access).map_err(Error::Index)?;
99 copies
100 .next()
101 .transpose()
102 .map(|value| {
103 if value.is_some() {
104 None
105 } else {
106 Some(Missing::Absent)
107 }
108 })
109 .map_err(Error::Index)
110 }
111
112 pub(super) fn open<X: Xml<Id = N, Document = D, Generation = G>, Q: Work, PE>(
113 &self,
114 location: Location<N, D, G>,
115 access: &Access<'_, X, Q>,
116 ) -> Result<Option<Missing>, Error<X::Error, PE, N>> {
117 if let Some((coverage, evidence)) = self.archive {
118 return coverage
119 .covers(evidence, location.node, access)
120 .map(|covered| {
121 if covered {
122 None
123 } else {
124 Some(Missing::Uncovered)
125 }
126 })
127 .map_err(|cause| Error::Archive(ArchiveError::Coverage(cause)));
128 }
129 Ok(None)
130 }
131}