aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-02-19 20:44:54 +0800
committerRunxi Yu <me@runxiyu.org>2025-02-19 20:44:54 +0800
commit294d06ea4865e4bae88c1dee6a8a841a7f204189 (patch)
tree9d80c02fc509f43626f220874f46d8e906c0b6dc
parentssh/recv: Rename access -> direct_access (diff)
downloadforge-294d06ea4865e4bae88c1dee6a8a841a7f204189.tar.gz
forge-294d06ea4865e4bae88c1dee6a8a841a7f204189.tar.zst
forge-294d06ea4865e4bae88c1dee6a8a841a7f204189.zip
ssh/recv, users, schema: Create pubkey_only users
Diffstat (limited to '')
-rw-r--r--acl.go9
-rw-r--r--schema.sql3
-rw-r--r--ssh_handle_receive_pack.go11
-rw-r--r--ssh_utils.go12
-rw-r--r--users.go26
5 files changed, 46 insertions, 15 deletions
diff --git a/acl.go b/acl.go
index 095c1f1..7ad48fb 100644
--- a/acl.go
+++ b/acl.go
@@ -6,7 +6,7 @@ import (
// get_path_perm_by_group_repo_key returns the filesystem path and direct
// access permission for a given repo and a provided ssh public key.
-func get_path_perm_by_group_repo_key(ctx context.Context, group_name, repo_name, ssh_pubkey string) (filesystem_path string, access bool, contrib_requirements string, is_registered_user bool, err error) {
+func get_path_perm_by_group_repo_key(ctx context.Context, group_name, repo_name, ssh_pubkey string) (filesystem_path string, access bool, contrib_requirements string, user_type string, err error) {
err = database.QueryRow(ctx,
`SELECT
r.filesystem_path,
@@ -15,10 +15,7 @@ func get_path_perm_by_group_repo_key(ctx context.Context, group_name, repo_name,
ELSE FALSE
END AS has_role_in_group,
r.contrib_requirements,
- CASE
- WHEN u.id IS NOT NULL THEN TRUE
- ELSE FALSE
- END
+ COALESCE(u.type, '')
FROM
groups g
JOIN
@@ -33,6 +30,6 @@ func get_path_perm_by_group_repo_key(ctx context.Context, group_name, repo_name,
g.name = $1
AND r.name = $2;`,
group_name, repo_name, ssh_pubkey,
- ).Scan(&filesystem_path, &access, &contrib_requirements, &is_registered_user)
+ ).Scan(&filesystem_path, &access, &contrib_requirements, &user_type)
return
}
diff --git a/schema.sql b/schema.sql
index 2589a07..3db8967 100644
--- a/schema.sql
+++ b/schema.sql
@@ -48,7 +48,8 @@ CREATE TABLE mailing_list_emails (
CREATE TABLE users (
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
- username TEXT NOT NULL UNIQUE,
+ username TEXT UNIQUE,
+ type TEXT NOT NULL CHECK (type IN ('pubkey_only', 'registered')),
password TEXT
);
diff --git a/ssh_handle_receive_pack.go b/ssh_handle_receive_pack.go
index ba83397..293bb36 100644
--- a/ssh_handle_receive_pack.go
+++ b/ssh_handle_receive_pack.go
@@ -21,7 +21,7 @@ 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_path, direct_access, contrib_requirements, is_registered_user, err := get_repo_path_perms_from_ssh_path_pubkey(session.Context(), repo_identifier, pubkey)
+ repo_path, direct_access, contrib_requirements, user_type, err := get_repo_path_perms_from_ssh_path_pubkey(session.Context(), repo_identifier, pubkey)
if err != nil {
return err
}
@@ -33,13 +33,20 @@ func ssh_handle_receive_pack(session glider_ssh.Session, pubkey string, repo_ide
return errors.New("You need direct access to push to this repo.")
}
case "registered_user":
- if !is_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)
diff --git a/ssh_utils.go b/ssh_utils.go
index bf8bf5e..fb8f920 100644
--- a/ssh_utils.go
+++ b/ssh_utils.go
@@ -9,19 +9,19 @@ import (
var err_ssh_illegal_endpoint = errors.New("illegal endpoint during SSH access")
-func get_repo_path_perms_from_ssh_path_pubkey(ctx context.Context, ssh_path string, ssh_pubkey string) (repo_path string, direct_access bool, contrib_requirements string, is_registered_user bool, err error) {
+func get_repo_path_perms_from_ssh_path_pubkey(ctx context.Context, ssh_path string, ssh_pubkey string) (repo_path string, direct_access bool, contrib_requirements string, user_type string, err error) {
segments := strings.Split(strings.TrimPrefix(ssh_path, "/"), "/")
for i, segment := range segments {
var err error
segments[i], err = url.PathUnescape(segment)
if err != nil {
- return "", false, "", false, err
+ return "", false, "", "", err
}
}
if segments[0] == ":" {
- return "", false, "", false, err_ssh_illegal_endpoint
+ return "", false, "", "", err_ssh_illegal_endpoint
}
separator_index := -1
@@ -37,9 +37,9 @@ func get_repo_path_perms_from_ssh_path_pubkey(ctx context.Context, ssh_path stri
switch {
case separator_index == -1:
- return "", false, "", false, err_ssh_illegal_endpoint
+ return "", false, "", "", err_ssh_illegal_endpoint
case len(segments) <= separator_index+2:
- return "", false, "", false, err_ssh_illegal_endpoint
+ return "", false, "", "", err_ssh_illegal_endpoint
}
group_name := segments[0]
@@ -49,6 +49,6 @@ func get_repo_path_perms_from_ssh_path_pubkey(ctx context.Context, ssh_path stri
case "repos":
return get_path_perm_by_group_repo_key(ctx, group_name, module_name, ssh_pubkey)
default:
- return "", false, "", false, err_ssh_illegal_endpoint
+ return "", false, "", "", err_ssh_illegal_endpoint
}
}
diff --git a/users.go b/users.go
new file mode 100644
index 0000000..9ac0798
--- /dev/null
+++ b/users.go
@@ -0,0 +1,26 @@
+package main
+
+import (
+ "context"
+)
+
+func add_user_ssh(ctx context.Context, pubkey string) (user_id int, err error) {
+ tx, err := database.Begin(ctx)
+ if err != nil {
+ return
+ }
+ defer tx.Rollback(ctx)
+
+ err = tx.QueryRow(ctx, `INSERT INTO users (type) VALUES ('pubkey_only') RETURNING id`).Scan(&user_id)
+ if err != nil {
+ return
+ }
+
+ _, err = tx.Exec(ctx, `INSERT INTO ssh_public_keys (key_string, user_id) VALUES ($1, $2)`, pubkey, user_id)
+ if err != nil {
+ return
+ }
+
+ err = tx.Commit(ctx)
+ return
+}