diff --git a/resources/goldens/schema.graphql b/resources/goldens/schema.graphql index 8f03c4a..884d396 100644 --- a/resources/goldens/schema.graphql +++ b/resources/goldens/schema.graphql @@ -12,91 +12,91 @@ interface Attribute { } #generated, do not edit manually! -type StringAttribute implements Attribute { +type StringAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! string: String! } #generated, do not edit manually! -type BooleanAttribute implements Attribute { +type BooleanAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! boolean: Boolean! } #generated, do not edit manually! -type ReferenceAttribute implements Attribute { +type ReferenceAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! ref: ID! } #generated, do not edit manually! -type FloatAttribute implements Attribute { +type FloatAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! float: Float! } #generated, do not edit manually! -type DateTimeAttribute implements Attribute { +type DateTimeAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! dateTime: AWSDateTime! } #generated, do not edit manually! -type TupleAttribute implements Attribute { +type TupleAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! tuple: AWSJSON! } #generated, do not edit manually! -type MultiStringAttribute implements Attribute { +type MultiStringAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! strings: [String!]! } #generated, do not edit manually! -type MultiBooleanAttribute implements Attribute { +type MultiBooleanAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! booleans: [Boolean!]! } #generated, do not edit manually! -type MultiReferenceAttribute implements Attribute { +type MultiReferenceAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! refs: [ID!]! } #generated, do not edit manually! -type MultiFloatAttribute implements Attribute { +type MultiFloatAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! floats: [Float!]! } #generated, do not edit manually! -type MultiDateTimeAttribute implements Attribute { +type MultiDateTimeAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! dateTimes: [AWSDateTime!]! } #generated, do not edit manually! -type MultiTupleAttribute implements Attribute { +type MultiTupleAttribute implements Attribute @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! name: String! tuples: [AWSJSON!]! } #generated, do not edit manually! -type PageInfo { +type PageInfo @aws_cognito_user_pools(cognito_groups: ["Users"]) { size: Int! first: Int! prev: Int @@ -119,19 +119,38 @@ input EntityFilter { #generated, do not edit manually! type Query { getEntity(id: ID!): Entity + @aws_cognito_user_pools(cognito_groups: ["Admins"]) + listEntity(page: PageQuery, filter: EntityFilter): EntityListPage! + @aws_cognito_user_pools(cognito_groups: ["Admins"]) + getBreakdown(id: ID!): Breakdown + @aws_cognito_user_pools(cognito_groups: ["Users"]) + getDataPoint(id: ID!): DataPoint + @aws_cognito_user_pools(cognito_groups: ["Users"]) + getPlanetaryBoundary(id: ID!): PlanetaryBoundary + @aws_cognito_user_pools(cognito_groups: ["Users"]) + getQuantification(id: ID!): Quantification + @aws_cognito_user_pools(cognito_groups: ["Users"]) + listBreakdown(page: PageQuery): BreakdownListPage! + @aws_cognito_user_pools(cognito_groups: ["Users"]) + listDataPoint(page: PageQuery): DataPointListPage! + @aws_cognito_user_pools(cognito_groups: ["Users"]) + listPlanetaryBoundary(page: PageQuery): PlanetaryBoundaryListPage! + @aws_cognito_user_pools(cognito_groups: ["Users"]) + listQuantification(page: PageQuery): QuantificationListPage! + @aws_cognito_user_pools(cognito_groups: ["Users"]) } #generated, do not edit manually! -type Entity { +type Entity @aws_cognito_user_pools(cognito_groups: ["Admins"]) { id: ID! attributes: [Attribute!]! } @@ -142,14 +161,14 @@ interface EntityBase { } #generated, do not edit manually! -type Breakdown implements EntityBase { +type Breakdown implements EntityBase @aws_cognito_user_pools(cognito_groups: ["Users"]) { id: ID! components: [DataPoint!] parent: DataPoint } #generated, do not edit manually! -type DataPoint implements EntityBase { +type DataPoint implements EntityBase @aws_cognito_user_pools(cognito_groups: ["Users"]) { id: ID! breakdowns: [Breakdown!] compositions: [Breakdown!] @@ -158,7 +177,7 @@ type DataPoint implements EntityBase { } #generated, do not edit manually! -type PlanetaryBoundary implements EntityBase { +type PlanetaryBoundary implements EntityBase @aws_cognito_user_pools(cognito_groups: ["Users"]) { id: ID! description: String name: String @@ -166,7 +185,7 @@ type PlanetaryBoundary implements EntityBase { } #generated, do not edit manually! -type Quantification implements EntityBase { +type Quantification implements EntityBase @aws_cognito_user_pools(cognito_groups: ["Users"]) { id: ID! dataPoints: [DataPoint!] name: String @@ -174,31 +193,31 @@ type Quantification implements EntityBase { } #generated, do not edit manually! -type EntityListPage { +type EntityListPage @aws_cognito_user_pools(cognito_groups: ["Admins"]) { info: PageInfo! values: [Entity!]! } #generated, do not edit manually! -type BreakdownListPage { +type BreakdownListPage @aws_cognito_user_pools(cognito_groups: ["Users"]) { info: PageInfo! values: [Breakdown!]! } #generated, do not edit manually! -type DataPointListPage { +type DataPointListPage @aws_cognito_user_pools(cognito_groups: ["Users"]) { info: PageInfo! values: [DataPoint!]! } #generated, do not edit manually! -type PlanetaryBoundaryListPage { +type PlanetaryBoundaryListPage @aws_cognito_user_pools(cognito_groups: ["Users"]) { info: PageInfo! values: [PlanetaryBoundary!]! } #generated, do not edit manually! -type QuantificationListPage { +type QuantificationListPage @aws_cognito_user_pools(cognito_groups: ["Users"]) { info: PageInfo! values: [Quantification!]! } @@ -238,29 +257,64 @@ input QuantificationInput { #generated, do not edit manually! type Mutation { publishCreatedBreakdown(value: BreakdownInput!): Breakdown + publishCreatedDataPoint(value: DataPointInput!): DataPoint + publishCreatedPlanetaryBoundary(value: PlanetaryBoundaryInput!): PlanetaryBoundary + publishCreatedQuantification(value: QuantificationInput!): Quantification + publishUpdatedBreakdown(value: BreakdownInput!): Breakdown + publishUpdatedDataPoint(value: DataPointInput!): DataPoint + publishUpdatedPlanetaryBoundary(value: PlanetaryBoundaryInput!): PlanetaryBoundary + publishUpdatedQuantification(value: QuantificationInput!): Quantification + publishDeletedBreakdown(value: BreakdownInput!): Breakdown + publishDeletedDataPoint(value: DataPointInput!): DataPoint + publishDeletedPlanetaryBoundary(value: PlanetaryBoundaryInput!): PlanetaryBoundary + publishDeletedQuantification(value: QuantificationInput!): Quantification + createBreakdown(value: BreakdownInput!): Breakdown! + @aws_cognito_user_pools(cognito_groups: ["Users"]) + createDataPoint(value: DataPointInput!): DataPoint! + @aws_cognito_user_pools(cognito_groups: ["Users"]) + createPlanetaryBoundary(value: PlanetaryBoundaryInput!): PlanetaryBoundary! + @aws_cognito_user_pools(cognito_groups: ["Users"]) + createQuantification(value: QuantificationInput!): Quantification! + @aws_cognito_user_pools(cognito_groups: ["Users"]) + mergeBreakdown(value: BreakdownInput!): Breakdown + @aws_cognito_user_pools(cognito_groups: ["Users"]) + mergeDataPoint(value: DataPointInput!): DataPoint + @aws_cognito_user_pools(cognito_groups: ["Users"]) + mergePlanetaryBoundary(value: PlanetaryBoundaryInput!): PlanetaryBoundary + @aws_cognito_user_pools(cognito_groups: ["Users"]) + mergeQuantification(value: QuantificationInput!): Quantification + @aws_cognito_user_pools(cognito_groups: ["Users"]) + deleteBreakdown(id: ID!): Breakdown + @aws_cognito_user_pools(cognito_groups: ["Users"]) + deleteDataPoint(id: ID!): DataPoint + @aws_cognito_user_pools(cognito_groups: ["Users"]) + deletePlanetaryBoundary(id: ID!): PlanetaryBoundary + @aws_cognito_user_pools(cognito_groups: ["Users"]) + deleteQuantification(id: ID!): Quantification + @aws_cognito_user_pools(cognito_groups: ["Users"]) } #generated, do not edit manually! diff --git a/src/graphql/directives.clj b/src/graphql/directives.clj new file mode 100644 index 0000000..93c5c09 --- /dev/null +++ b/src/graphql/directives.clj @@ -0,0 +1,12 @@ +(ns graphql.directives) + +(def user-access + {:name :aws_cognito_user_pools + :arguments [{:name :cognito_groups + :value ["Users"]}]}) + +; are also user, so don't need to be part in the user access description +(def admin-access + {:name :aws_cognito_user_pools + :arguments [{:name :cognito_groups + :value ["Admins"]}]}) diff --git a/src/graphql/fields.clj b/src/graphql/fields.clj index ca8a9be..e5c69b3 100644 --- a/src/graphql/fields.clj +++ b/src/graphql/fields.clj @@ -6,14 +6,14 @@ (def required-id arguments/required-id) -(defn get-query [field-name entity] - {:name field-name - :arguments [arguments/required-id] - :type (name entity)}) +(defn get-query [field-name entity directives] + {:name field-name + :arguments [arguments/required-id] + :type (name entity) + :directives directives}) (defn list-page-query - ([field-name entity] (list-page-query field-name entity nil)) - ([field-name entity filter-type] + ([field-name entity filter-type directives] {:name field-name :arguments (concat [{:name :page @@ -22,7 +22,8 @@ [{:name :filter :type filter-type}])) :type (types/list-page-type entity) - :required-type? true})) + :required-type? true + :directives directives})) (defn publish-mutation [field-name entity-name] {:name field-name diff --git a/src/graphql/objects.clj b/src/graphql/objects.clj index 2351432..be4b881 100644 --- a/src/graphql/objects.clj +++ b/src/graphql/objects.clj @@ -2,13 +2,14 @@ (:require [graphql.types :as types])) -(defn list-page [entity] - {:name (types/list-page-type entity) - :fields [{:name :info - :type types/page-info-type - :required-type? true} - {:name :values - :type entity - :list? true - :required-type? true - :required-list? true}]}) \ No newline at end of file +(defn list-page [entity directives] + {:name (types/list-page-type entity) + :directives directives + :fields [{:name :info + :type types/page-info-type + :required-type? true} + {:name :values + :type entity + :list? true + :required-type? true + :required-list? true}]}) diff --git a/src/graphql/schema.clj b/src/graphql/schema.clj index 4af160f..2cb4386 100644 --- a/src/graphql/schema.clj +++ b/src/graphql/schema.clj @@ -3,6 +3,7 @@ [clojure.string :as s] [datomic.client.api :as d] [datomic.framework :as framework] + [graphql.directives :as directives] [graphql.fields :as fields] [graphql.objects :as objects] [graphql.spec :as spec] @@ -18,6 +19,7 @@ #(spec/object-type-definition {:name (:graphql/single-value-type-name %) :interfaces [types/attribute-type] + :directives [directives/admin-access] :fields (conj attribute-fields {:name (:graphql/single-value-field-name %) @@ -29,6 +31,7 @@ #(spec/object-type-definition {:name (:graphql/multi-value-type-name %) :interfaces [types/attribute-type] + :directives [directives/admin-access] :fields (conj attribute-fields {:name (:graphql/multi-value-field-name %) @@ -113,23 +116,24 @@ :fields attribute-fields}) (generate-attribute-subtypes attribute-fields) (spec/object-type-definition - {:name types/page-info-type - :fields [{:name :size - :type types/int-type - :required-type? true} - {:name :first - :type types/int-type - :required-type? true} - {:name :prev - :type types/int-type} - {:name :current - :type types/int-type - :required-type? true} - {:name :next - :type types/int-type} - {:name :last - :type types/int-type - :required-type? true}]}) + {:name types/page-info-type + :directives [directives/user-access] + :fields [{:name :size + :type types/int-type + :required-type? true} + {:name :first + :type types/int-type + :required-type? true} + {:name :prev + :type types/int-type} + {:name :current + :type types/int-type + :required-type? true} + {:name :next + :type types/int-type} + {:name :last + :type types/int-type + :required-type? true}]}) ; entity framework & dynamic schema: query inputs (spec/input-object-type-definition {:name types/page-query-type @@ -141,26 +145,36 @@ :value 20}]}) ; TODO generate filters for dynamic types (spec/input-object-type-definition - {:name entity-filter-type - :fields [{:name :attributes - :type types/id-type - :list? true - :required-type? true}]}) + {:name entity-filter-type + :directives [directives/admin-access] + :fields [{:name :attributes + :type types/id-type + :list? true + :required-type? true}]}) ;; entity framework & dynamic schema: query results (spec/object-type-definition - {:name types/query-type - :fields (concat - [(fields/get-query (str "get" (name types/entity-type)) types/entity-type) - (fields/list-page-query (str "list" (name types/entity-type)) types/entity-type entity-filter-type)] - query-fields)}) + {:name types/query-type + :spaced-fields? true + :fields (concat + [(fields/get-query + (str "get" (name types/entity-type)) + types/entity-type + [directives/admin-access]) + (fields/list-page-query + (str "list" (name types/entity-type)) + types/entity-type + entity-filter-type + [directives/admin-access])] + query-fields)}) (spec/object-type-definition - {:name types/entity-type - :fields [fields/required-id - {:name :attributes - :type types/attribute-type - :list? true - :required-type? true - :required-list? true}]}) + {:name types/entity-type + :directives [directives/admin-access] + :fields [fields/required-id + {:name :attributes + :type types/attribute-type + :list? true + :required-type? true + :required-list? true}]}) (spec/interface-type-definition {:name types/entity-base-type :fields [fields/required-id]}) @@ -170,9 +184,10 @@ (spec/object-type-definition {:name entity-type :interfaces [types/entity-base-type] + :directives [directives/user-access] :fields (gen-entity-fields fields false)}))) (spec/object-type-definition - (objects/list-page types/entity-type)) + (objects/list-page types/entity-type [directives/admin-access])) (s/join (for [op ops/all-operations entity-type (keys dynamic-schema-types) @@ -187,8 +202,9 @@ :fields (gen-entity-fields fields true)}))) (when mutation-fields (spec/object-type-definition - {:name types/mutation-type - :fields mutation-fields})) + {:name types/mutation-type + :spaced-fields? true + :fields mutation-fields})) (when subscription-fields (spec/object-type-definition {:name types/subscription-type diff --git a/src/shared/operations.clj b/src/shared/operations.clj index 069e2d7..1b0029b 100644 --- a/src/shared/operations.clj +++ b/src/shared/operations.clj @@ -8,6 +8,7 @@ [datomic.framework :as framework] [datomic.queries :as queries] [graphql.arguments :as arguments] + [graphql.directives :as directives] [graphql.fields :as fields] [graphql.objects :as objects] [graphql.parsing :as parsing] @@ -103,6 +104,8 @@ (defn extract-entity-type [op field-name] (str/replace (name field-name) (::prefix op) "")) +; should return data that the field generation can handle: +#_graphql.spec/field-definition (defn gen-graphql-field [op entity-type fields] (let [{:keys [shared.operations/prefix]} op field-name (gen-field-name op entity-type)] @@ -110,18 +113,21 @@ "publishCreated" (fields/publish-mutation field-name entity-type) "publishUpdated" (fields/publish-mutation field-name entity-type) "publishDeleted" (fields/publish-mutation field-name entity-type) - "get" (fields/get-query field-name entity-type) - "list" (fields/list-page-query field-name entity-type) + "get" (fields/get-query field-name entity-type [directives/user-access]) + "list" (fields/list-page-query field-name entity-type nil [directives/user-access]) "create" {:name field-name :arguments [(arguments/required-input-value entity-type)] :type entity-type - :required-type? true} - "merge" {:name field-name - :arguments [(arguments/required-input-value entity-type)] - :type entity-type} - "delete" {:name field-name - :arguments [arguments/required-id] - :type entity-type} + :required-type? true + :directives [directives/user-access]} + "merge" {:name field-name + :arguments [(arguments/required-input-value entity-type)] + :type entity-type + :directives [directives/user-access]} + "delete" {:name field-name + :arguments [arguments/required-id] + :type entity-type + :directives [directives/user-access]} "onCreated" (fields/subscription field-name entity-type fields (gen-field-name publish-created-op entity-type)) "onUpdated" (fields/subscription field-name entity-type fields (gen-field-name publish-updated-op entity-type)) "onDeleted" (fields/subscription field-name entity-type fields (gen-field-name publish-deleted-op entity-type))))) @@ -129,7 +135,7 @@ (defn gen-graphql-object-types [op entity-type] (let [{:keys [shared.operations/prefix]} op] (case prefix - "list" [(objects/list-page entity-type)] + "list" [(objects/list-page entity-type [directives/user-access])] nil))) (defn- convert-to-input [entity paths]