feat: better way to detect initial account creation

This commit is contained in:
Deluan 2020-02-08 13:43:14 -05:00
parent 730722cfe3
commit 10ead1f5f2
5 changed files with 77 additions and 47 deletions

View File

@ -49,6 +49,7 @@ func (app *Router) routes() http.Handler {
}) })
// Serve UI app assets // Serve UI app assets
r.Handle("/", ServeIndex(app.ds))
r.Handle("/*", http.StripPrefix(app.path, http.FileServer(assets.AssetFile()))) r.Handle("/*", http.StripPrefix(app.path, http.FileServer(assets.AssetFile())))
return r return r

43
server/app/serve_index.go Normal file
View File

@ -0,0 +1,43 @@
package app
import (
"encoding/json"
"html/template"
"io/ioutil"
"net/http"
"github.com/deluan/navidrome/assets"
"github.com/deluan/navidrome/log"
"github.com/deluan/navidrome/model"
)
// Injects the `firstTime` config in the `index.html` template
func ServeIndex(ds model.DataStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
c, err := ds.User(r.Context()).CountAll()
firstTime := c == 0 && err == nil
t := template.New("initial state")
fs := assets.AssetFile()
indexHtml, err := fs.Open("index.html")
if err != nil {
log.Error(r, "Could not find `index.html` template", err)
}
indexStr, err := ioutil.ReadAll(indexHtml)
if err != nil {
log.Error(r, "Could not read from `index.html`", err)
}
t, _ = t.Parse(string(indexStr))
appConfig := map[string]interface{}{
"firstTime": firstTime,
}
j, _ := json.Marshal(appConfig)
data := map[string]interface{}{
"AppConfig": string(j),
}
err = t.Execute(w, data)
if err != nil {
log.Error(r, "Could not execute `index.html` template", err)
}
}
}

View File

@ -25,6 +25,9 @@
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>Navidrome</title> <title>Navidrome</title>
<script>
window.__APP_CONFIG__ = "{{.AppConfig}}"
</script>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react' import React from 'react'
import { Admin, resolveBrowserLocale, Resource } from 'react-admin' import { Admin, resolveBrowserLocale, Resource } from 'react-admin'
import dataProvider from './dataProvider' import dataProvider from './dataProvider'
import authProvider from './authProvider' import authProvider from './authProvider'
@ -19,7 +19,17 @@ const i18nProvider = polyglotI18nProvider(
resolveBrowserLocale() resolveBrowserLocale()
) )
const App = () => ( const App = () => {
try {
const appConfig = JSON.parse(window.__APP_CONFIG__)
// This flags to the login process that it should create the first account instead
if (appConfig.firstTime) {
localStorage.setItem('initialAccountCreation', 'true')
}
} catch (e) {}
return (
<Admin <Admin
theme={theme} theme={theme}
customReducers={{ queue: playQueueReducer }} customReducers={{ queue: playQueueReducer }}
@ -37,30 +47,7 @@ const App = () => (
<Player /> <Player />
]} ]}
</Admin> </Admin>
) )
// TODO: This is a complicated way to force a first check for initial setup. A better way would be to send this info
// set in the `window` object in the index.html
const AppWrapper = () => {
const [checked, setChecked] = useState(false)
if (!checked) {
dataProvider
.getOne('keepalive', { id: new Date().getTime() })
.then(() => setChecked(true))
.catch((err) => {
authProvider
.checkError(err)
.then(() => {
setChecked(true)
})
.catch(() => {
setChecked(true)
})
})
return null
}
return <App />
} }
export default AppWrapper export default App

View File

@ -56,11 +56,7 @@ const authProvider = {
checkAuth: () => checkAuth: () =>
localStorage.getItem('token') ? Promise.resolve() : Promise.reject(), localStorage.getItem('token') ? Promise.resolve() : Promise.reject(),
checkError: (error) => { checkError: ({ status }) => {
const { status, message } = error
if (message === 'no users created') {
localStorage.setItem('initialAccountCreation', 'true')
}
if (status === 401 || status === 403) { if (status === 401 || status === 403) {
removeItems() removeItems()
return Promise.reject() return Promise.reject()