Skip to content

Commit

Permalink
Merge pull request #120 from ccims/feature/syncAllowedFields
Browse files Browse the repository at this point in the history
Feature/sync allowed fields
  • Loading branch information
nk-coding authored Aug 25, 2024
2 parents 3eed9b9 + 427b014 commit 279d1e2
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 10 deletions.
52 changes: 52 additions & 0 deletions api-common/src/main/kotlin/gropius/graphql/GraphQLConfiguration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import graphql.Scalars
import graphql.scalars.regex.RegexScalar
import graphql.schema.*
import gropius.authorization.GropiusAuthorizationContext
import gropius.authorization.checkPermission
import gropius.authorization.gropiusAuthorizationContext
import gropius.graphql.filter.*
Expand All @@ -33,6 +34,7 @@ import io.github.graphglue.connection.filter.definition.scalars.StringFilterDefi
import io.github.graphglue.definition.ExtensionFieldDefinition
import io.github.graphglue.definition.NodeDefinition
import io.github.graphglue.definition.NodeDefinitionCollection
import io.github.graphglue.graphql.extensions.authorizationContext
import org.neo4j.cypherdsl.core.Cypher
import org.neo4j.cypherdsl.core.Expression
import org.neo4j.driver.Driver
Expand Down Expand Up @@ -309,6 +311,56 @@ class GraphQLConfiguration {
}
}

/**
* Provides the [ExtensionFieldDefinition] for checking if the current user allows to sync their data to a target
*/
@Bean(SYNC_SELF_ALLOWED_FIELD_BEAN)
fun syncSelfAllowedField(): ExtensionFieldDefinition = syncAllowedField(true)

/**
* Provides the [ExtensionFieldDefinition] for checking if the current user allows to sync other users' data to a target
*/
@Bean(SYNC_OTHERS_ALLOWED_FIELD_BEAN)
fun syncOthersAllowedField(): ExtensionFieldDefinition = syncAllowedField(false)

/**
* Provides the [ExtensionFieldDefinition] for checking if the current user allows to sync data to a target
*
* @param self if the field is the self or other variant
* @return the generated field definition
*/
private fun syncAllowedField(self: Boolean): ExtensionFieldDefinition {
val field = GraphQLFieldDefinition.newFieldDefinition().name("isSync${if (self) "Self" else "Others"}Allowed")
.description("Checks if the current user allows to sync ${if (self) "their" else "other users'"} data to this target")
.type(GraphQLNonNull(Scalars.GraphQLBoolean)).build()

return object : ExtensionFieldDefinition(field) {
override fun generateFetcher(
dfe: DataFetchingEnvironment,
arguments: Map<String, Any?>,
node: org.neo4j.cypherdsl.core.Node,
nodeDefinition: NodeDefinition
): Expression {
val authorizationContext = dfe.authorizationContext as? GropiusAuthorizationContext
return if (authorizationContext != null) {
Cypher.exists(
node.relationshipFrom(
authorizationContext.userNode,
if (self) GropiusUser.CAN_SYNC_SELF else GropiusUser.CAN_SYNC_OTHERS
)
)
} else {
Cypher.literalFalse()
}
}

override fun transformResult(result: Value): Any {
return result.asBoolean()
}

}
}

/**
* Provides the [KotlinDataFetcherFactoryProvider] which generates a FunctionDataFetcher which handles
* JSON input value injecting correctly.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class UpdateSyncPermissionsInput(
@GraphQLDescription("The SyncPermissionTarget to update the sync permissions for the current user")
val id: ID,
@GraphQLDescription("Whether the sync service is allowed to sync content of the user")
val canSyncSelf: Boolean,
val canSyncSelf: Boolean?,
@GraphQLDescription("Whether the sync service is allowed to sync content of other users")
val canSyncOthers: Boolean
val canSyncOthers: Boolean?
) : Input()
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class IMSProject(
@GraphQLDescription("The IMS this project is a part of.")
@GraphQLNullable
@FilterProperty
@OrderProperty
val ims by NodeProperty<IMS>()

@NodeRelationship(IMSIssue.PROJECT, Direction.INCOMING)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,23 @@ import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import gropius.model.common.NamedNode
import gropius.model.user.GropiusUser
import io.github.graphglue.model.Direction
import io.github.graphglue.model.ExtensionField
import io.github.graphglue.model.FilterProperty
import io.github.graphglue.model.NodeRelationship

/**
* Name of the bean which provides the sync allowed extension field
*/
const val SYNC_SELF_ALLOWED_FIELD_BEAN = "syncSelfAllowedFieldBean"

/**
* Name of the bean which provides the sync allowed extension field
*/
const val SYNC_OTHERS_ALLOWED_FIELD_BEAN = "syncOthersAllowedFieldBean"

@GraphQLDescription("A target where users can configure how the sync should behave.")
@ExtensionField(SYNC_SELF_ALLOWED_FIELD_BEAN)
@ExtensionField(SYNC_OTHERS_ALLOWED_FIELD_BEAN)
abstract class SyncPermissionTarget(name: String, description: String) : NamedNode(name, description) {

@NodeRelationship(GropiusUser.CAN_SYNC_SELF, Direction.INCOMING)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,19 @@ class SyncPermissionTargetService(
val target = repository.findById(input.id)
checkPermission(target, Permission(NodePermission.READ, authorizationContext), "use the SyncPermissionTarget")
val user = getUser(authorizationContext)
if (input.canSyncSelf) {
target.syncSelfAllowedBy() += user
} else {
target.syncSelfAllowedBy() -= user
if (input.canSyncSelf != null) {
if (input.canSyncSelf) {
target.syncSelfAllowedBy() += user
} else {
target.syncSelfAllowedBy() -= user
}
}
if (input.canSyncOthers) {
target.syncOthersAllowedBy() += user
} else {
target.syncOthersAllowedBy() -= user
if (input.canSyncOthers != null) {
if (input.canSyncOthers) {
target.syncOthersAllowedBy() += user
} else {
target.syncOthersAllowedBy() -= user
}
}
return repository.save(target).awaitSingle()
}
Expand Down

0 comments on commit 279d1e2

Please sign in to comment.