Goit

Simple and lightweight Git web server
git clone https://git.omkov.net/Goit
git clone [email protected]:Goit
Log | Tree | Refs | README | Download

Goit/src/shell/main.go (112 lines, 2.9 KiB) -rw-r--r-- file download

77702b3 Jakob Wakeling 2025-01-04 13:20:23
0
// Copyright (C) 2025, Jakob Wakeling
77702b3 Jakob Wakeling 2025-01-04 13:20:23
1
// All rights reserved.
77702b3 Jakob Wakeling 2025-01-04 13:20:23
2
77702b3 Jakob Wakeling 2025-01-04 13:20:23
3
package main
77702b3 Jakob Wakeling 2025-01-04 13:20:23
4
77702b3 Jakob Wakeling 2025-01-04 13:20:23
5
import (
77702b3 Jakob Wakeling 2025-01-04 13:20:23
6
	"database/sql"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
7
	"fmt"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
8
	"os"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
9
	"path/filepath"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
10
	"regexp"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
11
	"strings"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
12
77702b3 Jakob Wakeling 2025-01-04 13:20:23
13
	"github.com/Jamozed/Goit/src/goit"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
14
	"github.com/Jamozed/Goit/src/util"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
15
	_ "github.com/mattn/go-sqlite3"
77702b3 Jakob Wakeling 2025-01-04 13:20:23
16
)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
17
77702b3 Jakob Wakeling 2025-01-04 13:20:23
18
func main() {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
19
	if len(os.Args) < 2 || os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
20
		fmt.Fprint(os.Stderr, "Interactive Goit shell is not enabled.\n")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
21
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
22
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
23
77702b3 Jakob Wakeling 2025-01-04 13:20:23
24
	username := os.Args[1]
77702b3 Jakob Wakeling 2025-01-04 13:20:23
25
	soc := os.Getenv("SSH_ORIGINAL_COMMAND")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
26
77702b3 Jakob Wakeling 2025-01-04 13:20:23
27
	/* Parse the SSH_ORIGINAL_COMMAND value for the direction and repository name. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
28
	re := regexp.MustCompile(`^(git-upload-pack|git-receive-pack|git-upload-archive) '?/?(.*?)'?$`)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
29
	matches := re.FindStringSubmatch(soc)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
30
	if len(matches) != 3 || matches[1] == "" {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
31
		fmt.Fprintln(os.Stderr, "Unknown command:", soc)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
32
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
33
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
34
77702b3 Jakob Wakeling 2025-01-04 13:20:23
35
	command := matches[1]
77702b3 Jakob Wakeling 2025-01-04 13:20:23
36
	action := util.If(strings.Contains(command, "upload"), "r", "w")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
37
	reponame := strings.TrimSuffix(strings.TrimSuffix(matches[2], "/"), ".git")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
38
77702b3 Jakob Wakeling 2025-01-04 13:20:23
39
	if !goit.IsLegal(reponame) {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
40
		fmt.Fprintln(os.Stderr, "Repository not found.")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
41
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
42
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
43
77702b3 Jakob Wakeling 2025-01-04 13:20:23
44
	/* Load the config. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
45
	conf, err := goit.LoadConfig()
77702b3 Jakob Wakeling 2025-01-04 13:20:23
46
	if err != nil {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
47
		fmt.Fprintln(os.Stderr, "Failed to load config:", err.Error())
77702b3 Jakob Wakeling 2025-01-04 13:20:23
48
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
49
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
50
77702b3 Jakob Wakeling 2025-01-04 13:20:23
51
	/* Open the database. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
52
	db, err := sql.Open("sqlite3", filepath.Join(conf.DataPath, "goit.db?_timeout=5000"))
77702b3 Jakob Wakeling 2025-01-04 13:20:23
53
	if err != nil {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
54
		fmt.Fprintln(os.Stderr, "Failed to open database:", err.Error())
77702b3 Jakob Wakeling 2025-01-04 13:20:23
55
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
56
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
57
	defer db.Close()
77702b3 Jakob Wakeling 2025-01-04 13:20:23
58
77702b3 Jakob Wakeling 2025-01-04 13:20:23
59
	/* Set global config and database variables correctly. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
60
	goit.Conf = conf
77702b3 Jakob Wakeling 2025-01-04 13:20:23
61
	goit.ShellSetDB(db)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
62
77702b3 Jakob Wakeling 2025-01-04 13:20:23
63
	/* Confirm that the database is the expected version. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
64
	var version int
77702b3 Jakob Wakeling 2025-01-04 13:20:23
65
	if err := db.QueryRow("PRAGMA user_version").Scan(&version); err != nil {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
66
		fmt.Fprintln(os.Stderr, "Failed to get database version:", err.Error())
77702b3 Jakob Wakeling 2025-01-04 13:20:23
67
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
68
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
69
	if version != goit.LATEST_VERSION {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
70
		fmt.Fprintln(os.Stderr, "Unexpected database version.")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
71
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
72
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
73
77702b3 Jakob Wakeling 2025-01-04 13:20:23
74
	/* Confirm that the user exists and is enabled. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
75
	user, err := goit.GetUserByName(username)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
76
	if err != nil {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
77
		fmt.Fprintln(os.Stderr, "Failed to get user:", err.Error())
77702b3 Jakob Wakeling 2025-01-04 13:20:23
78
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
79
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
80
	if user == nil {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
81
		fmt.Fprintln(os.Stderr, "User not found.")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
82
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
83
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
84
77702b3 Jakob Wakeling 2025-01-04 13:20:23
85
	/* Confirm that the repository exists. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
86
	repo, err := goit.GetRepoByName(reponame)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
87
	if err != nil {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
88
		fmt.Fprintln(os.Stderr, "Failed to get repository:", err.Error())
77702b3 Jakob Wakeling 2025-01-04 13:20:23
89
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
90
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
91
77702b3 Jakob Wakeling 2025-01-04 13:20:23
92
	/* Check user authorization against repository. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
93
	if repo == nil || (repo.Visibility == goit.Private && user.Id != repo.OwnerId) {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
94
		fmt.Fprintln(os.Stderr, "Repository not found.")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
95
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
96
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
97
77702b3 Jakob Wakeling 2025-01-04 13:20:23
98
	/* Check if user has write permissions for the repository, if required. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
99
	if action == "w" && repo.OwnerId != user.Id {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
100
		fmt.Fprintln(os.Stderr, "Write access denied.")
77702b3 Jakob Wakeling 2025-01-04 13:20:23
101
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
102
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
103
77702b3 Jakob Wakeling 2025-01-04 13:20:23
104
	/* Run git-shell command. */
77702b3 Jakob Wakeling 2025-01-04 13:20:23
105
	if _, _, err := goit.NewGitCommand(
77702b3 Jakob Wakeling 2025-01-04 13:20:23
106
		"shell", "-c", command+" '"+goit.RepoPath(reponame, true)+"'",
77702b3 Jakob Wakeling 2025-01-04 13:20:23
107
	).Run(os.Stdin, os.Stdout); err != nil {
77702b3 Jakob Wakeling 2025-01-04 13:20:23
108
		os.Exit(-1)
77702b3 Jakob Wakeling 2025-01-04 13:20:23
109
	}
77702b3 Jakob Wakeling 2025-01-04 13:20:23
110
}
111