Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

amazon s3 and django - Allow only the users from my website and not the anonymous users

I am using amazon s3 to store uploaded user images. My problems are:

  • If I permit or grantee for me, I cannot upload or download the contents.
  • If I permit or grantee for everyone, all the users and (especially) anonymous users will be able to see the contents, which I don't want.

So, my question is, what do I do so that only the users from my website can upload, download and delete the content?

In that I have conditions that:

  1. Only the users (user1, user2, user3, ...) who are following the user (user0) can download/view the content?
  2. Only the user who uploaded the view can delete the content.

models.py:

def get_upload_file_name(instance, filename):
    return "uploaded_files/%s_%s" %(str(time()).replace('.','_'), filename)

PRIVACY = (
    ('H','Hide'),
    ('F','Followers'),
    ('A','All'),
)

class Status(models.Model):
    body = models.TextField(max_length=200)
    image = models.ImageField(blank=True, null=True, upload_to=get_upload_file_name)
    privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
    pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
    user = models.ForeignKey(User)

settings.py:

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

AWS_ACCESS_KEY_ID = 'FAKEAMAZONKEY'

AWS_SECRET_ACCESS_KEY = 'FAKEAMAZONSECRETKEY'

AWS_STORAGE_BUCKET_NAME = 'fakebucketname'

Update

Model for relationship between users

class Person(models.Model):
    user = models.OneToOneField(User)
    relationships = models.ManyToManyField('self', through='Relationship', 
                                           symmetrical=False, 
                                           related_name='related_to')

    def __unicode__(self):
        return self.user.username

    def add_relationship(self, person, status):
        relationship, created = Relationship.objects.get_or_create(
            from_person=self,
            to_person=person,
            status=status)
        return relationship

    def remove_relationship(self, person, status):
        Relationship.objects.filter(
            from_person=self, 
            to_person=person,
            status=status).delete()
        return

    def get_relationships(self, status):
        return self.relationships.filter(
            to_people__status=status, 
            to_people__from_person=self)

    def get_related_to(self, status):
        return self.related_to.filter(
            from_people__status=status, 
            from_people__to_person=self)

    def get_following(self):
        return self.get_relationships(RELATIONSHIP_FOLLOWING)

    def get_followers(self):
        return self.get_related_to(RELATIONSHIP_FOLLOWING)

    def get_friends(self):
        return self.relationships.filter(
            to_people__status=RELATIONSHIP_FOLLOWING, 
            to_people__from_person=self,
            from_people__status=RELATIONSHIP_FOLLOWING, 
            from_people__to_person=self)


RELATIONSHIP_FOLLOWING = 1
RELATIONSHIP_BLOCKED = 2
RELATIONSHIP_STATUSES = (
    (RELATIONSHIP_FOLLOWING, 'Following'),
    (RELATIONSHIP_BLOCKED, 'Blocked'),
)

class Relationship(models.Model):
    from_person = models.ForeignKey(Person, related_name='from_people')
    to_person = models.ForeignKey(Person, related_name='to_people')
    status = models.IntegerField(choices=RELATIONSHIP_STATUSES)

    def __unicode__(self):
        return "%s %s %s" % (self.from_person, self.get_status_display(), self.to_person)


class Activity(models.Model):
    actor = models.ForeignKey(User)
    action = models.CharField(max_length=100)
    content_type = models.ForeignKey(ContentType, related_name="content_type")
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    element_type = models.ForeignKey(ContentType, related_name="element_type", blank=True, null=True)
    element_id = models.PositiveIntegerField(blank=True, null=True)
    element_object = generic.GenericForeignKey('element_type', 'element_id')
    pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)

    class Meta:
        verbose_name = 'Activity'
        verbose_name_plural = 'Activities'
        ordering = ['-pub_date']

    def __unicode__(self):
        return ("%s %s") % (self.actor.username, self.action)

    def get_rendered_html(self, user=None):
        if self.element_type:
            template_name = '%s_activity.html' %(self.element_type.name)
        else:
            template_name = '%s_activity.html' %(self.content_type.name)

        return render_to_string(template_name, {
            'object':self.content_object,
            'actor':self.actor,
            'action':self.action,
            'element_object':self.element_object,
            'user':user,
            'pub_date':self.pub_date
            })
like image 558
Kakar Avatar asked Feb 06 '15 11:02

Kakar


1 Answers

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,,,

like image 106
Bernhard Vallant Avatar answered Sep 27 '22 19:09

Bernhard Vallant