[Bps-public-commit] rt-extension-rest2 branch, master, updated. 1.04-16-g2efee24

? sunnavy sunnavy at bestpractical.com
Mon Nov 19 14:30:45 EST 2018


The branch, master has been updated
       via  2efee24a93488db7f817225504cf9d59d67b3fca (commit)
       via  5ef01fa077200b0080f3379cc84384208b84cf12 (commit)
       via  592753c73865c67df9ae7b6fd6c5a0152f248117 (commit)
       via  ff147579f0dd4b959f078cf7164d41031a04fc4f (commit)
       via  676c261d459fe543386595711c99fe74d4f76efd (commit)
       via  72dcdf0a1306bdc8fec9f3cf594baba57a5bebf2 (commit)
       via  520e6646db181de4c001ff232f5e73975eff9964 (commit)
       via  8c6d34b809aea162f54fa0a162ac1c8d20c94098 (commit)
       via  dc173e739d8683df34c49323060f9631086c9a02 (commit)
       via  a1b14989536a57258a09784ebc1c5ebd26a34cff (commit)
       via  a0bf988b9034eef920df7ee20d568040da7ef626 (commit)
       via  4092a6124a49276f7cbfaba01c3daf40c2857e80 (commit)
       via  40968cf0c08030b51aca18c6f4fd45231b47d061 (commit)
       via  42110ddd4daed62ddc15ce2da930df87a0756ffb (commit)
       via  353de0d045aa502e85cbe74797a00b238ecabd57 (commit)
       via  6caf780aa31ea2bfecfe88bfd79a34c9cbde5527 (commit)
      from  5e06368f1e1a13fab452b1d7c17f9c72a8453b91 (commit)

Summary of changes:
 MANIFEST                                           |   4 +
 README                                             |  60 ++++-
 lib/RT/Extension/REST2.pm                          |  62 ++++-
 lib/RT/Extension/REST2/Resource/Group.pm           |  40 +++
 lib/RT/Extension/REST2/Resource/GroupMembers.pm    | 152 +++++++++++
 lib/RT/Extension/REST2/Resource/Record/Writable.pm |  21 +-
 lib/RT/Extension/REST2/Resource/User.pm            |  11 +
 lib/RT/Extension/REST2/Resource/UserGroups.pm      | 120 +++++++++
 t/group-members.t                                  | 288 +++++++++++++++++++++
 t/ticket-customroles.t                             |   2 +-
 t/ticket-watchers.t                                |   2 +-
 t/user-memberships.t                               | 119 +++++++++
 12 files changed, 872 insertions(+), 9 deletions(-)
 create mode 100644 lib/RT/Extension/REST2/Resource/GroupMembers.pm
 create mode 100644 lib/RT/Extension/REST2/Resource/UserGroups.pm
 create mode 100644 t/group-members.t
 create mode 100644 t/user-memberships.t

- Log -----------------------------------------------------------------
commit 8c6d34b809aea162f54fa0a162ac1c8d20c94098
Author: gibus <gibus at easter-eggs.com>
Date:   Thu Sep 20 15:17:05 2018 +0200

    Add tests for group members endpoints

