2024-01-23 19:24:01 +00:00
package cli
import (
"fmt"
"github.com/rs/zerolog/log"
2024-10-07 21:56:32 +00:00
"github.com/thomiceli/opengist/internal/auth/webauthn"
2024-01-23 19:24:01 +00:00
"github.com/thomiceli/opengist/internal/config"
"github.com/thomiceli/opengist/internal/db"
"github.com/thomiceli/opengist/internal/git"
"github.com/thomiceli/opengist/internal/index"
"github.com/thomiceli/opengist/internal/memdb"
"github.com/thomiceli/opengist/internal/ssh"
"github.com/thomiceli/opengist/internal/web"
"github.com/urfave/cli/v2"
"os"
2024-09-09 09:44:22 +00:00
"os/signal"
2024-01-23 19:24:01 +00:00
"path"
"path/filepath"
2024-09-09 09:44:22 +00:00
"syscall"
2024-01-23 19:24:01 +00:00
)
var CmdVersion = cli . Command {
Name : "version" ,
Usage : "Print the version of Opengist" ,
Action : func ( c * cli . Context ) error {
2024-04-27 00:53:48 +00:00
fmt . Println ( "Opengist " + config . OpengistVersion )
2024-01-23 19:24:01 +00:00
return nil
} ,
}
var CmdStart = cli . Command {
Name : "start" ,
Usage : "Start Opengist server" ,
Action : func ( ctx * cli . Context ) error {
2024-09-09 09:44:22 +00:00
stopCtx , stop := signal . NotifyContext ( ctx . Context , syscall . SIGINT , syscall . SIGTERM )
defer stop ( )
2024-01-23 19:24:01 +00:00
Initialize ( ctx )
2024-09-09 09:44:22 +00:00
2024-11-02 00:05:43 +00:00
go web . NewServer ( os . Getenv ( "OG_DEV" ) == "1" , path . Join ( config . GetHomeDir ( ) , "sessions" ) , false ) . Start ( )
2024-01-23 19:24:01 +00:00
go ssh . Start ( )
2024-09-09 09:44:22 +00:00
<- stopCtx . Done ( )
shutdown ( )
return nil
2024-01-23 19:24:01 +00:00
} ,
}
var ConfigFlag = cli . StringFlag {
Name : "config" ,
Aliases : [ ] string { "c" } ,
Usage : "Path to a config file in YAML format" ,
}
func App ( ) error {
app := cli . NewApp ( )
app . Name = "Opengist"
app . Usage = "A self-hosted pastebin powered by Git."
app . HelpName = "opengist"
2024-02-24 17:45:36 +00:00
app . Commands = [ ] * cli . Command { & CmdVersion , & CmdStart , & CmdHook , & CmdAdmin }
2024-01-23 19:24:01 +00:00
app . DefaultCommand = CmdStart . Name
app . Flags = [ ] cli . Flag {
& ConfigFlag ,
}
return app . Run ( os . Args )
}
func Initialize ( ctx * cli . Context ) {
2024-04-27 00:53:48 +00:00
fmt . Println ( "Opengist " + config . OpengistVersion )
2024-01-23 19:24:01 +00:00
2024-01-29 23:07:57 +00:00
if err := config . InitConfig ( ctx . String ( "config" ) , os . Stdout ) ; err != nil {
2024-01-23 19:24:01 +00:00
panic ( err )
}
if err := os . MkdirAll ( filepath . Join ( config . GetHomeDir ( ) ) , 0755 ) ; err != nil {
panic ( err )
}
2024-10-31 13:50:13 +00:00
config . SetupSecretKey ( )
2024-01-23 19:24:01 +00:00
config . InitLog ( )
gitVersion , err := git . GetGitVersion ( )
if err != nil {
log . Fatal ( ) . Err ( err ) . Send ( )
}
if ok , err := config . CheckGitVersion ( gitVersion ) ; err != nil {
log . Fatal ( ) . Err ( err ) . Send ( )
} else if ! ok {
log . Warn ( ) . Msg ( "Git version may be too old, as Opengist has not been tested prior git version 2.28 and some features would not work. " +
"Current git version: " + gitVersion )
}
homePath := config . GetHomeDir ( )
log . Info ( ) . Msg ( "Data directory: " + homePath )
2024-11-26 21:28:17 +00:00
if err := git . InitGitConfig ( ) ; err != nil {
log . Warn ( ) . Err ( err ) . Msgf ( "Failed to change the host's git global config, ensure to add to `safe.directory` the path %s, and `receive.advertisePushOptions` is set to true." , homePath )
}
2024-01-29 23:07:57 +00:00
if err := createSymlink ( homePath , ctx . String ( "config" ) ) ; err != nil {
log . Fatal ( ) . Err ( err ) . Msg ( "Failed to create symlinks" )
2024-01-23 19:24:01 +00:00
}
2024-04-02 23:48:31 +00:00
if err := os . MkdirAll ( filepath . Join ( homePath , "sessions" ) , 0755 ) ; err != nil {
log . Fatal ( ) . Err ( err ) . Send ( )
}
2024-01-23 19:24:01 +00:00
if err := os . MkdirAll ( filepath . Join ( homePath , "repos" ) , 0755 ) ; err != nil {
log . Fatal ( ) . Err ( err ) . Send ( )
}
if err := os . MkdirAll ( filepath . Join ( homePath , "tmp" , "repos" ) , 0755 ) ; err != nil {
log . Fatal ( ) . Err ( err ) . Send ( )
}
if err := os . MkdirAll ( filepath . Join ( homePath , "custom" ) , 0755 ) ; err != nil {
log . Fatal ( ) . Err ( err ) . Send ( )
}
2024-09-20 14:01:09 +00:00
db . DeprecationDBFilename ( )
if err := db . Setup ( config . C . DBUri , false ) ; err != nil {
2024-01-23 19:24:01 +00:00
log . Fatal ( ) . Err ( err ) . Msg ( "Failed to initialize database" )
}
if err := memdb . Setup ( ) ; err != nil {
log . Fatal ( ) . Err ( err ) . Msg ( "Failed to initialize in memory database" )
}
2024-10-07 21:56:32 +00:00
if err := webauthn . Init ( config . C . ExternalUrl ) ; err != nil {
log . Error ( ) . Err ( err ) . Msg ( "Failed to initialize WebAuthn" )
}
2024-01-23 19:24:01 +00:00
if config . C . IndexEnabled {
log . Info ( ) . Msg ( "Index directory: " + filepath . Join ( homePath , config . C . IndexDirname ) )
2024-09-09 09:44:22 +00:00
index . Init ( filepath . Join ( homePath , config . C . IndexDirname ) )
}
}
func shutdown ( ) {
log . Info ( ) . Msg ( "Shutting down database..." )
if err := db . Close ( ) ; err != nil {
log . Error ( ) . Err ( err ) . Msg ( "Failed to close database" )
}
if config . C . IndexEnabled {
log . Info ( ) . Msg ( "Shutting down index..." )
index . Close ( )
2024-01-23 19:24:01 +00:00
}
2024-09-09 09:44:22 +00:00
log . Info ( ) . Msg ( "Shutdown complete" )
2024-01-23 19:24:01 +00:00
}
2024-01-29 23:07:57 +00:00
func createSymlink ( homePath string , configPath string ) error {
if err := os . MkdirAll ( filepath . Join ( homePath , "symlinks" ) , 0755 ) ; err != nil {
return err
}
2024-01-23 19:24:01 +00:00
exePath , err := os . Executable ( )
if err != nil {
return err
}
2024-01-29 23:07:57 +00:00
symlinkExePath := path . Join ( config . GetHomeDir ( ) , "symlinks" , "opengist" )
if _ , err := os . Lstat ( symlinkExePath ) ; err == nil {
if err := os . Remove ( symlinkExePath ) ; err != nil {
return err
}
}
if err = os . Symlink ( exePath , symlinkExePath ) ; err != nil {
return err
}
if configPath == "" {
return nil
}
2024-01-23 19:24:01 +00:00
2024-01-29 23:07:57 +00:00
configPath , _ = filepath . Abs ( configPath )
configPath = filepath . Clean ( configPath )
symlinkConfigPath := path . Join ( config . GetHomeDir ( ) , "symlinks" , "config.yml" )
if _ , err := os . Lstat ( symlinkConfigPath ) ; err == nil {
if err := os . Remove ( symlinkConfigPath ) ; err != nil {
2024-01-23 19:24:01 +00:00
return err
}
}
2024-01-29 23:07:57 +00:00
if err = os . Symlink ( configPath , symlinkConfigPath ) ; err != nil {
return err
}
2024-01-23 19:24:01 +00:00
2024-01-29 23:07:57 +00:00
return nil
2024-01-23 19:24:01 +00:00
}