class PlaceOS::Model::Group

Overview

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.

Included Modules

Defined in:

placeos-models/group.cr

Constant Summary

CALLBACKS = {before_save: [do if (__temp_1337 = @authority) && __temp_1337.new_record? __temp_1337.save self.authority_id = __temp_1337.id.not_nil! end end, do if (__temp_1338 = @parent) && __temp_1338.new_record? __temp_1338.save self.parent_id = __temp_1338.id.not_nil! end end, :normalize_ad_group_mappings] of Nil, after_save: [] of Nil, before_create: [do self.created_at = self.updated_at = Time.utc end] of Nil, after_create: [] of Nil, before_update: [do self.updated_at = Time.utc end] of Nil, after_update: [] of Nil, before_destroy: [] of Nil, after_destroy: [do end, do end, :__record_history_destroy__] of Nil}

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.

MAX_FEATURE_DEPTH = 2

Objects may nest inside a feature value at most this many levels deep.

MAX_FEATURE_KEY_SIZE = 64
PRIMARY_KEY_TYPES = {:id => UUID} of Nil => Nil

macro level key => type

PRIMARY_KEYS = [{:id}]

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.

Constructors

Class Method Summary

Instance Method Summary

Instance methods inherited from module PlaceOS::Model::History::Tracked

change_history change_history, history_correlation_id : String | Nil history_correlation_id, history_resource_id : String history_resource_id

Macros inherited from module PlaceOS::Model::History::Tracked

history_ignore(*fields) history_ignore, history_redact(*fields) history_redact

Constructor Detail

def self.from_json(string_or_io : String | IO, trusted : Bool = false) : self #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.from_json(string_or_io : String | IO, root : String, trusted : Bool = false) : self #

Deserializes the given JSON in string_or_io into an instance of self, assuming the JSON consists of an JSON object with key root, and whose value is the value to deserialize. Will not deserialise from fields with mass_assign: false

class User < ActiveModel::Model
  attribute name : String
  attribute google_id : UUID, mass_assign: false
end

User.from_json(%({"main": {"name": "Jason", "google_id": "f6f70bfb-c882-446d-8758-7ce47db39620"}}), root: "main") # => #<User:0x103131b20 @name="Jason">

def self.from_trusted_json(string_or_io : String | IO, root : String) : self #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.from_trusted_json(string_or_io : String | IO) : self #

Serialize from a trusted JSON source


def self.from_trusted_yaml(string_or_io : String | IO) : self #

Serialize from a trusted YAML source


def self.from_yaml(string_or_io : String | IO, trusted : Bool = false) : self #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


[View source]
def self.new(pull : JSON::PullParser) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


[View source]
def self.new(rs : DB::ResultSet) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.new(created_at : Time | ActiveModel::Model::None = ::ActiveModel::Model::None.new, updated_at : Time | ActiveModel::Model::None = ::ActiveModel::Model::None.new, id : UUID | ActiveModel::Model::None = ::ActiveModel::Model::None.new, name : String | ActiveModel::Model::None = ::ActiveModel::Model::None.new, description : String | ActiveModel::Model::None = ::ActiveModel::Model::None.new, subsystems : Array(String) | ActiveModel::Model::None = ::ActiveModel::Model::None.new, default_permissions : Int32 | ActiveModel::Model::None = ::ActiveModel::Model::None.new, ad_group_mappings : Hash(String, Tuple(String, Int32)) | ActiveModel::Model::None = ::ActiveModel::Model::None.new, features : Hash(String, Hash(String, JSON::Any)) | ActiveModel::Model::None = ::ActiveModel::Model::None.new, authority_id : String | ActiveModel::Model::None = ::ActiveModel::Model::None.new, parent_id : UUID | Nil | ActiveModel::Model::None = ::ActiveModel::Model::None.new) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.new(params : HTTP::Params | Hash(String, String) | Tuple(String, String)) #

Initialize PlaceOS::Model::Group from HTTP::Params.


def self.undelete(resource_id : String) : self #

Recreates a deleted record from its latest delete entry, keeping its id.

Records removed alongside it (cascading deletes) are not restored and redacted fields are left at their defaults. Raises if there is no delete entry or the record can't be saved, e.g. if it already exists.


