(ns auto-ap.graphql.utils (:require [clojure.string :as str] [auto-ap.datomic :refer [conn]] [clj-time.coerce :as coerce] [auto-ap.time :as atime] [buddy.auth :refer [throw-unauthorized]] [datomic.api :as d] [clojure.walk :as walk] [clojure.tools.logging :as log])) (defn snake->kebab [s] (str/replace s #"_" "-")) (defn kebab [x] (if (qualified-keyword? x) (keyword (snake->kebab (namespace x)) (snake->kebab (name x)) ) (keyword (snake->kebab (name x))))) (defn kebab->snake [s] (str/replace (str/replace s #"-" "_") #"\?$" "" )) (defn snake [x] (keyword (kebab->snake (name x)))) (defn ->graphql [m] (walk/postwalk (fn [node] (cond (keyword? node) (snake node) :else node)) m)) (defn <-graphql [m] (walk/postwalk (fn [node] (cond (keyword? node) (kebab node) :else node)) m)) (defn is-admin? [id] (= "admin" (:user/role id))) (defn assert-admin [id] (when-not (= "admin" (:user/role id)) (log/warn "user " id " not an admin!") (throw-unauthorized))) (defn assert-present ([args key] (assert-present args key (name key))) ([args key name] (if (not (get args key)) (throw (ex-info (str "Missing field '" name "'.") {:validation-error (str "Missing field '" name "'.")}))))) (defn assert-failure ([message] (throw (ex-info message {:validation-error message})))) (defn assert-power-user [id] (when-not (#{"power-user" "admin"} (:user/role id)) (log/warn "user " id " not an power-user!") (throw-unauthorized))) (defn can-see-client? [identity client] (when (not client) (log/warn "WARNING - permission checking for null client")) (or (= "admin" (:user/role identity)) ((set (map :db/id (:user/clients identity))) (:db/id client)) ((set (map :db/id (:user/clients identity))) client))) (defn assert-can-see-client [identity client] (when-not (can-see-client? identity client) (log/warn "IDENTITY " identity " can not see company " client) (throw-unauthorized))) (defn limited-clients [id] (cond (or (= (:user/role id) "none")) [] (= (:user/role id) "admin") nil (#{"manager" "user" "power-user"} (:user/role id)) (:user/clients id []))) (defn result->page [results result-count key args] {key (map ->graphql results) :total result-count :count (count results) :start (:start args 0) :end (+ (:start args 0) (count results))}) (defn ident->enum-f [k] #(update % k (fn [value] (some-> value :db/ident name keyword)))) (defn enum->keyword [e namespace] (some->> e name snake->kebab (keyword namespace))) (defn get-locked-until [client-id] (:client/locked-until (d/pull (d/db conn) [:client/locked-until] client-id))) (defn assert-not-locked [client-id date] (let [locked-until (get-locked-until client-id)] (when (and locked-until (>= (compare locked-until (coerce/to-date date)) 0)) (assert-failure (str "Integreat has locked finances prior to " (-> locked-until coerce/to-date-time (atime/unparse-local atime/normal-date)) "."))))) (defn assert-none-locked [client-id dates] (doseq [d dates] (assert-not-locked client-id d)))