mirror of
https://github.com/navidrome/navidrome.git
synced 2025-06-06 10:23:21 +03:00
feat: better way to detect initial account creation
This commit is contained in:
parent
730722cfe3
commit
10ead1f5f2
@ -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
43
server/app/serve_index.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user