prisma-client-py icon indicating copy to clipboard operation
prisma-client-py copied to clipboard

Consider refactoring Base64 API

Open RobertCraigie opened this issue 2 years ago • 3 comments

Problem

It is not obvious how Base64 objects should be constructed, it would be a very easy mistake to construct the object like so:

data = Base64(b'my binary data')
# when it should be
data = Base64(base64.b64encode(b'my binary data'))
# or
data = Base64.encode(b'my binary data')

Suggested solution

One solution to this would be to disable construction through __init__ and instead require a classmethod to be used, the API would then look like this:

data = Base64.from_data(b'my binary data')
data = Base64.from_b64(base64.b64encode(b'my binary data'))

We would then deprecate the previous API and remove it in a later release.

RobertCraigie avatar Mar 04 '22 18:03 RobertCraigie

Unfortunately the Base64 Type is not Pydantic friendly and fastAPI gives erroring out:

ValueError: [TypeError("'Base64' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]

I'm trying to save a binary b64 encoded password in the database and retrieve but with this typing generated the server errors out

Ali-Parandeh avatar Aug 13 '22 20:08 Ali-Parandeh

Oh that is unfortunate, sorry about that @Ali-Parandeh.

Could you please provide example code that results in that error?

RobertCraigie avatar Aug 13 '22 21:08 RobertCraigie

@RobertCraigie Thank you! Absolutely

Set this database schema in a PostgreSQL

generator client {
  provider  = "prisma-client-py"
  interface = "asyncio"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

enum Role {
  USER
  ADMIN
}

model User {
id       String         @id             @default(dbgenerated("gen_random_uuid()")) @db.Uuid
email    String         @unique
password Bytes
disabled Boolean        @default(false)
role     Role           @default(USER)

}

The try creating a user using Prisma and Fastapi /create endpoint

from prisma import Base64
from prisma.models import User

from fastapi import FastAPI

app = FastAPI()

def hash_password(password: str) -> Base64:
    return Base64.encode(bcrypt.hashpw(password.encode("UTF-8"), bcrypt.gensalt()))

async def create(user: User) -> User:
    async with Prisma() as db:
        user = await db.user.create(
            {
                "email": user.email,
                "password": hash_password(user.password),
                "role": user.role,
            }
        )
    return user


Ali-Parandeh avatar Aug 14 '22 14:08 Ali-Parandeh