-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#3 access control entry data to hold the data for access control entr…
…ies support is added
- Loading branch information
Krishnakant C
authored and
Krishnakant C
committed
Sep 10, 2024
1 parent
54528d2
commit 92d7493
Showing
2 changed files
with
331 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
// Copyright 2024 Atomstate Technologies Private Limited | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package acl | ||
|
||
import "fmt" | ||
|
||
// AccessControlEntryData holds the data for access control entries. | ||
type AccessControlEntryData struct { | ||
principal string | ||
host string | ||
operation AclOperation | ||
permissionType AclPermissionType | ||
} | ||
|
||
// NewAccessControlEntryData creates a new AccessControlEntryData instance. | ||
// | ||
// Parameters: | ||
// - principal: The principal (user or entity) associated with the entry. | ||
// - host: The host associated with the entry. | ||
// - operation: The ACL operation that this entry allows or denies. | ||
// - permissionType: The type of permission (ALLOW, DENY, etc.) associated with the entry. | ||
// | ||
// Returns: | ||
// A pointer to a new AccessControlEntryData instance. | ||
// | ||
// Example usage: | ||
// | ||
// entry := NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW) | ||
func NewAccessControlEntryData( | ||
principal, host string, | ||
operation AclOperation, | ||
permissionType AclPermissionType) *AccessControlEntryData { | ||
return &AccessControlEntryData{ | ||
principal: principal, | ||
host: host, | ||
operation: operation, | ||
permissionType: permissionType, | ||
} | ||
} | ||
|
||
// Principal returns the principal associated with the entry. | ||
// | ||
// Returns: | ||
// The principal as a string. | ||
// | ||
// Example usage: | ||
// | ||
// principal := entry.Principal() | ||
func (a *AccessControlEntryData) Principal() string { | ||
return a.principal | ||
} | ||
|
||
// Host returns the host associated with the entry. | ||
// | ||
// Returns: | ||
// The host as a string. | ||
// | ||
// Example usage: | ||
// | ||
// host := entry.Host() | ||
func (a *AccessControlEntryData) Host() string { | ||
return a.host | ||
} | ||
|
||
// Operation returns the ACL operation associated with the entry. | ||
// | ||
// Returns: | ||
// The ACL operation as an AclOperation type. | ||
// | ||
// Example usage: | ||
// | ||
// operation := entry.Operation() | ||
func (a *AccessControlEntryData) Operation() AclOperation { | ||
return a.operation | ||
} | ||
|
||
// PermissionType returns the permission type associated with the entry. | ||
// | ||
// Returns: | ||
// The permission type as an AclPermissionType type. | ||
// | ||
// Example usage: | ||
// | ||
// permissionType := entry.PermissionType() | ||
func (a *AccessControlEntryData) PermissionType() AclPermissionType { | ||
return a.permissionType | ||
} | ||
|
||
// FindIndefiniteField checks for indefinite fields and returns a corresponding message. | ||
// | ||
// Returns: | ||
// A string message indicating which field is indefinite, or an empty string if all fields are defined. | ||
// | ||
// Example usage: | ||
// | ||
// message := entry.FindIndefiniteField() | ||
func (a *AccessControlEntryData) FindIndefiniteField() string { | ||
switch { | ||
case a.principal == "": | ||
return "Principal is NULL" | ||
case a.host == "": | ||
return "Host is NULL" | ||
case a.operation == OpAny: | ||
return "Operation is ANY" | ||
case a.operation == OpUnknown: | ||
return "Operation is UNKNOWN" | ||
case a.permissionType == ANY: | ||
return "Permission type is ANY" | ||
case a.permissionType == UNKNOWN: | ||
return "Permission type is UNKNOWN" | ||
default: | ||
return "" | ||
} | ||
} | ||
|
||
// IsUnknown checks if there are any UNKNOWN components in the entry. | ||
// | ||
// Returns: | ||
// A boolean indicating whether the entry contains any UNKNOWN components. | ||
// | ||
// Example usage: | ||
// | ||
// if entry.IsUnknown() { | ||
// fmt.Println("Entry contains unknown components.") | ||
// } | ||
func (a *AccessControlEntryData) IsUnknown() bool { | ||
return a.operation == OpUnknown || a.permissionType == UNKNOWN | ||
} | ||
|
||
// String returns a string representation of the AccessControlEntryData. | ||
// | ||
// Returns: | ||
// A formatted string that represents the AccessControlEntryData instance. | ||
// | ||
// Example usage: | ||
// | ||
// fmt.Println(entry.String()) | ||
func (a *AccessControlEntryData) String() string { | ||
principalStr := "<any>" | ||
if a.principal != "" { | ||
principalStr = a.principal | ||
} | ||
hostStr := "<any>" | ||
if a.host != "" { | ||
hostStr = a.host | ||
} | ||
return fmt.Sprintf("(principal=%s, host=%s, operation=%d, permissionType=%d)", | ||
principalStr, | ||
hostStr, | ||
a.operation, | ||
a.permissionType) | ||
} | ||
|
||
// Equals checks if two AccessControlEntryData instances are equal. | ||
// | ||
// Parameters: | ||
// - other: A pointer to another AccessControlEntryData instance to compare against. | ||
// | ||
// Returns: | ||
// A boolean indicating whether the two instances are equal. | ||
// | ||
// Example usage: | ||
// | ||
// if entry.Equals(otherEntry) { | ||
// fmt.Println("Entries are equal.") | ||
// } | ||
func (a *AccessControlEntryData) Equals(other *AccessControlEntryData) bool { | ||
if other == nil { | ||
return false | ||
} | ||
return a.principal == other.principal && | ||
a.host == other.host && | ||
a.operation == other.operation && | ||
a.permissionType == other.permissionType | ||
} | ||
|
||
// HashCode returns a hash code for the AccessControlEntryData. | ||
// | ||
// Returns: | ||
// An integer representing the hash code of the instance. | ||
// | ||
// Example usage: | ||
// | ||
// hash := entry.HashCode() | ||
func (a *AccessControlEntryData) HashCode() int { | ||
hash := 0 | ||
for _, char := range a.principal { | ||
hash += int(char) | ||
} | ||
for _, char := range a.host { | ||
hash += int(char) | ||
} | ||
hash += int(a.operation) + int(a.permissionType) | ||
return hash | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// Copyright 2024 Atomstate Technologies Private Limited | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package acl | ||
|
||
import "testing" | ||
|
||
func TestNewAccessControlEntryData(t *testing.T) { | ||
entry := NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW) | ||
|
||
if entry.Principal() != "user1" { | ||
t.Errorf("Expected principal user1, got %s", entry.Principal()) | ||
} | ||
if entry.Host() != "localhost" { | ||
t.Errorf("Expected host localhost, got %s", entry.Host()) | ||
} | ||
if entry.Operation() != OpRead { | ||
t.Errorf("Expected operation OpRead, got %d", entry.Operation()) | ||
} | ||
if entry.PermissionType() != ALLOW { | ||
t.Errorf("Expected permission type ALLOW, got %d", entry.PermissionType()) | ||
} | ||
} | ||
|
||
func TestFindIndefiniteField(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
entry *AccessControlEntryData | ||
expected string | ||
}{ | ||
{"Nil Principal", NewAccessControlEntryData("", "localhost", OpRead, ALLOW), "Principal is NULL"}, | ||
{"Nil Host", NewAccessControlEntryData("user1", "", OpRead, ALLOW), "Host is NULL"}, | ||
{"Any Operation", NewAccessControlEntryData("user1", "localhost", OpAny, ALLOW), "Operation is ANY"}, | ||
{"Unknown Operation", NewAccessControlEntryData("user1", "localhost", OpUnknown, ALLOW), "Operation is UNKNOWN"}, | ||
{"Any Permission Type", NewAccessControlEntryData("user1", "localhost", OpRead, ANY), "Permission type is ANY"}, | ||
{"Unknown Permission Type", NewAccessControlEntryData("user1", "localhost", OpRead, UNKNOWN), "Permission type is UNKNOWN"}, | ||
{"All Fields Valid", NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW), ""}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
result := tt.entry.FindIndefiniteField() | ||
if result != tt.expected { | ||
t.Errorf("Expected %s, got %s", tt.expected, result) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestIsUnknown(t *testing.T) { | ||
tests := []struct { | ||
entry *AccessControlEntryData | ||
expected bool | ||
}{ | ||
{NewAccessControlEntryData("user1", "localhost", OpUnknown, ALLOW), true}, | ||
{NewAccessControlEntryData("user1", "localhost", OpRead, UNKNOWN), true}, | ||
{NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW), false}, | ||
} | ||
|
||
for _, tt := range tests { | ||
result := tt.entry.IsUnknown() | ||
if result != tt.expected { | ||
t.Errorf("Expected %v, got %v", tt.expected, result) | ||
} | ||
} | ||
} | ||
|
||
func TestString(t *testing.T) { | ||
entry := NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW) | ||
expected := "(principal=user1, host=localhost, operation=3, permissionType=3)" | ||
if entry.String() != expected { | ||
t.Errorf("Expected %s, got %s", expected, entry.String()) | ||
} | ||
} | ||
|
||
func TestEquals(t *testing.T) { | ||
entry1 := NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW) | ||
entry2 := NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW) | ||
entry3 := NewAccessControlEntryData("user2", "localhost", OpRead, ALLOW) | ||
|
||
if !entry1.Equals(entry2) { | ||
t.Errorf("Expected entries to be equal") | ||
} | ||
if entry1.Equals(entry3) { | ||
t.Errorf("Expected entries to be different") | ||
} | ||
if entry1.Equals(nil) { | ||
t.Errorf("Expected entry1 to not equal nil") | ||
} | ||
} | ||
|
||
func TestHashCode(t *testing.T) { | ||
entry := NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW) | ||
expectedHash := entry.HashCode() // Store the expected hash | ||
if entry.HashCode() != expectedHash { | ||
t.Errorf("Hash code should remain consistent; got %d", entry.HashCode()) | ||
} | ||
|
||
// Test with different entries | ||
entry2 := NewAccessControlEntryData("user2", "localhost", OpRead, ALLOW) | ||
if entry.HashCode() == entry2.HashCode() { | ||
t.Errorf("Expected different hash codes for different entries") | ||
} | ||
} | ||
|
||
func TestHashCodeConsistency(t *testing.T) { | ||
entry := NewAccessControlEntryData("user1", "localhost", OpRead, ALLOW) | ||
hash1 := entry.HashCode() | ||
hash2 := entry.HashCode() | ||
if hash1 != hash2 { | ||
t.Errorf("Hash code should be consistent; got %d and %d", hash1, hash2) | ||
} | ||
} |