internal.block.management

Block storage management module.

  1"""Block storage management module."""
  2
  3import asyncio
  4from io import BytesIO
  5
  6from fastapi import HTTPException, UploadFile, status
  7from minio import Minio, S3Error
  8from PIL import Image
  9
 10from internal.settings.env import block_settings
 11
 12PROFILE_IMAGES_BUCKET = "profileimages"
 13BUNDLE_IMAGES_BUCKET = "bundleimages"
 14MAX_SIZE = 5 * 1024 * 1024  # 5mb
 15
 16
 17async def process_image(file: UploadFile) -> bytes:
 18    """Confirm image and compress.
 19
 20    Args:
 21        file: uploaded file
 22
 23    Returns:
 24        compressed image
 25
 26    Raises:
 27        HTTPException: if not jpeg or larger then 5mb
 28    """
 29    if file.content_type != "image/jpeg":
 30        raise HTTPException(
 31            status.HTTP_400_BAD_REQUEST, "only jpeg images are accepted"
 32        )
 33    file_bytes = await file.read()
 34    if len(file_bytes) > MAX_SIZE:
 35        raise HTTPException(status_code=400, detail="image must be under 5mb")
 36    image = Image.open(BytesIO(file_bytes))
 37    output = BytesIO()
 38    image.save(output, format="JPEG", quality=85, optimize=True)
 39    return output.getvalue()
 40
 41
 42class BlockManagement:
 43    """Block storage management class."""
 44
 45    client: Minio
 46
 47    def initialise(self) -> None:
 48        """Initialise block storage connection."""
 49        self.client = Minio(
 50            endpoint=block_settings.url_port,
 51            access_key=block_settings.access_key,
 52            secret_key=block_settings.secret_key,
 53            secure=False,
 54        )
 55        if not self.client.bucket_exists(PROFILE_IMAGES_BUCKET):
 56            self.client.make_bucket(PROFILE_IMAGES_BUCKET)
 57        if not self.client.bucket_exists(BUNDLE_IMAGES_BUCKET):
 58            self.client.make_bucket(BUNDLE_IMAGES_BUCKET)
 59
 60    async def upload_profile_image(self, user_id: int, file: UploadFile) -> None:
 61        """Change user profile image.
 62
 63        Args:
 64            user_id: user id
 65            file: uploaded file
 66        """
 67        image_bytes = await process_image(file)
 68        await asyncio.to_thread(
 69            self.client.put_object,
 70            bucket_name=PROFILE_IMAGES_BUCKET,
 71            object_name=f"{user_id}.jpeg",
 72            data=BytesIO(image_bytes),
 73            length=len(image_bytes),
 74            content_type="image/jpeg",
 75        )
 76
 77    async def upload_bundle_image(self, bundle_id: int, file: UploadFile) -> None:
 78        """Change bundle image.
 79
 80        Args:
 81            bundle_id: bundle id
 82            file: uploaded file
 83        """
 84        image_bytes = await process_image(file)
 85        await asyncio.to_thread(
 86            self.client.put_object,
 87            bucket_name=BUNDLE_IMAGES_BUCKET,
 88            object_name=f"{bundle_id}.jpeg",
 89            data=BytesIO(image_bytes),
 90            length=len(image_bytes),
 91            content_type="image/jpeg",
 92        )
 93
 94    def get_profile_image(self, user_id: int) -> bytes:
 95        """Get user profile image.
 96
 97        Args:
 98            user_id: user id
 99
100        Returns:
101            image bytes
102
103        Raises:
104            HTTPException: if failed to get image
105        """
106        try:
107            image = self.client.get_object(PROFILE_IMAGES_BUCKET, f"{user_id}.jpeg")
108            try:
109                return image.read()
110            finally:
111                image.close()
112                image.release_conn()
113        except S3Error as err:
114            if err.code == "NoSuchKey":
115                raise HTTPException(status.HTTP_404_NOT_FOUND, "image not found")
116            raise HTTPException(
117                status.HTTP_500_INTERNAL_SERVER_ERROR, "failed to get image"
118            )
119
120    def get_bundle_image(self, bundle_id: int) -> bytes:
121        """Get bundle image.
122
123        Args:
124            bundle_id: bundle id
125
126        Returns:
127            image bytes
128
129        Raises:
130            HTTPException: if failed to get image
131        """
132        try:
133            image = self.client.get_object(BUNDLE_IMAGES_BUCKET, f"{bundle_id}.jpeg")
134            try:
135                return image.read()
136            finally:
137                image.close()
138                image.release_conn()
139        except S3Error as err:
140            if err.code == "NoSuchKey":
141                raise HTTPException(status.HTTP_404_NOT_FOUND, "image not found")
142            raise HTTPException(
143                status.HTTP_500_INTERNAL_SERVER_ERROR, "failed to get image"
144            )
145
146
147block_management = BlockManagement()
PROFILE_IMAGES_BUCKET = 'profileimages'
BUNDLE_IMAGES_BUCKET = 'bundleimages'
MAX_SIZE = 5242880
async def process_image(file: fastapi.datastructures.UploadFile) -> bytes:
18async def process_image(file: UploadFile) -> bytes:
19    """Confirm image and compress.
20
21    Args:
22        file: uploaded file
23
24    Returns:
25        compressed image
26
27    Raises:
28        HTTPException: if not jpeg or larger then 5mb
29    """
30    if file.content_type != "image/jpeg":
31        raise HTTPException(
32            status.HTTP_400_BAD_REQUEST, "only jpeg images are accepted"
33        )
34    file_bytes = await file.read()
35    if len(file_bytes) > MAX_SIZE:
36        raise HTTPException(status_code=400, detail="image must be under 5mb")
37    image = Image.open(BytesIO(file_bytes))
38    output = BytesIO()
39    image.save(output, format="JPEG", quality=85, optimize=True)
40    return output.getvalue()

