| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- using Inversion;
- using Spry;
- using Spry.Authentication;
- using Statum;
- using ClankerSaddle.Services;
- namespace ClankerSaddle {
- /** Sealed capability id carried by {@link DeleteCapabilityAction}. */
- public class CapabilityActionPrivate : Object {
- public int64 capability_id { get; set; }
- }
- /** Sealed saddle-capability attachment identity. */
- public class SaddleCapabilityActionPrivate : Object {
- public int64 saddle_id { get; set; }
- public int64 link_id { get; set; }
- }
- /** Sealed task-capability attachment identity. */
- public class TaskCapabilityActionPrivate : Object {
- public int64 task_id { get; set; }
- public int64 link_id { get; set; }
- }
- /**
- * Creates a capability (tag) from the saddles page's capabilities
- * section; names are unique.
- */
- public class CreateCapabilityAction : StatumAction {
- private CapabilityService capabilities = inject<CapabilityService>();
- private UserService users = inject<UserService>();
- public override async DirectiveBuilder handle() throws GLib.Error {
- // The roles decision: capabilities are admin-managed (the
- // catalogue feeds the dispatcher's routing).
- var guard = yield SpryAuth.require_permission(directives(), request, users,
- SpryAuth.ADMIN_PERMISSION, "/login");
- if (guard != null) {
- return (!)guard;
- }
- string name = Forms.field(request, "name");
- if (name.length == 0) {
- return directives().notify("error", "A capability name is required").navigate("/saddles");
- }
- try {
- var capability = yield capabilities.create_capability(name);
- return directives().notify("success", @"Capability '$(capability.name)' created")
- .navigate("/saddles");
- } catch (Error e) {
- return directives().notify("error", @"Could not create the capability: $(e.message)")
- .navigate("/saddles");
- }
- }
- }
- /**
- * Deletes a capability everywhere (saddles stop carrying it, tasks
- * stop requiring it); the id is sealed.
- */
- public class DeleteCapabilityAction : TypedStatumAction<CapabilityActionPrivate> {
- private CapabilityService capabilities = inject<CapabilityService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(CapabilityActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- // The roles decision: capabilities are admin-managed.
- var guard = yield SpryAuth.require_permission(directives(), request, users,
- SpryAuth.ADMIN_PERMISSION, "/login");
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- if (ctx == null) {
- return directives().navigate("/saddles");
- }
- try {
- yield capabilities.delete_capability(((!)ctx).capability_id);
- return directives().notify("success", "Capability deleted").navigate("/saddles");
- } catch (Error e) {
- return directives().notify("error", @"Could not delete the capability: $(e.message)")
- .navigate("/saddles");
- }
- }
- }
- /**
- * Attaches the form-selected capability to the sealed saddle; the
- * saddle card's capability chips.
- */
- public class AttachSaddleCapabilityAction : TypedStatumAction<SaddleActionPrivate> {
- private CapabilityService capabilities = inject<CapabilityService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(SaddleActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- int64 saddle_id = ctx != null ? ((!)ctx).saddle_id : Forms.integer(request, "saddle_id", 0);
- int64 capability_id = Forms.integer(request, "capability_id", 0);
- if (saddle_id <= 0 || capability_id <= 0) {
- return directives().notify("error", "Pick a capability to attach").navigate("/saddles");
- }
- try {
- yield capabilities.attach_to_saddle(capability_id, saddle_id);
- return directives().notify("success", "Capability attached").navigate("/saddles");
- } catch (Error e) {
- return directives().notify("error", @"Could not attach the capability: $(e.message)")
- .navigate("/saddles");
- }
- }
- }
- /** Detaches a saddle capability; both ids are sealed. */
- public class DetachSaddleCapabilityAction : TypedStatumAction<SaddleCapabilityActionPrivate> {
- private CapabilityService capabilities = inject<CapabilityService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(SaddleCapabilityActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- if (ctx == null) {
- return directives().navigate("/saddles");
- }
- try {
- yield capabilities.detach_from_saddle(((!)ctx).link_id);
- return directives().notify("success", "Capability removed").navigate("/saddles");
- } catch (Error e) {
- return directives().notify("error", @"Could not remove the capability: $(e.message)")
- .navigate("/saddles");
- }
- }
- }
- /**
- * True when the task's required capabilities are still editable:
- * in draft, or queued before any worker has the job. Once a
- * saddle is assigned (or the task is parked on one) the pairing
- * the dispatcher negotiated is locked, and terminal tasks lock
- * everything.
- */
- private static async bool task_capabilities_editable(TaskService tasks, int64 task_id)
- throws GLib.Error {
- var detail = yield tasks.get_task(task_id);
- if (detail == null) {
- return false;
- }
- string status = ((!)detail).task.status;
- return status == STATUS_DRAFT || status == STATUS_QUEUED;
- }
- /**
- * Attaches the form-selected capability to the sealed task as a
- * required capability; the task page's capabilities section. Only
- * editable while the task is draft or queued (before a worker has
- * the job).
- */
- public class AttachTaskCapabilityAction : SealedTaskAction {
- private CapabilityService capability_service = inject<CapabilityService>();
- private TaskService task_service = inject<TaskService>();
- private UserService users = inject<UserService>();
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- int64 task_id = sealed_task_id();
- int64 capability_id = Forms.integer(request, "capability_id", 0);
- if (task_id <= 0 || capability_id <= 0) {
- return directives().notify("error", "Pick a capability to require")
- .navigate(@"/tasks/$(task_id)");
- }
- if (!(yield task_capabilities_editable(task_service, task_id))) {
- return directives().notify("error",
- "Capabilities are locked once a worker has the job")
- .navigate(@"/tasks/$(task_id)");
- }
- try {
- yield capability_service.attach_to_task(capability_id, task_id);
- return directives().notify("success", "Capability required")
- .navigate(@"/tasks/$(task_id)");
- } catch (Error e) {
- return directives().notify("error", @"Could not attach the capability: $(e.message)")
- .navigate(@"/tasks/$(task_id)");
- }
- }
- }
- /** Detaches a task's required capability; both ids are sealed. */
- public class DetachTaskCapabilityAction : TypedStatumAction<TaskCapabilityActionPrivate> {
- private CapabilityService capabilities = inject<CapabilityService>();
- private TaskService task_service = inject<TaskService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(TaskCapabilityActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- if (ctx == null) {
- return directives().navigate("/tasks");
- }
- if (!(yield task_capabilities_editable(task_service, ((!)ctx).task_id))) {
- return directives().notify("error",
- "Capabilities are locked once a worker has the job")
- .navigate(@"/tasks/$(((!)ctx).task_id)");
- }
- try {
- yield capabilities.detach_from_task(((!)ctx).link_id);
- return directives().notify("success", "Requirement removed")
- .navigate(@"/tasks/$(((!)ctx).task_id)");
- } catch (Error e) {
- return directives().notify("error", @"Could not remove the requirement: $(e.message)")
- .navigate(@"/tasks/$(((!)ctx).task_id)");
- }
- }
- }
- }
|