1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
package main
import (
"errors"
"fmt"
"os"
"os/exec"
glider_ssh "github.com/gliderlabs/ssh"
"go.lindenii.runxiyu.org/lindenii-common/cmap"
)
type pack_to_hook_t struct {
session glider_ssh.Session
pubkey string
direct_access bool
repo_path string
user_id int
repo_id int
}
var pack_to_hook_by_cookie = cmap.Map[string, pack_to_hook_t]{}
// ssh_handle_receive_pack handles attempts to push to repos.
func ssh_handle_receive_pack(session glider_ssh.Session, pubkey string, repo_identifier string) (err error) {
repo_id, repo_path, direct_access, contrib_requirements, user_type, user_id, err := get_repo_path_perms_from_ssh_path_pubkey(session.Context(), repo_identifier, pubkey)
if err != nil {
return err
}
if !direct_access {
switch contrib_requirements {
case "closed":
if !direct_access {
return errors.New("You need direct access to push to this repo.")
}
case "registered_user":
if user_type != "registered" {
return errors.New("You need to be a registered user to push to this repo.")
}
case "ssh_pubkey":
if pubkey == "" {
return errors.New("You need to have an SSH public key to push to this repo.")
}
if user_type == "" {
user_id, err = add_user_ssh(session.Context(), pubkey)
if err != nil {
return err
}
fmt.Fprintln(session.Stderr(), "You are now registered as user ID", user_id)
}
case "public":
default:
panic("unknown contrib_requirements value " + contrib_requirements)
}
}
cookie, err := random_urlsafe_string(16)
if err != nil {
fmt.Fprintln(session.Stderr(), "Error while generating cookie:", err)
}
pack_to_hook_by_cookie.Store(cookie, pack_to_hook_t{
session: session,
pubkey: pubkey,
direct_access: direct_access,
repo_path: repo_path,
user_id: user_id,
repo_id: repo_id,
})
defer pack_to_hook_by_cookie.Delete(cookie)
// The Delete won't execute until proc.Wait returns unless something
// horribly wrong such as a panic occurs.
proc := exec.CommandContext(session.Context(), "git-receive-pack", repo_path)
proc.Env = append(os.Environ(),
"LINDENII_FORGE_HOOKS_SOCKET_PATH="+config.Hooks.Socket,
"LINDENII_FORGE_HOOKS_COOKIE="+cookie,
)
proc.Stdin = session
proc.Stdout = session
proc.Stderr = session.Stderr()
err = proc.Start()
if err != nil {
fmt.Fprintln(session.Stderr(), "Error while starting process:", err)
return err
}
err = proc.Wait()
if exitError, ok := err.(*exec.ExitError); ok {
fmt.Fprintln(session.Stderr(), "Process exited with error", exitError.ExitCode())
} else if err != nil {
fmt.Fprintln(session.Stderr(), "Error while waiting for process:", err)
}
return err
}
|