blob: 2419eb23b774bcba97a9d1d8ad4d3585876f4639 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
(ns bbbg.web
(:require
[bbbg.discord.auth :as discord.auth :refer [wrap-discord-auth]]
[bbbg.handlers.attendee-checks :as attendee-checks]
[bbbg.handlers.attendees :as attendees]
[bbbg.handlers.core :refer [wrap-dynamic-auth]]
[bbbg.handlers.events :as events]
[bbbg.handlers.home :as home]
[bbbg.handlers.signup-form :as signup-form]
[bbbg.styles :refer [stylesheet]]
[bbbg.util.core :as u]
[bbbg.views.flash :refer [wrap-page-flash]]
clj-time.coerce
[clojure.spec.alpha :as s]
[com.stuartsierra.component :as component]
[compojure.core :refer [GET routes]]
[config.core :refer [env]]
[org.httpkit.server :as http-kit]
[ring.middleware.flash :refer [wrap-flash]]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]
[ring.middleware.params :refer [wrap-params]]
[ring.middleware.session :refer [wrap-session]]
[ring.middleware.session.cookie :refer [cookie-store]]
[ring.util.response :refer [content-type resource-response response]])
(:import
java.util.Base64))
(s/def ::port pos-int?)
(s/def ::cookie-secret
(s/and bytes? #(= 16 (count %))))
(s/def ::config
(s/merge
(s/keys :req [::port]
:opt [::cookie-secret])
::discord.auth/config))
(s/fdef make-server
:args (s/cat :config ::config))
(defn- string->cookie-secret [raw]
(s/assert
::cookie-secret
(when raw
(.decode (Base64/getDecoder)
(.getBytes raw "UTF-8")))))
(defn env->config []
(s/assert
::config
(u/remove-nils
(merge
{::port (:port env 8888)
::cookie-secret (some-> env :cookie-secret string->cookie-secret)}
(discord.auth/env->config)))))
(defn dev-config []
(s/assert
::config
(merge
{::port 8888
::cookie-secret (into-array Byte/TYPE (repeat 16 0))}
(discord.auth/dev-config))))
;;;
(defn app-routes [env]
(routes
(GET "/main.css" []
(-> (response stylesheet)
(content-type "text/css")))
(GET "/main.js" []
(-> (resource-response "main.js")
(content-type "text/javascript")))
(attendees/attendees-routes env)
(attendee-checks/attendee-checks-routes env)
(signup-form/signup-form-routes env)
(events/events-routes env)
(home/home-routes env)))
(defn middleware [app env]
(-> app
wrap-dynamic-auth
(wrap-discord-auth env)
wrap-keyword-params
wrap-params
wrap-page-flash
wrap-flash
(wrap-session {:store (cookie-store
{:key (:cookie-secret env)
:readers {'clj-time/date-time
clj-time.coerce/from-string}})
:cookie-attrs {:same-site :lax}})))
(defn handler [env]
(-> (app-routes env)
(middleware env)))
(defrecord WebServer [port cookie-secret db]
component/Lifecycle
(start [this]
(assoc this
::shutdown-fn
(http-kit/run-server
(fn [r] ((handler this) r))
{:port port})))
(stop [this]
(if-let [shutdown-fn (::shutdown-fn this)]
(do (shutdown-fn :timeout 100)
(dissoc this ::shutdown-fn))
this)))
(defn make-server [{::keys [port cookie-secret]
:as env}]
(component/using
(map->WebServer
(merge
{:port port
:cookie-secret cookie-secret}
env))
[:db]))
|