All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lightningkite.lightningdb.ModelPermissionsFieldCollection.kt Maven / Gradle / Ivy

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)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy