NextAuth: Recommended way for extending the sessions user object for multiple user types? - next-auth

I'm creating a web app that's similar to Fiverr/UpWork where users have the option to become sellers to offer their services. I'm using NextAuth with the Prisma Adapter (with MongoDB) which is storing the generic user object in my Users collection in my database with the following structure:
{
id: string;
name: string;
email: string;
image: string;
}
If a user chooses to become a seller, they will need to create a seller profile to give additional details, such as their bio, education, skills, etc., and I am planning on storing these additional details in a separate Sellers collection, and relating them via a Foreign Key as follows:
{
id: string;
userId: string; // Foreign Key
bio: string;
skills: string[];
otherAdditionalItems: any;
}
My question is this: using NextAuth, what is the recommended way to fetch a user's seller profile when they sign in and have access to this on the client? And where should this be stored? Can I somehow store the seller profile on the NextAuth sessions user object (after the separate seller profile is fetched) so that it's accessible via session.user? Or will I need to store the seller profile in some sort of state management solution such as Redux?
I can't seem to find a recommended way to do something like this so would love any sort of input/help!
Much appreciated.

Related

Is there a way to embed metadata into an Apostrophe CMS version 3 user type

I am looking into the Apostrophe CMS for a way to embed data into the mongoDB user documents so that I can keep more data about a given user beyond just their username, password, and role (admin, guest, contributor, etc).
Looking through the Apostrophe CMS version 3 documentation (https://v3.docs.apostrophecms.org/guide/users.html) there seems to be no information about how to interact with the database so that more data can be added to a user. As it stands there don't seem to be any methods available to interact with the database in this fasion.
An example might be:
user: {
role: guest,
group: eastUS,
groupID: 1jfe25226,
isActive: true,
hasBeenContacted: true
}
If anyone has attempted to do this or successfully achieved this please let me know your approach.
Apostrophe users are just Apostrophe pieces. That means you can extend them with custom fields in a project-level modules/#apostrophecms/user/index.js file, just like you would add fields to any piece type. This gives you a way to add additional editable fields.
The documentation on queries also applies to users. However bear in mind that for security reasons only admins can query for users or update them.
To update a single custom property of the current user you might write the following inside an Apostrophe apiRoute, promise event handler, etc.:
await self.apos.doc.db.update({ _id: req.user._id }, { $set: { group: 'xyz' } });
This goes directly to MongoDB to $set one property and bypasses permissions checks, so use with care.
Apostrophe's standard REST APIs also work for users, but bear in mind that for security reasons only an admin user can fetch and edit users.
I can revise and add more clarification if you can be more specific about what you are trying to do and in what situation.

Joins in mongodb documents

I am creating an application related to e-books for both authors and readers. Schema is written in mongodb with 2 collections USERS and AUTHORS. USRES store the data of every person signed up in the application. In USERS i have email document. A user can also register as an author in the application. (What I want to do is when a User register as an AUTHOR the email from USER document automatically become the email document in AUTHOR collection. And every AUTHOR have specific email which they used for registration. How to do that in mongodb???)
I can sugest u a simple option
Creating 2 separate collection for user and author is a bad choice. At the end both uses same application
Basically just add one more field is user
Collection as isAuthor
Users schema
"_id": id,
email: {type: String},
isAuthor: {type: Boolean} true/false
After this u don't need to copy emails and stuff from 2 different Collections

How to design user access system using Keycloak

I need help figuring it out how to design a good user access management system using Keycloak.
We have multiple services and we need to implement SSO between them. I'll explain our concerns for just one of them for simplicity's sake.
We have a userType Restaurant, Restaurant user breaks down on several other kinds of access, like owner, employee and cashier. A single user can be owner and employee at the same time, depending on the restaurant.
We tried a lot of different ways, but we are overwhelmed with all the possibilities Keycloak has given to us, I mean scopes, policy, permission, groups, roles, resources. What is the best practice for our use case? Is there a correct approach to this in a way it's easy to build and maintain? Documentation wasn't helpful regarding this problem.
Use case:
restaurant Best Pizza
id: 1
user: John Doe
access: Owner
what he can do: view, edit, delete orders
.
id: 2
user: Mark
access: Employee
what he can do: view orders
restaurant Not the Best Pizza
id: 2
user: Mark
access: Owner
what he can do: view, edit, delete orders
.
id: 3
user: Jane Doe
access: Employee
what she can do: view, edit orders

How to design schema denormalization to handle data changes?

I'm designing a schema for MongoDB, and keep running into scenarios where future updates might invalidate my cached copies of data. One example is for Users, Orders and Addresses.
const UserSchema = mongoose.Schema({
addresses: [{ street: String, city: String, state: String, zip: String }]
});
const OrderSchema = mongoose.Schema({
address: { street: String, city: String, state: String, zip: String }
});
This seems to be a standard approach, since MongoDB isn't meant to be a relational database, to denormalize the data where possible. However, the following scenario confuses me:
User adds an Address to their User document.
User places an Order and selects an Address from their list of
addresses.
The address data is copied into the Order document when the order is
persisted.
Before the order is shipped, the user discovers that they mistyped
the address.
User changes that incorrect Address in their User document.
The Address in the Order object needs to change also, otherwise it
will be shipped to an invalid address.
This seems to point towards the need for a reference using mongoose.Schema.Types.ObjectId to simulate a relational structure between the collections. (In that case, there would also be an Addresses collection, of course.) However, there are other considerations such as the history aspect of the denormalization. I want to store the actual address to which the order was shipped, even if that address is later deleted or changed. With denormalization this would seem to be easier than the relational paradigm.
One approach I considered to create an Addresses collection, then mark its records as invalidated when they are deleted, in case they are already referenced in an Order. And when they are modified, I would need to check the Orders collection to see if that Address is referenced. If it's already been referenced in a shipped order, I would have to leave it alone (for historical purposes), and create an additional Address document with the new changes. All of which sounds a bit complicated, compared to the denormalization approach.
The next part of the issue regards querying and reporting. If I want to pull up a list of all Users who have ever had an address in Illinois, I would need to traverse both the Addresses collection and the Orders in order to find out. Because they may have had an Illinois address, used it in a shipped order, then deleted it from the Addresses collection.
How do the smartest MongoDB data architects handle situations like this? I'm an experienced relational database architect, but am somewhat baffled by the conceptual framework of NoSQL. Thanks!

IPad App pull and push relational data

Im currently putting together a business app for an ipad. It will be talking to a Microsoft SQL server database.
My question is what is the most efficient way to pull relational data over the line. One example is im showing a contact listing in the app. The contact record has a departmentID field (which is related to the department table) and a ContactTypeID field (which is related to the ContactType table). I am hoping that when the user first starts the app I will pull the department and contacttype table data over onto the ipad. Than when i pull the contact listing data I will just pull the ID's for the fields over and pull their related data out of the data i pulled at startup. The user must than be able to click on a record in the listing and bring up the details page for the selected contact. This is a simple example but hopefully it makes my point.
Has anyone got any advice on the best approach for this? I will be needing to both pull data and push data to and from the server.
Thanks in advance
A popular approach is to convert your server-side objects to JSON, and then send the JSON string to the device. On the device, decode JSON into NSDictionary/NSArray values using some JSON framework (I suggest JSONKit since it's very simple and very fast).
Once you have your decoded JSON, you can use (shameless plug warning) this technique to turn your NS* objects into CoreData objects, and save them onto your phone.
As for maintaining relationships, you can either use a nested representation or a flat representation. An example nested implementation would be:
{
class: "Contact",
first_name: "John",
last_name: "Doe",
contact_type: {
class: "ContactType",
type: "some value"
},
department: {
class: "Department",
name: "Department of Transportation"
}
}
This is a preferred approach if you have a simple database, with no relationship cycles.
Alternatively, you can use a flat representation:
{
class: "Contact",
id: 1,
first_name: "John",
last_name: "Doe",
contact_type_id: 15,
department_id: 34
}
{
class: "ContactType",
id: 15,
type: "some value"
}
{
class: "Department",
id: 34,
name: "Department of Transportation"
}
Then you would have to resolve the relationships manually using contact_type_id and department_id, on the device.
It's best to test both of these approaches and see which one works better in your particular case. Personally, I'd recommend the nested approach (if your DB layout allows it), since it's much faster and relationship resolution is done on the server (where you can probably afford it), instead of on the device (where you probably can't afford it if you have a large database).