CDS
view release on metacpan or search on metacpan
my $accountHash = shift; die 'wrong type '.ref($accountHash).' for $accountHash' if defined $accountHash && ref $accountHash ne 'CDS::Hash';
my $boxLabel = shift;
my $hash = shift; die 'wrong type '.ref($hash).' for $hash' if defined $hash && ref $hash ne 'CDS::Hash';
my $keyPair = shift; die 'wrong type '.ref($keyPair).' for $keyPair' if defined $keyPair && ref $keyPair ne 'CDS::KeyPair';
return 'This store only handles objects.';
}
sub modify {
my $o = shift;
my $modifications = shift;
my $keyPair = shift; die 'wrong type '.ref($keyPair).' for $keyPair' if defined $keyPair && ref $keyPair ne 'CDS::KeyPair';
return $modifications->executeIndividually($o, $keyPair);
}
# BEGIN AUTOGENERATED
package CDS::Commands::ActorGroup;
sub register {
my $class = shift;
my $cds = shift;
my $help = shift;
my $node000 = CDS::Parser::Node->new(0);
my $node001 = CDS::Parser::Node->new(0);
my $node002 = CDS::Parser::Node->new(0);
my $node003 = CDS::Parser::Node->new(0);
my $node004 = CDS::Parser::Node->new(0);
my $node005 = CDS::Parser::Node->new(0);
my $node006 = CDS::Parser::Node->new(0);
my $node007 = CDS::Parser::Node->new(0);
my $node008 = CDS::Parser::Node->new(0);
my $node009 = CDS::Parser::Node->new(1, {constructor => \&new, function => \&help});
my $node010 = CDS::Parser::Node->new(1, {constructor => \&new, function => \&show});
my $node011 = CDS::Parser::Node->new(0);
my $node012 = CDS::Parser::Node->new(0);
my $node013 = CDS::Parser::Node->new(0);
my $node014 = CDS::Parser::Node->new(1, {constructor => \&new, function => \&joinMember});
my $node015 = CDS::Parser::Node->new(1, {constructor => \&new, function => \&setMember});
my $node016 = CDS::Parser::Node->new(0);
$cds->addArrow($node001, 1, 0, 'show');
$cds->addArrow($node003, 1, 0, 'join');
$cds->addArrow($node004, 1, 0, 'set');
$help->addArrow($node000, 1, 0, 'actor');
$node000->addArrow($node009, 1, 0, 'group');
$node001->addArrow($node002, 1, 0, 'actor');
$node002->addArrow($node010, 1, 0, 'group');
$node003->addArrow($node005, 1, 0, 'member');
$node004->addArrow($node007, 1, 0, 'member');
$node005->addDefault($node006);
$node005->addArrow($node011, 1, 0, 'ACTOR', \&collectActor);
$node006->addArrow($node006, 1, 0, 'ACCOUNT', \&collectAccount);
$node006->addArrow($node014, 1, 1, 'ACCOUNT', \&collectAccount);
$node007->addDefault($node008);
$node008->addArrow($node008, 1, 0, 'ACTOR', \&collectActor1);
$node008->addArrow($node013, 1, 0, 'ACTOR', \&collectActor1);
$node011->addArrow($node012, 1, 0, 'on');
$node012->addArrow($node014, 1, 0, 'STORE', \&collectStore);
$node013->addArrow($node015, 1, 0, 'active', \&collectActive);
$node013->addArrow($node015, 1, 0, 'backup', \&collectBackup);
$node013->addArrow($node015, 1, 0, 'idle', \&collectIdle);
$node013->addArrow($node015, 1, 0, 'revoked', \&collectRevoked);
$node014->addArrow($node016, 1, 0, 'and');
$node016->addDefault($node005);
}
sub collectAccount {
my $o = shift;
my $label = shift;
my $value = shift;
push @{$o->{accountTokens}}, $value;
}
sub collectActive {
my $o = shift;
my $label = shift;
my $value = shift;
$o->{status} = 'active';
}
sub collectActor {
my $o = shift;
my $label = shift;
my $value = shift;
$o->{actorHash} = $value;
}
sub collectActor1 {
my $o = shift;
my $label = shift;
my $value = shift;
push @{$o->{actorHashes}}, $value;
}
sub collectBackup {
my $o = shift;
my $label = shift;
my $value = shift;
$o->{status} = 'backup';
}
sub collectIdle {
my $o = shift;
my $label = shift;
my $value = shift;
$o->{status} = 'idle';
}
sub collectRevoked {
my $o = shift;
my $label = shift;
my $value = shift;
$o->{status} = 'revoked';
}
sub collectStore {
my $o = shift;
my $label = shift;
my $value = shift;
push @{$o->{accountTokens}}, CDS::AccountToken->new($value, $o->{actorHash});
delete $o->{actorHash};
}
sub new {
my $class = shift;
my $actor = shift;
bless {actor => $actor, ui => $actor->ui} }
# END AUTOGENERATED
# HTML FOLDER NAME actor-group
# HTML TITLE Actor group
sub help {
my $o = shift;
my $cmd = shift;
my $ui = $o->{ui};
$ui->space;
$ui->command('cds show actor group');
$ui->p('Shows all members of our actor group and the entrusted keys.');
$ui->space;
$ui->command('cds join ACCOUNT*');
$ui->command('cds join ACTOR on STORE');
$ui->p('Adds a member to our actor group. To complete the association, the new member must join us, too.');
$ui->space;
$ui->command('cds set member ACTOR* active');
$ui->command('cds set member ACTOR* backup');
$ui->command('cds set member ACTOR* idle');
$ui->command('cds set member ACTOR* revoked');
$ui->p('Changes the status of a member to one of the following:');
$ui->p($ui->bold('Active members'), ' share the group data among themselves, and are advertised to receive messages.');
$ui->p($ui->bold('Backup members'), ' share the group data (like active members), but are publicly advertised as not processing messages (like idle members). This is suitable for backup actors.');
$ui->p($ui->bold('Idle members'), ' are part of the group, but advertised as not processing messages. They generally do not have the latest group data, and may have no group data at all. Idle members may reactivate themselves, or get reactivated by ...
$ui->p($ui->bold('Revoked members'), ' have explicitly been removed from the group, e.g. because their private key (or device) got lost. Revoked members can be reactivated by any active member of the group.');
$ui->p('Note that changing the status does not start or stop the corresponding actor, but just change how it is regarded by others. The status of each member should reflect its actual behavior.');
$ui->space;
$ui->p('After modifying the actor group members, you should "cds announce" yourself to publish the changes.');
$ui->space;
}
sub show {
my $o = shift;
my $cmd = shift;
my $hasMembers = 0;
for my $actorSelector ($o->{actor}->actorGroupSelector->children) {
my $record = $actorSelector->record;
my $hash = $record->child('hash')->hashValue // next;
next if substr($hash->bytes, 0, length $actorSelector->label) ne $actorSelector->label;
my $storeUrl = $record->child('store')->textValue;
my $revisionText = $o->{ui}->niceDateTimeLocal($actorSelector->revision);
$o->{ui}->line($o->{ui}->gray($revisionText), ' ', $o->coloredType7($actorSelector), ' ', $hash->hex, ' on ', $storeUrl);
$hasMembers = 1;
}
return if $hasMembers;
$o->{ui}->line($o->{ui}->blue('(just you)'));
}
sub type {
my $o = shift;
my $actorSelector = shift; die 'wrong type '.ref($actorSelector).' for $actorSelector' if defined $actorSelector && ref $actorSelector ne 'CDS::Selector';
my $groupData = $actorSelector->child('group data')->isSet;
my $active = $actorSelector->child('active')->isSet;
my $revoked = $actorSelector->child('revoked')->isSet;
return
$revoked ? 'revoked' :
$active && $groupData ? 'active' :
$groupData ? 'backup' :
$active ? 'weird' :
'idle';
}
sub coloredType7 {
my $o = shift;
my $actorSelector = shift; die 'wrong type '.ref($actorSelector).' for $actorSelector' if defined $actorSelector && ref $actorSelector ne 'CDS::Selector';
my $groupData = $actorSelector->child('group data')->isSet;
my $active = $actorSelector->child('active')->isSet;
my $revoked = $actorSelector->child('revoked')->isSet;
return
$revoked ? $o->{ui}->red('revoked') :
$active && $groupData ? $o->{ui}->green('active ') :
$groupData ? $o->{ui}->blue('backup ') :
$active ? $o->{ui}->orange('weird ') :
$o->{ui}->gray('idle ');
}
sub joinMember {
my $o = shift;
my $cmd = shift;
$o->{accountTokens} = [];
$cmd->collect($o);
my $selector = $o->{actor}->actorGroupSelector;
for my $accountToken (@{$o->{accountTokens}}) {
my $actorHash = $accountToken->actorHash;
# Get the public key
my ($publicKey, $invalidReason, $storeError) = $o->{actor}->keyPair->getPublicKey($actorHash, $accountToken->cliStore);
if (defined $storeError) {
$o->{ui}->pRed('Unable to get the public key of ', $actorHash->hex, ' from ', $accountToken->cliStore->url, ': ', $storeError);
next;
}
if (defined $invalidReason) {
$o->{ui}->pRed('Unable to get the public key of ', $actorHash->hex, ' from ', $accountToken->cliStore->url, ': ', $invalidReason);
next;
}
# Add or update this member
my $label = substr($actorHash->bytes, 0, 16);
my $actorSelector = $selector->child($label);
my $wasMember = $actorSelector->isSet;
my $record = CDS::Record->new;
$record->add('hash')->addHash($actorHash);
$record->add('store')->addText($accountToken->cliStore->url);
$actorSelector->set($record);
$actorSelector->addObject($publicKey->hash, $publicKey->object);
$o->{ui}->pGreen('Updated ', $o->type($actorSelector), ' member ', $actorHash->hex, '.') if $wasMember;
$o->{ui}->pGreen('Added ', $actorHash->hex, ' as ', $o->type($actorSelector), ' member of the actor group.') if ! $wasMember;
}
# Save
$o->{actor}->saveOrShowError;
}
sub setFlag {
my $o = shift;
my $actorSelector = shift; die 'wrong type '.ref($actorSelector).' for $actorSelector' if defined $actorSelector && ref $actorSelector ne 'CDS::Selector';
my $label = shift;
my $value = shift;
my $child = $actorSelector->child($label);
if ($value) {
$child->setBoolean(1);
} else {
$child->clear;
}
}
sub setMember {
my $o = shift;
my $cmd = shift;
$o->{actorHashes} = [];
$cmd->collect($o);
my $selector = $o->{actor}->actorGroupSelector;
for my $actorHash (@{$o->{actorHashes}}) {
my $label = substr($actorHash->bytes, 0, 16);
my $actorSelector = $selector->child($label);
my $record = $actorSelector->record;
my $hash = $record->child('hash')->hashValue;
if (! $hash) {
$o->{ui}->pRed($actorHash->hex, ' is not a member of our actor group.');
next;
}
$o->setFlag($actorSelector, 'group data', $o->{status} eq 'active' || $o->{status} eq 'backup');
$o->setFlag($actorSelector, 'active', $o->{status} eq 'active');
$o->setFlag($actorSelector, 'revoked', $o->{status} eq 'revoked');
$o->{ui}->pGreen($actorHash->hex, ' is now ', $o->type($actorSelector), '.');
}
# Save
$o->{actor}->saveOrShowError;
}
# BEGIN AUTOGENERATED
package CDS::Commands::Announce;
sub register {
my $class = shift;
my $cds = shift;
my $help = shift;
my $node000 = CDS::Parser::Node->new(1, {constructor => \&new, function => \&help});
my $node001 = CDS::Parser::Node->new(1, {constructor => \&new, function => \&announceMe});
my $node002 = CDS::Parser::Node->new(1);
my $node003 = CDS::Parser::Node->new(0);
my $node004 = CDS::Parser::Node->new(0);
my $node005 = CDS::Parser::Node->new(0);
my $node006 = CDS::Parser::Node->new(0);
my $node007 = CDS::Parser::Node->new(0);
my $node008 = CDS::Parser::Node->new(0);
my $node009 = CDS::Parser::Node->new(0);
my $node010 = CDS::Parser::Node->new(0);
my $node011 = CDS::Parser::Node->new(0);
my $node012 = CDS::Parser::Node->new(0);
my $node013 = CDS::Parser::Node->new(1);
my $node014 = CDS::Parser::Node->new(0);
my $node015 = CDS::Parser::Node->new(0);
my $node016 = CDS::Parser::Node->new(0);
my $node017 = CDS::Parser::Node->new(0, {constructor => \&new, function => \&announceKeyPair});
$cds->addArrow($node001, 1, 0, 'announce');
$cds->addArrow($node002, 1, 0, 'announce');
$help->addArrow($node000, 1, 0, 'announce');
$node002->addArrow($node003, 1, 0, 'KEYPAIR', \&collectKeypair);
$node003->addArrow($node004, 1, 0, 'on');
$node004->addArrow($node005, 1, 0, 'STORE', \&collectStore);
$node005->addArrow($node006, 1, 0, 'without');
$node005->addArrow($node007, 1, 0, 'with');
$node005->addDefault($node017);
$node006->addArrow($node006, 1, 0, 'ACTOR', \&collectActor);
$node006->addArrow($node017, 1, 0, 'ACTOR', \&collectActor);
$node007->addArrow($node008, 1, 0, 'active', \&collectActive);
$node007->addArrow($node008, 1, 0, 'entrusted', \&collectEntrusted);
$node007->addArrow($node008, 1, 0, 'idle', \&collectIdle);
$node007->addArrow($node008, 1, 0, 'revoked', \&collectRevoked);
$node008->addDefault($node009);
$node008->addDefault($node010);
$node009->addArrow($node009, 1, 0, 'ACCOUNT', \&collectAccount);
$node009->addArrow($node013, 1, 1, 'ACCOUNT', \&collectAccount);
$node010->addArrow($node010, 1, 0, 'ACTOR', \&collectActor1);
$node010->addArrow($node011, 1, 0, 'ACTOR', \&collectActor1);
$node011->addArrow($node012, 1, 0, 'on');
$node012->addArrow($node013, 1, 0, 'STORE', \&collectStore1);
$node013->addArrow($node014, 1, 0, 'but');
$node013->addArrow($node016, 1, 0, 'and');
( run in 1.530 second using v1.01-cache-2.11-cpan-39bf76dae61 )