[View source]

Class Method Detail

def self.accessible_zone_ids(authority_id : String, subsystem : String, user_id : String) : Array(String) #

Zone ids this user has any non-zero effective permission on, within subsystem. Includes zones reached transitively (via ancestor group membership and via ancestor zone GroupZone rows), minus anything masked off by deny rows.


[View source]
def self.accessible_zones_sql(authority_id : String, subsystems : Array(String), user_id : String, required : Permissions) : String | Nil #

Returns a self-contained SQL subquery (single column: zone id) yielding every zone where the user's effective permissions within any of #subsystems satisfy required (Manage is a superset). The same rules as .resolve_subsystem_permissions apply, but only the per-row grant decisions are made in Crystal (bounded by the explicit GroupUser / GroupZone rows) — the zone-subtree expansion runs in the database via a recursive CTE, so the qualifying zone set is never materialised in application memory. Returns nil when the user holds no qualifying grants (callers should treat nil as an empty set).


[View source]
def self.add_remove_ad_groups(authority_id : String, user_id : String, ad_groups : Array(String)) : Nil #

Syncs a user's automatic group memberships with the AD groups they are currently a member of, within #authority_id:

  • the user is added to every group whose #ad_group_mappings contains one of ad_groups (unless they are already a member),
  • auto-assigned memberships (GroupUser#auto_assigned set) are removed when the user is no longer in a mapped AD group for that group, and updated when the mapping's permissions change.

Memberships added manually (auto_assigned nil) are never modified. When several of the user's AD groups map to the same group the permissions are combined and the lowest AD group id is recorded.


[View source]
def self.attributes : Array(Symbol) #

Returns all attribute keys.


def self.by_authority_id(id) #

[View source]
def self.by_parent_id(id) #

[View source]
def self.change_history(resource_id : String) #

Entries recorded for the resource, newest first


[View source]
def self.changefeed_ignored_update_columns : Array(String) | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.changes(id : UUID | Nil = nil) : ChangeFeed #

Changefeed at row (if #id passed) or whole table level. Returns a ChangeFeed instance which can be used to invoke async callbacks via on or use blocking Iterator via each method.


def self.effective_permissions(authority_id : String, subsystem : String, user_id : String, zone_id : String) : Permissions #

Effective permission bitmask for (user, zone) within subsystem.


[View source]
def self.effective_permissions(authority_id : String, subsystem : String, user_id : String, zone_ids : Array(String)) : Permissions #

Effective permissions across a batch of zones. For every zone, the closest applicable grant in that zone's own ancestry wins (replace semantics — same rule as the single-zone form). Results are OR'd across the list: this answers "what can the user do if any of these zones is in play?". Zones with no applicable grant contribute nothing. Returns Permissions::None for an empty list or for a user who can't reach any of the supplied zones.


[View source]
def self.from_rs(__temp_2555 : DB::ResultSet) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.history_ignored : Array(String) #

Fields not recorded, changes to only these fields are not recorded at all


[View source]
def self.history_redacted : Array(String) #

Fields whose values are never recorded


[View source]
def self.on_error(err : Exception | IO::Error) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.primary_key #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


[View source]
def self.resolve_subsystem_permissions(authority_id : String, subsystem : String, user_id : String) : Hash(String, Permissions) #

Full {zone_id => Permissions} map for the user within subsystem. Public entry point for callers that want to resolve once and cache the whole map (e.g. a per-request memo), instead of re-resolving per query.


[View source]
def self.table_name #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def self.zone_accessible?(authority_id : String, subsystem : String, user_id : String, zone_id : String) : Bool #

Does this user have any non-zero effective permission on this zone (directly or transitively) for subsystem?


[View source]

Instance Method Detail

def ad_group_mappings : Hash(String, Tuple(String, Int32)) #

def ad_group_mappings=(value : Hash(String, Tuple(String, Int32))) #

def ad_group_mappings? : Hash(String, Tuple(String, Int32)) | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def ad_group_mappings_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def ad_group_mappings_change : Tuple(Hash(String, Tuple(String, Int32)) | Nil, Hash(String, Tuple(String, Int32)) | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def ad_group_mappings_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def ad_group_mappings_default : Hash(String, Tuple(String, Int32)) #

#ad_group_mappings's default value


[View source]
def ad_group_mappings_present? : Bool #

AD group id => {display name, permissions bitmask}. Users who are members of a mapped AD group are added to this group by .add_remove_ad_groups. Keys are normalised (stripped + downcased) on save so matching is case-insensitive.


def ad_group_mappings_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def ad_group_mappings_was : Hash(String, Tuple(String, Int32)) | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def ad_group_mappings_will_change! : Nil #

Include #ad_group_mappings in the set of changed attributes, whether it has changed or not.


def after_create #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def after_destroy #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def after_initialize(trusted : Bool) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def after_save #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def after_update #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def apply_defaults #

Generate code to apply default values


def assign_attributes(created_at : Time | Missing = Missing, updated_at : Time | Missing = Missing, id : UUID | Missing = Missing, name : String | Missing = Missing, description : String | Missing = Missing, subsystems : Array(String) | Missing = Missing, default_permissions : Int32 | Missing = Missing, ad_group_mappings : Hash(String, Tuple(String, Int32)) | Missing = Missing, features : Hash(String, Hash(String, JSON::Any)) | Missing = Missing, authority_id : String | Missing = Missing, parent_id : UUID | Nil | Missing = Missing) #

Assign to multiple attributes.


def assign_attributes(params : HTTP::Params | Hash(String, String) | Tuple(String, String)) #

Assign to multiple attributes via HTTP::Params.


def assign_attributes(model : PlaceOS::Model::Group) #

Assign to multiple attributes from a model object


def assign_attributes_from_json(json, root : String) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def assign_attributes_from_json(json) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def assign_attributes_from_trusted_json(json, root : String) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def assign_attributes_from_trusted_json(json) #

Assign each field from JSON if field exists in JSON and has changed in model


def assign_attributes_from_trusted_yaml(yaml) #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def assign_attributes_from_yaml(yaml) #

Uses the YAML parser as JSON is valid YAML


def attributes #

Returns a Hash of all attribute values


def attributes_json(io : IO) : Nil #

Serialize attributes to JSON, without any other properties to_json may include, as .from_json expects them.

Values are serialized as in to_json, applying any attribute converters.


def attributes_json(json : JSON::Builder) : Nil #

Serialize attributes to JSON, without any other properties to_json may include, as .from_json expects them.

Values are serialized as in to_json, applying any attribute converters.


def attributes_json : String #

Serialize attributes to JSON, without any other properties to_json may include, as .from_json expects them.

Values are serialized as in to_json, applying any attribute converters.


def attributes_tuple #

Returns a NamedTuple of all attribute values.


def authority : PlaceOS::Model::Authority #

[View source]
def authority! : PlaceOS::Model::Authority #

[View source]

[View source]
def authority? : PlaceOS::Model::Authority | Nil #

[View source]
def authority_id : String #

#authority_id getter


def authority_id=(value : String) #

#authority_id setter


def authority_id? : String | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def authority_id_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def authority_id_change : Tuple(String | Nil, String | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def authority_id_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def authority_id_default : String #

#authority_id's default value


[View source]
def authority_id_present? : Bool #

def authority_id_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def authority_id_was : String | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def authority_id_will_change! : Nil #

Include #authority_id in the set of changed attributes, whether it has changed or not.


def before_create #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def before_destroy #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def before_save #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def before_update #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def build_authority(**attributes) : PlaceOS::Model::Authority #

[View source]
def build_parent(**attributes) : Group #

[View source]
def changed? #

Check if any attributes have changed.


def changed_attributes #

Returns a Hash with all changed attributes.


def changed_json(io : IO) : Nil #

Serialize the set of changed attributes to JSON.


def changed_json : String #

Serialize the set of changed attributes to JSON.


def changed_persist_attributes #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def changed_yaml(io : IO) : Nil #

Serialize the set of changed attributes to YAML.


def changed_yaml : String #

Serialize the set of changed attributes to YAML.


def changes #

Returns a Hash of changed attributes, mapping each to a {previous, current} tuple.


def changes_json(io : IO) : Nil #

Serialize changed attributes to JSON as {"attribute": [previous, current]}.

Values are serialized as in to_json, applying any attribute converters.


def changes_json(json : JSON::Builder) : Nil #

Serialize changed attributes to JSON as {"attribute": [previous, current]}.

Values are serialized as in to_json, applying any attribute converters.


def changes_json : String #

Serialize changed attributes to JSON as {"attribute": [previous, current]}.

Values are serialized as in to_json, applying any attribute converters.


def children #

Immediate children.


[View source]
def clear_changes_information #

Reset changes for all attributes.


def create_authority(**attributes) : PlaceOS::Model::Authority #

[View source]
def create_authority!(**attributes) : PlaceOS::Model::Authority #

[View source]
def create_parent(**attributes) : Group #

[View source]
def create_parent!(**attributes) : Group #

[View source]
def created_at : Time #

#created_at getter


def created_at=(value : Time) #

Setters #created_at setter


def created_at? : Time | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def created_at_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def created_at_change : Tuple(Time | Nil, Time | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def created_at_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def created_at_default : Time #

#created_at's default value


def created_at_present? : Bool #

def created_at_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def created_at_was : Time | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def created_at_will_change! : Nil #

Include #created_at in the set of changed attributes, whether it has changed or not.


def default_permissions : Int32 #

def default_permissions=(value : Int32) #

def default_permissions? : Int32 | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def default_permissions_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def default_permissions_change : Tuple(Int32 | Nil, Int32 | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def default_permissions_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def default_permissions_default : Int32 #

#default_permissions's default value


[View source]
def default_permissions_present? : Bool #

Stored as an Int32 bitmask. Use permission_flags / permission_flags= when working with the Permissions flags enum directly.


def default_permissions_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def default_permissions_was : Int32 | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def default_permissions_will_change! : Nil #

Include #default_permissions in the set of changed attributes, whether it has changed or not.


def descendant_ids : Array(UUID) #

All descendant group ids (including self) via a recursive CTE.


[View source]
def description : String #

#description getter


def description=(value : String) #

#description setter


def description? : String | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def description_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def description_change : Tuple(String | Nil, String | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def description_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def description_default : String #

#description's default value


[View source]
def description_present? : Bool #

def description_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def description_was : String | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def description_will_change! : Nil #

Include #description in the set of changed attributes, whether it has changed or not.


def effective_features(subsystem : String) : Hash(String, JSON::Any) #

Effective features for one subsystem ({} when nothing on the path sets it).


[View source]
def effective_features : Hash(String, Hash(String, JSON::Any)) #

Features merged down the tree from the root to this group: for each subsystem, key by key, the deepest group that sets a key wins (a child's list replaces its parent's rather than unioning with it). Uses this group's in-memory #features, so unsaved edits are reflected.


[View source]
def feature?(subsystem : String, key : String) : Bool #

Is key truthy in this group's effective subsystem features? Truthy: true, a non-zero number, or a non-empty string / array / object. Intended for server-side enforcement of features that matter beyond UI.


[View source]
def features : Hash(String, Hash(String, JSON::Any)) #

#features getter


def features=(value : Hash(String, Hash(String, JSON::Any))) #

#features setter


def features? : Hash(String, Hash(String, JSON::Any)) | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def features_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def features_change : Tuple(Hash(String, Hash(String, JSON::Any)) | Nil, Hash(String, Hash(String, JSON::Any)) | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def features_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def features_default : Hash(String, Hash(String, JSON::Any)) #

#features's default value


[View source]
def features_for(subsystem : String) : Hash(String, JSON::Any) #

This group's own features for subsystem, without inheritance.


[View source]
def features_present? : Bool #

Per-subsystem feature flags / display config, keyed by subsystem code: {"signage" => {"templates" => true, "plugins" => [...]}}. Keys inside a subsystem are opaque to the backend. Children inherit their ancestors' features and may override individual keys (see #effective_features).


def features_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def features_was : Hash(String, Hash(String, JSON::Any)) | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def features_will_change! : Nil #

Include #features in the set of changed attributes, whether it has changed or not.


def group_users #

Direct GroupUser rows for this group.


[View source]
def group_zones #

Direct GroupZone rows for this group.


[View source]
def history_action : String | Nil #

Overrides the action recorded by the next change, e.g. approve


def history_action=(history_action : String | Nil) #

Overrides the action recorded by the next change, e.g. approve


def history_correlation_id : String | Nil #
Description copied from module PlaceOS::Model::History::Tracked

A parent the change should also be found under


[View source]
def history_metadata : PlaceOS::Model::History::Metadata | Nil #

Request details recorded with changes to this record, defaults to History.current_metadata


def history_metadata=(history_metadata : PlaceOS::Model::History::Metadata | Nil) #

Request details recorded with changes to this record, defaults to History.current_metadata


def id : UUID #

#id getter


def id=(value : UUID) #

#id setter


def id? #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def id_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def id_change : Tuple(UUID | Nil, UUID | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def id_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def id_default : UUID #

#id's default value


def id_present? : Bool #

def id_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def id_was : UUID | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def id_will_change! : Nil #

Include #id in the set of changed attributes, whether it has changed or not.


def invoke_props #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def name : String #

#name getter


def name=(value : String) #

#name setter


def name? : String | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def name_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def name_change : Tuple(String | Nil, String | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def name_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def name_default : String #

#name's default value


[View source]
def name_present? : Bool #

def name_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def name_was : String | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def name_will_change! : Nil #

Include #name in the set of changed attributes, whether it has changed or not.


def parent : Group #

[View source]
def parent! : Group #

[View source]
def parent=(record : Group) : Group #

[View source]
def parent? : Group | Nil #

[View source]
def parent_id : UUID | Nil #

#parent_id getter


def parent_id=(value : UUID | Nil) #

#parent_id setter


def parent_id_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def parent_id_change : Tuple(UUID | Nil | Nil, UUID | Nil | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def parent_id_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def parent_id_default : UUID | Nil #

#parent_id's default value


[View source]
def parent_id_present? : Bool #

def parent_id_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def parent_id_was : UUID | Nil | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def parent_id_will_change! : Nil #

Include #parent_id in the set of changed attributes, whether it has changed or not.


def persistent_attributes #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def primary_key #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


[View source]
def primary_key_hash #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def reload_authority : PlaceOS::Model::Authority #

[View source]
def reload_authority? : PlaceOS::Model::Authority | Nil #

[View source]
def reload_parent : Group #

[View source]
def reload_parent? : Group | Nil #

[View source]
def restore_attributes #

Reset each attribute to their previous values and clears all changes.


def subsystems : Array(String) #

#subsystems getter


def subsystems=(value : Array(String)) #

#subsystems setter


def subsystems? : Array(String) | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def subsystems_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def subsystems_change : Tuple(Array(String) | Nil, Array(String) | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def subsystems_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def subsystems_default : Array(String) #

#subsystems's default value


[View source]
def subsystems_present? : Bool #

def subsystems_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def subsystems_was : Array(String) | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def subsystems_will_change! : Nil #

Include #subsystems in the set of changed attributes, whether it has changed or not.


def table_name #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def updated_at : Time #

#updated_at getter


def updated_at=(value : Time) #

#updated_at setter


def updated_at? : Time | Nil #

NOTE use getter / getter! (not property / property!) so that the setter defined later in __create_initializer__ is the only setter on the field. Crystal's overload resolution silently fails to replace a property-defined setter with one of identical signature for generic types (e.g. Set(String)?, Array(String)?, String | Array(String)), although it does work for non-generic ones like String?. Defining the setter only once via __create_initializer__ ensures change tracking, sanitization, and custom setter blocks run uniformly across all types.


def updated_at_assigned? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def updated_at_change : Tuple(Time | Nil, Time | Nil) | Nil #

Returns a Tuple of the previous and the current value of an instance variable if it has changed


def updated_at_changed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def updated_at_default : Time #

#updated_at's default value


def updated_at_present? : Bool #

def updated_at_removed? : Bool #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def updated_at_was : Time | Nil #

A node in the group tree for an authority. The tree represents the organisational hierarchy. Each group declares which subsystems (signage, events, parking, ...) it participates in via the #subsystems text array; subsystem-scoped permission queries are filtered against that array. An authority may have several root groups (#parent_id nil), each heading its own independent tree.


def updated_at_will_change! : Nil #

Include #updated_at in the set of changed attributes, whether it has changed or not.


def validate_nilability #

Validate that all non-nillable fields have values.