Skip to content

all: add per-client filter list assignment#8274

Open
fegauthier-paragon wants to merge 1 commit intoAdguardTeam:masterfrom
fegauthier-paragon:feat/per-client-filter-lists-backend
Open

all: add per-client filter list assignment#8274
fegauthier-paragon wants to merge 1 commit intoAdguardTeam:masterfrom
fegauthier-paragon:feat/per-client-filter-lists-backend

Conversation

@fegauthier-paragon
Copy link

Summary

  • Add UseOwnFilterLists, FilterListIDs, and AllowFilterListIDs fields to the client data model, following the existing UseOwnBlockedServices pattern
  • Add per-client filter list filtering in matchHost(): when a client has its own filter lists, only rules from assigned lists apply; user rules (ID 0) always apply
  • Load all filters into the DNS engine regardless of their global enabled state, so that per-client assignments work even for globally-disabled filters; globally-disabled filters are excluded at match time for clients using global settings
  • Add YAML and JSON serialization for the new fields, including API endpoints for client add/update/get
  • Add unit tests for filterDNSResultByListIDs, CheckHost with client filter lists, and ApplyClientFiltering

Test plan

  • go test ./internal/filtering/... passes
  • go test ./internal/client/... passes
  • go test ./internal/home/... passes
  • Create a client with use_global_filter_lists: false and specific filter_list_ids via the API
  • Verify that a DNS query for a domain blocked by an assigned list is blocked
  • Verify that a DNS query for a domain blocked by a non-assigned list passes through
  • Verify that user rules always apply regardless of per-client assignment
  • Verify that the YAML config saves and reloads correctly with the new fields

Copy link

@windsurf-bot windsurf-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other comments (2)
  • internal/filtering/filter.go (668-669) The new `enabledBlockFilterIDs` and `enabledAllowFilterIDs` maps are key to the per-client filtering functionality, but they lack documentation. Consider adding comments explaining their purpose and how they're used in the filtering process.
  • internal/filtering/filter.go (218-221) The code now loads all filters regardless of their enabled state, which is a significant change in behavior. Consider adding a comment explaining this design decision to help future maintainers understand the rationale.

💡 To request another review, post a new comment with "?url=https%3A%2F%2Fgithub.com%2Fwindsurf-review".

@fegauthier-paragon fegauthier-paragon force-pushed the feat/per-client-filter-lists-backend branch from 28b699c to 249a7d3 Compare March 2, 2026 18:48
@fegauthier-paragon
Copy link
Author

/windsurf-review

Copy link

@windsurf-bot windsurf-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other comments (1)
  • internal/filtering/filtering.go (1031-1038) When both `setts.ClientFilterListIDs` and `d.enabledBlockFilterIDs` are nil, no filtering is applied to the DNS result. Consider adding a fallback behavior to keep all rules in this case, or document that this is the intended behavior.

💡 To request another review, post a new comment with "?url=https%3A%2F%2Fgithub.com%2Fwindsurf-review".

Add the ability to assign specific blocklists and allowlists to
individual clients.  When UseOwnFilterLists is true, only the
assigned filter lists apply to that client instead of the global
ones.  User rules (ID 0) always apply regardless of assignment.

All filters are now loaded into the engine even when globally
disabled, so that per-client assignments work for any filter.
Globally-disabled filters are excluded at match time for clients
using global settings.
@fegauthier-paragon fegauthier-paragon force-pushed the feat/per-client-filter-lists-backend branch from 249a7d3 to 944544d Compare March 2, 2026 18:53
@fegauthier-paragon
Copy link
Author

/windsurf-review

Copy link

@windsurf-bot windsurf-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other comments (4)
  • internal/client/storage_test.go (1330-1331) Consider using the two-value lookup pattern for map access here as well:
    	require.NotNil(t, setts.ClientAllowListIDs)
    	val, ok := setts.ClientAllowListIDs[5]
    	assert.True(t, ok && val)
    
  • internal/filtering/filter.go (209-214) While the new comment at line 209-214 explains why disabled filters are loaded, it would be helpful to add a note about the memory usage implications. Consider mentioning approximate memory overhead per rule or filter to help users understand the tradeoff between functionality and resource usage.
  • internal/filtering/filter.go (649-658) Variable naming inconsistency: `enabledBlockIDs` and `enabledAllowIDs` are declared but then assigned to `d.enabledBlockFilterIDs` and `d.enabledAllowFilterIDs`. Consider using consistent naming to avoid confusion.
    	enabledBlockFilterIDs := make(map[rules.ListID]bool, len(d.conf.Filters))
    	for _, filter := range d.conf.Filters {
    		filters = append(filters, Filter{
    			ID:       filter.ID,
    			FilePath: filter.Path(d.conf.DataDir),
    		})
    		if filter.Enabled {
    			enabledBlockFilterIDs[filter.ID] = true
    		}
    	}
    
  • internal/filtering/filter.go (660-670) Similar naming inconsistency for allowlist filters. Consider using consistent variable names.
    	enabledAllowFilterIDs := make(map[rules.ListID]bool, len(d.conf.WhitelistFilters))
    	var allowFilters []Filter
    	for _, filter := range d.conf.WhitelistFilters {
    		allowFilters = append(allowFilters, Filter{
    			ID:       filter.ID,
    			FilePath: filter.Path(d.conf.DataDir),
    		})
    		if filter.Enabled {
    			enabledAllowFilterIDs[filter.ID] = true
    		}
    	}
    

💡 To request another review, post a new comment with "?url=https%3A%2F%2Fgithub.com%2Fwindsurf-review".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant