From d0f6b8f9a641826a9cda5998931870b979be0eae Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Sat, 17 Jul 2021 17:32:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=89=B4=E6=9D=83?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yml.example | 3 + package-lock.json | 209 ++++++++++++++++++++++++++++++ package.json | 2 + src/app.module.ts | 10 ++ src/articles/articles.resolver.ts | 4 + src/commons/commons.module.ts | 3 +- 6 files changed, 230 insertions(+), 1 deletion(-) diff --git a/config.yml.example b/config.yml.example index 64ac8e1..220e738 100644 --- a/config.yml.example +++ b/config.yml.example @@ -14,5 +14,8 @@ db: port: 6379 password: prefix: blog + etcd: + hosts: + - 'http://192.168.31.194:2379' workspaces: root: '/Users/ivanli/Projects/fennec/workspaces' \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 76802e7..23d02f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "version": "0.0.1", "license": "UNLICENSED", "dependencies": { + "@nestjs-lib/auth": "^0.1.1", "@nestjs/bull": "^0.3.1", "@nestjs/common": "^7.6.15", "@nestjs/config": "^0.6.2", @@ -28,6 +29,7 @@ "ioredis": "^4.25.0", "js-yaml": "^4.0.0", "marked": "^2.1.3", + "nestjs-etcd": "^0.2.0", "nestjs-redis": "^1.2.8", "observable-to-async-generator": "^1.0.1-rc", "pg": "^8.5.1", @@ -2058,6 +2060,31 @@ "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" } }, + "node_modules/@grpc/grpc-js": { + "version": "1.3.5", + "resolved": "https://npm.ivanli.cc/@grpc%2fgrpc-js/-/grpc-js-1.3.5.tgz", + "integrity": "sha512-V29L2QNKkLWM3bcJfVFMSo+Z7kkO8A1s7MAfdzBXLYEC1PE5/M0n1iXBDiD5aUtyVLh5GILcbme2bGtIHl0FMQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.5.6", + "resolved": "https://npm.ivanli.cc/@grpc%2fproto-loader/-/proto-loader-0.5.6.tgz", + "integrity": "sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2476,6 +2503,18 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@nestjs-lib/auth": { + "version": "0.1.1", + "resolved": "https://npm.ivanli.cc/@nestjs-lib%2fauth/-/auth-0.1.1.tgz", + "integrity": "sha512-fYje3oHErN/1ZKyrzTlZ+3+w7fp3XplkKz26U9OycTA5hu+/LlM6EEvuMt7pfdo02KllVtcUWMtmKbezzr4Ujw==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^7.0.0", + "@nestjs/graphql": "^7.10.3", + "jose": "^3.14.0", + "nestjs-etcd": "^0.2.0" + } + }, "node_modules/@nestjs/bull": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-0.3.1.tgz", @@ -4923,6 +4962,15 @@ "node": "*" } }, + "node_modules/bignumber.js": { + "version": "9.0.1", + "resolved": "https://npm.ivanli.cc/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -5713,6 +5761,15 @@ "node": ">= 0.12.0" } }, + "node_modules/cockatiel": { + "version": "1.1.1", + "resolved": "https://npm.ivanli.cc/cockatiel/-/cockatiel-1.1.1.tgz", + "integrity": "sha512-YO02ZhTcK2HOZodksWfg4tS1GYYt1j7R6U1unAkwcQf1uoIYKSBqPrfqXlLNbsyMvkDXMwa2nuwZDHbUkB1VbQ==", + "license": "MIT", + "engines": { + "node": ">=10 <11 || >=12" + } + }, "node_modules/code-block-writer": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-10.1.1.tgz", @@ -6866,6 +6923,18 @@ "node": ">= 0.6" } }, + "node_modules/etcd3": { + "version": "1.1.0", + "resolved": "https://npm.ivanli.cc/etcd3/-/etcd3-1.1.0.tgz", + "integrity": "sha512-9SnJvaPyW5IYdJHJWX91CYo1QZCAev2B7PxrQWIe2tGbutZOmsXHfjNDKwEltFWoG5h++K3/JfWPjJdOGX90hg==", + "license": "MIT", + "dependencies": { + "@grpc/grpc-js": "^1.1.7", + "@grpc/proto-loader": "^0.5.5", + "bignumber.js": "^9.0.0", + "cockatiel": "^1.1.1" + } + }, "node_modules/eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -9795,6 +9864,16 @@ "node": ">= 10.13.0" } }, + "node_modules/jose": { + "version": "3.14.0", + "resolved": "https://npm.ivanli.cc/jose/-/jose-3.14.0.tgz", + "integrity": "sha512-Hk4yFVGiSTuryL0XVyRTCvCPoD9eDCvEX/t+SpHTXXeNXsoxyopPLhoCLTt90vnu7yeIYXDdJWHNgI3Ix4H1FQ==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -10079,6 +10158,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://npm.ivanli.cc/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "license": "MIT" + }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -10723,6 +10808,21 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/nestjs-etcd": { + "version": "0.2.0", + "resolved": "https://npm.ivanli.cc/nestjs-etcd/-/nestjs-etcd-0.2.0.tgz", + "integrity": "sha512-I5tekNGFJ97auyHeCrnCN38D5AkaxxUAx3PlaZA0EOO/BTyNfyw9Fzqs4McCoUakT/sVVwdGELulcofRUzaFpw==", + "license": "MIT", + "dependencies": { + "etcd3": "^1.1.0" + }, + "peerDependencies": { + "@nestjs/common": "^6.7.0 || ^7.0.0", + "@nestjs/core": "^6.7.0 || ^7.0.0", + "reflect-metadata": "^0.1.12", + "rxjs": "^6.0.0" + } + }, "node_modules/nestjs-redis": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/nestjs-redis/-/nestjs-redis-1.3.3.tgz", @@ -11763,6 +11863,32 @@ "react-is": "^16.8.1" } }, + "node_modules/protobufjs": { + "version": "6.11.2", + "resolved": "https://npm.ivanli.cc/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, "node_modules/proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -17246,6 +17372,23 @@ "integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==", "requires": {} }, + "@grpc/grpc-js": { + "version": "1.3.5", + "resolved": "https://npm.ivanli.cc/@grpc%2fgrpc-js/-/grpc-js-1.3.5.tgz", + "integrity": "sha512-V29L2QNKkLWM3bcJfVFMSo+Z7kkO8A1s7MAfdzBXLYEC1PE5/M0n1iXBDiD5aUtyVLh5GILcbme2bGtIHl0FMQ==", + "requires": { + "@types/node": ">=12.12.47" + } + }, + "@grpc/proto-loader": { + "version": "0.5.6", + "resolved": "https://npm.ivanli.cc/@grpc%2fproto-loader/-/proto-loader-0.5.6.tgz", + "integrity": "sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ==", + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -17592,6 +17735,12 @@ "tar": "^6.1.0" } }, + "@nestjs-lib/auth": { + "version": "0.1.1", + "resolved": "https://npm.ivanli.cc/@nestjs-lib%2fauth/-/auth-0.1.1.tgz", + "integrity": "sha512-fYje3oHErN/1ZKyrzTlZ+3+w7fp3XplkKz26U9OycTA5hu+/LlM6EEvuMt7pfdo02KllVtcUWMtmKbezzr4Ujw==", + "requires": {} + }, "@nestjs/bull": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-0.3.1.tgz", @@ -19516,6 +19665,11 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://npm.ivanli.cc/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -20131,6 +20285,11 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, + "cockatiel": { + "version": "1.1.1", + "resolved": "https://npm.ivanli.cc/cockatiel/-/cockatiel-1.1.1.tgz", + "integrity": "sha512-YO02ZhTcK2HOZodksWfg4tS1GYYt1j7R6U1unAkwcQf1uoIYKSBqPrfqXlLNbsyMvkDXMwa2nuwZDHbUkB1VbQ==" + }, "code-block-writer": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-10.1.1.tgz", @@ -21016,6 +21175,17 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "etcd3": { + "version": "1.1.0", + "resolved": "https://npm.ivanli.cc/etcd3/-/etcd3-1.1.0.tgz", + "integrity": "sha512-9SnJvaPyW5IYdJHJWX91CYo1QZCAev2B7PxrQWIe2tGbutZOmsXHfjNDKwEltFWoG5h++K3/JfWPjJdOGX90hg==", + "requires": { + "@grpc/grpc-js": "^1.1.7", + "@grpc/proto-loader": "^0.5.5", + "bignumber.js": "^9.0.0", + "cockatiel": "^1.1.1" + } + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -23248,6 +23418,12 @@ "supports-color": "^7.0.0" } }, + "jose": { + "version": "3.14.0", + "resolved": "https://npm.ivanli.cc/jose/-/jose-3.14.0.tgz", + "integrity": "sha512-Hk4yFVGiSTuryL0XVyRTCvCPoD9eDCvEX/t+SpHTXXeNXsoxyopPLhoCLTt90vnu7yeIYXDdJWHNgI3Ix4H1FQ==", + "peer": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -23462,6 +23638,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://npm.ivanli.cc/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -23965,6 +24146,14 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "nestjs-etcd": { + "version": "0.2.0", + "resolved": "https://npm.ivanli.cc/nestjs-etcd/-/nestjs-etcd-0.2.0.tgz", + "integrity": "sha512-I5tekNGFJ97auyHeCrnCN38D5AkaxxUAx3PlaZA0EOO/BTyNfyw9Fzqs4McCoUakT/sVVwdGELulcofRUzaFpw==", + "requires": { + "etcd3": "^1.1.0" + } + }, "nestjs-redis": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/nestjs-redis/-/nestjs-redis-1.3.3.tgz", @@ -24757,6 +24946,26 @@ "react-is": "^16.8.1" } }, + "protobufjs": { + "version": "6.11.2", + "resolved": "https://npm.ivanli.cc/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", diff --git a/package.json b/package.json index 01f2d67..93ab2d0 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { + "@nestjs-lib/auth": "^0.1.1", "@nestjs/bull": "^0.3.1", "@nestjs/common": "^7.6.15", "@nestjs/config": "^0.6.2", @@ -41,6 +42,7 @@ "ioredis": "^4.25.0", "js-yaml": "^4.0.0", "marked": "^2.1.3", + "nestjs-etcd": "^0.2.0", "nestjs-redis": "^1.2.8", "observable-to-async-generator": "^1.0.1-rc", "pg": "^8.5.1", diff --git a/src/app.module.ts b/src/app.module.ts index f749f74..a374afd 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -11,6 +11,8 @@ import { ParseBodyMiddleware } from './commons/middleware/parse-body.middleware' import { BullModule } from '@nestjs/bull'; import { PubSubModule } from './commons/pub-sub/pub-sub.module'; import { ArticlesModule } from './articles/articles.module'; +import { EtcdModule } from 'nestjs-etcd'; +import { CommonsModule } from './commons/commons.module'; @Module({ imports: [ @@ -73,6 +75,14 @@ import { ArticlesModule } from './articles/articles.module'; }), inject: [ConfigService], }), + EtcdModule.forRootAsync({ + imports: [ConfigModule], + useFactory: (configService: ConfigService) => ({ + hosts: configService.get('db.etcd.hosts', 'localhost:2379'), + }), + inject: [ConfigService], + }), + CommonsModule, ArticlesModule, ], controllers: [AppController], diff --git a/src/articles/articles.resolver.ts b/src/articles/articles.resolver.ts index 75cafcf..02c9b19 100644 --- a/src/articles/articles.resolver.ts +++ b/src/articles/articles.resolver.ts @@ -13,11 +13,13 @@ import { CreateArticleInput } from './dto/create-article.input'; import { UpdateArticleInput } from './dto/update-article.input'; import * as marked from 'marked'; import { getLanguage, highlight } from 'highlight.js'; +import { AccountRole, Roles } from '@nestjs-lib/auth'; @Resolver(() => Article) export class ArticlesResolver { constructor(private readonly articlesService: ArticlesService) {} + @Roles(AccountRole.admin, AccountRole.super) @Mutation(() => Article) createArticle( @Args('createArticleInput') createArticleInput: CreateArticleInput, @@ -35,6 +37,7 @@ export class ArticlesResolver { return this.articlesService.findOne(id); } + @Roles(AccountRole.admin, AccountRole.super) @Mutation(() => Article) async updateArticle( @Args('updateArticleInput') updateArticleInput: UpdateArticleInput, @@ -43,6 +46,7 @@ export class ArticlesResolver { return this.articlesService.update(article, updateArticleInput); } + @Roles(AccountRole.admin, AccountRole.super) @Mutation(() => Int) removeArticle(@Args('id', { type: () => String }) id: string) { return this.articlesService.remove(id); diff --git a/src/commons/commons.module.ts b/src/commons/commons.module.ts index 476581d..26c2fd1 100644 --- a/src/commons/commons.module.ts +++ b/src/commons/commons.module.ts @@ -1,10 +1,11 @@ import { Module } from '@nestjs/common'; import { PasswordConverter } from './services/password-converter'; import { PubSubModule } from './pub-sub/pub-sub.module'; +import { AuthModule } from '@nestjs-lib/auth'; @Module({ + imports: [PubSubModule, AuthModule], providers: [PasswordConverter], exports: [PasswordConverter], - imports: [PubSubModule], }) export class CommonsModule {}