circle core objects work again
This commit is contained in:
@@ -64,10 +64,12 @@ os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowunive
|
|||||||
println('Herolib installation completed successfully!')
|
println('Herolib installation completed successfully!')
|
||||||
|
|
||||||
// Add vtest alias
|
// Add vtest alias
|
||||||
addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -n -w -cg -gc none -cc tcc test\' ') or {
|
addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -show-c-output -n -w -cg -gc none -cc tcc test\' ') or {
|
||||||
eprintln('Failed to add vtest alias: ${err}')
|
eprintln('Failed to add vtest alias: ${err}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//alias vtest='v -gc none -stats -enable-globals -show-c-output -keepc -n -w -cg -o /tmp/tester.c -g -cc tcc test'
|
||||||
|
|
||||||
addtoscript('HOME/hero/bin', 'export PATH="\$PATH:\$HOME/hero/bin"') or {
|
addtoscript('HOME/hero/bin', 'export PATH="\$PATH:\$HOME/hero/bin"') or {
|
||||||
eprintln('Failed to add path to hero, ${err}')
|
eprintln('Failed to add path to hero, ${err}')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ pub struct CircleCoordinator {
|
|||||||
pub mut:
|
pub mut:
|
||||||
name string //is a unique name on planetary scale is a dns name
|
name string //is a unique name on planetary scale is a dns name
|
||||||
agents &core.AgentDB
|
agents &core.AgentDB
|
||||||
// circles &core.CircleDB
|
circles &core.CircleDB
|
||||||
// names &core.NameDB
|
names &core.NameDB
|
||||||
session_state models.SessionState
|
session_state models.SessionState
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,13 +54,13 @@ pub fn new(args_ CircleCoordinatorArgs) !&CircleCoordinator {
|
|||||||
|
|
||||||
// Initialize the db handlers with proper ourdb instances
|
// Initialize the db handlers with proper ourdb instances
|
||||||
mut agent_db := core.new_agentdb(session_state)!
|
mut agent_db := core.new_agentdb(session_state)!
|
||||||
// mut circle_db := core.new_circledb(session_state)!
|
mut circle_db := core.new_circledb(session_state)!
|
||||||
// mut name_db := core.new_namedb(session_state)!
|
mut name_db := core.new_namedb(session_state)!
|
||||||
|
|
||||||
mut cm := &CircleCoordinator{
|
mut cm := &CircleCoordinator{
|
||||||
agents: &agent_db
|
agents: &agent_db
|
||||||
// circles: &circle_db
|
circles: &circle_db
|
||||||
// names: &name_db
|
names: &name_db
|
||||||
session_state: session_state
|
session_state: session_state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
149
lib/circles/dbs/core/circle_db.v
Normal file
149
lib/circles/dbs/core/circle_db.v
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
module core
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.circles.models { DBHandler, SessionState }
|
||||||
|
import freeflowuniverse.herolib.circles.models.core { Circle }
|
||||||
|
|
||||||
|
@[heap]
|
||||||
|
pub struct CircleDB {
|
||||||
|
pub mut:
|
||||||
|
db DBHandler[Circle]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_circledb(session_state SessionState) !CircleDB {
|
||||||
|
return CircleDB{
|
||||||
|
db: models.new_dbhandler[Circle]('circle', session_state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut m CircleDB) new() Circle {
|
||||||
|
return Circle{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set adds or updates a circle
|
||||||
|
pub fn (mut m CircleDB) set(circle Circle) !Circle {
|
||||||
|
return m.db.set(circle)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// get retrieves a circle by its ID
|
||||||
|
pub fn (mut m CircleDB) get(id u32) !Circle {
|
||||||
|
return m.db.get(id)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// list returns all circle IDs
|
||||||
|
pub fn (mut m CircleDB) list() ![]u32 {
|
||||||
|
return m.db.list()!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut m CircleDB) getall() ![]Circle {
|
||||||
|
return m.db.getall()!
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete removes a circle by its ID
|
||||||
|
pub fn (mut m CircleDB) delete(id u32) ! {
|
||||||
|
m.db.delete(id)!
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////CUSTOM METHODS//////////////////////////////////
|
||||||
|
|
||||||
|
// get_by_name retrieves a circle by its name
|
||||||
|
pub fn (mut m CircleDB) get_by_name(name string) !Circle {
|
||||||
|
return m.db.get_by_key('name', name)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete_by_name removes a circle by its name
|
||||||
|
pub fn (mut m CircleDB) delete_by_name(name string) ! {
|
||||||
|
// Get the circle by name
|
||||||
|
circle := m.get_by_name(name) or {
|
||||||
|
// Circle not found, nothing to delete
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the circle by ID
|
||||||
|
m.delete(circle.id)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_all_circle_names returns all circle names
|
||||||
|
pub fn (mut m CircleDB) get_all_circle_names() ![]string {
|
||||||
|
// Get all circle IDs
|
||||||
|
circle_ids := m.list()!
|
||||||
|
|
||||||
|
// Get names for all circles
|
||||||
|
mut names := []string{}
|
||||||
|
for id in circle_ids {
|
||||||
|
circle := m.get(id) or { continue }
|
||||||
|
names << circle.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
// add_member adds a member to a circle
|
||||||
|
pub fn (mut m CircleDB) add_member(circle_name string, member core.Member) !Circle {
|
||||||
|
// Get the circle by name
|
||||||
|
mut circle := m.get_by_name(circle_name)!
|
||||||
|
|
||||||
|
// Check if member with same name already exists
|
||||||
|
for existing_member in circle.members {
|
||||||
|
if existing_member.name == member.name {
|
||||||
|
return error('Member with name ${member.name} already exists in circle ${circle_name}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the member
|
||||||
|
circle.members << member
|
||||||
|
|
||||||
|
// Save the updated circle
|
||||||
|
return m.set(circle)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove_member removes a member from a circle by name
|
||||||
|
pub fn (mut m CircleDB) remove_member(circle_name string, member_name string) !Circle {
|
||||||
|
// Get the circle by name
|
||||||
|
mut circle := m.get_by_name(circle_name)!
|
||||||
|
|
||||||
|
// Find and remove the member
|
||||||
|
mut found := false
|
||||||
|
mut new_members := []core.Member{}
|
||||||
|
|
||||||
|
for member in circle.members {
|
||||||
|
if member.name == member_name {
|
||||||
|
found = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
new_members << member
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return error('Member with name ${member_name} not found in circle ${circle_name}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the circle members
|
||||||
|
circle.members = new_members
|
||||||
|
|
||||||
|
// Save the updated circle
|
||||||
|
return m.set(circle)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_member_role updates the role of a member in a circle
|
||||||
|
pub fn (mut m CircleDB) update_member_role(circle_name string, member_name string, new_role core.Role) !Circle {
|
||||||
|
// Get the circle by name
|
||||||
|
mut circle := m.get_by_name(circle_name)!
|
||||||
|
|
||||||
|
// Find and update the member
|
||||||
|
mut found := false
|
||||||
|
|
||||||
|
for i, mut member in circle.members {
|
||||||
|
if member.name == member_name {
|
||||||
|
circle.members[i].role = new_role
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return error('Member with name ${member_name} not found in circle ${circle_name}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the updated circle
|
||||||
|
return m.set(circle)!
|
||||||
|
}
|
||||||
192
lib/circles/dbs/core/circle_db_test.v
Normal file
192
lib/circles/dbs/core/circle_db_test.v
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
module core
|
||||||
|
|
||||||
|
import os
|
||||||
|
import rand
|
||||||
|
import freeflowuniverse.herolib.circles.actionprocessor
|
||||||
|
import freeflowuniverse.herolib.circles.models.core
|
||||||
|
|
||||||
|
fn test_circle_db() {
|
||||||
|
// Create a temporary directory for testing
|
||||||
|
test_dir := os.join_path(os.temp_dir(), 'hero_circle_test_${rand.intn(9000) or { 0 } + 1000}')
|
||||||
|
os.mkdir_all(test_dir) or { panic(err) }
|
||||||
|
defer { os.rmdir_all(test_dir) or {} }
|
||||||
|
|
||||||
|
mut runner := actionprocessor.new(path: test_dir)!
|
||||||
|
|
||||||
|
// Create multiple circles for testing
|
||||||
|
mut circle1 := runner.circles.new()
|
||||||
|
circle1.name = 'test-circle-1'
|
||||||
|
circle1.description = 'Test Circle 1'
|
||||||
|
|
||||||
|
mut circle2 := runner.circles.new()
|
||||||
|
circle2.name = 'test-circle-2'
|
||||||
|
circle2.description = 'Test Circle 2'
|
||||||
|
|
||||||
|
mut circle3 := runner.circles.new()
|
||||||
|
circle3.name = 'test-circle-3'
|
||||||
|
circle3.description = 'Test Circle 3'
|
||||||
|
|
||||||
|
// Create members for testing
|
||||||
|
mut member1 := core.Member{
|
||||||
|
name: 'member1'
|
||||||
|
description: 'Test Member 1'
|
||||||
|
role: .admin
|
||||||
|
pubkeys: ['pubkey1']
|
||||||
|
emails: ['member1@example.com']
|
||||||
|
}
|
||||||
|
|
||||||
|
mut member2 := core.Member{
|
||||||
|
name: 'member2'
|
||||||
|
description: 'Test Member 2'
|
||||||
|
role: .member
|
||||||
|
pubkeys: ['pubkey2']
|
||||||
|
emails: ['member2@example.com']
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add members to circle1
|
||||||
|
circle1.members << member1
|
||||||
|
circle1.members << member2
|
||||||
|
|
||||||
|
// Add the circles
|
||||||
|
println('Adding circle 1')
|
||||||
|
circle1 = runner.circles.set(circle1)!
|
||||||
|
|
||||||
|
// Explicitly set different IDs for each circle to avoid overwriting
|
||||||
|
circle2.id = 1 // Set a different ID for circle2
|
||||||
|
println('Adding circle 2')
|
||||||
|
circle2 = runner.circles.set(circle2)!
|
||||||
|
|
||||||
|
circle3.id = 2 // Set a different ID for circle3
|
||||||
|
println('Adding circle 3')
|
||||||
|
circle3 = runner.circles.set(circle3)!
|
||||||
|
|
||||||
|
// Test list functionality
|
||||||
|
println('Testing list functionality')
|
||||||
|
|
||||||
|
// Get all circles
|
||||||
|
all_circles := runner.circles.getall()!
|
||||||
|
println('Retrieved ${all_circles.len} circles')
|
||||||
|
for i, circle in all_circles {
|
||||||
|
println('Circle ${i}: id=${circle.id}, name=${circle.name}')
|
||||||
|
}
|
||||||
|
|
||||||
|
assert all_circles.len == 3, 'Expected 3 circles, got ${all_circles.len}'
|
||||||
|
|
||||||
|
// Verify all circles are in the list
|
||||||
|
mut found1 := false
|
||||||
|
mut found2 := false
|
||||||
|
mut found3 := false
|
||||||
|
|
||||||
|
for circle in all_circles {
|
||||||
|
if circle.name == 'test-circle-1' {
|
||||||
|
found1 = true
|
||||||
|
} else if circle.name == 'test-circle-2' {
|
||||||
|
found2 = true
|
||||||
|
} else if circle.name == 'test-circle-3' {
|
||||||
|
found3 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert found1, 'Circle 1 not found in list'
|
||||||
|
assert found2, 'Circle 2 not found in list'
|
||||||
|
assert found3, 'Circle 3 not found in list'
|
||||||
|
|
||||||
|
// Get and verify individual circles
|
||||||
|
println('Verifying individual circles')
|
||||||
|
retrieved_circle1 := runner.circles.get_by_name('test-circle-1')!
|
||||||
|
assert retrieved_circle1.name == circle1.name
|
||||||
|
assert retrieved_circle1.description == circle1.description
|
||||||
|
assert retrieved_circle1.members.len == 2
|
||||||
|
assert retrieved_circle1.members[0].name == 'member1'
|
||||||
|
assert retrieved_circle1.members[0].role == .admin
|
||||||
|
assert retrieved_circle1.members[1].name == 'member2'
|
||||||
|
assert retrieved_circle1.members[1].role == .member
|
||||||
|
|
||||||
|
// Test add_member method
|
||||||
|
println('Testing add_member method')
|
||||||
|
mut member3 := core.Member{
|
||||||
|
name: 'member3'
|
||||||
|
description: 'Test Member 3'
|
||||||
|
role: .contributor
|
||||||
|
pubkeys: ['pubkey3']
|
||||||
|
emails: ['member3@example.com']
|
||||||
|
}
|
||||||
|
|
||||||
|
runner.circles.add_member('test-circle-2', member3)!
|
||||||
|
updated_circle2 := runner.circles.get_by_name('test-circle-2')!
|
||||||
|
assert updated_circle2.members.len == 1
|
||||||
|
assert updated_circle2.members[0].name == 'member3'
|
||||||
|
assert updated_circle2.members[0].role == .contributor
|
||||||
|
|
||||||
|
// Test update_member_role method
|
||||||
|
println('Testing update_member_role method')
|
||||||
|
runner.circles.update_member_role('test-circle-2', 'member3', .stakeholder)!
|
||||||
|
role_updated_circle2 := runner.circles.get_by_name('test-circle-2')!
|
||||||
|
assert role_updated_circle2.members[0].role == .stakeholder
|
||||||
|
|
||||||
|
// Test remove_member method
|
||||||
|
println('Testing remove_member method')
|
||||||
|
runner.circles.remove_member('test-circle-1', 'member2')!
|
||||||
|
member_removed_circle1 := runner.circles.get_by_name('test-circle-1')!
|
||||||
|
assert member_removed_circle1.members.len == 1
|
||||||
|
assert member_removed_circle1.members[0].name == 'member1'
|
||||||
|
|
||||||
|
// Test get_all_circle_names method
|
||||||
|
println('Testing get_all_circle_names method')
|
||||||
|
circle_names := runner.circles.get_all_circle_names()!
|
||||||
|
assert circle_names.len == 3
|
||||||
|
assert 'test-circle-1' in circle_names
|
||||||
|
assert 'test-circle-2' in circle_names
|
||||||
|
assert 'test-circle-3' in circle_names
|
||||||
|
|
||||||
|
// Test delete functionality
|
||||||
|
println('Testing delete functionality')
|
||||||
|
// Delete circle 2
|
||||||
|
runner.circles.delete_by_name('test-circle-2')!
|
||||||
|
|
||||||
|
// Verify deletion with list
|
||||||
|
circles_after_delete := runner.circles.getall()!
|
||||||
|
assert circles_after_delete.len == 2, 'Expected 2 circles after deletion, got ${circles_after_delete.len}'
|
||||||
|
|
||||||
|
// Verify the remaining circles
|
||||||
|
mut found_after_delete1 := false
|
||||||
|
mut found_after_delete2 := false
|
||||||
|
mut found_after_delete3 := false
|
||||||
|
|
||||||
|
for circle in circles_after_delete {
|
||||||
|
if circle.name == 'test-circle-1' {
|
||||||
|
found_after_delete1 = true
|
||||||
|
} else if circle.name == 'test-circle-2' {
|
||||||
|
found_after_delete2 = true
|
||||||
|
} else if circle.name == 'test-circle-3' {
|
||||||
|
found_after_delete3 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert found_after_delete1, 'Circle 1 not found after deletion'
|
||||||
|
assert !found_after_delete2, 'Circle 2 found after deletion (should be deleted)'
|
||||||
|
assert found_after_delete3, 'Circle 3 not found after deletion'
|
||||||
|
|
||||||
|
// Delete another circle
|
||||||
|
println('Deleting another circle')
|
||||||
|
runner.circles.delete_by_name('test-circle-3')!
|
||||||
|
|
||||||
|
// Verify only one circle remains
|
||||||
|
circles_after_second_delete := runner.circles.getall()!
|
||||||
|
assert circles_after_second_delete.len == 1, 'Expected 1 circle after second deletion, got ${circles_after_second_delete.len}'
|
||||||
|
assert circles_after_second_delete[0].name == 'test-circle-1', 'Remaining circle should be test-circle-1'
|
||||||
|
|
||||||
|
// Delete the last circle
|
||||||
|
println('Deleting last circle')
|
||||||
|
runner.circles.delete_by_name('test-circle-1')!
|
||||||
|
|
||||||
|
// Verify no circles remain
|
||||||
|
circles_after_all_deleted := runner.circles.getall() or {
|
||||||
|
// This is expected to fail with 'No circles found' error
|
||||||
|
assert err.msg().contains('No index keys defined for this type') || err.msg().contains('No circles found')
|
||||||
|
[]core.Circle{cap: 0}
|
||||||
|
}
|
||||||
|
assert circles_after_all_deleted.len == 0, 'Expected 0 circles after all deletions, got ${circles_after_all_deleted.len}'
|
||||||
|
|
||||||
|
println('All tests passed successfully')
|
||||||
|
}
|
||||||
194
lib/circles/dbs/core/name_db.v
Normal file
194
lib/circles/dbs/core/name_db.v
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
module core
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.circles.models { DBHandler, SessionState }
|
||||||
|
import freeflowuniverse.herolib.circles.models.core { Name, Record, RecordType }
|
||||||
|
|
||||||
|
@[heap]
|
||||||
|
pub struct NameDB {
|
||||||
|
pub mut:
|
||||||
|
db DBHandler[Name]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_namedb(session_state SessionState) !NameDB {
|
||||||
|
return NameDB{
|
||||||
|
db: models.new_dbhandler[Name]('name', session_state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut m NameDB) new() Name {
|
||||||
|
return Name{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set adds or updates a name
|
||||||
|
pub fn (mut m NameDB) set(name Name) !Name {
|
||||||
|
return m.db.set(name)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// get retrieves a name by its ID
|
||||||
|
pub fn (mut m NameDB) get(id u32) !Name {
|
||||||
|
return m.db.get(id)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// list returns all name IDs
|
||||||
|
pub fn (mut m NameDB) list() ![]u32 {
|
||||||
|
return m.db.list()!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut m NameDB) getall() ![]Name {
|
||||||
|
return m.db.getall()!
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete removes a name by its ID
|
||||||
|
pub fn (mut m NameDB) delete(id u32) ! {
|
||||||
|
m.db.delete(id)!
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////CUSTOM METHODS//////////////////////////////////
|
||||||
|
|
||||||
|
// get_by_domain retrieves a name by its domain
|
||||||
|
pub fn (mut m NameDB) get_by_domain(domain string) !Name {
|
||||||
|
return m.db.get_by_key('domain', domain)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete_by_domain removes a name by its domain
|
||||||
|
pub fn (mut m NameDB) delete_by_domain(domain string) ! {
|
||||||
|
// Get the name by domain
|
||||||
|
name := m.get_by_domain(domain) or {
|
||||||
|
// Name not found, nothing to delete
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the name by ID
|
||||||
|
m.delete(name.id)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_all_domains returns all domains
|
||||||
|
pub fn (mut m NameDB) get_all_domains() ![]string {
|
||||||
|
// Get all name IDs
|
||||||
|
name_ids := m.list()!
|
||||||
|
|
||||||
|
// Get domains for all names
|
||||||
|
mut domains := []string{}
|
||||||
|
for id in name_ids {
|
||||||
|
name := m.get(id) or { continue }
|
||||||
|
domains << name.domain
|
||||||
|
}
|
||||||
|
|
||||||
|
return domains
|
||||||
|
}
|
||||||
|
|
||||||
|
// add_record adds a record to a name
|
||||||
|
pub fn (mut m NameDB) add_record(domain string, record Record) !Name {
|
||||||
|
// Get the name by domain
|
||||||
|
mut name := m.get_by_domain(domain)!
|
||||||
|
|
||||||
|
// Check if record with same name and type already exists
|
||||||
|
for existing_record in name.records {
|
||||||
|
if existing_record.name == record.name && existing_record.category == record.category {
|
||||||
|
return error('Record with name ${record.name} and type ${record.category} already exists in domain ${domain}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the record
|
||||||
|
name.records << record
|
||||||
|
|
||||||
|
// Save the updated name
|
||||||
|
return m.set(name)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove_record removes a record from a name by record name and type
|
||||||
|
pub fn (mut m NameDB) remove_record(domain string, record_name string, record_type RecordType) !Name {
|
||||||
|
// Get the name by domain
|
||||||
|
mut name := m.get_by_domain(domain)!
|
||||||
|
|
||||||
|
// Find and remove the record
|
||||||
|
mut found := false
|
||||||
|
mut new_records := []Record{}
|
||||||
|
|
||||||
|
for record in name.records {
|
||||||
|
if record.name == record_name && record.category == record_type {
|
||||||
|
found = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
new_records << record
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return error('Record with name ${record_name} and type ${record_type} not found in domain ${domain}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the name records
|
||||||
|
name.records = new_records
|
||||||
|
|
||||||
|
// Save the updated name
|
||||||
|
return m.set(name)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_record_text updates the text of a record
|
||||||
|
pub fn (mut m NameDB) update_record_text(domain string, record_name string, record_type RecordType, new_text string) !Name {
|
||||||
|
// Get the name by domain
|
||||||
|
mut name := m.get_by_domain(domain)!
|
||||||
|
|
||||||
|
// Find and update the record
|
||||||
|
mut found := false
|
||||||
|
|
||||||
|
for i, mut record in name.records {
|
||||||
|
if record.name == record_name && record.category == record_type {
|
||||||
|
name.records[i].text = new_text
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return error('Record with name ${record_name} and type ${record_type} not found in domain ${domain}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the updated name
|
||||||
|
return m.set(name)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// add_admin adds an admin to a name
|
||||||
|
pub fn (mut m NameDB) add_admin(domain string, pubkey string) !Name {
|
||||||
|
// Get the name by domain
|
||||||
|
mut name := m.get_by_domain(domain)!
|
||||||
|
|
||||||
|
// Check if admin already exists
|
||||||
|
if pubkey in name.admins {
|
||||||
|
return error('Admin with pubkey ${pubkey} already exists in domain ${domain}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the admin
|
||||||
|
name.admins << pubkey
|
||||||
|
|
||||||
|
// Save the updated name
|
||||||
|
return m.set(name)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove_admin removes an admin from a name
|
||||||
|
pub fn (mut m NameDB) remove_admin(domain string, pubkey string) !Name {
|
||||||
|
// Get the name by domain
|
||||||
|
mut name := m.get_by_domain(domain)!
|
||||||
|
|
||||||
|
// Find and remove the admin
|
||||||
|
mut found := false
|
||||||
|
mut new_admins := []string{}
|
||||||
|
|
||||||
|
for admin in name.admins {
|
||||||
|
if admin == pubkey {
|
||||||
|
found = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
new_admins << admin
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return error('Admin with pubkey ${pubkey} not found in domain ${domain}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the name admins
|
||||||
|
name.admins = new_admins
|
||||||
|
|
||||||
|
// Save the updated name
|
||||||
|
return m.set(name)!
|
||||||
|
}
|
||||||
209
lib/circles/dbs/core/name_db_test.v
Normal file
209
lib/circles/dbs/core/name_db_test.v
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
module core
|
||||||
|
|
||||||
|
import os
|
||||||
|
import rand
|
||||||
|
import freeflowuniverse.herolib.circles.actionprocessor
|
||||||
|
import freeflowuniverse.herolib.circles.models.core
|
||||||
|
|
||||||
|
fn test_name_db() {
|
||||||
|
// Create a temporary directory for testing
|
||||||
|
test_dir := os.join_path(os.temp_dir(), 'hero_name_test_${rand.intn(9000) or { 0 } + 1000}')
|
||||||
|
os.mkdir_all(test_dir) or { panic(err) }
|
||||||
|
defer { os.rmdir_all(test_dir) or {} }
|
||||||
|
|
||||||
|
mut runner := actionprocessor.new(path: test_dir)!
|
||||||
|
|
||||||
|
// Create multiple names for testing
|
||||||
|
mut name1 := runner.names.new()
|
||||||
|
name1.domain = 'example.com'
|
||||||
|
name1.description = 'Example Domain'
|
||||||
|
name1.admins = ['admin1_pubkey']
|
||||||
|
|
||||||
|
mut name2 := runner.names.new()
|
||||||
|
name2.domain = 'test.org'
|
||||||
|
name2.description = 'Test Organization'
|
||||||
|
name2.admins = ['admin2_pubkey']
|
||||||
|
|
||||||
|
mut name3 := runner.names.new()
|
||||||
|
name3.domain = 'herolib.io'
|
||||||
|
name3.description = 'HeroLib Website'
|
||||||
|
name3.admins = ['admin3_pubkey']
|
||||||
|
|
||||||
|
// Create records for testing
|
||||||
|
mut record1 := core.Record{
|
||||||
|
name: 'www'
|
||||||
|
text: 'Web server'
|
||||||
|
category: .a
|
||||||
|
addr: ['192.168.1.1', '192.168.1.2']
|
||||||
|
}
|
||||||
|
|
||||||
|
mut record2 := core.Record{
|
||||||
|
name: 'mail'
|
||||||
|
text: 'Mail server'
|
||||||
|
category: .mx
|
||||||
|
addr: ['192.168.2.1']
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add records to name1
|
||||||
|
name1.records << record1
|
||||||
|
name1.records << record2
|
||||||
|
|
||||||
|
// Add the names
|
||||||
|
println('Adding name 1')
|
||||||
|
name1 = runner.names.set(name1)!
|
||||||
|
|
||||||
|
// Explicitly set different IDs for each name to avoid overwriting
|
||||||
|
name2.id = 1 // Set a different ID for name2
|
||||||
|
println('Adding name 2')
|
||||||
|
name2 = runner.names.set(name2)!
|
||||||
|
|
||||||
|
name3.id = 2 // Set a different ID for name3
|
||||||
|
println('Adding name 3')
|
||||||
|
name3 = runner.names.set(name3)!
|
||||||
|
|
||||||
|
// Test list functionality
|
||||||
|
println('Testing list functionality')
|
||||||
|
|
||||||
|
// Get all names
|
||||||
|
all_names := runner.names.getall()!
|
||||||
|
println('Retrieved ${all_names.len} names')
|
||||||
|
for i, name in all_names {
|
||||||
|
println('Name ${i}: id=${name.id}, domain=${name.domain}')
|
||||||
|
}
|
||||||
|
|
||||||
|
assert all_names.len == 3, 'Expected 3 names, got ${all_names.len}'
|
||||||
|
|
||||||
|
// Verify all names are in the list
|
||||||
|
mut found1 := false
|
||||||
|
mut found2 := false
|
||||||
|
mut found3 := false
|
||||||
|
|
||||||
|
for name in all_names {
|
||||||
|
if name.domain == 'example.com' {
|
||||||
|
found1 = true
|
||||||
|
} else if name.domain == 'test.org' {
|
||||||
|
found2 = true
|
||||||
|
} else if name.domain == 'herolib.io' {
|
||||||
|
found3 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert found1, 'Name 1 not found in list'
|
||||||
|
assert found2, 'Name 2 not found in list'
|
||||||
|
assert found3, 'Name 3 not found in list'
|
||||||
|
|
||||||
|
// Get and verify individual names
|
||||||
|
println('Verifying individual names')
|
||||||
|
retrieved_name1 := runner.names.get_by_domain('example.com')!
|
||||||
|
assert retrieved_name1.domain == name1.domain
|
||||||
|
assert retrieved_name1.description == name1.description
|
||||||
|
assert retrieved_name1.records.len == 2
|
||||||
|
assert retrieved_name1.records[0].name == 'www'
|
||||||
|
assert retrieved_name1.records[0].category == .a
|
||||||
|
assert retrieved_name1.records[1].name == 'mail'
|
||||||
|
assert retrieved_name1.records[1].category == .mx
|
||||||
|
assert retrieved_name1.admins.len == 1
|
||||||
|
assert retrieved_name1.admins[0] == 'admin1_pubkey'
|
||||||
|
|
||||||
|
// Test add_record method
|
||||||
|
println('Testing add_record method')
|
||||||
|
mut record3 := core.Record{
|
||||||
|
name: 'api'
|
||||||
|
text: 'API server'
|
||||||
|
category: .a
|
||||||
|
addr: ['192.168.3.1']
|
||||||
|
}
|
||||||
|
|
||||||
|
runner.names.add_record('test.org', record3)!
|
||||||
|
updated_name2 := runner.names.get_by_domain('test.org')!
|
||||||
|
assert updated_name2.records.len == 1
|
||||||
|
assert updated_name2.records[0].name == 'api'
|
||||||
|
assert updated_name2.records[0].category == .a
|
||||||
|
assert updated_name2.records[0].text == 'API server'
|
||||||
|
|
||||||
|
// Test update_record_text method
|
||||||
|
println('Testing update_record_text method')
|
||||||
|
runner.names.update_record_text('test.org', 'api', .a, 'Updated API server')!
|
||||||
|
text_updated_name2 := runner.names.get_by_domain('test.org')!
|
||||||
|
assert text_updated_name2.records[0].text == 'Updated API server'
|
||||||
|
|
||||||
|
// Test remove_record method
|
||||||
|
println('Testing remove_record method')
|
||||||
|
runner.names.remove_record('example.com', 'mail', .mx)!
|
||||||
|
record_removed_name1 := runner.names.get_by_domain('example.com')!
|
||||||
|
assert record_removed_name1.records.len == 1
|
||||||
|
assert record_removed_name1.records[0].name == 'www'
|
||||||
|
|
||||||
|
// Test add_admin method
|
||||||
|
println('Testing add_admin method')
|
||||||
|
runner.names.add_admin('example.com', 'new_admin_pubkey')!
|
||||||
|
admin_added_name1 := runner.names.get_by_domain('example.com')!
|
||||||
|
assert admin_added_name1.admins.len == 2
|
||||||
|
assert 'new_admin_pubkey' in admin_added_name1.admins
|
||||||
|
|
||||||
|
// Test remove_admin method
|
||||||
|
println('Testing remove_admin method')
|
||||||
|
runner.names.remove_admin('example.com', 'admin1_pubkey')!
|
||||||
|
admin_removed_name1 := runner.names.get_by_domain('example.com')!
|
||||||
|
assert admin_removed_name1.admins.len == 1
|
||||||
|
assert admin_removed_name1.admins[0] == 'new_admin_pubkey'
|
||||||
|
|
||||||
|
// Test get_all_domains method
|
||||||
|
println('Testing get_all_domains method')
|
||||||
|
domains := runner.names.get_all_domains()!
|
||||||
|
assert domains.len == 3
|
||||||
|
assert 'example.com' in domains
|
||||||
|
assert 'test.org' in domains
|
||||||
|
assert 'herolib.io' in domains
|
||||||
|
|
||||||
|
// Test delete functionality
|
||||||
|
println('Testing delete functionality')
|
||||||
|
// Delete name 2
|
||||||
|
runner.names.delete_by_domain('test.org')!
|
||||||
|
|
||||||
|
// Verify deletion with list
|
||||||
|
names_after_delete := runner.names.getall()!
|
||||||
|
assert names_after_delete.len == 2, 'Expected 2 names after deletion, got ${names_after_delete.len}'
|
||||||
|
|
||||||
|
// Verify the remaining names
|
||||||
|
mut found_after_delete1 := false
|
||||||
|
mut found_after_delete2 := false
|
||||||
|
mut found_after_delete3 := false
|
||||||
|
|
||||||
|
for name in names_after_delete {
|
||||||
|
if name.domain == 'example.com' {
|
||||||
|
found_after_delete1 = true
|
||||||
|
} else if name.domain == 'test.org' {
|
||||||
|
found_after_delete2 = true
|
||||||
|
} else if name.domain == 'herolib.io' {
|
||||||
|
found_after_delete3 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert found_after_delete1, 'Name 1 not found after deletion'
|
||||||
|
assert !found_after_delete2, 'Name 2 found after deletion (should be deleted)'
|
||||||
|
assert found_after_delete3, 'Name 3 not found after deletion'
|
||||||
|
|
||||||
|
// Delete another name
|
||||||
|
println('Deleting another name')
|
||||||
|
runner.names.delete_by_domain('herolib.io')!
|
||||||
|
|
||||||
|
// Verify only one name remains
|
||||||
|
names_after_second_delete := runner.names.getall()!
|
||||||
|
assert names_after_second_delete.len == 1, 'Expected 1 name after second deletion, got ${names_after_second_delete.len}'
|
||||||
|
assert names_after_second_delete[0].domain == 'example.com', 'Remaining name should be example.com'
|
||||||
|
|
||||||
|
// Delete the last name
|
||||||
|
println('Deleting last name')
|
||||||
|
runner.names.delete_by_domain('example.com')!
|
||||||
|
|
||||||
|
// Verify no names remain
|
||||||
|
names_after_all_deleted := runner.names.getall() or {
|
||||||
|
// This is expected to fail with 'No names found' error
|
||||||
|
assert err.msg().contains('No index keys defined for this type') || err.msg().contains('No names found')
|
||||||
|
[]core.Name{cap: 0}
|
||||||
|
}
|
||||||
|
assert names_after_all_deleted.len == 0, 'Expected 0 names after all deletions, got ${names_after_all_deleted.len}'
|
||||||
|
|
||||||
|
println('All tests passed successfully')
|
||||||
|
}
|
||||||
@@ -74,7 +74,7 @@ pub fn (c Circle) dumps() ![]u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// loads deserializes binary data into a Circle struct
|
// loads deserializes binary data into a Circle struct
|
||||||
pub fn Circle.loads(data []u8) !Circle {
|
pub fn circle_loads(data []u8) !Circle {
|
||||||
mut d := encoder.decoder_new(data)
|
mut d := encoder.decoder_new(data)
|
||||||
mut circle := Circle{}
|
mut circle := Circle{}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
module models
|
module models
|
||||||
|
|
||||||
import freeflowuniverse.herolib.circles.models.core { agent_loads, Agent }
|
import freeflowuniverse.herolib.circles.models.core { agent_loads, Agent, circle_loads, Circle, name_loads, Name }
|
||||||
|
|
||||||
pub struct DBHandler[T] {
|
pub struct DBHandler[T] {
|
||||||
pub mut:
|
pub mut:
|
||||||
@@ -39,18 +39,24 @@ pub fn (mut m DBHandler[T]) get(id u32) !T {
|
|||||||
item_data := m.session_state.dbs.db_data_core.get(id) or {
|
item_data := m.session_state.dbs.db_data_core.get(id) or {
|
||||||
return error('Item data not found for ID ${id}')
|
return error('Item data not found for ID ${id}')
|
||||||
}
|
}
|
||||||
mut o:= T{}
|
|
||||||
match o {
|
//THIS IS SUPER ANNOYING AND NOT NICE
|
||||||
Agent {
|
$if T is Agent {
|
||||||
o=agent_loads(item_data)!
|
mut o:= agent_loads(item_data)!
|
||||||
}else{
|
o.id = id
|
||||||
return panic('Not implemented object')
|
return o
|
||||||
}
|
} $else $if T is Circle {
|
||||||
}
|
mut o:= circle_loads(item_data)!
|
||||||
|
o.id = id
|
||||||
// o.loads(item_data)!
|
return o
|
||||||
o.id = id
|
} $else $if T is Name {
|
||||||
return o
|
mut o:= name_loads(item_data)!
|
||||||
|
o.id = id
|
||||||
|
return o
|
||||||
|
} $else {
|
||||||
|
return error('Unsupported type for deserialization')
|
||||||
|
}
|
||||||
|
panic("bug")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut m DBHandler[T]) exists(id u32) !bool {
|
pub fn (mut m DBHandler[T]) exists(id u32) !bool {
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
module core
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.data.ourtime
|
|
||||||
import freeflowuniverse.herolib.circles.models { DBHandler, SessionState }
|
|
||||||
import freeflowuniverse.herolib.circles.models.core { Agent, AgentService, AgentServiceAction, AgentState }
|
|
||||||
|
|
||||||
|
|
||||||
@[heap]
|
|
||||||
pub struct AgentDB {
|
|
||||||
pub mut:
|
|
||||||
db models.DBHandler[Agent]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_agentdb(session_state SessionState) !AgentDB {
|
|
||||||
return AgentDB{
|
|
||||||
db:models.new_dbhandler[Agent]('agent', session_state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut m AgentDB) new() Agent {
|
|
||||||
return Agent{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set adds or updates an agent
|
|
||||||
pub fn (mut m AgentDB) set(agent Agent) !Agent {
|
|
||||||
return m.db.set(agent)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// get retrieves an agent by its ID
|
|
||||||
pub fn (mut m AgentDB) get(id u32) !Agent {
|
|
||||||
return m.db.get(id)!
|
|
||||||
}
|
|
||||||
// list returns all agent IDs
|
|
||||||
pub fn (mut m AgentDB) list() ![]u32 {
|
|
||||||
return m.db.list()!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut m AgentDB) getall() ![]Agent {
|
|
||||||
return m.db.getall()!
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete removes an agent by its ID
|
|
||||||
pub fn (mut m AgentDB) delete(id u32) ! {
|
|
||||||
m.db.delete(id)!
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////CUSTOM METHODS//////////////////////////////////
|
|
||||||
|
|
||||||
// get_by_pubkey retrieves an agent by its public key
|
|
||||||
pub fn (mut m AgentDB) get_by_pubkey(pubkey string) !Agent {
|
|
||||||
return m.db.get_by_key('pubkey', pubkey)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete_by_pubkey removes an agent by its public key
|
|
||||||
pub fn (mut m AgentDB) delete_by_pubkey(pubkey string) ! {
|
|
||||||
// Get the agent by pubkey
|
|
||||||
agent := m.get_by_pubkey(pubkey) or {
|
|
||||||
// Agent not found, nothing to delete
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the agent by ID
|
|
||||||
m.delete(agent.id)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// update_status updates just the status of an agent
|
|
||||||
pub fn (mut m AgentDB) update_status(pubkey string, status AgentState) !Agent {
|
|
||||||
// Get the agent by pubkey
|
|
||||||
mut agent := m.get_by_pubkey(pubkey)!
|
|
||||||
|
|
||||||
// Update the status
|
|
||||||
agent.status.status = status
|
|
||||||
agent.status.timestamp_last = ourtime.now()
|
|
||||||
|
|
||||||
// Save the updated agent
|
|
||||||
return m.set(agent)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// get_all_agent_pubkeys returns all agent pubkeys
|
|
||||||
pub fn (mut m AgentDB) get_all_agent_pubkeys() ![]string {
|
|
||||||
// Get all agent IDs
|
|
||||||
agent_ids := m.list()!
|
|
||||||
|
|
||||||
// Get pubkeys for all agents
|
|
||||||
mut pubkeys := []string{}
|
|
||||||
for id in agent_ids {
|
|
||||||
agent := m.get(id) or { continue }
|
|
||||||
pubkeys << agent.pubkey
|
|
||||||
}
|
|
||||||
|
|
||||||
return pubkeys
|
|
||||||
}
|
|
||||||
|
|
||||||
// get_by_service returns all agents that provide a specific service
|
|
||||||
pub fn (mut m AgentDB) get_by_service(actor string, action string) ![]Agent {
|
|
||||||
mut matching_agents := []Agent{}
|
|
||||||
|
|
||||||
// Get all agent IDs
|
|
||||||
agent_ids := m.list()!
|
|
||||||
|
|
||||||
// Filter agents that provide the specified service
|
|
||||||
for id in agent_ids {
|
|
||||||
// Get the agent by ID
|
|
||||||
agent := m.get(id) or { continue }
|
|
||||||
|
|
||||||
// Check if agent provides the specified service
|
|
||||||
for service in agent.services {
|
|
||||||
if service.actor == actor {
|
|
||||||
for service_action in service.actions {
|
|
||||||
if service_action.action == action {
|
|
||||||
matching_agents << agent
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return matching_agents
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
module core
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.data.ourdb
|
|
||||||
import freeflowuniverse.herolib.data.radixtree
|
|
||||||
import freeflowuniverse.herolib.core.playbook
|
|
||||||
import freeflowuniverse.herolib.circles.models
|
|
||||||
|
|
||||||
@[heap]
|
|
||||||
pub struct CircleDB {
|
|
||||||
pub mut:
|
|
||||||
db models.DBHandler[Circle]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_circledb(session_state models.SessionState) !CircleDB {
|
|
||||||
return CircleDB{
|
|
||||||
db: models.new_dbhandler[Circle]('circle', session_state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut m CircleDB) new() Circle {
|
|
||||||
return Circle{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set adds or updates a circle
|
|
||||||
pub fn (mut m CircleDB) set(circle Circle) !Circle {
|
|
||||||
return m.db.set(circle)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// get retrieves a circle by its ID
|
|
||||||
pub fn (mut m CircleDB) get(id u32) !Circle {
|
|
||||||
return m.db.get(id)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// list returns all circle IDs
|
|
||||||
pub fn (mut m CircleDB) list() ![]u32 {
|
|
||||||
return m.db.list()!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut m CircleDB) getall() ![]Circle {
|
|
||||||
return m.db.getall()!
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete removes a circle by its ID
|
|
||||||
pub fn (mut m CircleDB) delete(id u32) ! {
|
|
||||||
m.db.delete(id)!
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////CUSTOM METHODS//////////////////////////////////
|
|
||||||
|
|
||||||
// get_by_name retrieves a circle by its name
|
|
||||||
pub fn (mut m CircleDB) get_by_name(name string) !Circle {
|
|
||||||
return m.db.get_by_key('name', name)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete_by_name removes a circle by its name
|
|
||||||
pub fn (mut m CircleDB) delete_by_name(name string) ! {
|
|
||||||
// Get the circle by name
|
|
||||||
circle := m.get_by_name(name) or {
|
|
||||||
// Circle not found, nothing to delete
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the circle by ID
|
|
||||||
m.delete(circle.id)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// add_member adds a member to a circle
|
|
||||||
pub fn (mut m CircleDB) add_member(circle_id u32, member Member) !Circle {
|
|
||||||
// Get the circle by ID
|
|
||||||
mut circle := m.get(circle_id)!
|
|
||||||
|
|
||||||
// Check if member with the same pubkey already exists
|
|
||||||
if member.pubkeys.len == 0 {
|
|
||||||
return error('Member must have at least one pubkey')
|
|
||||||
}
|
|
||||||
|
|
||||||
for existing_member in circle.members {
|
|
||||||
for existing_pubkey in existing_member.pubkeys {
|
|
||||||
for pubkey in member.pubkeys {
|
|
||||||
if existing_pubkey == pubkey {
|
|
||||||
return error('Member with pubkey ${pubkey} already exists in circle ${circle.name}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the member to the circle
|
|
||||||
circle.members << member
|
|
||||||
|
|
||||||
// Save the updated circle
|
|
||||||
return m.set(circle)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove_member removes a member from a circle by pubkey
|
|
||||||
pub fn (mut m CircleDB) remove_member(circle_id u32, pubkey string) !Circle {
|
|
||||||
// Get the circle by ID
|
|
||||||
mut circle := m.get(circle_id)!
|
|
||||||
|
|
||||||
// Find and remove the member with the specified pubkey
|
|
||||||
mut found := false
|
|
||||||
mut new_members := []Member{}
|
|
||||||
|
|
||||||
for member in circle.members {
|
|
||||||
mut has_pubkey := false
|
|
||||||
for p in member.pubkeys {
|
|
||||||
if p == pubkey {
|
|
||||||
has_pubkey = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !has_pubkey {
|
|
||||||
new_members << member
|
|
||||||
} else {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return error('Member with pubkey ${pubkey} not found in circle ${circle.name}')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the circle's members
|
|
||||||
circle.members = new_members
|
|
||||||
|
|
||||||
// Save the updated circle
|
|
||||||
return m.set(circle)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// update_member_role updates the role of a member in a circle
|
|
||||||
pub fn (mut m CircleDB) update_member_role(circle_id u32, pubkey string, role Role) !Circle {
|
|
||||||
// Get the circle by ID
|
|
||||||
mut circle := m.get(circle_id)!
|
|
||||||
|
|
||||||
// Find and update the member with the specified pubkey
|
|
||||||
mut found := false
|
|
||||||
|
|
||||||
for i, mut member in circle.members {
|
|
||||||
for p in member.pubkeys {
|
|
||||||
if p == pubkey {
|
|
||||||
circle.members[i].role = role
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return error('Member with pubkey ${pubkey} not found in circle ${circle.name}')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the updated circle
|
|
||||||
return m.set(circle)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// get_members returns all members of a circle
|
|
||||||
pub fn (mut m CircleDB) get_members(circle_id u32) ![]Member {
|
|
||||||
// Get the circle by ID
|
|
||||||
circle := m.get(circle_id)!
|
|
||||||
|
|
||||||
return circle.members
|
|
||||||
}
|
|
||||||
|
|
||||||
// get_members_by_role returns all members of a circle with a specific role
|
|
||||||
pub fn (mut m CircleDB) get_members_by_role(circle_id u32, role Role) ![]Member {
|
|
||||||
// Get the circle by ID
|
|
||||||
circle := m.get(circle_id)!
|
|
||||||
|
|
||||||
// Filter members by role
|
|
||||||
mut members_with_role := []Member{}
|
|
||||||
|
|
||||||
for member in circle.members {
|
|
||||||
if member.role == role {
|
|
||||||
members_with_role << member
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return members_with_role
|
|
||||||
}
|
|
||||||
|
|
||||||
// play processes heroscript commands for circles
|
|
||||||
pub fn play_circle(mut cm CircleDB, mut plbook playbook.PlayBook) ! {
|
|
||||||
// Find all actions that start with 'circle.'
|
|
||||||
circle_actions := plbook.actions_find(actor: 'circle')!
|
|
||||||
if circle_actions.len == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process circle.create actions
|
|
||||||
mut create_actions := plbook.actions_find(actor: 'circle', name: 'create')!
|
|
||||||
for mut action in create_actions {
|
|
||||||
mut p := action.params
|
|
||||||
|
|
||||||
// Create a new circle
|
|
||||||
mut circle := cm.new()
|
|
||||||
circle.name = p.get('name')!
|
|
||||||
circle.description = p.get_default('description', '')!
|
|
||||||
|
|
||||||
// Save the circle
|
|
||||||
circle = cm.set(circle)!
|
|
||||||
|
|
||||||
// Mark the action as done
|
|
||||||
action.done = true
|
|
||||||
|
|
||||||
// Return the created circle as a result
|
|
||||||
action.result.set('id', circle.id.str())
|
|
||||||
action.result.set('name', circle.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process circle.add_member actions
|
|
||||||
mut add_member_actions := plbook.actions_find(actor: 'circle', name: 'add_member')!
|
|
||||||
for mut action in add_member_actions {
|
|
||||||
mut p := action.params
|
|
||||||
|
|
||||||
// Get circle name
|
|
||||||
circle_name := p.get('circle')!
|
|
||||||
|
|
||||||
// Find the circle by name
|
|
||||||
mut circle := cm.get_by_name(circle_name) or {
|
|
||||||
action.result.set('error', 'Circle with name ${circle_name} not found')
|
|
||||||
action.done = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new member
|
|
||||||
mut member := Member{
|
|
||||||
name: p.get('name')!
|
|
||||||
description: p.get_default('description', '')!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get pubkeys if provided
|
|
||||||
if p.exists('pubkey') {
|
|
||||||
member.pubkeys << p.get('pubkey')!
|
|
||||||
} else if p.exists('pubkeys') {
|
|
||||||
member.pubkeys = p.get_list('pubkeys')!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get emails if provided
|
|
||||||
if p.exists('email') {
|
|
||||||
member.emails << p.get('email')!
|
|
||||||
} else if p.exists('emails') {
|
|
||||||
member.emails = p.get_list('emails')!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get role if provided
|
|
||||||
role_str := p.get_default('role', 'member')!
|
|
||||||
member.role = match role_str.to_lower() {
|
|
||||||
'admin' { Role.admin }
|
|
||||||
'stakeholder' { Role.stakeholder }
|
|
||||||
'member' { Role.member }
|
|
||||||
'contributor' { Role.contributor }
|
|
||||||
'guest' { Role.guest }
|
|
||||||
else { Role.member }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the member to the circle
|
|
||||||
circle = cm.add_member(circle.id, member) or {
|
|
||||||
action.result.set('error', err.str())
|
|
||||||
action.done = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the action as done
|
|
||||||
action.done = true
|
|
||||||
|
|
||||||
// Return the member info as a result
|
|
||||||
action.result.set('circle_id', circle.id.str())
|
|
||||||
action.result.set('member_name', member.name)
|
|
||||||
action.result.set('role', role_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
module core
|
|
||||||
|
|
||||||
import os
|
|
||||||
import rand
|
|
||||||
|
|
||||||
fn test_circle_db() {
|
|
||||||
// Create a temporary directory for testing
|
|
||||||
test_dir := os.join_path(os.temp_dir(), 'hero_circle_test_${rand.intn(9000) or { 0 } + 1000}')
|
|
||||||
os.mkdir_all(test_dir) or { panic(err) }
|
|
||||||
defer { os.rmdir_all(test_dir) or {} }
|
|
||||||
|
|
||||||
mut runner := new(path: test_dir)!
|
|
||||||
|
|
||||||
// Create multiple circles for testing
|
|
||||||
mut circle1 := runner.circles.new()
|
|
||||||
circle1.name = 'Development Team'
|
|
||||||
circle1.description = 'Software development team'
|
|
||||||
|
|
||||||
mut circle2 := runner.circles.new()
|
|
||||||
circle2.name = 'Marketing Team'
|
|
||||||
circle2.description = 'Marketing and communications team'
|
|
||||||
|
|
||||||
mut circle3 := runner.circles.new()
|
|
||||||
circle3.name = 'Executive Team'
|
|
||||||
circle3.description = 'Executive leadership team'
|
|
||||||
|
|
||||||
// Add the circles
|
|
||||||
println('Adding circle 1')
|
|
||||||
circle1 = runner.circles.set(circle1)!
|
|
||||||
|
|
||||||
// Explicitly set different IDs for each circle to avoid overwriting
|
|
||||||
circle2.id = 1 // Set a different ID for circle2
|
|
||||||
println('Adding circle 2')
|
|
||||||
circle2 = runner.circles.set(circle2)!
|
|
||||||
|
|
||||||
circle3.id = 2 // Set a different ID for circle3
|
|
||||||
println('Adding circle 3')
|
|
||||||
circle3 = runner.circles.set(circle3)!
|
|
||||||
|
|
||||||
// Test list functionality
|
|
||||||
println('Testing list functionality')
|
|
||||||
|
|
||||||
// Debug: Print the circle IDs in the list
|
|
||||||
circle_ids := runner.circles.list()!
|
|
||||||
println('Circle IDs in list: ${circle_ids}')
|
|
||||||
|
|
||||||
// Get all circles
|
|
||||||
all_circles := runner.circles.getall()!
|
|
||||||
println('Retrieved ${all_circles.len} circles')
|
|
||||||
for i, circle in all_circles {
|
|
||||||
println('Circle ${i}: id=${circle.id}, name=${circle.name}')
|
|
||||||
}
|
|
||||||
|
|
||||||
assert all_circles.len == 3, 'Expected 3 circles, got ${all_circles.len}'
|
|
||||||
|
|
||||||
// Verify all circles are in the list
|
|
||||||
mut found1 := false
|
|
||||||
mut found2 := false
|
|
||||||
mut found3 := false
|
|
||||||
|
|
||||||
for circle in all_circles {
|
|
||||||
if circle.name == 'Development Team' {
|
|
||||||
found1 = true
|
|
||||||
} else if circle.name == 'Marketing Team' {
|
|
||||||
found2 = true
|
|
||||||
} else if circle.name == 'Executive Team' {
|
|
||||||
found3 = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert found1, 'Circle 1 not found in list'
|
|
||||||
assert found2, 'Circle 2 not found in list'
|
|
||||||
assert found3, 'Circle 3 not found in list'
|
|
||||||
|
|
||||||
// Get and verify individual circles
|
|
||||||
println('Verifying individual circles')
|
|
||||||
retrieved_circle1 := runner.circles.get_by_name('Development Team')!
|
|
||||||
assert retrieved_circle1.name == circle1.name
|
|
||||||
assert retrieved_circle1.description == circle1.description
|
|
||||||
assert retrieved_circle1.members.len == 0
|
|
||||||
|
|
||||||
// Test adding members to a circle
|
|
||||||
println('Testing adding members to a circle')
|
|
||||||
|
|
||||||
// Create members
|
|
||||||
mut member1 := Member{
|
|
||||||
pubkeys: ['dev-lead-pubkey']
|
|
||||||
name: 'Development Lead'
|
|
||||||
description: 'Lead developer'
|
|
||||||
role: .admin
|
|
||||||
emails: ['dev.lead@example.com']
|
|
||||||
}
|
|
||||||
|
|
||||||
mut member2 := Member{
|
|
||||||
pubkeys: ['dev-member-pubkey']
|
|
||||||
name: 'Developer'
|
|
||||||
description: 'Team developer'
|
|
||||||
role: .member
|
|
||||||
emails: ['developer@example.com']
|
|
||||||
}
|
|
||||||
|
|
||||||
mut member3 := Member{
|
|
||||||
pubkeys: ['contributor-pubkey']
|
|
||||||
name: 'Contributor'
|
|
||||||
description: 'External contributor'
|
|
||||||
role: .contributor
|
|
||||||
emails: ['contributor@example.com']
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add members to circle 1
|
|
||||||
runner.circles.add_member(circle1.id, member1)!
|
|
||||||
runner.circles.add_member(circle1.id, member2)!
|
|
||||||
runner.circles.add_member(circle1.id, member3)!
|
|
||||||
|
|
||||||
// Verify members were added
|
|
||||||
updated_circle1 := runner.circles.get(circle1.id)!
|
|
||||||
assert updated_circle1.members.len == 3, 'Expected 3 members, got ${updated_circle1.members.len}'
|
|
||||||
|
|
||||||
// Test get_members functionality
|
|
||||||
println('Testing get_members functionality')
|
|
||||||
members := runner.circles.get_members(circle1.id)!
|
|
||||||
assert members.len == 3, 'Expected 3 members, got ${members.len}'
|
|
||||||
|
|
||||||
// Test get_members_by_role functionality
|
|
||||||
println('Testing get_members_by_role functionality')
|
|
||||||
admin_members := runner.circles.get_members_by_role(circle1.id, .admin)!
|
|
||||||
assert admin_members.len == 1, 'Expected 1 admin member, got ${admin_members.len}'
|
|
||||||
assert admin_members[0].pubkeys.len > 0
|
|
||||||
assert admin_members[0].pubkeys[0] == 'dev-lead-pubkey'
|
|
||||||
|
|
||||||
regular_members := runner.circles.get_members_by_role(circle1.id, .member)!
|
|
||||||
assert regular_members.len == 1, 'Expected 1 regular member, got ${regular_members.len}'
|
|
||||||
assert regular_members[0].pubkeys.len > 0
|
|
||||||
assert regular_members[0].pubkeys[0] == 'dev-member-pubkey'
|
|
||||||
|
|
||||||
contributor_members := runner.circles.get_members_by_role(circle1.id, .contributor)!
|
|
||||||
assert contributor_members.len == 1, 'Expected 1 contributor member, got ${contributor_members.len}'
|
|
||||||
assert contributor_members[0].pubkeys.len > 0
|
|
||||||
assert contributor_members[0].pubkeys[0] == 'contributor-pubkey'
|
|
||||||
|
|
||||||
// Test update_member_role functionality
|
|
||||||
println('Testing update_member_role functionality')
|
|
||||||
runner.circles.update_member_role(circle1.id, 'dev-member-pubkey', .stakeholder)!
|
|
||||||
|
|
||||||
// Verify role was updated
|
|
||||||
updated_circle_after_role_change := runner.circles.get(circle1.id)!
|
|
||||||
mut found_stakeholder := false
|
|
||||||
|
|
||||||
for member in updated_circle_after_role_change.members {
|
|
||||||
if member.pubkeys.len > 0 && member.pubkeys[0] == 'dev-member-pubkey' {
|
|
||||||
assert member.role == .stakeholder, 'Expected role to be stakeholder, got ${member.role}'
|
|
||||||
found_stakeholder = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert found_stakeholder, 'Stakeholder member not found after role update'
|
|
||||||
|
|
||||||
// Test remove_member functionality
|
|
||||||
println('Testing remove_member functionality')
|
|
||||||
runner.circles.remove_member(circle1.id, 'contributor-pubkey')!
|
|
||||||
|
|
||||||
// Verify member was removed
|
|
||||||
updated_circle_after_removal := runner.circles.get(circle1.id)!
|
|
||||||
assert updated_circle_after_removal.members.len == 2, 'Expected 2 members after removal, got ${updated_circle_after_removal.members.len}'
|
|
||||||
|
|
||||||
mut found_contributor := false
|
|
||||||
for member in updated_circle_after_removal.members {
|
|
||||||
if member.pubkeys.len > 0 && member.pubkeys[0] == 'contributor-pubkey' {
|
|
||||||
found_contributor = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert !found_contributor, 'Contributor still found after removal'
|
|
||||||
|
|
||||||
// Test delete_by_name functionality
|
|
||||||
println('Testing delete_by_name functionality')
|
|
||||||
runner.circles.delete_by_name('Marketing Team')!
|
|
||||||
|
|
||||||
// Verify deletion
|
|
||||||
circles_after_delete := runner.circles.getall()!
|
|
||||||
assert circles_after_delete.len == 2, 'Expected 2 circles after deletion, got ${circles_after_delete.len}'
|
|
||||||
|
|
||||||
mut found_marketing := false
|
|
||||||
for circle in circles_after_delete {
|
|
||||||
if circle.name == 'Marketing Team' {
|
|
||||||
found_marketing = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert !found_marketing, 'Marketing Team still found after deletion'
|
|
||||||
|
|
||||||
// Delete remaining circles
|
|
||||||
println('Deleting remaining circles')
|
|
||||||
runner.circles.delete_by_name('Development Team')!
|
|
||||||
runner.circles.delete_by_name('Executive Team')!
|
|
||||||
|
|
||||||
// Verify all circles are deleted
|
|
||||||
circles_after_all_deleted := runner.circles.getall() or {
|
|
||||||
// This is expected to fail with 'No circles found' error
|
|
||||||
assert err.msg().contains('not found'), 'Expected error message to contain "not found"'
|
|
||||||
[]Circle{}
|
|
||||||
}
|
|
||||||
assert circles_after_all_deleted.len == 0, 'Expected 0 circles after all deletions, got ${circles_after_all_deleted.len}'
|
|
||||||
|
|
||||||
println('All circle manager tests passed successfully')
|
|
||||||
}
|
|
||||||
@@ -1,356 +0,0 @@
|
|||||||
module core
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.data.ourdb
|
|
||||||
import freeflowuniverse.herolib.data.radixtree
|
|
||||||
import freeflowuniverse.herolib.core.playbook
|
|
||||||
import freeflowuniverse.herolib.circles.models
|
|
||||||
|
|
||||||
@[heap]
|
|
||||||
pub struct NameDB {
|
|
||||||
pub mut:
|
|
||||||
db models.DBHandler[Name]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_namedb(session_state models.SessionState) !NameDB {
|
|
||||||
return NameDB{
|
|
||||||
db: models.new_dbhandler[Name]('name', session_state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut m NameDB) new() Name {
|
|
||||||
return Name{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set adds or updates a name
|
|
||||||
pub fn (mut m NameDB) set(name Name) !Name {
|
|
||||||
return m.db.set(name)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// get retrieves a name by its ID
|
|
||||||
pub fn (mut m NameDB) get(id u32) !Name {
|
|
||||||
return m.db.get(id)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// list returns all name IDs
|
|
||||||
pub fn (mut m NameDB) list() ![]u32 {
|
|
||||||
return m.db.list()!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut m NameDB) getall() ![]Name {
|
|
||||||
return m.db.getall()!
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete removes a name by its ID
|
|
||||||
pub fn (mut m NameDB) delete(id u32) ! {
|
|
||||||
m.db.delete(id)!
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////CUSTOM METHODS//////////////////////////////////
|
|
||||||
|
|
||||||
// get_by_domain retrieves a name by its domain
|
|
||||||
pub fn (mut m NameDB) get_by_domain(domain string) !Name {
|
|
||||||
return m.db.get_by_key('domain', domain)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete_by_domain removes a name by its domain
|
|
||||||
pub fn (mut m NameDB) delete_by_domain(domain string) ! {
|
|
||||||
// Get the name by domain
|
|
||||||
name := m.get_by_domain(domain) or {
|
|
||||||
// Name not found, nothing to delete
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the name by ID
|
|
||||||
m.delete(name.id)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// add_record adds a record to a name
|
|
||||||
pub fn (mut m NameDB) add_record(name_id u32, record Record) !Name {
|
|
||||||
// Get the name by ID
|
|
||||||
mut name := m.get(name_id)!
|
|
||||||
|
|
||||||
// Check if record with the same name and category already exists
|
|
||||||
for existing_record in name.records {
|
|
||||||
if existing_record.name == record.name && existing_record.category == record.category {
|
|
||||||
return error('Record with name ${record.name} and category ${record.category} already exists in domain ${name.domain}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the record to the name
|
|
||||||
name.records << record
|
|
||||||
|
|
||||||
// Save the updated name
|
|
||||||
return m.set(name)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove_record removes a record from a name by name and category
|
|
||||||
pub fn (mut m NameDB) remove_record(name_id u32, record_name string, category RecordType) !Name {
|
|
||||||
// Get the name by ID
|
|
||||||
mut name := m.get(name_id)!
|
|
||||||
|
|
||||||
// Find and remove the record with the specified name and category
|
|
||||||
mut found := false
|
|
||||||
mut new_records := []Record{}
|
|
||||||
|
|
||||||
for record in name.records {
|
|
||||||
if record.name != record_name || record.category != category {
|
|
||||||
new_records << record
|
|
||||||
} else {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return error('Record with name ${record_name} and category ${category} not found in domain ${name.domain}')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the name's records
|
|
||||||
name.records = new_records
|
|
||||||
|
|
||||||
// Save the updated name
|
|
||||||
return m.set(name)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// update_record updates a record in a name
|
|
||||||
pub fn (mut m NameDB) update_record(name_id u32, record_name string, category RecordType, new_record Record) !Name {
|
|
||||||
// Get the name by ID
|
|
||||||
mut name := m.get(name_id)!
|
|
||||||
|
|
||||||
// Find and update the record with the specified name and category
|
|
||||||
mut found := false
|
|
||||||
|
|
||||||
for i, mut record in name.records {
|
|
||||||
if record.name == record_name && record.category == category {
|
|
||||||
// If the new record has a different name or category, check for conflicts
|
|
||||||
if (new_record.name != record_name || new_record.category != category) {
|
|
||||||
// Check for conflicts with existing records
|
|
||||||
for existing_record in name.records {
|
|
||||||
if existing_record.name == new_record.name && existing_record.category == new_record.category {
|
|
||||||
return error('Cannot update record: A record with name ${new_record.name} and category ${new_record.category} already exists')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
name.records[i] = new_record
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return error('Record with name ${record_name} and category ${category} not found in domain ${name.domain}')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the updated name
|
|
||||||
return m.set(name)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// get_records returns all records of a name
|
|
||||||
pub fn (mut m NameDB) get_records(name_id u32) ![]Record {
|
|
||||||
// Get the name by ID
|
|
||||||
name := m.get(name_id)!
|
|
||||||
|
|
||||||
return name.records
|
|
||||||
}
|
|
||||||
|
|
||||||
// get_records_by_category returns all records of a name with a specific category
|
|
||||||
pub fn (mut m NameDB) get_records_by_category(name_id u32, category RecordType) ![]Record {
|
|
||||||
// Get the name by ID
|
|
||||||
name := m.get(name_id)!
|
|
||||||
|
|
||||||
// Filter records by category
|
|
||||||
mut records_with_category := []Record{}
|
|
||||||
|
|
||||||
for record in name.records {
|
|
||||||
if record.category == category {
|
|
||||||
records_with_category << record
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return records_with_category
|
|
||||||
}
|
|
||||||
|
|
||||||
// add_admin adds an admin to a name
|
|
||||||
pub fn (mut m NameDB) add_admin(name_id u32, pubkey string) !Name {
|
|
||||||
// Get the name by ID
|
|
||||||
mut name := m.get(name_id)!
|
|
||||||
|
|
||||||
// Check if admin already exists
|
|
||||||
for admin in name.admins {
|
|
||||||
if admin == pubkey {
|
|
||||||
return error('Admin with pubkey ${pubkey} already exists in domain ${name.domain}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the admin to the name
|
|
||||||
name.admins << pubkey
|
|
||||||
|
|
||||||
// Save the updated name
|
|
||||||
return m.set(name)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove_admin removes an admin from a name
|
|
||||||
pub fn (mut m NameDB) remove_admin(name_id u32, pubkey string) !Name {
|
|
||||||
// Get the name by ID
|
|
||||||
mut name := m.get(name_id)!
|
|
||||||
|
|
||||||
// Find and remove the admin with the specified pubkey
|
|
||||||
mut found := false
|
|
||||||
mut new_admins := []string{}
|
|
||||||
|
|
||||||
for admin in name.admins {
|
|
||||||
if admin != pubkey {
|
|
||||||
new_admins << admin
|
|
||||||
} else {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return error('Admin with pubkey ${pubkey} not found in domain ${name.domain}')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure there's at least one admin left
|
|
||||||
if new_admins.len == 0 {
|
|
||||||
return error('Cannot remove the last admin from domain ${name.domain}')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the name's admins
|
|
||||||
name.admins = new_admins
|
|
||||||
|
|
||||||
// Save the updated name
|
|
||||||
return m.set(name)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// play processes heroscript commands for names
|
|
||||||
pub fn (mut m NameDB) play(mut plbook playbook.PlayBook) ! {
|
|
||||||
// Find all actions that start with 'name.'
|
|
||||||
name_actions := plbook.actions_find(actor: 'name')!
|
|
||||||
if name_actions.len == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process name.create actions
|
|
||||||
mut create_actions := plbook.actions_find(actor: 'name', name: 'create')!
|
|
||||||
for mut action in create_actions {
|
|
||||||
mut p := action.params
|
|
||||||
|
|
||||||
// Create a new name
|
|
||||||
mut name := m.new()
|
|
||||||
name.domain = p.get('domain')!
|
|
||||||
name.description = p.get_default('description', '')!
|
|
||||||
|
|
||||||
// Add admin if provided
|
|
||||||
if p.exists('admin') {
|
|
||||||
name.admins << p.get('admin')!
|
|
||||||
} else if p.exists('admins') {
|
|
||||||
name.admins = p.get_list('admins')!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the name
|
|
||||||
name = m.set(name)!
|
|
||||||
|
|
||||||
// Mark the action as done
|
|
||||||
action.done = true
|
|
||||||
|
|
||||||
// Return the created name as a result
|
|
||||||
action.result.set('id', name.id.str())
|
|
||||||
action.result.set('domain', name.domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process name.add_record actions
|
|
||||||
mut add_record_actions := plbook.actions_find(actor: 'name', name: 'add_record')!
|
|
||||||
for mut action in add_record_actions {
|
|
||||||
mut p := action.params
|
|
||||||
|
|
||||||
// Get domain name
|
|
||||||
domain := p.get('domain')!
|
|
||||||
|
|
||||||
// Find the name by domain
|
|
||||||
mut name := m.get_by_domain(domain) or {
|
|
||||||
action.result.set('error', 'Domain ${domain} not found')
|
|
||||||
action.done = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new record
|
|
||||||
mut record := Record{
|
|
||||||
name: p.get('name')!
|
|
||||||
text: p.get_default('text', '')!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get record type
|
|
||||||
type_str := p.get('type')!
|
|
||||||
record.category = match type_str.to_lower() {
|
|
||||||
'a' { RecordType.a }
|
|
||||||
'aaaa' { RecordType.aaaa }
|
|
||||||
'cname' { RecordType.cname }
|
|
||||||
'mx' { RecordType.mx }
|
|
||||||
'ns' { RecordType.ns }
|
|
||||||
'ptr' { RecordType.ptr }
|
|
||||||
'soa' { RecordType.soa }
|
|
||||||
'srv' { RecordType.srv }
|
|
||||||
'txt' { RecordType.txt }
|
|
||||||
else {
|
|
||||||
action.result.set('error', 'Invalid record type: ${type_str}')
|
|
||||||
action.done = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get addresses
|
|
||||||
if p.exists('addr') {
|
|
||||||
record.addr << p.get('addr')!
|
|
||||||
} else if p.exists('addrs') {
|
|
||||||
record.addr = p.get_list('addrs')!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the record to the name
|
|
||||||
name = m.add_record(name.id, record) or {
|
|
||||||
action.result.set('error', err.str())
|
|
||||||
action.done = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the action as done
|
|
||||||
action.done = true
|
|
||||||
|
|
||||||
// Return the record info as a result
|
|
||||||
action.result.set('domain_id', name.id.str())
|
|
||||||
action.result.set('record_name', record.name)
|
|
||||||
action.result.set('type', type_str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process name.add_admin actions
|
|
||||||
mut add_admin_actions := plbook.actions_find(actor: 'name', name: 'add_admin')!
|
|
||||||
for mut action in add_admin_actions {
|
|
||||||
mut p := action.params
|
|
||||||
|
|
||||||
// Get domain name
|
|
||||||
domain := p.get('domain')!
|
|
||||||
|
|
||||||
// Find the name by domain
|
|
||||||
mut name := m.get_by_domain(domain) or {
|
|
||||||
action.result.set('error', 'Domain ${domain} not found')
|
|
||||||
action.done = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get admin pubkey
|
|
||||||
pubkey := p.get('pubkey')!
|
|
||||||
|
|
||||||
// Add the admin to the name
|
|
||||||
name = m.add_admin(name.id, pubkey) or {
|
|
||||||
action.result.set('error', err.str())
|
|
||||||
action.done = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the action as done
|
|
||||||
action.done = true
|
|
||||||
|
|
||||||
// Return the admin info as a result
|
|
||||||
action.result.set('domain_id', name.id.str())
|
|
||||||
action.result.set('pubkey', pubkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,328 +0,0 @@
|
|||||||
module core
|
|
||||||
|
|
||||||
import os
|
|
||||||
import rand
|
|
||||||
|
|
||||||
fn test_name_db() {
|
|
||||||
// Create a temporary directory for testing
|
|
||||||
test_dir := os.join_path(os.temp_dir(), 'hero_name_test_${rand.intn(9000) or { 0 } + 1000}')
|
|
||||||
os.mkdir_all(test_dir) or { panic(err) }
|
|
||||||
defer { os.rmdir_all(test_dir) or {} }
|
|
||||||
|
|
||||||
mut runner := new(path: test_dir)!
|
|
||||||
|
|
||||||
// Create multiple names for testing
|
|
||||||
mut name1 := runner.names.new()
|
|
||||||
name1.domain = 'example.com'
|
|
||||||
name1.description = 'Example domain'
|
|
||||||
name1.admins = ['admin1-pubkey']
|
|
||||||
|
|
||||||
mut name2 := runner.names.new()
|
|
||||||
name2.domain = 'example.org'
|
|
||||||
name2.description = 'Example organization domain'
|
|
||||||
name2.admins = ['admin2-pubkey']
|
|
||||||
|
|
||||||
mut name3 := runner.names.new()
|
|
||||||
name3.domain = 'example.net'
|
|
||||||
name3.description = 'Example network domain'
|
|
||||||
name3.admins = ['admin3-pubkey']
|
|
||||||
|
|
||||||
// Add the names
|
|
||||||
println('Adding name 1')
|
|
||||||
name1 = runner.names.set(name1)!
|
|
||||||
|
|
||||||
// Explicitly set different IDs for each name to avoid overwriting
|
|
||||||
name2.id = 1 // Set a different ID for name2
|
|
||||||
println('Adding name 2')
|
|
||||||
name2 = runner.names.set(name2)!
|
|
||||||
|
|
||||||
name3.id = 2 // Set a different ID for name3
|
|
||||||
println('Adding name 3')
|
|
||||||
name3 = runner.names.set(name3)!
|
|
||||||
|
|
||||||
// Test list functionality
|
|
||||||
println('Testing list functionality')
|
|
||||||
|
|
||||||
// Debug: Print the name IDs in the list
|
|
||||||
name_ids := runner.names.list()!
|
|
||||||
println('Name IDs in list: ${name_ids}')
|
|
||||||
|
|
||||||
// Get all names
|
|
||||||
all_names := runner.names.getall()!
|
|
||||||
println('Retrieved ${all_names.len} names')
|
|
||||||
for i, name in all_names {
|
|
||||||
println('Name ${i}: id=${name.id}, domain=${name.domain}')
|
|
||||||
}
|
|
||||||
|
|
||||||
assert all_names.len == 3, 'Expected 3 names, got ${all_names.len}'
|
|
||||||
|
|
||||||
// Verify all names are in the list
|
|
||||||
mut found1 := false
|
|
||||||
mut found2 := false
|
|
||||||
mut found3 := false
|
|
||||||
|
|
||||||
for name in all_names {
|
|
||||||
if name.domain == 'example.com' {
|
|
||||||
found1 = true
|
|
||||||
} else if name.domain == 'example.org' {
|
|
||||||
found2 = true
|
|
||||||
} else if name.domain == 'example.net' {
|
|
||||||
found3 = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert found1, 'Name 1 not found in list'
|
|
||||||
assert found2, 'Name 2 not found in list'
|
|
||||||
assert found3, 'Name 3 not found in list'
|
|
||||||
|
|
||||||
// Get and verify individual names
|
|
||||||
println('Verifying individual names')
|
|
||||||
retrieved_name1 := runner.names.get_by_domain('example.com')!
|
|
||||||
assert retrieved_name1.domain == name1.domain
|
|
||||||
assert retrieved_name1.description == name1.description
|
|
||||||
assert retrieved_name1.records.len == 0
|
|
||||||
assert retrieved_name1.admins.len == 1
|
|
||||||
assert retrieved_name1.admins[0] == 'admin1-pubkey'
|
|
||||||
|
|
||||||
// Test adding records to a name
|
|
||||||
println('Testing adding records to a name')
|
|
||||||
|
|
||||||
// Create records
|
|
||||||
mut record1 := Record{
|
|
||||||
name: 'www'
|
|
||||||
text: 'Website'
|
|
||||||
category: .a
|
|
||||||
addr: ['192.168.1.1']
|
|
||||||
}
|
|
||||||
|
|
||||||
mut record2 := Record{
|
|
||||||
name: 'mail'
|
|
||||||
text: 'Mail server'
|
|
||||||
category: .mx
|
|
||||||
addr: ['mail.example.com']
|
|
||||||
}
|
|
||||||
|
|
||||||
mut record3 := Record{
|
|
||||||
name: 'txt'
|
|
||||||
text: 'SPF record'
|
|
||||||
category: .txt
|
|
||||||
addr: ['v=spf1 include:_spf.example.com ~all']
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add records to name 1
|
|
||||||
runner.names.add_record(name1.id, record1)!
|
|
||||||
runner.names.add_record(name1.id, record2)!
|
|
||||||
runner.names.add_record(name1.id, record3)!
|
|
||||||
|
|
||||||
// Verify records were added
|
|
||||||
updated_name1 := runner.names.get(name1.id)!
|
|
||||||
assert updated_name1.records.len == 3, 'Expected 3 records, got ${updated_name1.records.len}'
|
|
||||||
|
|
||||||
// Test get_records functionality
|
|
||||||
println('Testing get_records functionality')
|
|
||||||
records := runner.names.get_records(name1.id)!
|
|
||||||
assert records.len == 3, 'Expected 3 records, got ${records.len}'
|
|
||||||
|
|
||||||
// Test get_records_by_category functionality
|
|
||||||
println('Testing get_records_by_category functionality')
|
|
||||||
a_records := runner.names.get_records_by_category(name1.id, .a)!
|
|
||||||
assert a_records.len == 1, 'Expected 1 A record, got ${a_records.len}'
|
|
||||||
assert a_records[0].name == 'www'
|
|
||||||
|
|
||||||
mx_records := runner.names.get_records_by_category(name1.id, .mx)!
|
|
||||||
assert mx_records.len == 1, 'Expected 1 MX record, got ${mx_records.len}'
|
|
||||||
assert mx_records[0].name == 'mail'
|
|
||||||
|
|
||||||
txt_records := runner.names.get_records_by_category(name1.id, .txt)!
|
|
||||||
assert txt_records.len == 1, 'Expected 1 TXT record, got ${txt_records.len}'
|
|
||||||
assert txt_records[0].name == 'txt'
|
|
||||||
|
|
||||||
// Test update_record functionality
|
|
||||||
println('Testing update_record functionality')
|
|
||||||
mut updated_record := Record{
|
|
||||||
name: 'www'
|
|
||||||
text: 'Updated website'
|
|
||||||
category: .a
|
|
||||||
addr: ['192.168.1.1', '192.168.1.2'] // Added a second IP
|
|
||||||
}
|
|
||||||
|
|
||||||
runner.names.update_record(name1.id, 'www', .a, updated_record)!
|
|
||||||
|
|
||||||
// Verify record was updated
|
|
||||||
updated_name_after_record_change := runner.names.get(name1.id)!
|
|
||||||
mut found_updated_record := false
|
|
||||||
|
|
||||||
for record in updated_name_after_record_change.records {
|
|
||||||
if record.name == 'www' && record.category == .a {
|
|
||||||
assert record.text == 'Updated website', 'Expected text to be "Updated website", got "${record.text}"'
|
|
||||||
assert record.addr.len == 2, 'Expected 2 addresses, got ${record.addr.len}'
|
|
||||||
found_updated_record = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert found_updated_record, 'Updated record not found after update'
|
|
||||||
|
|
||||||
// Test remove_record functionality
|
|
||||||
println('Testing remove_record functionality')
|
|
||||||
runner.names.remove_record(name1.id, 'txt', .txt)!
|
|
||||||
|
|
||||||
// Verify record was removed
|
|
||||||
updated_name_after_removal := runner.names.get(name1.id)!
|
|
||||||
assert updated_name_after_removal.records.len == 2, 'Expected 2 records after removal, got ${updated_name_after_removal.records.len}'
|
|
||||||
|
|
||||||
mut found_txt_record := false
|
|
||||||
for record in updated_name_after_removal.records {
|
|
||||||
if record.name == 'txt' && record.category == .txt {
|
|
||||||
found_txt_record = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert !found_txt_record, 'TXT record still found after removal'
|
|
||||||
|
|
||||||
// Test admin management
|
|
||||||
println('Testing admin management')
|
|
||||||
|
|
||||||
// Add admin
|
|
||||||
runner.names.add_admin(name1.id, 'admin2-pubkey')!
|
|
||||||
|
|
||||||
// Verify admin was added
|
|
||||||
updated_name_after_admin_add := runner.names.get(name1.id)!
|
|
||||||
assert updated_name_after_admin_add.admins.len == 2, 'Expected 2 admins after addition, got ${updated_name_after_admin_add.admins.len}'
|
|
||||||
assert 'admin2-pubkey' in updated_name_after_admin_add.admins, 'New admin not found after addition'
|
|
||||||
|
|
||||||
// Remove admin
|
|
||||||
runner.names.remove_admin(name1.id, 'admin2-pubkey')!
|
|
||||||
|
|
||||||
// Verify admin was removed
|
|
||||||
updated_name_after_admin_removal := runner.names.get(name1.id)!
|
|
||||||
assert updated_name_after_admin_removal.admins.len == 1, 'Expected 1 admin after removal, got ${updated_name_after_admin_removal.admins.len}'
|
|
||||||
assert 'admin2-pubkey' !in updated_name_after_admin_removal.admins, 'Removed admin still found after removal'
|
|
||||||
|
|
||||||
// Test delete_by_domain functionality
|
|
||||||
println('Testing delete_by_domain functionality')
|
|
||||||
runner.names.delete_by_domain('example.org')!
|
|
||||||
|
|
||||||
// Verify deletion
|
|
||||||
names_after_delete := runner.names.getall()!
|
|
||||||
assert names_after_delete.len == 2, 'Expected 2 names after deletion, got ${names_after_delete.len}'
|
|
||||||
|
|
||||||
mut found_org := false
|
|
||||||
for name in names_after_delete {
|
|
||||||
if name.domain == 'example.org' {
|
|
||||||
found_org = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert !found_org, 'example.org still found after deletion'
|
|
||||||
|
|
||||||
// Delete remaining names
|
|
||||||
println('Deleting remaining names')
|
|
||||||
runner.names.delete_by_domain('example.com')!
|
|
||||||
runner.names.delete_by_domain('example.net')!
|
|
||||||
|
|
||||||
// Verify all names are deleted
|
|
||||||
names_after_all_deleted := runner.names.getall() or {
|
|
||||||
// This is expected to fail with 'No names found' error
|
|
||||||
assert err.msg().contains('not found'), 'Expected error message to contain "not found"'
|
|
||||||
[]Name{}
|
|
||||||
}
|
|
||||||
assert names_after_all_deleted.len == 0, 'Expected 0 names after all deletions, got ${names_after_all_deleted.len}'
|
|
||||||
|
|
||||||
println('All name manager tests passed successfully')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn test_name_play() {
|
|
||||||
|
|
||||||
test_dir := os.join_path(os.temp_dir(), 'hero_name_test_${rand.intn(9000) or { 0 } + 1000}')
|
|
||||||
os.mkdir_all(test_dir) or { panic(err) }
|
|
||||||
defer { os.rmdir_all(test_dir) or {} }
|
|
||||||
|
|
||||||
mut runner := new(path: test_dir)!
|
|
||||||
|
|
||||||
|
|
||||||
// Create heroscript for testing
|
|
||||||
heroscript_text := "
|
|
||||||
!!name.create
|
|
||||||
domain: 'example.org'
|
|
||||||
description: 'Example domain for testing'
|
|
||||||
admins: 'admin1-pubkey,admin2-pubkey'
|
|
||||||
|
|
||||||
!!name.add_record
|
|
||||||
domain: 'example.org'
|
|
||||||
name: 'www'
|
|
||||||
type: 'a'
|
|
||||||
addrs: '192.168.1.1,192.168.1.2'
|
|
||||||
text: 'Web server'
|
|
||||||
|
|
||||||
!!name.add_record
|
|
||||||
domain: 'example.org'
|
|
||||||
name: 'mail'
|
|
||||||
type: 'mx'
|
|
||||||
addr: '192.168.1.10'
|
|
||||||
text: 'Mail server'
|
|
||||||
|
|
||||||
!!name.add_admin
|
|
||||||
domain: 'example.org'
|
|
||||||
pubkey: 'admin3-pubkey'
|
|
||||||
"
|
|
||||||
|
|
||||||
// Parse the heroscript
|
|
||||||
mut pb := playbook.new(text: heroscript_text)!
|
|
||||||
|
|
||||||
name_manager:=runner.names
|
|
||||||
|
|
||||||
runner.names.play(mut pb)!
|
|
||||||
|
|
||||||
// Verify the domain was created
|
|
||||||
mut names := name_manager.getall()!
|
|
||||||
assert names.len == 1
|
|
||||||
|
|
||||||
// Get the created domain
|
|
||||||
mut name := name_manager.get_by_domain('example.org')!
|
|
||||||
|
|
||||||
// Verify domain properties
|
|
||||||
assert name.domain == 'example.org'
|
|
||||||
assert name.description == 'Example domain for testing'
|
|
||||||
|
|
||||||
// Verify admins
|
|
||||||
assert name.admins.len == 3
|
|
||||||
assert 'admin1-pubkey' in name.admins
|
|
||||||
assert 'admin2-pubkey' in name.admins
|
|
||||||
assert 'admin3-pubkey' in name.admins
|
|
||||||
|
|
||||||
// Verify records
|
|
||||||
assert name.records.len == 2
|
|
||||||
|
|
||||||
// Find and verify the www record
|
|
||||||
mut www_record := Record{}
|
|
||||||
mut mail_record := Record{}
|
|
||||||
|
|
||||||
for record in name.records {
|
|
||||||
if record.name == 'www' {
|
|
||||||
www_record = record
|
|
||||||
} else if record.name == 'mail' {
|
|
||||||
mail_record = record
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify www record
|
|
||||||
assert www_record.name == 'www'
|
|
||||||
assert www_record.category == RecordType.a
|
|
||||||
assert www_record.text == 'Web server'
|
|
||||||
assert www_record.addr.len == 2
|
|
||||||
assert www_record.addr[0] == '192.168.1.1'
|
|
||||||
assert www_record.addr[1] == '192.168.1.2'
|
|
||||||
|
|
||||||
// Verify mail record
|
|
||||||
assert mail_record.name == 'mail'
|
|
||||||
assert mail_record.category == RecordType.mx
|
|
||||||
assert mail_record.text == 'Mail server'
|
|
||||||
assert mail_record.addr.len == 1
|
|
||||||
assert mail_record.addr[0] == '192.168.1.10'
|
|
||||||
|
|
||||||
// No need to explicitly close the databases
|
|
||||||
|
|
||||||
println('Name play heroscript test passed successfully')
|
|
||||||
}
|
|
||||||
@@ -19,9 +19,10 @@ pub fn decoder_new(data []u8) Decoder {
|
|||||||
|
|
||||||
pub fn (mut d Decoder) get_string() !string {
|
pub fn (mut d Decoder) get_string() !string {
|
||||||
n := d.get_u16()!
|
n := d.get_u16()!
|
||||||
if n > 64 * 1024 { // 64KB limit
|
//THIS IS ALWAYS TRYE BECAUSE u16 is max 64KB
|
||||||
return error('string length ${n} exceeds 64KB limit')
|
// if n > 64 * 1024 { // 64KB limit
|
||||||
}
|
// return error('string length ${n} exceeds 64KB limit')
|
||||||
|
// }
|
||||||
if n > d.data.len {
|
if n > d.data.len {
|
||||||
return error('string length ${n} exceeds remaining data length ${d.data.len}')
|
return error('string length ${n} exceeds remaining data length ${d.data.len}')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,8 @@ pub fn new(args OurDBConfig) !OurDB {
|
|||||||
keysize = 2
|
keysize = 2
|
||||||
} else if args.record_nr_max < 16777216 {
|
} else if args.record_nr_max < 16777216 {
|
||||||
keysize = 3
|
keysize = 3
|
||||||
} else if args.record_nr_max < 4294967296 {
|
|
||||||
keysize = 4
|
|
||||||
} else {
|
} else {
|
||||||
return error('max supported records is 4294967296 in OurDB')
|
keysize = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
if f64(args.record_size_max * args.record_nr_max) / 2 > mbyte_ * 10 {
|
if f64(args.record_size_max * args.record_nr_max) / 2 > mbyte_ * 10 {
|
||||||
|
|||||||
Reference in New Issue
Block a user