Skip to content

Commit

Permalink
Merge pull request #4868 from cyrusimap/jmap_copy_state
Browse files Browse the repository at this point in the history
Foo/copy: add support for if[From]InState, destroyFromIfInState, old/newState
  • Loading branch information
ksmurchison committed Mar 27, 2024
2 parents d8da38b + 39d24ed commit 8b8414b
Show file tree
Hide file tree
Showing 9 changed files with 518 additions and 27 deletions.
109 changes: 109 additions & 0 deletions cassandane/tiny-tests/JMAPCalendars/calendarevent_copy_state
@@ -0,0 +1,109 @@
#!perl
use Cassandane::Tiny;

sub test_calendarevent_copy_state
:needs_component_jmap
{
my ($self) = @_;
my $jmap = $self->{jmap};
my $caldav = $self->{caldav};
my $admintalk = $self->{adminstore}->get_client();
my $service = $self->{instance}->get_service("http");

xlog $self, "create shared accounts";
$admintalk->create("user.other");

my $othercaldav = Net::CalDAVTalk->new(
user => "other",
password => 'pass',
host => $service->host(),
port => $service->port(),
scheme => 'http',
url => '/',
expandurl => 1,
);

$admintalk->setacl('user.other', admin => 'lrswipkxtecdan');
$admintalk->setacl('user.other', other => 'lrswipkxtecdn');

xlog $self, "create source calendar";
my $srcCalendarId = $caldav->NewCalendar({name => 'Source Calendar'});
$self->assert_not_null($srcCalendarId);

xlog $self, "create destination calendar";
my $dstCalendarId = $othercaldav->NewCalendar({name => 'Destination Calendar'});
$self->assert_not_null($dstCalendarId);

xlog $self, "share calendar";
$admintalk->setacl("user.other.#calendars.$dstCalendarId", "cassandane" => 'lrswipkxtecdn') or die;

my $event = {
calendarIds => {
$srcCalendarId => JSON::true,
},
"uid" => "58ADE31-custom-UID",
"title"=> "foo",
"start"=> "2015-11-07T09:00:00",
"duration"=> "PT5M",
"sequence"=> 42,
"timeZone"=> "Etc/UTC",
"showWithoutTime"=> JSON::false,
"locale" => "en",
"status" => "tentative",
"description"=> "",
"freeBusyStatus"=> "busy",
"participants" => undef,
"alerts"=> undef,
};

xlog $self, "create event";
my $res = $jmap->CallMethods([
['CalendarEvent/set', {
create => {"1" => $event}
}, "R1"],
['CalendarEvent/get', {
accountId => 'other',
ids => ['foo'], # Just fetching current state for 'other'
}, 'R2'],
]);
$self->assert_not_null($res->[0][1]{created});
my $eventId = $res->[0][1]{created}{"1"}{id};
my $fromState = $res->[0][1]->{newState};
$self->assert_not_null($fromState);
my $state = $res->[1][1]->{state};
$self->assert_not_null($state);

xlog $self, "move event";
$res = $jmap->CallMethods([
['CalendarEvent/copy', {
fromAccountId => 'cassandane',
accountId => 'other',
ifFromInState => $fromState,
ifInState => $state,
create => {
1 => {
id => $eventId,
calendarIds => {
$dstCalendarId => JSON::true,
},
},
},
onSuccessDestroyOriginal => JSON::true,
destroyFromIfInState => $fromState,
}, "R1"],
['CalendarEvent/get', {
accountId => 'other',
ids => ['#1'],
properties => ['title'],
}, 'R2'],
]);
$self->assert_not_null($res->[0][1]{created});
my $copiedEventId = $res->[0][1]{created}{"1"}{id};
my $oldState = $res->[0][1]->{oldState};
$self->assert_str_equals($oldState, $state);
my $newState = $res->[0][1]->{newState};
$self->assert_not_null($newState);
$self->assert_str_equals('CalendarEvent/set', $res->[1][0]);
$self->assert_str_equals($eventId, $res->[1][1]{destroyed}[0]);
$self->assert_str_equals('foo', $res->[2][1]{list}[0]{title});
}
83 changes: 83 additions & 0 deletions cassandane/tiny-tests/JMAPContacts/card_copy_state
@@ -0,0 +1,83 @@
#!perl
use Cassandane::Tiny;

