Documentation and user concepts.
This commit is contained in:
parent
9ae8c76885
commit
45f61df441
6 changed files with 253 additions and 10 deletions
|
@ -1,38 +1,44 @@
|
|||
package gs.smolban.model
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
/** Enumeration that describes the status of a [[Ticket]] in Smolban. Smolban
|
||||
* does not yet support custom status/workflow.
|
||||
*
|
||||
* @param value
|
||||
* The string value of the status.
|
||||
*/
|
||||
sealed abstract class Status(val value: String)
|
||||
sealed trait Status:
|
||||
def name: String
|
||||
def enteredAt: Instant
|
||||
|
||||
object Status:
|
||||
|
||||
/** This ticket is new, and ready to be started. New tickets may be put into
|
||||
* progress or canceled.
|
||||
*/
|
||||
case object Ready extends Status("ready")
|
||||
case class Ready(enteredAt: Instant) extends Status:
|
||||
val name: String = "ready"
|
||||
|
||||
/** This ticket is being worked on actively. In progress tickets can be
|
||||
* paused, completed, or canceled.
|
||||
*/
|
||||
case object InProgress extends Status("in_progress")
|
||||
case class InProgress(enteredAt: Instant) extends Status:
|
||||
val name: String = "in_progress"
|
||||
|
||||
/** This ticket was being worked on, but was temporarily stopped. Paused
|
||||
* tickets may be put into progress or canceled.
|
||||
*/
|
||||
case object Paused extends Status("paused")
|
||||
case class Paused(enteredAt: Instant) extends Status:
|
||||
val name: String = "paused"
|
||||
|
||||
/** This ticket was driven to completion. The work is done. Once in this
|
||||
* state, the status may no longer change.
|
||||
*/
|
||||
case object Complete extends Status("complete")
|
||||
case class Complete(enteredAt: Instant) extends Status:
|
||||
val name: String = "complete"
|
||||
|
||||
/** This ticket was canceled for some reason. Once in this state, the status
|
||||
* may no longer change.
|
||||
*/
|
||||
case object Canceled extends Status("canceled")
|
||||
case class Canceled(enteredAt: Instant) extends Status:
|
||||
val name: String = "canceled"
|
||||
|
||||
end Status
|
||||
|
|
|
@ -2,6 +2,27 @@ package gs.smolban.model
|
|||
|
||||
import cats.Show
|
||||
|
||||
/** Tickets represent some tracked work.
|
||||
*
|
||||
* @param id
|
||||
* Unique identifier _within_ the [[Group]].
|
||||
* @param group
|
||||
* Unique identifier of the [[Group]] that owns this ticket.
|
||||
* @param createdAt
|
||||
* The instant at which this ticket was created.
|
||||
* @param createdBy
|
||||
* The unique identifier of the [[User]] who created this ticket.
|
||||
* @param title
|
||||
* Arbitrary string title of the ticket.
|
||||
* @param description
|
||||
* Markdown contents of the ticket.
|
||||
* @param tags
|
||||
* List of [[Tag]] applied to this ticket.
|
||||
* @param status
|
||||
* Current [[Status]] of this ticket.
|
||||
* @param statusHistory
|
||||
* Linear history of this ticket in terms of status changes.
|
||||
*/
|
||||
case class Ticket(
|
||||
id: Ticket.Id,
|
||||
group: Group.Id,
|
||||
|
|
104
modules/model/src/main/scala/gs/smolban/model/users/Role.scala
Normal file
104
modules/model/src/main/scala/gs/smolban/model/users/Role.scala
Normal file
|
@ -0,0 +1,104 @@
|
|||
package gs.smolban.model.users
|
||||
|
||||
/** Roles define what each [[User]] is allowed to do.
|
||||
*
|
||||
* @param name
|
||||
* The name of the role.
|
||||
* @param scope
|
||||
* The [[Scope]] to which the role applies.
|
||||
*/
|
||||
sealed abstract class Role(
|
||||
val name: String,
|
||||
val scope: Scope
|
||||
):
|
||||
|
||||
override def toString(): String =
|
||||
s"[$name]${Role.Delimiter}$scope"
|
||||
|
||||
object Role:
|
||||
|
||||
val Delimiter: String = ":"
|
||||
|
||||
/** Administrator for the API. Can perform any operation through the API.
|
||||
*/
|
||||
case object ApiAdmin extends Role(s"api${Delimiter}admin", Scope.ApiGlobal)
|
||||
|
||||
/** Global read access to the API.
|
||||
*/
|
||||
case object ApiGlobalReader
|
||||
extends Role(s"api${Delimiter}reader", Scope.ApiGlobal)
|
||||
|
||||
/** Global write access to the API.
|
||||
*/
|
||||
case object ApiGlobalWriter
|
||||
extends Role(s"api${Delimiter}writer", Scope.ApiGlobal)
|
||||
|
||||
/** Administrator for a specific [[gs.smolban.model.Group]] via the API. Can
|
||||
* perform any operation through the API for the indicated group.
|
||||
*
|
||||
* @param groupId
|
||||
* The unique identifier for the group to which this role is scoped.
|
||||
*/
|
||||
case class ApiGroupAdmin(
|
||||
groupId: gs.smolban.model.Group.Id
|
||||
) extends Role(s"api${Delimiter}group_admin", Scope.ApiGroup(groupId))
|
||||
|
||||
/** Grants API read access for a specific [[gs.smolban.model.Group]].
|
||||
*
|
||||
* @param groupId
|
||||
* The unique identifier for the group to which this role is scoped.
|
||||
*/
|
||||
case class ApiGroupReader(
|
||||
groupId: gs.smolban.model.Group.Id
|
||||
) extends Role(s"api${Delimiter}group_reader", Scope.ApiGroup(groupId))
|
||||
|
||||
/** Grants API write access for a specific [[gs.smolban.model.Group]].
|
||||
*
|
||||
* @param groupId
|
||||
* The unique identifier for the group to which this role is scoped.
|
||||
*/
|
||||
case class ApiGroupWriter(
|
||||
groupId: gs.smolban.model.Group.Id
|
||||
) extends Role(s"api${Delimiter}group_writer", Scope.ApiGroup(groupId))
|
||||
|
||||
/** Administrator for the UI. Can perform any operation through the UI.
|
||||
*/
|
||||
case object UiAdmin extends Role(s"ui${Delimiter}admin", Scope.UiGlobal)
|
||||
|
||||
/** Global read access to the UI.
|
||||
*/
|
||||
case object UiGlobalReader extends Role("ui:reader", Scope.UiGlobal)
|
||||
|
||||
/** Global write access to the UI.
|
||||
*/
|
||||
case object UiGlobalWriter extends Role("ui:writer", Scope.UiGlobal)
|
||||
|
||||
/** Administrator for a specific [[gs.smolban.model.Group]] via the UI. Can
|
||||
* perform any operation through the UI for the indicated group.
|
||||
*
|
||||
* @param groupId
|
||||
* The unique identifier for the group to which this role is scoped.
|
||||
*/
|
||||
case class UiGroupAdmin(
|
||||
groupId: gs.smolban.model.Group.Id
|
||||
) extends Role(s"ui${Delimiter}group_admin", Scope.UiGroup(groupId))
|
||||
|
||||
/** Grants UI read access for a specific [[gs.smolban.model.Group]].
|
||||
*
|
||||
* @param groupId
|
||||
* The unique identifier for the group to which this role is scoped.
|
||||
*/
|
||||
case class UiGroupReader(
|
||||
groupId: gs.smolban.model.Group.Id
|
||||
) extends Role(s"ui${Delimiter}group_reader", Scope.UiGroup(groupId))
|
||||
|
||||
/** Grants UI write access for a specific [[gs.smolban.model.Group]].
|
||||
*
|
||||
* @param groupId
|
||||
* The unique identifier for the group to which this role is scoped.
|
||||
*/
|
||||
case class UiGroupWriter(
|
||||
groupId: gs.smolban.model.Group.Id
|
||||
) extends Role(s"ui${Delimiter}group_writer", Scope.UiGroup(groupId))
|
||||
|
||||
end Role
|
|
@ -0,0 +1,78 @@
|
|||
package gs.smolban.model.users
|
||||
|
||||
import cats.syntax.all.*
|
||||
|
||||
/** Describes a _Scope_, or service of Smolban, to which a user can have access.
|
||||
*
|
||||
* Scopes consist of two parts:
|
||||
*
|
||||
* - `service`: The name of a service Smolban offers.
|
||||
* - `name`: The name of the scope within the given service.
|
||||
*
|
||||
* @param service
|
||||
* The name of a service Smolban offers (e.g. `api`, `ui`)
|
||||
* @param name
|
||||
* The name of the scope within the service.
|
||||
*/
|
||||
sealed abstract class Scope(
|
||||
val service: String,
|
||||
val name: String
|
||||
)
|
||||
|
||||
object Scope:
|
||||
|
||||
given CanEqual[Scope, Scope] = CanEqual.derived
|
||||
|
||||
object Services:
|
||||
|
||||
val Api: String = "api"
|
||||
val Ui: String = "ui"
|
||||
|
||||
end Services
|
||||
|
||||
object Names:
|
||||
|
||||
val Global: String = "global"
|
||||
val Group: String = "group"
|
||||
|
||||
end Names
|
||||
|
||||
val Delimiter: String = ":"
|
||||
|
||||
/** The `api:global` scope covers the Smolban API across all groups.
|
||||
*/
|
||||
case object ApiGlobal extends Scope(Services.Api, Names.Global):
|
||||
override def toString(): String = s"[$service$Delimiter$name]"
|
||||
|
||||
/** The `api:group:<id>` scope refers the the Smolban API for a specific
|
||||
* [[Group]].
|
||||
*
|
||||
* @param groupId
|
||||
* The unique identifier of the [[Group]].
|
||||
*/
|
||||
case class ApiGroup(
|
||||
groupId: gs.smolban.model.Group.Id
|
||||
) extends Scope(Services.Api, Names.Group):
|
||||
|
||||
override def toString(): String =
|
||||
s"[$service$Delimiter$name$Delimiter${groupId.show}]"
|
||||
|
||||
/** The `ui:global` scope covers the Smolban UI across all groups.
|
||||
*/
|
||||
case object UiGlobal extends Scope(Services.Ui, Names.Global):
|
||||
override def toString(): String = s"[$service$Delimiter$name]"
|
||||
|
||||
/** The `ui:group:<id>` scope refers the the Smolban UI for a specific
|
||||
* [[Group]].
|
||||
*
|
||||
* @param groupId
|
||||
* The unique identifier of the [[Group]].
|
||||
*/
|
||||
case class UiGroup(
|
||||
groupId: gs.smolban.model.Group.Id
|
||||
) extends Scope(Services.Ui, Names.Group):
|
||||
|
||||
override def toString(): String =
|
||||
s"[$service$Delimiter$name$Delimiter${groupId.show}]"
|
||||
|
||||
end Scope
|
|
@ -4,10 +4,25 @@ import cats.Show
|
|||
import gs.smolban.model.CreatedAt
|
||||
import gs.uuid.v0.UUID
|
||||
|
||||
/** Represents a user that can interact with Smolban.
|
||||
*
|
||||
* @param id
|
||||
* Unique identifier of this user.
|
||||
* @param createdAt
|
||||
* The instant at which this user was created.
|
||||
* @param username
|
||||
* The (unique) [[Username]] of this user.
|
||||
* @param userType
|
||||
* The [[UserType]] of this user.
|
||||
* @param roles
|
||||
* List of [[Role]] assigned to this user.
|
||||
*/
|
||||
case class User(
|
||||
id: User.Id,
|
||||
createdAt: CreatedAt,
|
||||
username: Username
|
||||
username: Username,
|
||||
userType: UserType,
|
||||
roles: List[Role]
|
||||
)
|
||||
|
||||
object User:
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package gs.smolban.model.users
|
||||
|
||||
/** Enumeration that describes the type of a [[User]].
|
||||
*/
|
||||
sealed abstract class UserType(val name: String)
|
||||
|
||||
object UserType:
|
||||
|
||||
/** Regular users are typically human, and are expected to be using the Web UI
|
||||
* and _possibly_ APIs.
|
||||
*/
|
||||
case object Regular extends UserType("regular")
|
||||
|
||||
/** Service users are intended for use by API-consuming services. They are not
|
||||
* suitable for human/UI interactive use.
|
||||
*/
|
||||
case object Service extends UserType("service")
|
||||
|
||||
end UserType
|
Loading…
Add table
Reference in a new issue