Replies: 5 comments 5 replies
-
Hello Doesn’t Collection have the same interface as an Array or maybe even extends it? |
Beta Was this translation helpful? Give feedback.
-
Looks like there is a different solution if you can efficiently extract underlying array. You can create custom conditions matcher which will be completely the same as built in one but with custom compare function which for collections will extract underlying array. You can take a look how it’s done for dates and objects that have toJSON method Alternatively, if you do |
Beta Was this translation helpful? Give feedback.
-
Hi, sorry for the delay. |
Beta Was this translation helpful? Give feedback.
-
I found a solution that makes use of the toJSON() of MikroORM in combination with the subject() helper function from @casl/ability. So, in my BaseEntity I add a method toSubject() import { wrap, PrimaryKey, Property, SerializedPrimaryKey, Entity } from "@mikro-orm/core";
import { subject } from "@casl/ability";
import { ObjectId } from "@mikro-orm/mongodb";
@Entity({ abstract: true })
export abstract class BaseEntity {
@PrimaryKey()
_id!: ObjectId;
@SerializedPrimaryKey()
id!: string;
// convert to JSON and add__caslSubjectType__
// this is used in AbilityFactory to determine the subject
toSubject(): object {
// @ts-ignore - subject wants to use a string as identifier, but on the server we use the class constructor
return subject(this.constructor, wrap(this.toJSON());
}
} my createForUser uses this export async function createForUser(user: User): Promise<AnyAbility> {
const builder = new AbilityBuilder<MongoAbility>(createMongoAbility);
for (const factory of factories) {
await factory.createRules(builder, user);
}
const ability = builder.build({
detectSubjectType: (object) => {
// either use the __caslSubjectType__ or the original constructor
return object.__caslSubjectType__ || (object.constructor as ExtractSubjectType<MongoAbility>);
},
});
return ability;
} Now I can create an endpoint like so @Get(":id")
async get(
@Param("id") id: string,
@Query("action") action: string,
@CurrentUser() currentUser: User,
) {
action = action || Action.Read;
const user = await this.usersService.findOne({ id }, { populate: ["roles"] });
if (!user) {
throw new NotFoundException("Gebruiker niet gevonden");
}
const ability = await createForUser(currentUser);
throwUnlessCan(ability, action, user.toSubject());
return permittedFields(ability, action, user.toSubject());
} |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Hello, I am attempting to create more complex rules for my application and have encountered a problem related to MikroOrm Collections.
Let's say I have the following code:
The code above will function as expected. However, if we use a
Meeting
entity instead of "Meeting", theusers
will change from anArray
to aCollection
, causing the code above to no longer work.My question is how to fix this? I know I could serialize an entity before passing it to casl for validation, but that could have some performance implications.
Beta Was this translation helpful? Give feedback.
All reactions