diff --git a/src/keri/app/__init__.py b/src/keri/app/__init__.py index 5863ca62b..ae5fdf2b7 100644 --- a/src/keri/app/__init__.py +++ b/src/keri/app/__init__.py @@ -5,3 +5,5 @@ keri.app package """ + +from .organizing import Organizer, IdentifierOrganizer diff --git a/src/keri/app/cli/commands/challenge/respond.py b/src/keri/app/cli/commands/challenge/respond.py index 9fb3e79f1..5ff1555a0 100644 --- a/src/keri/app/cli/commands/challenge/respond.py +++ b/src/keri/app/cli/commands/challenge/respond.py @@ -7,7 +7,7 @@ from hio.base import doing -from keri.app import habbing, forwarding, connecting +from keri.app import habbing, forwarding, organizing from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.app.habbing import GroupHab @@ -75,7 +75,7 @@ def __init__(self, name, base, bran, alias, words: list, recp: str): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.postman = forwarding.Poster(hby=self.hby) self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) doers = [self.hbyDoer, self.postman, doing.doify(self.respondDo)] super(RespondDoer, self).__init__(doers=doers) diff --git a/src/keri/app/cli/commands/challenge/verify.py b/src/keri/app/cli/commands/challenge/verify.py index 3f5949de1..cdd189efc 100644 --- a/src/keri/app/cli/commands/challenge/verify.py +++ b/src/keri/app/cli/commands/challenge/verify.py @@ -11,7 +11,7 @@ from hio.base import doing from keri import help -from keri.app import indirecting, challenging, connecting, signaling +from keri.app import indirecting, challenging, organizing, signaling from keri.app.cli.commands.challenge.generate import generateWords from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery @@ -66,7 +66,7 @@ def __init__(self, name, base, bran, words, generate, strength, out, signer): self.signer = signer self.hby = existing.setupHby(name=name, base=base, bran=bran) self.exc = exchanging.Exchanger(hby=self.hby, handlers=[]) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) signaler = signaling.Signaler() challenging.loadHandlers(db=self.hby.db, signaler=signaler, exc=self.exc) diff --git a/src/keri/app/cli/commands/contacts/list.py b/src/keri/app/cli/commands/contacts/list.py index 3fbb459d8..8da4e9576 100644 --- a/src/keri/app/cli/commands/contacts/list.py +++ b/src/keri/app/cli/commands/contacts/list.py @@ -11,7 +11,7 @@ from hio.base import doing from keri import help, kering -from keri.app import connecting +from keri.app import organizing from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.kering import ConfigurationError @@ -39,7 +39,7 @@ def list(tymth, tock=0.0, **opts): try: with existing.existingHby(name=name, base=base, bran=bran) as hby: - org = connecting.Organizer(hby=hby) + org = organizing.Organizer(hby=hby) for c in org.list(): aid = c['id'] diff --git a/src/keri/app/cli/commands/contacts/replace.py b/src/keri/app/cli/commands/contacts/replace.py index 0f30b64d2..dc2c5772b 100644 --- a/src/keri/app/cli/commands/contacts/replace.py +++ b/src/keri/app/cli/commands/contacts/replace.py @@ -10,7 +10,7 @@ from hio.base import doing from keri import help -from keri.app import connecting +from keri.app import organizing from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.kering import ConfigurationError @@ -44,7 +44,7 @@ def replace(tymth, tock=0.0, **opts): try: with existing.existingHby(name=name, base=base, bran=bran) as hby: - org = connecting.Organizer(hby=hby) + org = organizing.Organizer(hby=hby) if prefix not in hby.kevers: print(f"{prefix} is not a known identifier, oobi must be resolved first") diff --git a/src/keri/app/cli/commands/introduce.py b/src/keri/app/cli/commands/introduce.py index b06688f91..96c6b3e38 100644 --- a/src/keri/app/cli/commands/introduce.py +++ b/src/keri/app/cli/commands/introduce.py @@ -10,7 +10,7 @@ from keri.app.cli.common.parsing import Parsery from keri.core import serdering from ..common import existing -from ... import habbing, connecting, forwarding +from ... import habbing, organizing, forwarding parser = argparse.ArgumentParser(description='Send an rpy /introduce message to recipient with OOBI', parents=[Parsery.keystore()]) @@ -64,7 +64,7 @@ def __init__(self, name, base, bran, alias, introducee, recipient, role): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.postman = forwarding.Poster(hby=self.hby) doers = [self.hbyDoer, self.postman, doing.doify(self.introduceDo)] diff --git a/src/keri/app/cli/commands/ipex/admit.py b/src/keri/app/cli/commands/ipex/admit.py index 376502127..54a59939c 100644 --- a/src/keri/app/cli/commands/ipex/admit.py +++ b/src/keri/app/cli/commands/ipex/admit.py @@ -8,7 +8,7 @@ from hio.base import doing from keri.kering import Vrsn_1_0, Vrsn_2_0 -from keri.app import connecting, habbing, grouping, indirecting, agenting, forwarding +from keri.app import organizing, habbing, grouping, indirecting, agenting, forwarding from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.app.notifying import Notifier @@ -52,7 +52,7 @@ def __init__(self, name, alias, base, bran, said, message, timestamp ): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.witq = agenting.WitnessInquisitor(hby=self.hby) self.kvy = eventing.Kevery(db=self.hby.db) diff --git a/src/keri/app/cli/commands/ipex/grant.py b/src/keri/app/cli/commands/ipex/grant.py index e6120fa08..4317c87b4 100644 --- a/src/keri/app/cli/commands/ipex/grant.py +++ b/src/keri/app/cli/commands/ipex/grant.py @@ -8,7 +8,7 @@ from hio.base import doing from keri.kering import Vrsn_1_0, Vrsn_2_0 -from keri.app import forwarding, connecting, habbing, grouping, indirecting, signing +from keri.app import forwarding, organizing, habbing, grouping, indirecting, signing from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.app.notifying import Notifier @@ -54,7 +54,7 @@ def __init__(self, name, alias, base, bran, said, recp, message, timestamp): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) notifier = Notifier(self.hby) mux = grouping.Multiplexor(self.hby, notifier=notifier) diff --git a/src/keri/app/cli/commands/ipex/join.py b/src/keri/app/cli/commands/ipex/join.py index 03c579a83..9db7331a7 100644 --- a/src/keri/app/cli/commands/ipex/join.py +++ b/src/keri/app/cli/commands/ipex/join.py @@ -11,7 +11,7 @@ from keri import help from keri.kering import Vrsn_1_0, Vrsn_2_0 -from keri.app import habbing, indirecting, agenting, notifying, grouping, connecting, forwarding +from keri.app import habbing, indirecting, agenting, notifying, grouping, organizing, forwarding from keri.app.cli.common import existing from keri.core import parsing, routing, serdering, coring from keri.peer import exchanging @@ -60,7 +60,7 @@ def __init__(self, name, base, bran, auto=False): self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base) self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer self.witq = agenting.WitnessInquisitor(hby=self.hby) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.notifier = notifying.Notifier(hby=self.hby) self.exc = exchanging.Exchanger(hby=self.hby, handlers=[]) self.verifier = verifying.Verifier(hby=self.hby, reger=self.rgy.reger) diff --git a/src/keri/app/cli/commands/ipex/list.py b/src/keri/app/cli/commands/ipex/list.py index 8e564b4ad..889935cd5 100644 --- a/src/keri/app/cli/commands/ipex/list.py +++ b/src/keri/app/cli/commands/ipex/list.py @@ -14,7 +14,7 @@ from hio.base import doing from keri import help, kering -from keri.app import indirecting, notifying, connecting +from keri.app import indirecting, notifying, organizing from keri.app.cli.common import existing, terming from keri.app.cli.common.parsing import Parsery from keri.core import scheming @@ -73,7 +73,7 @@ def __init__(self, name, alias, base, bran, poll=False, verbose=False, said=Fals self.hab = self.hby.habByName(alias) self.notifier = notifying.Notifier(hby=self.hby) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base) self.vry = verifying.Verifier(hby=self.hby, reger=self.rgy.reger) self.exc = exchanging.Exchanger(hby=self.hby, handlers=[]) diff --git a/src/keri/app/cli/commands/ipex/spurn.py b/src/keri/app/cli/commands/ipex/spurn.py index 28f9d261c..450487fac 100644 --- a/src/keri/app/cli/commands/ipex/spurn.py +++ b/src/keri/app/cli/commands/ipex/spurn.py @@ -9,7 +9,7 @@ from hio.base import doing from keri.kering import Vrsn_1_0, Vrsn_2_0 -from keri.app import forwarding, connecting, habbing, grouping, indirecting +from keri.app import forwarding, organizing, habbing, grouping, indirecting from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.app.notifying import Notifier @@ -50,7 +50,7 @@ def __init__(self, name, alias, base, bran, said, message): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) kvy = eventing.Kevery(db=self.hby.db) tvy = teventing.Tevery(db=self.hby.db, reger=self.rgy.reger) diff --git a/src/keri/app/cli/commands/mailbox/add.py b/src/keri/app/cli/commands/mailbox/add.py index b77cc1fa1..fff26fe3a 100644 --- a/src/keri/app/cli/commands/mailbox/add.py +++ b/src/keri/app/cli/commands/mailbox/add.py @@ -10,7 +10,7 @@ from hio.help import Hict from keri import help, kering -from keri.app import connecting, habbing +from keri.app import organizing, habbing from keri.app.agenting import httpClient, WitnessPublisher from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery @@ -46,7 +46,7 @@ class AddDoer(doing.DoDoer): def __init__(self, name, alias, base, bran, mailbox): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.witpub = WitnessPublisher(hby=self.hby) if mailbox in self.hby.kevers: diff --git a/src/keri/app/cli/commands/mailbox/list.py b/src/keri/app/cli/commands/mailbox/list.py index ccdcba8ed..fa0589655 100644 --- a/src/keri/app/cli/commands/mailbox/list.py +++ b/src/keri/app/cli/commands/mailbox/list.py @@ -9,7 +9,7 @@ from hio.base import doing from keri import help -from keri.app import connecting +from keri.app import organizing from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.kering import ConfigurationError, Roles @@ -48,7 +48,7 @@ def listMailboxes(tymth, tock=0.0, **opts): try: with existing.existingHby(name=name, base=base, bran=bran) as hby: - org = connecting.Organizer(hby=hby) + org = organizing.Organizer(hby=hby) if alias is None: alias = existing.aliasInput(hby) diff --git a/src/keri/app/cli/commands/multisig/join.py b/src/keri/app/cli/commands/multisig/join.py index d0cfa8c62..b3d3d76c5 100644 --- a/src/keri/app/cli/commands/multisig/join.py +++ b/src/keri/app/cli/commands/multisig/join.py @@ -13,7 +13,7 @@ from keri import help, kering from keri.kering import Vrsn_1_0, Vrsn_2_0 -from keri.app import habbing, indirecting, agenting, notifying, grouping, connecting, forwarding +from keri.app import habbing, indirecting, agenting, notifying, grouping, organizing, forwarding from keri.app.cli.common import existing, displaying from keri.app.cli.common.parsing import Parsery from keri.core import coring, eventing, scheming, parsing, routing, serdering @@ -68,7 +68,7 @@ def __init__(self, name, base, bran, group, auto=False): self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base) self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer self.witq = agenting.WitnessInquisitor(hby=self.hby) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.notifier = notifying.Notifier(hby=self.hby) self.exc = exchanging.Exchanger(hby=self.hby, handlers=[]) self.verifier = verifying.Verifier(hby=self.hby, reger=self.rgy.reger) diff --git a/src/keri/app/cli/commands/multisig/shell.py b/src/keri/app/cli/commands/multisig/shell.py index 82beff5a2..4ca3dddb6 100644 --- a/src/keri/app/cli/commands/multisig/shell.py +++ b/src/keri/app/cli/commands/multisig/shell.py @@ -5,7 +5,7 @@ import os from hio.base import doing -from keri.app import connecting, apping +from keri.app import organizing, apping from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.core import coring @@ -37,7 +37,7 @@ def kims(tymth, tock=0.0, **opts): static = args.static with existing.existingHby(name=name, base=base, bran=bran) as hby: - org = connecting.Organizer(hby=hby) + org = organizing.Organizer(hby=hby) contacts = org.list() MultiSigShell(hby, contacts, static).cmdloop() return True diff --git a/src/keri/app/cli/commands/vc/create.py b/src/keri/app/cli/commands/vc/create.py index 1abbe8de7..e4d177d82 100644 --- a/src/keri/app/cli/commands/vc/create.py +++ b/src/keri/app/cli/commands/vc/create.py @@ -5,7 +5,7 @@ from hio.base import doing from keri import core, help, kering -from keri.app import indirecting, habbing, grouping, connecting, forwarding, signing, notifying +from keri.app import indirecting, habbing, grouping, organizing, forwarding, signing, notifying from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.core import coring, eventing, serdering @@ -145,7 +145,7 @@ def __init__(self, name, alias, base, bran, registryName=None, schema=None, edge self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer self.counselor = grouping.Counselor(hby=self.hby) self.registrar = credentialing.Registrar(hby=self.hby, rgy=self.rgy, counselor=self.counselor) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.postman = forwarding.Poster(hby=self.hby) notifier = notifying.Notifier(self.hby) mux = grouping.Multiplexor(self.hby, notifier=notifier) diff --git a/src/keri/app/cli/commands/vc/revoke.py b/src/keri/app/cli/commands/vc/revoke.py index bc4f8fb21..21d0dab8e 100644 --- a/src/keri/app/cli/commands/vc/revoke.py +++ b/src/keri/app/cli/commands/vc/revoke.py @@ -8,7 +8,7 @@ from hio.base import doing from keri import kering -from keri.app import indirecting, habbing, grouping, forwarding, connecting, notifying +from keri.app import indirecting, habbing, grouping, forwarding, organizing, notifying from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.app.habbing import GroupHab @@ -48,7 +48,7 @@ def __init__(self, name, alias, said, base, bran, registryName, send, timestamp, self.registryName = registryName self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base) self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer self.counselor = grouping.Counselor(hby=self.hby) diff --git a/src/keri/app/cli/commands/watcher/add.py b/src/keri/app/cli/commands/watcher/add.py index 8a6fd8905..cae4ead11 100644 --- a/src/keri/app/cli/commands/watcher/add.py +++ b/src/keri/app/cli/commands/watcher/add.py @@ -9,7 +9,7 @@ from hio.base import doing from keri import help -from keri.app import connecting, habbing, forwarding +from keri.app import organizing, habbing, forwarding from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.core import serdering @@ -48,7 +48,7 @@ class AddDoer(doing.DoDoer): def __init__(self, name, alias, base, bran, watcher, watched): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) wat = None if watcher in self.hby.kevers: diff --git a/src/keri/app/cli/commands/watcher/adjudicate.py b/src/keri/app/cli/commands/watcher/adjudicate.py index 953cba87c..6c19b47f4 100644 --- a/src/keri/app/cli/commands/watcher/adjudicate.py +++ b/src/keri/app/cli/commands/watcher/adjudicate.py @@ -12,7 +12,7 @@ from hio.base import doing from keri import help -from keri.app import connecting, indirecting, querying, watching +from keri.app import organizing, indirecting, querying, watching from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.help import helping @@ -69,7 +69,7 @@ def adjudicate(self, tymth, tock=0.0, **opts): _ = (yield tock) try: - org = connecting.Organizer(hby=self.hby) + org = organizing.Organizer(hby=self.hby) if self.poll: end = helping.nowUTC() + datetime.timedelta(seconds=5) diff --git a/src/keri/app/cli/commands/watcher/list.py b/src/keri/app/cli/commands/watcher/list.py index c4dee2cd8..97280a07a 100644 --- a/src/keri/app/cli/commands/watcher/list.py +++ b/src/keri/app/cli/commands/watcher/list.py @@ -9,7 +9,7 @@ from hio.base import doing from keri import help -from keri.app import connecting +from keri.app import organizing from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery from keri.kering import ConfigurationError, Roles @@ -48,7 +48,7 @@ def listWatchers(tymth, tock=0.0, **opts): try: with existing.existingHby(name=name, base=base, bran=bran) as hby: - org = connecting.Organizer(hby=hby) + org = organizing.Organizer(hby=hby) if alias is None: alias = existing.aliasInput(hby) diff --git a/src/keri/app/cli/commands/witness/authenticate.py b/src/keri/app/cli/commands/witness/authenticate.py index eb7fc3033..204e29ecd 100644 --- a/src/keri/app/cli/commands/witness/authenticate.py +++ b/src/keri/app/cli/commands/witness/authenticate.py @@ -12,7 +12,7 @@ from hio.help import Hict from keri import help -from keri.app import httping, connecting +from keri.app import httping, organizing from keri.app.agenting import httpClient from keri.app.cli.common import existing from keri.app.cli.common.parsing import Parsery @@ -53,7 +53,7 @@ class AuthDoer(doing.DoDoer): def __init__(self, name, alias, base, bran, witness, urlOnly): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) self.urlOnly = urlOnly if witness in self.hby.kevers: diff --git a/src/keri/app/oobiing.py b/src/keri/app/oobiing.py index 7a90f9a5c..13328d0c7 100644 --- a/src/keri/app/oobiing.py +++ b/src/keri/app/oobiing.py @@ -19,7 +19,7 @@ from .. import help from .. import kering from ..kering import Vrsn_1_0, Vrsn_2_0 -from ..app import connecting +from ..app import organizing from ..core import routing, eventing, parsing, scheming, serdering from ..db import basing from ..end import ending @@ -291,7 +291,7 @@ def __init__(self, hby, rvy=None, clienter=None, cues=None): self.registerReplyRoutes(self.rvy.rtr) self.clienter = clienter or httping.Clienter() - self.org = connecting.Organizer(hby=self.hby) + self.org = organizing.Organizer(hby=self.hby) # Set up a local parser for returned events from OOBI queries. rtr = routing.Router() diff --git a/src/keri/app/connecting.py b/src/keri/app/organizing.py similarity index 71% rename from src/keri/app/connecting.py rename to src/keri/app/organizing.py index e6a2f545c..cf9ba9269 100644 --- a/src/keri/app/connecting.py +++ b/src/keri/app/organizing.py @@ -1,6 +1,6 @@ # -*- encoding: utf-8 -*- """ -keri.app.connecting module +keri.app.organizing module """ import re @@ -11,16 +11,24 @@ from keri import kering -class Organizer: - """ Organizes contacts relating contact information to AIDs """ +class BaseOrganizer: + """ Base class for organizing contact or identifier information """ - def __init__(self, hby): - """ Create contact Organizer + def __init__(self, hby, cigsdb, datadb, fielddb, imgsdb): + """ Create base Organizer Parameters: - hby (Habery): database environment for contact information + hby (Habery): database environment + cigsdb: database for storing signatures + datadb: database for storing main data + fielddb: database for storing individual fields + imgsdb: database for storing images """ self.hby = hby + self.cigsdb = cigsdb + self.datadb = datadb + self.fielddb = fielddb + self.imgsdb = imgsdb def update(self, pre, data): """ Add or update contact information in data for the identifier prefix @@ -39,11 +47,11 @@ def update(self, pre, data): raw = json.dumps(existing).encode("utf-8") cigar = self.hby.signator.sign(ser=raw) - self.hby.db.ccigs.pin(keys=(pre,), val=cigar) - self.hby.db.cons.pin(keys=(pre,), val=raw) + self.cigsdb.pin(keys=(pre,), val=cigar) + self.datadb.pin(keys=(pre,), val=raw) for field, val in data.items(): - self.hby.db.cfld.pin(keys=(pre, field), val=val) + self.fielddb.pin(keys=(pre, field), val=val) def replace(self, pre, data): """ Replace all contact information for identifier prefix with data @@ -68,7 +76,7 @@ def set(self, pre, field, val): data = self.get(pre) or dict() data[field] = val self.replace(pre, data) - self.hby.db.cfld.pin(keys=(pre, field), val=val) + self.fielddb.pin(keys=(pre, field), val=val) def unset(self, pre, field): """ Remove field from contact information for identifier prefix @@ -81,7 +89,7 @@ def unset(self, pre, field): data = self.get(pre) del data[field] self.replace(pre, data) - self.hby.db.cfld.rem(keys=(pre, field)) + self.fielddb.rem(keys=(pre, field)) def rem(self, pre): """ Remove all contact information for identifier prefix @@ -92,9 +100,9 @@ def rem(self, pre): Returns: """ - self.hby.db.ccigs.rem(keys=(pre,)) - self.hby.db.cons.rem(keys=(pre,)) - return self.hby.db.cfld.trim(keys=(pre,)) + self.cigsdb.rem(keys=(pre,)) + self.datadb.rem(keys=(pre,)) + return self.fielddb.trim(keys=(pre,)) def get(self, pre, field=None): """ Retrieve all contact information for identifier prefix @@ -107,10 +115,10 @@ def get(self, pre, field=None): dict: Contact data """ - raw = self.hby.db.cons.get(keys=(pre,)) + raw = self.datadb.get(keys=(pre,)) if raw is None: return None - cigar = self.hby.db.ccigs.get(keys=(pre,)) + cigar = self.cigsdb.get(keys=(pre,)) if not self.hby.signator.verify(ser=raw.encode("utf-8"), cigar=cigar): raise kering.ValidationError(f"failed signature on {pre} contact data") @@ -135,7 +143,7 @@ def list(self): key = "" data = None contacts = [] - for (pre, field), val in self.hby.db.cfld.getItemIter(): + for (pre, field), val in self.fielddb.getItemIter(): if pre != key: if data is not None: contacts.append(data) @@ -162,7 +170,7 @@ def find(self, field, val): """ pres = [] prog = re.compile(f".*{val}.*", re.I) - for (pre, f), v in self.hby.db.cfld.getItemIter(): + for (pre, f), v in self.fielddb.getItemIter(): if f == field and prog.match(v): pres.append(pre) @@ -182,10 +190,9 @@ def values(self, field, val=None): prog = re.compile(f".*{val}.*", re.I) if val is not None else None vals = oset() - for (pre, f), v in self.hby.db.cfld.getItemIter(): - if f == field: - if prog is None or prog.match(v): - vals.add(v) + for (pre, f), v in self.fielddb.getItemIter(): + if f == field and (prog is None or prog.match(v)): + vals.add(v) return list(vals) @@ -201,10 +208,10 @@ def setImg(self, pre, typ, stream): stream (file): file-like stream of image data """ - self.hby.db.delTopVal(db=self.hby.db.imgs, top=pre.encode("utf-8")) + self.hby.db.delTopVal(db=self.imgsdb, top=pre.encode("utf-8")) key = f"{pre}.content-type".encode("utf-8") - self.hby.db.setVal(db=self.hby.db.imgs, key=key, val=typ.encode("utf-8")) + self.hby.db.setVal(db=self.imgsdb, key=key, val=typ.encode("utf-8")) idx = 0 size = 0 @@ -213,12 +220,12 @@ def setImg(self, pre, typ, stream): if not chunk: break key = f"{pre}.{idx}".encode("utf-8") - self.hby.db.setVal(db=self.hby.db.imgs, key=key, val=chunk) + self.hby.db.setVal(db=self.imgsdb, key=key, val=chunk) idx += 1 size += len(chunk) key = f"{pre}.content-length".encode("utf-8") - self.hby.db.setVal(db=self.hby.db.imgs, key=key, val=size.to_bytes(4, "big")) + self.hby.db.setVal(db=self.imgsdb, key=key, val=size.to_bytes(4, "big")) def getImgData(self, pre): """ Get image metadata for identifier image if one exists @@ -231,12 +238,12 @@ def getImgData(self, pre): """ key = f"{pre}.content-length".encode("utf-8") - size = self.hby.db.getVal(db=self.hby.db.imgs, key=key) + size = self.hby.db.getVal(db=self.imgsdb, key=key) if size is None: return None key = f"{pre}.content-type".encode("utf-8") - typ = self.hby.db.getVal(db=self.hby.db.imgs, key=key) + typ = self.hby.db.getVal(db=self.imgsdb, key=key) if typ is None: return None @@ -255,8 +262,44 @@ def getImg(self, pre): idx = 0 while True: key = f"{pre}.{idx}".encode("utf-8") - chunk = self.hby.db.getVal(db=self.hby.db.imgs, key=key) + chunk = self.hby.db.getVal(db=self.imgsdb, key=key) if not chunk: break yield bytes(chunk) idx += 1 + + +class Organizer(BaseOrganizer): + """ Organizes contacts relating contact information to AIDs """ + + def __init__(self, hby): + """ Create contact Organizer + + Parameters: + hby (Habery): database environment for contact information + """ + super().__init__( + hby=hby, + cigsdb=hby.db.ccigs, + datadb=hby.db.cons, + fielddb=hby.db.cfld, + imgsdb=hby.db.imgs + ) + + +class IdentifierOrganizer(BaseOrganizer): + """ Organizes identifier information for local identifiers """ + + def __init__(self, hby): + """ Create identifier Organizer + + Parameters: + hby (Habery): database environment for identifier information + """ + super().__init__( + hby=hby, + cigsdb=hby.db.icigs, + datadb=hby.db.sids, + fielddb=hby.db.ifld, + imgsdb=hby.db.iimgs + ) \ No newline at end of file diff --git a/src/keri/db/basing.py b/src/keri/db/basing.py index 0188fd417..241e76ffa 100644 --- a/src/keri/db/basing.py +++ b/src/keri/db/basing.py @@ -1281,6 +1281,24 @@ def reopen(self, **kwa): # TODO: clean self.imgs = self.env.open_db(key=b'imgs.') + # Field values for identifier information for local identifiers. Keyed by prefix/field + # TODO: clean + self.ifld = subing.Suber(db=self, + subkey="ifld.") + + # Signed identifier data, keys by prefix + # TODO: clean + self.sids = subing.Suber(db=self, + subkey="sids.") + + # Transferable signatures on identifier data + # TODO: clean + self.icigs = subing.CesrSuber(db=self, subkey='icigs.', klas=coring.Cigar) + + # Chunked image data for identifier information for local identifiers + # TODO: clean + self.iimgs = self.env.open_db(key=b'iimgs.') + # Delegation escrow dbs # # delegated partial witness escrow self.dpwe = subing.SerderSuber(db=self, subkey='dpwe.') @@ -1499,7 +1517,8 @@ def clean(self): # reprocess them. We need a more secure method in the future unsecured = ["hbys", "schema", "states", "rpys", "eans", "tops", "cgms", "exns", "erpy", "kdts", "ksns", "knas", "oobis", "roobi", "woobi", "moobi", "mfa", "rmfa", - "cfld", "cons", "ccigs", "cdel", "migs"] + "cfld", "cons", "ccigs", "cdel", "migs", + "ifld", "sids", "icigs"] for name in unsecured: srcdb = getattr(self, name) @@ -1521,6 +1540,10 @@ def clean(self): for (key, val) in self.getTopItemIter(self.imgs): copy.imgs.setVal(key=key, val=val) + # Insecure raw iimgs database copy. + for (key, val) in self.getTopItemIter(self.iimgs): + copy.iimgs.setVal(key=key, val=val) + # clone .habs habitat name prefix Komer subdb # copy.habs = koming.Komer(db=copy, schema=HabitatRecord, subkey='habs.') # copy for keys, val in self.habs.getItemIter(): diff --git a/tests/app/test_connecting.py b/tests/app/test_connecting.py deleted file mode 100644 index 448cbc37a..000000000 --- a/tests/app/test_connecting.py +++ /dev/null @@ -1,187 +0,0 @@ -# -*- encoding: utf-8 -*- -""" -tests.app.connecting module -""" -import io -import os - -import pytest - -from keri import kering -from keri.app import connecting, habbing -from keri.core import signing - - -def test_organizer(): - joe = "EtyPSuUjLyLdXAtGMrsTt0-ELyWeU8fJcymHiGOfuaSA" - bob = "EuEQX8At31X96iDVpigv-rTdOKvFiWFunbJ1aDfq89IQ" - ken = "EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU" - jen = "ED61oxVwVNf_olqR5wAhAjvuK59xuBOJXnJPGhwWDYoc" - wil = "EPzeu5_C80nzPc_BGUHVBkXXfNmlS55Ayl7Rd1I0gWFE" - sal = "Eo60ITGA69z4jNBU4RsvbgsjfAHFcTM2HVEXea1SvnXk" - joed = dict(first="Joe", last="Jury", address="9934 Glen Creek St.", city="Lawrence", state="MA", zip="01841", - company="HCF", alias="joe") - bobd = dict(first="Bob", last="Burns", address="37 East Shadow Brook St.", city="Sebastian", state="FL", - zip="32958", company="HCF", alias="bob") - kend = dict(first="Ken", last="Knight", address="28 Williams Ave.", city="Bridgewater", state="NJ", zip="08807", - company="GLEIF", alias="ken") - jend = dict(first="Jen", last="Jones", address="7977 Manor Street", city="Henderson", state="KY", zip="42420", - company="GLEIF", alias="jen") - wild = dict(first="Will", last="Weaver", address="7196 2nd Dr.", city="Norwich", state="CT", zip="06360", - company="GLEIF", alias="will") - sald = dict(first="Sally", last="Smith", address="31 Gainsway Court", city="Lake Charles", state="LA", - zip="70605", - company="GLEIF", alias="sally") - - with habbing.openHby(name="test", temp=True) as hby: - org = connecting.Organizer(hby=hby) - - org.replace(pre=joe, data=joed) - org.replace(pre=bob, data=bobd) - org.replace(pre=ken, data=kend) - org.replace(pre=jen, data=jend) - org.replace(pre=wil, data=wild) - org.replace(pre=sal, data=sald) - - contacts = org.list() - assert len(contacts) == 6 - data = {d["id"]: d for d in contacts} - assert joe in data - assert bob in data - assert ken in data - assert jen in data - assert wil in data - assert sal in data - - d = org.get(pre=bob) - assert d["id"] == bob - assert d["first"] == "Bob" - assert d["address"] == "37 East Shadow Brook St." - assert d["city"] == "Sebastian" - - d = org.get(pre=sal) - assert d["id"] == sal - assert d["first"] == "Sally" - assert d["alias"] == "sally" - - d = org.get(pre="E8AKUcbZyik8EdkOwXgnyAxO5mSIPJWGZ_o7zMhnNnjo") - assert d is None - - d = org.get(pre=jen) - assert d["id"] == jen - assert d["first"] == "Jen" - assert d["last"] == "Jones" - org.set(pre=jen, field="last", val="Smith") - d = org.get(pre=jen) - assert d["last"] == "Smith" - - org.unset(pre=jen, field="first") - d = org.get(pre=jen) - assert d["id"] == jen - assert "first" not in d - assert d["last"] == "Smith" - - org.update(pre=ken, data=dict( - first="Kenneth", - mobile="222-555-1212" - )) - - d = org.get(pre=ken) - assert d == {'address': '28 Williams Ave.', - 'alias': 'ken', - 'city': 'Bridgewater', - 'company': 'GLEIF', - 'first': 'Kenneth', - 'id': 'EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU', - 'last': 'Knight', - 'mobile': '222-555-1212', - 'state': 'NJ', - 'zip': '08807'} - - org.replace(pre=ken, data=kend) - d = org.get(pre=ken) - assert d == {'address': '28 Williams Ave.', - 'alias': 'ken', - 'city': 'Bridgewater', - 'company': 'GLEIF', - 'first': 'Ken', - 'id': 'EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU', - 'last': 'Knight', - 'state': 'NJ', - 'zip': '08807'} - - org.rem(pre=wil) - d = org.get(pre=wil) - assert d is None - org.replace(pre=wil, data=wild) - - companies = org.values(field="company") - assert companies == ["GLEIF", "HCF"] - - grouped = org.find(field="company", val="HCF") - data = {d["id"]: d for d in grouped} - assert len(data) == 2 - assert joe in data - assert bob in data - - grouped = org.find(field="company", val="GLEIF") - data = {d["id"]: d for d in grouped} - assert len(data) == 4 - assert ken in data - assert jen in data - assert wil in data - assert sal in data - - d = org.get(pre=ken) - assert d == {'address': '28 Williams Ave.', - 'alias': 'ken', - 'city': 'Bridgewater', - 'company': 'GLEIF', - 'first': 'Ken', - 'id': 'EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU', - 'last': 'Knight', - 'state': 'NJ', - 'zip': '08807'} - - # Update the Jen's data signature by signing garbage - nonce = signing.Salter().qb64 - cigar = hby.signator.sign(ser=nonce.encode("utf-8")) - hby.db.ccigs.pin(keys=(jen,), val=cigar) - with pytest.raises(kering.ValidationError): - org.get(pre=jen) - - # This will fail too because it contains Jen - with pytest.raises(kering.ValidationError): - org.find(field="company", val="GLEIF") - - -def test_organizer_imgs(): - - with habbing.openHab(name="test", transferable=True, temp=True) as (hby, hab): - org = connecting.Organizer(hby=hby) - pre = "EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU" - data = bytearray(os.urandom(100000)) - assert len(data) == 100000 - stream = io.BytesIO(data) - - org.setImg(pre, "image/png", stream) - - img = bytearray() - for chunk in org.getImg(pre): - img.extend(chunk) - - assert img == data - - md = org.getImgData(pre=pre) - assert md["type"] == "image/png" - assert md["length"] == len(data) - - pre = "Eo60ITGA69z4jNBU4RsvbgsjfAHFcTM2HVEXea1SvnXk" - md = org.getImgData(pre=pre) - assert md is None - - img = bytearray() - for chunk in org.getImg(pre): - img.extend(chunk) - - assert len(img) == 0 diff --git a/tests/app/test_organizing.py b/tests/app/test_organizing.py new file mode 100644 index 000000000..53e4fd539 --- /dev/null +++ b/tests/app/test_organizing.py @@ -0,0 +1,433 @@ +# -*- encoding: utf-8 -*- +""" +tests.app.organizing module +""" +import io +import os + +import pytest + +from keri import kering +from keri.app import organizing, habbing +from keri.core import signing + + +def test_organizer(): + joe = "EtyPSuUjLyLdXAtGMrsTt0-ELyWeU8fJcymHiGOfuaSA" + bob = "EuEQX8At31X96iDVpigv-rTdOKvFiWFunbJ1aDfq89IQ" + ken = "EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU" + jen = "ED61oxVwVNf_olqR5wAhAjvuK59xuBOJXnJPGhwWDYoc" + wil = "EPzeu5_C80nzPc_BGUHVBkXXfNmlS55Ayl7Rd1I0gWFE" + sal = "Eo60ITGA69z4jNBU4RsvbgsjfAHFcTM2HVEXea1SvnXk" + joed = dict(first="Joe", last="Jury", address="9934 Glen Creek St.", city="Lawrence", state="MA", zip="01841", + company="HCF", alias="joe") + bobd = dict(first="Bob", last="Burns", address="37 East Shadow Brook St.", city="Sebastian", state="FL", + zip="32958", company="HCF", alias="bob") + kend = dict(first="Ken", last="Knight", address="28 Williams Ave.", city="Bridgewater", state="NJ", zip="08807", + company="GLEIF", alias="ken") + jend = dict(first="Jen", last="Jones", address="7977 Manor Street", city="Henderson", state="KY", zip="42420", + company="GLEIF", alias="jen") + wild = dict(first="Will", last="Weaver", address="7196 2nd Dr.", city="Norwich", state="CT", zip="06360", + company="GLEIF", alias="will") + sald = dict(first="Sally", last="Smith", address="31 Gainsway Court", city="Lake Charles", state="LA", + zip="70605", + company="GLEIF", alias="sally") + + with habbing.openHby(name="test", temp=True) as hby: + org = organizing.Organizer(hby=hby) + + org.replace(pre=joe, data=joed) + org.replace(pre=bob, data=bobd) + org.replace(pre=ken, data=kend) + org.replace(pre=jen, data=jend) + org.replace(pre=wil, data=wild) + org.replace(pre=sal, data=sald) + + contacts = org.list() + assert len(contacts) == 6 + data = {d["id"]: d for d in contacts} + assert joe in data + assert bob in data + assert ken in data + assert jen in data + assert wil in data + assert sal in data + + d = org.get(pre=bob) + assert d["id"] == bob + assert d["first"] == "Bob" + assert d["address"] == "37 East Shadow Brook St." + assert d["city"] == "Sebastian" + + d = org.get(pre=sal) + assert d["id"] == sal + assert d["first"] == "Sally" + assert d["alias"] == "sally" + + d = org.get(pre="E8AKUcbZyik8EdkOwXgnyAxO5mSIPJWGZ_o7zMhnNnjo") + assert d is None + + d = org.get(pre=jen) + assert d["id"] == jen + assert d["first"] == "Jen" + assert d["last"] == "Jones" + org.set(pre=jen, field="last", val="Smith") + d = org.get(pre=jen) + assert d["last"] == "Smith" + + org.unset(pre=jen, field="first") + d = org.get(pre=jen) + assert d["id"] == jen + assert "first" not in d + assert d["last"] == "Smith" + + org.update(pre=ken, data=dict( + first="Kenneth", + mobile="222-555-1212" + )) + + d = org.get(pre=ken) + assert d == {'address': '28 Williams Ave.', + 'alias': 'ken', + 'city': 'Bridgewater', + 'company': 'GLEIF', + 'first': 'Kenneth', + 'id': 'EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU', + 'last': 'Knight', + 'mobile': '222-555-1212', + 'state': 'NJ', + 'zip': '08807'} + + org.replace(pre=ken, data=kend) + d = org.get(pre=ken) + assert d == {'address': '28 Williams Ave.', + 'alias': 'ken', + 'city': 'Bridgewater', + 'company': 'GLEIF', + 'first': 'Ken', + 'id': 'EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU', + 'last': 'Knight', + 'state': 'NJ', + 'zip': '08807'} + + org.rem(pre=wil) + d = org.get(pre=wil) + assert d is None + org.replace(pre=wil, data=wild) + + companies = org.values(field="company") + assert companies == ["GLEIF", "HCF"] + + grouped = org.find(field="company", val="HCF") + data = {d["id"]: d for d in grouped} + assert len(data) == 2 + assert joe in data + assert bob in data + + grouped = org.find(field="company", val="GLEIF") + data = {d["id"]: d for d in grouped} + assert len(data) == 4 + assert ken in data + assert jen in data + assert wil in data + assert sal in data + + d = org.get(pre=ken) + assert d == {'address': '28 Williams Ave.', + 'alias': 'ken', + 'city': 'Bridgewater', + 'company': 'GLEIF', + 'first': 'Ken', + 'id': 'EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU', + 'last': 'Knight', + 'state': 'NJ', + 'zip': '08807'} + + # Update the Jen's data signature by signing garbage + nonce = signing.Salter().qb64 + cigar = hby.signator.sign(ser=nonce.encode("utf-8")) + hby.db.ccigs.pin(keys=(jen,), val=cigar) + with pytest.raises(kering.ValidationError): + org.get(pre=jen) + + # This will fail too because it contains Jen + with pytest.raises(kering.ValidationError): + org.find(field="company", val="GLEIF") + + +def test_organizer_imgs(): + + with habbing.openHab(name="test", transferable=True, temp=True) as (hby, hab): + org = organizing.Organizer(hby=hby) + pre = "EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU" + data = bytearray(os.urandom(100000)) + assert len(data) == 100000 + stream = io.BytesIO(data) + + org.setImg(pre, "image/png", stream) + + img = bytearray() + for chunk in org.getImg(pre): + img.extend(chunk) + + assert img == data + + md = org.getImgData(pre=pre) + assert md["type"] == "image/png" + assert md["length"] == len(data) + + pre = "Eo60ITGA69z4jNBU4RsvbgsjfAHFcTM2HVEXea1SvnXk" + md = org.getImgData(pre=pre) + assert md is None + + img = bytearray() + for chunk in org.getImg(pre): + img.extend(chunk) + + assert len(img) == 0 + + +def test_base_organizer(): + """Test BaseOrganizer with custom database configuration""" + joe = "EtyPSuUjLyLdXAtGMrsTt0-ELyWeU8fJcymHiGOfuaSA" + bob = "EuEQX8At31X96iDVpigv-rTdOKvFiWFunbJ1aDfq89IQ" + + joed = {"first": "Joe", "last": "Jury", "address": "9934 Glen Creek St.", "city": "Lawrence", "state": "MA", "zip": "01841", + "company": "HCF", "alias": "joe"} + bobd = {"first": "Bob", "last": "Burns", "address": "37 East Shadow Brook St.", "city": "Sebastian", "state": "FL", + "zip": "32958", "company": "HCF", "alias": "bob"} + + with habbing.openHby(name="test", temp=True) as hby: + # Test BaseOrganizer with contact databases (same as Organizer) + base_org = organizing.BaseOrganizer( + hby=hby, + cigsdb=hby.db.ccigs, + datadb=hby.db.cons, + fielddb=hby.db.cfld, + imgsdb=hby.db.imgs + ) + + # Test basic CRUD operations + base_org.replace(pre=joe, data=joed) + retrieved = base_org.get(pre=joe) + assert retrieved["first"] == "Joe" + assert retrieved["last"] == "Jury" + assert retrieved["id"] == joe + + # Test update + base_org.update(pre=bob, data=bobd) + retrieved = base_org.get(pre=bob) + assert retrieved["first"] == "Bob" + + # Test list + contacts = base_org.list() + assert len(contacts) == 2 + + # Test find + results = base_org.find(field="company", val="HCF") + assert len(results) == 2 + + # Test values + companies = base_org.values(field="company") + assert "HCF" in companies + + # Test set + base_org.set(pre=joe, field="phone", val="555-1234") + retrieved = base_org.get(pre=joe, field="phone") + assert retrieved == "555-1234" + + # Test unset + base_org.unset(pre=joe, field="phone") + retrieved = base_org.get(pre=joe, field="phone") + assert retrieved is None + + # Test rem + base_org.rem(pre=joe) + retrieved = base_org.get(pre=joe) + assert retrieved is None + + +def test_identifier_organizer(): + """Test IdentifierOrganizer with identifier databases""" + aid1 = "EtyPSuUjLyLdXAtGMrsTt0-ELyWeU8fJcymHiGOfuaSA" + aid2 = "EuEQX8At31X96iDVpigv-rTdOKvFiWFunbJ1aDfq89IQ" + + # Sample identifier metadata + id1_data = {"name": "Primary ID", "description": "Main identifier", "role": "controller", + "created": "2025-08-29T00:00:00Z", "status": "active"} + id2_data = {"name": "Secondary ID", "description": "Backup identifier", "role": "witness", + "created": "2025-08-29T01:00:00Z", "status": "active"} + + with habbing.openHby(name="test", temp=True) as hby: + # Test IdentifierOrganizer + id_org = organizing.IdentifierOrganizer(hby=hby) + + # Test basic CRUD operations + id_org.replace(pre=aid1, data=id1_data) + retrieved = id_org.get(pre=aid1) + assert retrieved["name"] == "Primary ID" + assert retrieved["role"] == "controller" + assert retrieved["id"] == aid1 + + # Test update + id_org.update(pre=aid2, data=id2_data) + retrieved = id_org.get(pre=aid2) + assert retrieved["name"] == "Secondary ID" + + # Test list + identifiers = id_org.list() + assert len(identifiers) == 2 + + # Test find by role + controllers = id_org.find(field="role", val="controller") + assert len(controllers) == 1 + assert controllers[0]["name"] == "Primary ID" + + witnesses = id_org.find(field="role", val="witness") + assert len(witnesses) == 1 + assert witnesses[0]["name"] == "Secondary ID" + + # Test values + roles = id_org.values(field="role") + assert "controller" in roles + assert "witness" in roles + + statuses = id_org.values(field="status") + assert "active" in statuses + + # Test set field + id_org.set(pre=aid1, field="version", val="1.0") + retrieved = id_org.get(pre=aid1, field="version") + assert retrieved == "1.0" + + # Test unset field + id_org.unset(pre=aid1, field="version") + retrieved = id_org.get(pre=aid1, field="version") + assert retrieved is None + + # Test rem + id_org.rem(pre=aid1) + retrieved = id_org.get(pre=aid1) + assert retrieved is None + + # Verify only one identifier remains + identifiers = id_org.list() + assert len(identifiers) == 1 + assert identifiers[0]["name"] == "Secondary ID" + + +def test_organizer_vs_identifier_organizer_separation(): + """Test that Organizer and IdentifierOrganizer store data separately""" + contact_id = "EtyPSuUjLyLdXAtGMrsTt0-ELyWeU8fJcymHiGOfuaSA" + identifier_id = "EuEQX8At31X96iDVpigv-rTdOKvFiWFunbJ1aDfq89IQ" + + contact_data = {"first": "John", "last": "Doe", "company": "ACME Corp"} + identifier_data = {"name": "Test ID", "role": "controller", "status": "active"} + + with habbing.openHby(name="test", temp=True) as hby: + # Create both organizers + contact_org = organizing.Organizer(hby=hby) + id_org = organizing.IdentifierOrganizer(hby=hby) + + # Add data to both + contact_org.replace(pre=contact_id, data=contact_data) + id_org.replace(pre=identifier_id, data=identifier_data) + + # Verify contact organizer only has contact data + contacts = contact_org.list() + assert len(contacts) == 1 + assert contacts[0]["first"] == "John" + assert contacts[0]["company"] == "ACME Corp" + + # Verify identifier organizer only has identifier data + identifiers = id_org.list() + assert len(identifiers) == 1 + assert identifiers[0]["name"] == "Test ID" + assert identifiers[0]["role"] == "controller" + + # Verify cross-contamination doesn't occur + assert contact_org.get(pre=identifier_id) is None + assert id_org.get(pre=contact_id) is None + + # Test with same ID in both systems (should be separate) + same_id = "EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU" + contact_org.replace(pre=same_id, data={"name": "Contact Person"}) + id_org.replace(pre=same_id, data={"name": "Identifier Name"}) + + contact_data = contact_org.get(pre=same_id) + id_data = id_org.get(pre=same_id) + + assert contact_data["name"] == "Contact Person" + assert id_data["name"] == "Identifier Name" + # They should be completely separate + assert contact_data != id_data + + +def test_identifier_organizer_imgs(): + """Test IdentifierOrganizer image functionality""" + with habbing.openHab(name="test", transferable=True, temp=True) as (hby, hab): + id_org = organizing.IdentifierOrganizer(hby=hby) + pre = "EFC7f_MEPE5dboc_E4yG15fnpMD34YaU3ue6vnDLodJU" + + # Create test image data + data = bytearray(os.urandom(50000)) + assert len(data) == 50000 + stream = io.BytesIO(data) + + # Test setImg + id_org.setImg(pre, "image/jpeg", stream) + + # Test getImg + img = bytearray() + for chunk in id_org.getImg(pre): + img.extend(chunk) + + assert img == data + + # Test getImgData + md = id_org.getImgData(pre=pre) + assert md["type"] == "image/jpeg" + assert md["length"] == len(data) + + # Test non-existent image + non_existent = "Eo60ITGA69z4jNBU4RsvbgsjfAHFcTM2HVEXea1SvnXk" + md = id_org.getImgData(pre=non_existent) + assert md is None + + img = bytearray() + for chunk in id_org.getImg(non_existent): + img.extend(chunk) + + assert len(img) == 0 + + +def test_base_organizer_inheritance(): + """Test that Organizer and IdentifierOrganizer properly inherit from BaseOrganizer""" + with habbing.openHby(name="test", temp=True) as hby: + contact_org = organizing.Organizer(hby=hby) + id_org = organizing.IdentifierOrganizer(hby=hby) + + # Test inheritance + assert isinstance(contact_org, organizing.BaseOrganizer) + assert isinstance(id_org, organizing.BaseOrganizer) + + # Test that they have all the expected methods + expected_methods = ['update', 'replace', 'set', 'unset', 'rem', 'get', 'list', 'find', 'values', + 'setImg', 'getImgData', 'getImg'] + + for method in expected_methods: + assert hasattr(contact_org, method) + assert hasattr(id_org, method) + assert callable(getattr(contact_org, method)) + assert callable(getattr(id_org, method)) + + # Test that database attributes are set correctly + assert contact_org.cigsdb == hby.db.ccigs + assert contact_org.datadb == hby.db.cons + assert contact_org.fielddb == hby.db.cfld + assert contact_org.imgsdb == hby.db.imgs + + assert id_org.cigsdb == hby.db.icigs + assert id_org.datadb == hby.db.sids + assert id_org.fielddb == hby.db.ifld + assert id_org.imgsdb == hby.db.iimgs