2021-02-17 20:29:20 +01:00
|
|
|
// Package classification Focalboard Server
|
|
|
|
//
|
|
|
|
// Server for Focalboard
|
|
|
|
//
|
|
|
|
// Schemes: http, https
|
|
|
|
// Host: localhost
|
|
|
|
// BasePath: /api/v1
|
2021-03-08 18:36:14 +01:00
|
|
|
// Version: 1.0.0
|
2021-02-17 20:29:20 +01:00
|
|
|
// License: Custom https://github.com/mattermost/focalboard/blob/main/LICENSE.txt
|
|
|
|
// Contact: Focalboard<api@focalboard.com> https://www.focalboard.com
|
|
|
|
//
|
|
|
|
// Consumes:
|
|
|
|
// - application/json
|
|
|
|
//
|
|
|
|
// Produces:
|
|
|
|
// - application/json
|
|
|
|
//
|
|
|
|
// securityDefinitions:
|
|
|
|
// BearerAuth:
|
|
|
|
// type: apiKey
|
|
|
|
// name: Authorization
|
|
|
|
// in: header
|
|
|
|
// description: 'Pass session token using Bearer authentication, e.g. set header "Authorization: Bearer <session token>"'
|
|
|
|
//
|
|
|
|
// swagger:meta
|
2020-10-08 18:21:27 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-03-01 20:36:36 +01:00
|
|
|
"C"
|
2020-10-08 18:21:27 +02:00
|
|
|
"flag"
|
|
|
|
"log"
|
|
|
|
"os"
|
2021-03-01 20:36:36 +01:00
|
|
|
"os/signal"
|
2020-10-22 15:22:36 +02:00
|
|
|
"syscall"
|
|
|
|
"time"
|
2020-10-16 19:12:53 +02:00
|
|
|
|
2021-01-26 23:13:46 +01:00
|
|
|
"github.com/mattermost/focalboard/server/model"
|
|
|
|
"github.com/mattermost/focalboard/server/server"
|
|
|
|
"github.com/mattermost/focalboard/server/services/config"
|
2020-10-08 18:21:27 +02:00
|
|
|
)
|
|
|
|
|
2021-03-01 20:36:36 +01:00
|
|
|
// Active server used with shared code (dll)
|
|
|
|
var pServer *server.Server
|
2020-10-08 18:21:27 +02:00
|
|
|
|
2020-10-22 13:34:42 +02:00
|
|
|
const (
|
|
|
|
timeBetweenPidMonitoringChecks = 2 * time.Second
|
|
|
|
)
|
|
|
|
|
2020-10-08 18:21:27 +02:00
|
|
|
func isProcessRunning(pid int) bool {
|
|
|
|
process, err := os.FindProcess(pid)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
err = process.Signal(syscall.Signal(0))
|
2020-10-22 15:22:36 +02:00
|
|
|
|
2020-10-18 02:07:35 +02:00
|
|
|
return err == nil
|
2020-10-08 18:21:27 +02:00
|
|
|
}
|
|
|
|
|
2021-03-01 20:36:36 +01:00
|
|
|
// monitorPid is used to keep the server lifetime in sync with another (client app) process
|
2020-10-08 18:21:27 +02:00
|
|
|
func monitorPid(pid int) {
|
|
|
|
log.Printf("Monitoring PID: %d", pid)
|
2020-10-22 13:34:42 +02:00
|
|
|
|
2020-10-08 18:21:27 +02:00
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
if !isProcessRunning(pid) {
|
|
|
|
log.Printf("Monitored process not found, exiting.")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2020-10-22 13:34:42 +02:00
|
|
|
|
|
|
|
time.Sleep(timeBetweenPidMonitoringChecks)
|
2020-10-08 18:21:27 +02:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2021-03-01 20:36:36 +01:00
|
|
|
func logInfo() {
|
|
|
|
log.Println("Focalboard Server")
|
2021-01-19 23:10:14 +01:00
|
|
|
log.Println("Version: " + model.CurrentVersion)
|
|
|
|
log.Println("Edition: " + model.Edition)
|
|
|
|
log.Println("Build Number: " + model.BuildNumber)
|
|
|
|
log.Println("Build Date: " + model.BuildDate)
|
|
|
|
log.Println("Build Hash: " + model.BuildHash)
|
2021-03-01 20:36:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
logInfo()
|
2021-01-19 23:10:14 +01:00
|
|
|
|
2020-10-08 18:21:27 +02:00
|
|
|
// config.json file
|
2020-10-16 19:12:53 +02:00
|
|
|
config, err := config.ReadConfigFile()
|
2020-10-09 10:27:20 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal("Unable to read the config file: ", err)
|
|
|
|
return
|
|
|
|
}
|
2020-10-08 18:21:27 +02:00
|
|
|
|
|
|
|
// Command line args
|
|
|
|
pMonitorPid := flag.Int("monitorpid", -1, "a process ID")
|
|
|
|
pPort := flag.Int("port", config.Port, "the port number")
|
2021-02-11 19:13:17 +01:00
|
|
|
pSingleUser := flag.Bool("single-user", false, "single user mode")
|
2021-03-01 20:36:36 +01:00
|
|
|
pDBType := flag.String("dbtype", "", "Database type")
|
|
|
|
pDBConfig := flag.String("dbconfig", "", "Database config")
|
2020-12-04 16:03:09 +01:00
|
|
|
flag.Parse()
|
|
|
|
|
2021-02-11 19:13:17 +01:00
|
|
|
singleUser := false
|
|
|
|
if pSingleUser != nil {
|
|
|
|
singleUser = *pSingleUser
|
|
|
|
}
|
|
|
|
|
2021-02-09 21:27:34 +01:00
|
|
|
singleUserToken := ""
|
2021-02-11 19:13:17 +01:00
|
|
|
if singleUser {
|
|
|
|
singleUserToken = os.Getenv("FOCALBOARD_SINGLE_USER_TOKEN")
|
|
|
|
if len(singleUserToken) < 1 {
|
|
|
|
log.Fatal("The FOCALBOARD_SINGLE_USER_TOKEN environment variable must be set for single user mode ")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
log.Printf("Single user mode")
|
2020-12-04 11:28:35 +01:00
|
|
|
}
|
2020-10-08 18:21:27 +02:00
|
|
|
|
|
|
|
if pMonitorPid != nil && *pMonitorPid > 0 {
|
|
|
|
monitorPid(*pMonitorPid)
|
|
|
|
}
|
|
|
|
|
2021-03-01 20:36:36 +01:00
|
|
|
// Override config from commandline
|
|
|
|
|
|
|
|
if pDBType != nil && len(*pDBType) > 0 {
|
|
|
|
config.DBType = *pDBType
|
|
|
|
log.Printf("DBType from commandline: %s", *pDBType)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pDBConfig != nil && len(*pDBConfig) > 0 {
|
|
|
|
config.DBConfigString = *pDBConfig
|
|
|
|
// Don't echo, as the confix string may contain passwords
|
|
|
|
log.Printf("DBConfigString overriden from commandline")
|
|
|
|
}
|
|
|
|
|
2020-10-08 18:21:27 +02:00
|
|
|
if pPort != nil && *pPort > 0 && *pPort != config.Port {
|
|
|
|
// Override port
|
|
|
|
log.Printf("Port from commandline: %d", *pPort)
|
|
|
|
config.Port = *pPort
|
|
|
|
}
|
|
|
|
|
2021-02-09 21:27:34 +01:00
|
|
|
server, err := server.New(config, singleUserToken)
|
2020-10-09 10:08:38 +02:00
|
|
|
if err != nil {
|
2021-01-20 22:52:25 +01:00
|
|
|
log.Fatal("server.New ERROR: ", err)
|
2020-10-09 10:08:38 +02:00
|
|
|
}
|
2020-10-08 18:21:27 +02:00
|
|
|
|
2020-10-16 16:21:42 +02:00
|
|
|
if err := server.Start(); err != nil {
|
2021-01-20 22:52:25 +01:00
|
|
|
log.Fatal("server.Start ERROR: ", err)
|
2020-10-08 18:21:27 +02:00
|
|
|
}
|
2021-03-01 20:36:36 +01:00
|
|
|
|
|
|
|
// Setting up signal capturing
|
|
|
|
stop := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(stop, os.Interrupt)
|
|
|
|
|
|
|
|
// Waiting for SIGINT (pkill -2)
|
|
|
|
<-stop
|
|
|
|
|
|
|
|
server.Shutdown()
|
|
|
|
}
|
|
|
|
|
|
|
|
// StartServer starts the server
|
|
|
|
//export StartServer
|
2021-04-22 03:25:26 +02:00
|
|
|
func StartServer(webPath *C.char, filesPath *C.char, port int, singleUserToken, dbConfigString *C.char) {
|
2021-03-01 20:36:36 +01:00
|
|
|
startServer(
|
|
|
|
C.GoString(webPath),
|
2021-04-22 03:25:26 +02:00
|
|
|
C.GoString(filesPath),
|
2021-03-01 20:36:36 +01:00
|
|
|
port,
|
|
|
|
C.GoString(singleUserToken),
|
|
|
|
C.GoString(dbConfigString),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// StopServer stops the server
|
|
|
|
//export StopServer
|
|
|
|
func StopServer() {
|
|
|
|
stopServer()
|
|
|
|
}
|
|
|
|
|
2021-04-22 03:25:26 +02:00
|
|
|
func startServer(webPath string, filesPath string, port int, singleUserToken, dbConfigString string) {
|
2021-03-01 20:36:36 +01:00
|
|
|
logInfo()
|
|
|
|
|
|
|
|
if pServer != nil {
|
|
|
|
stopServer()
|
|
|
|
pServer = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// config.json file
|
|
|
|
config, err := config.ReadConfigFile()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("Unable to read the config file: ", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-04-22 03:25:26 +02:00
|
|
|
if len(filesPath) > 0 {
|
|
|
|
config.FilesPath = filesPath
|
|
|
|
}
|
|
|
|
|
2021-03-01 20:36:36 +01:00
|
|
|
if len(webPath) > 0 {
|
|
|
|
config.WebPath = webPath
|
|
|
|
}
|
|
|
|
|
|
|
|
if port > 0 {
|
|
|
|
config.Port = port
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(dbConfigString) > 0 {
|
|
|
|
config.DBConfigString = dbConfigString
|
|
|
|
}
|
|
|
|
|
|
|
|
pServer, err = server.New(config, singleUserToken)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("server.New ERROR: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := pServer.Start(); err != nil {
|
|
|
|
log.Fatal("server.Start ERROR: ", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func stopServer() {
|
|
|
|
if pServer == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err := pServer.Shutdown()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("server.Shutdown ERROR: ", err)
|
|
|
|
}
|
2020-10-08 18:21:27 +02:00
|
|
|
}
|