7a7e73dda8cf32681cc31bedf64055f0094a2e21

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

fix(auth): wrong auth for anon users

This fixes an issue with using anon-access with registered users.

Fixes: d88ccb97d3e7 ("ref(config): clarify repo auth for key")

Diff

This diff is truncated to protect this page.

  1diff --git a/config/auth.go b/config/auth.go
  2index ff1d3c0567a75b42535a68ddf54789a8994c2917..30e8d6719c1605b68ee314d9f90f04ad97d004dd 100644
  3--- a/config/auth.go
  4+++ b/config/auth.go
  5@@ -81,10 +81,8 @@ func (cfg *Config) anonAccessLevel() gm.AccessLevel {
  6 // If repo exists, and private, then admins and collabs are allowed access.
  7 // If repo exists, and not private, then access is based on config.AnonAccess.
  8 func (cfg *Config) accessForKey(repo string, pk ssh.PublicKey) gm.AccessLevel {
  9-	var u *User
 10-	var r *RepoConfig
 11 	anon := cfg.anonAccessLevel()
 12-OUT:
 13+	private := cfg.isPrivate(repo)
 14 	// Find user
 15 	for _, user := range cfg.Users {
 16 		for _, k := range user.PublicKeys {
 17@@ -94,49 +92,63 @@ OUT:
 18 				return gm.NoAccess
 19 			}
 20 			if ssh.KeysEqual(pk, apk) {
 21-				us := user
 22-				u = &us
 23-				break OUT
 24+				if user.Admin {
 25+					return gm.AdminAccess
 26+				}
 27+				u := user
 28+				if cfg.isCollab(repo, &u) {
 29+					if anon > gm.ReadWriteAccess {
 30+						return anon
 31+					}
 32+					return gm.ReadWriteAccess
 33+				}
 34+				if !private {
 35+					if anon > gm.ReadOnlyAccess {
 36+						return anon
 37+					}
 38+					return gm.ReadOnlyAccess
 39+				}
 40 			}
 41 		}
 42 	}
 43-	// Find repo
 44-	for _, rp := range cfg.Repos {
 45-		if rp.Repo == repo {
 46-			rr := rp
 47-			r = &rr
 48-			break
 49-		}
 50+	// Don't restrict access to private repos if no users are configured.
 51+	// Return anon access level.
 52+	if private && len(cfg.Users) > 0 {
 53+		return gm.NoAccess
 54 	}
 55-	if u != nil && u.Admin {
 56-		return gm.AdminAccess
 57+	return anon
 58+}
 59+
 60+func (cfg *Config) findRepo(repo string) *RepoConfig {
 61+	for _, r := range cfg.Repos {
 62+		if r.Repo == repo {
 63+			return &r
 64+		}
 65 	}
 66-	if r == nil || len(cfg.Users) == 0 {
 67-		return anon
 68+	return nil
 69+}
 70+
 71+func (cfg *Config) isPrivate(repo string) bool {
 72+	if r := cfg.findRepo(repo); r != nil {
 73+		return r.Private
 74 	}
 75-	// Collabs default access is read-write
 76-	if u != nil {
 77-		ac := gm.ReadWriteAccess
 78-		if anon > ac {
 79-			ac = anon
 80-		}
 81-		for _, c := range r.Collabs {
 82-			if c == u.Name {
 83-				return ac
 84+	return false
 85+}
 86+
 87+func (cfg *Config) isCollab(repo string, user *User) bool {
 88+	if user != nil {
 89+		for _, r := range user.CollabRepos {
 90+			if r == repo {
 91+				return true
 92 			}
 93 		}
 94-		for _, rr := range u.CollabRepos {
 95-			if rr == r.Repo {
 96-				return ac
 97+		if r := cfg.findRepo(repo); r != nil {
 98+			for _, c := range r.Collabs {
 99+				if c == user.Name {
100+					return true
101+				}
102 			}
103 		}
104 	}
105diff --git a/config/auth_test.go b/config/auth_test.go
106index 7e59b59b3be5d0618cf53ffb480ef7bda75a4a0e..4f48bafb47cae15a0ba47b17a8a5f6db04c2bce8 100644
107--- a/config/auth_test.go
108+++ b/config/auth_test.go
109@@ -34,6 +34,27 @@ func TestAuth(t *testing.T) {
110 				},
111 			},
112 		},
113+		{
114+			name:   "anon access: no-access, anonymous user with admin user",
115+			access: git.NoAccess,
116+			repo:   "foo",
117+			cfg: Config{
118+				AnonAccess: "no-access",
119+				Repos: []RepoConfig{
120+					{
121+						Repo: "foo",
122+					},
123+				},
124+				Users: []User{
125+					{
126+						Admin: true,
127+						PublicKeys: []string{
128+							adminKey,
129+						},
130+					},
131+				},
132+			},
133+		},
134 		{
135 			name:   "anon access: no-access, authd user",
136 			key:    dummyPk,
137@@ -55,6 +76,28 @@ func TestAuth(t *testing.T) {
138 				},
139 			},
140 		},
141+		{
142+			name:   "anon access: no-access, anonymous user with admin user",
143+			key:    dummyPk,
144+			repo:   "foo",
145+			access: git.NoAccess,
146+			cfg: Config{
147+				AnonAccess: "no-access",
148+				Repos: []RepoConfig{
149+					{
150+						Repo: "foo",
151+					},
152+				},
153+				Users: []User{
154+					{
155+						Admin: true,
156+						PublicKeys: []string{
157+							adminKey,
158+						},
159+					},
160+				},
161+			},
162+		},
163 		{
164 			name:   "anon access: no-access, admin user",
165 			repo:   "foo",
166@@ -429,7 +472,7 @@ func TestAuth(t *testing.T) {
167 			name:   "anon access: no-access, authd user, new repo",
168 			key:    dummyPk,
169 			repo:   "foo",
170-			access: git.NoAccess,
171+			access: git.ReadOnlyAccess,
172 			cfg: Config{
173 				AnonAccess: "no-access",
174 				Users: []User{
175@@ -441,6 +484,22 @@ func TestAuth(t *testing.T) {
176 				},
177 			},
178 		},
179+		{
180+			name:   "anon access: no-access, authd user, new repo, with user",
181+			key:    dummyPk,
182+			repo:   "foo",
183+			access: git.NoAccess,
184+			cfg: Config{
185+				AnonAccess: "no-access",
186+				Users: []User{
187+					{
188+						PublicKeys: []string{
189+							adminKey,
190+						},
191+					},
192+				},
193+			},
194+		},
195 		{
196 			name:   "anon access: no-access, admin user, new repo",
197 			repo:   "foo",