Use a field's generated value as another field's default value in prisma? - postgresql

I have this User model in prisma (postgres), I want to use the same value cuid() generates for id in username. How do I achieve that?
model User {
id String #id #default(cuid())
username String? #unique
}
I know I can just regenerate cuid() for a different value, it would still work for what I am working on, but I want user's id and username to be same by default.

Related

What should I use as validation tool using NestJS and MongoDB?

Let's say, I am creating application using NestJS. I use MongoDB as a database and mongoose as ODM. So, NestJS has it's own way to validate data - ValidationPipe's. On the other side, there is mongoose built-in ways to validate data that being pushed into DB.
The question is - can I use only NestJS validation or do I need also second-check my data using mongoose validation tools?
Personally, I can't see why should I use additional layer of validation if I already have NestJS validation. But maybe there is best-practice or something?
Each database validates input data and emits an error if found. However, you must take into account your schema file. For instance, if you are using Prisma(It doesn't actually matter) and you have a User model like below
model User {
id String #id #default(auto()) #map("_id") #db.ObjectId
email String #unique
password String
name String
image String?
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##map("user")
}
As you can see there is only one optional property "image". Whether you pass a value for image property or not, the database will insert the data as a row. On the other hand, the properties without "?" mark at the end of the type, will not be stored if you don't pass them and emit an error.
Therefore, if you modeled schema according to your business logic, you don't need to validate twice but only add an exception handling like the one below.
const user = await this.usersService.findOne('id...')
.catch((e) => new NotFoundException({ message: 'No user found.' }))

Conditional unique contstraint in prisma/postgres schema? Is it possible?

I am trying to implement an AuthProvider model for our prisma schema, using postgres as the provider. You can see the start of my work here:
model AuthProvider {
id String #id #default(cuid())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
type AuthProviderType
externalUserId String? #unique
email String #unique // this should not be unique if the userId is the same among two AuthProviders
emailVerified Boolean? #default(false)
password String? // Hashed password
user User #relation(fields: [userId], references: [id])
userId String
##map("auth_providers")
}
A user can have many authentication providers, such as email + password, google, twitter. They can sign in with whatever they choose once they have connected it
Now here comes the tricky part:
what I want to accomplish is to make it so an AuthProviders email is unique, but ONLY if the userId of that AuthProvider is different.
So a user should be able to have several AuthProviders with the same email, but if one user tries to connect an authprovider with an email that another user already has connected (on any of their authproviders), then it should fail via unique constraint.
would this be achieveable just using unique constraints/indexes in the schema?

Use of #map and ##map for Prisma schema

I am new to Prisma and have been wondering what is the use of #map and ##map for Prisma schema? I have looked at their website: https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#map but still don't fully get the purpose of #map and ##map.
From what I can comprehend, if I have something like
lastName String #map("last_name") #db.VarChar(256)
it maps "last_name" to lastname? But I am not too sure when I will need this.
Thank you! Appreciate any help.
#map can be used to assign a different name to your columns names, for example if the column name for a table in your database is userLastName but you want to assign a different name (user_last_name) and access it with a different name in your generated PrismaClient you can use #map attribute for it.
model User {
id Int #id #default(autoincrement())
userLastName String #map("user_last_name")
}
#map does not rename the columns / fields in the database
#map does change the field names in the generated prisma client
On the other hand ##map is used to assign a different name to a model and not a particular field. So for example if a table name is UserDetails and you want to access it as user_details in the generated client you can use ##map attribute.
model UserDetails {
id Int #id #default(autoincrement())
name String
##map("users_details")
}
Maps a field name or enum value from the Prisma schema to a column or document field with a different name in the database
A use case could be people integrating existing database with prisma and want to use different naming conventions between database & prisma client.
For example, one might use snakecase for database column but want to use camelcase for prisma client, then they will do:
model User {
createdAt String #map("created_at")
}
Same thing with ##map, but just for table name.
Detailed guide from prisma:
https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/use-custom-model-and-field-names

How to map a navigational property to a table where it isn't a key column?

I have an Entity like:
User
Id
Username
public virtual List<String> CountryNames { get;set; }
And it has a property for CountryNames as seen above, and this is linked to another table but it isn't linked on a key column.
The CountryNames property should get all UserCountry rows that have the Username.
UserCountry
Id
CountrName
Username
How can I configure the User model to do this?
I realize this is bad design, I'm not looking for schema design advise at this point as it is out of my hands.
I'm using EF6.

How to let ebean not generate any value for the ID?

I'm using Ebean, and define such a model:
#Entity
#Table(name = "users")
public class User extends Model {
#Id
public String id;
public String email;
public String name;
}
You can see the field id is String, and has a #Id annotation.
Now I save it:
User user = new User();
user.id = "abc";
user.email = "a#a.com";
Ebean.save(user);
But when I saved it, I found the value of it's id is: 1, not abc I specified.
I checked the sql, found the table generate:
create table users (
id varchar(255) not null,
email varchar(255),
name varchar(255),
constraint pk_users primary key (id))
;
create sequence users_seq;
You can see there is a seq users_seq which has been used when inserting a user.
How to define the model or how to configure Ebean to let it not do anything to the #Id field? Just let it use my specified value?
===========
UPDATE
Sorry, guys, I found this strange behavior is because of my mistake!
Yes, I use it with playframework 1, and I tried to create a play-ebean module for myself. But there is something wrong: When I save a model, I cleared the id value by mistake!
So the assigned value abc is missing, then Ebean will try to use a seq to get a new value for it.
Thanks for all you help, and sorry again, I will be more careful when I ask question next time.
Isn't it better idea to create another unique field and use it optionally ie. String userCode or something?
Play with Ebean uses auto incrementation of Id's to make sure the Id is unique so I'd personally didn't change that as all docs assumes that id of model is some numeric kind.
You can thought use Play's routes to find user by its string-id and still use Long id to perform basic operations.
(I'm writing in Play's context as I assume that you ask in it ;) )
You need to extend GenericModel instead of Model if you want to operate on your own #Id field. I am also talking in PlayFramework context.