File Coverage

blib/lib/WebService/Moodle/Simple.pm
Criterion Covered Total %
statement 31 130 23.8
branch 0 20 0.0
condition 0 5 0.0
subroutine 11 20 55.0
pod 7 9 77.7
total 49 184 26.6


line stmt bran cond sub pod time code
1             package WebService::Moodle::Simple;
2              
3 3     3   50046 use 5.008_005;
  3         13  
4             our $VERSION = '0.05';
5 3     3   1379 use namespace::clean;
  3         44588  
  3         20  
6              
7 3     3   1933 use HTTP::Request;
  3         52115  
  3         96  
8 3     3   1703 use JSON;
  3         23781  
  3         18  
9 3     3   340 use List::Util qw/first/;
  3         6  
  3         228  
10 3     3   1559 use LWP::UserAgent;
  3         49403  
  3         83  
11 3     3   1273 use Moo;
  3         18530  
  3         15  
12 3     3   4374 use Ouch;
  3         4195  
  3         147  
13 3     3   21 use URI;
  3         50  
  3         77  
14 3     3   1188 use Sys::SigAction qw( timeout_call );
  3         29049  
  3         3109  
15              
16              
17             # ABSTRACT: API client for Stripe
18              
19              
20             my $REST_FORMAT = 'json';
21             # https://moodle.org/mod/forum/discuss.php?d=340377
22             my $STUDENT_ROLE_ID = 5;
23              
24             # the base domain like moodle.example.com
25             has domain => (
26             is => 'ro',
27             );
28              
29             # name of the moodle external service
30             has target => (
31             is => 'ro',
32             );
33              
34             has token => (
35             is => 'ro',
36             );
37              
38             has port => (
39             is => 'ro',
40             default => 443,
41             );
42              
43             has timeout => (
44             is => 'ro',
45             default => 1000,
46             );
47              
48             has scheme => (
49             is => 'rw',
50             default => 'https',
51             );
52              
53              
54              
55             sub dns_uri {
56 1     1 0 2075 my $self = shift;
57 1         18 return URI->new($self->scheme.'://'.$self->domain.':'.$self->port);
58             }
59              
60             sub rest_call {
61 0     0 0   my ($self, $dns_uri) = @_;
62              
63 0           my $timeout = $self->timeout + 1;
64              
65 0           my $res;
66              
67 0 0         if ( timeout_call( $timeout,
68             sub {
69 0     0     my $req = HTTP::Request->new (GET => $dns_uri);
70 0           $req->content_type('application/json');
71              
72 0           my $lwp = LWP::UserAgent->new;
73 0           $lwp->timeout($timeout);
74 0           $res = $lwp->request( $req );
75             }
76             )) {
77 0           ouch 408, 'Timeout: no response from '.$self->domain;
78             }
79              
80 0 0         unless ($res->is_success) {
81 0           ouch $res->code, $res->message;
82             }
83              
84 0           return $res;
85             }
86              
87              
88             sub set_password {
89 0     0 1   my $self = shift;
90 0           my %args = (
91             username => undef,
92             password => undef,
93             @_
94             );
95              
96 0           my $username = lc($args{username});
97              
98             my $params = {
99             'wstoken' => $self->token,
100             'wsfunction' => "core_user_update_users",
101             'moodlewsrestformat' => $REST_FORMAT,
102             'users[0][id]' => $self->get_user(username => $username )->{id},
103             'users[0][password]' => $args{password},
104 0           };
105              
106              
107 0           my $dns_uri = $self->dns_uri;
108 0           $dns_uri->path('webservice/rest/server.php');
109 0           $dns_uri->query_form( $params );
110              
111 0           my $res = $self->rest_call($dns_uri);
112              
113 0           return { ok => $res->is_success };
114             }
115              
116              
117              
118             sub add_user {
119 0     0 1   my $self = shift;
120 0           my %args = (
121             firstname => undef,
122             lastname => undef,
123             email => undef,
124             username => undef,
125             password => undef,
126             @_
127             );
128              
129              
130 0           my $username = lc($args{username});
131              
132             my $params = {
133             'wstoken' => $self->token,
134             'wsfunction' => "core_user_create_users",
135             'moodlewsrestformat' => $REST_FORMAT,
136             'users[0][username]' => $username,
137             'users[0][email]' => $args{email},
138             'users[0][firstname]' => $args{firstname},
139             'users[0][lastname]' => $args{lastname},
140             'users[0][password]' => $args{password},
141 0           };
142              
143              
144 0           my $dns_uri = $self->dns_uri;
145 0           $dns_uri->path('webservice/rest/server.php');
146 0           $dns_uri->query_form( $params );
147              
148 0           my $res = $self->rest_call($dns_uri);
149              
150 0           my $response = from_json($res->content);
151              
152 0 0         unless (ref($response) eq 'ARRAY') {
153 0           return { ok => 0, msg => $response->{debuginfo} };
154             }
155              
156              
157 0           return { ok => 1, %{$response->[0]} }
  0            
158             }
159              
160             sub get_user {
161 0     0 1   my $self = shift;
162 0           my %args = (
163             username => undef,
164             @_
165             );
166              
167              
168 0           my $username = lc($args{username});
169              
170 0           my $params = {
171             'wstoken' => $self->token,
172             'wsfunction' => "core_user_get_users_by_field",
173             'moodlewsrestformat' => $REST_FORMAT,
174             'field' => 'username',
175             'values[0]' => $username,
176             };
177              
178              
179 0           my $dns_uri = $self->dns_uri;
180 0           $dns_uri->path('webservice/rest/server.php');
181 0           $dns_uri->query_form( $params );
182              
183 0           my $res = $self->rest_call($dns_uri);
184              
185 0           my $dat = from_json($res->content);
186 0 0 0       unless ($dat && ref($dat) eq 'ARRAY' && scalar(@$dat)) {
      0        
187 0           return;
188             }
189 0           return $dat->[0];
190             }
191              
192              
193             sub enrol_student {
194 0     0 1   my $self = shift;
195 0           my %args = (
196             username => undef,
197             course => undef,
198             @_
199             );
200              
201             my $user = $self->get_user(
202             username => $args{username}
203 0           );
204 0 0         return { ok => undef, msg => "Invalid user $args{username}" } unless $user;
205              
206 0           my $user_id = $user->{id};
207              
208             my $params = {
209             'wstoken' => $self->token,
210             'wsfunction' => "enrol_manual_enrol_users",
211             'moodlewsrestformat' => $REST_FORMAT,
212             'enrolments[0][roleid]' => $STUDENT_ROLE_ID,
213             'enrolments[0][userid]' => $user_id,
214 0           'enrolments[0][courseid]' => $self->get_course_id ( short_cname => $args{course} ),
215             };
216              
217              
218 0           my $dns_uri = $self->dns_uri;
219 0           $dns_uri->path('webservice/rest/server.php');
220 0           $dns_uri->query_form( $params );
221              
222 0           my $res = $self->rest_call($dns_uri);
223 0 0         unless ($res->is_success) {
224 0           ouch $res->code, $res->message;
225             }
226              
227 0 0         return { ok => 1, msg => "$args{username} enrolled in $args{course}" } if ($res->content eq 'null');
228 0           return { ok => undef, msg => from_json($res->content)->{message} };
229             }
230              
231             sub get_course_id {
232 0     0 1   my $self = shift;
233 0           my %args = (
234             short_cname => undef,
235             @_
236             );
237              
238 0           my $dns_uri = $self->dns_uri;
239 0           $dns_uri->path('webservice/rest/server.php');
240 0           $dns_uri->query_form( {
241             wstoken => $self->token,
242             wsfunction => 'core_course_get_courses',
243             moodlewsrestformat => $REST_FORMAT,
244             } );
245              
246 0           my $res = $self->rest_call($dns_uri);
247 0           my $ra_courses = from_json($res->content);
248 0           foreach my $rh_course (@$ra_courses) {
249 0 0         if ($rh_course->{shortname} eq $args{short_cname}) {
250 0           return $rh_course->{id};
251             }
252             }
253              
254 0           ouch 'MSE-0002', 'failed to find course of name '.$args{short_cname};
255             }
256              
257              
258             # NOTE: suspend_user depends on the 'suspended' parameter
259             # https://tracker.moodle.org/browse/MDL-31465
260              
261             sub suspend_user {
262 0     0 1   my $self = shift;
263 0           my %args = (
264             username => undef,
265             suspend => 1, # suspend unless it is 0
266             @_
267             );
268              
269 0           my $mdl_user = $self->get_user( username => $args{username} );
270              
271             my $params = {
272             'wstoken' => $self->token,
273             'wsfunction' => "core_user_update_users",
274             'moodlewsrestformat' => $REST_FORMAT,
275             'users[0][id]' => $mdl_user->{id},
276 0           'users[0][suspended]' => $args{suspend} + 0,
277             };
278              
279              
280 0           my $dns_uri = $self->dns_uri;
281 0           $dns_uri->path('webservice/rest/server.php');
282 0           $dns_uri->query_form( $params );
283              
284 0           $self->rest_call($dns_uri);
285              
286 0           return;
287             }
288              
289              
290             sub check_password {
291 0     0 1   my $self = shift;
292 0           my %args = (
293             username => undef,
294             password => undef,
295             @_
296             );
297              
298 0           my $username = $args{username};
299 0           my $password = $args{password};
300              
301             my $params = {
302             'username' => $args{username},
303             'password' => $args{password},
304 0           'service' => 'moodle_mobile_app',
305             };
306              
307              
308 0           my $dns_uri = $self->dns_uri;
309 0           $dns_uri->path('login/token.php');
310 0           $dns_uri->query_form( $params );
311              
312 0           my $res = $self->rest_call($dns_uri);
313              
314 0           my $content = $res->content;
315              
316 0           my $data;
317 0           eval {
318 0           $data = from_json($res->content);
319             };
320 0 0         if ($@){
321             return {
322 0           msg => "'$username' login failed",
323             ok => 0,
324             };
325             }
326              
327 0 0         if ( $data->{token} ) {
328             return {
329 0           msg => "'$username' has the correct password",
330             ok => 1,
331             };
332             }
333              
334             return {
335             msg => "'$username' login failed, error code: ".$data->{errorcode},
336 0           ok => 0,
337             };
338              
339             }
340              
341             1;
342              
343             __END__