Verdaccio 插件
插件介绍
Verdaccio 是插件应用程序。它可以通过多种方式扩展,包括新的身份验证方法,添加端点或使用自定义存储。
插件有 5 种类型:
- 认证方式
- 中间件
- 存储
- 自定义主题
- 过滤器
使用
安装
$> npm install --global verdaccio-activedirectory
verdaccio 作为 sinopia 分支,它具有与兼容的插件的向后兼容性 sinopia@1.4.0。在这种情况下,安装是相同的。
$> npm install --global sinopia-memory
配置
打开 config.yaml
文件并按如下说明更新 auth
部分:
默认配置如下所示,由于在默认情况下我们使用一个内置的 htpasswd
插件,我们可以通过注释下面几行代码来禁用它:
认证配置
htpasswd:
file: ./htpasswd
# max_users: 1000
如果你决定使用 ldap
插件,将上述部分进行替换。
auth:
activedirectory:
url: "ldap://10.0.100.1"
baseDN: 'dc=sample,dc=local'
domainSuffix: 'sample.local'
多个身份验证插件
从技术上讲这是可能的,这使得插件的顺序很重要,因为凭据将按顺序解析。
auth:
htpasswd:
file: ./htpasswd
#max_users: 1000
activedirectory:
url: "ldap://10.0.100.1"
baseDN: 'dc=sample,dc=local'
domainSuffix: 'sample.local'
中间件配置
这是一个如何设置中间件插件的示例。所有中间件插件都必须在中间件名称空间中定义。
middlewares:
audit:
enabled: true
您可以跟着 audit middle plugin(审核中间插件)的基本范例。
https://github.com/verdaccio/verdaccio-audit
存储配置
这是一个如何设置存储插件的示例。所有存储插件都必须在商店名称空间中定义。
store:
memory:
limit: 1000
主题配置
Verdaccio 允许将用户界面替换为自定义界面,我们将其称为 theme。默认情况下,
使用 @verdaccio/ui-theme
内置,但您可以使用其他方式安装自己的插件。
$> npm install --global verdaccio-theme-dark
插件名称前缀必须以开头
verdaccio-theme
,否则插件将无法加载。
您一次只能加载一个主题,并在需要时通过选项。
theme:
dark:
option1: foo
option2: bar
旧式插件
Sinopia 插件
如果您依赖任何 sinopia 插件,请记住它们已被弃用,将来可能无法正常工作。
- sinopia-npm:支持 npm 注册表的 sinopia 认证插件。
- sinopia-memory:在内存中缓存用户的 sinopia 认证插件。
- sinopia-github-oauth-cli。
- sinopia-crowd:支持 atlassian crowd 的 sinopia 认证插件。
- sinopia-activedirectory:sinopia Active Directory 认证插件。
- sinopia-github-oauth:sinopia2 的认证插件,支持 github oauth web flow。
- sinopia-delegated-auth:将认证代理给另一个 HTTP URL 的 Sinopia 认证插件。
- sinopia-altldap:另一个 Sinopia LDAP 认证插件
- sinopia-request:一个简单易用且功能齐全的认证插件,可以通过配置使用外部 API。
- sinopia-htaccess-gpg-email:使用 htaccess 格式生成密码,通过 GPG 加密并通过 MailGun API 发送给用户。
- sinopia-mongodb:一个易用且功能齐全的认证插件,可通过配置使用 mongodb 数据库。
- sinopia-htpasswd:支持 htpasswd 格式的 sinopia 认证插件。
- sinopia-leveldb:针对 Sinopia private npm 的基于 leveldb 的 Sinopia 认证插件。
- sinopia-gitlabheres:sinopia Gitlab 认证插件。
- sinopia-gitlab:sinopia Gitlab 认证插件。
- sinopia-ldap:sinopia LDAP 认证插件。
- sinopia-github-oauth-env:基于 github oauth web flow 的 Sinopia 认证插件。
所有 sinopia 插件都应该和所有 verdaccio 将来版本兼容。
开发插件
我们建议使用我们的 Typescript 类型定义来开发插件。
主题插件
插件必须返回一个返回字符串的函数。
该字符串应该是用户界面根目录的绝对位置。
API
const path = require('path');
module.exports = (...arguments) => {
return path.join(__dirname, 'static');
};
插件名称必须以 verdaccio-theme-prefix
开头很重要。
主题例子
@verdaccio/ui-theme
:基于 React.js 的默认 Verdaccio 主题。
过滤器插件
根据要求引入了过滤器插件,以便能够从上行链路中过滤元数据。
PR 中的更多信息。
filters:
storage-filter-blackwhitelist:
filter_file: /path/to/file
API
该方法 filter_metadata 将允许您过滤来自任何上行链路的元数据,该方法 Promise 基于并必须返回修改后的相同元数据。
不要从元数据中删除属性,请尝试不要变异而是返回一个新对象。
interface IPluginStorageFilter<T> extends IPlugin<T> {
filter_metadata(packageInfo: Package): Promise<Package>;
}
开发人员指南
帮助你开发插件
插件生成器
安装 Yeoman Generator
Verdaccio 是一个可插入的应用程序,其目的是帮助开发人员生成新的插件,
我们在 Yeoman 有一个自定义生成器,用于生成各种插件。
要安装生成器,首先必须安装 yeoman 命令 yo。
npm install -g yo
然后,在终端中安装运行以下命令的定制生成器。
npm i -g generator-verdaccio-plugin
使用发电机
使用 yeoman 非常简单,您可以在此处阅读有关它的更多信息。
成功安装后,请 yo verdaccio-plugin 在您的终端中运行并按照以下步骤操作。
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? (customname)
1. 最佳实务*
我们建议使用 Typescript 开发新的插件,我们提供了对 Types 的广泛支持,可帮助您进行开发。
? What is the name of your plugin? my-plugin
? Select Language (Use arrow keys)
❯ typescript
javascript
在描述您的插件时,要简短明了,请记住一个好的描述会增加您使用插件的机会。
? Please, describe your plugin (An amazing verdaccio plugin)
不要犹豫,包括有意义的关键字,如 verdaccio,plugin 或者你的插件类型。
好的关键字将帮助我们找到您,并在我们收集所有插件信息的过程中为您提供进一步的改进。
? Key your keywords (comma to split) verdaccio,plugin,storage,minio,verdaccio-plugin
不断更新您的生成器,不要错过任何错误修复和性能改进。
2. 贡献
帮助我们改进生成器,您可以在以下存储库中做出贡献。
身份验证插件
什么是身份验证插件?
是一种排序插件,允许处理谁访问或发布到特定程序包。默认情况下,它 htpasswd 是内置的,但可以轻松地由您自己替换。
入门
身份验证插件在本 auth: 节中定义,如下所示:
auth:
htpasswd:
file: ./htpasswd
也可以链接多个插件:
auth:
htpasswd:
file: ./htpasswd
anotherAuth:
foo: bar
bar: foo
lastPlugin:
foo: bar
bar: foo
如果链中的一个插件能够解决请求,则下一个插件将被忽略。
身份验证插件如何工作?
基本上我们必须用一个叫做 authenticate
的单一方法来返回一个 object(对象),此方法将接收到 3 个参数 (user
, password
, callback
)。
在每次请求时,authenticate
都会触发,插件应返回凭据,如果 authenticate
失败,则 $anonymous 默认情况下将回退到角色。
API
interface IPluginAuth<T> extends IPlugin<T> {
authenticate(user: string, password: string, cb: AuthCallback): void;
adduser?(user: string, password: string, cb: AuthCallback): void;
changePassword?(user: string, password: string, newPassword: string, cb: AuthCallback): void;
allow_publish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_access?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_unpublish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
apiJWTmiddleware?(helpers: any): Function;
}
只有 adduser,allow_access,apiJWTmiddleware,allow_publish 和 allow_unpublish 是可选的,verdaccio 在所有这些情况下,提供一个备用的。
apiJWTmiddleware 方法
apiJWTmiddleware 为了完全控制令牌处理程序而在 PR#1227 上引入,重写此方法将禁用 login/adduser
支持。
我们建议除非完全必要,否则不要实现此方法。在这里查看完整的示例。
https://github.com/verdaccio/verdaccio/pull/1227#issuecomment-463235068
我应该在每种方法中返回什么?
Verdaccio callback 在撰写本文时依赖于功能。
每个方法都应调用该方法,并且返回的内容很重要,让我们回顾一下如何做。
authentication
回调
一旦执行了认证,有两个选项来回应 verdaccio。
- 如果认证失败
如果 auth 不成功,则 false 作为第二个参数返回。
callback(null, false)
- 如果认证成功
授权成功
groups
是用户组成的一组字符串。
callback(null, groups);
- 如果认证产生错误
身份验证服务可能会失败,并且您可能希望在用户响应中反映出来,例如:服务不可用。
import { getInternalError } from '@verdaccio/commons-api';
callback(getInternalError('something bad message), null);
登录失败与服务错误不同,如果您想通知用户 credentails 错误,只需返回 false 一组字符串即可。行为主要取决于您。
adduser
回调
- 如果 adduser 成功
如果服务能够创建用户,请 true 作为第二个参数返回。
callback(null, true)
- 如果 adduser 失败
除成功以外的任何其他操作都必须返回错误。
import { getConflict } from '@verdaccio/commons-api';
const err = getConflict('maximum amount of users reached');
callback(err);
changePassword
回调
- 如果请求成功
如果服务能够创建用户,请 true 作为第二个参数返回。
const user = serviceUpdatePassword(user, password, newPassword);
callback(null, user)
- 如果请求失败
除成功以外的任何其他操作都必须返回错误。
import { getNotFound } from '@verdaccio/commons-api';
const err = getNotFound('user not found');
callback(err);
allow_access,allow_publish 或 allow_unpublish 回调
这些方法旨在允许或拒绝触发某些动作。
- 如果请求成功
如果服务能够创建用户,则返回 a true 作为第二个参数。
allow_access(user: RemoteUser, pkg: PackageAccess, cb: Callback): void {
const isAllowed: boolean = checkAction(user, pkg);
callback(null, isAllowed)
}
- 如果请求失败
除成功以外的任何其他操作都必须返回错误。
import { getNotFound } from '@verdaccio/commons-api';
const err = getForbidden('not allowed to access package');
callback(err);
生成身份验证插件
有关详细信息,请查看我们的插件生成器。yo 在您的终端中运行命令,然后按照下列步骤操作。
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? service-name
? Select Language typescript
? What kind of plugin you want to create? auth
? Please, describe your plugin awesome auth plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,auth,awesome,verdaccio-plugin
create verdaccio-plugin-authservice-name/package.json
create verdaccio-plugin-authservice-name/.gitignore
create verdaccio-plugin-authservice-name/.npmignore
create verdaccio-plugin-authservice-name/jest.config.js
create verdaccio-plugin-authservice-name/.babelrc
create verdaccio-plugin-authservice-name/.travis.yml
create verdaccio-plugin-authservice-name/README.md
create verdaccio-plugin-authservice-name/.eslintrc
create verdaccio-plugin-authservice-name/.eslintignore
create verdaccio-plugin-authservice-name/src/index.ts
create verdaccio-plugin-authservice-name/index.ts
create verdaccio-plugin-authservice-name/tsconfig.json
create verdaccio-plugin-authservice-name/types/index.ts
create verdaccio-plugin-authservice-name/.editorconfig
I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc
安装完成后,访问您的项目目录。
➜ cd verdaccio-plugin-service-name
➜ cat package.json
{
"name": "verdaccio-plugin-service-name",
"version": "0.0.1",
"description": "awesome auth plugin",
...
完整实施 ES5 示例
function Auth(config, stuff) {
var self = Object.create(Auth.prototype);
self._users = {};
// config for this module
self._config = config;
// verdaccio logger
self._logger = stuff.logger;
// pass verdaccio logger to ldapauth
self._config.client_options.log = stuff.logger;
return self;
}
Auth.prototype.authenticate = function (user, password, callback) {
var LdapClient = new LdapAuth(self._config.client_options);
....
LdapClient.authenticate(user, password, function (err, ldapUser) {
...
var groups;
...
callback(null, groups);
});
};
module.exports = Auth;
配置将如下所示:
auth:
htpasswd:
file: ./htpasswd
htpasswd 插件名称的后缀在哪里。例如:verdaccio-htpasswd 主体的其余部分将是插件配置参数。
列出社区身份验证插件
- verdaccio-bitbucket:verdaccio Bitbucket 认证插件。
- verdaccio-bitbucket-server:verdaccio 的 Bitbucket 服务器身份验证插件。
- verdaccio-ldap:verdaccio 的 LDAP 身份验证插件。
- verdaccio-active-directory:verdaccio 的 Active Directory 身份验证插件
- verdaccio-gitlab:使用 GitLab 个人访问令牌进行身份验证
- verdaccio-gitlab-ci:启用 GitLab CI 来针对 verdaccio 进行身份验证。
- verdaccio-htpasswd:基于 htpasswd 文件插件(内置)的 verdaccio 身份验证
- verdaccio-github-oauth:verdaccio 的 Github oauth 认证插件。
- verdaccio-github-oauth-ui:verdaccio 登录按钮的 GitHub OAuth 插件。
- verdaccio-groupnames:用于使用 $group 语法处理动态组关联的插件。与 ldap 插件配合使用效果最佳。
中间件插件
什么是中间件插件?
中间件插件具有修改 API(Web 和 cli)层的能力,可以添加新的端点或拦截请求。
API
interface IPluginMiddleware<T> extends IPlugin<T> {
register_middlewares(app: any, auth: IBasicAuth<T>, storage: IStorageManager<T>): void;
}
register_middlewares
该方法通过 auth
和提供了对身份验证和存储的完全访问权限 storage
。
app
是允许您添加新端点的快速应用程序。
public register_middlewares(
app: Application,
auth: IBasicAuth<CustomConfig>,
storage: IStorageManager<CustomConfig>
): void {
const router = Router();
router.post(
'/custom-endpoint',
(req: Request, res: Response & { report_error?: Function }, next: NextFunction): void => {
const encryptedString = auth.aesEncrypt(Buffer.from(this.foo, 'utf8'));
res.setHeader('X-Verdaccio-Token-Plugin', encryptedString.toString());
next();
}
);
app.use('/-/npm/something-new', router);
}
在 auth
和 storage
这样的例子,可以延长,但我们不建议这种方法,除非有充分的理由。
verdaccio-audit 是中间件插件的一个很好的例子。
https://github.com/verdaccio/monorepo/tree/master/plugins/audi
生成中间件插件
有关详细信息,请查看我们的插件生成器。
yo 在您的终端中运行命令,然后按照下列步骤操作。
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? custom-endpoint
? Select Language typescript
? What kind of plugin you want to create? middleware
? Please, describe your plugin awesome middleware plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,middleware,awesome,verdaccio-plugin
create verdaccio-plugin-custom-endpoint/package.json
create verdaccio-plugin-custom-endpoint/.gitignore
create verdaccio-plugin-custom-endpoint/.npmignore
create verdaccio-plugin-custom-endpoint/jest.config.js
create verdaccio-plugin-custom-endpoint/.babelrc
create verdaccio-plugin-custom-endpoint/.travis.yml
create verdaccio-plugin-custom-endpoint/README.md
create verdaccio-plugin-custom-endpoint/.eslintrc
create verdaccio-plugin-custom-endpoint/.eslintignore
create verdaccio-plugin-custom-endpoint/src/index.ts
create verdaccio-plugin-custom-endpoint/index.ts
create verdaccio-plugin-custom-endpoint/tsconfig.json
create verdaccio-plugin-custom-endpoint/types/index.ts
create verdaccio-plugin-custom-endpoint/.editorconfig
I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc
安装完成后,访问您的项目目录。
➜ cd verdaccio-plugin-auth-service-name
➜ cat package.json
{
"name": "verdaccio-plugin-custom-endpoint",
"version": "0.0.1",
"description": "awesome middleware plugin",
...
中间件是在内置端点之后注册的,因此无法覆盖已实现的中间件。
列出社区中间件插件
- verdaccio-audit:用于 npm audit cli 支持的 verdaccio 插件(内置)(从 3.x 开始兼容)
- verdaccio 型材式 API:verdacci 插件 NPM 轮廓 CLI 支持和 NPM 轮廓设置的密码为 verdaccio-htpasswd 的基于 authentificaton
- verdaccio-https 如果设置了 x-forward-proto 标头,则 Verdaccio 中间件插件可重定向到 https
存储插件
什么是存储插件?
默认情况下,Verdaccio 使用文件系统存储插件 local-storage。可以使用社区插件或自己创建一个插件来轻松替换默认存储。
API
存储插件由两个对象,IPluginStorage
- 该 IPluginStorage 对象处理私有软件包的本地数据库。
interface IPluginStorage<T> extends IPlugin<T>, ITokenActions {
logger: Logger;
config: T & Config;
add(name: string, callback: Callback): void;
remove(name: string, callback: Callback): void;
get(callback: Callback): void;
getSecret(): Promise<string>;
setSecret(secret: string): Promise<any>;
getPackageStorage(packageInfo: string): IPackageStorage;
search(onPackage: onSearchPackage, onEnd: onEndSearchPackage, validateName: onValidatePackage): void;
}
- IPackageStorage 是由每个请求创建一个对象,该手柄用于元数据和压缩档的 I / O 操作。
interface IPackageStorage {
logger: Logger;
writeTarball(pkgName: string): IUploadTarball;
readTarball(pkgName: string): IReadTarball;
readPackage(fileName: string, callback: ReadPackageCallback): void;
createPackage(pkgName: string, value: Package, cb: CallbackAction): void;
deletePackage(fileName: string, callback: CallbackAction): void;
removePackage(callback: CallbackAction): void;
updatePackage(
pkgFileName: string,
updateHandler: StorageUpdateCallback,
onWrite: StorageWriteCallback,
transformPackage: PackageTransformer,
onEnd: CallbackAction
): void;
savePackage(fileName: string, json: Package, callback: CallbackAction): void;
}
生成中间件插件
有关详细信息,请查看我们的插件生成器。
yo 在您的终端中运行命令,然后按照下列步骤操作。
➜ yo verdaccio-plugin
Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator
_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What is the name of your plugin? custom-endpoint
? Select Language typescript
? What kind of plugin you want to create? storage
? Please, describe your plugin awesome storage plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,storage,awesome,verdaccio-plugin
create verdaccio-plugin-storage-package-database/package.json
create verdaccio-plugin-storage-package-database/.gitignore
create verdaccio-plugin-storage-package-database/.npmignore
create verdaccio-plugin-storage-package-database/jest.config.js
create verdaccio-plugin-storage-package-database/.babelrc
create verdaccio-plugin-storage-package-database/.travis.yml
create verdaccio-plugin-storage-package-database/README.md
create verdaccio-plugin-storage-package-database/.eslintrc
create verdaccio-plugin-storage-package-database/.eslintignore
create verdaccio-plugin-storage-package-database/src/PackageStorage.ts
create verdaccio-plugin-storage-package-database/src/index.ts
create verdaccio-plugin-storage-package-database/src/plugin.ts
create verdaccio-plugin-storage-package-database/index.ts
create verdaccio-plugin-storage-package-database/tsconfig.json
create verdaccio-plugin-storage-package-database/types/index.ts
create verdaccio-plugin-storage-package-database/.editorconfig
I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc
列出社区存储插件
以下插件列表实现存储 API,可以被用作示例。
- verdaccio-memory 在内存中装载包的存储插件
- verdaccio-s3-storage 存储插件以托管程序包 Amazon S3
- verdaccio-aws-s3-storage 存储插件,用于托管 Amazon S3 程序包(由 Verdaccio 核心团队维护)
- verdaccio-google-cloud Storage 插件,用于托管软件包 Google Cloud Storage
- verdaccio-minio 一个 verdaccio 插件,用于在 Minio 中存储数据
节点 API
Verdaccio
可以通过程序调用。 在版本 verdaccio@3.0.0
之后引入了节点 API。
使用
编程
import startServer from 'verdaccio';
startServer(configJsonFormat, 6000, store, '1.0.0', 'verdaccio',
(webServer, addrs, pkgName, pkgVersion) => {
webServer.listen(addr.port || addr.path, addr.host, () => {
console.log('verdaccio running');
});
});
其他执行
- verdaccio-server 本地 npm registry proxy server(代理服务器)
// js
import * as verdaccioServer from "verdaccio-server";
verdaccioServer.start();
verdaccioServer.stop();
verdaccioServer.list();
verdaccioServer.stopAll();
verdaccioServer.show();
verdaccioServer.cli();
// windows .net2
verdaccioServer.serviceInstall();
verdaccioServer.serviceUninstall();
verdaccioServer.serviceStart();
verdaccioServer.serviceStop();
verdaccioServer.serviceRestart();