sub test_card_copy_state
:needs_component_jmap :needs_dependency_icalvcard
{
my ($self) = @_;
my $jmap = $self->{jmap};
my $carddav = $self->{carddav};
my $admintalk = $self->{adminstore}->get_client();
my $service = $self->{instance}->get_service("http");

xlog $self, "create shared account";
$admintalk->create("user.other");

my $othercarddav = Net::CardDAVTalk->new(
user => "other",
password => 'pass',
host => $service->host(),
port => $service->port(),
scheme => 'http',
url => '/',
expandurl => 1,
);

xlog $self, "share addressbook";
$admintalk->setacl("user.other.#addressbooks.Default",
"cassandane" => 'lrswipkxtecdn') or die;

my $card = {
"addressBookId" => "Default",
name => { full => "foo bar" },
};

xlog $self, "create card";
$res = $jmap->CallMethods([
['ContactCard/set', {
create => {"1" => $card}
}, "R1"],
['ContactCard/get', {
accountId => 'other',
ids => ['foo'], # Just fetching current state for 'other'
}, 'R2'],
]);
$self->assert_not_null($res->[0][1]{created});
my $cardId = $res->[0][1]{created}{"1"}{id};
my $fromState = $res->[0][1]->{newState};
$self->assert_not_null($fromState);
my $state = $res->[1][1]->{state};
$self->assert_not_null($state);

xlog $self, "move card";
$res = $jmap->CallMethods([
['ContactCard/copy', {
fromAccountId => 'cassandane',
accountId => 'other',
ifFromInState => $fromState,
ifInState => $state,
create => {
1 => {
id => $cardId,
addressBookId => "Default",
},
},
onSuccessDestroyOriginal => JSON::true,
destroyFromIfInState => $fromState,
}, "R1"],
['ContactCard/get', {
accountId => 'other',
ids => ['#1'],
properties => ['name'],
}, 'R2'],
]);
$self->assert_not_null($res->[0][1]{created});
my $copiedCardId = $res->[0][1]{created}{"1"}{id};
my $oldState = $res->[0][1]->{oldState};
$self->assert_str_equals($oldState, $state);
my $newState = $res->[0][1]->{newState};
$self->assert_not_null($newState);
$self->assert_str_equals('ContactCard/set', $res->[1][0]);
$self->assert_str_equals($cardId, $res->[1][1]{destroyed}[0]);
$self->assert_str_equals('foo bar', $res->[2][1]{list}[0]{name}{full});
}
84 changes: 84 additions & 0 deletions cassandane/tiny-tests/JMAPContacts/contact_copy_state
@@ -0,0 +1,84 @@
#!perl
use Cassandane::Tiny;

