Skip to content

Commit 2357053

Browse files
authored
Merge pull request mtgred#8527 from NBKelly/ip-ban-functionality
ip ban framework
2 parents 75eac11 + 9352382 commit 2357053

4 files changed

Lines changed: 186 additions & 17 deletions

File tree

‎src/clj/web/admin.clj‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
[web.versions :refer [frontend-version banned-msg]]
1313
[web.ws :as ws]))
1414

15+
(defn- last-ip-address
16+
"Legacy because I got it wrong the first time"
17+
[user]
18+
(or (:last-ip-address user) (:lastIpAddress user)))
19+
1520
(defmethod ws/-msg-handler :admin/announce
1621
admin--announce
1722
[{{user :user} :ring-req
@@ -116,6 +121,76 @@
116121
(ws/broadcast-to! [uid] :admin/user-edit {:error "Not found"})))
117122
(ws/broadcast-to! [uid] :admin/user-edit {:error "Not allowed"})))
118123

124+
(def ip-ban-collection "ip-bans")
125+
126+
(defmethod ws/-msg-handler :admin/look-up-ip
127+
admin--look-up-ip
128+
[{{db :system/db user :user} :ring-req
129+
{:keys [username] :as data} :?data
130+
uid :uid}]
131+
(if (and (active-user? user)
132+
(or (:ismoderator user) (:isadmin user)))
133+
(if-let [res (mc/find-one-as-map db user-collection {:username username}
134+
{:username 1
135+
:lastIpAddress 1
136+
:last-ip-address 1
137+
:_id 0})]
138+
(ws/broadcast-to! [uid] :admin/look-up-ip {:success (-> res
139+
(dissoc :lastIpAddress)
140+
(assoc :last-ip-address (last-ip-address res)))})
141+
(ws/broadcast-to! [uid] :admin/look-up-ip {:error "Not found"}))
142+
(ws/broadcast-to! [uid] :admin/look-up-ip {:error "Not allowed"})))
143+
144+
(defmethod ws/-msg-handler :admin/fetch-ip-bans
145+
admin--fetch-ip-bans
146+
[{{db :system/db user :user} :ring-req
147+
uid :uid}]
148+
(if (and (active-user? user)
149+
(or (:ismoderator user) (:isadmin user)))
150+
(let [ip-bans (mc/find-maps db ip-ban-collection {}
151+
{:username 1
152+
:ip-address 1
153+
:_id 0})]
154+
(ws/broadcast-to! [uid] :admin/fetch-ip-bans {:success ip-bans}))
155+
(ws/broadcast-to! [uid] :admin/fetch-ip-bans {:error "Not allowed"})))
156+
157+
(defmethod ws/-msg-handler :admin/ip-ban-user
158+
admin--ip-ban-user
159+
[{{db :system/db user :user} :ring-req
160+
{:keys [username] :as data} :?data
161+
uid :uid}]
162+
(if (and (active-user? user)
163+
(or (:ismoderator user) (:isadmin user)))
164+
(if-let [res (mc/find-one-as-map db user-collection {:username username}
165+
{:username 1
166+
:lastIpAddress 1
167+
:last-ip-address 1
168+
:_id 0})]
169+
(if-let [ip (last-ip-address res)]
170+
(do
171+
(prn "res: " res)
172+
(prn "ip: " ip)
173+
(mc/insert db ip-ban-collection {:username username :ip-address ip})
174+
(ws/broadcast-to! [uid] :admin/ip-ban-user {:success {:username username
175+
:ip-address ip}}))
176+
(ws/broadcast-to! [uid] :admin/ip-ban-user {:error "Legacy user? No IP Address on record"}))
177+
(ws/broadcast-to! [uid] :admin/ip-ban-user {:error "Not found"}))
178+
(ws/broadcast-to! [uid] :admin/ip-ban-user {:error "Not allowed"})))
179+
180+
(defmethod ws/-msg-handler :admin/ip-unban-user
181+
admin--ip-unban-user
182+
[{{db :system/db user :user} :ring-req
183+
{:keys [username] :as data} :?data
184+
uid :uid}]
185+
(if (and (active-user? user)
186+
(or (:ismoderator user) (:isadmin user)))
187+
(let [result (mc/remove db ip-ban-collection {:username username})
188+
n (.getN result)]
189+
(if (pos? n)
190+
(ws/broadcast-to! [uid] :admin/ip-unban-user {:success username})
191+
(ws/broadcast-to! [uid] :admin/ip-unban-user {:error "Not found"})))
192+
(ws/broadcast-to! [uid] :admin/ip-unban-user {:error "Not allowed"})))
193+
119194
(defmethod ws/-msg-handler :admin/fetch-users
120195
admin--fetch-users
121196
[{{db :system/db user :user} :ring-req

‎src/clj/web/auth.clj‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,20 @@
107107
;; note - if the user is behind a proxy, their IP will be the first on in x-forwarded-for
108108
;; otherwise it will just be the remote-addr key for the request.
109109
;; I'm hoping the nginx reverese proxy plays nice with this...
110-
(let [client-ip (if-let [ips (get-in headers ["x-forwarded-for"])]
111-
(-> ips (str/split #",") first)
112-
remote-address)
110+
(let [client-ip (or (some-> headers (get "x-forwarded-for") (str/split #",") first)
111+
(some-> headers (get "x-real-ip"))
112+
remote-address)
113113
user (mc/find-one-as-map db "users" {:username username})]
114114
(cond
115-
(and user (:banned user)) (response 403 {:error (or @banned-msg "Account Locked")})
115+
(and user (password/check password (:password user)) (:banned user))
116+
(response 403 {:error (or @banned-msg "Account Locked")})
117+
(and user (password/check password (:password user)) (mc/find-one-as-map db "ip-bans" {:ip-address client-ip}))
118+
(response 403 {:error (or @banned-msg "Account Locked")})
116119
(and user (password/check password (:password user)))
117120
(do (mc/update db "users"
118121
{:username username}
119-
{"$set" {:lastConnection (inst/now)
120-
:lastIpAddress (str client-ip)}})
122+
{"$set" {:last-connection (inst/now)
123+
:last-ip-address (str client-ip)}})
121124
(assoc (response 200 {:message "ok"})
122125
:cookies {"session" (merge {:value (create-token auth user)}
123126
(:cookie auth))}))

‎src/cljs/nr/admin.cljs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@
178178
:on-change #(update-pause-game-creation (.. % -target -checked))}]
179179
" Pause new game creation (allows draining games before maintenance)"]]]))
180180

181-
182181
(defn admin []
183182
(r/with-let [user (r/cursor app-state [:user])]
184183
[:div.page-container

‎src/cljs/nr/users.cljs‎

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,33 @@
2323
{}
2424
success))))
2525

26+
(defmethod ws/event-msg-handler :admin/fetch-ip-bans
27+
[{{success :success} :?data}]
28+
(when success
29+
(swap! users-state assoc :ip-banned success)))
30+
31+
(defmethod ws/event-msg-handler :admin/look-up-ip
32+
[{{:keys [error success]} :?data}]
33+
(if success
34+
(let [{:keys [username last-ip-address]} success]
35+
(prn "success: " success)
36+
(swap! users-state assoc :ip-lookup-name username :ip-lookup-result last-ip-address))
37+
(non-game-toast error nil)))
38+
39+
(defmethod ws/event-msg-handler :admin/ip-ban-user
40+
[{{:keys [error success]} :?data}]
41+
(if success
42+
(let [{:keys [username ip-address]} success]
43+
(swap! users-state update :ip-banned conj {:username username :ip-address ip-address}))
44+
(non-game-toast error nil)))
45+
46+
(defmethod ws/event-msg-handler :admin/ip-unban-user
47+
[{{:keys [error success]} :?data}]
48+
(if success
49+
(let [{:keys [username ip-address]} success]
50+
(swap! users-state update :ip-banned #(filterv (fn [m] (not= username (:username m))) %)))
51+
(non-game-toast error nil)))
52+
2653
(defmethod ws/event-msg-handler :admin/user-edit
2754
[{{:keys [error success]} :?data}]
2855
(cond
@@ -70,6 +97,36 @@
7097
"Remove"]]
7198
[:span.title (:username d "")]]))]])
7299

