Safe Haskell | Trustworthy |
---|
This module exports the basic types used to create queries and
selections. Different from standard MongoDB, Hails queries are limited
to SearchableField
s (similarly, ordering a query result is limited
to such fields) and projections are carried out by this library and
not the database. The later is a result of allowing policy modules to
express a labeling policy as a function of a document -- hence we
cannot determine at compile time if a field is used in a policy and
thus must be included in the projection.
- class InsertLike doc where
- insert :: CollectionName -> doc -> DBAction ObjectId
- insert_ :: CollectionName -> doc -> DBAction ()
- insertP :: DCPriv -> CollectionName -> doc -> DBAction ObjectId
- insertP_ :: DCPriv -> CollectionName -> doc -> DBAction ()
- save :: CollectionName -> doc -> DBAction ()
- saveP :: DCPriv -> CollectionName -> doc -> DBAction ()
- class Select selectionOrQuery where
- select :: Selector -> CollectionName -> selectionOrQuery
- data Selection = Selection {}
- type Selector = BsonDocument
- data Query = Query {}
- data QueryOption
- type Limit = Word32
- type BatchSize = Word32
- data Order
- orderName :: Order -> FieldName
- data Cursor
- curLabel :: Cursor -> DCLabel
- find :: Query -> DBAction Cursor
- findP :: DCPriv -> Query -> DBAction Cursor
- next :: Cursor -> DBAction (Maybe LabeledHsonDocument)
- nextP :: DCPriv -> Cursor -> DBAction (Maybe LabeledHsonDocument)
- findOne :: Query -> DBAction (Maybe LabeledHsonDocument)
- findOneP :: DCPriv -> Query -> DBAction (Maybe LabeledHsonDocument)
- data DBError
- applyCollectionPolicyP :: MonadDC m => DCPriv -> Collection -> HsonDocument -> m LabeledHsonDocument
- data PolicyError
- typeCheckDocument :: Map FieldName FieldPolicy -> HsonDocument -> DC ()
Write
class InsertLike doc whereSource
Class used to generalize insertion and saving of documents.
Specifically, it permits reusing function names when inserting/saving
both already-labeled and unlabeled documents.
Minimal definition: insertP
and saveP
.
insert :: CollectionName -> doc -> DBAction ObjectIdSource
Insert document into collection and return its _id
value. When
performing an insert
it is required that the computation be able
to write to both the database and collection. To this end, insert
internally applies guardWrite
on the database label and collection
label. Of course, the computation must be able to name the
collection in the database, and thus must be able to read the
database collection map as verified by applying taint
to the
collections label.
When inserting an unlabeled document, all policies must be
succesfully applied using applyCollectionPolicyP
and the document
must be "well-typed" (see applyCollectionPolicyP
).
When inserting an already-labeled document, the labels on fields and the document itself are compared against the policy-generated labels. Note that this approach allows an untrusted piece of code to insert a document it could not label according to the policy module.
insert_ :: CollectionName -> doc -> DBAction ()Source
Same as insert
except it does not return _id
insertP :: DCPriv -> CollectionName -> doc -> DBAction ObjectIdSource
Same as insert
, but uses privileges when applying the
policies and performing label comparisons.
insertP_ :: DCPriv -> CollectionName -> doc -> DBAction ()Source
Same as insertP
except it does not return the _id
.
save :: CollectionName -> doc -> DBAction ()Source
Update a document according to its _id
value. The IFC requirements
subsume those of insert
. Specifically, in addition to being able
to apply all the policies and requiring that the current label flow
to the label of the collection and database, save
requires that
the current label flow to the label of the existing database
record (i.e, the existing document can be overwritten).
saveP :: DCPriv -> CollectionName -> doc -> DBAction ()Source
Same as save
, but uses privileges when applying the
policies and performing label comparisons.
Note that a find is performed if the provided document contains
an _id
field. This lookup does _not_ leak timing information
since the _id
field is always searchable and thus solely
protected by the collection label (which the computation is
tainted by).
Read
Selection
class Select selectionOrQuery whereSource
Class used to simplicy the creation of a 'Selection'/'Query'.
Specifically, select
can be used to create a Section
in a
straight foward manner, but similarly can be used to create a
Query
with a set of default options.
select :: Selector -> CollectionName -> selectionOrQuerySource
A Section
is a Selector
query on a Collection
. In other
words, a Selection
is the necessary information for performing a
database query.
Selection | |
|
type Selector = BsonDocumentSource
Filter for a query, analogous to the WHERE
clause in
SQL. []
matches all documents in collection. For example,
[x
is analogous to
-:
a, y -:
b]WHERE x = a AND y = b
in SQL.
Note: only FieldName
s of SearchableField
s may be used in
selections, and thus all other fields are ignored.
Query
Use select to create a basic query with defaults, then modify if
desired. Example: (select sel col) {limit =: 10}
. For simplicity,
and since policies may be specified in terms of arbitrary fields,
The selection
and sort
fields are restricted to SearchableField
s,
or the _id
field that is implicitly a SearchableField
.
Query | |
|
data QueryOption
TailableCursor | Tailable means cursor is not closed when the last data is retrieved. Rather, the cursor marks the final object's position. You can resume using the cursor later, from where it was located, if more data were received. Like any latent cursor, the cursor may become invalid at some point – for example if the final object it references were deleted. Thus, you should be prepared to requery on CursorNotFound exception. |
NoCursorTimeout | The server normally times out idle cursors after 10 minutes to prevent a memory leak in case a client forgets to close a cursor. Set this option to allow a cursor to live forever until it is closed. |
AwaitData | Use with TailableCursor. If we are at the end of the data, block for a while rather than returning no data. After a timeout period, we do return as normal.
| Exhaust -- ^ Stream the data down full blast in multiple more packages, on the assumption that the client will fully read all data queried. Faster when you are pulling a lot of data and know you want to pull it all down. Note: the client is not allowed to not read all the data unless it closes the connection.
Exhaust commented out because not compatible with current |
Partial | Get partial results from a _mongos_ if some shards are down, instead of throwing an error. |
Maximum number of documents to return, i.e. cursor will close after iterating over this number of documents. 0 means no limit.
The number of document to return in each batch response from the server. 0 means use Mongo default.
Find
A labeled cursor. The cursor is labeled with the join of the database and collection it reads from. The collection policies are "carried" along since they are applied on-demand.
find :: Query -> DBAction CursorSource
Fetch documents satisfying query. A labeled Cursor
is returned,
which can be used to retrieve the actual HsonDocument
s. For this
function to succeed the current computation must be able to read from
the database and collection (implicilty the database's
collection-set). This is satisfied by applying taint
to the join
join of the collection, database, and ccollection-set label.
The curor label is labeled by the upperBound
of the database and
collection labels and must be used within the same withPolicyModule
block.
Note that this function is quite permissive in the queries it
accepts. Specifically, any non-SearchableField
s used in sort
,
order
, or hint
are ignored (as opposed to throwing an
exception).
findP :: DCPriv -> Query -> DBAction CursorSource
Same as find
, but uses privileges when reading from the
collection and database.
next :: Cursor -> DBAction (Maybe LabeledHsonDocument)Source
Return next HsonDocument
in the query result, or Nothing
if
finished. Note that the current computation must be able to read from
the labeled Cursor
. To enforce this, next
uses taint
to raise
the current label to join of the current label and 'Cursor'\'s label.
The returned document is labeled according to the underlying
Collection
policy.
nextP :: DCPriv -> Cursor -> DBAction (Maybe LabeledHsonDocument)Source
Same as next
, but usess privileges when raising the current label.
findOne :: Query -> DBAction (Maybe LabeledHsonDocument)Source
Fetch the first document satisfying query, or Nothing
if not
documents matched the query.
findOneP :: DCPriv -> Query -> DBAction (Maybe LabeledHsonDocument)Source
Same as findOne
, but uses privileges when performing label
comparisons.
Query failures
Exceptions thrown by invalid database queries.
UnknownCollection | Collection does not exist |
UnknownPolicyModule | Policy module not found |
ExecFailure Failure | Execution of action failed |
Applying policies
:: MonadDC m | |
=> DCPriv | Privileges |
-> Collection | Collection and policies |
-> HsonDocument | Document to apply policies to |
-> m LabeledHsonDocument |
Apply a collection policy the given document, using privileges when labeling the document and performing label comparisons. The labeling proceeds as follows:
- If two fields have the same
FieldName
, only the first is kept. This filtering is only perfomed at the top level. - Each policy labeled value (
HsonLabeled
) is labled if the policy has not been applied. If the value is already labeled, then the label is checked to be equivalent to that generated by the policy. In both cases a failure results inPolicyViolation
being thrown; the actual error must be hidden to retain the opaqueness ofPolicyLabeled
.
Note: For each FieldNamed
in the policy there must be a
field in the document corresponding to it. Moreover its "type"
must be correct: all policy labeled values must be HsonLabeled
values and all searchable fields must be HsonValue
s. The _id
field is always treated as a SearchableField
.
- The resulting document (from the above step) is labeled according to the collection policy.
The labels on PolicyLabeled
values and the document must be bounded
by the current label and clearance as imposed by guardAllocP
.
Additionally, these labels must flow to the label of the collection
clearance. (Of course, in both cases privileges are used to allow for
more permissive flows.)
Policy errors
data PolicyError Source
A document policy error.
TypeError String | Document is not "well-typed" |
PolicyViolation | Policy has been violated |
Internal
typeCheckDocument :: Map FieldName FieldPolicy -> HsonDocument -> DC ()Source
This function "type-checks" a document against a set of policies.
Specifically, it checks that the set of policy labeled values is the
same between the policy and document, searchable fields are not
policy labeled, and all searchable/policy-labeled fields named in
the collection policy are present in the document (except for _id
).