From 48fa9c96a7a0309a4adf1f1e04a11ea3526af641 Mon Sep 17 00:00:00 2001
From: Gusted <postmaster@gusted.xyz>
Date: Wed, 4 Dec 2024 11:01:05 +0100
Subject: [PATCH] fix: correct permission loading for limited organisation

- If a organisation is set to be limited visible, then it will still be
visible for signed-in users. However `UnitPermission` didn't take this
into account, it does now.
- Add unit test.
- Resolves #6141

(cherry picked from commit bc9f1e25337b44706cbef04c68a4041c0cc4b672)
---
 models/organization/org.go      |  2 +-
 models/organization/org_test.go | 34 +++++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/models/organization/org.go b/models/organization/org.go
index 45f19c7696..379c30b5bc 100644
--- a/models/organization/org.go
+++ b/models/organization/org.go
@@ -264,7 +264,7 @@ func (org *Organization) UnitPermission(ctx context.Context, doer *user_model.Us
 		}
 	}
 
-	if org.Visibility.IsPublic() {
+	if org.Visibility.IsPublic() || (org.Visibility.IsLimited() && doer != nil) {
 		return perm.AccessModeRead
 	}
 
diff --git a/models/organization/org_test.go b/models/organization/org_test.go
index 39ccc2d466..21d954b884 100644
--- a/models/organization/org_test.go
+++ b/models/organization/org_test.go
@@ -8,7 +8,9 @@ import (
 
 	"code.gitea.io/gitea/models/db"
 	"code.gitea.io/gitea/models/organization"
+	"code.gitea.io/gitea/models/perm"
 	repo_model "code.gitea.io/gitea/models/repo"
+	"code.gitea.io/gitea/models/unit"
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/structs"
@@ -512,3 +514,35 @@ func TestCreateOrganization4(t *testing.T) {
 	assert.True(t, db.IsErrNameReserved(err))
 	unittest.CheckConsistencyFor(t, &organization.Organization{}, &organization.Team{})
 }
+
+func TestUnitPermission(t *testing.T) {
+	require.NoError(t, unittest.PrepareTestDatabase())
+
+	publicOrg := &organization.Organization{ID: 1001, Visibility: structs.VisibleTypePublic}
+	limitedOrg := &organization.Organization{ID: 1001, Visibility: structs.VisibleTypeLimited}
+	privateOrg := &organization.Organization{ID: 1001, Visibility: structs.VisibleTypePrivate}
+	user := &user_model.User{ID: 1001}
+	t.Run("Anonymous", func(t *testing.T) {
+		t.Run("Public", func(t *testing.T) {
+			assert.EqualValues(t, perm.AccessModeRead, publicOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
+		})
+		t.Run("Limited", func(t *testing.T) {
+			assert.EqualValues(t, perm.AccessModeNone, limitedOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
+		})
+		t.Run("Private", func(t *testing.T) {
+			assert.EqualValues(t, perm.AccessModeNone, privateOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
+		})
+	})
+
+	t.Run("Logged in", func(t *testing.T) {
+		t.Run("Public", func(t *testing.T) {
+			assert.EqualValues(t, perm.AccessModeRead, publicOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
+		})
+		t.Run("Limited", func(t *testing.T) {
+			assert.EqualValues(t, perm.AccessModeRead, limitedOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
+		})
+		t.Run("Private", func(t *testing.T) {
+			assert.EqualValues(t, perm.AccessModeNone, privateOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
+		})
+	})
+}