com.lightningkite.lightningdb.ModelPermissionsFieldCollection.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of server-core Show documentation
Show all versions of server-core Show documentation
A set of tools to fill in/replace what Ktor is lacking in.
The newest version!
package com.lightningkite.lightningdb
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
/**
* Uses [ModelPermissions] to secure a [FieldCollection].
*/
open class ModelPermissionsFieldCollection(
override val wraps: FieldCollection,
val permissions: ModelPermissions
) : FieldCollection {
override fun registerRawSignal(callback: suspend (CollectionChanges) -> Unit) {
wraps.registerRawSignal(callback)
}
override suspend fun find(
condition: Condition,
orderBy: List>,
skip: Int,
limit: Int,
maxQueryMs: Long
): Flow {
val sortImposedConditions = permissions.readMask.permitSort(orderBy)
return wraps.find(
condition = condition and permissions.read and sortImposedConditions and permissions.readMask(condition),
orderBy = orderBy,
skip = skip,
limit = limit,
maxQueryMs = maxQueryMs
).map { permissions.mask(it) }
}
override suspend fun findPartial(
fields: Set>,
condition: Condition,
orderBy: List>,
skip: Int,
limit: Int,
maxQueryMs: Long
): Flow> {
val sortImposedConditions = permissions.readMask.permitSort(orderBy)
val allFields = fields.toMutableSet()
permissions.readMask.pairs.forEach {
it.first.emitReadPaths {
allFields.add(it)
}
}
return wraps.findPartial(
fields = allFields,
condition = condition and permissions.read and sortImposedConditions and permissions.readMask(condition),
orderBy = orderBy,
skip = skip,
limit = limit,
maxQueryMs = maxQueryMs
).map { permissions.mask(it) }
}
override suspend fun insert(models: Iterable): List {
val passingModels = models.filter { permissions.create(it) }
return wraps.insertMany(passingModels).map { permissions.mask(it) }
}
override suspend fun count(condition: Condition): Int = wraps.count(condition and permissions.read)
override suspend fun groupCount(
condition: Condition,
groupBy: DataClassPath
): Map {
return wraps.groupCount(
condition and permissions.read and permissions.readMask(groupBy) and permissions.readMask(condition),
groupBy
)
}
override suspend fun aggregate(
aggregate: Aggregate,
condition: Condition,
property: DataClassPath
): Double? = wraps.aggregate(aggregate, condition and permissions.read and permissions.readMask(condition), property)
override suspend fun groupAggregate(
aggregate: Aggregate,
condition: Condition,
groupBy: DataClassPath,
property: DataClassPath
): Map = wraps.groupAggregate(
aggregate,
condition and permissions.read and permissions.readMask(groupBy) and permissions.readMask(condition),
groupBy,
property
)
override suspend fun replaceOne(condition: Condition, model: Model, orderBy: List>): EntryChange {
val sortImposedConditions = permissions.readMask.permitSort(orderBy)
return wraps.replaceOne(
condition and permissions.allowed(Modification.Assign(model)) and sortImposedConditions,
model,
orderBy
).map { permissions.mask(it) }
}
override suspend fun upsertOne(
condition: Condition,
modification: Modification,
model: Model
): EntryChange {
if (!permissions.create(model)) throw SecurityException("You do not have permission to insert this instance. You can only insert instances that adhere to the following condition: ${permissions.create}")
return wraps.upsertOne(condition and permissions.allowed(modification), modification, model)
.map { permissions.mask(it) }
}
override suspend fun updateOne(
condition: Condition,
modification: Modification,
orderBy: List>
): EntryChange {
val sortImposedConditions = permissions.readMask.permitSort(orderBy)
return wraps.updateOne(condition and permissions.allowed(modification) and sortImposedConditions, modification, orderBy)
.map { permissions.mask(it) }
}
override suspend fun updateOneIgnoringResult(
condition: Condition,
modification: Modification,
orderBy: List>
): Boolean {
val sortImposedConditions = permissions.readMask.permitSort(orderBy)
return wraps.updateOneIgnoringResult(condition and permissions.allowed(modification) and sortImposedConditions, modification, orderBy)
}
override suspend fun updateManyIgnoringResult(condition: Condition, modification: Modification): Int {
return wraps.updateManyIgnoringResult(condition and permissions.allowed(modification), modification)
}
override suspend fun deleteOneIgnoringOld(condition: Condition, orderBy: List>): Boolean {
val sortImposedConditions = permissions.readMask.permitSort(orderBy)
return wraps.deleteOneIgnoringOld(condition and permissions.delete and sortImposedConditions, orderBy)
}
override suspend fun deleteManyIgnoringOld(condition: Condition): Int {
return wraps.deleteManyIgnoringOld(condition and permissions.delete)
}
override suspend fun replaceOneIgnoringResult(
condition: Condition,
model: Model,
orderBy: List>
): Boolean {
val sortImposedConditions = permissions.readMask.permitSort(orderBy)
return wraps.replaceOneIgnoringResult(
condition and permissions.allowed(Modification.Assign(model)) and sortImposedConditions,
model,
orderBy
)
}
override suspend fun upsertOneIgnoringResult(
condition: Condition,
modification: Modification,
model: Model
): Boolean {
if (!permissions.create(model)) throw SecurityException("You do not have permission to insert this instance. You can only insert instances that adhere to the following condition: ${permissions.create}")
return wraps.upsertOneIgnoringResult(condition and permissions.allowed(modification), modification, model)
}
override suspend fun updateMany(
condition: Condition,
modification: Modification
): CollectionChanges {
return wraps.updateMany(condition and permissions.allowed(modification), modification)
.map { permissions.mask(it) }
}
override suspend fun deleteOne(condition: Condition, orderBy: List>): Model? {
val sortImposedConditions = permissions.readMask.permitSort(orderBy)
return wraps.deleteOne(condition and permissions.delete and sortImposedConditions, orderBy)?.let { permissions.mask(it) }
}
override suspend fun deleteMany(condition: Condition): List {
return wraps.deleteMany(condition and permissions.delete).map { permissions.mask(it) }
}
override suspend fun fullCondition(condition: Condition): Condition = permissions.read and condition and permissions.readMask(condition)
override suspend fun mask(): Mask = permissions.readMask
}
fun FieldCollection.withPermissions(permissions: ModelPermissions): FieldCollection =
ModelPermissionsFieldCollection(this, permissions)