Class: Decidim::Api::Types::BaseObject

Inherits:
GraphQL::Schema::Object
  • Object
show all
Includes:
RequiredScopes
Defined in:
decidim-api/lib/decidim/api/types/base_object.rb

Direct Known Subclasses

Decidim::Accountability::MilestoneType, Decidim::Accountability::ResultType, Decidim::Accountability::StatusType, MutationType, QueryType, Decidim::Assemblies::AssemblyType, Blogs::PostType, Budgets::BudgetType, Budgets::ProjectType, CollaborativeTexts::DocumentType, CollaborativeTexts::SuggestionType, CollaborativeTexts::VersionType, Comments::AddCommentType, Comments::CommentMutationType, Comments::CommentType, Comments::CommentableMutationType, Comments::CommentableType, Conferences::ConferenceMediaLinkType, Conferences::ConferencePartnerType, Conferences::ConferenceRegistrationTypeType, Conferences::ConferenceSpeakerType, Conferences::ConferenceType, Core::AmendmentType, Core::AreaApiType, Core::AreaTypeType, Core::AttachmentCollectionType, Core::AttachmentType, Core::CategoryType, Core::ComponentType, Core::CoordinatesType, Core::DecidimType, Core::FingerprintType, Core::LocalizedStringType, Core::OrganizationType, Core::ParticipatorySpaceLinkType, Core::ParticipatorySpaceManifestType, Core::ParticipatorySpaceType, Core::QuantifiableTranslatedFieldType, Core::ScopeApiType, Core::SessionType, Core::StatisticType, Core::TaxonomyType, Core::TraceVersionType, Core::TranslatedFieldType, Core::UserType, Debates::DebateType, Forms::QuestionMatrixRowType, Forms::QuestionType, Forms::QuestionnaireType, Forms::ResponseOptionType, Initiatives::InitiativeApiType, Initiatives::InitiativeCommitteeMemberType, Initiatives::InitiativeType, Meetings::AgendaItemType, Meetings::AgendaType, Meetings::MeetingType, Meetings::ServiceType, Pages::PageType, ParticipatoryProcesses::ParticipatoryProcessGroupType, ParticipatoryProcesses::ParticipatoryProcessStepType, ParticipatoryProcesses::ParticipatoryProcessType, ParticipatoryProcesses::ParticipatoryProcessTypeType, Proposals::ProposalMutationType, Proposals::ProposalStateType, Proposals::ProposalType, Sortitions::SortitionType, Surveys::SurveyType

Class Method Summary collapse

Class Method Details

.allowed_to?(action, subject, object, context, scope: :public) ⇒ Boolean

This is a simplified adaptation of allowed_to? from NeedsPermission concern



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'decidim-api/lib/decidim/api/types/base_object.rb', line 38

def self.allowed_to?(action, subject, object, context, scope: :public)
  unless subject.is_a?(::Symbol)
    subject = determine_subject_name(object)
    context[subject] = object
  end

  permission_action = Decidim::PermissionAction.new(scope:, action:, subject:)

  permission_chain(object).inject(permission_action) do |current_permission_action, permission_class|
    permission_context =
      if scope == :admin
        local_admin_context(object, context)
      else
        local_context(object, context)
      end

    permission_class.new(
      context[:current_user],
      current_permission_action,
      permission_context
    ).permissions
  end.allowed?
end

.authorized?(object, context) ⇒ Boolean



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'decidim-api/lib/decidim/api/types/base_object.rb', line 13

def self.authorized?(object, context)
  return false unless scope_authorized?(context)

  chain = []

  subject = determine_subject_name(object)
  context[subject] = object

  chain.unshift(allowed_to?(:read, :participatory_space, object, context)) if object.respond_to?(:participatory_space)
  chain.unshift(allowed_to?(:read, :component, object, context)) if object.respond_to?(:component) && object.component.present?

  super && chain.all?
end

.determine_subject_name(object) ⇒ Object



27
28
29
# File 'decidim-api/lib/decidim/api/types/base_object.rb', line 27

def self.determine_subject_name(object)
  object.class.name.split("::").last.underscore.to_sym
end

.local_admin_context(object, context) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'decidim-api/lib/decidim/api/types/base_object.rb', line 80

def self.local_admin_context(object, context)
  context = local_context(object, context)

  component = context[:current_component]
  return context unless component
  return context unless component.respond_to?(:current_settings)
  return context unless component.respond_to?(:settings)
  return context unless component.respond_to?(:organization)

  context[:current_settings] = component.current_settings
  context[:component_settings] = component.settings
  context[:current_organization] = component.organization

  context
end

.local_context(object, context) ⇒ Object

Injects into context object current_participatory_space and current_component keys as they are needed



68
69
70
71
72
73
74
75
76
77
78
# File 'decidim-api/lib/decidim/api/types/base_object.rb', line 68

def self.local_context(object, context)
  context[:current_participatory_space] = object.participatory_space if object.respond_to?(:participatory_space)
  context[:current_component] =
    if object.is_a?(Decidim::Component)
      object
    elsif object.respond_to?(:component)
      object.component
    end

  context.to_h
end

.permission_chain(object) ⇒ Decidim::DefaultPermissions

Creates the permission chain arrau that contains all the permission classes required to authorize a certain resource We are using unshift as we need the Admin and base permissions to be last in the chain



101
102
103
104
105
106
107
108
109
110
111
# File 'decidim-api/lib/decidim/api/types/base_object.rb', line 101

def self.permission_chain(object)
  permissions = [
    Decidim::Admin::Permissions,
    Decidim::Permissions
  ]

  permissions.unshift(object.participatory_space.manifest.permissions_class) if object.respond_to?(:participatory_space)
  permissions.unshift(object.component.manifest.permissions_class) if object.respond_to?(:component) && object.component.present?

  permissions
end