Confirm image and compress.

Arguments:
  • file: uploaded file
Returns:

compressed image

Raises:
  • HTTPException: if not jpeg or larger then 5mb
class BlockManagement:
 43class BlockManagement:
 44    """Block storage management class."""
 45
 46    client: Minio
 47
 48    def initialise(self) -> None:
 49        """Initialise block storage connection."""
 50        self.client = Minio(
 51            endpoint=block_settings.url_port,
 52            access_key=block_settings.access_key,
 53            secret_key=block_settings.secret_key,
 54            secure=False,
 55        )
 56        if not self.client.bucket_exists(PROFILE_IMAGES_BUCKET):
 57            self.client.make_bucket(PROFILE_IMAGES_BUCKET)
 58        if not self.client.bucket_exists(BUNDLE_IMAGES_BUCKET):
 59            self.client.make_bucket(BUNDLE_IMAGES_BUCKET)
 60
 61    async def upload_profile_image(self, user_id: int, file: UploadFile) -> None:
 62        """Change user profile image.
 63
 64        Args:
 65            user_id: user id
 66            file: uploaded file
 67        """
 68        image_bytes = await process_image(file)
 69        await asyncio.to_thread(
 70            self.client.put_object,
 71            bucket_name=PROFILE_IMAGES_BUCKET,
 72            object_name=f"{user_id}.jpeg",
 73            data=BytesIO(image_bytes),
 74            length=len(image_bytes),
 75            content_type="image/jpeg",
 76        )
 77
 78    async def upload_bundle_image(self, bundle_id: int, file: UploadFile) -> None:
 79        """Change bundle image.
 80
 81        Args:
 82            bundle_id: bundle id
 83            file: uploaded file
 84        """
 85        image_bytes = await process_image(file)
 86        await asyncio.to_thread(
 87            self.client.put_object,
 88            bucket_name=BUNDLE_IMAGES_BUCKET,
 89            object_name=f"{bundle_id}.jpeg",
 90            data=BytesIO(image_bytes),
 91            length=len(image_bytes),
 92            content_type="image/jpeg",
 93        )
 94
 95    def get_profile_image(self, user_id: int) -> bytes:
 96        """Get user profile image.
 97
 98        Args:
 99            user_id: user id
100
101        Returns:
102            image bytes
103
104        Raises:
105            HTTPException: if failed to get image
106        """
107        try:
108            image = self.client.get_object(PROFILE_IMAGES_BUCKET, f"{user_id}.jpeg")
109            try:
110                return image.read()
111            finally:
112                image.close()
113                image.release_conn()
114        except S3Error as err:
115            if err.code == "NoSuchKey":
116                raise HTTPException(status.HTTP_404_NOT_FOUND, "image not found")
117            raise HTTPException(
118                status.HTTP_500_INTERNAL_SERVER_ERROR, "failed to get image"
119            )
120
121    def get_bundle_image(self, bundle_id: int) -> bytes:
122        """Get bundle image.
123
124        Args:
125            bundle_id: bundle id
126
127        Returns:
128            image bytes
129
130        Raises:
131            HTTPException: if failed to get image
132        """
133        try:
134            image = self.client.get_object(BUNDLE_IMAGES_BUCKET, f"{bundle_id}.jpeg")
135            try:
136                return image.read()
137            finally:
138                image.close()
139                image.release_conn()
140        except S3Error as err:
141            if err.code == "NoSuchKey":
142                raise HTTPException(status.HTTP_404_NOT_FOUND, "image not found")
143            raise HTTPException(
144                status.HTTP_500_INTERNAL_SERVER_ERROR, "failed to get image"
145            )

