blib/lib/WebService/Mattermost/V4/API/Resource/User.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 6 | 11 | 54.5 |
branch | n/a | ||
condition | n/a | ||
subroutine | 2 | 4 | 50.0 |
pod | 1 | 1 | 100.0 |
total | 9 | 16 | 56.2 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package WebService::Mattermost::V4::API::Resource::User; 2: 3: # ABSTRACT: Wrapped API methods for the users API endpoints. 4: 5: use Moo; 6: use Types::Standard qw(HashRef Str); 7: 8: extends 'WebService::Mattermost::V4::API::Resource'; 9: with qw( 10: WebService::Mattermost::V4::API::Resource::Role::Single 11: WebService::Mattermost::V4::API::Resource::Role::View::User 12: ); 13: 14: ################################################################################ 15: 16: has available_user_roles => (is => 'ro', isa => HashRef, lazy => 1, builder => 1); 17: 18: has role_system_admin => (is => 'ro', isa => Str, default => 'system_admin'); 19: has role_system_user => (is => 'ro', isa => Str, default => 'system_user'); 20: 21: ################################################################################ 22: 23: around [ qw( 24: get 25: update 26: teams 27: patch 28: 29: update_roles 30: update_active_status 31: update_password 32: update_authentication_method 33: 34: generate_mfa_secret 35: update_mfa 36: 37: get_profile_image 38: set_profile_image 39: 40: get_status 41: set_status 42: 43: get_sessions 44: revoke_session 45: revoke_all_sessions 46: 47: get_preferences 48: set_preferences 49: delete_preferences 50: list_preferences_by_category 51: get_preference_by_category_and_name 52: 53: get_flagged_posts 54: 55: remove_reaction 56: 57: get_authorized_apps 58: get_authorised_apps 59: ) ] => sub { 60: my $orig = shift; 61: my $self = shift; 62: my $id = shift; 63: 64: return $self->validate_id($orig, $id, @_); 65: }; 66: 67: sub get { 68: my $self = shift; 69: my $id = shift; 70: 71: return $self->_single_view_get({ 72: endpoint => '%s', 73: ids => [ $id ], 74: }); 75: } 76: 77: sub update { 78: my $self = shift; 79: my $id = shift; 80: my $args = shift; 81: 82: return $self->_put({ 83: endpoint => '%s', 84: ids => [ $id ], 85: parameters => $args, 86: }); 87: } 88: 89: sub teams { 90: my $self = shift; 91: my $id = shift; 92: 93: return $self->_get({ 94: endpoint => '%s/teams', 95: ids => [ $id ], 96: view => 'Team', 97: }); 98: } 99: 100: sub deactivate { 101: my $self = shift; 102: my $id = shift; 103: 104: return $self->_delete({ 105: endpoint => '%s', 106: ids => [ $id ], 107: }); 108: } 109: 110: sub patch { 111: my $self = shift; 112: my $id = shift; 113: my $args = shift; 114: 115: return $self->_put({ 116: endpoint => '%s/patch', 117: ids => [ $id ], 118: parameters => $args, 119: }); 120: } 121: 122: sub update_roles { 123: my $self = shift; 124: my $id = shift; 125: my $roles = shift; # ArrayRef 126: 127: foreach my $role (@{$roles}) { 128: unless ($self->available_user_roles->{$role}) { 129: my $err = sprintf('"%s" is not a valid role. Valid roles: %s', 130: $role, join(', ', keys %{$self->available_user_roles})); 131: 132: return $self->error_return($err); 133: } 134: } 135: 136: return $self->_put({ 137: endpoint => '%s/roles', 138: ids => [ $id ], 139: parameters => { 140: roles => $roles, 141: }, 142: }); 143: } 144: 145: sub generate_mfa_secret { 146: my $self = shift; 147: my $id = shift; 148: 149: return $self->_post({ 150: endpoint => '%s/mfa/generate', 151: ids => [ $id ], 152: }); 153: } 154: 155: sub update_mfa { 156: my $self = shift; 157: my $id = shift; 158: my $args = shift; 159: 160: return $self->_put({ 161: endpoint => '%s/mfa', 162: ids => [ $id ], 163: parameters => $args, 164: }); 165: } 166: 167: sub get_profile_image { 168: my $self = shift; 169: my $id = shift; 170: 171: return $self->_get({ 172: endpoint => '%s/image', 173: ids => [ $id ], 174: }); 175: } 176: 177: sub set_profile_image { 178: my $self = shift; 179: my $id = shift; 180: my $filename = shift; 181: 182: unless ($filename && -f $filename) { 183: return $self->error_return(sprintf('%s is not a valid file', $filename)); 184: } 185: 186: return $self->_post({ 187: endpoint => '%s/image', 188: ids => [ $id ], 189: override_data_type => 'form', 190: parameters => { 191: image => { file => $filename }, 192: }, 193: }); 194: } 195: 196: sub update_active_status { 197: my $self = shift; 198: my $id = shift; 199: my $args = shift; 200: 201: return $self->_put({ 202: endpoint => '%s/active', 203: ids => [ $id ], 204: parameters => $args, 205: required => [ 'active' ], 206: }); 207: } 208: 209: sub update_password { 210: my $self = shift; 211: my $id = shift; 212: my $args = shift; 213: 214: return $self->_put({ 215: endpoint => '%s/password', 216: ids => [ $id ], 217: parameters => $args, 218: }); 219: } 220: 221: sub update_authentication_method { 222: my $self = shift; 223: my $id = shift; 224: my $args = shift; 225: 226: return $self->_put({ 227: endpoint => '%s/auth', 228: ids => [ $id ], 229: paramters => $args, 230: }); 231: } 232: 233: sub get_status { 234: my $self = shift; 235: my $id = shift; 236: 237: return $self->_single_view_get({ 238: endpoint => '%s/status', 239: ids => [ $id ], 240: view => 'User::Status', 241: }); 242: } 243: 244: sub set_status { 245: my $self = shift; 246: my $id = shift; 247: my $status = shift; 248: 249: # online, away, offline, dnd 250: 251: return $self->_single_view_put({ 252: endpoint => '%s/status', 253: ids => [ $id ], 254: parameters => { 255: status => $status, 256: }, 257: required => [ 'status' ], 258: view => 'User::Status', 259: }); 260: } 261: 262: sub get_sessions { 263: my $self = shift; 264: my $id = shift; 265: 266: return $self->_get({ 267: endpoint => '%s/sessions', 268: ids => [ $id ], 269: view => 'User::Session', 270: }); 271: } 272: 273: sub revoke_session { 274: my $self = shift; 275: my $id = shift; 276: my $session_id = shift; 277: 278: return $self->_single_view_post({ 279: endpoint => '%s/sessions/revoke', 280: ids => [ $id ], 281: parameters => { 282: session_id => $session_id, 283: }, 284: required => [ 'session_id' ], 285: view => 'Status', 286: }); 287: } 288: 289: sub revoke_all_sessions { 290: my $self = shift; 291: my $id = shift; 292: 293: return $self->_single_view_post({ 294: endpoint => '%s/sessions/revoke/all', 295: view => 'Status', 296: }); 297: } 298: 299: sub get_preferences { 300: my $self = shift; 301: my $id = shift; 302: 303: return $self->_get({ 304: endpoint => '%s/preferences', 305: ids => [ $id ], 306: view => 'User::Preference', 307: }); 308: } 309: 310: sub set_preferences { 311: my $self = shift; 312: my $id = shift; 313: my $args = shift; 314: 315: unless (ref $args eq 'ARRAY') { 316: return $self->error_return('An ArrayRef of preferences must be passed'); 317: } 318: 319: return $self->_single_view_put({ 320: endpoint => '%s/preferences', 321: ids => [ $id ], 322: parameters => $args, 323: view => 'Status', 324: }); 325: } 326: 327: sub delete_preferences { 328: my $self = shift; 329: my $id = shift; 330: my $args = shift; 331: 332: unless (ref $args eq 'ARRAY') { 333: return $self->error_return('An ArrayRef of preferences must be passed'); 334: } 335: 336: return $self->_single_view_post({ 337: endpoint => '%s/preferences/delete', 338: ids => [ $id ], 339: parameters => $args, 340: view => 'Status', 341: }); 342: } 343: 344: sub list_preferences_by_category { 345: my $self = shift; 346: my $id = shift; 347: my $category = shift; 348: 349: unless ($category) { 350: return $self->error_return('A category is required'); 351: } 352: 353: return $self->_get({ 354: endpoint => '%s/preferences/%s', 355: ids => [ $id, $category ], 356: view => 'User::Category', 357: }); 358: } 359: 360: sub get_preference_by_category_and_name { 361: my $self = shift; 362: my $id = shift; 363: my $category = shift; 364: my $name = shift; 365: 366: unless ($category && $name) { 367: return $self->error_return('A category and a name must be passed'); 368: } 369: 370: return $self->_single_view_get({ 371: endpoint => '%s/preferences/%s/name/%s', 372: ids => [ $id, $category, $name ], 373: view => 'User::Category', 374: }); 375: } 376: 377: sub get_flagged_posts { 378: my $self = shift; 379: my $id = shift; 380: my $args = shift; 381: 382: return $self->_single_view_get({ 383: endpoint => '%s/posts/flagged', 384: ids => [ $id ], 385: parameters => $args, 386: view => 'Thread', 387: }); 388: } 389: 390: sub remove_reaction { 391: my $self = shift; 392: my $user_id = shift; 393: my $post_id = shift; 394: my $emoji_name = shift; 395: 396: unless ($post_id && $emoji_name) { 397: return $self->error_return('A post ID and an emoji name are required'); 398: } 399: 400: return $self->_single_view_delete({ 401: endpoint => '%s/posts/%s/reactions/%s', 402: ids => [ $user_id, $post_id, $emoji_name ], 403: view => 'Status', 404: }); 405: } 406: 407: sub get_authorized_apps { shift->get_authorised_apps(@_) } 408: 409: sub get_authorised_apps { 410: my $self = shift; 411: my $id = shift; 412: my $args = shift; 413: 414: return $self->_get({ 415: endpoint => '%s/oauth/apps/authorized', 416: ids => [ $id ], 417: parameters => $args, 418: view => 'Application', 419: }); 420: } 421: 422: ################################################################################ 423: 424: sub _build_available_user_roles { 425: my $self = shift; 426: 427: return { 428: $self->role_system_admin => 1, 429: $self->role_system_user => 1, 430: }; 431: } 432: 433: ################################################################################ 434: 435: 1; 436: 437: __END__ 438: 439: =pod 440: 441: =encoding UTF-8 442: 443: =head1 NAME 444: 445: WebService::Mattermost::V4::API::Resource::User - Wrapped API methods for the users API endpoints. 446: 447: =head1 VERSION 448: 449: version 0.28 450: 451: =head1 DESCRIPTION 452: 453: API methods relating to a single user by ID. 454: 455: =head2 USAGE 456: 457: use WebService::Mattermost; 458: 459: my $mm = WebService::Mattermost->new({ 460: authenticate => 1, 461: username => 'me@somewhere.com', 462: password => 'hunter2', 463: base_url => 'https://my.mattermost.server.com/api/v4/', 464: }); 465: 466: my $resource = $mm->api->user; 467: 468: Optionally, you can set a global user ID for the resource and not pass the ID 469: to every method: 470: 471: $resource->id('USER-ID-HERE'); 472: 473: =head2 METHODS 474: 475: All of the below methods can either be called as documented under each item, or 476: from a user result object: 477: 478: my $user = $resource->get('USER-ID-HERE')->item; 479: 480: # Calls method "teams" 481: my $response = $user->call('teams'); 482: 483: # Calls method "update" 484: $response = $user->call('update', { 485: # parameters 486: }); 487: 488: =over 4 489: 490: =item C<get()> 491: 492: L<Get a user|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D%2Fget> 493: 494: Get a user by their ID. 495: 496: my $response = $resource->get('USER-ID-HERE'); 497: 498: =item C<update()> 499: 500: L<Update a user|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D%2Fput> 501: 502: Update a user by their ID. 503: 504: my $response = $resource->update('USER-ID-HERE', { 505: # Optional arguments 506: email => '...', 507: username => '...', 508: first_name => '...', 509: last_name => '...', 510: nickname => '...', 511: locale => '...', 512: position => '...', 513: props => { 514: # ... 515: }, 516: notify_props => { 517: email => \1, 518: push => \1, 519: desktop => \1, 520: desktop_sound => \1, 521: mention_keys => \1, 522: channel => \1, 523: first_name => \1, 524: }, 525: }); 526: 527: =item C<teams()> 528: 529: L<Get a user's teams|https://api.mattermost.com/#tag/teams%2Fpaths%2F~1users~1%7Buser_id%7D~1teams%2Fget> 530: 531: =item C<deactivate()> 532: 533: L<Deactivate a user account|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D%2Fdelete> 534: 535: Set a user as inactive by ID. 536: 537: $response->deactivate('USER-ID-HERE'); 538: 539: =item C<patch()> 540: 541: L<Patch a user|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1patch%2Fput> 542: 543: my $response = $resource->patch('USER-ID-HERE', { 544: # Optional parameters: 545: email => '...', 546: username => '...', 547: first_name => '...', 548: last_name => '...', 549: nickname => '...', 550: locale => '...', 551: position => '...', 552: props => { 553: # ... 554: }, 555: notify_props => { 556: email => \1, 557: push => \1, 558: desktop => \1, 559: desktop_sound => \1, 560: mention_keys => \1, 561: channel => \1, 562: first_name => \1, 563: }, 564: }); 565: 566: =item C<update_roles()> 567: 568: L<Update a user's roles|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1roles%2Fput> 569: 570: Valid roles are C<system_user> and C<system_admin>. 571: 572: my $response = $resource->update_roles('USER-ID-HERE', [ 573: 'ROLE-NAME-HERE', 574: 'ANOTHER-ROLE-HERE', 575: ]); 576: 577: =item C<generate_mfa_secret()> 578: 579: L<Generate MFA secret|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1mfa~1generate%2Fpost> 580: 581: Returns a base64 encoded QR code image. 582: 583: my $response = $resource->generate_mfa_secret('USER-ID-HERE'); 584: 585: =item C<update_mfa()> 586: 587: L<Update a user's MFA|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1mfa%2Fput> 588: 589: Set whether a user requires multi-factor auth. If the user currently has MFA 590: active, a code from the MFA client is required. 591: 592: my $response = $resource->update_mfa('ID-HERE', { 593: activate => \1, # or \0 for false 594: code => 1234, # required if MFA is already active 595: }); 596: 597: =item C<get_profile_image()> 598: 599: L<Get user's profile image|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1image%2Fget> 600: 601: Get a user's profile image. Warning: returns binary content. 602: 603: my $response = $resource->get_profile_image('ID-HERE'); 604: 605: # $response->raw_content contains the image as binary 606: 607: =item C<set_profile_image()> 608: 609: L<Set user's profile image|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1image%2Fpost> 610: 611: Set a user's profile image. 612: 613: my $response = $resource->set_profile_image('ID-HERE', '/path/to/file.jpg'); 614: 615: =item C<update_active_status()> 616: 617: L<Update user active status|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1active%2Fput> 618: 619: Set a user as active or inactive. 620: 621: $resource->update_active_status('ID-HERE', { 622: active => \1, # \1 for true, \0 for false 623: }); 624: 625: =item C<update_password()> 626: 627: L<Update a user's password|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1password%2Fput> 628: 629: my $response = $resource->update_password('ID-HERE', { 630: old_password => '...', 631: new_password => '...', 632: }); 633: 634: =item C<update_authentication_method()> 635: 636: L<Update a user's authentication method|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1auth%2Fput> 637: 638: my $response = $resource->update_authentication_method('USER-ID-HERE', { 639: # Optional parameters: 640: auth_data => '...', 641: auth_service => '...', 642: password => '...', 643: }); 644: 645: =item C<get_status()> 646: 647: L<Get a user's status|https://api.mattermost.com/#tag/status%2Fpaths%2F~1users~1%7Buser_id%7D~1status%2Fget> 648: 649: my $response = $resource->get_status('USER-ID-HERE'); 650: 651: =item C<set_status()> 652: 653: L<Update a user's status|https://api.mattermost.com/#tag/status%2Fpaths%2F~1users~1%7Buser_id%7D~1status%2Fput> 654: 655: my $response = $resource->set_status('USER-ID-HERE', 'STATUS-HERE'); 656: 657: Available statuses are "online", "away", "offline" and "dnd". 658: 659: =item C<get_sessions()> 660: 661: L<Get a user's sessions|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1sessions%2Fget> 662: 663: my $response = $resource->get_sessions('USER-ID-HERE'); 664: 665: =item C<revoke_session()> 666: 667: L<Revoke a user sesssion|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1sessions~1revoke%2Fpost> 668: 669: my $response = $resource->revoke_session('USER-ID-HERE', 'SESSION-ID-HERE'); 670: 671: =item C<revoke_all_sessions()> 672: 673: L<Revoke all active sessions for a user|https://api.mattermost.com/#tag/users%2Fpaths%2F~1users~1%7Buser_id%7D~1sessions~1revoke~1all%2Fpost> 674: 675: my $response = $resource->revoke_all_sessions('USER-ID-HERE'); 676: 677: =item C<get_preferences()> 678: 679: L<Get the user's preferences|https://api.mattermost.com/#tag/preferences%2Fpaths%2F~1users~1%7Buser_id%7D~1preferences%2Fget> 680: 681: my $response = $resource->get_preferences('USER-ID-HERE'); 682: 683: =item C<set_preferences()> 684: 685: L<Save the user's preferences|https://api.mattermost.com/#tag/preferences%2Fpaths%2F~1users~1%7Buser_id%7D~1preferences%2Fput> 686: 687: my $response = $resource->set_preferences('USER-ID-HERE', [ 688: { user_id => 'USER-ID-HERE', category => '...', name => '...', value => '...' }, 689: { user_id => 'USER-ID-HERE', category => '...', name => '...', value => '...' }, 690: { user_id => 'USER-ID-HERE', category => '...', name => '...', value => '...' }, 691: ]); 692: 693: =item C<delete_preferences()> 694: 695: L<Delete user's preferences|https://api.mattermost.com/#tag/preferences%2Fpaths%2F~1users~1%7Buser_id%7D~1preferences~1delete%2Fpost> 696: 697: my $response = $resource->delete_preferences('USER-ID-HERE', [ 698: { user_id => 'USER-ID-HERE', category => '...', name => '...', value => '...' }, 699: { user_id => 'USER-ID-HERE', category => '...', name => '...', value => '...' }, 700: { user_id => 'USER-ID-HERE', category => '...', name => '...', value => '...' }, 701: ]); 702: 703: =item C<list_preferences_by_category()> 704: 705: L<List a user's preferences by category|https://api.mattermost.com/#tag/preferences%2Fpaths%2F~1users~1%7Buser_id%7D~1preferences~1%7Bcategory%7D%2Fget> 706: 707: my $response = $resource->list_preferences_by_category('USER-ID-HERE', 'CATEGORY-HERE'); 708: 709: =item C<get_preference_by_category_and_name()> 710: 711: L<Get a specific user preference|https://api.mattermost.com/#tag/preferences%2Fpaths%2F~1users~1%7Buser_id%7D~1preferences~1%7Bcategory%7D~1name~1%7Bpreference_name%7D%2Fget> 712: 713: my $response = $resource->get_preference_by_category_and_name( 714: 'USER-ID-HERE', 715: 'CATEGORY-HERE', 716: 'NAME-HERE', 717: ); 718: 719: =item C<get_flagged_posts()> 720: 721: L<Get a list of flagged posts|https://api.mattermost.com/#tag/posts%2Fpaths%2F~1users~1%7Buser_id%7D~1posts~1flagged%2Fget> 722: 723: Retrieve a list of posts flagged by the user with the given ID. 724: 725: my $response = $resource->get_flagged_posts('USER-ID-HERE', { 726: # Optional parameters 727: team_id => '...', 728: channel_id => '...', 729: page => 0, 730: per_page => 60, 731: }); 732: 733: =item C<remove_reaction()> 734: 735: L<Remove a reaction from a user's post|https://api.mattermost.com/#tag/reactions%2Fpaths%2F~1users~1%7Buser_id%7D~1posts~1%7Bpost_id%7D~1reactions~1%7Bemoji_name%7D%2Fdelete> 736: 737: my $response = $resource->remove_reaction( 738: 'USER-ID-HERE', 739: 'POST-ID-HERE', 740: 'EMOJI-NAME-HERE', 741: ); 742: 743: =item C<get_authorized_apps()> 744: 745: Alias for C<get_authorised_apps()>. 746: 747: =item C<get_authorised_apps()> 748: 749: L<Get authorized OAuth apps|https://api.mattermost.com/#tag/OAuth%2Fpaths%2F~1users~1%7Buser_id%7D~1oauth~1apps~1authorized%2Fget> 750: 751: my $response = $resource->get_authorised_apps('USER-ID-HERE', { 752: # Optional parameters: 753: page => 0, 754: per_page => 60, 755: }); 756: 757: =back 758: 759: =head1 AUTHOR 760: 761: Mike Jones <mike@netsplit.org.uk> 762: 763: =head1 COPYRIGHT AND LICENSE 764: 765: This software is Copyright (c) 2020 by Mike Jones. 766: 767: This is free software, licensed under: 768: 769: The MIT (X11) License 770: 771: =cut 772: |