100+
(defn- ip-bans-list [users]
101+
;; here it's a list of {:username ... :address ...}
102+
[:div.users-box.panel.blue-shade
103+
[:ul.list
104+
(doall
105+
(for [d (sort-by #(str/lower-case (:username %)) @users)]
106+
[:li.users-item
107+
{:key (:username d)}
108+
[:span
109+
[:button.delete
110+
{:on-click #(ws/ws-send! [:admin/ip-unban-user {:username (:username d)}])}
111+
"Remove"]]
112+
[:span.title (:username d "") " - " (:ip-address d)]]))]])
113+
114+
(defn- ip-ban-user-add [state state-key]
115+
[:form.msg-box {:on-submit #(let [username (state-key @state "")]
116+
(.preventDefault %)
117+
(when-not (str/blank? username)
118+
(ws/ws-send! [:admin/ip-ban-user {:username username}])
119+
(swap! state assoc state-key "")))}
120+
[:input {:type "text"
121+
:placeholder "Type username"
122+
:value (state-key @state "")
123+
:on-change #(swap! state assoc state-key (-> % .-target .-value))}]
124+
(let [username (state-key @state "")
125+
disabled (str/blank? username)]
126+
[:button {:disabled disabled
127+
:class (if disabled "disabled" "")}
128+
"IP Ban User"])])
129+
73130
(defn- user-add [state state-key add-fn]
74131
[:form.msg-box {:on-submit #(let [username (state-key @state "")]
75132
(.preventDefault %)
@@ -86,11 +143,35 @@
86143
:class (if disabled "disabled" "")}
87144
"Add"])])
88145

146+
(defn- ip-lookup-box [state state-key]
147+
(fn []
148+
[:form.msg-box {:on-submit #(let [username (state-key @state "")]
149+
(.preventDefault %)
150+
(when-not (str/blank? username)
151+
(ws/ws-send! [:admin/look-up-ip {:username username}])))}
152+
[:input {:type "text"
153+
:placeholder "Type username"
154+
:value (state-key @state "")
155+
:on-change #(swap! state assoc state-key (-> % .-target .-value))}]
156+
[:input {:type "text"
157+
:read-only true
158+
:value (:ip-lookup-result @state "")
159+
:placeholder "Look up an IP"}]
160+
(let [username (state-key @state "")
161+
disabled (str/blank? username)]
162+
[:button {:disabled disabled
163+
:class (if disabled "disabled" "")}
164+
"Search"])]))
165+
166+
167+
168+
89169
(defn users-container []
90170
(r/with-let [mods (r/cursor users-state [:mods])
91171
specials (r/cursor users-state [:specials])
92172
tos (r/cursor users-state [:tos])
93-
banned (r/cursor users-state [:banned])]
173+
banned (r/cursor users-state [:banned])
174+
ip-bans (r/cursor users-state [:ip-banned])]
94175
(let [s (r/atom {})
95176
rows [{:h3 "Moderators"
96177
:cursor mods
@@ -109,19 +190,30 @@
109190
:key :banned
110191
:h4 "Ban user"}]]
111192
(fn []
112-
(into [:div.container.panel.blue-shade.content-page]
113-
(->> (for [row rows]
114-
[[:h3 (:h3 row)]
115-
(users-list (:cursor row) (remove-user (:key row)))
116-
[:h4 (:h4 row)]
117-
(user-add s (:key row) (add-user (:key row)))])
118-
(interpose [[:br]])
119-
(mapcat identity)
120-
(map-indexed (fn [idx itm] ^{:key idx} itm))))))))
193+
[:div.container.panel.blue-shade.content-page
194+
(into [:div]
195+
(->> (for [{:keys [h3 cursor key h4] :as row} rows]
196+
;; (if (= key :ip-bans)
197+
;; [[:h3 (:h3 row)]
198+
[[:h3 h3]
199+
(users-list cursor (remove-user key))
200+
[:h4 h4]
201+
(user-add s key (add-user key))])
202+
(interpose [[:br]])
203+
(mapcat identity)
204+
(map-indexed (fn [idx itm] ^{:key idx} itm))))
205+
[:br]
206+
[:h3 "IP Lookup"]
207+
[ip-lookup-box users-state :ip-lookup-name]
208+
[:br]
209+
[:h3 "Ip Bans"]
210+
[ip-bans-list ip-bans]
211+
[ip-ban-user-add users-state :ip-ban-name]]))))
121212

122213
(defn users []
123214
(r/with-let [user (r/cursor app-state [:user])]
124215
(ws/ws-send! [:admin/fetch-users])
216+
(ws/ws-send! [:admin/fetch-ip-bans])
125217
[:div.page-container
126218
[:div.account-bg]
127219
(when (or (:isadmin @user) (:ismoderator @user))

0 commit comments

Comments
 (0)