7👍
When loading the files directly you can use Amazon’s Query String Authentication where you have to include a signature into the URL to verify that you are allowed to get the files.
Your app can use boto’s Key.generate_url
method to create such an url. You should also add an expiry time after which the link will not be valid anymore.
EDIT: A more detailled description about how to set this up using boto,,,
3👍
Since boto3 is out, we can use:
https://github.com/boto/boto3/blob/develop/docs/source/guide/s3-presigned-urls.rst
import boto3
s3_client = boto3.client('s3')
try:
response = s3_client.generate_presigned_url(ClientMethod=client_method_name,
Params=method_parameters,
ExpiresIn=expiration,
HttpMethod=http_method)
except ClientError as e:
logging.error(e)
return None
# The response contains the presigned URL
return response
We can also use similar method for uploading objects in the same ref link.
2👍
So as George said, you need to take 2 steps to make this work, although instead of granting access to ec2 instances (never used that method) i recommend just granting rights to your specific keys (have used this method extensively)
- Allow full control to the bucket resources to the user you wish.
Here are the amazon on how permissions work. They are not trivial, so you need to understand who the principal account is, and whether you’re using its keys or the keys for an IAM user. Regardless, your keys should have full access to the resources (Hope it’s your bucket, not someone else’s, cuz then things a little more complicated)
http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-access-control.html
- Implement business logic to:
- allow your app users to create S3 files
- allow users who are following user X to view/ download files created by user X
- allow only user X to delete files that he created
For creating the resources:
– if the backend you provided works, and you’ve configured your S3 rights well, you shouldn’t have to do anything. However, to check that your keys are not an issue, do this:
from boto.s3.connection import S3Connection as s3c
connection = s3c('your-aws-access-key', 'your-aws-secret-key')
bucket = connection.get_bucket('your-bucket-name')
new_key = bucket.new_key('your-key-name') #meaning the name of the file
# https://github.com/boto/boto/blob/develop/boto/s3/bucket.py#L611
new_key.send_file(file_object) #this will upload the file
# https://github.com/boto/boto/blob/develop/boto/s3/key.py#L709
If everything works well, you should be able to see your file in the S3 browser – if not, you’ll have to get back to the documentation about S3 access rights.
To only allow users who are following user X have access to the files that user uploaded:
Your models.py
file doesn’t say how you’ve implemented the follow
logic. I can’t tell who is following who. Do you have your own custom User
model? Do you use Django’s but with an extension? Do you have your own model which links users? Share more information about how one user ‘follows’ another, and then I could even share code fragments.
To allow user X to delete its own files:
I’m guessing that the Status.user field will already contain a reference to the user that created the image. If so: put this in your view:
def picture_deletion_view(request, status_identifier ...):
try:
status = Status.objects.filter(id_or_some_identifier=status_identifier)
except Status.DoesNotExist:
return SomeHttpResponse()
if request.user.id == status.user.id:
# you can delete the picture and redirect... to somewhere
else:
# you can't delete! redirect...or something
- Django Rest Framework override model fields in modelserialzer
- How to parse URL encoded data recieved via POST
- Execute code on model creation in Django
- Django File Upload and Rename
- Is there any way to use GUIDs in django?
0👍
This is logic which is handled by the view and template.
In the template for example you can have a block like this {% if user.is_authenticated %}
with a uploadform and in the view you can check also if the user in authenticated and only then load your stuff to s3
-1👍
so i can’t speak to the aws.s3 piece, but for django, the best way to limit who has access to a view is to require login through django’s login_required
decorator:
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
or, if you want to expose all of the view, but not parts of the page (links, etc), you could put that information into the template, as @t_io said, but the django docs strongly recommend against putting too much processing logic in the templates, as it slows down the site. it would be better to put that information in the view:
@login_required
def image_view(request):
user = request.user
# this list has the user's own images
mine = []
for status in user.status_set.all():
mine.append(status.image)
# this list has the images the user can see (relationship-based)
following = []
friends = []
# you can get the person from the user
person = user.person
for status in person.get_friends().all():
friends.append(status.image)
for status in person.get_following().all():
following.append(status.image)
ctx = dict(user=request.user, friends=friends, following=following, mine=mine)
return render("template.html", ctx)
and in the template, you could walk the lists
{% for img in mine %}
<li><a href=...></a></li>
{% endfor %}
{% for img in following %}
<li><a href=...></a></li>
{% endfor %}
…you get the idea
to prevent people from just navigating directly to the media url, you could use sendfile (python library), or the apache/nginx equivalent. so you’d need another view:
import sendfile
from django.conf import settings
@login_required
def handle_media(request, path=None):
try:
requested_file = os.path.join(settings.MEDIA_ROOT, path)
return sendfile.sendfile(request, requested_file)
except:
pass
return HttpResponseNotFound('<h1>Page not found {}</h1>'.format(path))
and then you’d need an additional url (urls.py):
urlpatterns = patterns('',
url(r'/media/(?P<path>[a-zA-Z0-9_- /]+)$', views.handle_media),
)
see django-sendfile for use on sendfile
- Django test error only with pycharm – Not the terminal | apps aren't loaded yet
- Clone an inherited django model instance