{"_id":"@elchinabilov/nestjs-ownership","name":"@elchinabilov/nestjs-ownership","dist-tags":{"latest":"1.1.7"},"versions":{"1.1.7":{"name":"@elchinabilov/nestjs-ownership","version":"1.1.7","description":"A dynamic and recursive access control library for NestJS that enforces branch-level ownership across entities.","author":{"name":"Elchin Abilov","email":"abilovelchin@gmail.com"},"license":"ISC","keywords":["nestjs","ownership"],"main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","lint":"eslint \"src/**/*.ts\" --fix","test":"jest","test:watch":"jest --watch","test:cov":"jest --coverage","prepublishOnly":"npm run build","prepublish":"npm run build"},"peerDependencies":{"@nestjs/common":"^11.0.0","typeorm":"^0.3.21"},"engines":{"node":">=18.0.0"},"packageManager":"pnpm@10.17.0+sha512.fce8a3dd29a4ed2ec566fb53efbb04d8c44a0f05bc6f24a73046910fb9c3ce7afa35a0980500668fa3573345bd644644fa98338fa168235c80f4aa17aa17fbef","dependencies":{"@nestjs/core":"^11.1.8","typescript":"^5.9.3"},"_id":"@elchinabilov/nestjs-ownership@1.1.7","_nodeVersion":"22.19.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-DlT/IUdKixZSJMkJkFzQCOEW84qHDHQ1BqPKt+D3avblbNfAZ5PZOovyA9OTEmMwXwDko+vxIwbb6g4wozpvmQ==","shasum":"f1176455e8f334a0124a8ff752ab934eef78d1bc","tarball":"https://registry.npmjs.org/@elchinabilov/nestjs-ownership/-/nestjs-ownership-1.1.7.tgz","fileCount":36,"unpackedSize":246388,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDE+ZIXGgM8nyl3/FqnfddleUGJ/Mkwc660YkTYz7v7uAIhAPGr24a+umgQxiRcXsuwjjhPuWhf6MeIGLt43FcePD9m"}]},"_npmUser":{"name":"abilov","email":"abilovelchin@gmail.com"},"directories":{},"maintainers":[{"name":"abilov","email":"abilovelchin@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-ownership_1.1.7_1761811551349_0.598316338601522"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-30T08:05:51.224Z","1.1.7":"2025-10-30T08:05:51.545Z","modified":"2025-10-30T08:05:51.880Z"},"maintainers":[{"name":"abilov","email":"abilovelchin@gmail.com"}],"description":"A dynamic and recursive access control library for NestJS that enforces branch-level ownership across entities.","keywords":["nestjs","ownership"],"author":{"name":"Elchin Abilov","email":"abilovelchin@gmail.com"},"license":"ISC","readme":"# @elchinabilov/nestjs-ownership\n\nA dynamic, recursive branch-based access control module for NestJS.\n\n### Installation\n\n```bash\nnpm install @elchinabilov/nestjs-ownership\n```\n\n### Nə edir?\n\nBu modul entitilərdə filial/şöbə (`branch`) əsaslı sahibliyi məcburi edir. İstifadəçi yalnız özünün aid olduğu `branchId`-ə sahib olan resurslara daxil ola bilir. Admin rollar üçün bypass var.\n\n### Tez başlanğıc\n\n1. Modulu layihənizə qoşun (asinxron konfiqurasiya ilə):\n\n```ts\n// app.module.ts\nimport { Module } from \"@nestjs/common\";\nimport { TypeOrmModule, getDataSourceToken } from \"@nestjs/typeorm\";\nimport { OwnershipModule } from \"@elchinabilov/nestjs-ownership\";\nimport { DataSource } from \"typeorm\";\n\n@Module({\n  imports: [\n    TypeOrmModule.forRoot({\n      /* ... */\n    }),\n    OwnershipModule.forRootAsync({\n      imports: [\n        TypeOrmModule.forRoot({\n          /* ... */\n        }),\n      ],\n      inject: [getDataSourceToken()],\n      useFactory: async (dataSource: DataSource) => ({\n        dataSource,\n        // İstədiyiniz qədər entity üçün xəritə\n        map: {\n          // Açarı entity adı və ya cədvəl adı ola bilər (bax: OwnershipService.getRepositoryByName)\n          menu: {\n            // entity-dən branch-a gedən əlaqələr zənciri\n            // məsələn: Menu -> Restaurant -> Branch\n            path: [\"restaurant\", \"branch\"],\n            // route param-ın adı (default: \"id\")\n            idParam: \"id\",\n          },\n        },\n        // İstifadəçinin rolunun saxlandığı sahə (req.user[roleField])\n        roleField: \"role\",\n        // Sahibliyin müqayisə olunduğu sahə ( həm user, həm də owner obyektində )\n        ownershipField: \"branchId\",\n        // Admin rollar (tam bypass)\n        adminRoles: [\"admin\"],\n      }),\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n2. Kontroller və ya metod səviyyəsində dekoratorla entity-ni qeyd edin:\n\n```ts\nimport { Controller, Get, Param, UseGuards } from \"@nestjs/common\";\nimport { Ownership, OwnershipGuard } from \"@elchinabilov/nestjs-ownership\";\n\n@Controller(\"menus\")\n@Ownership(\"menu\") // bütün metodlara şamil olunur\n@UseGuards(OwnershipGuard)\nexport class MenuController {\n  @Get(\":id\")\n  // İstəsəniz metod səviyyəsində də təyin edə bilərsiniz, idParam-ı override etmək mümkündür\n  @Ownership(\"menu\", { idParam: \"id\" })\n  findOne(@Param(\"id\") id: string) {\n    // ...\n  }\n}\n```\n\n3. İstifadəçinin `branchId` və `role` məlumatı `request.user` daxilində olmalıdır.\n\n### Necə işləyir?\n\n- Guard `request.user` içindəki `roleField` əsasında admin olub-olmadığını yoxlayır. Adminlər üçün bypass edilir.\n- Dekoratordan oxunan `entityKey` və `idParam` əsasında resursun `id`-si `params/body/query` üzərindən götürülür.\n- `OwnershipService.loadOwnerThroughPath` TypeORM vasitəsilə xəritədə verilmiş `path` üzrə `LEFT JOIN` edərək resursun sahibini (`ownerObj`) çıxarır.\n- `ownerObj[ownershipField]` ilə `user[ownershipField]` müqayisə olunur. Uyğun deyilsə `403 Forbidden` atılır.\n- `id` verilməyən sorğular (məs: siyahı və ya create) guard tərəfindən buraxılır.\n\n### Konfiqurasiya parametrləri\n\n- `dataSource: DataSource` — TypeORM `DataSource` obyekti (mütləq)\n- `map: OwnershipMap` — entity -> { path, idParam } xəritəsi (mütləq)\n- `roleField?: string` — istifadəçi rol sahəsi; default: `\"role\"`\n- `ownershipField?: string` — müqayisə sahəsi; default: `\"branchId\"`\n- `adminRoles?: string[]` — admin rollar; default: `[\"admin\"]`\n\n`OwnershipMap` tipi:\n\n```ts\ntype OwnershipMap = Record<\n  string,\n  {\n    path?: string[]; // entity-dən branch-a gedən əlaqələr\n    idParam?: string; // route param (default: \"id\")\n  }\n>;\n```\n\n### Qeydlər\n\n- Modul `@Global()` olduğu üçün `OwnershipGuard` qlobal qeydiyyatla gəlir; lakin istəsəniz kontroller səviyyəsində də `@UseGuards(OwnershipGuard)` ilə tətbiq edə bilərsiniz.\n- Entity açarı olaraq həm entity adı, həm də cədvəl adı istifadə edilə bilər. Daxildə metadata ilə uyğunluq yoxlanılır.\n- `src/common/ownership.map.ts` faylı geriyə uyğunluq üçün mövcuddur və tipləri `src/common/interfaces.ts` ilə eyni xəttə gətirilmişdir.\n\n### Lisenzya\n\nISC\n","readmeFilename":"README.md","_rev":"1-fd056bda763c0928ecdf85ae87dac098"}