add socket verification for pooled pithos backends
[pithos] / snf-pithos-app / pithos / api / public.py
1 # Copyright 2011-2012 GRNET S.A. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
5 # conditions are met:
6 #
7 #   1. Redistributions of source code must retain the above
8 #      copyright notice, this list of conditions and the following
9 #      disclaimer.
10 #
11 #   2. Redistributions in binary form must reproduce the above
12 #      copyright notice, this list of conditions and the following
13 #      disclaimer in the documentation and/or other materials
14 #      provided with the distribution.
15 #
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
28 #
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
33
34 import logging
35
36 from django.http import HttpResponse
37 from django.views.decorators.csrf import csrf_exempt
38
39 from synnefo.lib.astakos import get_user
40
41 from pithos.api.faults import (Fault, BadRequest, ItemNotFound)
42 from pithos.api.util import (put_object_headers, update_manifest_meta,
43                              validate_modification_preconditions, validate_matching_preconditions,
44                              object_data_response, api_method)
45 from pithos.api.short_url import decode_url
46 from pithos.api.settings import AUTHENTICATION_URL, AUTHENTICATION_USERS
47
48
49 logger = logging.getLogger(__name__)
50
51
52 @csrf_exempt
53 def public_demux(request, v_public):
54     get_user(request, AUTHENTICATION_URL, AUTHENTICATION_USERS)
55     if request.method == 'HEAD':
56         return public_meta(request, v_public)
57     elif request.method == 'GET':
58         return public_read(request, v_public)
59     else:
60         return method_not_allowed(request)
61
62
63 @api_method('HEAD', user_required=False)
64 def public_meta(request, v_public):
65     # Normal Response Codes: 204
66     # Error Response Codes: internalServerError (500),
67     #                       itemNotFound (404),
68     #                       badRequest (400)
69
70     try:
71         v_account, v_container, v_object = request.backend.get_public(
72             request.user_uniq,
73             decode_url(v_public))
74         meta = request.backend.get_object_meta(request.user_uniq, v_account,
75                                                v_container, v_object, 'pithos')
76         public = request.backend.get_object_public(
77             request.user_uniq, v_account,
78             v_container, v_object)
79     except:
80         raise ItemNotFound('Object does not exist')
81
82     if not public:
83         raise ItemNotFound('Object does not exist')
84     update_manifest_meta(request, v_account, meta)
85
86     response = HttpResponse(status=200)
87     put_object_headers(response, meta, True)
88     return response
89
90
91 @api_method('GET', user_required=False)
92 def public_read(request, v_public):
93     # Normal Response Codes: 200, 206
94     # Error Response Codes: internalServerError (500),
95     #                       rangeNotSatisfiable (416),
96     #                       preconditionFailed (412),
97     #                       itemNotFound (404),
98     #                       badRequest (400),
99     #                       notModified (304)
100     try:
101         v_account, v_container, v_object = request.backend.get_public(
102             request.user_uniq,
103             decode_url(v_public))
104         meta = request.backend.get_object_meta(request.user_uniq, v_account,
105                                                v_container, v_object, 'pithos')
106         public = request.backend.get_object_public(
107             request.user_uniq, v_account,
108             v_container, v_object)
109     except:
110         raise ItemNotFound('Object does not exist')
111
112     if not public:
113         raise ItemNotFound('Object does not exist')
114     update_manifest_meta(request, v_account, meta)
115
116     # Evaluate conditions.
117     validate_modification_preconditions(request, meta)
118     try:
119         validate_matching_preconditions(request, meta)
120     except NotModified:
121         response = HttpResponse(status=304)
122         response['ETag'] = meta['ETag']
123         return response
124
125     sizes = []
126     hashmaps = []
127     if 'X-Object-Manifest' in meta:
128         try:
129             src_container, src_name = split_container_object_string(
130                 '/' + meta['X-Object-Manifest'])
131             objects = request.backend.list_objects(
132                 request.user_uniq, v_account,
133                 src_container, prefix=src_name, virtual=False)
134         except:
135             raise ItemNotFound('Object does not exist')
136
137         try:
138             for x in objects:
139                 s, h = request.backend.get_object_hashmap(request.user_uniq,
140                                                           v_account, src_container, x[0], x[1])
141                 sizes.append(s)
142                 hashmaps.append(h)
143         except:
144             raise ItemNotFound('Object does not exist')
145     else:
146         try:
147             s, h = request.backend.get_object_hashmap(
148                 request.user_uniq, v_account,
149                 v_container, v_object)
150             sizes.append(s)
151             hashmaps.append(h)
152         except:
153             raise ItemNotFound('Object does not exist')
154
155     if 'Content-Disposition' not in meta:
156         name = v_object.rstrip('/').split('/')[-1]
157         if not name:
158             name = v_public
159         meta['Content-Disposition'] = 'attachment; filename=%s' % (name,)
160
161     return object_data_response(request, sizes, hashmaps, meta, True)
162
163
164 @api_method(user_required=False)
165 def method_not_allowed(request, **v_args):
166     raise ItemNotFound('Object does not exist')