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
|
|