Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import io.github.graphglue.authorization.AuthorizationContext
import io.github.graphglue.authorization.Permission
import io.jsonwebtoken.JwtException
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.io.Decoders
import io.jsonwebtoken.security.Keys
import kotlinx.coroutines.reactor.awaitSingle
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Component
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gropius.schema.mutation

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.annotations.GraphQLIgnore
import com.expediagroup.graphql.server.operations.Mutation
import graphql.schema.DataFetchingEnvironment
import gropius.authorization.gropiusAuthorizationContext
Expand All @@ -15,7 +14,6 @@ import gropius.graphql.AutoPayloadType
import gropius.model.architecture.*
import gropius.model.architecture.layout.View
import gropius.service.architecture.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional

Expand Down
144 changes: 137 additions & 7 deletions api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ import gropius.dto.input.issue.*
import gropius.dto.payload.DeleteNodePayload
import gropius.graphql.AutoPayloadType
import gropius.model.architecture.Trackable
import gropius.model.issue.Artefact
import gropius.model.issue.Issue
import gropius.model.issue.Label
import gropius.model.issue.*
import gropius.model.issue.timeline.*
import gropius.service.issue.ArtefactService
import gropius.service.issue.IssueService
import gropius.service.issue.LabelService
import gropius.service.issue.*
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
Expand All @@ -32,7 +28,10 @@ import org.springframework.transaction.annotation.Transactional
class IssueMutations(
private val issueService: IssueService,
private val labelService: LabelService,
private val artefactService: ArtefactService
private val artefactService: ArtefactService,
private val issueBoardService: IssueBoardService,
private val issueBoardColumnService: IssueBoardColumnService,
private val issueBoardItemService: IssueBoardItemService
) : Mutation {

@GraphQLDescription(
Expand Down Expand Up @@ -524,4 +523,135 @@ class IssueMutations(
return issueService.deleteIssueComment(dfe.gropiusAuthorizationContext, input)
}

@GraphQLDescription(
"""Creates a new Issue Board on one trackable. Requires MANAGE_ISSUE_BOARDS on the provided trackable.
"""
)
@AutoPayloadType("The created Issue Board")
suspend fun createIssueBoard(
@GraphQLDescription("Defines the created Issue Board")
input: CreateIssueBoardInput, dfe: DataFetchingEnvironment
): IssueBoard {
return issueBoardService.createIssueBoard(dfe.gropiusAuthorizationContext, input)
}

@GraphQLDescription("Updates the specified Issue Board, Requires MANAGE_ISSUE_BOARDS on the provided trackable.")
@AutoPayloadType("The updated Issue Board")
suspend fun updateIssueBoard(
@GraphQLDescription("Defines which Issue Board to update and how to update it")
input: UpdateIssueBoardInput, dfe: DataFetchingEnvironment
): IssueBoard {
return issueBoardService.updateIssueBoard(dfe.gropiusAuthorizationContext, input)
}

@GraphQLDescription(
"""Deletes the Issue Board, requires MANAGE_ISSUE_BOARDS on the provided trackable.
"""
)
suspend fun deleteIssueBoard(
@GraphQLDescription("Defines which Issue Board to delete")
input: DeleteNodeInput, dfe: DataFetchingEnvironment
): DeleteNodePayload {
issueBoardService.deleteIssueBoard(dfe.gropiusAuthorizationContext, input)
return DeleteNodePayload(input.id)
}

@GraphQLDescription(
"""Creates a new Issue Board Column on one trackable. Requires MANAGE_ISSUE_BOARDS on the parent trackable.
"""
)
@AutoPayloadType("The created Issue Board Column")
suspend fun createIssueBoardColumn(
@GraphQLDescription("Defines the created Issue Board Column")
input: CreateIssueBoardColumnInput, dfe: DataFetchingEnvironment
): IssueBoardColumn {
return issueBoardColumnService.createIssueBoardColumn(dfe.gropiusAuthorizationContext, input)
}

@GraphQLDescription("Updates the specified Issue Board Column, Requires MANAGE_ISSUE_BOARDS on the parent trackable.")
@AutoPayloadType("The updated Issue Board Column")
suspend fun updateIssueBoardColumn(
@GraphQLDescription("Defines which Issue Board Column to update and how to update it")
input: UpdateIssueBoardColumnInput, dfe: DataFetchingEnvironment
): IssueBoardColumn {
return issueBoardColumnService.updateIssueBoardColumn(dfe.gropiusAuthorizationContext, input)
}

@GraphQLDescription(
"""Deletes the Issue Board Column, requires MANAGE_ISSUE_BOARDS on the parent trackable.
"""
)
suspend fun deleteIssueBoardColumn(
@GraphQLDescription("Defines which Issue Board Column to delete")
input: DeleteNodeInput, dfe: DataFetchingEnvironment
): DeleteNodePayload {
issueBoardColumnService.deleteIssueBoardColumn(dfe.gropiusAuthorizationContext, input)
return DeleteNodePayload(input.id)
}

@GraphQLDescription(
"""Adds an Issue State to a Board Column, requires MANAGE_ISSUE_BOARDS on the parent Trackable
of the column the Issue State should be added to, and READ on the Issue State.
Returns the updated column (unchanged if the state was already assigned).
"""
)
suspend fun addIssueStateToBoardColumn(
@GraphQLDescription("Defines the board column ID and the issue state ID to add")
input: AddIssueStateToBoardColumnInput,
dfe: DataFetchingEnvironment
): IssueBoardColumn {
return issueBoardColumnService.addIssueStateToBoardColumn(dfe.gropiusAuthorizationContext, input)
}

@GraphQLDescription(
"""Removes an Issue State from a Board Column, requires MANAGE_ISSUE_BOARDS on the parent Trackable
of the column the Issue State should be removed from, and READ on the Issue State.
Returns the updated column.
"""
)
suspend fun removeIssueStateFromBoardColumn(
@GraphQLDescription("Defines the board column ID and the issue state ID to remove")
input: RemoveIssueStateFromBoardColumnInput,
dfe: DataFetchingEnvironment
): IssueBoardColumn {
return issueBoardColumnService.removeIssueStateFromBoardColumn(
dfe.gropiusAuthorizationContext,
input
)
}

@GraphQLDescription(
"""Creates a new Issue Board Item on an Issue Board. Requires MANAGE_ISSUES on the parent Trackable.
"""
)
@AutoPayloadType("The created Issue Board Item")
suspend fun createIssueBoardItem(
@GraphQLDescription("Defines the created Issue Board Item")
input: CreateIssueBoardItemInput, dfe: DataFetchingEnvironment
): IssueBoardItem {
return issueBoardItemService.createIssueBoardItem(dfe.gropiusAuthorizationContext, input)
}

@GraphQLDescription("Updates the specified Issue Board Item, Requires MANAGE_ISSUES on the parent Trackable.")
@AutoPayloadType("The updated Issue Board Item")
suspend fun updateIssueBoardItem(
@GraphQLDescription("Defines which Issue Board Item to update and how to update it")
input: UpdateIssueBoardItemInput, dfe: DataFetchingEnvironment
): IssueBoardItem {
return issueBoardItemService.updateIssueBoardItem(dfe.gropiusAuthorizationContext, input)
}


@GraphQLDescription(
"""Deletes the Issue Board Item, requires MANAGE_ISSUES on the parent Trackable.
"""
)
suspend fun deleteIssueBoardItem(
@GraphQLDescription("Defines which Issue Board Item to delete")
input: DeleteNodeInput, dfe: DataFetchingEnvironment
): DeleteNodePayload {
issueBoardItemService.deleteIssueBoardItem(dfe.gropiusAuthorizationContext, input)
return DeleteNodePayload(input.id)
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gropius.dto.input.architecture

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import gropius.dto.input.common.CreateNamedNodeInput
import gropius.dto.input.common.Input
import gropius.dto.input.common.JSONFieldInput
import gropius.dto.input.common.validateAndEnsureNoDuplicates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package gropius.dto.input.architecture
import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.execution.OptionalInput
import gropius.dto.input.common.JSONFieldInput
import gropius.dto.input.common.UpdateNamedNodeInput
import gropius.dto.input.common.UpdateNodeInput
import gropius.dto.input.common.validateAndEnsureNoDuplicates
import gropius.dto.input.ifPresent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package gropius.dto.input.architecture

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.execution.OptionalInput
import gropius.dto.input.common.*
import gropius.dto.input.common.JSONFieldInput
import gropius.dto.input.common.UpdateNodeInput
import gropius.dto.input.common.validateAndEnsureNoDuplicates
import gropius.dto.input.ifPresent
import gropius.dto.input.template.UpdateTemplatedNodeInput

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package gropius.dto.input.issue

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.scalars.ID
import gropius.dto.input.common.Input

@GraphQLDescription("Input for the addIssueStateToBoardColumn mutation")
class AddIssueStateToBoardColumnInput(
@GraphQLDescription("The id of the Issue Board Column where to add the Issue State")
val column: ID,
@GraphQLDescription("The id of the Issue State to add")
val state: ID
) : Input()
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package gropius.dto.input.issue

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.scalars.ID
import gropius.dto.input.common.CreateNamedNodeInput

@GraphQLDescription("Input for the createIssueBoardColumn mutation")
class CreateIssueBoardColumnInput(
@GraphQLDescription("ID of issue board the column is added to")
val issueBoard: ID
) : CreateNamedNodeInput()
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package gropius.dto.input.issue

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.scalars.ID
import gropius.dto.input.common.CreateNamedNodeInput

@GraphQLDescription("Input for the createIssueBoard mutation")
class CreateIssueBoardInput(
@GraphQLDescription("ID of Trackable the issue board is added to")
val trackable: ID
) : CreateNamedNodeInput()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package gropius.dto.input.issue

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.scalars.ID
import gropius.dto.input.common.Input

@GraphQLDescription("Input for the createIssueBoardItem mutation")
class CreateIssueBoardItemInput(
@GraphQLDescription("ID of the IssueBoard to add this item to")
val issueBoard: ID,
@GraphQLDescription("ID of the Issue to represent in this board item")
val issue: ID,
@GraphQLDescription("Initial position of the new board item")
val position: Double
) : Input() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package gropius.dto.input.issue

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.scalars.ID
import gropius.dto.input.common.Input

@GraphQLDescription("Input for the removeIssueStateFromBoardColumn mutation")
class RemoveIssueStateFromBoardColumnInput(
@GraphQLDescription("The id of the Issue Board Column from which the Issue State should be removed")
val column: ID,
@GraphQLDescription("The id of the Issue State to remove from the board column")
val state: ID
) : Input()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package gropius.dto.input.issue

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import gropius.dto.input.common.UpdateNamedNodeInput

@GraphQLDescription("Input for the updateIssueBoardColumn mutation")
class UpdateIssueBoardColumnInput : UpdateNamedNodeInput()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package gropius.dto.input.issue

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import gropius.dto.input.common.UpdateNamedNodeInput

@GraphQLDescription("Input for the updateIssueBoard mutation")
class UpdateIssueBoardInput : UpdateNamedNodeInput()
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package gropius.dto.input.issue

import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.execution.OptionalInput
import gropius.dto.input.common.UpdateNodeInput

@GraphQLDescription("Input for the updateIssueBoardItem mutation")
class UpdateIssueBoardItemInput(
@GraphQLDescription("New position (order) for this board item")
val position: OptionalInput<Double>
) : UpdateNodeInput()
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import com.expediagroup.graphql.generator.annotations.GraphQLIgnore
import gropius.model.architecture.layout.RelationPartnerLayout
import gropius.model.issue.AggregatedIssue
import gropius.model.template.RelationPartnerTemplate
import gropius.model.template.TemplatedNode
import io.github.graphglue.model.*
import io.github.graphglue.model.property.NodeCache

Expand Down
14 changes: 13 additions & 1 deletion core/src/main/kotlin/gropius/model/architecture/Trackable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import gropius.authorization.RELATED_TO_NODE_PERMISSION_RULE
import gropius.model.issue.Artefact
import gropius.model.issue.Issue
import gropius.model.issue.IssueBoard
import gropius.model.issue.Label
import gropius.model.user.permission.NodePermission
import gropius.model.user.permission.TrackablePermission
Expand All @@ -12,7 +13,7 @@ import java.net.URI

@DomainNode("trackables", searchQueryName = "searchTrackables")
@GraphQLDescription(
"""An entity which can have Issues, Labels and Artefacts.
"""An entity which can have Issues,Issue Boards, Labels and Artefacts.
Has pinned issues.
Can be synced to an IMS by creating an IMSProject.
Can be affected by Issues.
Expand Down Expand Up @@ -77,6 +78,9 @@ import java.net.URI
@Authorization(
TrackablePermission.MANAGE_LABELS, allow = [Rule(RELATED_TO_NODE_PERMISSION_RULE, options = [NodePermission.ADMIN])]
)
@Authorization(
TrackablePermission.MANAGE_ISSUE_BOARDS, allow = [Rule(RELATED_TO_NODE_PERMISSION_RULE, options = [NodePermission.ADMIN])]
)
@Authorization(
TrackablePermission.MANAGE_ARTEFACTS,
allow = [Rule(RELATED_TO_NODE_PERMISSION_RULE, options = [NodePermission.ADMIN])]
Expand Down Expand Up @@ -107,6 +111,7 @@ abstract class Trackable(
const val LABEL = "LABEL"
const val ARTEFACT = "ARTEFACT"
const val SYNCS_TO = "SYNCS_TO"
const val ISSUE_BOARD = "ISSUE_BOARD"
}

@NodeRelationship(ISSUE, Direction.OUTGOING)
Expand All @@ -118,6 +123,13 @@ abstract class Trackable(
@FilterProperty
val issues by NodeSetProperty<Issue>()

@NodeRelationship(ISSUE_BOARD, Direction.OUTGOING)
@GraphQLDescription(
"""The set of Issue Boards which are part of this Trackable. """
)
@FilterProperty
val issueBoards by NodeSetProperty<IssueBoard>()

@NodeRelationship(LABEL, Direction.OUTGOING)
@GraphQLDescription("The set of Labels which can be added to issues of this trackable.")
@FilterProperty
Expand Down
1 change: 1 addition & 0 deletions core/src/main/kotlin/gropius/model/issue/Issue.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class Issue(
const val ASSIGNMENT = "ASSIGNMENT"
const val PINNED_ON = "PINNED_ON"
const val AFFECTS = "AFFECTS"
const val ISSUE_BOARD_ITEM = "ISSUE_BOARD_ITEM"
}

@NodeRelationship(BaseTemplate.USED_IN, Direction.INCOMING)
Expand Down
Loading
Loading