diff --git a/project.clj b/project.clj index 595fcd6..5b79ce4 100644 --- a/project.clj +++ b/project.clj @@ -5,6 +5,7 @@ :dependencies [;;clojure core [org.clojure/clojure "1.10.1"] + [org.clojure/tools.logging "0.4.1"] ;; static site [compojure "1.6.1"] diff --git a/src/wanijo/attribute/domain.clj b/src/wanijo/attribute/domain.clj index 1a21dac..10cd386 100644 --- a/src/wanijo/attribute/domain.clj +++ b/src/wanijo/attribute/domain.clj @@ -14,6 +14,11 @@ (spec/def ::created-at (spec/and string? ::neo4j/date-str)) +(spec/def ::attribute + (spec/keys ::req-un [::name + ::type + ::created-at])) + (neo4j/defquery findy-by-schema "MATCH (a:attribute)-->(s:schema) diff --git a/src/wanijo/handler.clj b/src/wanijo/handler.clj index 2af6139..b50ac47 100644 --- a/src/wanijo/handler.clj +++ b/src/wanijo/handler.clj @@ -7,6 +7,7 @@ [ring.util.response :as rur] [ring.middleware.session.cookie :as session-cookie] [ring.middleware.json :as ring-json] + [clojure.spec.alpha :as spec] [wanijo.home.routes :as home-routes] [wanijo.schema [routes :as schema-routes] @@ -43,8 +44,14 @@ schema-middleware/wrap-user-schemas (wrap-defaults site-defaults))) +(defn wrap-spec-asserts [handler] + (fn [req] + (spec/check-asserts true) + (handler req))) + (def app (-> app-routes + wrap-spec-asserts devmode/wrap-devmode schema-middleware/wrap-user-schemas ring-json/wrap-json-response diff --git a/src/wanijo/instance/domain.clj b/src/wanijo/instance/domain.clj index 95b9e09..d8bf6a6 100644 --- a/src/wanijo/instance/domain.clj +++ b/src/wanijo/instance/domain.clj @@ -1,11 +1,14 @@ (ns wanijo.instance.domain (:require [clojure.spec.alpha :as spec] [wanijo.framework.neo4j :as neo4j] - [clojure.pprint :as pprint])) + [wanijo.schema.domain :as domain-schema] + [wanijo.attribute.domain :as domain-attr])) (spec/def ::created-at ::neo4j/date-str) +(spec/def ::created_at ::neo4j/date-str) (spec/def ::updated-at ::neo4j/date-str) -(spec/def ::name (spec/and (complement empty?) string?)) +(spec/def ::updated_at ::neo4j/date-str) +(spec/def ::name string?) (spec/def ::value (spec/or :string string? :bool boolean? @@ -13,6 +16,38 @@ :number number?)) (spec/def ::instance_uuid ::neo4j/uuid) (spec/def ::attribute_uuid ::neo4j/uuid) +(spec/def ::instance + (spec/keys :req-un [::neo4j/uuid + ::created_at + ::updated_at + ::name])) +(spec/def ::properties + (spec/coll-of + (spec/keys :req-un [::neo4j/uuid + ::created_at + ::updated_at + ::domain-attr/attribute]))) +(spec/def ::link + (spec/keys :req-un [::neo4j/uuid + ::created_at + ::name])) +(spec/def ::target ::instance) +(spec/def ::source ::instance) +(spec/def ::links-out + (spec/coll-of + (spec/keys :req-un [::link + ::target + ::domain-schema/schema]))) +(spec/def ::links-in + (spec/coll-of + (spec/keys :req-un [::link + ::source + ::domain-schema/schema]))) +(spec/def ::tags + (spec/coll-of + (spec/keys :req-un [::neo4j/uuid + ::name + ::created-at]))) (neo4j/defquery findy-by-schema "MATCH (i:instance)-[:of]->(s:schema) @@ -70,7 +105,13 @@ -[:of]->(s:schema) RETURN i, s") +(spec/def ::instance-with-schema + (spec/and ::instance + (spec/keys :req-un + [::domain-schema/schema]))) + (defn find-by-uuid! [uuid] + {:post [(spec/assert ::instance-with-schema %)]} (->> (neo4j/exec-query! find-by-uuid {:uuid uuid}) (map #(assoc (:i %) @@ -96,7 +137,6 @@ "MATCH (i:instance {uuid:{uuid}}) SET i.name = {name}, i.updated_at = {updated_at}") - (neo4j/defquery edit-property "MATCH (i:instance {uuid:{instance_uuid}}), (a:attribute {uuid:{attribute_uuid}}) @@ -107,7 +147,6 @@ p.value = {value} ON MATCH SET p.updated_at = {now}, p.value = {value}") - (spec/def ::now ::neo4j/date-str) (spec/def ::prop-tuple-values (spec/keys :req-un [::neo4j/uuid @@ -118,7 +157,6 @@ (spec/def ::prop-tuple (spec/coll-of (spec/tuple fn? ::prop-tuple-values))) - (defn instance->prop-tuples [instance] {:post [(spec/assert ::prop-tuple %)]} (map (fn [prop] @@ -133,7 +171,6 @@ :instance_uuid (:uuid instance) :attribute_uuid (-> prop :attribute :uuid)}])) (:properties instance))) - (defn edit! [instance] (let [prop-tuples (instance->prop-tuples instance)] (apply neo4j/exec-queries! @@ -151,7 +188,6 @@ (p:property)-[pc:of]->(i), (p)-[pac:of]->(a:attribute) DELETE pac, pc, cb, ic, p, i") - (defn delete! [uuid] (neo4j/exec-query! delete {:uuid uuid})) @@ -163,7 +199,6 @@ SET l.created_at = {created_at}, l.name = {name} CREATE (i)<-[:link_from]-(l)-[:link_to]->(t)") - (defn create-link! [link] (let [tuples (map (fn [target-uuid] [create-link @@ -183,8 +218,8 @@ (t)-[:of]->(s:schema) RETURN i, l, t, s ORDER BY s.name, t.name, t.created_at") - (defn outgoing-links! [uuid] + {:post [(spec/assert ::links-out %)]} (map (fn [row] {:link (:l row) :target (:t row) @@ -199,8 +234,8 @@ (source)-[:of]->(schema:schema) RETURN i, l, source, schema ORDER BY schema.name, source.name, source.created_at") - (defn incoming-links! [uuid] + {:post [(spec/assert ::links-in %)]} (map (fn [row] {:link (:l row) :source (:source row) @@ -212,7 +247,6 @@ "MATCH (l:link {uuid:{uuid}}), (l)-[r]-() DELETE r, l") - (defn delete-link! [uuid] (neo4j/exec-query! delete-link {:uuid uuid})) @@ -221,12 +255,23 @@ "MATCH (i:instance {uuid:{uuid}})-[:has]->(t:tag) RETURN t ORDER BY t.name") - (defn tags! [uuid] + {:post [(spec/assert ::tags %)]} (neo4j/exec-query! tags {:uuid uuid})) +(spec/def ::full-instance + (spec/and ::instance-with-schema + (spec/keys ::req-un [::neo4j/uuid + ::created-at + ::updated-at + ::name + ::properties + ::links-out + ::links-in + ::tags]))) (defn full-instance-by-uuid! [uuid] + {:post [(spec/assert ::full-instance %)]} (assoc (find-by-uuid! uuid) :properties (find-properties! uuid) @@ -241,7 +286,6 @@ "MATCH (u:user {uuid:{user_uuid}}), (i:instance {uuid:{uuid}}) RETURN EXISTS((i)-[:starred_by]->(u)) AS starred") - (defn is-starred! [uuid user-uuid] (-> (neo4j/exec-query! is-starred {:user_uuid user-uuid @@ -255,7 +299,6 @@ MERGE (i)-[s:starred_by]->(u) ON CREATE SET s.created_at = {now}") - (defn mark-starred! [uuid user-uuid] (neo4j/exec-query! mark-starred {:uuid uuid @@ -267,7 +310,6 @@ -[s:starred_by]-> (:user {uuid:{user_uuid}}) DELETE s") - (defn remove-starred! [uuid user-uuid] (neo4j/exec-query! remove-starred {:uuid uuid @@ -279,7 +321,6 @@ (i:instance) RETURN i, s ORDER BY s.created_at DESC") - (defn starred-by-user! [user-uuid] (map #(assoc (:i %) :starred_at (-> % :s :created_at)) diff --git a/src/wanijo/main.clj b/src/wanijo/main.clj index e3ec709..1c3e5d3 100644 --- a/src/wanijo/main.clj +++ b/src/wanijo/main.clj @@ -1,11 +1,8 @@ (ns wanijo.main (:require [ring.adapter.jetty :refer [run-jetty]] - [clojure.spec.alpha :as spec] - [wanijo.handler :as wanijo]) + [wanijo.handler :as wanijo-handler]) (:gen-class)) -(spec/check-asserts true) - (defonce server (atom nil)) (defn start-server! @@ -14,7 +11,7 @@ :or {port 3080 join? true}}] (reset! server - (run-jetty wanijo/standalone-app + (run-jetty wanijo-handler/standalone-app {:port port :join? join?}))) diff --git a/src/wanijo/schema/domain.clj b/src/wanijo/schema/domain.clj index 00981d3..4944c77 100644 --- a/src/wanijo/schema/domain.clj +++ b/src/wanijo/schema/domain.clj @@ -4,17 +4,18 @@ (spec/def ::name (spec/and string? not-empty)) - (spec/def ::created-at (spec/and string? ::neo4j/date-str)) - (spec/def ::assigned-to (spec/or :public empty? :assigned-single ::neo4j/uuid :assigned (spec/coll-of ::neo4j/uuid))) +(spec/def ::schema + (spec/keys ::req-un [::name + ::created-at + ::neo4j/uuid])) -(neo4j/defquery - all-created-by +(neo4j/defquery all-created-by "MATCH (s:schema)-[:created_by]->(u:user) WHERE u.uuid = {uuid} RETURN s @@ -26,8 +27,7 @@ all-created-by {:uuid user-uuid}))) -(neo4j/defquery - all +(neo4j/defquery all "MATCH (s:schema) RETURN s ORDER BY s.name") @@ -36,8 +36,7 @@ (map :s (neo4j/exec-query! all {}))) -(neo4j/defquery - create-new +(neo4j/defquery create-new "MATCH (u:user) WHERE u.uuid = {u_uuid} CREATE (s:schema)-[:created_by]->(u) @@ -57,8 +56,7 @@ first :uuid)) -(neo4j/defquery - find-by-uuid +(neo4j/defquery find-by-uuid "MATCH (s:schema) WHERE s.uuid = {uuid} RETURN s") @@ -71,8 +69,7 @@ first :s)) -(neo4j/defquery - schema-creator +(neo4j/defquery schema-creator "MATCH (s:schema)-->(u:user) WHERE s.uuid = {uuid} RETURN u.uuid as uuid") @@ -85,8 +82,7 @@ first :uuid)) -(neo4j/defquery - schema-permissions +(neo4j/defquery schema-permissions "MATCH (s:schema {uuid:{schema_uuid}}) RETURN EXISTS((:user {uuid:{user_uuid}}) @@ -111,8 +107,7 @@ (defn has-user-read-permissions? [schema-uuid user-uuid] (has-user-permission? "read" schema-uuid user-uuid)) -(neo4j/defquery - accessible-schemas +(neo4j/defquery accessible-schemas "MATCH (s:schema), (u:user {uuid:{user_uuid}}) WHERE EXISTS((u)-[:permission {type:'read'}]->(s)) @@ -125,8 +120,7 @@ (neo4j/exec-query! accessible-schemas {:user_uuid user-uuid}))) -(neo4j/defquery - delete +(neo4j/defquery delete "MATCH (s:schema) WHERE s.uuid = {uuid} OPTIONAL MATCH (s)--(a:attribute) @@ -140,8 +134,7 @@ delete {:uuid uuid})) -(neo4j/defquery - edit +(neo4j/defquery edit "MATCH (s:schema) WHERE s.uuid = {uuid} SET s.name = {name}") @@ -151,8 +144,7 @@ edit schema)) -(neo4j/defquery - assigned-users +(neo4j/defquery assigned-users "MATCH (s:schema)-[p:permission]-(u:user) WHERE s.uuid = {uuid} RETURN u, p @@ -163,8 +155,7 @@ assigned-users {:uuid uuid})) -(neo4j/defquery - assigned-schemas +(neo4j/defquery assigned-schemas "MATCH (s1:schema)-[p:permission]-(s2:schema) WHERE s1.uuid = {uuid} RETURN s2 @@ -189,15 +180,13 @@ :assigned-write-users (:write users) :assigned-schemas schemas))) -(neo4j/defquery - remove-assignments +(neo4j/defquery remove-assignments "MATCH (s:schema)-[c:permission]-(:user) WHERE s.uuid = {uuid} AND c.type = {permtype} DELETE c") -(neo4j/defquery - create-assignments +(neo4j/defquery create-assignments "MATCH (s:schema), (u:user) WHERE s.uuid = {uuid} AND u.uuid IN {users} @@ -213,14 +202,12 @@ :users users :permtype permission}])) -(neo4j/defquery - remove-schema-assignments +(neo4j/defquery remove-schema-assignments "MATCH (s1:schema)-[p:permission]-(s2:schema) WHERE s1.uuid = {uuid} DELETE p") -(neo4j/defquery - create-schema-assignments +(neo4j/defquery create-schema-assignments "MATCH (s1:schema), (s2:schema) WHERE s1.uuid = {uuid} AND s2.uuid IN {schemas}