feat: add commands for managing organizations and users

Introduce `AddUserToOrganization`, `RemoveAPIKey`, and 
`RemoveOrganization` commands to enhance organization 
management. Implement validation for user addition and 
API key removal. Update GraphQL schema to support new 
mutations and add caching for the new events, ensuring 
that organizations and their relationships are accurately 
represented in the cache.
This commit is contained in:
argoyle committed 2025-11-22 18:37:07 +01:00
1 parent 335a9f3b54
commit ffcf41b85a
14 files changed
+1500 -30

No files matched your search

+78
View File
@@ -53,6 +53,17 @@ func (c *Cache) OrganizationsByUser(sub string) []domain.Organization {
return orgs
}
func (c *Cache) AllOrganizations() []domain.Organization {
c.mu.RLock()
defer c.mu.RUnlock()
orgs := make([]domain.Organization, 0, len(c.organizations))
for _, org := range c.organizations {
orgs = append(orgs, org)
}
return orgs
}
func (c *Cache) ApiKeyByKey(key string) *domain.APIKey {
c.mu.RLock()
defer c.mu.RUnlock()
@@ -100,6 +111,16 @@ func (c *Cache) Update(msg any, _ goamqp.Headers) (any, error) {
c.organizations[m.ID.String()] = o
c.addUser(m.Initiator, o)
c.logger.With("org_id", m.ID.String(), "event", "OrganizationAdded").Debug("cache updated")
case *domain.UserAddedToOrganization:
org, exists := c.organizations[m.ID.String()]
if exists {
m.UpdateOrganization(&org)
c.organizations[m.ID.String()] = org
c.addUser(m.UserId, org)
c.logger.With("org_id", m.ID.String(), "user_id", m.UserId, "event", "UserAddedToOrganization").Debug("cache updated")
} else {
c.logger.With("org_id", m.ID.String(), "event", "UserAddedToOrganization").Warn("organization not found in cache")
}
case *domain.APIKeyAdded:
key := domain.APIKey{
Name: m.Name,
@@ -117,6 +138,63 @@ func (c *Cache) Update(msg any, _ goamqp.Headers) (any, error) {
org.APIKeys = append(org.APIKeys, key)
c.organizations[m.OrganizationId] = org
c.logger.With("org_id", m.OrganizationId, "key_name", m.Name, "event", "APIKeyAdded").Debug("cache updated")
case *domain.APIKeyRemoved:
orgId := m.ID.String()
org, exists := c.organizations[orgId]
if exists {
// Remove from organization's API keys list
for i, key := range org.APIKeys {
if key.Name == m.KeyName {
org.APIKeys = append(org.APIKeys[:i], org.APIKeys[i+1:]...)
break
}
}
c.organizations[orgId] = org
// Remove from apiKeys map
delete(c.apiKeys, apiKeyId(orgId, m.KeyName))
c.logger.With("org_id", orgId, "key_name", m.KeyName, "event", "APIKeyRemoved").Debug("cache updated")
} else {
c.logger.With("org_id", orgId, "event", "APIKeyRemoved").Warn("organization not found in cache")
}
case *domain.OrganizationRemoved:
orgId := m.ID.String()
org, exists := c.organizations[orgId]
if exists {
// Remove all API keys for this organization
for _, key := range org.APIKeys {
delete(c.apiKeys, apiKeyId(orgId, key.Name))
}
// Remove organization from all users
for userId, userOrgs := range c.users {
for i, userOrgId := range userOrgs {
if userOrgId == orgId {
c.users[userId] = append(userOrgs[:i], userOrgs[i+1:]...)
break
}
}
// If user has no more organizations, remove from map
if len(c.users[userId]) == 0 {
delete(c.users, userId)
}
}
// Remove services for this organization
if refs, exists := c.services[orgId]; exists {
for ref := range refs {
// Remove all subgraphs for this org/ref combination
for service := range refs[ref] {
delete(c.subGraphs, subGraphKey(orgId, ref, service))
}
// Remove lastUpdate for this org/ref
delete(c.lastUpdate, refKey(orgId, ref))
}
delete(c.services, orgId)
}
// Remove organization
delete(c.organizations, orgId)
c.logger.With("org_id", orgId, "event", "OrganizationRemoved").Debug("cache updated")
} else {
c.logger.With("org_id", orgId, "event", "OrganizationRemoved").Warn("organization not found in cache")
}
case *domain.SubGraphUpdated:
c.updateSubGraph(m.OrganizationId, m.Ref, m.ID.String(), m.Service, m.Time)
c.logger.With("org_id", m.OrganizationId, "ref", m.Ref, "service", m.Service, "event", "SubGraphUpdated").Debug("cache updated")