基于TypeScript自定义Strapi users-permissions插件接口

Strapi的官方文档提供了扩展插件的方式,例如在src/extensions/users-permissions/strapi-server.ts中自定义,但文档提供的例子直接重写了原有插件的函数,而无法通过类似自定义API调用super.find()等方式调用原有插件的函数。

// 自定义API的方式const uid: Common.UID.ContentType = 'api::api-name···';
export default factories.createCoreController(uid, ({ strapi: Strapi }) => ({async find(ctx: Context) {// TODO ...return await super.find(ctx);},
}));

此时需要将原插件的函数复制出来,并在重写的函数里调用,以自定义/users/me接口为例。

users-permissions的/users/me接口提供了对获得当前用户信息的方法,若需要自定义获得哪些信息,可通过修改原有me函数实现,users-permissions对me函数的定义位于@strapi/plugin-users-permissions/server/controllers/user.js中,尝试通过导入这个函数,并在自定义的me函数中调用这个函数。

失败的方案

进一步观察代码,该me函数位于user.js的导出对象中,user.js的导出对象是controllers导出对象的成员,位于@strapi/plugin-users-permissions/server/controllers/index.js中,controllers又是server导出函数的返回值成员,位于@strapi/plugin-users-permissions/server/index.js中,故要访问user.js中的方法,可通过以下方式。

const { controllers } = server();
controllers.user.me(ctx);

导入原有me函数时,要注意users-permissions插件的导出对象名,查看/@strapi/plugin-users-permissions/package.json发现,其exports对象导出名为strapi-server,故实际引用users-permissions的server对象,需要使用

import server from '@strapi/plugin-users-permissions/strapi-server';

此时,如果在重写的me函数中直接调用controllers.user.me(ctx);则会陷入死递归,因为Strapi初始化时已经将原有的me函数覆盖为自定义的me函数,实际上调用controllers.user.me(ctx);即调用的当前函数,故该方法无法实现。

可行的方案

既然如此,就把整个原有的me函数照搬过来,相当于复制了一份me函数,进入@strapi/plugin-users-permissions/server/controllers/user.js中,发现me函数的定义如下:

/*** Retrieve authenticated user.* @return {Object|Array}*/async me(ctx) {const authUser = ctx.state.user;const { query } = ctx;if (!authUser) {return ctx.unauthorized();}await validateQuery(query, ctx);const sanitizedQuery = await sanitizeQuery(query, ctx);const user = await getService('user').fetch(authUser.id, sanitizedQuery);ctx.body = await sanitizeOutput(user, ctx);},

其调用了validateQuerysanitizeQuerygetServicesanitizeOutput4个方法,其中validateQuerysanitizeQuerysanitizeOutput均在user.js中有定义,可直接照搬

// @strapi/plugin-users-permissions/server/controllers/user.js
const utils = require('@strapi/utils');
const { sanitize, validate } = utils;const sanitizeOutput = async (user, ctx) => {const schema = strapi.getModel('plugin::users-permissions.user');const { auth } = ctx.state;return sanitize.contentAPI.output(user, schema, { auth });
};const validateQuery = async (query, ctx) => {const schema = strapi.getModel('plugin::users-permissions.user');const { auth } = ctx.state;return validate.contentAPI.query(query, schema, { auth });
};const sanitizeQuery = async (query, ctx) => {const schema = strapi.getModel('plugin::users-permissions.user');const { auth } = ctx.state;return sanitize.contentAPI.query(query, schema, { auth });
};

getService位于@strapi/plugin-users-permissions/server/utils/index.js

// @strapi/plugin-users-permissions/server/utils/index.js
const sanitize = require('./sanitize');const getService = (name) => {return strapi.plugin('users-permissions').service(name);
};module.exports = {getService,sanitize,
};

观察@strapi/plugin-users-permissions/server/index.js发现,utils并未被server导出,故无法在外部引用该函数

// @strapi/plugin-users-permissions/server/index.js
const register = require('./register');
const bootstrap = require('./bootstrap');
const contentTypes = require('./content-types');
const middlewares = require('./middlewares');
const services = require('./services');
const routes = require('./routes');
const controllers = require('./controllers');
const config = require('./config');module.exports = () => ({register,bootstrap,config,routes,controllers,contentTypes,middlewares,services,
});

不过所幸getService仅为一句简单的return strapi.plugin('users-permissions').service(name);并未引用新的外部依赖,故可以在自定义的文件中重新定义一次该函数。

故最终实现代码如下:

// src/extensions/users-permissions/strapi-server.tsimport type { Strapi, Common, CoreApi } from '@strapi/types';
import { sanitize, validate } from '@strapi/utils';const getService = (name) => {return strapi.plugin('users-permissions').service(name);
};
const validateQuery = async (query, ctx) => {const schema = strapi.getModel('plugin::users-permissions.user');const { auth } = ctx.state;return validate.contentAPI.query(query, schema, { auth });
};const sanitizeQuery = async (query, ctx) => {const schema = strapi.getModel('plugin::users-permissions.user');const { auth } = ctx.state;return sanitize.contentAPI.query(query, schema, { auth });
};const sanitizeOutput = async (user, ctx) => {const schema = strapi.getModel('plugin::users-permissions.user');const { auth } = ctx.state;return sanitize.contentAPI.output(user, schema, { auth });
};const originMe = async (ctx) => {const authUser = ctx.state.user;const { query } = ctx;if (!authUser) {return ctx.unauthorized();}await validateQuery(query, ctx);const sanitizedQuery = await sanitizeQuery(query, ctx);const user = await getService('user').fetch(authUser.id, sanitizedQuery);// ctx.body = await sanitizeOutput(user, ctx);return await sanitizeOutput(user, ctx);
};export default async (plugin) => {const uid: Common.UID.ContentType = 'plugin::users-permissions.user';plugin.controllers.user.me = async (ctx) => {// Custom code here;const res = await originMe(ctx); // 调用了原有的me函数return res;};return plugin;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/826215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Webservice使用教程

Webservice使用教程(jax-ws) Webservice的交互模式是一个类似于CS结构的模式,因此它需要一个Server端与一个Client端。在Client端访问Server端的接口来实现Webservice的功能。 Server端 打开IDEA创建gradle模块 webservice-01-server1 然后…

【VI/VIM】基本操作备忘录

简介 新建/打开文件 工作模式 常用命令 移动命令 文本选中 撤销、删除 复制粘贴 替换 缩排 查找 替换 插入 分屏 练习

【动态规划】C++简单多状态dp问题(打家劫舍、粉刷房子、买卖股票的最佳时机...)

文章目录 前言1. 前言 - 理解动态规划算法2. 关于 简单多状态的dp问题2.5 例题按摩师/打家劫舍 3. 算法题3.1_打家劫舍II3.2_删除并获得点数3.3_粉刷房子3.4_买卖股票的最佳时机含冷冻期3.5_买卖股票的最佳时机含手续费3.6_买卖股票的最佳时机III3.7_买卖股票的最佳时机IV 前言…

AcWing 800. 数组元素的目标和——算法基础课题解

AcWing 800. 数组元素的目标和 题目描述 给定两个升序排序的有序数组 A 和 B,以及一个目标值 x。 数组下标从 0 开始。 请你求出满足 A[i]B[j]x 的数对 (i,j)。 数据保证有唯一解。 输入格式 第一行包含三个整数 n,m,x,分别表示 A 的长度&#xf…

C# 语法全解总目录

C# 语法全解总目录 简介正文C#各大版本特性C# 语言类型C# 面向对象编程(一) 类相关(二) 继承 C#进阶(一) 委托(二) 事件(三) 元组(四) XML相关(五) 动态绑定 简介 记录C# 专栏所有文章的路径 正文 C#各大版本特性 C#各大版本特性 C# 语言类型 系列链接 C#语法系列:C# 语言类…

交换机的种类有哪些?主要都具有哪些作用?

在当今数字化时代,网络已经成为我们生活和工作中不可或缺的一部分。无论是家庭网络还是企业网络,都需要有效的网络设备来实现数据通信和资源共享。而网络交换机作为一种重要的网络设备,扮演着连接和管理网络设备的关键角色。本文将探讨交换机…

开源贡献代码之​探索一下CPython

探索一下Cython 本篇文章将会围绕最近给Apache提的一个feature为背景,展开讲讲CPython遇到的问题,以及尝试自己从0写一个库出来,代码也已经放星球了,感兴趣的同学可以去下载学习。 0.背景 最近在给apache arrow提的一个feature因为…

《TinyLlama: An Open-Source Small Language Model》全文翻译

【Title】 TinyLlama:开源小语言模型 【Abstract】 我们推出了 TinyLlama,这是一个紧凑的 1.1B 语言模型,在大约 1 万亿个令牌上进行了大约 3 个时期的预训练。 TinyLlama 基于 Llama 2(Touvron 等人,2023b&#xff…

VUE项目使用.env配置多种环境以及如何加载环境

第一步,创建多个环境配置文件 Vue CLI 项目默认使用 .env 文件来定义环境变量。你可以通过创建不同的 .env 文件来为不同环境设置不同的环境变量,例如: .env —— 所有模式共用.env.local —— 所有模式共用,但不会被 git 提交&…

C语言 三目运算符

C语言 逻辑分支语句中 还有一种 三目运算符 我们编写代码如下 #include <stdio.h>int main() {const char* a 1 1 ? "表达式1" : "表达式2";printf("%s", a);return 0; }这里 我们根据逻辑 先定义一个a 然后 它的值 等于一个 三目运算…

【CodeGeeX】国产的免费AI编程助手

CodeGeeX&#xff08;官网&#xff1a;https://codegeex.cn/&#xff09;是一款基于大模型的全能的智能编程助手。它可以实现代码的生成与补全、自动添加注释、代码翻译以及智能问答等功能&#xff0c;能够帮助开发者显著提高工作效率。CodeGeeX支持主流的编程语言&#xff0c;…

Serverless:程序员必须知道的云计算利器

作为一名程序员&#xff0c;你是否厌倦了管理服务器和基础设施的繁琐任务&#xff1f;Serverless 架构横空出世&#xff0c;解放你 khỏi这些负担&#xff0c;让你专注于编写代码。 什么是 Serverless&#xff1f; Serverless 是一种云计算模型&#xff0c;它允许你编写和部署…

C++练级之路——类和对象(下)

目录 1、构造函数初始化列表 2、类型转换 3、explicit关键字 4、static成员 5、友元 友元函数 友元类 6、内部类 7、匿名对象 8、拷贝构造时的一些编译器优化 差不多结束了&#xff0c;类和对象&#xff01; 1、构造函数初始化列表 初始化列表&#xff1a;以一个冒号…

python:元组,字符串,切片

一、元组# 列表可以修改内容&#xff0c;元组可以不被修改 # 在程序内封装数据&#xff0c;不希望数据被篡改&#xff0c;所以使用元组 # 语法&#xff1a; 不限制类型 # 定于元组的字面量&#xff1a; &#xff08;元素&#xff0c;元素&#xff0c;元素.....&#xff09; # 定…

萌新_1 环境安装(基于QQNT框架 Python Flask)

遇到问题加QQ群聊 群主在线解答 点击加入群聊【星辰开发】 一&#xff1a;安装QQ 目前为开发&#xff0c;推荐都安装到一台电脑上 直接安装到本地windows电脑&#xff0c; 优点方便开发 一键安装 Windows 用户一键安装方案 https://github.com/super1207/install_llob/rel…

LLMs——扩展数据受限的语言模型解决方案

概述 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;大型语言模型的发展一直是研究的热点。这些模型通过增加参数数量和训练数据量来提升性能&#xff0c;但这种增长趋势是否会有一个极限&#xff1f;实际上&#xff0c;研究者们已经注意到&#xff0c;为了有效地…

go语言触发浏览器打开网址程序实例

在Go语言中&#xff0c;触发浏览器打开特定的网址通常涉及调用操作系统的命令行工具来启动默认的浏览器并导航到指定的URL。 示例&#xff1a; package main import ( "fmt" "os/exec" "runtime" ) func main() { url : "https:/…

大话设计模式-依赖倒转原则

依赖倒转原则 在大话设计模式这本书中&#xff0c;作者通过电话修电脑这个例子引入了面向对象设计的基本原则之一&#xff1a;依赖倒转原则。 概念 依赖倒转原则是面向对象设计的基本原则之一&#xff0c;它用于减少类之间的耦合&#xff0c;提高系统的灵活性和可维护性。在…

QT C++ sqlite 对多个数据库的操作

//本文描述&#xff0c;QT 对多数据库的操作。 //你可能会想&#xff0c;多数据库的操作时&#xff0c;查询语句怎么知道是哪个数据库。 //QT提供了这样一种构造函数 QSqlQuery(const QSqlDatabase &db) //指定数据库 //在QT6.2.4 MSVC2019调试通过。 //效果见下图&am…

Docker(二)Docker+ server部署极简前端页面

本篇文章介绍如何使用 Dockerserver 将一个极简前端页面进行部署 1.本地运行一个简单的前端页面&#xff0c;再把它部署到服务器上 index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name&quo…