diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9ea312e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,127 @@ +name: CI + +on: [push, pull_request] + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ^20 + + - name: Install Dependency + run: yarn install --no-lockfile + + - name: Run Lint + run: yarn run lint + + coverage: + needs: [lint] + runs-on: ubuntu-latest + services: + redis: + image: redis + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 6379:6379 + redis-cluster: + image: grokzen/redis-cluster:6.2.0 + ports: + - 7000:7000 + - 7001:7001 + - 7002:7002 + - 7003:7003 + - 7004:7004 + - 7005:7005 + steps: + - uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ^20 + + - name: Install Dependency + run: yarn install --no-lockfile + + - name: Run Coverage + run: yarn run coverage + + - name: Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + test: + needs: [lint] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: [^20] + services: + redis: + image: redis + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 6379:6379 + redis-cluster: + image: grokzen/redis-cluster:6.2.0 + ports: + - 7000:7000 + - 7001:7001 + - 7002:7002 + - 7003:7003 + - 7004:7004 + - 7005:7005 + steps: + - uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - name: Install Dependency + run: yarn install --no-lockfile + + - name: Run Unit test + run: yarn run test + + semantic-release: + needs: [lint, test, coverage] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ^20 + + - name: Run semantic-release + if: github.repository == 'node-casbin/redis-watcher' && github.event_name == 'push' + run: | + yarn install --no-lockfile + yarn run build + yarn run release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index f4f225b..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: main -on: [push, pull_request] -jobs: - test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - node-version: [^20] - services: - # Label used to access the service container - redis: - # Docker Hub image - image: redis - # Set health checks to wait until redis has started - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - -p 6379:6379 - --name redis - redis-cluster: - image: grokzen/redis-cluster:6.2.0 - options: >- - -p 7000:7000 - -p 7001:7001 - -p 7002:7002 - -p 7003:7003 - -p 7004:7004 - -p 7005:7005 - --name redis-cluster - - steps: - - uses: actions/checkout@v2 - - - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn install --no-lockfile - - run: yarn lint - - - run: docker logs redis - - run: docker logs redis-cluster - - - run: yarn test - - semantic-release: - needs: [test] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Run semantic-release - if: github.repository == 'node-casbin/redis-watcher' && github.event_name == 'push' - run: yarn install --no-lockfile && yarn semantic-release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/README.md b/README.md index 8133e6e..2499d4e 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,88 @@ -# Redis-watcher +# Redis Watcher +[![CI](https://github.com/node-casbin/redis-watcher/actions/workflows/ci.yml/badge.svg)](https://github.com/node-casbin/redis-watcher/actions/workflows/ci.yml) +[![Coverage Status](https://coveralls.io/repos/github/node-casbin/redis-watcher/badge.svg?branch=master)](https://coveralls.io/github/node-casbin/redis-watcher?branch=master) [![NPM version][npm-image]][npm-url] [![NPM download][download-image]][download-url] -[![ci](https://github.com/node-casbin/redis-watcher/actions/workflows/main.yml/badge.svg)](https://github.com/node-casbin/redis-watcher/actions/workflows/main.yml) -[![Coverage Status](https://coveralls.io/repos/github/node-casbin/redis-watcher/badge.svg?branch=master)](https://coveralls.io/github/node-casbin/redis-watcher?branch=master) [![Discord](https://img.shields.io/discord/1022748306096537660?logo=discord&label=discord&color=5865F2)](https://discord.gg/S5UjpzGZjN) -[npm-image]: https://img.shields.io/npm/v/redis-watcher.svg?style=flat-square -[npm-url]: https://npmjs.com/package/redis-watcher -[download-image]: https://img.shields.io/npm/dm/redis-watcher.svg?style=flat-square -[download-url]: https://npmjs.com/package/redis-watcher +[npm-image]: https://img.shields.io/npm/v/@casbin/redis-watcher.svg?style=flat-square +[npm-url]: https://npmjs.com/package/@casbin/redis-watcher +[download-image]: https://img.shields.io/npm/dm/@casbin/redis-watcher.svg?style=flat-square +[download-url]: https://npmjs.com/package/@casbin/redis-watcher -Redis watcher for node-casbin based on [ioredis](https://github.com/luin/ioredis). +Redis Watcher is the [Redis](https://redis.io/) watcher for [Node-Casbin](https://github.com/casbin/node-casbin). With this library, Node-Casbin can synchronize policy changes across multiple enforcer instances via Redis pub/sub. -# Installation +This watcher is based on [ioredis](https://github.com/luin/ioredis) and supports both single Redis instances and Redis clusters. -```shell script -# NPM -npm install --save @casbin/redis-watcher +## Installation -# Yarn -yarn add @casbin/redis-watcher +```bash +npm install @casbin/redis-watcher ``` -**Note: redis-watcher has been deprecated on NPM.** +**Note: The old package name `redis-watcher` has been deprecated on NPM. Please use `@casbin/redis-watcher` instead.** + +## Simple Example -# Example Using Redis: ```typescript import { RedisWatcher } from '@casbin/redis-watcher'; import { newEnforcer } from 'casbin'; -// Initialize the watcher, see https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options -const watcher = await RedisWatcher.newWatcher('redis://localhost:6379/5'); +async function myFunction() { + // Initialize the watcher + // See https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options + const watcher = await RedisWatcher.newWatcher('redis://localhost:6379/5'); + + // Initialize the enforcer + const enforcer = await newEnforcer('examples/authz_model.conf', 'examples/authz_policy.csv'); -// Initialize the enforcer. -const enforcer = await newEnforcer('examples/authz_model.conf', 'examples/authz_policy.csv'); + // Set the watcher for the enforcer + enforcer.setWatcher(watcher); -enforcer.setWatcher(watcher); + // Update the policy + await enforcer.addPolicy('alice', 'data1', 'read'); + + // The policy change will be synchronized to other enforcers via Redis pub/sub +} ``` -Using Redis cluster: +Using Redis Cluster: ```typescript import { RedisWatcher } from '@casbin/redis-watcher'; import { newEnforcer } from 'casbin'; -// Initialize the watcher, see https://github.com/luin/ioredis/blob/master/API.md#new-clusterstartupnodes-options. -const watcher = await RedisWatcher.newWatcherWithCluster([{ port: 7000, host: 'localhost' }]); +async function myFunction() { + // Initialize the watcher with Redis cluster + // See https://github.com/luin/ioredis/blob/master/API.md#new-clusterstartupnodes-options + const watcher = await RedisWatcher.newWatcherWithCluster([ + { port: 7000, host: 'localhost' }, + { port: 7001, host: 'localhost' }, + { port: 7002, host: 'localhost' } + ]); + + // Initialize the enforcer + const enforcer = await newEnforcer('examples/authz_model.conf', 'examples/authz_policy.csv'); + + // Set the watcher for the enforcer + enforcer.setWatcher(watcher); + + // Update the policy + await enforcer.addPolicy('bob', 'data2', 'write'); + + // The policy change will be synchronized to other enforcers via Redis pub/sub +} +``` -// Initialize the enforcer. -const enforcer = await newEnforcer('examples/authz_model.conf', 'examples/authz_policy.csv'); +## Getting Help -enforcer.setWatcher(watcher); -``` +- [Node-Casbin](https://github.com/casbin/node-casbin) +- [Casbin Forum](https://forum.casbin.com/) + +## License + +This project is under Apache 2.0 License. See the [LICENSE](LICENSE) file for the full license text. diff --git a/package.json b/package.json index c1dad65..46702dc 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "prettier": "prettier --write **/*.{ts,js}", "build": "rimraf lib && tsc -p tsconfig.json", "lint": "tslint -p . -c tslint.json", - "test": "jest --forceExit" + "test": "jest --forceExit", + "coverage": "jest --coverage --forceExit", + "release": "npx -p semantic-release -p @semantic-release/git -p @semantic-release/changelog semantic-release" }, "devDependencies": { "@semantic-release/changelog": "^5.0.1",