Bundle and serve admin (#317)
* WIP with admin bundling * Current state of the admin is bundled * Update admin bundler to work with binary bundling * Log detail about the admin interface. Closes #312 * Move bundle script to the build dir * Update to current version of admin * Commit updated API documentation Co-authored-by: Owncast <owncast@owncast.online>
This commit is contained in:
parent
2517e9944e
commit
1dbd550134
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,6 +25,7 @@ webroot/static/content.md
|
|||||||
hls/
|
hls/
|
||||||
dist/
|
dist/
|
||||||
data/
|
data/
|
||||||
|
admin/
|
||||||
transcoder.log
|
transcoder.log
|
||||||
chat.db
|
chat.db
|
||||||
.yp.key
|
.yp.key
|
||||||
|
40
build/admin/bundleAdmin.sh
Executable file
40
build/admin/bundleAdmin.sh
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
INSTALL_TEMP_DIRECTORY="$(mktemp -d)"
|
||||||
|
PROJECT_SOURCE_DIR=$(pwd)
|
||||||
|
cd $INSTALL_TEMP_DIRECTORY
|
||||||
|
|
||||||
|
shutdown () {
|
||||||
|
rm -rf "$PROJECT_SOURCE_DIR/admin"
|
||||||
|
rm -rf "$INSTALL_TEMP_DIRECTORY"
|
||||||
|
}
|
||||||
|
trap shutdown INT TERM ABRT EXIT
|
||||||
|
|
||||||
|
echo "Cloning owncast admin into $INSTALL_TEMP_DIRECTORY..."
|
||||||
|
git clone --depth 1 https://github.com/owncast/owncast-admin 2> /dev/null
|
||||||
|
cd owncast-admin
|
||||||
|
|
||||||
|
echo "Installing npm modules for the owncast admin..."
|
||||||
|
npm --silent install 2> /dev/null
|
||||||
|
|
||||||
|
echo "Building owncast admin..."
|
||||||
|
rm -rf .next
|
||||||
|
(node_modules/.bin/next build && node_modules/.bin/next export) | grep info
|
||||||
|
|
||||||
|
echo "Copying admin to project directory..."
|
||||||
|
ADMIN_BUILD_DIR=$(pwd)
|
||||||
|
cd $PROJECT_SOURCE_DIR
|
||||||
|
mkdir -p admin 2> /dev/null
|
||||||
|
cd admin
|
||||||
|
cp -R ${ADMIN_BUILD_DIR}/out/* .
|
||||||
|
|
||||||
|
echo "Bundling admin into owncast codebase..."
|
||||||
|
~/go/bin/pkger
|
||||||
|
|
||||||
|
shutdown
|
||||||
|
echo "Done."
|
44
controllers/admin/index.go
Normal file
44
controllers/admin/index.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"mime"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger"
|
||||||
|
"github.com/owncast/owncast/router/middleware"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServeAdmin will return admin web assets
|
||||||
|
func ServeAdmin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Set a cache control max-age header
|
||||||
|
middleware.SetCachingHeaders(w, r)
|
||||||
|
|
||||||
|
path := r.URL.Path
|
||||||
|
if path == "/admin" || path == "/admin/" {
|
||||||
|
path = "/admin/index.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := pkger.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err, path)
|
||||||
|
errorHandler(w, r, http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mimeType := mime.TypeByExtension(filepath.Ext(path))
|
||||||
|
w.Header().Set("Content-Type", mimeType)
|
||||||
|
w.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorHandler(w http.ResponseWriter, r *http.Request, status int) {
|
||||||
|
w.WriteHeader(status)
|
||||||
|
}
|
@ -28,7 +28,6 @@ type MetadataPage struct {
|
|||||||
//IndexHandler handles the default index route
|
//IndexHandler handles the default index route
|
||||||
func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
middleware.EnableCors(&w)
|
middleware.EnableCors(&w)
|
||||||
|
|
||||||
isIndexRequest := r.URL.Path == "/" || filepath.Base(r.URL.Path) == "index.html" || filepath.Base(r.URL.Path) == ""
|
isIndexRequest := r.URL.Path == "/" || filepath.Base(r.URL.Path) == "index.html" || filepath.Base(r.URL.Path) == ""
|
||||||
|
|
||||||
// For search engine bots and social scrapers return a special
|
// For search engine bots and social scrapers return a special
|
||||||
|
@ -65,6 +65,10 @@ func Start() error {
|
|||||||
// start the rtmp server
|
// start the rtmp server
|
||||||
go rtmp.Start(setStreamAsConnected, setBroadcaster)
|
go rtmp.Start(setStreamAsConnected, setBroadcaster)
|
||||||
|
|
||||||
|
port := config.Config.GetPublicWebServerPort()
|
||||||
|
log.Infof("Web server is listening on port %d, RTMP is accepting inbound streams on port 1935.", port)
|
||||||
|
log.Infoln("The web admin interface is available at /admin.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ func Start(setStreamAsConnected func(), setBroadcaster func(models.Broadcaster))
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
log.Infof("RTMP server is listening for incoming stream on port: %d", port)
|
log.Tracef("RTMP server is listening for incoming stream on port: %d", port)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
nc, err := lis.Accept()
|
nc, err := lis.Accept()
|
||||||
|
1
go.mod
1
go.mod
@ -8,6 +8,7 @@ require (
|
|||||||
github.com/aws/aws-sdk-go v1.35.22
|
github.com/aws/aws-sdk-go v1.35.22
|
||||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||||
github.com/grafov/m3u8 v0.11.1
|
github.com/grafov/m3u8 v0.11.1
|
||||||
|
github.com/markbates/pkger v0.17.1
|
||||||
github.com/mattn/go-sqlite3 v1.14.4
|
github.com/mattn/go-sqlite3 v1.14.4
|
||||||
github.com/microcosm-cc/bluemonday v1.0.4
|
github.com/microcosm-cc/bluemonday v1.0.4
|
||||||
github.com/mssola/user_agent v0.5.2
|
github.com/mssola/user_agent v0.5.2
|
||||||
|
7
go.sum
7
go.sum
@ -13,6 +13,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||||
|
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
|
||||||
|
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
||||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||||
github.com/grafov/m3u8 v0.11.1 h1:igZ7EBIB2IAsPPazKwRKdbhxcoBKO3lO1UY57PZDeNA=
|
github.com/grafov/m3u8 v0.11.1 h1:igZ7EBIB2IAsPPazKwRKdbhxcoBKO3lO1UY57PZDeNA=
|
||||||
@ -21,9 +23,12 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
|
|||||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
|
||||||
|
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
||||||
github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI=
|
github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI=
|
||||||
github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
|
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
|
||||||
@ -79,9 +84,11 @@ golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
|||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
4
main.go
4
main.go
@ -4,6 +4,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger"
|
||||||
"github.com/owncast/owncast/logging"
|
"github.com/owncast/owncast/logging"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -29,6 +30,8 @@ func main() {
|
|||||||
configureLogging()
|
configureLogging()
|
||||||
|
|
||||||
log.Infoln(getReleaseString())
|
log.Infoln(getReleaseString())
|
||||||
|
// Enable bundling of admin assets
|
||||||
|
pkger.Include("/admin")
|
||||||
|
|
||||||
configFile := flag.String("configFile", "config.yaml", "Config File full path. Defaults to current folder")
|
configFile := flag.String("configFile", "config.yaml", "Config File full path. Defaults to current folder")
|
||||||
dbFile := flag.String("database", "", "Path to the database file.")
|
dbFile := flag.String("database", "", "Path to the database file.")
|
||||||
@ -72,7 +75,6 @@ func main() {
|
|||||||
log.Error("failed to start/run the router")
|
log.Error("failed to start/run the router")
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//getReleaseString gets the version string
|
//getReleaseString gets the version string
|
||||||
|
@ -19,6 +19,9 @@ func Start() error {
|
|||||||
// static files
|
// static files
|
||||||
http.HandleFunc("/", controllers.IndexHandler)
|
http.HandleFunc("/", controllers.IndexHandler)
|
||||||
|
|
||||||
|
// admin static files
|
||||||
|
http.HandleFunc("/admin/", middleware.RequireAdminAuth(admin.ServeAdmin))
|
||||||
|
|
||||||
// status of the system
|
// status of the system
|
||||||
http.HandleFunc("/api/status", controllers.GetStatus)
|
http.HandleFunc("/api/status", controllers.GetStatus)
|
||||||
|
|
||||||
@ -76,7 +79,7 @@ func Start() error {
|
|||||||
|
|
||||||
port := config.Config.GetPublicWebServerPort()
|
port := config.Config.GetPublicWebServerPort()
|
||||||
|
|
||||||
log.Infof("Web server running on port: %d", port)
|
log.Tracef("Web server running on port: %d", port)
|
||||||
|
|
||||||
return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
|
return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
PROJECT_SOURCE_DIR=$(pwd)
|
|
||||||
mkdir $TMPDIR/admin 2> /dev/null
|
|
||||||
cd $TMPDIR/admin
|
|
||||||
git clone --depth 1 https://github.com/owncast/owncast-admin 2> /dev/null
|
|
||||||
cd owncast-admin
|
|
||||||
npm --silent install 2> /dev/null
|
|
||||||
(node_modules/.bin/next build && node_modules/.bin/next export) | grep info
|
|
||||||
ADMIN_BUILD_DIR=$(pwd)
|
|
||||||
cd $PROJECT_SOURCE_DIR
|
|
||||||
mkdir webroot/admin 2> /dev/null
|
|
||||||
cd webroot/admin
|
|
||||||
cp -R ${ADMIN_BUILD_DIR}/out/* .
|
|
||||||
rm -rf $TMPDIR/admin
|
|
Loading…
x
Reference in New Issue
Block a user