theriverman / django-minio-backend

Minio Backend for Django
https://pypi.org/project/django-minio-backend/
MIT License
111 stars 22 forks source link

How can I create private link for files? #24

Closed ghorbani-mohammad closed 3 years ago

ghorbani-mohammad commented 3 years ago

Hello there,

I need to create a private link for my files for a specific duration. For example, if my model has an image field I need to something like this:

obj.image.create_presignedurl()

and this link must be valid for a specific time, How I can achieve this?

a13xg0 commented 3 years ago

Regarding url method you might just get the URL and if your bucket is private you will get your presigned URL with valid time according to your settings MINIO_URL_EXPIRY_HOURS

theriverman commented 3 years ago

Thanks for stepping in, @a13xg0 ! I'm closing this now. If you're still experiencing problems, @ghorbani-mohammad, please open another issue!

Podolyan98 commented 1 year ago

@a13xg0 Hello. Through the Django admin panel the URL method works, but through the my API I only see the direct path:

GET http://localhost:8888/api/users/aa658d18-e0b0-4537-8cb6-7e3c2251c197

Response:

{
"id": "aa658d18-e0b0-4537-8cb6-7e3c2251c197",
"photo": "aa658d18-e0b0-4537-8cb6-7e3c2251c197/2022-12-16_11-34-01.png",
"license": "aa658d18-e0b0-4537-8cb6-7e3c2251c197/file.md",

How to get pre-signed url?

a13xg0 commented 1 year ago

@Podolyan98 Hi! My first guess looking at your response, is that you just got the value from your DB, not the resolved URL thru the minio's backend. You may check the order of middleware in your config.

Podolyan98 commented 1 year ago

@a13xg0 How can I get the resolved url through the minio backend?

models.py:

photo = models.ImageField(storage=MinioBackend(bucket_name='django-backend-users-private', replace_existing=True), upload_to=user_directory_path, null=True, blank=True)
license = models.FileField(storage=MinioBackend(bucket_name='django-backend-users-private', replace_existing=True), upload_to=user_directory_path, null=True, blank=True)

settings.py:

MINIO_ENDPOINT = 'docs.domain.com'
MINIO_EXTERNAL_ENDPOINT = 'docs.domain.com'
MINIO_EXTERNAL_ENDPOINT_USE_HTTPS = True 
MINIO_ACCESS_KEY = '123'
MINIO_SECRET_KEY = '123'
MINIO_USE_HTTPS = True
MINIO_URL_EXPIRY_HOURS = timedelta(days=1)
MINIO_PRIVATE_BUCKETS = [
    'django-backend-dev-private',
    'django-backend-users-private',
]
MINIO_POLICY_HOOKS: List[Tuple[str, dict]] = []
MINIO_BUCKET_CHECK_ON_SAVE = True
theriverman commented 1 year ago

@Podolyan98 you can get the url by accessing .file.url. in your case it would be either photo.file.url or license.file.url. Using an example from DjangoExampleApplication:

from DjangoExampleApplication.models import PrivateAttachment
pa = PrivateAttachment.objects.first()
print(pa.file.url)
'https://play.min.io/xxxxx/2022-12-17/user/xxxx.png?X-Amz-Algorithm=(........)'
Podolyan98 commented 1 year ago

@theriverman In models.py I specified the method that is used to get the private link in the APIView.

models.py:

photo_0 = models.ImageField(storage=MinioBackend(bucket_name='django-backend-users-private', replace_existing=True), upload_to=User_directory_path('photo_0'), null=True, blank=True)

@property
def photo_0_url(self):
    if self.photo_0 and hasattr(self.photo_0, 'url'):
        return self.photo_0.url

views.py:

def get(self, request, pk):
    try:
        queryset = User.objects.filter(id=pk).first()
        user_dict = queryset.values().first()
        # overwrite file path using resolved URL thru the minio's backend
        user_dict['photo_0'] = user.photo_0_url
        return Response(user_dict, status=status.HTTP_200_OK) 
    except Exception as error:
        logger.error(traceback.format_exc())
        raise APIException(error)

It works. The problem is that there are a lot of fields like ImageField and FileField, I need to overwrite each field in views.py, for example user_dict['photo_0'] = user.photo_0_url. Is it possible to call similar methods automatically for every ImageField or FileField?

By the way, when creating or updating records with ImageField and FileField, private links are automatically generated.

theriverman commented 1 year ago

@Podolyan98 I don't see how your question is related to this third-party package. What you're asking is more of a generic Django question which should not be discussed here.