105 lines
2.5 KiB
V
105 lines
2.5 KiB
V
module core
|
|
|
|
import incubaid.herolib.web.doctree
|
|
import incubaid.herolib.core.pathlib
|
|
import os
|
|
|
|
@[heap]
|
|
pub struct Group {
|
|
pub mut:
|
|
name string // normalized to lowercase
|
|
patterns []string // email patterns, normalized to lowercase
|
|
}
|
|
|
|
@[params]
|
|
pub struct GroupNewArgs {
|
|
pub mut:
|
|
name string @[required]
|
|
patterns []string @[required]
|
|
}
|
|
|
|
// Create a new Group
|
|
pub fn new_group(args GroupNewArgs) !Group {
|
|
mut name := doctree.name_fix(args.name)
|
|
mut patterns := args.patterns.map(it.to_lower())
|
|
|
|
return Group{
|
|
name: name
|
|
patterns: patterns
|
|
}
|
|
}
|
|
|
|
// Check if email matches any pattern in this group
|
|
pub fn (g Group) matches(email string) bool {
|
|
email_lower := email.to_lower()
|
|
|
|
for pattern in g.patterns {
|
|
if matches_pattern(email_lower, pattern) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Helper: match email against wildcard pattern
|
|
// '*@domain.com' matches 'user@domain.com'
|
|
// 'exact@email.com' matches only 'exact@email.com'
|
|
fn matches_pattern(email string, pattern string) bool {
|
|
if pattern == '*' {
|
|
return true
|
|
}
|
|
|
|
if !pattern.contains('*') {
|
|
return email == pattern
|
|
}
|
|
|
|
// Handle wildcard patterns like '*@domain.com'
|
|
if pattern.starts_with('*') {
|
|
suffix := pattern[1..] // Remove the '*'
|
|
return email.ends_with(suffix)
|
|
}
|
|
|
|
// Could add more complex patterns here if needed
|
|
return false
|
|
}
|
|
|
|
// parse_group_file parses a single .group file, resolving includes recursively.
|
|
fn parse_group_file(filename string, base_path string, mut visited map[string]bool) !Group {
|
|
if filename in visited {
|
|
return error('Circular include detected: ${filename}')
|
|
}
|
|
|
|
visited[filename] = true
|
|
|
|
mut group := Group{
|
|
name: doctree.name_fix(filename)
|
|
patterns: []string{}
|
|
}
|
|
|
|
mut file_path := pathlib.get_file(path: '${base_path}/${filename}.group')!
|
|
content := file_path.read()!
|
|
|
|
for line_orig in content.split_into_lines() {
|
|
line := line_orig.trim_space()
|
|
if line.len == 0 || line.starts_with('//') {
|
|
continue
|
|
}
|
|
|
|
if line.starts_with('include:') {
|
|
mut included_name := line.trim_string_left('include:').trim_space()
|
|
included_name = included_name.replace('.group', '') // Remove .group if present
|
|
include_path := '${base_path}/${included_name}.group'
|
|
if !os.exists(include_path) {
|
|
return error('Included group file not found: ${included_name}.group')
|
|
}
|
|
included_group := parse_group_file(included_name, base_path, mut visited)!
|
|
|
|
group.patterns << included_group.patterns
|
|
} else {
|
|
group.patterns << line.to_lower()
|
|
}
|
|
}
|
|
|
|
return group
|
|
}
|