Skip to content

Commit c5e194f

Browse files
committed
cursor-review: add missing field, sanity check and mutex locking
1 parent 7b872ed commit c5e194f

File tree

1 file changed

+41
-21
lines changed

1 file changed

+41
-21
lines changed

server/lib/policy/policy.go

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ const PolicyPath = "/etc/chromium/policies/managed/policy.json"
1313
type Policy struct {
1414
mu sync.Mutex
1515

16-
PasswordManagerEnabled bool `json:"PasswordManagerEnabled"`
17-
AutofillCreditCardEnabled bool `json:"AutofillCreditCardEnabled"`
18-
TranslateEnabled bool `json:"TranslateEnabled"`
19-
ExtensionSettings map[string]ExtensionSetting `json:"ExtensionSettings"`
16+
PasswordManagerEnabled bool `json:"PasswordManagerEnabled"`
17+
AutofillCreditCardEnabled bool `json:"AutofillCreditCardEnabled"`
18+
TranslateEnabled bool `json:"TranslateEnabled"`
19+
DefaultNotificationsSetting int `json:"DefaultNotificationsSetting"`
20+
ExtensionSettings map[string]ExtensionSetting `json:"ExtensionSettings"`
2021
}
2122

2223
// ExtensionSetting represents settings for a specific extension
@@ -29,23 +30,19 @@ type ExtensionSetting struct {
2930
RuntimeAllowedHosts []string `json:"runtime_allowed_hosts,omitempty"`
3031
}
3132

32-
var (
33-
)
34-
35-
// ReadPolicy reads the current enterprise policy from disk
36-
func (p *Policy) ReadPolicy() (*Policy, error) {
37-
p.mu.Lock()
38-
defer p.mu.Unlock()
39-
33+
// readPolicyUnlocked reads the current enterprise policy from disk without locking
34+
// This is an internal helper for use within already-locked operations
35+
func (p *Policy) readPolicyUnlocked() (*Policy, error) {
4036
data, err := os.ReadFile(PolicyPath)
4137
if err != nil {
4238
if os.IsNotExist(err) {
4339
// Return default policy if file doesn't exist
4440
return &Policy{
45-
PasswordManagerEnabled: false,
46-
AutofillCreditCardEnabled: false,
47-
TranslateEnabled: false,
48-
ExtensionSettings: make(map[string]ExtensionSetting),
41+
PasswordManagerEnabled: false,
42+
AutofillCreditCardEnabled: false,
43+
TranslateEnabled: false,
44+
DefaultNotificationsSetting: 2,
45+
ExtensionSettings: make(map[string]ExtensionSetting),
4946
}, nil
5047
}
5148
return nil, fmt.Errorf("failed to read policy file: %w", err)
@@ -56,14 +53,25 @@ func (p *Policy) ReadPolicy() (*Policy, error) {
5653
return nil, fmt.Errorf("failed to parse policy file: %w", err)
5754
}
5855

56+
// Initialize ExtensionSettings map if it's nil to prevent panic on write
57+
if policy.ExtensionSettings == nil {
58+
policy.ExtensionSettings = make(map[string]ExtensionSetting)
59+
}
60+
5961
return &policy, nil
6062
}
6163

62-
// WritePolicy writes the policy to disk
63-
func (p *Policy) WritePolicy(policy *Policy) error {
64+
// ReadPolicy reads the current enterprise policy from disk
65+
func (p *Policy) ReadPolicy() (*Policy, error) {
6466
p.mu.Lock()
6567
defer p.mu.Unlock()
6668

69+
return p.readPolicyUnlocked()
70+
}
71+
72+
// writePolicyUnlocked writes the policy to disk without locking
73+
// This is an internal helper for use within already-locked operations
74+
func (p *Policy) writePolicyUnlocked(policy *Policy) error {
6775
data, err := json.MarshalIndent(policy, "", " ")
6876
if err != nil {
6977
return fmt.Errorf("failed to marshal policy: %w", err)
@@ -76,10 +84,22 @@ func (p *Policy) WritePolicy(policy *Policy) error {
7684
return nil
7785
}
7886

87+
// WritePolicy writes the policy to disk
88+
func (p *Policy) WritePolicy(policy *Policy) error {
89+
p.mu.Lock()
90+
defer p.mu.Unlock()
91+
92+
return p.writePolicyUnlocked(policy)
93+
}
94+
7995
// AddExtension adds or updates an extension in the policy
8096
// extensionID should be a stable identifier (can be derived from extension path)
81-
func (p *Policy) AddExtension(extensionID, extensionPath string, requiresEnterprisePolicy bool) error {
82-
policy, err := p.ReadPolicy()
97+
func (p *Policy) AddExtension(extensionID, extensionPath string, requiresEnterprisePolicy bool) error {
98+
// Lock for the entire read-modify-write cycle to prevent race conditions
99+
p.mu.Lock()
100+
defer p.mu.Unlock()
101+
102+
policy, err := p.readPolicyUnlocked()
83103
if err != nil {
84104
return err
85105
}
@@ -109,7 +129,7 @@ func (p *Policy) AddExtension(extensionID, extensionPath string, requiresEnterpr
109129

110130
policy.ExtensionSettings[extensionID] = setting
111131

112-
return p.WritePolicy(policy)
132+
return p.writePolicyUnlocked(policy)
113133
}
114134

115135
// GenerateExtensionID returns a stable identifier for the extension policy.

0 commit comments

Comments
 (0)