mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
Merge pull request #7432 from penpot/niwinz-develop-virtual-clock
🎉 Add virtual clock support
This commit is contained in:
@@ -45,7 +45,41 @@ Debug Main Page
|
|||||||
</form>
|
</form>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>VIRTUAL CLOCK</legend>
|
||||||
|
|
||||||
|
<desc>
|
||||||
|
<p>
|
||||||
|
CURRENT CLOCK: <b>{{current-clock}}</b>
|
||||||
|
<br />
|
||||||
|
CURRENT OFFSET: <b>{{current-offset}}</b>
|
||||||
|
<br />
|
||||||
|
CURRENT TIME: <b>{{current-time}}</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Examples: 3h, -7h, 24h (allowed suffixes: h, s)</p>
|
||||||
|
</desc>
|
||||||
|
|
||||||
|
<form method="post" action="/dbg/actions/set-virtual-clock">
|
||||||
|
<div class="row">
|
||||||
|
<input type="text" name="offset" placeholder="3h" value="" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<label for="force-verify">Are you sure?</label>
|
||||||
|
<input id="force-verify" type="checkbox" name="force" />
|
||||||
|
<br />
|
||||||
|
<small>
|
||||||
|
This is a just a security double check for prevent non intentional submits.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<input type="submit" name="submit" value="Submit" />
|
||||||
|
<input type="submit" name="reset" value="Reset" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -434,10 +434,10 @@
|
|||||||
(sm/validator schema:info))
|
(sm/validator schema:info))
|
||||||
|
|
||||||
(defn- get-info
|
(defn- get-info
|
||||||
[{:keys [::provider ::setup/props] :as cfg} {:keys [params] :as request}]
|
[{:keys [::provider] :as cfg} {:keys [params] :as request}]
|
||||||
(let [state (get params :state)
|
(let [state (get params :state)
|
||||||
code (get params :code)
|
code (get params :code)
|
||||||
state (tokens/verify props {:token state :iss :oauth})
|
state (tokens/verify cfg {:token state :iss :oauth})
|
||||||
tdata (fetch-access-token cfg code)
|
tdata (fetch-access-token cfg code)
|
||||||
info (case (cf/get :oidc-user-info-source)
|
info (case (cf/get :oidc-user-info-source)
|
||||||
:token (get-user-info cfg tdata)
|
:token (get-user-info cfg tdata)
|
||||||
@@ -516,7 +516,7 @@
|
|||||||
:iss :prepared-register
|
:iss :prepared-register
|
||||||
:exp (ct/in-future {:hours 48}))
|
:exp (ct/in-future {:hours 48}))
|
||||||
|
|
||||||
params {:token (tokens/generate (::setup/props cfg) info)
|
params {:token (tokens/generate cfg info)
|
||||||
:provider (:provider (:path-params request))
|
:provider (:provider (:path-params request))
|
||||||
:fullname (:fullname info)}
|
:fullname (:fullname info)}
|
||||||
params (d/without-nils params)]
|
params (d/without-nils params)]
|
||||||
@@ -569,7 +569,7 @@
|
|||||||
:else
|
:else
|
||||||
(let [sxf (session/create-fn cfg (:id profile))
|
(let [sxf (session/create-fn cfg (:id profile))
|
||||||
token (or (:invitation-token info)
|
token (or (:invitation-token info)
|
||||||
(tokens/generate (::setup/props cfg)
|
(tokens/generate cfg
|
||||||
{:iss :auth
|
{:iss :auth
|
||||||
:exp (ct/in-future "15m")
|
:exp (ct/in-future "15m")
|
||||||
:profile-id (:id profile)}))
|
:profile-id (:id profile)}))
|
||||||
@@ -620,8 +620,7 @@
|
|||||||
:external-session-id esid
|
:external-session-id esid
|
||||||
:props props
|
:props props
|
||||||
:exp (ct/in-future "4h")}
|
:exp (ct/in-future "4h")}
|
||||||
state (tokens/generate (::setup/props cfg)
|
state (tokens/generate cfg (d/without-nils params))
|
||||||
(d/without-nils params))
|
|
||||||
uri (build-auth-uri cfg state)]
|
uri (build-auth-uri cfg state)]
|
||||||
{::yres/status 200
|
{::yres/status 200
|
||||||
::yres/body {:redirect-uri uri}}))
|
::yres/body {:redirect-uri uri}}))
|
||||||
|
|||||||
@@ -23,9 +23,9 @@
|
|||||||
(second)))
|
(second)))
|
||||||
|
|
||||||
(defn- decode-token
|
(defn- decode-token
|
||||||
[props token]
|
[cfg token]
|
||||||
(when token
|
(when token
|
||||||
(tokens/verify props {:token token :iss "access-token"})))
|
(tokens/verify cfg {:token token :iss "access-token"})))
|
||||||
|
|
||||||
(def sql:get-token-data
|
(def sql:get-token-data
|
||||||
"SELECT perms, profile_id, expires_at
|
"SELECT perms, profile_id, expires_at
|
||||||
@@ -43,11 +43,11 @@
|
|||||||
(defn- wrap-soft-auth
|
(defn- wrap-soft-auth
|
||||||
"Soft Authentication, will be executed synchronously on the undertow
|
"Soft Authentication, will be executed synchronously on the undertow
|
||||||
worker thread."
|
worker thread."
|
||||||
[handler {:keys [::setup/props]}]
|
[handler cfg]
|
||||||
(letfn [(handle-request [request]
|
(letfn [(handle-request [request]
|
||||||
(try
|
(try
|
||||||
(let [token (get-token request)
|
(let [token (get-token request)
|
||||||
claims (decode-token props token)]
|
claims (decode-token cfg token)]
|
||||||
(cond-> request
|
(cond-> request
|
||||||
(map? claims)
|
(map? claims)
|
||||||
(assoc ::id (:tid claims))))
|
(assoc ::id (:tid claims))))
|
||||||
|
|||||||
@@ -107,7 +107,7 @@
|
|||||||
[cfg headers]
|
[cfg headers]
|
||||||
(let [tdata (get headers "x-penpot-data")]
|
(let [tdata (get headers "x-penpot-data")]
|
||||||
(when-not (str/empty? tdata)
|
(when-not (str/empty? tdata)
|
||||||
(let [result (tokens/verify (::setup/props cfg) {:token tdata :iss :profile-identity})]
|
(let [result (tokens/verify cfg {:token tdata :iss :profile-identity})]
|
||||||
(:profile-id result)))))
|
(:profile-id result)))))
|
||||||
|
|
||||||
(defn- parse-notification
|
(defn- parse-notification
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
[app.rpc.commands.profile :as profile]
|
[app.rpc.commands.profile :as profile]
|
||||||
[app.rpc.commands.teams :as teams]
|
[app.rpc.commands.teams :as teams]
|
||||||
[app.setup :as-alias setup]
|
[app.setup :as-alias setup]
|
||||||
|
[app.setup.clock :as clock]
|
||||||
[app.srepl.main :as srepl]
|
[app.srepl.main :as srepl]
|
||||||
[app.storage :as-alias sto]
|
[app.storage :as-alias sto]
|
||||||
[app.storage.tmp :as tmp]
|
[app.storage.tmp :as tmp]
|
||||||
@@ -49,11 +50,17 @@
|
|||||||
|
|
||||||
(defn index-handler
|
(defn index-handler
|
||||||
[_cfg _request]
|
[_cfg _request]
|
||||||
|
(let [{:keys [clock offset]} @clock/current]
|
||||||
{::yres/status 200
|
{::yres/status 200
|
||||||
::yres/headers {"content-type" "text/html"}
|
::yres/headers {"content-type" "text/html"}
|
||||||
::yres/body (-> (io/resource "app/templates/debug.tmpl")
|
::yres/body (-> (io/resource "app/templates/debug.tmpl")
|
||||||
(tmpl/render {:version (:full cf/version)
|
(tmpl/render {:version (:full cf/version)
|
||||||
:supported-features cfeat/supported-features}))})
|
:current-clock (str clock)
|
||||||
|
:current-offset (if offset
|
||||||
|
(ct/format-duration offset)
|
||||||
|
"NO OFFSET")
|
||||||
|
:current-time (ct/format-inst (ct/now) :http)
|
||||||
|
:supported-features cfeat/supported-features}))}))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; FILE CHANGES
|
;; FILE CHANGES
|
||||||
@@ -417,7 +424,6 @@
|
|||||||
::yres/headers {"content-type" "text/plain"}
|
::yres/headers {"content-type" "text/plain"}
|
||||||
::yres/body "OK"}))
|
::yres/body "OK"}))
|
||||||
|
|
||||||
|
|
||||||
(defn- handle-team-features
|
(defn- handle-team-features
|
||||||
[cfg {:keys [params] :as request}]
|
[cfg {:keys [params] :as request}]
|
||||||
(let [team-id (some-> params :team-id d/parse-uuid)
|
(let [team-id (some-> params :team-id d/parse-uuid)
|
||||||
@@ -462,6 +468,20 @@
|
|||||||
::yres/headers {"content-type" "text/plain"}
|
::yres/headers {"content-type" "text/plain"}
|
||||||
::yres/body "OK"}))))
|
::yres/body "OK"}))))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; VIRTUAL CLOCK
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn- set-virtual-clock
|
||||||
|
[_ {:keys [params] :as request}]
|
||||||
|
(let [offset (some-> params :offset str/trim not-empty ct/duration)
|
||||||
|
reset? (contains? params :reset)]
|
||||||
|
(if (or reset? (zero? (inst-ms offset)))
|
||||||
|
(clock/set-offset! nil)
|
||||||
|
(clock/set-offset! offset))
|
||||||
|
{::yres/status 302
|
||||||
|
::yres/headers {"location" "/dbg"}}))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; OTHER SMALL VIEWS/HANDLERS
|
;; OTHER SMALL VIEWS/HANDLERS
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -548,6 +568,8 @@
|
|||||||
["/error/:id" {:handler (partial error-handler cfg)}]
|
["/error/:id" {:handler (partial error-handler cfg)}]
|
||||||
["/error" {:handler (partial error-list-handler cfg)}]
|
["/error" {:handler (partial error-list-handler cfg)}]
|
||||||
["/actions" {:middleware [[errors]]}
|
["/actions" {:middleware [[errors]]}
|
||||||
|
["/set-virtual-clock"
|
||||||
|
{:handler (partial set-virtual-clock cfg)}]
|
||||||
["/resend-email-verification"
|
["/resend-email-verification"
|
||||||
{:handler (partial resend-email-notification cfg)}]
|
{:handler (partial resend-email-notification cfg)}]
|
||||||
["/reset-file-version"
|
["/reset-file-version"
|
||||||
|
|||||||
@@ -79,8 +79,7 @@
|
|||||||
(defn- authenticate
|
(defn- authenticate
|
||||||
[cfg request]
|
[cfg request]
|
||||||
(let [token (-> request :params :token)
|
(let [token (-> request :params :token)
|
||||||
props (get cfg ::setup/props)
|
result (tokens/verify cfg {:token token :iss "authentication"})]
|
||||||
result (tokens/verify props {:token token :iss "authentication"})]
|
|
||||||
{::yres/status 200
|
{::yres/status 200
|
||||||
::yres/body result}))
|
::yres/body result}))
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
(sm/validator schema:params))
|
(sm/validator schema:params))
|
||||||
|
|
||||||
(defn- prepare-session-params
|
(defn- prepare-session-params
|
||||||
[key params]
|
[params key]
|
||||||
(assert (string? key) "expected key to be a string")
|
(assert (string? key) "expected key to be a string")
|
||||||
(assert (not (str/blank? key)) "expected key to be not empty")
|
(assert (not (str/blank? key)) "expected key to be not empty")
|
||||||
(assert (valid-params? params) "expected valid params")
|
(assert (valid-params? params) "expected valid params")
|
||||||
@@ -90,7 +90,9 @@
|
|||||||
(db/exec-one! pool (sql/select :http-session {:id token})))
|
(db/exec-one! pool (sql/select :http-session {:id token})))
|
||||||
|
|
||||||
(write! [_ key params]
|
(write! [_ key params]
|
||||||
(let [params (prepare-session-params key params)]
|
(let [params (-> params
|
||||||
|
(assoc :created-at (ct/now))
|
||||||
|
(prepare-session-params key))]
|
||||||
(db/insert! pool :http-session params)
|
(db/insert! pool :http-session params)
|
||||||
params))
|
params))
|
||||||
|
|
||||||
@@ -113,7 +115,9 @@
|
|||||||
(get @cache token))
|
(get @cache token))
|
||||||
|
|
||||||
(write! [_ key params]
|
(write! [_ key params]
|
||||||
(let [params (prepare-session-params key params)]
|
(let [params (-> params
|
||||||
|
(assoc :created-at (ct/now))
|
||||||
|
(prepare-session-params key))]
|
||||||
(swap! cache assoc key params)
|
(swap! cache assoc key params)
|
||||||
params))
|
params))
|
||||||
|
|
||||||
@@ -150,16 +154,15 @@
|
|||||||
(declare ^:private gen-token)
|
(declare ^:private gen-token)
|
||||||
|
|
||||||
(defn create-fn
|
(defn create-fn
|
||||||
[{:keys [::manager ::setup/props]} profile-id]
|
[{:keys [::manager] :as cfg} profile-id]
|
||||||
(assert (manager? manager) "expected valid session manager")
|
(assert (manager? manager) "expected valid session manager")
|
||||||
(assert (uuid? profile-id) "expected valid uuid for profile-id")
|
(assert (uuid? profile-id) "expected valid uuid for profile-id")
|
||||||
|
|
||||||
(fn [request response]
|
(fn [request response]
|
||||||
(let [uagent (yreq/get-header request "user-agent")
|
(let [uagent (yreq/get-header request "user-agent")
|
||||||
params {:profile-id profile-id
|
params {:profile-id profile-id
|
||||||
:user-agent uagent
|
:user-agent uagent}
|
||||||
:created-at (ct/now)}
|
token (gen-token cfg params)
|
||||||
token (gen-token props params)
|
|
||||||
session (write! manager token params)]
|
session (write! manager token params)]
|
||||||
(l/trace :hint "create" :profile-id (str profile-id))
|
(l/trace :hint "create" :profile-id (str profile-id))
|
||||||
(-> response
|
(-> response
|
||||||
@@ -181,14 +184,14 @@
|
|||||||
(clear-auth-data-cookie)))))
|
(clear-auth-data-cookie)))))
|
||||||
|
|
||||||
(defn- gen-token
|
(defn- gen-token
|
||||||
[props {:keys [profile-id created-at]}]
|
[cfg {:keys [profile-id created-at]}]
|
||||||
(tokens/generate props {:iss "authentication"
|
(tokens/generate cfg {:iss "authentication"
|
||||||
:iat created-at
|
:iat created-at
|
||||||
:uid profile-id}))
|
:uid profile-id}))
|
||||||
(defn- decode-token
|
(defn- decode-token
|
||||||
[props token]
|
[cfg token]
|
||||||
(when token
|
(when token
|
||||||
(tokens/verify props {:token token :iss "authentication"})))
|
(tokens/verify cfg {:token token :iss "authentication"})))
|
||||||
|
|
||||||
(defn- get-token
|
(defn- get-token
|
||||||
[request]
|
[request]
|
||||||
@@ -208,12 +211,12 @@
|
|||||||
(neg? (compare default-renewal-max-age elapsed)))))
|
(neg? (compare default-renewal-max-age elapsed)))))
|
||||||
|
|
||||||
(defn- wrap-soft-auth
|
(defn- wrap-soft-auth
|
||||||
[handler {:keys [::manager ::setup/props]}]
|
[handler {:keys [::manager] :as cfg}]
|
||||||
(assert (manager? manager) "expected valid session manager")
|
(assert (manager? manager) "expected valid session manager")
|
||||||
(letfn [(handle-request [request]
|
(letfn [(handle-request [request]
|
||||||
(try
|
(try
|
||||||
(let [token (get-token request)
|
(let [token (get-token request)
|
||||||
claims (decode-token props token)]
|
claims (decode-token cfg token)]
|
||||||
(cond-> request
|
(cond-> request
|
||||||
(map? claims)
|
(map? claims)
|
||||||
(-> (assoc ::token-claims claims)
|
(-> (assoc ::token-claims claims)
|
||||||
@@ -256,7 +259,7 @@
|
|||||||
(defn- assign-auth-token-cookie
|
(defn- assign-auth-token-cookie
|
||||||
[response {token :id updated-at :updated-at}]
|
[response {token :id updated-at :updated-at}]
|
||||||
(let [max-age (cf/get :auth-token-cookie-max-age default-cookie-max-age)
|
(let [max-age (cf/get :auth-token-cookie-max-age default-cookie-max-age)
|
||||||
created-at (or updated-at (ct/now))
|
created-at updated-at
|
||||||
renewal (ct/plus created-at default-renewal-max-age)
|
renewal (ct/plus created-at default-renewal-max-age)
|
||||||
expires (ct/plus created-at max-age)
|
expires (ct/plus created-at max-age)
|
||||||
secure? (contains? cf/flags :secure-session-cookies)
|
secure? (contains? cf/flags :secure-session-cookies)
|
||||||
@@ -279,7 +282,7 @@
|
|||||||
domain (cf/get :auth-data-cookie-domain)
|
domain (cf/get :auth-data-cookie-domain)
|
||||||
cname default-auth-data-cookie-name
|
cname default-auth-data-cookie-name
|
||||||
|
|
||||||
created-at (or updated-at (ct/now))
|
created-at updated-at
|
||||||
renewal (ct/plus created-at default-renewal-max-age)
|
renewal (ct/plus created-at default-renewal-max-age)
|
||||||
expires (ct/plus created-at max-age)
|
expires (ct/plus created-at max-age)
|
||||||
|
|
||||||
@@ -313,13 +316,10 @@
|
|||||||
(string? domain)
|
(string? domain)
|
||||||
(update :cookies assoc cname {:domain domain :path "/" :value "" :max-age 0}))))
|
(update :cookies assoc cname {:domain domain :path "/" :value "" :max-age 0}))))
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; TASK: SESSION GC
|
;; TASK: SESSION GC
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; FIXME: MOVE
|
|
||||||
|
|
||||||
(defmethod ig/assert-key ::tasks/gc
|
(defmethod ig/assert-key ::tasks/gc
|
||||||
[_ params]
|
[_ params]
|
||||||
(assert (db/pool? (::db/pool params)) "expected valid database pool")
|
(assert (db/pool? (::db/pool params)) "expected valid database pool")
|
||||||
@@ -332,16 +332,16 @@
|
|||||||
|
|
||||||
(def ^:private
|
(def ^:private
|
||||||
sql:delete-expired
|
sql:delete-expired
|
||||||
"delete from http_session
|
"DELETE FROM http_session
|
||||||
where updated_at < now() - ?::interval
|
WHERE updated_at < ?::timestamptz
|
||||||
or (updated_at is null and
|
or (updated_at is null and
|
||||||
created_at < now() - ?::interval)")
|
created_at < ?::timestamptz)")
|
||||||
|
|
||||||
(defn- collect-expired-tasks
|
(defn- collect-expired-tasks
|
||||||
[{:keys [::db/conn ::tasks/max-age]}]
|
[{:keys [::db/conn ::tasks/max-age]}]
|
||||||
(let [interval (db/interval max-age)
|
(let [threshold (ct/minus (ct/now) max-age)
|
||||||
result (db/exec-one! conn [sql:delete-expired interval interval])
|
result (-> (db/exec-one! conn [sql:delete-expired threshold threshold])
|
||||||
result (:next.jdbc/update-count result)]
|
(db/get-update-count))]
|
||||||
(l/debug :task "gc"
|
(l/debug :task "gc"
|
||||||
:hint "clean http sessions"
|
:hint "clean http sessions"
|
||||||
:deleted result)
|
:deleted result)
|
||||||
@@ -350,4 +350,5 @@
|
|||||||
(defmethod ig/init-key ::tasks/gc
|
(defmethod ig/init-key ::tasks/gc
|
||||||
[_ {:keys [::tasks/max-age] :as cfg}]
|
[_ {:keys [::tasks/max-age] :as cfg}]
|
||||||
(l/debug :hint "initializing session gc task" :max-age max-age)
|
(l/debug :hint "initializing session gc task" :max-age max-age)
|
||||||
(fn [_] (db/tx-run! cfg collect-expired-tasks)))
|
(fn [_]
|
||||||
|
(db/tx-run! cfg collect-expired-tasks)))
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.logging :as l]
|
[app.common.logging :as l]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.time :as ct]
|
|
||||||
[app.common.transit :as t]
|
[app.common.transit :as t]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
@@ -53,9 +52,8 @@
|
|||||||
|
|
||||||
(defn- send!
|
(defn- send!
|
||||||
[{:keys [::uri] :as cfg} events]
|
[{:keys [::uri] :as cfg} events]
|
||||||
(let [token (tokens/generate (::setup/props cfg)
|
(let [token (tokens/generate cfg
|
||||||
{:iss "authentication"
|
{:iss "authentication"
|
||||||
:iat (ct/now)
|
|
||||||
:uid uuid/zero})
|
:uid uuid/zero})
|
||||||
body (t/encode {:events events})
|
body (t/encode {:events events})
|
||||||
headers {"content-type" "application/transit+json"
|
headers {"content-type" "application/transit+json"
|
||||||
|
|||||||
@@ -334,7 +334,7 @@
|
|||||||
:app.rpc.doc/routes
|
:app.rpc.doc/routes
|
||||||
{:app.rpc/methods (ig/ref :app.rpc/methods)}
|
{:app.rpc/methods (ig/ref :app.rpc/methods)}
|
||||||
|
|
||||||
:app.rpc/routes
|
::rpc/routes
|
||||||
{::rpc/methods (ig/ref :app.rpc/methods)
|
{::rpc/methods (ig/ref :app.rpc/methods)
|
||||||
::db/pool (ig/ref ::db/pool)
|
::db/pool (ig/ref ::db/pool)
|
||||||
::session/manager (ig/ref ::session/manager)
|
::session/manager (ig/ref ::session/manager)
|
||||||
@@ -426,6 +426,9 @@
|
|||||||
;; module requires the migrations to run before initialize.
|
;; module requires the migrations to run before initialize.
|
||||||
::migrations (ig/ref :app.migrations/migrations)}
|
::migrations (ig/ref :app.migrations/migrations)}
|
||||||
|
|
||||||
|
::setup/clock
|
||||||
|
{}
|
||||||
|
|
||||||
:app.loggers.audit.archive-task/handler
|
:app.loggers.audit.archive-task/handler
|
||||||
{::setup/props (ig/ref ::setup/props)
|
{::setup/props (ig/ref ::setup/props)
|
||||||
::db/pool (ig/ref ::db/pool)
|
::db/pool (ig/ref ::db/pool)
|
||||||
|
|||||||
@@ -23,14 +23,14 @@
|
|||||||
(dissoc row :perms))
|
(dissoc row :perms))
|
||||||
|
|
||||||
(defn create-access-token
|
(defn create-access-token
|
||||||
[{:keys [::db/conn ::setup/props]} profile-id name expiration]
|
[{:keys [::db/conn] :as cfg} profile-id name expiration]
|
||||||
(let [created-at (ct/now)
|
(let [token-id (uuid/next)
|
||||||
token-id (uuid/next)
|
expires-at (some-> expiration (ct/in-future))
|
||||||
token (tokens/generate props {:iss "access-token"
|
created-at (ct/now)
|
||||||
:tid token-id
|
token (tokens/generate cfg {:iss "access-token"
|
||||||
:iat created-at})
|
:iat created-at
|
||||||
|
:tid token-id})
|
||||||
|
|
||||||
expires-at (some-> expiration ct/in-future)
|
|
||||||
token (db/insert! conn :access-token
|
token (db/insert! conn :access-token
|
||||||
{:id token-id
|
{:id token-id
|
||||||
:name name
|
:name name
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
(profile/strip-private-attrs))
|
(profile/strip-private-attrs))
|
||||||
|
|
||||||
invitation (when-let [token (:invitation-token params)]
|
invitation (when-let [token (:invitation-token params)]
|
||||||
(tokens/verify (::setup/props cfg) {:token token :iss :team-invitation}))
|
(tokens/verify cfg {:token token :iss :team-invitation}))
|
||||||
|
|
||||||
;; If invitation member-id does not matches the profile-id, we just proceed to ignore the
|
;; If invitation member-id does not matches the profile-id, we just proceed to ignore the
|
||||||
;; invitation because invitations matches exactly; and user can't login with other email and
|
;; invitation because invitations matches exactly; and user can't login with other email and
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
(defn recover-profile
|
(defn recover-profile
|
||||||
[{:keys [::db/conn] :as cfg} {:keys [token password]}]
|
[{:keys [::db/conn] :as cfg} {:keys [token password]}]
|
||||||
(letfn [(validate-token [token]
|
(letfn [(validate-token [token]
|
||||||
(let [tdata (tokens/verify (::setup/props cfg) {:token token :iss :password-recovery})]
|
(let [tdata (tokens/verify cfg {:token token :iss :password-recovery})]
|
||||||
(:profile-id tdata)))
|
(:profile-id tdata)))
|
||||||
|
|
||||||
(update-password [conn profile-id]
|
(update-password [conn profile-id]
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
:hint "registration disabled"))
|
:hint "registration disabled"))
|
||||||
|
|
||||||
(when (contains? params :invitation-token)
|
(when (contains? params :invitation-token)
|
||||||
(let [invitation (tokens/verify (::setup/props cfg)
|
(let [invitation (tokens/verify cfg
|
||||||
{:token (:invitation-token params)
|
{:token (:invitation-token params)
|
||||||
:iss :team-invitation})]
|
:iss :team-invitation})]
|
||||||
(when-not (= (:email params) (:member-email invitation))
|
(when-not (= (:email params) (:member-email invitation))
|
||||||
@@ -249,7 +249,7 @@
|
|||||||
:props {:newsletter-updates (or accept-newsletter-updates false)}}
|
:props {:newsletter-updates (or accept-newsletter-updates false)}}
|
||||||
|
|
||||||
params (d/without-nils params)
|
params (d/without-nils params)
|
||||||
token (tokens/generate (::setup/props cfg) params)]
|
token (tokens/generate cfg params)]
|
||||||
|
|
||||||
(with-meta {:token token}
|
(with-meta {:token token}
|
||||||
{::audit/profile-id uuid/zero})))
|
{::audit/profile-id uuid/zero})))
|
||||||
@@ -343,14 +343,14 @@
|
|||||||
|
|
||||||
(defn send-email-verification!
|
(defn send-email-verification!
|
||||||
[{:keys [::db/conn] :as cfg} profile]
|
[{:keys [::db/conn] :as cfg} profile]
|
||||||
(let [vtoken (tokens/generate (::setup/props cfg)
|
(let [vtoken (tokens/generate cfg
|
||||||
{:iss :verify-email
|
{:iss :verify-email
|
||||||
:exp (ct/in-future "72h")
|
:exp (ct/in-future "72h")
|
||||||
:profile-id (:id profile)
|
:profile-id (:id profile)
|
||||||
:email (:email profile)})
|
:email (:email profile)})
|
||||||
;; NOTE: this token is mainly used for possible complains
|
;; NOTE: this token is mainly used for possible complains
|
||||||
;; identification on the sns webhook
|
;; identification on the sns webhook
|
||||||
ptoken (tokens/generate (::setup/props cfg)
|
ptoken (tokens/generate cfg
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)
|
:profile-id (:id profile)
|
||||||
:exp (ct/in-future {:days 30})})]
|
:exp (ct/in-future {:days 30})})]
|
||||||
@@ -364,7 +364,7 @@
|
|||||||
|
|
||||||
(defn register-profile
|
(defn register-profile
|
||||||
[{:keys [::db/conn ::wrk/executor] :as cfg} {:keys [token] :as params}]
|
[{:keys [::db/conn ::wrk/executor] :as cfg} {:keys [token] :as params}]
|
||||||
(let [claims (tokens/verify (::setup/props cfg) {:token token :iss :prepared-register})
|
(let [claims (tokens/verify cfg {:token token :iss :prepared-register})
|
||||||
params (into claims params)
|
params (into claims params)
|
||||||
|
|
||||||
profile (if-let [profile-id (:profile-id claims)]
|
profile (if-let [profile-id (:profile-id claims)]
|
||||||
@@ -387,7 +387,7 @@
|
|||||||
created? (-> profile meta :created true?)
|
created? (-> profile meta :created true?)
|
||||||
|
|
||||||
invitation (when-let [token (:invitation-token params)]
|
invitation (when-let [token (:invitation-token params)]
|
||||||
(tokens/verify (::setup/props cfg) {:token token :iss :team-invitation}))
|
(tokens/verify cfg {:token token :iss :team-invitation}))
|
||||||
|
|
||||||
props (-> (audit/profile->props profile)
|
props (-> (audit/profile->props profile)
|
||||||
(assoc :from-invitation (some? invitation)))
|
(assoc :from-invitation (some? invitation)))
|
||||||
@@ -420,7 +420,7 @@
|
|||||||
(= (:email profile)
|
(= (:email profile)
|
||||||
(:member-email invitation)))
|
(:member-email invitation)))
|
||||||
(let [claims (assoc invitation :member-id (:id profile))
|
(let [claims (assoc invitation :member-id (:id profile))
|
||||||
token (tokens/generate (::setup/props cfg) claims)]
|
token (tokens/generate cfg claims)]
|
||||||
(-> {:invitation-token token}
|
(-> {:invitation-token token}
|
||||||
(rph/with-transform (session/create-fn cfg (:id profile)))
|
(rph/with-transform (session/create-fn cfg (:id profile)))
|
||||||
(rph/with-meta {::audit/replace-props props
|
(rph/with-meta {::audit/replace-props props
|
||||||
@@ -494,14 +494,14 @@
|
|||||||
(defn- request-profile-recovery
|
(defn- request-profile-recovery
|
||||||
[{:keys [::db/conn] :as cfg} {:keys [email] :as params}]
|
[{:keys [::db/conn] :as cfg} {:keys [email] :as params}]
|
||||||
(letfn [(create-recovery-token [{:keys [id] :as profile}]
|
(letfn [(create-recovery-token [{:keys [id] :as profile}]
|
||||||
(let [token (tokens/generate (::setup/props cfg)
|
(let [token (tokens/generate cfg
|
||||||
{:iss :password-recovery
|
{:iss :password-recovery
|
||||||
:exp (ct/in-future "15m")
|
:exp (ct/in-future "15m")
|
||||||
:profile-id id})]
|
:profile-id id})]
|
||||||
(assoc profile :token token)))
|
(assoc profile :token token)))
|
||||||
|
|
||||||
(send-email-notification [conn profile]
|
(send-email-notification [conn profile]
|
||||||
(let [ptoken (tokens/generate (::setup/props cfg)
|
(let [ptoken (tokens/generate cfg
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)
|
:profile-id (:id profile)
|
||||||
:exp (ct/in-future {:days 30})})]
|
:exp (ct/in-future {:days 30})})]
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
::doc/added "1.15"
|
::doc/added "1.15"
|
||||||
::doc/module :auth
|
::doc/module :auth
|
||||||
::sm/params schema:login-with-ldap}
|
::sm/params schema:login-with-ldap}
|
||||||
[{:keys [::setup/props ::ldap/provider] :as cfg} params]
|
[{:keys [::ldap/provider] :as cfg} params]
|
||||||
(when-not provider
|
(when-not provider
|
||||||
(ex/raise :type :restriction
|
(ex/raise :type :restriction
|
||||||
:code :ldap-not-initialized
|
:code :ldap-not-initialized
|
||||||
@@ -60,11 +60,11 @@
|
|||||||
;; user comes from team-invitation process; in this case,
|
;; user comes from team-invitation process; in this case,
|
||||||
;; regenerate token and send back to the user a new invitation
|
;; regenerate token and send back to the user a new invitation
|
||||||
;; token (and mark current session as logged).
|
;; token (and mark current session as logged).
|
||||||
(let [claims (tokens/verify props {:token token :iss :team-invitation})
|
(let [claims (tokens/verify cfg {:token token :iss :team-invitation})
|
||||||
claims (assoc claims
|
claims (assoc claims
|
||||||
:member-id (:id profile)
|
:member-id (:id profile)
|
||||||
:member-email (:email profile))
|
:member-email (:email profile))
|
||||||
token (tokens/generate props claims)]
|
token (tokens/generate cfg claims)]
|
||||||
(-> {:invitation-token token}
|
(-> {:invitation-token token}
|
||||||
(rph/with-transform (session/create-fn cfg (:id profile)))
|
(rph/with-transform (session/create-fn cfg (:id profile)))
|
||||||
(rph/with-meta {::audit/props (:props profile)
|
(rph/with-meta {::audit/props (:props profile)
|
||||||
|
|||||||
@@ -345,12 +345,12 @@
|
|||||||
|
|
||||||
(defn- request-email-change!
|
(defn- request-email-change!
|
||||||
[{:keys [::db/conn] :as cfg} {:keys [profile email] :as params}]
|
[{:keys [::db/conn] :as cfg} {:keys [profile email] :as params}]
|
||||||
(let [token (tokens/generate (::setup/props cfg)
|
(let [token (tokens/generate cfg
|
||||||
{:iss :change-email
|
{:iss :change-email
|
||||||
:exp (ct/in-future "15m")
|
:exp (ct/in-future "15m")
|
||||||
:profile-id (:id profile)
|
:profile-id (:id profile)
|
||||||
:email email})
|
:email email})
|
||||||
ptoken (tokens/generate (::setup/props cfg)
|
ptoken (tokens/generate cfg
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)
|
:profile-id (:id profile)
|
||||||
:exp (ct/in-future {:days 30})})]
|
:exp (ct/in-future {:days 30})})]
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
(defn- create-invitation-token
|
(defn- create-invitation-token
|
||||||
[cfg {:keys [profile-id valid-until team-id member-id member-email role]}]
|
[cfg {:keys [profile-id valid-until team-id member-id member-email role]}]
|
||||||
(tokens/generate (::setup/props cfg)
|
(tokens/generate cfg
|
||||||
{:iss :team-invitation
|
{:iss :team-invitation
|
||||||
:exp valid-until
|
:exp valid-until
|
||||||
:profile-id profile-id
|
:profile-id profile-id
|
||||||
@@ -54,12 +54,8 @@
|
|||||||
|
|
||||||
(defn- create-profile-identity-token
|
(defn- create-profile-identity-token
|
||||||
[cfg profile-id]
|
[cfg profile-id]
|
||||||
|
(assert (uuid? profile-id) "expected valid uuid for profile-id")
|
||||||
(dm/assert!
|
(tokens/generate cfg
|
||||||
"expected valid uuid for profile-id"
|
|
||||||
(uuid? profile-id))
|
|
||||||
|
|
||||||
(tokens/generate (::setup/props cfg)
|
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id profile-id
|
:profile-id profile-id
|
||||||
:exp (ct/in-future {:days 30})}))
|
:exp (ct/in-future {:days 30})}))
|
||||||
@@ -522,7 +518,7 @@
|
|||||||
|
|
||||||
(defn- check-existing-team-access-request
|
(defn- check-existing-team-access-request
|
||||||
"Checks if an existing team access request is still valid"
|
"Checks if an existing team access request is still valid"
|
||||||
[conn team-id profile-id]
|
[{:keys [::db/conn]} team-id profile-id]
|
||||||
(when-let [request (db/get* conn :team-access-request
|
(when-let [request (db/get* conn :team-access-request
|
||||||
{:team-id team-id
|
{:team-id team-id
|
||||||
:requester-id profile-id})]
|
:requester-id profile-id})]
|
||||||
@@ -540,8 +536,8 @@
|
|||||||
|
|
||||||
(defn- upsert-team-access-request
|
(defn- upsert-team-access-request
|
||||||
"Create or update team access request for provided team and profile-id"
|
"Create or update team access request for provided team and profile-id"
|
||||||
[conn team-id requester-id]
|
[{:keys [::db/conn] :as cfg} team-id requester-id]
|
||||||
(check-existing-team-access-request conn team-id requester-id)
|
(check-existing-team-access-request cfg team-id requester-id)
|
||||||
(let [valid-until (ct/in-future {:hours 24})
|
(let [valid-until (ct/in-future {:hours 24})
|
||||||
auto-join-until (ct/in-future {:days 7})
|
auto-join-until (ct/in-future {:days 7})
|
||||||
request-id (uuid/next)]
|
request-id (uuid/next)]
|
||||||
@@ -603,7 +599,7 @@
|
|||||||
(teams/check-email-bounce conn (:email team-owner) false)
|
(teams/check-email-bounce conn (:email team-owner) false)
|
||||||
(teams/check-email-spam conn (:email team-owner) true)
|
(teams/check-email-spam conn (:email team-owner) true)
|
||||||
|
|
||||||
(let [request (upsert-team-access-request conn team-id profile-id)
|
(let [request (upsert-team-access-request cfg team-id profile-id)
|
||||||
factory (cond
|
factory (cond
|
||||||
(and (some? file) (:is-default team) is-viewer)
|
(and (some? file) (:is-default team) is-viewer)
|
||||||
eml/request-file-access-yourpenpot-view
|
eml/request-file-access-yourpenpot-view
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
::doc/module :auth
|
::doc/module :auth
|
||||||
::sm/params schema:verify-token}
|
::sm/params schema:verify-token}
|
||||||
[cfg {:keys [token] :as params}]
|
[cfg {:keys [token] :as params}]
|
||||||
(let [claims (tokens/verify (::setup/props cfg) {:token token})]
|
(let [claims (tokens/verify cfg {:token token})]
|
||||||
(db/tx-run! cfg process-token params claims)))
|
(db/tx-run! cfg process-token params claims)))
|
||||||
|
|
||||||
(defmethod process-token :change-email
|
(defmethod process-token :change-email
|
||||||
|
|||||||
48
backend/src/app/setup/clock.clj
Normal file
48
backend/src/app/setup/clock.clj
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.setup.clock
|
||||||
|
"A service/module that manages the system clock and allows runtime
|
||||||
|
modification of time offset (useful for testing and time adjustments)."
|
||||||
|
(:require
|
||||||
|
[app.common.logging :as l]
|
||||||
|
[app.common.time :as ct]
|
||||||
|
[app.setup :as-alias setup]
|
||||||
|
[integrant.core :as ig])
|
||||||
|
(:import
|
||||||
|
java.time.Clock
|
||||||
|
java.time.Duration))
|
||||||
|
|
||||||
|
(defonce current
|
||||||
|
(atom {:clock (Clock/systemDefaultZone)
|
||||||
|
:offset nil}))
|
||||||
|
|
||||||
|
(defmethod ig/init-key ::setup/clock
|
||||||
|
[_ _]
|
||||||
|
(add-watch current ::common
|
||||||
|
(fn [_ _ _ {:keys [clock offset]}]
|
||||||
|
(let [clock (if (ct/duration? offset)
|
||||||
|
(Clock/offset ^Clock clock
|
||||||
|
^Duration offset)
|
||||||
|
clock)]
|
||||||
|
(l/wrn :hint "altering clock" :clock (str clock))
|
||||||
|
(alter-var-root #'ct/*clock* (constantly clock))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defmethod ig/halt-key! ::setup/clock
|
||||||
|
[_ _]
|
||||||
|
(remove-watch current ::common))
|
||||||
|
|
||||||
|
(defn set-offset!
|
||||||
|
[duration]
|
||||||
|
(swap! current assoc :offset (some-> duration ct/duration)))
|
||||||
|
|
||||||
|
(defn set-clock!
|
||||||
|
([]
|
||||||
|
(swap! current assoc :clock (Clock/systemDefaultZone)))
|
||||||
|
([clock]
|
||||||
|
(when (instance? Clock clock)
|
||||||
|
(swap! current assoc :clock clock))))
|
||||||
@@ -129,8 +129,7 @@
|
|||||||
(defmethod exec-command "authenticate"
|
(defmethod exec-command "authenticate"
|
||||||
[{:keys [token]}]
|
[{:keys [token]}]
|
||||||
(when-let [system (get-current-system)]
|
(when-let [system (get-current-system)]
|
||||||
(let [props (get system ::setup/props)]
|
(tokens/verify system {:token token :iss "authentication"})))
|
||||||
(tokens/verify props {:token token :iss "authentication"}))))
|
|
||||||
|
|
||||||
(def ^:private schema:get-customer
|
(def ^:private schema:get-customer
|
||||||
[:map [:id ::sm/uuid]])
|
[:map [:id ::sm/uuid]])
|
||||||
|
|||||||
@@ -8,33 +8,40 @@
|
|||||||
"Tokens generation API."
|
"Tokens generation API."
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.time :as ct]
|
[app.common.time :as ct]
|
||||||
[app.common.transit :as t]
|
[app.common.transit :as t]
|
||||||
|
[app.setup :as-alias setup]
|
||||||
[buddy.sign.jwe :as jwe]))
|
[buddy.sign.jwe :as jwe]))
|
||||||
|
|
||||||
(defn generate
|
(defn generate
|
||||||
[{:keys [tokens-key]} claims]
|
[{:keys [::setup/props] :as cfg} claims]
|
||||||
|
(assert (contains? cfg ::setup/props))
|
||||||
|
|
||||||
(dm/assert!
|
(let [tokens-key
|
||||||
"expexted token-key to be bytes instance"
|
(get props :tokens-key)
|
||||||
(bytes? tokens-key))
|
|
||||||
|
|
||||||
(let [payload (-> claims
|
payload
|
||||||
(assoc :iat (ct/now))
|
(-> claims
|
||||||
|
(update :iat (fn [v] (or v (ct/now))))
|
||||||
(d/without-nils)
|
(d/without-nils)
|
||||||
(t/encode))]
|
(t/encode))]
|
||||||
|
|
||||||
(jwe/encrypt payload tokens-key {:alg :a256kw :enc :a256gcm})))
|
(jwe/encrypt payload tokens-key {:alg :a256kw :enc :a256gcm})))
|
||||||
|
|
||||||
(defn decode
|
(defn decode
|
||||||
[{:keys [tokens-key]} token]
|
[{:keys [::setup/props] :as cfg} token]
|
||||||
(let [payload (jwe/decrypt token tokens-key {:alg :a256kw :enc :a256gcm})]
|
(let [tokens-key
|
||||||
|
(get props :tokens-key)
|
||||||
|
|
||||||
|
payload
|
||||||
|
(jwe/decrypt token tokens-key {:alg :a256kw :enc :a256gcm})]
|
||||||
|
|
||||||
(t/decode payload)))
|
(t/decode payload)))
|
||||||
|
|
||||||
(defn verify
|
(defn verify
|
||||||
[sprops {:keys [token] :as params}]
|
[cfg {:keys [token] :as params}]
|
||||||
(let [claims (decode sprops token)]
|
(let [claims (decode cfg token)]
|
||||||
(when (and (ct/inst? (:exp claims))
|
(when (and (ct/inst? (:exp claims))
|
||||||
(ct/is-before? (:exp claims) (ct/now)))
|
(ct/is-before? (:exp claims) (ct/now)))
|
||||||
(ex/raise :type :validation
|
(ex/raise :type :validation
|
||||||
|
|||||||
@@ -101,12 +101,10 @@
|
|||||||
|
|
||||||
(t/deftest test-parse-bounce-report
|
(t/deftest test-parse-bounce-report
|
||||||
(let [profile (th/create-profile* 1)
|
(let [profile (th/create-profile* 1)
|
||||||
props (:app.setup/props th/*system*)
|
report (bounce-report {:token (tokens/generate th/*system*
|
||||||
cfg {:app.setup/props props}
|
|
||||||
report (bounce-report {:token (tokens/generate props
|
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)})})
|
:profile-id (:id profile)})})
|
||||||
result (#'awsns/parse-notification cfg report)]
|
result (#'awsns/parse-notification th/*system* report)]
|
||||||
;; (pprint result)
|
;; (pprint result)
|
||||||
|
|
||||||
(t/is (= "bounce" (:type result)))
|
(t/is (= "bounce" (:type result)))
|
||||||
@@ -117,12 +115,10 @@
|
|||||||
|
|
||||||
(t/deftest test-parse-complaint-report
|
(t/deftest test-parse-complaint-report
|
||||||
(let [profile (th/create-profile* 1)
|
(let [profile (th/create-profile* 1)
|
||||||
props (:app.setup/props th/*system*)
|
report (complaint-report {:token (tokens/generate th/*system*
|
||||||
cfg {:app.setup/props props}
|
|
||||||
report (complaint-report {:token (tokens/generate props
|
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)})})
|
:profile-id (:id profile)})})
|
||||||
result (#'awsns/parse-notification cfg report)]
|
result (#'awsns/parse-notification th/*system* report)]
|
||||||
;; (pprint result)
|
;; (pprint result)
|
||||||
(t/is (= "complaint" (:type result)))
|
(t/is (= "complaint" (:type result)))
|
||||||
(t/is (= "abuse" (:kind result)))
|
(t/is (= "abuse" (:kind result)))
|
||||||
@@ -143,15 +139,13 @@
|
|||||||
|
|
||||||
(t/deftest test-process-bounce-report
|
(t/deftest test-process-bounce-report
|
||||||
(let [profile (th/create-profile* 1)
|
(let [profile (th/create-profile* 1)
|
||||||
props (:app.setup/props th/*system*)
|
|
||||||
pool (:app.db/pool th/*system*)
|
pool (:app.db/pool th/*system*)
|
||||||
cfg {:app.setup/props props :app.db/pool pool}
|
report (bounce-report {:token (tokens/generate th/*system*
|
||||||
report (bounce-report {:token (tokens/generate props
|
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)})})
|
:profile-id (:id profile)})})
|
||||||
report (#'awsns/parse-notification cfg report)]
|
report (#'awsns/parse-notification th/*system* report)]
|
||||||
|
|
||||||
(#'awsns/process-report cfg report)
|
(#'awsns/process-report th/*system* report)
|
||||||
|
|
||||||
(let [rows (->> (db/query pool :profile-complaint-report {:profile-id (:id profile)})
|
(let [rows (->> (db/query pool :profile-complaint-report {:profile-id (:id profile)})
|
||||||
(mapv decode-row))]
|
(mapv decode-row))]
|
||||||
@@ -170,16 +164,13 @@
|
|||||||
|
|
||||||
(t/deftest test-process-complaint-report
|
(t/deftest test-process-complaint-report
|
||||||
(let [profile (th/create-profile* 1)
|
(let [profile (th/create-profile* 1)
|
||||||
props (:app.setup/props th/*system*)
|
|
||||||
pool (:app.db/pool th/*system*)
|
pool (:app.db/pool th/*system*)
|
||||||
cfg {:app.setup/props props
|
report (complaint-report {:token (tokens/generate th/*system*
|
||||||
:app.db/pool pool}
|
|
||||||
report (complaint-report {:token (tokens/generate props
|
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)})})
|
:profile-id (:id profile)})})
|
||||||
report (#'awsns/parse-notification cfg report)]
|
report (#'awsns/parse-notification th/*system* report)]
|
||||||
|
|
||||||
(#'awsns/process-report cfg report)
|
(#'awsns/process-report th/*system* report)
|
||||||
|
|
||||||
(let [rows (->> (db/query pool :profile-complaint-report {:profile-id (:id profile)})
|
(let [rows (->> (db/query pool :profile-complaint-report {:profile-id (:id profile)})
|
||||||
(mapv decode-row))]
|
(mapv decode-row))]
|
||||||
@@ -200,16 +191,14 @@
|
|||||||
|
|
||||||
(t/deftest test-process-bounce-report-to-self
|
(t/deftest test-process-bounce-report-to-self
|
||||||
(let [profile (th/create-profile* 1)
|
(let [profile (th/create-profile* 1)
|
||||||
props (:app.setup/props th/*system*)
|
|
||||||
pool (:app.db/pool th/*system*)
|
pool (:app.db/pool th/*system*)
|
||||||
cfg {:app.setup/props props :app.db/pool pool}
|
|
||||||
report (bounce-report {:email (:email profile)
|
report (bounce-report {:email (:email profile)
|
||||||
:token (tokens/generate props
|
:token (tokens/generate th/*system*
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)})})
|
:profile-id (:id profile)})})
|
||||||
report (#'awsns/parse-notification cfg report)]
|
report (#'awsns/parse-notification th/*system* report)]
|
||||||
|
|
||||||
(#'awsns/process-report cfg report)
|
(#'awsns/process-report th/*system* report)
|
||||||
|
|
||||||
(let [rows (db/query pool :profile-complaint-report {:profile-id (:id profile)})]
|
(let [rows (db/query pool :profile-complaint-report {:profile-id (:id profile)})]
|
||||||
(t/is (= 1 (count rows))))
|
(t/is (= 1 (count rows))))
|
||||||
@@ -222,16 +211,14 @@
|
|||||||
|
|
||||||
(t/deftest test-process-complaint-report-to-self
|
(t/deftest test-process-complaint-report-to-self
|
||||||
(let [profile (th/create-profile* 1)
|
(let [profile (th/create-profile* 1)
|
||||||
props (:app.setup/props th/*system*)
|
|
||||||
pool (:app.db/pool th/*system*)
|
pool (:app.db/pool th/*system*)
|
||||||
cfg {:app.setup/props props :app.db/pool pool}
|
|
||||||
report (complaint-report {:email (:email profile)
|
report (complaint-report {:email (:email profile)
|
||||||
:token (tokens/generate props
|
:token (tokens/generate th/*system*
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)})})
|
:profile-id (:id profile)})})
|
||||||
report (#'awsns/parse-notification cfg report)]
|
report (#'awsns/parse-notification th/*system* report)]
|
||||||
|
|
||||||
(#'awsns/process-report cfg report)
|
(#'awsns/process-report th/*system* report)
|
||||||
|
|
||||||
(let [rows (db/query pool :profile-complaint-report {:profile-id (:id profile)})]
|
(let [rows (db/query pool :profile-complaint-report {:profile-id (:id profile)})]
|
||||||
(t/is (= 1 (count rows))))
|
(t/is (= 1 (count rows))))
|
||||||
|
|||||||
@@ -25,8 +25,7 @@
|
|||||||
|
|
||||||
(t/deftest authenticate-method
|
(t/deftest authenticate-method
|
||||||
(let [profile (th/create-profile* 1)
|
(let [profile (th/create-profile* 1)
|
||||||
props (get th/*system* :app.setup/props)
|
token (#'sess/gen-token th/*system* {:profile-id (:id profile)})
|
||||||
token (#'sess/gen-token props {:profile-id (:id profile)})
|
|
||||||
request {:params {:token token}}
|
request {:params {:token token}}
|
||||||
response (#'mgmt/authenticate th/*system* request)]
|
response (#'mgmt/authenticate th/*system* request)]
|
||||||
|
|
||||||
|
|||||||
@@ -514,8 +514,7 @@
|
|||||||
(t/is (= 0 (:call-count @mock))))))))
|
(t/is (= 0 (:call-count @mock))))))))
|
||||||
|
|
||||||
(t/deftest prepare-and-register-with-invitation-and-enabled-registration-1
|
(t/deftest prepare-and-register-with-invitation-and-enabled-registration-1
|
||||||
(let [sprops (:app.setup/props th/*system*)
|
(let [itoken (tokens/generate th/*system*
|
||||||
itoken (tokens/generate sprops
|
|
||||||
{:iss :team-invitation
|
{:iss :team-invitation
|
||||||
:exp (ct/in-future "48h")
|
:exp (ct/in-future "48h")
|
||||||
:role :editor
|
:role :editor
|
||||||
@@ -543,8 +542,7 @@
|
|||||||
(t/is (string? (:invitation-token result))))))
|
(t/is (string? (:invitation-token result))))))
|
||||||
|
|
||||||
(t/deftest prepare-and-register-with-invitation-and-enabled-registration-2
|
(t/deftest prepare-and-register-with-invitation-and-enabled-registration-2
|
||||||
(let [sprops (:app.setup/props th/*system*)
|
(let [itoken (tokens/generate th/*system*
|
||||||
itoken (tokens/generate sprops
|
|
||||||
{:iss :team-invitation
|
{:iss :team-invitation
|
||||||
:exp (ct/in-future "48h")
|
:exp (ct/in-future "48h")
|
||||||
:role :editor
|
:role :editor
|
||||||
@@ -565,8 +563,7 @@
|
|||||||
|
|
||||||
(t/deftest prepare-and-register-with-invitation-and-disabled-registration-1
|
(t/deftest prepare-and-register-with-invitation-and-disabled-registration-1
|
||||||
(with-redefs [app.config/flags [:disable-registration]]
|
(with-redefs [app.config/flags [:disable-registration]]
|
||||||
(let [sprops (:app.setup/props th/*system*)
|
(let [itoken (tokens/generate th/*system*
|
||||||
itoken (tokens/generate sprops
|
|
||||||
{:iss :team-invitation
|
{:iss :team-invitation
|
||||||
:exp (ct/in-future "48h")
|
:exp (ct/in-future "48h")
|
||||||
:role :editor
|
:role :editor
|
||||||
@@ -586,8 +583,7 @@
|
|||||||
|
|
||||||
(t/deftest prepare-and-register-with-invitation-and-disabled-registration-2
|
(t/deftest prepare-and-register-with-invitation-and-disabled-registration-2
|
||||||
(with-redefs [app.config/flags [:disable-registration]]
|
(with-redefs [app.config/flags [:disable-registration]]
|
||||||
(let [sprops (:app.setup/props th/*system*)
|
(let [itoken (tokens/generate th/*system*
|
||||||
itoken (tokens/generate sprops
|
|
||||||
{:iss :team-invitation
|
{:iss :team-invitation
|
||||||
:exp (ct/in-future "48h")
|
:exp (ct/in-future "48h")
|
||||||
:role :editor
|
:role :editor
|
||||||
@@ -608,8 +604,7 @@
|
|||||||
|
|
||||||
(t/deftest prepare-and-register-with-invitation-and-disabled-login-with-password
|
(t/deftest prepare-and-register-with-invitation-and-disabled-login-with-password
|
||||||
(with-redefs [app.config/flags [:disable-login-with-password]]
|
(with-redefs [app.config/flags [:disable-login-with-password]]
|
||||||
(let [sprops (:app.setup/props th/*system*)
|
(let [itoken (tokens/generate th/*system*
|
||||||
itoken (tokens/generate sprops
|
|
||||||
{:iss :team-invitation
|
{:iss :team-invitation
|
||||||
:exp (ct/in-future "48h")
|
:exp (ct/in-future "48h")
|
||||||
:role :editor
|
:role :editor
|
||||||
|
|||||||
@@ -208,8 +208,6 @@
|
|||||||
profile2 (th/create-profile* 2 {:is-active true})
|
profile2 (th/create-profile* 2 {:is-active true})
|
||||||
|
|
||||||
team (th/create-team* 1 {:profile-id (:id profile1)})
|
team (th/create-team* 1 {:profile-id (:id profile1)})
|
||||||
|
|
||||||
sprops (:app.setup/props th/*system*)
|
|
||||||
pool (:app.db/pool th/*system*)]
|
pool (:app.db/pool th/*system*)]
|
||||||
|
|
||||||
;; Try to invite a not existing user
|
;; Try to invite a not existing user
|
||||||
@@ -226,7 +224,7 @@
|
|||||||
(t/is (= 1 (-> out :result :total)))
|
(t/is (= 1 (-> out :result :total)))
|
||||||
|
|
||||||
(let [token (-> out :result :invitations first)
|
(let [token (-> out :result :invitations first)
|
||||||
claims (tokens/decode sprops token)]
|
claims (tokens/decode th/*system* token)]
|
||||||
(t/is (= :team-invitation (:iss claims)))
|
(t/is (= :team-invitation (:iss claims)))
|
||||||
(t/is (= (:id profile1) (:profile-id claims)))
|
(t/is (= (:id profile1) (:profile-id claims)))
|
||||||
(t/is (= :editor (:role claims)))
|
(t/is (= :editor (:role claims)))
|
||||||
@@ -250,7 +248,7 @@
|
|||||||
(t/is (= 1 (-> out :result :total)))
|
(t/is (= 1 (-> out :result :total)))
|
||||||
|
|
||||||
(let [token (-> out :result :invitations first)
|
(let [token (-> out :result :invitations first)
|
||||||
claims (tokens/decode sprops token)]
|
claims (tokens/decode th/*system* token)]
|
||||||
(t/is (= :team-invitation (:iss claims)))
|
(t/is (= :team-invitation (:iss claims)))
|
||||||
(t/is (= (:id profile1) (:profile-id claims)))
|
(t/is (= (:id profile1) (:profile-id claims)))
|
||||||
(t/is (= :editor (:role claims)))
|
(t/is (= :editor (:role claims)))
|
||||||
@@ -266,10 +264,9 @@
|
|||||||
|
|
||||||
team (th/create-team* 1 {:profile-id (:id profile1)})
|
team (th/create-team* 1 {:profile-id (:id profile1)})
|
||||||
|
|
||||||
sprops (:app.setup/props th/*system*)
|
|
||||||
pool (:app.db/pool th/*system*)]
|
pool (:app.db/pool th/*system*)]
|
||||||
|
|
||||||
(let [token (tokens/generate sprops
|
(let [token (tokens/generate th/*system*
|
||||||
{:iss :team-invitation
|
{:iss :team-invitation
|
||||||
:exp (ct/in-future "1h")
|
:exp (ct/in-future "1h")
|
||||||
:profile-id (:id profile1)
|
:profile-id (:id profile1)
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
[cuerdas.core :as str])
|
[cuerdas.core :as str])
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(:import
|
(:import
|
||||||
|
java.time.Clock
|
||||||
java.time.Duration
|
java.time.Duration
|
||||||
java.time.Instant
|
java.time.Instant
|
||||||
java.time.OffsetDateTime
|
java.time.OffsetDateTime
|
||||||
@@ -63,9 +64,11 @@
|
|||||||
java.time.temporal.TemporalAmount
|
java.time.temporal.TemporalAmount
|
||||||
java.time.temporal.TemporalUnit)))
|
java.time.temporal.TemporalUnit)))
|
||||||
|
|
||||||
|
#?(:clj (def ^:dynamic *clock* (Clock/systemDefaultZone)))
|
||||||
|
|
||||||
(defn now
|
(defn now
|
||||||
[]
|
[]
|
||||||
#?(:clj (Instant/now)
|
#?(:clj (Instant/now *clock*)
|
||||||
:cljs (new js/Date)))
|
:cljs (new js/Date)))
|
||||||
|
|
||||||
;; --- DURATION
|
;; --- DURATION
|
||||||
|
|||||||
Reference in New Issue
Block a user