Block storage management class.

client: minio.api.Minio
def initialise(self) -> None:
48    def initialise(self) -> None:
49        """Initialise block storage connection."""
50        self.client = Minio(
51            endpoint=block_settings.url_port,
52            access_key=block_settings.access_key,
53            secret_key=block_settings.secret_key,
54            secure=False,
55        )
56        if not self.client.bucket_exists(PROFILE_IMAGES_BUCKET):
57            self.client.make_bucket(PROFILE_IMAGES_BUCKET)
58        if not self.client.bucket_exists(BUNDLE_IMAGES_BUCKET):
59            self.client.make_bucket(BUNDLE_IMAGES_BUCKET)

Initialise block storage connection.

async def upload_profile_image(self, user_id: int, file: fastapi.datastructures.UploadFile) -> None:
61    async def upload_profile_image(self, user_id: int, file: UploadFile) -> None:
62        """Change user profile image.
63
64        Args:
65            user_id: user id
66            file: uploaded file
67        """
68        image_bytes = await process_image(file)
69        await asyncio.to_thread(
70            self.client.put_object,
71            bucket_name=PROFILE_IMAGES_BUCKET,
72            object_name=f"{user_id}.jpeg",
73            data=BytesIO(image_bytes),
74            length=len(image_bytes),
75            content_type="image/jpeg",
76        )

Change user profile image.

Arguments:
  • user_id: user id
  • file: uploaded file
async def upload_bundle_image(self, bundle_id: int, file: fastapi.datastructures.UploadFile) -> None:
78    async def upload_bundle_image(self, bundle_id: int, file: UploadFile) -> None:
79        """Change bundle image.
80
81        Args:
82            bundle_id: bundle id
83            file: uploaded file
84        """
85        image_bytes = await process_image(file)
86        await asyncio.to_thread(
87            self.client.put_object,
88            bucket_name=BUNDLE_IMAGES_BUCKET,
89            object_name=f"{bundle_id}.jpeg",
90            data=BytesIO(image_bytes),
91            length=len(image_bytes),
92            content_type="image/jpeg",
93        )

Change bundle image.

Arguments:
  • bundle_id: bundle id
  • file: uploaded file
def get_profile_image(self, user_id: int) -> bytes:
 95    def get_profile_image(self, user_id: int) -> bytes:
 96        """Get user profile image.
 97
 98        Args:
 99            user_id: user id
100
101        Returns:
102            image bytes
103
104        Raises:
105            HTTPException: if failed to get image
106        """
107        try:
108            image = self.client.get_object(PROFILE_IMAGES_BUCKET, f"{user_id}.jpeg")
109            try:
110                return image.read()
111            finally:
112                image.close()
113                image.release_conn()
114        except S3Error as err:
115            if err.code == "NoSuchKey":
116                raise HTTPException(status.HTTP_404_NOT_FOUND, "image not found")
117            raise HTTPException(
118                status.HTTP_500_INTERNAL_SERVER_ERROR, "failed to get image"
119            )

Get user profile image.

Arguments:
  • user_id: user id
Returns:

image bytes

Raises:
  • HTTPException: if failed to get image
def get_bundle_image(self, bundle_id: int) -> bytes:
121    def get_bundle_image(self, bundle_id: int) -> bytes:
122        """Get bundle image.
123
124        Args:
125            bundle_id: bundle id
126
127        Returns:
128            image bytes
129
130        Raises:
131            HTTPException: if failed to get image
132        """
133        try:
134            image = self.client.get_object(BUNDLE_IMAGES_BUCKET, f"{bundle_id}.jpeg")
135            try:
136                return image.read()
137            finally:
138                image.close()
139                image.release_conn()
140        except S3Error as err:
141            if err.code == "NoSuchKey":
142                raise HTTPException(status.HTTP_404_NOT_FOUND, "image not found")
143            raise HTTPException(
144                status.HTTP_500_INTERNAL_SERVER_ERROR, "failed to get image"
145            )

Get bundle image.

Arguments:
  • bundle_id: bundle id
Returns:

image bytes

Raises:
  • HTTPException: if failed to get image
block_management = <BlockManagement object>