blib/lib/WebService/Mattermost/V4/API/Resource.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 108 | 131 | 82.4 |
branch | 18 | 24 | 75.0 |
condition | 10 | 12 | 83.3 |
subroutine | 24 | 28 | 85.7 |
pod | n/a | ||
total | 160 | 195 | 82.0 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package WebService::Mattermost::V4::API::Resource; 2: 3: # ABSTRACT: Base class for API resources. 4: 5: use List::MoreUtils 'all'; 6: use Moo; 7: use Types::Standard qw(Bool HashRef Maybe Object Str); 8: 9: use WebService::Mattermost::Helper::Alias 'view'; 10: use WebService::Mattermost::V4::API::Object::Channel; 11: use WebService::Mattermost::V4::API::Object::Icon; 12: use WebService::Mattermost::V4::API::Object::Status; 13: use WebService::Mattermost::V4::API::Object::Team; 14: use WebService::Mattermost::V4::API::Object::TeamMember; 15: use WebService::Mattermost::V4::API::Object::TeamStats; 16: use WebService::Mattermost::V4::API::Object::Plugins; 17: use WebService::Mattermost::V4::API::Object::Results; 18: use WebService::Mattermost::V4::API::Object::User; 19: use WebService::Mattermost::V4::API::Request; 20: use WebService::Mattermost::V4::API::Response; 21: 22: with qw( 23: WebService::Mattermost::Role::Logger 24: WebService::Mattermost::Role::Returns 25: WebService::Mattermost::Role::UserAgent 26: WebService::Mattermost::V4::API::Role::RequireID 27: WebService::Mattermost::V4::API::Role::NewRelatedResource 28: ); 29: 30: ################################################################################ 31: 32: has api => (is => 'ro', isa => Object, required => 1); 33: has base_url => (is => 'ro', isa => Str, required => 1); 34: has resource => (is => 'ro', isa => Str, required => 1); 35: has auth_token => (is => 'rw', isa => Str, required => 1); 36: 37: has DELETE => (is => 'ro', isa => Str, default => 'DELETE'); 38: has GET => (is => 'ro', isa => Str, default => 'GET'); 39: has headers => (is => 'ro', isa => HashRef, default => sub { {} }); 40: has POST => (is => 'ro', isa => Str, default => 'POST'); 41: has PUT => (is => 'ro', isa => Str, default => 'PUT'); 42: has debug => (is => 'ro', isa => Bool, default => 0); 43: 44: has id => (is => 'rw', isa => Maybe[Str]); 45: 46: ################################################################################ 47: 48: sub _delete { 49: my $self = shift; 50: my $args = shift; 51: 52: $args->{method} = $self->DELETE; 53: 54: return $self->_call($args); 55: } 56: 57: sub _single_view_delete { 58: my $self = shift; 59: my $args = shift; 60: 61: $args->{single} = 1; 62: 63: return $self->_delete($args); 64: } 65: 66: sub _get { 67: my $self = shift; 68: my $args = shift; 69: 70: $args->{method} = $self->GET; 71: 72: return $self->_call($args); 73: } 74: 75: sub _single_view_get { 76: my $self = shift; 77: my $args = shift; 78: 79: $args->{single} = 1; 80: 81: return $self->_get($args); 82: } 83: 84: sub _post { 85: my $self = shift; 86: my $args = shift; 87: 88: $args->{method} = $self->POST; 89: 90: return $self->_call($args); 91: } 92: 93: sub _single_view_post { 94: my $self = shift; 95: my $args = shift; 96: 97: $args->{single} = 1; 98: 99: return $self->_post($args); 100: } 101: 102: sub _put { 103: my $self = shift; 104: my $args = shift; 105: 106: $args->{method} = $self->PUT; 107: 108: return $self->_call($args); 109: } 110: 111: sub _single_view_put { 112: my $self = shift; 113: my $args = shift; 114: 115: $args->{method} = $self->PUT; 116: 117: return $self->_put($args); 118: } 119: 120: sub _call { 121: my $self = shift; 122: my $args = shift; 123: 124: if ($args->{required}) { 125: my $validation = $self->_validate($args->{parameters}, $args->{required}); 126: 127: return $validation unless $validation->{valid}; 128: } 129: 130: my %headers = ('Keep-Alive' => 1); 131: 132: if ($self->auth_token) { 133: $headers{Authorization} = $self->bearer($self->auth_token); 134: } 135: 136: my $request = $self->_as_request($args); 137: my $method = lc $request->method; 138: 139: my $form_type; 140: 141: if (grep { $_ eq $request->method } ($self->PUT, $self->POST)) { 142: $form_type = 'json'; 143: } else { 144: $form_type = 'form'; 145: } 146: 147: $form_type = $args->{override_data_type} if $args->{override_data_type}; 148: 149: my $tx = $self->ua->$method( 150: $request->url => \%headers, 151: $form_type => $request->parameters, 152: ); 153: 154: if (my $error = $tx->req->error) { 155: $self->logger->warn('No HTTP code was received from Mattermost. Is your server alive?'); 156: $self->logger->warnf('The following may be useful: %s', $error->{message}); 157: } 158: 159: return $self->_as_response($tx->res, $args); 160: } 161: 162: sub _as_request { 163: my $self = shift; 164: my $args = shift; 165: 166: $args->{auth_token} = $self->auth_token; 167: $args->{base_url} = $self->base_url; 168: $args->{resource} = $self->resource; 169: $args->{debug} = $self->debug; 170: 171: $args->{endpoint} ||= ''; 172: $args->{parameters} ||= {}; 173: 174: return WebService::Mattermost::V4::API::Request->new($args); 175: } 176: 177: sub _as_response { 178: my $self = shift; 179: my $res = shift; 180: my $args = shift; 181: 182: my $view_name = $self->can('view_name') && $self->view_name; 183: 184: if ($args->{view}) { 185: $view_name = $args->{view}; 186: } 187: 188: if ($res->is_error && $self->debug) { 189: $self->logger->warnf('An API error occurred: %s', $res->message); 190: } 191: 192: return WebService::Mattermost::V4::API::Response->new({ 193: auth_token => $self->auth_token, 194: base_url => $self->base_url, 195: code => $res->code || 0, 196: headers => $res->headers, 197: is_error => $res->is_error ? 1 : 0, 198: is_success => $res->is_success ? 1 : 0, 199: message => $res->message, 200: prev => $res, 201: raw_content => $res->body, 202: item_view => $view_name, 203: single_item => $args->{single}, 204: }); 205: } 206: 207: sub _validate { 208: my $self = shift; 209: my $args = shift; 210: my $required = shift; 211: 212: my %slice; 213: 214: # Grab a slice of the keys from given arguments 215: @slice{@{$required}} = @{$args}{@{$required}}; 216: 217: # Return early, all's well 218: return { valid => 1 } if all { defined($_) } values %slice; 219: 220: my @missing; 221: 222: foreach my $kx (@{$required}) { 223: push @missing, $kx unless $args->{$kx}; 224: } 225: 226: return { 227: valid => 0, 228: missing => \@missing, 229: error => sprintf('Required parameters missing: %s', join(', ', @missing)), 230: }; 231: } 232: 233: ################################################################################ 234: 235: 1; 236: 237: __END__ 238: 239: =pod 240: 241: =encoding UTF-8 242: 243: =head1 NAME 244: 245: WebService::Mattermost::V4::API::Resource - Base class for API resources. 246: 247: =head1 VERSION 248: 249: version 0.28 250: 251: =head1 DESCRIPTION 252: 253: =head2 ATTRIBUTES 254: 255: =over 4 256: 257: =item C<auth_token> 258: 259: An auth token to use in the headers for every API call. Authentication is 260: required to use the Mattermost API. 261: 262: =item C<base_url> 263: 264: The API's base URL. 265: 266: =item C<resource> 267: 268: The name of the API resource, for example L<WebService::Mattermost::V4::API::Brand>'s 269: resource is 'brand'. 270: 271: =back 272: 273: =head1 AUTHOR 274: 275: Mike Jones <mike@netsplit.org.uk> 276: 277: =head1 COPYRIGHT AND LICENSE 278: 279: This software is Copyright (c) 2020 by Mike Jones. 280: 281: This is free software, licensed under: 282: 283: The MIT (X11) License 284: 285: =cut 286: |