diff --git a/t/group-members.t b/t/group-members.t
new file mode 100644
index 0000000..ee33050
--- /dev/null
+++ b/t/group-members.t
@@ -0,0 +1,275 @@
+use strict;
+use warnings;
+use lib 't/lib';
+use RT::Extension::REST2::Test tests => undef;
+use Test::Warn;
+use Test::Deep;
+
+my $mech = RT::Extension::REST2::Test->mech;
+
+my $auth = RT::Extension::REST2::Test->authorization_header;
+my $rest_base_path = '/REST/2.0';
+my $user = RT::Extension::REST2::Test->user;
+
+my $group1 = RT::Group->new(RT->SystemUser);
+my ($ok, $msg) = $group1->CreateUserDefinedGroup(Name => 'Group 1');
+ok($ok, $msg);
+
+my $user1 = RT::User->new(RT->SystemUser);
+($ok, $msg) = $user1->Create(Name => 'User 1');
+ok($ok, $msg);
+
+my $user2 = RT::User->new(RT->SystemUser);
+($ok, $msg) = $user2->Create(Name => 'User 2');
+ok($ok, $msg);
+
+# Group creation
+my ($group2_url, $group2_id);
+{
+    my $payload = {
+        Name => 'Group 2',
+    };
+
+    # Rights Test - No AdminGroup
+    my $res = $mech->post_json("$rest_base_path/group",
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 403, 'Cannot create group without AdminGroup right');
+
+    # Rights Test - With AdminGroup
+    $user->PrincipalObj->GrantRight(Right => 'AdminGroup');
+    $res = $mech->post_json("$rest_base_path/group",
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 201, 'Create group with AdminGroup right');
+    ok($group2_url = $res->header('location'), 'Created group url');
+    ok(($group2_id) = $group2_url =~ qr[/group/(\d+)], 'Created group id');
+}
+
+my $group2 = RT::Group->new(RT->SystemUser);
+$group2->Load($group2_id);
+
+# Group disabling
+{
+    # Rights Test - No AdminGroup
+    $user->PrincipalObj->RevokeRight(Right => 'AdminGroup');
+    my $res = $mech->delete($group2_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 403, 'Cannot disable group without AdminGroup right');
+
+    # Rights Test - With AdminGroup, no SeeGroup
+    $user->PrincipalObj->GrantRight(Right => 'AdminGroup', Object => $group2);
+    $res = $mech->delete($group2_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 403, 'Cannot disable group without SeeGroup right');
+
+    # Rights Test - With AdminGroup, no SeeGroup
+    $user->PrincipalObj->GrantRight(Right => 'SeeGroup', Object => $group2);
+    $res = $mech->delete($group2_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 204, 'Disable group with AdminGroup & SeeGroup rights');
+
+    is($group2->Disabled, 1, "Group disabled");
+}
+
+# Group enabling
+{
+    my $payload = {
+        Disabled => 0,
+    };
+
+    # Rights Test - No AdminGroup
+    $user->PrincipalObj->RevokeRight(Right => 'AdminGroup', Object => $group2);
+    $user->PrincipalObj->RevokeRight(Right => 'SeeGroup', Object => $group2);
+
+    my $res = $mech->put_json($group2_url,
+        $payload,
+        'Authorization' => $auth);
+    is($res->code, 403, 'Cannot enable group without AdminGroup right');
+
+    # Rights Test - With AdminGroup, no SeeGroup
+    $user->PrincipalObj->GrantRight(Right => 'AdminGroup', Object => $group2);
+    $res = $mech->put_json($group2_url,
+        $payload,
+        'Authorization' => $auth);
+    is($res->code, 403, 'Cannot enable group without SeeGroup right');
+
+    # Rights Test - With AdminGroup, no SeeGroup
+    $user->PrincipalObj->GrantRight(Right => 'SeeGroup', Object => $group2);
+    $res = $mech->put_json($group2_url,
+        $payload,
+        'Authorization' => $auth);
+    is($res->code, 200, 'Enable group with AdminGroup & SeeGroup rights');
+    is_deeply($mech->json_response, ['Group enabled']);
+
+    is($group2->Disabled, 0, "Group enabled");
+}
+
+my $group1_id = $group1->id;
+(my $group1_url = $group2_url) =~ s/$group2_id/$group1_id/;
+$user->PrincipalObj->GrantRight(Right => 'SeeGroup', Object => $group1);
+
+# Members addition
+{
+    my $payload = [
+        $user1->id,
+        $group2->id,
+        $user1->id + 666,
+    ];
+
+    # Rights Test - No AdminGroupMembership
+    my $res = $mech->put_json($group1_url . '/members',
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 403, 'Cannot add members to group without AdminGroupMembership right');
+
+    # Rights Test - With AdminGroupMembership
+    $user->PrincipalObj->GrantRight(Right => 'AdminGroupMembership', Object => $group1);
+    $res = $mech->put_json($group1_url . '/members',
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'Add members to group with AdminGroupMembership right');
+    is_deeply($mech->json_response, [
+        "Member added: " . $user1->Name,
+        "Member added: " . $group2->Name,
+        "Couldn't find that principal",
+    ], 'Two members added, bad principal rejected');
+    my $members1 = $group1->MembersObj;
+    is($members1->Count, 2, 'Two members added');
+    my $member = $members1->Next;
+    is($member->MemberObj->PrincipalType, 'User', 'User added as member');
+    is($member->MemberObj->id, $user1->id, 'Accurate user added as member');
+    $member = $members1->Next;
+    is($member->MemberObj->PrincipalType, 'Group', 'Group added as member');
+    is($member->MemberObj->id, $group2->id, 'Accurate group added as member');
+}
+
+# Members list
+{
+    # Add user to subgroup
+    $group2->AddMember($user2->id);
+
+    # Direct members
+    my $res = $mech->get($group1_url . '/members',
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'List direct members');
+
+    my $content = $mech->json_response;
+    is($content->{total}, 2, 'Two direct members');
+    is($content->{items}->[0]->{type}, 'user', 'User member');
+    is($content->{items}->[0]->{id}, $user1->id, 'Accurate user member');
+    is($content->{items}->[1]->{type}, 'group', 'Group member');
+    is($content->{items}->[1]->{id}, $group2->id, 'Accurate group member');
+
+    # Deep members
+    $res = $mech->get($group1_url . '/members?recursively=1',
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'List deep members');
+
+    $content = $mech->json_response;
+    is($content->{total}, 4, 'Four deep members');
+
+    cmp_deeply(
+        $content->{items},
+        bag({   type => 'group',
+                id   => $group1->id,
+                _url => re(qr{$rest_base_path/group/@{[$group1->id]}}),
+            },
+            {   type => 'group',
+                id   => $group2->id,
+                _url => re(qr{$rest_base_path/group/@{[$group2->id]}}),
+            },
+            {   type => 'user',
+                id   => $user1->id,
+                _url => re(qr{$rest_base_path/user/@{[$user1->id]}}),
+            },
+            {   type => 'user',
+                id   => $user2->id,
+                _url => re(qr{$rest_base_path/user/@{[$user2->id]}}),
+            }
+        ),
+        'Four deep member items'
+    );
+
+    # Direct user members
+    $res = $mech->get($group1_url . '/members?groups=0',
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'List direct user members');
+
+    $content = $mech->json_response;
+    is($content->{total}, 1, 'One direct user member');
+    is($content->{items}->[0]->{type}, 'user', 'Direct user member');
+    is($content->{items}->[0]->{id}, $user1->id, 'Accurate direct user member');
+
+    # Recursive user members
+    $res = $mech->get($group1_url . '/members?groups=0&recursively=1',
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'List recursive user members');
+
+    $content = $mech->json_response;
+    is($content->{total}, 2, 'Two recursive user members');
+    is($content->{items}->[0]->{type}, 'user', 'First recursive user member');
+    is($content->{items}->[0]->{id}, $user1->id, 'First accurate recursive user member');
+    is($content->{items}->[1]->{type}, 'user', 'Second recursive user member');
+    is($content->{items}->[1]->{id}, $user2->id, 'Second accurate recursive user member');
+
+    # Direct group members
+    $res = $mech->get($group1_url . '/members?users=0',
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'List direct group members');
+
+    $content = $mech->json_response;
+    is($content->{total}, 1, 'One direct group member');
+    is($content->{items}->[0]->{type}, 'group', 'Direct group member');
+    is($content->{items}->[0]->{id}, $group2->id, 'Accurate direct group member');
+
+    # Recursive group members
+    $res = $mech->get($group1_url . '/members?users=0&recursively=1',
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'List recursive group members');
+
+    $content = $mech->json_response;
+    is($content->{total}, 2, 'Two recursive group members');
+    is($content->{items}->[0]->{type}, 'group', 'First recursive group member');
+    is($content->{items}->[0]->{id}, $group1->id, 'First accurate recursive group member');
+    is($content->{items}->[1]->{type}, 'group', 'Second recursive group member');
+    is($content->{items}->[1]->{id}, $group2->id, 'Second accurate recursive group member');
+}
+
+# Members removal
+{
+    my $res = $mech->delete($group1_url . '/member/' . $user1->id,
+        'Authorization' => $auth,
+    );
+    is($res->code, 204, 'Remove member');
+    my $members1 = $group1->MembersObj;
+    is($members1->Count, 1, 'One member removed');
+    my $member = $members1->Next;
+    is($member->MemberObj->PrincipalType, 'Group', 'Group remaining member');
+    is($member->MemberObj->id, $group2->id, 'Accurate remaining member');
+}
+
+# All members removal
+{
+    my $res = $mech->delete($group1_url . '/members',
+        'Authorization' => $auth,
+    );
+    is($res->code, 204, 'Remove all members');
+    my $members1 = $group1->MembersObj;
+    is($members1->Count, 0, 'All members removed');
+}
+
+done_testing;

