summaryrefslogtreecommitdiffstats
path: root/Bugzilla/WebService/Server.pm
blob: a84ba29617841854fa4fc79fc6768a4be764edfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
#                 Max Kanat-Alexander <mkanat@bugzilla.org>

package Bugzilla::WebService::Server;
use strict;

use Bugzilla::Error;
use Bugzilla::Util qw(datetime_from);

use Digest::MD5 qw(md5_base64);
use Scalar::Util qw(blessed);
use Storable qw(freeze);

sub handle_login {
    my ($self, $class, $method, $full_method) = @_;
    # Throw error if the supplied class does not exist or the method is private
    ThrowCodeError('unknown_method', {method => $full_method}) if (!$class or $method =~ /^_/);

    # BMO - use the class and method as the name, instead of the cgi filename
    if (Bugzilla->metrics_enabled) {
        Bugzilla->metrics->name("$class $method");
    }

    # We never want to create a new session unless the user is calling the
    # login method.  Setting dont_persist_session makes
    # Bugzilla::Auth::_handle_login_result() skip calling persist_login().
    if ($full_method ne 'User.login') {
        Bugzilla->request_cache->{dont_persist_session} = 1;
    }

    eval "require $class";
    ThrowCodeError('unknown_method', {method => $full_method}) if $@;
    return if ($class->login_exempt($method) 
               and !defined Bugzilla->input_params->{Bugzilla_login});
    Bugzilla->login();

    Bugzilla::Hook::process(
        'webservice_before_call',
        { 'method'  => $method, full_method => $full_method });
}

sub datetime_format_inbound {
    my ($self, $time) = @_;

    my $converted = datetime_from($time, Bugzilla->local_timezone);
    if (!defined $converted) {
        ThrowUserError('illegal_date', { date => $time });
    }
    $time = $converted->ymd() . ' ' . $converted->hms();
    return $time
}

sub datetime_format_outbound {
    my ($self, $date) = @_;

    return undef if (!defined $date or $date eq '');

    my $time = $date;
    if (blessed($date)) {
        # We expect this to mean we were sent a datetime object
        $time->set_time_zone('UTC');
    } else {
        # We always send our time in UTC, for consistency.
        # passed in value is likely a string, create a datetime object
        $time = datetime_from($date, 'UTC');
    }
    return $time->iso8601();
}

# ETag support
sub bz_etag {
    my ($self, $data) = @_;
    my $cache = Bugzilla->request_cache;
    if (defined $data) {
        # Serialize the data if passed a reference
        local $Storable::canonical = 1;
        $data = freeze($data) if ref $data;

        # Wide characters cause md5_base64() to die.
        utf8::encode($data) if utf8::is_utf8($data);

        # Append content_type to the end of the data
        # string as we want the etag to be unique to
        # the content_type. We do not need this for
        # XMLRPC as text/xml is always returned.
        if (blessed($self) && $self->can('content_type')) {
            $data .= $self->content_type if $self->content_type;
        }

        $cache->{'bz_etag'} = md5_base64($data);
    }
    return $cache->{'bz_etag'};
}

1;

=head1 NAME

Bugzilla::WebService::Server - Base server class for the WebService API

=head1 DESCRIPTION

Bugzilla::WebService::Server is the base class for the individual WebService API
servers such as XMLRPC, JSONRPC, and REST. You never actually create a
Bugzilla::WebService::Server directly, you only make subclasses of it.

=head1 FUNCTIONS

=over

=item C<bz_etag>

This function is used to store an ETag value that will be used when returning
the data by the different API server modules such as XMLRPC, or REST. The individual
webservice methods can also set the value earlier in the process if needed such as
before a unique update token is added. If a value is not set earlier, an etag will
automatically be created using the returned data except in some cases when an error
has occurred.

=back

=head1 SEE ALSO

L<Bugzilla::WebService::Server::XMLRPC|XMLRPC>, L<Bugzilla::WebService::Server::JSONRPC|JSONRPC>,
and L<Bugzilla::WebService::Server::REST|REST>.

=head1 B<Methods in need of POD>

=over

=item handle_login

=item datetime_format_outbound

=item datetime_format_inbound

=back