アップロードされたユーザー画像を保存するためにAmazons3を使用しています。私の問題は次のとおりです。
許可または被付与者の場合、コンテンツをアップロードまたはダウンロードすることはできません。 すべてのユーザーに許可または許可を与えると、すべてのユーザーと(特に)匿名ユーザーが、私が望まないコンテンツを見ることができるようになります。 だから、私の質問は、私のウェブサイトのユーザーだけがコンテンツをアップロード、ダウンロード、削除できるようにするにはどうすればよいですか?
その中で私は次のような条件を持っています:
ユーザーをフォローしているユーザー(user1、user2、user3、...)のみ
(user0)コンテンツをダウンロード/表示できますか? ビューをアップロードしたユーザーのみがコンテンツを削除できます。 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'
更新ユーザー間の関係のモデル
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
})
推奨答え
ファイルを直接ロードする場合は、
Amazon's Query String Authenticationを使用して、URLに署名を含め、ファイルの取得が許可されていることを確認する必要があります。
アプリはbotoの
Key.generate_url
methodを使用してそのようなURLを作成できます。また、リンクが無効になるまでの有効期限を追加する必要があります。
編集:botoを使用してこれを設定する方法についてのより詳細な
description 、、、
その他答え #1
したがって、Georgeが言ったように、これを機能させるには2つの手順を実行する必要がありますが、ec2インスタンスへのアクセスを許可する代わりに(そのメソッドを使用したことはありません)、特定のキーに権限を付与することをお勧めします(このメソッドを広範囲に使用しました)
必要なユーザーにバケットリソースのフルコントロールを許可します。 これがパーミッションの仕組みに関するアマゾンです。これらは簡単ではないため、プリンシパルアカウントが誰であるか、およびそのキーを使用しているか、IAMユーザーのキーを使用しているかを理解する必要があります。とにかく、あなたの鍵はリソースへの完全なアクセス権を持っている必要があります(それがあなたのバケツであり、他の誰かのものではないことを願っています、それならもう少し複雑です)
http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-access-control.htmlビジネスロジックを次のように実装します。
を使用すると、アプリユーザーはS3ファイルを作成できますを使用すると、ユーザーXをフォローしているユーザーは、ユーザーXによって作成されたファイルを表示/ダウンロードできます。は、ユーザーXのみが自分で作成したファイルを削除できるようにします リソースを作成する場合:
-提供したバックエンドが機能し、S3権限を適切に設定している場合は、何もする必要はありません。ただし、キーが問題ではないことを確認するには、次のようにします。
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
すべてが正常に機能する場合は、S3ブラウザーでファイルを表示できるはずです。そうでない場合は、S3アクセス権に関するドキュメントに戻る必要があります。
ユーザーXをフォローしているユーザーのみに、ユーザーがアップロードしたファイルへのアクセスを許可するには、次のようにします。
models.py
ファイルには、
follow
ロジックをどのように実装したかが記載されていません。誰が誰をフォローしているのかわかりません。独自のカスタム
User
モデルはありますか? Djangoを使用していますが、拡張子が付いていますか?ユーザーをリンクする独自のモデルはありますか?あるユーザーが別のユーザーを「フォロー」する方法についての詳細を共有すると、コードフラグメントを共有することもできます。
ユーザーXが自分のファイルを削除できるようにするには:
Status.userフィールドには、画像を作成したユーザーへの参照がすでに含まれていると思います。もしそうなら:これをあなたの見解に入れてください:
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
その他答え #2
boto3が出ているので、次を使用できます。
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
同じ参照リンクにオブジェクトをアップロードするために同様の方法を使用することもできます。
その他答え #3
これは、ビューとテンプレートによって処理されるロジックです。
たとえば、テンプレートでは、uploadformを使用してこの
{% if user.is_authenticated %}
のようなブロックを作成できます。ビューでは、ユーザーが認証されているかどうかを確認してから、s3にコンテンツをロードすることもできます。
その他答え #4
そのため、aws.s3の部分と話すことはできませんが、djangoの場合、ビューにアクセスできるユーザーを制限する最善の方法は、djangoの
login_required
デコレーターを介してログインすることを要求することです。
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
または、ページの一部(リンクなど)ではなくすべてのビューを公開したい場合は、@ t_ioが言ったように、その情報をテンプレートに入れることができますが、djangoドキュメントでは、処理ロジックを多すぎないようにすることを強くお勧めしますテンプレートでは、サイトの速度が低下するためです。その情報をビューに配置することをお勧めします。
@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)
テンプレートでは、リストを歩くことができます
{% for img in mine %}
<li><a href=...></a></li>
{% endfor %}
{% for img in following %}
<li><a href=...></a></li>
{% endfor %}
...あなたはアイデアを得る
人々がメディアのURLに直接移動するのを防ぐために、sendfile(pythonライブラリ)または同等のapache / nginxを使用できます。したがって、別のビューが必要になります。
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))
次に、追加のURL(urls.py)が必要になります。
urlpatterns = patterns('',
url(r'/media/(?P<path>[a-zA-Z0-9_- /]+)$', views.handle_media),
)
sendfileでの使用については
django-sendfileを参照してください