commit 520e6646db181de4c001ff232f5e73975eff9964
Author: gibus <gibus at easter-eggs.com>
Date:   Thu Sep 20 17:34:05 2018 +0200

    Add tests for user memberships endpoints

diff --git a/t/user-memberships.t b/t/user-memberships.t
new file mode 100644
index 0000000..47f969a
--- /dev/null
+++ b/t/user-memberships.t
@@ -0,0 +1,105 @@
+use strict;
+use warnings;
+use lib 't/lib';
+use RT::Extension::REST2::Test tests => undef;
+use Test::Warn;
+
+my $mech = RT::Extension::REST2::Test->mech;
+
+my $auth = RT::Extension::REST2::Test->authorization_header;
+my $rest_base_path = '/REST/2.0';
+my $user = RT::Extension::REST2::Test->user;
+
+my $group1 = RT::Group->new(RT->SystemUser);
+my ($ok, $msg) = $group1->CreateUserDefinedGroup(Name => 'Group 1');
+ok($ok, $msg);
+
+my $group2 = RT::Group->new(RT->SystemUser);
+($ok, $msg) = $group2->CreateUserDefinedGroup(Name => 'Group 2');
+ok($ok, $msg);
+
+($ok, $msg) = $group1->AddMember($group2->id);
+ok($ok, $msg);
+
+# Membership addition
+{
+    my $payload = [ $group2->id ];
+
+    # Rights Test - No ModifyOwnMembership
+    my $res = $mech->put_json("$rest_base_path/user/" . $user->id . '/groups',
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 403, 'Cannot add user to group without ModifyOwnMembership right');
+
+    # Rights Test - With ModifyOwnMembership
+    $user->PrincipalObj->GrantRight(Right => 'ModifyOwnMembership');
+    $res = $mech->put_json("$rest_base_path/user/" . $user->id . '/groups',
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'Add user to group with ModifyOwnMembership right');
+    my $members2 = $group2->MembersObj;
+    is($members2->Count, 1, 'One member added');
+    my $member = $members2->Next;
+    is($member->MemberObj->PrincipalType, 'User', 'User added as member');
+    is($member->MemberObj->id, $user->id, 'Accurate user added as member');
+}
+
+
+# Memberships list
+{
+    # Rights Test - No SeeGroup
+    my $res = $mech->get("$rest_base_path/user/" . $user->id . '/groups',
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'List direct members');
+
+    my $content = $mech->json_response;
+    is($content->{total}, 2, 'Two recursive memberships');
+    is(scalar(@{$content->{items}}), 0, 'Cannot see memberships content withtout SeeGroup right');
+    
+    # Recursive memberships
+    $user->PrincipalObj->GrantRight(Right => 'SeeGroup');
+    $res = $mech->get("$rest_base_path/user/" . $user->id . '/groups',
+        'Authorization' => $auth,
+    );
+    is($res->code, 200, 'List direct members');
+
+    $content = $mech->json_response;
+    is($content->{total}, 2, 'Two recursive memberships');
+    is($content->{items}->[0]->{type}, 'group', 'First group membership');
+    is($content->{items}->[0]->{id}, $group1->id, 'Accurate first group membership');
+    is($content->{items}->[1]->{type}, 'group', 'Second group membership');
+    is($content->{items}->[1]->{id}, $group2->id, 'Accurate second group membership');
+}
+
+($ok, $msg) = $group1->AddMember($user->id);
+ok($ok, $msg);
+
+# Membership removal
+{
+    my $res = $mech->delete("$rest_base_path/user/" . $user->id . '/group/' . $group2->id,
+        'Authorization' => $auth,
+    );
+    is($res->code, 204, 'Remove membership');
+    my $memberships = $user->OwnGroups;
+    is($memberships->Count, 1, 'One membership removed');
+    my $membership = $memberships->Next;
+    is($membership->id, $group1->id, 'Accurate membership removed');
+}
+
+($ok, $msg) = $group2->AddMember($user->id);
+ok($ok, $msg);
+
+# All members removal
+{
+    my $res = $mech->delete("$rest_base_path/user/" . $user->id . '/groups',
+        'Authorization' => $auth,
+    );
+    is($res->code, 204, 'Remove all memberships');
+    my $memberships = $user->OwnGroups;
+    is($memberships->Count, 0, 'All membership removed');
+}
+
+done_testing;

