| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- using Statum;
- using Invercargill;
- using Invercargill.DataStructures;
- namespace Example {
- /**
- * `POST /_statum/action/{guid}` — logs in: reads the submitted name, builds a
- * session `auth` slot (with a typed private `is_admin` flag) carrying a
- * `logout` action reference, and redirects home.
- */
- public class LoginAction : StatumAction {
- public override async DirectiveBuilder handle() throws GLib.Error {
- var name = "guest";
- if (request.form != null) {
- var submitted = request.form.get_field("name");
- if (submitted != null && ((!)submitted).length > 0) {
- name = (!)submitted;
- }
- }
- var is_admin = name == "admin";
- var auth_public = new PropertyDictionary();
- auth_public.set_native<string>("name", name);
- auth_public.set_native<string>("role", is_admin ? "admin" : "member");
- auth_public["logout"] = action_registry.author<LogoutAction>().to_element();
- var auth_private = new PropertyDictionary();
- auth_private.set_native<bool>("is_admin", is_admin);
- var slot = state_service.new_slot(Scope.SESSION, new State() {
- type_name = "auth",
- public_data = auth_public,
- private_data = auth_private
- });
- return directives().set(slot).navigate("/");
- }
- }
- /**
- * `POST /_statum/action/{guid}` — logs out: clears the held `auth` slot
- * (server cache + clear directive) and redirects home.
- */
- public class LogoutAction : StatumAction {
- public override async DirectiveBuilder handle() throws GLib.Error {
- HeldSlot auth;
- if (request.held.try_get("auth", out auth)) {
- yield state_service.clear_slot(auth.key);
- return directives().clear(auth.key).navigate("/");
- }
- return directives().navigate("/");
- }
- }
- /**
- * `POST /_statum/action/{guid}` — bumps the counter by the typed private
- * `delta`, updating the held `counter` slot (sign + auto-push to subscribed
- * channels) and re-embedding the `bump` reference in the new public data.
- */
- public class BumpCounterAction : TypedStatumAction<CounterPrivate> {
- public override async DirectiveBuilder handle() throws GLib.Error {
- var delta = request_private != null ? ((!)request_private).delta : 1;
- HeldSlot held_counter;
- if (!request.held.try_get("counter", out held_counter)) {
- return directives().error("No counter slot held");
- }
- var slot = state_service.get_slot(held_counter.key);
- if (slot == null || ((!)slot).current_state == null) {
- return directives().error("Counter slot not found");
- }
- var current = ((!)slot).current_state;
- var value = GObjectMapping.get_int(current.public_data, "value") ?? 0;
- var new_public = new PropertyDictionary();
- new_public.set_native<int>("value", value + delta);
- var bump_private = new CounterPrivate();
- bump_private.delta = delta;
- new_public["bump"] = action_registry
- .author_private<BumpCounterAction, CounterPrivate>(bump_private)
- .to_element();
- var new_state = new State() {
- type_name = "counter",
- public_data = new_public,
- private_data = new PropertyDictionary()
- };
- return directives().update(held_counter.key, new_state);
- }
- }
- }
|