Skip to main content
Sign in
Snippets Groups Projects
Select Git revision
  • e673ca8cdf510551058bea4388c7215df6fd987d
  • main default protected
2 results

run.go

Blame
  • batch.go 3.82 KiB
    // Package batch contains the non-interactive maintenence commands.
    package batch
    
    import (
    	_ "embed"
    	"errors"
    	"fmt"
    	"os"
    	"path"
    	"strings"
    	"text/template"
    	"time"
    
    	"git.lyda.ie/kevin/bulletin/ask"
    	"git.lyda.ie/kevin/bulletin/key"
    	"git.lyda.ie/kevin/bulletin/storage"
    	"github.com/adrg/xdg"
    )
    
    //go:embed crontab
    var crontabTemplate string
    
    // Reboot deletes all messages with `shutdown` set.
    func Reboot() int {
    	ctx := storage.Context()
    
    	store, err := storage.Open()
    	ask.CheckErr(err)
    	q := storage.New(store.DB)
    
    	rows, err := q.DeleteAllShutdownMessages(ctx)
    	ask.CheckErr(err)
    	fmt.Printf("Removed %d shutdown messages\n", rows)
    	return 0
    }
    
    // Expire deletes all messages that have hit their expiration date.
    func Expire() int {
    	ctx := storage.Context()
    
    	store, err := storage.Open()
    	ask.CheckErr(err)
    	q := storage.New(store.DB)
    
    	rows, err := q.DeleteAllExpiredMessages(ctx)
    	ask.CheckErr(err)
    	fmt.Printf("Expired %d messages\n", rows)
    	return 0
    }
    
    // Install is an interactive command used to install the crontab.
    func Install() int {
    	ctx := storage.Context()
    
    	// Check if install has run before.
    	touchfile := path.Join(xdg.Home, ".bulletin-installed")
    	if _, err := os.Stat(touchfile); err == nil {
    		ask.CheckErr(errors.New("~/.bulletin-installed exists; BULLETIN install has run"))
    	} else {
    		if !errors.Is(err, os.ErrNotExist) {
    			fmt.Println("ERROR: Unknown error checking in ~/.bulletin-installed exists.")
    			fmt.Println("ERROR: Can't see if BULLETIN has been installed.")
    			ask.CheckErr(err)
    		}
    	}
    
    	// Connect to the database.
    	store, err := storage.Open()
    	ask.CheckErr(err)
    	q := storage.New(store.DB)
    
    	// Create the initial users.
    	fmt.Println(`Welcome to the BULLETIN install process.  This will create
    the following files:
    
      * ~/.local/share/BULLETIN/bulletin.db - BULLETIN's folder and user db.
    	* ~/.bulletin-installed - A file to make sure install isn't run again.
    	* ~/.config/BULLETIN/* - history files for each user.
    	* ~/.ssh/authorized_keys - key lines to let users connect to BULLETIN
    
    To complete the installation, please enter the login, name and ssh key for
    the first user.`)
    	login, err := ask.GetLine("Enter login of initial user: ")
    	login = strings.ToUpper(login)
    	ask.CheckErr(err)
    	name, err := ask.GetLine("Enter name of initial user: ")
    	ask.CheckErr(err)
    	sshkey, err := ask.GetLine("Enter ssh public key of initial user: ")
    	ask.CheckErr(err)
    
    	// Seed data.
    	seedMsgs, err := GetSeedMessages()
    	ask.CheckErr(err)
    	ask.CheckErr(q.SeedUserSystem(ctx))
    	ask.CheckErr(q.SeedFolderGeneral(ctx))
    	ask.CheckErr(q.SeedGeneralOwner(ctx))
    	_, err = q.AddUser(ctx, storage.AddUserParams{
    		Login: login,
    		Name:  name,
    	})
    	key.Add(login, sshkey)
    	userCreated := map[string]bool{
    		"SYSTEM": true,
    		login:    true,
    	}
    	for i := range seedMsgs {
    		if !userCreated[seedMsgs[i].Login] {
    			_, err = q.AddUser(ctx, storage.AddUserParams{
    				Login:    seedMsgs[i].Login,
    				Name:     seedMsgs[i].Name,
    				Disabled: 1,
    			})
    			ask.CheckErr(err)
    			userCreated[seedMsgs[i].Login] = true
    		}
    		ask.CheckErr(q.SeedCreateMessage(ctx, storage.SeedCreateMessageParams{
    			Folder:     "GENERAL",
    			Author:     seedMsgs[i].Login,
    			Subject:    seedMsgs[i].Subject,
    			Message:    seedMsgs[i].Message,
    			CreateAt:   seedMsgs[i].Date,
    			Expiration: time.Now(),
    		}))
    	}
    
    	// Install crontab.
    	bulletin, err := os.Executable()
    	if err != nil {
    		panic(err) // TODO: cleanup error handling.
    	}
    	crontab := &strings.Builder{}
    	template.Must(template.New("crontab").Parse(crontabTemplate)).
    		Execute(crontab, map[string]string{"Bulletin": bulletin})
    	fmt.Printf("Adding this to crontab:\n\n%s\n", crontab.String())
    	err = installCrontab(crontab.String())
    	if err != nil {
    		panic(err) // TODO: cleanup error handling.
    	}
    
    	// Mark that install has happened.
    	err = touch(touchfile)
    	if err != nil {
    		panic(err) // TODO: cleanup error handling.
    	}
    
    	return 0
    }