commit 72dcdf0a1306bdc8fec9f3cf594baba57a5bebf2
Author: gibus <gibus at easter-eggs.com>
Date:   Thu Sep 20 17:34:44 2018 +0200

    Fix existing tests missing SeeGroup right

diff --git a/t/ticket-customroles.t b/t/ticket-customroles.t
index 3b692a3..f20c4a1 100644
--- a/t/ticket-customroles.t
+++ b/t/ticket-customroles.t
@@ -41,7 +41,7 @@ for my $email (qw/multi at example.com test at localhost multi2 at example.com single2 at ex
 }
 
 $user->PrincipalObj->GrantRight( Right => $_ )
-    for qw/CreateTicket ShowTicket ModifyTicket OwnTicket AdminUsers/;
+    for qw/CreateTicket ShowTicket ModifyTicket OwnTicket AdminUsers SeeGroup/;
 
 # Create and view ticket with no watchers
 {
diff --git a/t/ticket-watchers.t b/t/ticket-watchers.t
index 20446fd..76bdbdc 100644
--- a/t/ticket-watchers.t
+++ b/t/ticket-watchers.t
@@ -13,7 +13,7 @@ my $user = RT::Extension::REST2::Test->user;
 my $queue = RT::Test->load_or_create_queue( Name => "General" );
 
 $user->PrincipalObj->GrantRight( Right => $_ )
-    for qw/CreateTicket ShowTicket ModifyTicket OwnTicket AdminUsers/;
+    for qw/CreateTicket ShowTicket ModifyTicket OwnTicket AdminUsers SeeGroup/;
 
 # Create and view ticket with no watchers
 {

commit 676c261d459fe543386595711c99fe74d4f76efd
Author: gibus <gibus at easter-eggs.com>
Date:   Fri Sep 21 15:49:30 2018 +0200

    Add documentation for group members and user memberships

diff --git a/README b/README
index 18aa7fa..c955661 100644
--- a/README
+++ b/README
@@ -398,11 +398,11 @@ USAGE
 
         GET /user/:id
         GET /user/:name
-            retrieve a user by numeric id or username
+            retrieve a user by numeric id or username (including its memberships and whether it is disabled)
 
         PUT /user/:id
         PUT /user/:name
-            update a user's metadata; provide JSON content
+            update a user's metadata (including its Disabled status); provide JSON content
 
         DELETE /user/:id
         DELETE /user/:name
@@ -417,12 +417,66 @@ USAGE
         POST /groups
             search for groups using L</JSON searches> syntax
 
+        POST /group
+            create a (user defined) group; provide JSON content
+
         GET /group/:id
-            retrieve a group (including its members)
+            retrieve a group (including its members and whether it is disabled)
+
+        PUT /group/:id
+            update a groups's metadata (including its Disabled status); provide JSON content
+
+        DELETE /group/:id
+            disable group
 
         GET /group/:id/history
             retrieve list of transactions for group
 
+   User Memberships
+        GET /user/:id/groups
+        GET /user/:name/groups
+            retrieve list of groups which a user is a member of
+
+        PUT /user/:id/groups
+        PUT /user/:name/groups
+            add a user to groups; provide a JSON array of groups ids
+
+        DELETE /user/:id/group/:id
+        DELETE /user/:name/group/:id
+            remove a user from a group
+
+        DELETE /user/:id/groups
+        DELETE /user/:name/groups
+            remove a user from all groups
+
+   Group Members
+        GET /group/:id/members
+            retrieve list of direct members of a group
+
+        GET /group/:id/members?recursively=1
+            retrieve list of direct and recursive members of a group
+
+        GET /group/:id/members?users=0
+            retrieve list of direct group members of a group
+
+        GET /group/:id/members?users=0&recursively=1
+            retrieve list of direct and recursive group members of a group
+
+        GET /group/:id/members?groups=0
+            retrieve list of direct user members of a group
+
+        GET /group/:id/members?groups=0&recursively=1
+            retrieve list of direct and recursive user members of a group
+
+        PUT /group/:id/members
+            add members to a group; provide a JSON array of principal ids
+
+        DELETE /group/:id/member/:id
+            remove a member from a group
+
+        DELETE /group/:id/members
+            remove all members from a group
+
    Custom Fields
         GET /customfields?query=<JSON>
         POST /customfields
diff --git a/lib/RT/Extension/REST2.pm b/lib/RT/Extension/REST2.pm
index e7e06fe..c4023df 100644
--- a/lib/RT/Extension/REST2.pm
+++ b/lib/RT/Extension/REST2.pm
@@ -440,11 +440,11 @@ Below are some examples using the endpoints above.
 
     GET /user/:id
     GET /user/:name
-        retrieve a user by numeric id or username
+        retrieve a user by numeric id or username (including its memberships and whether it is disabled)
 
     PUT /user/:id
     PUT /user/:name
-        update a user's metadata; provide JSON content
+        update a user's metadata (including its Disabled status); provide JSON content
 
     DELETE /user/:id
     DELETE /user/:name
@@ -460,12 +460,68 @@ Below are some examples using the endpoints above.
     POST /groups
         search for groups using L</JSON searches> syntax
 
+    POST /group
+        create a (user defined) group; provide JSON content
+
     GET /group/:id
-        retrieve a group (including its members)
+        retrieve a group (including its members and whether it is disabled)
+
+    PUT /group/:id
+        update a groups's metadata (including its Disabled status); provide JSON content
+
+    DELETE /group/:id
+        disable group
 
     GET /group/:id/history
         retrieve list of transactions for group
 
+=head3 User Memberships
+
+    GET /user/:id/groups
+    GET /user/:name/groups
+        retrieve list of groups which a user is a member of
+
+    PUT /user/:id/groups
+    PUT /user/:name/groups
+        add a user to groups; provide a JSON array of groups ids
+
+    DELETE /user/:id/group/:id
+    DELETE /user/:name/group/:id
+        remove a user from a group
+
+    DELETE /user/:id/groups
+    DELETE /user/:name/groups
+        remove a user from all groups
+
+=head3 Group Members
+
+    GET /group/:id/members
+        retrieve list of direct members of a group
+
+    GET /group/:id/members?recursively=1
+        retrieve list of direct and recursive members of a group
+
+    GET /group/:id/members?users=0
+        retrieve list of direct group members of a group
+
+    GET /group/:id/members?users=0&recursively=1
+        retrieve list of direct and recursive group members of a group
+
+    GET /group/:id/members?groups=0
+        retrieve list of direct user members of a group
+
+    GET /group/:id/members?groups=0&recursively=1
+        retrieve list of direct and recursive user members of a group
+
+    PUT /group/:id/members
+        add members to a group; provide a JSON array of principal ids
+
+    DELETE /group/:id/member/:id
+        remove a member from a group
+
+    DELETE /group/:id/members
+        remove all members from a group
+
 =head3 Custom Fields
 
     GET /customfields?query=<JSON>

commit ff147579f0dd4b959f078cf7164d41031a04fc4f
Author: gibus <gibus at easter-eggs.com>
Date:   Tue Oct 9 14:36:51 2018 +0200

    Add new files in MANIFEST

diff --git a/MANIFEST b/MANIFEST
index bac4498..98866ce 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -36,6 +36,7 @@ lib/RT/Extension/REST2/Resource/CustomFields.pm
 lib/RT/Extension/REST2/Resource/CustomRole.pm
 lib/RT/Extension/REST2/Resource/CustomRoles.pm
 lib/RT/Extension/REST2/Resource/Group.pm
+lib/RT/Extension/REST2/Resource/GroupMembers.pm
 lib/RT/Extension/REST2/Resource/Groups.pm
 lib/RT/Extension/REST2/Resource/Message.pm
 lib/RT/Extension/REST2/Resource/Queue.pm
@@ -56,6 +57,7 @@ lib/RT/Extension/REST2/Resource/TicketsBulk.pm
 lib/RT/Extension/REST2/Resource/Transaction.pm
 lib/RT/Extension/REST2/Resource/Transactions.pm
 lib/RT/Extension/REST2/Resource/User.pm
+lib/RT/Extension/REST2/Resource/UserGroups.pm
 lib/RT/Extension/REST2/Resource/Users.pm
 lib/RT/Extension/REST2/Util.pm
 Makefile.PL
@@ -66,6 +68,7 @@ t/asset-customfields.t
 t/assets.t
 t/catalogs.t
 t/conflict.t
+t/group-members.t
 t/lib/RT/Extension/REST2/Test.pm.in
 t/not_found.t
 t/organization.t
@@ -80,4 +83,5 @@ t/tickets-bulk.t
 t/tickets.t
 t/transactions.t
 t/user-customfields.t
+t/user-memberships.t
 TODO

commit 592753c73865c67df9ae7b6fd6c5a0152f248117
Author: gibus <gibus at easter-eggs.com>
Date:   Tue Oct 9 15:12:49 2018 +0200

    Add memberships in user's hypermedia links

diff --git a/lib/RT/Extension/REST2/Resource/User.pm b/lib/RT/Extension/REST2/Resource/User.pm
index a4ae3ae..8a74630 100644
--- a/lib/RT/Extension/REST2/Resource/User.pm
+++ b/lib/RT/Extension/REST2/Resource/User.pm
@@ -60,6 +60,12 @@ sub hypermedia_links {
     my $self = shift;
     my $links = $self->_default_hypermedia_links(@_);
     push @$links, $self->_transaction_history_link;
+
+    my $id = $self->record->id;
+    push @$links,
+      { ref  => 'memberships',
+        _url => RT::Extension::REST2->base_uri . "/user/$id/groups",
+      };
     return $links;
 }
 
diff --git a/t/user-memberships.t b/t/user-memberships.t
index 47f969a..b27ad12 100644
--- a/t/user-memberships.t
+++ b/t/user-memberships.t
@@ -102,4 +102,18 @@ ok($ok, $msg);
     is($memberships->Count, 0, 'All membership removed');
 }
 
+# User hypermedia links
+{
+    my $res = $mech->get("$rest_base_path/user/" . $user->id,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+    my $content = $mech->json_response;
+    my $links = $content->{_hyperlinks};
+    my @memberships_links = grep { $_->{ref} eq 'memberships' } @$links;
+    is(scalar(@memberships_links), 1);
+    my $user_id = $user->id;
+    like($memberships_links[0]->{_url}, qr{$rest_base_path/user/$user_id/groups$});
+}
+
 done_testing;

commit 5ef01fa077200b0080f3379cc84384208b84cf12
Author: gibus <gibus at easter-eggs.com>
Date:   Tue Oct 9 16:07:23 2018 +0200

    Add members in group's hypermedia links

diff --git a/lib/RT/Extension/REST2/Resource/Group.pm b/lib/RT/Extension/REST2/Resource/Group.pm
index 8235fa0..64377a3 100644
--- a/lib/RT/Extension/REST2/Resource/Group.pm
+++ b/lib/RT/Extension/REST2/Resource/Group.pm
@@ -45,6 +45,12 @@ sub hypermedia_links {
     my $self = shift;
     my $links = $self->_default_hypermedia_links(@_);
     push @$links, $self->_transaction_history_link;
+
+    my $id = $self->record->id;
+    push @$links,
+      { ref  => 'members',
+        _url => RT::Extension::REST2->base_uri . "/group/$id/members",
+      };
     return $links;
 }
 
diff --git a/t/group-members.t b/t/group-members.t
index ee33050..8a3bd3f 100644
--- a/t/group-members.t
+++ b/t/group-members.t
@@ -272,4 +272,17 @@ $user->PrincipalObj->GrantRight(Right => 'SeeGroup', Object => $group1);
     is($members1->Count, 0, 'All members removed');
 }
 
+# Group hypermedia links
+{
+    my $res = $mech->get("$rest_base_path/group/$group1_id",
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+    my $content = $mech->json_response;
+    my $links = $content->{_hyperlinks};
+    my @members_links = grep { $_->{ref} =~ /members/ } @$links;
+    is(scalar(@members_links), 1);
+    like($members_links[0]->{_url}, qr{$rest_base_path/group/$group1_id/members$});
+}
+
 done_testing;

commit 2efee24a93488db7f817225504cf9d59d67b3fca
Merge: 5e06368 5ef01fa
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Tue Nov 20 03:29:17 2018 +0800

    Merge branch 'add-group-members-user-memberships'


-----------------------------------------------------------------------


More information about the Bps-public-commit mailing list