nestjs-ip-filter 0.1.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +108 -134
- package/dist/index.d.ts +1 -2
- package/dist/index.js +6 -4
- package/dist/ipfilter-deny.exception.js +0 -1
- package/dist/ipfilter.constants.d.ts +0 -1
- package/dist/ipfilter.constants.js +1 -3
- package/dist/ipfilter.guard.d.ts +2 -3
- package/dist/ipfilter.guard.js +11 -25
- package/dist/ipfilter.interface.d.ts +1 -14
- package/dist/ipfilter.interface.js +0 -1
- package/dist/ipfilter.module-definition.d.ts +8 -0
- package/dist/ipfilter.module-definition.js +19 -0
- package/dist/ipfilter.module.d.ts +2 -5
- package/dist/ipfilter.module.js +21 -17
- package/dist/ipfilter.service.d.ts +7 -4
- package/dist/ipfilter.service.js +61 -13
- package/package.json +36 -60
- package/.eslintrc.js +0 -29
- package/.prettierrc +0 -4
- package/.vscode/settings.json +0 -3
- package/dist/index.js.map +0 -1
- package/dist/ipfilter-core.module.d.ts +0 -24
- package/dist/ipfilter-core.module.js +0 -87
- package/dist/ipfilter-core.module.js.map +0 -1
- package/dist/ipfilter-deny.exception.js.map +0 -1
- package/dist/ipfilter.constants.js.map +0 -1
- package/dist/ipfilter.guard.js.map +0 -1
- package/dist/ipfilter.interface.js.map +0 -1
- package/dist/ipfilter.module.js.map +0 -1
- package/dist/ipfilter.providers.d.ts +0 -3
- package/dist/ipfilter.providers.js +0 -13
- package/dist/ipfilter.providers.js.map +0 -1
- package/dist/ipfilter.service.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/index.js +0 -6
- package/index.ts +0 -1
- package/lib/index.ts +0 -8
- package/lib/ipfilter-core.module.ts +0 -94
- package/lib/ipfilter-deny.exception.ts +0 -7
- package/lib/ipfilter.constants.ts +0 -2
- package/lib/ipfilter.guard.ts +0 -56
- package/lib/ipfilter.interface.ts +0 -28
- package/lib/ipfilter.module.ts +0 -23
- package/lib/ipfilter.providers.ts +0 -13
- package/lib/ipfilter.service.ts +0 -37
- package/nest-cli.json +0 -5
- package/renovate.json +0 -10
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -24
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Breaking changes
|
|
6
|
+
|
|
7
|
+
- Rules are IPv4/IPv6 addresses and CIDR ranges instead of regular expressions; an invalid entry throws at startup or from a setter. An IPv4-mapped rule with an IPv6 prefix under 96 is rejected.
|
|
8
|
+
- The client IP is `req.ip`, which follows the app's `trust proxy` setting, instead of forwarded headers read from anyone.
|
|
9
|
+
- The filter mode is explicit: a configured `whitelist` (even `[]`) allows only its matches; without one, everyone not blacklisted is allowed. Configuring neither list (`undefined` or `null`) throws at startup.
|
|
10
|
+
- `IpFilterDenyException` carries only `{ clientIp }`.
|
|
11
|
+
- `IpFilterService.whitelist` / `blacklist` return `string[] | undefined` (a copy, or `undefined` when not configured).
|
|
12
|
+
- Requires NestJS 11 or 12 (now peer dependencies) and Node.js `>=22.12.0`.
|
|
13
|
+
- Removed the unused `IpFilterDenyHandler` interface.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- The guard crashed on GraphQL requests and denied every WebSocket/RPC message; non-HTTP contexts now pass through unfiltered.
|
|
18
|
+
- A rule like `10.0.0.1` also matched `110.0.0.15` (unanchored regex).
|
|
19
|
+
- A forged `X-Forwarded-For` header bypassed the whitelist.
|
|
20
|
+
- With both lists set, the whitelist was ignored.
|
|
21
|
+
- Denied clients received the full whitelist and blacklist in the exception response.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- `global: false` to apply the guard only where `@UseGuards(IpFilterGuard)` is used (#519).
|
|
26
|
+
- `IpFilterGuard` and `IPFILTER_TOKEN` resolve in every module; register `IpFilter` once in the root module.
|
|
27
|
+
- IPv6 rules.
|
|
28
|
+
- Tests and CI for Node.js 22/24 and NestJS 11/12 (#68).
|
|
29
|
+
|
|
30
|
+
### Removed
|
|
31
|
+
|
|
32
|
+
- The `@supercharge/request-ip` dependency; the package has no runtime dependencies.
|
|
33
|
+
- The `example/` project; the README covers its usage.
|
package/README.md
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# NestJS IP Filter
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A NestJS guard that allows or denies requests by client IP address, using whitelists and blacklists of IPv4/IPv6 addresses and CIDR ranges.
|
|
4
4
|
|
|
5
|
-
It
|
|
5
|
+
It filters HTTP requests. GraphQL, WebSocket and microservice (RPC) contexts are not filtered and pass through.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Requirements
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- NestJS 11 or 12
|
|
10
|
+
- Node.js `>=22.12.0`
|
|
11
|
+
- The Express platform (`@nestjs/platform-express`)
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
## Install
|
|
12
14
|
|
|
13
15
|
```bash
|
|
14
16
|
npm install nestjs-ip-filter
|
|
@@ -16,180 +18,152 @@ npm install nestjs-ip-filter
|
|
|
16
18
|
|
|
17
19
|
## Usage
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
> In Express-based framework, the incoming IP address will have prefix `::ffff:` characters. So if you have put `(^192.168.)` into the whitelist, it won't work because that regex describes it must have number `1` as a first character.
|
|
22
|
-
> So for now, you should put that prefix for your regex string like `(^::ffff:192.168.)`. Will patch the source codes in the near future.
|
|
23
|
-
|
|
24
|
-
You can use the Regex format string for the IP ranges.
|
|
25
|
-
|
|
26
|
-
For a simple example, if you want to allow the private network hosts in `192.168.0.1/16`, you can write the Regex string like the below.
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
# 192.168.0.0 ~ 192.168.255.255
|
|
30
|
-
(^192.168.)
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Check the other use cases.
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
# 192.168.0.100 ~ 192.168.0.110
|
|
37
|
-
(^192.168.0.1[0-1]0)
|
|
38
|
-
|
|
39
|
-
# 172.16.16.10, 172.16.17.10, 172.16.18.10
|
|
40
|
-
(^172.16.1[6-8].10)
|
|
41
|
-
|
|
42
|
-
# 110~119.*
|
|
43
|
-
(^11[0-9].*)
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
And, writing in this way also works on this package.
|
|
47
|
-
|
|
48
|
-
But be aware of that you should write the Regex string very carefully to avoid allowing unwanted incoming IP addresses.
|
|
49
|
-
|
|
50
|
-
### Basic usage for Whitelist
|
|
51
|
-
|
|
52
|
-
You can initialize the dedicated Guard using non-async or async mode, as the other NestJS packages support.
|
|
53
|
-
|
|
54
|
-
Use `forRoot` for the static IP address list.
|
|
21
|
+
Import `IpFilter` once, in your root module. The guard then applies to every route, and `IpFilterGuard` and `IPFILTER_TOKEN` are available in every module.
|
|
55
22
|
|
|
56
23
|
```typescript
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
24
|
+
import { Module } from '@nestjs/common';
|
|
25
|
+
import { IpFilter } from 'nestjs-ip-filter';
|
|
26
|
+
|
|
27
|
+
@Module({
|
|
28
|
+
imports: [
|
|
29
|
+
IpFilter.register({
|
|
30
|
+
whitelist: ['127.0.0.1', '::1', '192.168.0.0/16'],
|
|
31
|
+
}),
|
|
62
32
|
],
|
|
63
|
-
})
|
|
33
|
+
})
|
|
34
|
+
export class AppModule {}
|
|
64
35
|
```
|
|
65
36
|
|
|
66
|
-
|
|
37
|
+
Use `registerAsync` to load the lists from another provider, such as a config service or a database.
|
|
67
38
|
|
|
68
39
|
```typescript
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
useFactory: async (myConfigService: MyConfigService) => ({
|
|
76
|
-
whitelist: myConfigService.getWhitelist(),
|
|
40
|
+
IpFilter.registerAsync({
|
|
41
|
+
imports: [ConfigModule],
|
|
42
|
+
inject: [ConfigService],
|
|
43
|
+
useFactory: (config: ConfigService) => ({
|
|
44
|
+
whitelist: config.get<string[]>('ipFilter.whitelist'),
|
|
45
|
+
blacklist: config.get<string[]>('ipFilter.blacklist'),
|
|
77
46
|
}),
|
|
78
|
-
})
|
|
47
|
+
});
|
|
79
48
|
```
|
|
80
49
|
|
|
81
|
-
|
|
50
|
+
### Rules
|
|
82
51
|
|
|
83
|
-
|
|
52
|
+
Each entry is an IPv4 or IPv6 address, or a CIDR range:
|
|
84
53
|
|
|
85
|
-
|
|
54
|
+
```typescript
|
|
55
|
+
'10.0.0.1'; // one address
|
|
56
|
+
'10.0.0.0/8'; // 10.0.0.0 – 10.255.255.255
|
|
57
|
+
'2001:db8::/32'; // an IPv6 range
|
|
58
|
+
```
|
|
86
59
|
|
|
87
|
-
|
|
60
|
+
IPv4-mapped IPv6 client addresses (`::ffff:10.1.2.3`) match IPv4 rules, so write IPv4 ranges as IPv4 CIDR.
|
|
61
|
+
A mapped rule with an IPv6 prefix under 96 (`::ffff:192.168.0.0/16`) is rejected: as an IPv6 range it would span all of IPv4.
|
|
62
|
+
An invalid entry throws when the module starts or when a list is set, so a typo never silently matches nothing.
|
|
88
63
|
|
|
89
|
-
|
|
64
|
+
### How a request is evaluated
|
|
90
65
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
IpFilter.forRootAsync({
|
|
96
|
-
imports: [ MyConfigModule ],
|
|
97
|
-
inject: [ MyConfigService ],
|
|
98
|
-
useFactory: async (myConfigService: MyConfigService) => ({
|
|
99
|
-
whitelist: myConfigService.getWhitelist(),
|
|
100
|
-
blacklist: myConfigService.getBlacklist(),
|
|
101
|
-
}),
|
|
102
|
-
}),
|
|
103
|
-
```
|
|
66
|
+
1. A client IP in the `blacklist` is denied.
|
|
67
|
+
2. If a `whitelist` is configured, only client IPs in it are allowed. An empty whitelist (`[]`) allows nobody.
|
|
68
|
+
3. If no `whitelist` is configured, every client IP not denied by step 1 is allowed.
|
|
104
69
|
|
|
105
|
-
|
|
70
|
+
At least one of `whitelist` and `blacklist` must be configured; otherwise the module throws at startup.
|
|
71
|
+
This way a missing configuration value fails loudly instead of opening or closing everything.
|
|
106
72
|
|
|
107
|
-
|
|
73
|
+
| `whitelist` | `blacklist` | Allowed |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| `['10.0.0.0/8']` | not set | `10.0.0.0/8` only |
|
|
76
|
+
| not set | `['10.0.0.5']` | everyone except `10.0.0.5` |
|
|
77
|
+
| `['10.0.0.0/8']` | `['10.0.0.5']` | `10.0.0.0/8` except `10.0.0.5` |
|
|
78
|
+
| `[]` | not set | nobody |
|
|
79
|
+
| not set | `[]` | everyone |
|
|
80
|
+
| not set | not set | throws at startup |
|
|
108
81
|
|
|
109
|
-
|
|
82
|
+
### Behind a proxy or load balancer
|
|
110
83
|
|
|
111
|
-
|
|
84
|
+
The guard uses `req.ip`, so the client IP follows Express's [`trust proxy`](https://expressjs.com/en/guide/behind-proxies.html) setting.
|
|
85
|
+
Forwarded headers such as `X-Forwarded-For` are used only from proxies you trust; anyone else can forge them.
|
|
112
86
|
|
|
113
87
|
```typescript
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
IpFilter.forRootAsync({
|
|
118
|
-
imports: [ MyConfigModule ],
|
|
119
|
-
inject: [ MyConfigService ],
|
|
120
|
-
useFactory: async (myConfigService: MyConfigService) => ({
|
|
121
|
-
whitelist: myConfigService.getWhitelist(),
|
|
122
|
-
blacklist: myConfigService.getBlacklist(),
|
|
123
|
-
useDenyException: true,
|
|
124
|
-
}),
|
|
125
|
-
}),
|
|
126
|
-
```
|
|
88
|
+
import { NestFactory } from '@nestjs/core';
|
|
89
|
+
import { NestExpressApplication } from '@nestjs/platform-express';
|
|
127
90
|
|
|
128
|
-
|
|
91
|
+
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
|
92
|
+
app.set('trust proxy', 'loopback'); // or the proxy's address/CIDR, or the number of hops
|
|
93
|
+
```
|
|
129
94
|
|
|
130
|
-
|
|
95
|
+
Without it, every request behind a proxy appears to come from the proxy's address.
|
|
131
96
|
|
|
132
|
-
|
|
97
|
+
### Apply to some routes only
|
|
133
98
|
|
|
134
|
-
|
|
99
|
+
Set `global: false` in the root module and add `IpFilterGuard` where you need it, in any module.
|
|
135
100
|
|
|
136
|
-
|
|
101
|
+
```typescript
|
|
102
|
+
@Module({
|
|
103
|
+
imports: [IpFilter.register({ whitelist: ['10.0.0.0/8'], global: false }), AdminModule],
|
|
104
|
+
})
|
|
105
|
+
export class AppModule {}
|
|
137
106
|
|
|
138
|
-
|
|
107
|
+
@Controller('admin')
|
|
108
|
+
@UseGuards(IpFilterGuard)
|
|
109
|
+
export class AdminController {}
|
|
139
110
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
export class SomeService {
|
|
143
|
-
constructor(
|
|
144
|
-
@inject(IPFILTER_TOKEN)
|
|
145
|
-
private readonly ipFilterService: IpFilterService
|
|
146
|
-
) {}
|
|
147
|
-
// ...
|
|
148
|
-
}
|
|
111
|
+
@Module({ controllers: [AdminController] })
|
|
112
|
+
export class AdminModule {}
|
|
149
113
|
```
|
|
150
114
|
|
|
151
|
-
|
|
115
|
+
### Handle denied requests
|
|
116
|
+
|
|
117
|
+
By default a denied request gets NestJS's standard `403 Forbidden`.
|
|
118
|
+
With `useDenyException: true` the guard throws `IpFilterDenyException` instead, whose response is `{ clientIp }`, so you can catch it in an exception filter.
|
|
152
119
|
|
|
153
120
|
```typescript
|
|
154
|
-
|
|
155
|
-
|
|
121
|
+
@Catch(IpFilterDenyException)
|
|
122
|
+
export class IpFilterDenyExceptionFilter implements ExceptionFilter {
|
|
123
|
+
catch(exception: IpFilterDenyException, host: ArgumentsHost) {
|
|
124
|
+
const { clientIp } = exception.getResponse() as { clientIp?: string };
|
|
125
|
+
host.switchToHttp().getResponse<Response>().status(403).json({ message: 'Forbidden', clientIp });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
156
128
|
```
|
|
157
129
|
|
|
158
|
-
|
|
130
|
+
### Change the lists at runtime
|
|
159
131
|
|
|
160
|
-
|
|
132
|
+
Inject `IpFilterService` with `IPFILTER_TOKEN`. Setting a list replaces it and applies to the next request; an invalid entry throws and keeps the previous list.
|
|
161
133
|
|
|
162
|
-
|
|
134
|
+
```typescript
|
|
135
|
+
@Injectable()
|
|
136
|
+
export class IpRulesService {
|
|
137
|
+
constructor(@Inject(IPFILTER_TOKEN) private readonly ipFilter: IpFilterService) {}
|
|
163
138
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
139
|
+
block(address: string) {
|
|
140
|
+
this.ipFilter.blacklist = [...(this.ipFilter.blacklist ?? []), address];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
167
143
|
```
|
|
168
144
|
|
|
169
|
-
|
|
145
|
+
The getters return a copy of the list, or `undefined` when that list is not configured. Emptying a list keeps the mode: an empty whitelist still allows nobody.
|
|
146
|
+
Setting a whitelist on an app that had none switches it to whitelist mode, so only the whitelisted addresses pass from then on.
|
|
170
147
|
|
|
171
|
-
|
|
148
|
+
## Migrating from 0.x
|
|
172
149
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
150
|
+
- **Rules are addresses and CIDR ranges, not regular expressions.** Rewrite `'(^192.168.)'` as `'192.168.0.0/16'` and drop the `::ffff:` prefix workaround (write `'192.168.0.0/16'`, not `'::ffff:192.168.0.0/16'`). A regex entry now throws at startup.
|
|
151
|
+
- **The client IP is `req.ip`.** 0.x read `X-Forwarded-For` and similar headers from anyone, which allowed spoofing. Behind a proxy, set [`trust proxy`](#behind-a-proxy-or-load-balancer).
|
|
152
|
+
- **The blacklist no longer overrides the whitelist.** With both lists set, a client must be in the whitelist and not in the blacklist; 0.x let anyone outside the blacklist through.
|
|
153
|
+
- **Configure at least one list** (`null` counts as not configured). 0.x denied everything when both lists were empty. Set `whitelist: []` to keep that behavior, for example when the lists are filled at runtime.
|
|
154
|
+
- **`IpFilterDenyException` carries only `{ clientIp }`.** 0.x also sent both lists to the denied client.
|
|
155
|
+
- **The getters return `string[] | undefined`.**
|
|
156
|
+
- NestJS 11 or 12 and Node.js `>=22.12.0` are required.
|
|
176
157
|
|
|
177
|
-
|
|
158
|
+
## Development
|
|
178
159
|
|
|
179
160
|
```bash
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
```bash
|
|
186
|
-
{"statusCode":403,"timestamp":"2022-06-13T09:29:40.452Z","ipFilterData":{"clientIp":"::ffff:127.0.0.1","whitelist":["(^::1)","(^192.168.)"],"blacklist":[]},"path":"/ipfilter"}
|
|
161
|
+
npm ci
|
|
162
|
+
npm run lint
|
|
163
|
+
npm test
|
|
164
|
+
npm run build
|
|
187
165
|
```
|
|
188
166
|
|
|
189
|
-
[Our exception filter](example/src/exception/ipfilter-exception-filter.exception.ts) put that additional field on the typical HttpException results.
|
|
190
|
-
|
|
191
|
-
You can test the projects with your local host IP address, [by editing the whitelist and the blacklist](example/src/ip-repository/ip-repository.service.ts).
|
|
192
|
-
|
|
193
167
|
## License
|
|
194
168
|
|
|
195
|
-
|
|
169
|
+
[MIT](LICENSE)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export * from './ipfilter-core.module';
|
|
2
1
|
export * from './ipfilter-deny.exception';
|
|
3
2
|
export * from './ipfilter.constants';
|
|
4
3
|
export * from './ipfilter.guard';
|
|
5
4
|
export * from './ipfilter.interface';
|
|
6
5
|
export * from './ipfilter.module';
|
|
7
|
-
export * from './ipfilter.
|
|
6
|
+
export * from './ipfilter.module-definition';
|
|
8
7
|
export * from './ipfilter.service';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -10,12 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
10
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
15
|
};
|
|
12
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
__exportStar(require("./ipfilter-core.module"), exports);
|
|
14
17
|
__exportStar(require("./ipfilter-deny.exception"), exports);
|
|
15
18
|
__exportStar(require("./ipfilter.constants"), exports);
|
|
16
19
|
__exportStar(require("./ipfilter.guard"), exports);
|
|
17
20
|
__exportStar(require("./ipfilter.interface"), exports);
|
|
18
21
|
__exportStar(require("./ipfilter.module"), exports);
|
|
19
|
-
__exportStar(require("./ipfilter.
|
|
22
|
+
__exportStar(require("./ipfilter.module-definition"), exports);
|
|
20
23
|
__exportStar(require("./ipfilter.service"), exports);
|
|
21
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IPFILTER_TOKEN =
|
|
4
|
-
exports.IPFILTER_MODULE_OPTIONS = Symbol('IpFilterModuleOptions');
|
|
3
|
+
exports.IPFILTER_TOKEN = void 0;
|
|
5
4
|
exports.IPFILTER_TOKEN = Symbol('IpFilterToken');
|
|
6
|
-
//# sourceMappingURL=ipfilter.constants.js.map
|
package/dist/ipfilter.guard.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
-
import {
|
|
3
|
-
import { IpFilterService } from './ipfilter.service';
|
|
2
|
+
import type { IpFilterService } from './ipfilter.service';
|
|
4
3
|
export declare class IpFilterGuard implements CanActivate {
|
|
5
4
|
private readonly ipFilterService;
|
|
6
5
|
constructor(ipFilterService: IpFilterService);
|
|
7
|
-
canActivate(context: ExecutionContext):
|
|
6
|
+
canActivate(context: ExecutionContext): boolean;
|
|
8
7
|
}
|
package/dist/ipfilter.guard.js
CHANGED
|
@@ -14,44 +14,30 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.IpFilterGuard = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
|
-
const requestIp = require("@supercharge/request-ip");
|
|
18
|
-
const ipfilter_service_1 = require("./ipfilter.service");
|
|
19
17
|
const ipfilter_constants_1 = require("./ipfilter.constants");
|
|
20
18
|
const ipfilter_deny_exception_1 = require("./ipfilter-deny.exception");
|
|
21
19
|
let IpFilterGuard = class IpFilterGuard {
|
|
20
|
+
ipFilterService;
|
|
22
21
|
constructor(ipFilterService) {
|
|
23
22
|
this.ipFilterService = ipFilterService;
|
|
24
23
|
}
|
|
25
24
|
canActivate(context) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const whitelist = this.ipFilterService.whitelist;
|
|
29
|
-
const blacklist = this.ipFilterService.blacklist;
|
|
30
|
-
let approved = false;
|
|
31
|
-
if (whitelist.length > 0) {
|
|
32
|
-
approved = whitelist.some((item) => {
|
|
33
|
-
return new RegExp(item).test(ipAddress);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
if (blacklist.length > 0) {
|
|
37
|
-
approved = !blacklist.some((item) => {
|
|
38
|
-
return new RegExp(item).test(ipAddress);
|
|
39
|
-
});
|
|
25
|
+
if (context.getType() !== 'http') {
|
|
26
|
+
return true;
|
|
40
27
|
}
|
|
28
|
+
const ipAddress = context
|
|
29
|
+
.switchToHttp()
|
|
30
|
+
.getRequest().ip;
|
|
31
|
+
const approved = this.ipFilterService.isAllowed(ipAddress);
|
|
41
32
|
if (!approved && this.ipFilterService.useDenyException) {
|
|
42
|
-
throw new ipfilter_deny_exception_1.IpFilterDenyException({
|
|
43
|
-
clientIp: ipAddress,
|
|
44
|
-
whitelist: whitelist,
|
|
45
|
-
blacklist: blacklist,
|
|
46
|
-
}, 403);
|
|
33
|
+
throw new ipfilter_deny_exception_1.IpFilterDenyException({ clientIp: ipAddress }, 403);
|
|
47
34
|
}
|
|
48
35
|
return approved;
|
|
49
36
|
}
|
|
50
37
|
};
|
|
51
|
-
IpFilterGuard =
|
|
38
|
+
exports.IpFilterGuard = IpFilterGuard;
|
|
39
|
+
exports.IpFilterGuard = IpFilterGuard = __decorate([
|
|
52
40
|
(0, common_1.Injectable)(),
|
|
53
41
|
__param(0, (0, common_1.Inject)(ipfilter_constants_1.IPFILTER_TOKEN)),
|
|
54
|
-
__metadata("design:paramtypes", [
|
|
42
|
+
__metadata("design:paramtypes", [Function])
|
|
55
43
|
], IpFilterGuard);
|
|
56
|
-
exports.IpFilterGuard = IpFilterGuard;
|
|
57
|
-
//# sourceMappingURL=ipfilter.guard.js.map
|
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export declare type IpFilterModuleOptions = {
|
|
1
|
+
export type IpFilterModuleOptions = {
|
|
3
2
|
whitelist?: string[];
|
|
4
3
|
blacklist?: string[];
|
|
5
4
|
useDenyException?: boolean;
|
|
6
5
|
};
|
|
7
|
-
export interface IpFilterDenyHandler {
|
|
8
|
-
handle(): boolean;
|
|
9
|
-
}
|
|
10
|
-
export interface IpFilterOptionsFactory {
|
|
11
|
-
createIpFilterModuleOptions(): Promise<IpFilterModuleOptions> | IpFilterModuleOptions;
|
|
12
|
-
}
|
|
13
|
-
export interface IpFilterModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
|
|
14
|
-
inject?: any[];
|
|
15
|
-
useClass?: Type<IpFilterOptionsFactory>;
|
|
16
|
-
useExisting?: Type<IpFilterOptionsFactory>;
|
|
17
|
-
useFactory?: (...args: any[]) => Promise<IpFilterModuleOptions> | IpFilterModuleOptions;
|
|
18
|
-
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IpFilterModuleOptions } from './ipfilter.interface';
|
|
2
|
+
export declare const ConfigurableModuleClass: import("@nestjs/common").ConfigurableModuleCls<IpFilterModuleOptions, "register", "create", {
|
|
3
|
+
global: boolean;
|
|
4
|
+
}>, MODULE_OPTIONS_TOKEN: string | symbol, OPTIONS_TYPE: IpFilterModuleOptions & Partial<{
|
|
5
|
+
global: boolean;
|
|
6
|
+
}>, ASYNC_OPTIONS_TYPE: import("@nestjs/common").ConfigurableModuleAsyncOptions<IpFilterModuleOptions, "create"> & Partial<{
|
|
7
|
+
global: boolean;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.ASYNC_OPTIONS_TYPE = exports.OPTIONS_TYPE = exports.MODULE_OPTIONS_TOKEN = exports.ConfigurableModuleClass = void 0;
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const core_1 = require("@nestjs/core");
|
|
7
|
+
const ipfilter_guard_1 = require("./ipfilter.guard");
|
|
8
|
+
_a = new common_1.ConfigurableModuleBuilder()
|
|
9
|
+
.setExtras({ global: true }, (definition, extras) => ({
|
|
10
|
+
...definition,
|
|
11
|
+
global: true,
|
|
12
|
+
providers: extras.global !== false
|
|
13
|
+
? [
|
|
14
|
+
...(definition.providers ?? []),
|
|
15
|
+
{ provide: core_1.APP_GUARD, useClass: ipfilter_guard_1.IpFilterGuard },
|
|
16
|
+
]
|
|
17
|
+
: definition.providers,
|
|
18
|
+
}))
|
|
19
|
+
.build(), exports.ConfigurableModuleClass = _a.ConfigurableModuleClass, exports.MODULE_OPTIONS_TOKEN = _a.MODULE_OPTIONS_TOKEN, exports.OPTIONS_TYPE = _a.OPTIONS_TYPE, exports.ASYNC_OPTIONS_TYPE = _a.ASYNC_OPTIONS_TYPE;
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare class IpFilter {
|
|
4
|
-
static forRoot(options: IpFilterModuleOptions): DynamicModule;
|
|
5
|
-
static forRootAsync(options: IpFilterModuleAsyncOptions): DynamicModule;
|
|
1
|
+
import { ConfigurableModuleClass } from './ipfilter.module-definition';
|
|
2
|
+
export declare class IpFilter extends ConfigurableModuleClass {
|
|
6
3
|
}
|
package/dist/ipfilter.module.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
2
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
9
|
exports.IpFilter = void 0;
|
|
4
10
|
const common_1 = require("@nestjs/common");
|
|
5
|
-
const
|
|
6
|
-
(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
static forRootAsync(options) {
|
|
15
|
-
return {
|
|
16
|
-
module: IpFilter,
|
|
17
|
-
imports: [ipfilter_core_module_1.IpFilterCoreModule.forRootAsync(options)],
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
}
|
|
11
|
+
const ipfilter_constants_1 = require("./ipfilter.constants");
|
|
12
|
+
const ipfilter_module_definition_1 = require("./ipfilter.module-definition");
|
|
13
|
+
const ipfilter_service_1 = require("./ipfilter.service");
|
|
14
|
+
const ipFilterServiceProvider = {
|
|
15
|
+
provide: ipfilter_constants_1.IPFILTER_TOKEN,
|
|
16
|
+
useClass: ipfilter_service_1.IpFilterService,
|
|
17
|
+
};
|
|
18
|
+
let IpFilter = class IpFilter extends ipfilter_module_definition_1.ConfigurableModuleClass {
|
|
19
|
+
};
|
|
21
20
|
exports.IpFilter = IpFilter;
|
|
22
|
-
|
|
21
|
+
exports.IpFilter = IpFilter = __decorate([
|
|
22
|
+
(0, common_1.Module)({
|
|
23
|
+
providers: [ipFilterServiceProvider],
|
|
24
|
+
exports: [ipFilterServiceProvider],
|
|
25
|
+
})
|
|
26
|
+
], IpFilter);
|
|
@@ -2,11 +2,14 @@ import { IpFilterModuleOptions } from './ipfilter.interface';
|
|
|
2
2
|
export declare class IpFilterService {
|
|
3
3
|
readonly options: IpFilterModuleOptions;
|
|
4
4
|
useDenyException: boolean;
|
|
5
|
-
private _whitelist
|
|
6
|
-
private _blacklist
|
|
5
|
+
private _whitelist?;
|
|
6
|
+
private _blacklist?;
|
|
7
|
+
private whitelistRules?;
|
|
8
|
+
private blacklistRules?;
|
|
7
9
|
constructor(options: IpFilterModuleOptions);
|
|
8
|
-
get whitelist(): string[];
|
|
10
|
+
get whitelist(): string[] | undefined;
|
|
9
11
|
set whitelist(whitelist: string[]);
|
|
10
|
-
get blacklist(): string[];
|
|
12
|
+
get blacklist(): string[] | undefined;
|
|
11
13
|
set blacklist(blacklist: string[]);
|
|
14
|
+
isAllowed(ip: string | undefined): boolean;
|
|
12
15
|
}
|