Hey, I’m new to strapi and saw that people have been struggling to have proper lifecycle hooks for the past ~1.5 years, which seemed to work in the past. I found one solution including database hooks but that didn’t allow me to access the ctx
object which provides more detailed information about the request
and response
. In my use case, I need to log which user accessed / changed the information of another. And for that, ctx.state
is handy, which is not available in the database hook
So I’ve thought hacking around with this users-permissions plugin would be a good idea. I have little to none of a clue about strapi’s inner workings, but after some sherlock holmes level of investigations (actually just an hour or so) I thought I might have found what’s called a pro gamer move
Just monkey-patch the **** out of this plugin to do what we require from it.
Bonus: You’re even getting lifecycle functions for the users-permissions specific /me
api.
Here is how you do it:
- create a file at
src/extensions/users-permissions/content-types/user/lifecycles.ts
with the following content:
export const beforeCreate = async (ctx) => {};
export const afterCreate = async (ctx) => {};
export const beforeUpdate = async (ctx) => {};
export const afterUpdate = async (ctx) => {};
export const beforeFind = async (ctx) => {};
export const afterFind = async (ctx) => {};
export const beforeFindOne = async (ctx) => {};
export const afterFindOne = async (ctx) => {};
export const beforeCount = async (ctx) => {};
export const afterCount = async (ctx) => {};
export const beforeDestroy = async (ctx) => {};
export const afterDestroy = async (ctx) => {};
export const beforeMe = async (ctx) => {
console.log("before !");
};
export const afterMe = async (ctx) => {
console.log("after !");
};
So far, so unsuspicious. Now let’s get dirty: In src/extensions/users-permissions/strapi-server.ts
you put this:
import { Strapi } from '@strapi/strapi';
import * as hooks from './content-types/user/lifecycles';
module.exports = (plugin) => {
const controllers = plugin.controllers.user;
const methods = ['create', 'update', 'find', 'findOne', 'count', 'destroy', 'me'];
for (const method of methods) {
const oldMethod = controllers[method];
controllers[method] = async (ctx) => {
await hooks[`before${method[0].toUpperCase() + method.slice(1)}`](ctx);
const result = await oldMethod(ctx);
await hooks[`after${method[0].toUpperCase() + method.slice(1)}`](ctx);
return result;
};
}
return plugin;
};
Congratulations, you’ve monkey-patched the user permissions plugin. Now if you call users/me
, you see the appropriate logs in your console. Use and abuse as per your requirements. You can use the hooks to make DB entries, here is how I write a log entry:
export const afterFindOne = async (ctx) => {
const entry = await strapi.entityService.create('api::user-log.user-log', {
data: {
test: ctx.body.id.toString()
}
})
};
Check ctx.request, ctx.response and ctx.state for useful information, but I’m sure you already know by now !
What do you think of my solution?
System Information
- Strapi Version: 4.5.5
- Operating System: OSX
- Database: Postgres
- Node Version: 18 LTS
- NPM Version: 9.2.0
- Yarn Version: 1.17.3