sub test_contact_copy_state
:needs_component_jmap
{
my ($self) = @_;
my $jmap = $self->{jmap};
my $carddav = $self->{carddav};
my $admintalk = $self->{adminstore}->get_client();
my $service = $self->{instance}->get_service("http");

xlog $self, "create shared account";
$admintalk->create("user.other");

my $othercarddav = Net::CardDAVTalk->new(
user => "other",
password => 'pass',
host => $service->host(),
port => $service->port(),
scheme => 'http',
url => '/',
expandurl => 1,
);

xlog $self, "share addressbook";
$admintalk->setacl("user.other.#addressbooks.Default",
"cassandane" => 'lrswipkxtecdn') or die;

my $card = {
"addressbookId" => "Default",
"firstName"=> "foo",
"lastName"=> "bar",
};

xlog $self, "create card";
$res = $jmap->CallMethods([
['Contact/set', {
create => {"1" => $card}
}, "R1"],
['Contact/get', {
accountId => 'other',
ids => ['foo'], # Just fetching current state for 'other'
}, 'R2'],
]);
$self->assert_not_null($res->[0][1]{created});
my $cardId = $res->[0][1]{created}{"1"}{id};
my $fromState = $res->[0][1]->{newState};
$self->assert_not_null($fromState);
my $state = $res->[1][1]->{state};
$self->assert_not_null($state);

xlog $self, "move card";
$res = $jmap->CallMethods([
['Contact/copy', {
fromAccountId => 'cassandane',
accountId => 'other',
ifFromInState => $fromState,
ifInState => $state,
create => {
1 => {
id => $cardId,
addressbookId => "Default",
},
},
onSuccessDestroyOriginal => JSON::true,
destroyFromIfInState => $fromState,
}, "R1"],
['Contact/get', {
accountId => 'other',
ids => ['#1'],
properties => ['firstName'],
}, 'R2'],
]);
$self->assert_not_null($res->[0][1]{created});
my $copiedCardId = $res->[0][1]{created}{"1"}{id};
my $oldState = $res->[0][1]->{oldState};
$self->assert_str_equals($oldState, $state);
my $newState = $res->[0][1]->{newState};
$self->assert_not_null($newState);
$self->assert_str_equals('Contact/set', $res->[1][0]);
$self->assert_str_equals($cardId, $res->[1][1]{destroyed}[0]);
$self->assert_str_equals('foo', $res->[2][1]{list}[0]{firstName});
}
90 changes: 90 additions & 0 deletions cassandane/tiny-tests/JMAPEmail/email_copy_state
@@ -0,0 +1,90 @@
#!perl
use Cassandane::Tiny;

sub test_email_copy_state
:needs_component_jmap
{
my ($self) = @_;
my $jmap = $self->{jmap};
my $imaptalk = $self->{store}->get_client();
my $admintalk = $self->{adminstore}->get_client();

xlog $self, "Create user and share mailbox";
$self->{instance}->create_user("other");
$admintalk->setacl("user.other", "cassandane", "lrsiwntex") or die;

my $srcInboxId = $self->getinbox()->{id};
$self->assert_not_null($srcInboxId);

my $dstInboxId = $self->getinbox({accountId => 'other'})->{id};
$self->assert_not_null($dstInboxId);

xlog $self, "create email";
my $res = $jmap->CallMethods([
['Email/set', {
create => {
1 => {
mailboxIds => {
$srcInboxId => JSON::true,
},
keywords => {
'foo' => JSON::true,
},
subject => 'hello',
bodyStructure => {
type => 'text/plain',
partId => 'part1',
},
bodyValues => {
part1 => {
value => 'world',
}
},
},
},
}, 'R1'],
['Email/get', {
accountId => 'other',
ids => ['foo'], # Just fetching current state for 'other'
}, 'R2']
]);
my $emailId = $res->[0][1]->{created}{1}{id};
$self->assert_not_null($emailId);
my $fromState = $res->[0][1]->{newState};
$self->assert_not_null($fromState);
my $state = $res->[1][1]->{state};
$self->assert_not_null($state);

xlog $self, "move email";
$res = $jmap->CallMethods([
['Email/copy', {
fromAccountId => 'cassandane',
accountId => 'other',
ifFromInState => $fromState,
ifInState => $state,
create => {
1 => {
id => $emailId,
mailboxIds => {
$dstInboxId => JSON::true,
},
},
},
onSuccessDestroyOriginal => JSON::true,
destroyFromIfInState => $fromState,
}, 'R1'],
['Email/get', {
accountId => 'other',
ids => ['#1'],
properties => ['mailboxIds'],
}, 'R2']
]);
$self->assert_not_null($res->[0][1]{created});
my $oldState = $res->[0][1]->{oldState};
$self->assert_str_equals($oldState, $state);
my $newState = $res->[0][1]->{newState};
$self->assert_not_null($newState);
$self->assert_str_equals('Email/set', $res->[1][0]);
$self->assert_str_equals($emailId, $res->[1][1]{destroyed}[0]);
$self->assert_not_null($res->[2][1]{list}[0]{mailboxIds}{$dstInboxId});
}

0 comments on commit 8b8414b

Please sign in to comment.