mirror of
https://github.com/heyarne/airsonic-ui.git
synced 2026-05-07 02:33:39 +02:00
Save login credentials in local storage
Squashed commit of the following: commitb480676cefAuthor: Arne Schlüter <arne@schlueter.is> Date: Wed May 30 18:38:40 2018 +0200 Remember login credentials commited060e55b6Author: Arne Schlüter <arne@schlueter.is> Date: Wed May 30 14:45:11 2018 +0200 Add tests for auth process commitca8972f8c3Author: Arne Schlüter <arne@schlueter.is> Date: Wed May 30 13:34:38 2018 +0200 Make sure to always run tests in development
This commit is contained in:
parent
5929bc7581
commit
3376e01930
8 changed files with 111 additions and 46 deletions
|
|
@ -1,8 +1,11 @@
|
|||
(ns airsonic-ui.core
|
||||
(:require [reagent.core :as reagent]
|
||||
[re-frame.core :as re-frame]
|
||||
;; 3rd party effects / coeffects
|
||||
[day8.re-frame.http-fx]
|
||||
[airsonic-ui.audio] ; <- just registers effects
|
||||
[akiroz.re-frame.storage :as storage]
|
||||
;; our app
|
||||
[airsonic-ui.audio] ; <- just registers effects here
|
||||
[airsonic-ui.routes :as routes]
|
||||
[airsonic-ui.events :as events]
|
||||
[airsonic-ui.views :as views]
|
||||
|
|
@ -19,6 +22,9 @@
|
|||
|
||||
(defn ^:export init []
|
||||
(routes/start-routing!)
|
||||
(storage/reg-co-fx! :airsonic-ui {:fx :store
|
||||
:cofx :store})
|
||||
(re-frame/dispatch-sync [::events/initialize-db])
|
||||
(re-frame/dispatch [::events/try-remember-user])
|
||||
(dev-setup)
|
||||
(mount-root))
|
||||
|
|
|
|||
|
|
@ -2,6 +2,5 @@
|
|||
(:require [airsonic-ui.routes :as routes]))
|
||||
|
||||
(def default-db
|
||||
{:active-requests 0
|
||||
;; because navigate! executes asynchronously we force to display the login screen first
|
||||
{;; because navigate! executes asynchronously we force to display the login screen first
|
||||
:current-route [routes/default-route]})
|
||||
|
|
|
|||
|
|
@ -18,31 +18,51 @@
|
|||
(fn [_]
|
||||
db/default-db))
|
||||
|
||||
;; this is called with user and password to try and see if the credentials are
|
||||
;; correct; if yes, ::auth-success will be fired
|
||||
;; auth logic
|
||||
|
||||
(defn authenticate
|
||||
"Tries to authenticate a user by pinging the server with credentials, saving
|
||||
them when the request was succesful. Bypasses the request when a user saved
|
||||
their credentials."
|
||||
[{:keys [db]} [_ user pass server]]
|
||||
{:db (assoc-in db [:credentials :server] server)
|
||||
:http-xhrio {:method :get
|
||||
:uri (api/url server "ping" {:u user :p pass})
|
||||
:response-format (ajax/json-response-format {:keywords? true})
|
||||
:on-success [::credentials-verified user pass]
|
||||
:on-failure [::api-failure]}})
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::authenticate
|
||||
(fn [{:keys [db]} [_ user pass server]]
|
||||
{:db (-> (update db :active-requests inc)
|
||||
(assoc :server server))
|
||||
:http-xhrio {:method :get
|
||||
:uri (api/url server "ping" {:u user :p pass})
|
||||
:response-format (ajax/json-response-format {:keywords? true})
|
||||
:on-success [::auth-success user pass]
|
||||
:on-failure [::api-failure]}}))
|
||||
::authenticate authenticate)
|
||||
|
||||
;; TODO: Test that credentials are associated
|
||||
(defn try-remember-user
|
||||
"Enables skipping the auth request when credentials are saved in the
|
||||
local storage; otherwise has no effect"
|
||||
[{:keys [db store]} [_]]
|
||||
(when-let [credentials (:credentials store)]
|
||||
{:db (assoc-in db [:credentials :server] (:server credentials))
|
||||
:dispatch [::credentials-verified (:u credentials) (:p credentials) nil]}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::auth-success
|
||||
(fn [{:keys [db]} [_ user pass response]]
|
||||
;; TODO: Handle failures differently
|
||||
(let [login {:u user :p pass}]
|
||||
{:routes/set-credentials login
|
||||
:db (-> (update db :active-requests #(max (dec %) 0))
|
||||
(assoc :login login))
|
||||
:dispatch [::logged-in]})))
|
||||
::try-remember-user
|
||||
[(re-frame/inject-cofx :store)]
|
||||
try-remember-user)
|
||||
|
||||
(defn credentials-verified
|
||||
"Gets called after the server indicates that the credentials entered by a user
|
||||
are correct (see `authenticate`)"
|
||||
[{:keys [db store]} [_event user pass _response]]
|
||||
(let [auth {:u user :p pass}
|
||||
credentials (merge (:credentials db) auth)]
|
||||
{:routes/set-credentials auth
|
||||
:store {:credentials credentials}
|
||||
:db (assoc db :credentials credentials)
|
||||
:dispatch [::logged-in]}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::credentials-verified
|
||||
[(re-frame/inject-cofx :store)]
|
||||
credentials-verified)
|
||||
|
||||
;; TODO: We have to find another solution for this once we have routes that
|
||||
;; don't require a login but have the bottom controls
|
||||
|
|
@ -63,11 +83,15 @@
|
|||
;; TODO: Move these in the future? events.cljs should just do wiring. We could
|
||||
;; implement api.cljs as a completely independent module.
|
||||
|
||||
(defn- api-url [db endpoint params]
|
||||
(let [creds (:credentials db)]
|
||||
(api/url (:server creds) endpoint (merge params (select-keys creds [:u :p])))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
:api-request
|
||||
(fn [{:keys [db]} [_ endpoint k params]]
|
||||
{:http-xhrio {:method :get
|
||||
:uri (api/url (:server db) endpoint (merge params (:login db)))
|
||||
:uri (api-url db endpoint params)
|
||||
:response-format (ajax/json-response-format {:keywords? true})
|
||||
:on-success [::api-success k]
|
||||
:on-failure [::api-failure]}}))
|
||||
|
|
@ -88,11 +112,15 @@
|
|||
|
||||
; TODO: Make play, next and previous a bit prettier and more DRY
|
||||
|
||||
(defn- song-url [db song]
|
||||
(let [creds (:credentials db)]
|
||||
(api/song-url (:server creds) (select-keys creds [:u :p]) song)))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
; sets up the db, starts to play a song and adds the rest to a playlist
|
||||
::play-songs
|
||||
(fn [{:keys [db]} [_ songs song]]
|
||||
{:play-song (api/song-url (:server db) (:login db) song)
|
||||
{:play-song (song-url db song)
|
||||
:db (-> db
|
||||
(assoc-in [:currently-playing :item] song)
|
||||
(assoc-in [:currently-playing :playlist] songs))}))
|
||||
|
|
@ -104,7 +132,7 @@
|
|||
current (-> db :currently-playing :item)
|
||||
next (first (rest (drop-while #(not= % current) playlist)))]
|
||||
(when next
|
||||
{:play-song (api/song-url (:server db) (:login db) next)
|
||||
{:play-song (song-url db next)
|
||||
:db (assoc-in db [:currently-playing :item] next)}))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
|
|
@ -114,7 +142,7 @@
|
|||
current (-> db :currently-playing :item)
|
||||
previous (last (take-while #(not= % current) playlist))]
|
||||
(when previous
|
||||
{:play-song (api/song-url (:server db) (:login db) previous)
|
||||
{:play-song (song-url db previous)
|
||||
:db (assoc-in db [:currently-playing :item] previous)}))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@
|
|||
(:require [re-frame.core :as re-frame]))
|
||||
|
||||
;; can be used to query the user's credentials
|
||||
;; TODO: Organize login credentials and server location differently (i.e. together)
|
||||
|
||||
;; FIXME: this is used for cover images and it's quite ugly tbh
|
||||
(re-frame/reg-sub
|
||||
::login
|
||||
(fn [db]
|
||||
(:login db)))
|
||||
(select-keys (:credentials db) [:u :p])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::server
|
||||
(fn [db]
|
||||
(:server db)))
|
||||
(get-in db [:credentials :server])))
|
||||
|
||||
;; current hashbang
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue