Skip to content

Commit 7e93439

Browse files
committed
[Issue #189] Add CanReadAll() and CanWriteAll()
1 parent 12803fa commit 7e93439

3 files changed

Lines changed: 162 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## [3.2.0] Aug-19-2019
44

55
### Additions
6-
6+
- [Issue #189] Add CanReadAll() and CanWriteAll()
77

88
## [3.1.0] Aug-06-2019
99

src/bodyguard.ts

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
*/
131131

132132
/**
133-
* Bodyguard Decorators
133+
* # Bodyguard Decorators
134134
*/
135135
import 'reflect-metadata';
136136
import { BodyguardOwner, UserRole } from './enums';
@@ -142,6 +142,60 @@ const CanSearchSymbol = Symbol('CanSearch');
142142
const CanSearchRelationSymbol = Symbol('CanSearchRelation');
143143
const CanReadRelationSymbol = Symbol('CanReadRelationSymbol');
144144

145+
/**
146+
* ## Class Decorators
147+
*/
148+
149+
/**
150+
* Get if all members are readable
151+
* NOTE: This function only checks if the CanReadAll() decorator is present.
152+
* Individual fields may have fine-grain access rights, which this
153+
* function will ignore. Use getCanRead() instead for authorization.
154+
* @param target Object to test
155+
*/
156+
export function getCanReadAll(target: any) {
157+
return target.canReadAll;
158+
}
159+
160+
/**
161+
* Get if all members are writable
162+
* NOTE: This function only checks if the CanWriteAll() decorator is present.
163+
* Individual fields may have fine-grain access rights, which this
164+
* function will ignore. Use getCanWrite() instead for authorization.
165+
* @param target Object to test
166+
*/
167+
export function getCanWriteAll(target: any) {
168+
return target.canWriteAll;
169+
}
170+
171+
/**
172+
* All class members are readable
173+
* @param who Who can read the fields. Default is anyone
174+
*/
175+
export function CanReadAll(
176+
who: BodyguardOwner | UserRole = BodyguardOwner.Anyone
177+
) {
178+
return (constructor) => {
179+
constructor.prototype.canReadAll = who;
180+
};
181+
}
182+
183+
/**
184+
* All class members are readable
185+
* @param who Who can read the fields. Default is anyone
186+
*/
187+
export function CanWriteAll(
188+
who: BodyguardOwner | UserRole = BodyguardOwner.Anyone
189+
) {
190+
return (constructor) => {
191+
constructor.prototype.canWriteAll = who;
192+
};
193+
}
194+
195+
/**
196+
* ## Member Decorators
197+
*/
198+
145199
/**
146200
* Check if the key is a bodyguard key
147201
* @param target Object to test
@@ -157,7 +211,10 @@ export function isBodyguardKey(target: any, propertyKey: string): boolean {
157211
* @param propertyKey Key to check
158212
*/
159213
export function getCanRead(target: any, propertyKey: string): string {
160-
return Reflect.getMetadata(CanReadSymbol, target, propertyKey);
214+
return (
215+
Reflect.getMetadata(CanReadSymbol, target, propertyKey) ||
216+
getCanReadAll(target)
217+
);
161218
}
162219

163220
/**
@@ -166,7 +223,10 @@ export function getCanRead(target: any, propertyKey: string): string {
166223
* @param propertyKey Key to check
167224
*/
168225
export function getCanWrite(target: any, propertyKey: string): string {
169-
return Reflect.getMetadata(CanWriteSymbol, target, propertyKey);
226+
return (
227+
Reflect.getMetadata(CanWriteSymbol, target, propertyKey) ||
228+
getCanWriteAll(target)
229+
);
170230
}
171231

172232
/**

test/spec/api/bodyguard/bodyguard.spec.ts

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ import {
1414
CanRead,
1515
CanWrite,
1616
CanSearch,
17-
CanSearchRelation
17+
CanSearchRelation,
18+
CanReadAll,
19+
CanWriteAll,
20+
getCanReadAll,
21+
getCanWriteAll
1822
} from '../../../../src/bodyguard';
1923
import { BaseModel } from '../../../../src/models';
20-
import { BodyguardOwner } from '../../../../src/enums';
24+
import { BodyguardOwner, UserRole } from '../../../../src/enums';
2125

2226
class ExampleModel extends BaseModel {
2327
@BodyguardKey() public bodyguardKey: number = undefined;
@@ -48,6 +52,76 @@ class ExampleModel extends BaseModel {
4852
}
4953
const example = new ExampleModel();
5054

55+
@CanReadAll()
56+
class ExampleReadableModel extends BaseModel {
57+
public testField1: string = undefined;
58+
}
59+
const exampleReadable = new ExampleReadableModel();
60+
61+
@CanWriteAll()
62+
class ExampleWritableModel extends BaseModel {
63+
public testField1: string = undefined;
64+
}
65+
const exampleWritable = new ExampleWritableModel();
66+
67+
@CanReadAll(UserRole.Admin)
68+
class AdminReadableModel extends BaseModel {
69+
public testField1: string = undefined;
70+
}
71+
const adminReadable = new AdminReadableModel();
72+
73+
@CanWriteAll(UserRole.Admin)
74+
class AdminWritableModel extends BaseModel {
75+
public testField1: string = undefined;
76+
}
77+
const adminWritable = new AdminWritableModel();
78+
79+
@CanReadAll()
80+
class MixedReadableModel extends BaseModel {
81+
public anyoneCanReadThisField: string = undefined;
82+
83+
@CanRead(UserRole.Admin)
84+
public butOnlyAdminCanReadThisOne: string = undefined;
85+
}
86+
const mixedReadable = new MixedReadableModel();
87+
88+
@CanWriteAll()
89+
class MixedWritableModel extends BaseModel {
90+
public anyoneCanWriteThisField: string = undefined;
91+
92+
@CanWrite(UserRole.Admin)
93+
public butOnlyAdminCanWriteThisOne: string = undefined;
94+
}
95+
const mixedWritable = new MixedWritableModel();
96+
97+
/**
98+
* getCanReadAll()
99+
* pointyapi/bodyguard
100+
*/
101+
describe('getCanReadAll()', () => {
102+
it('returns anyone if no parameter is set', () => {
103+
expect(getCanReadAll(exampleReadable)).toEqual(BodyguardOwner.Anyone);
104+
});
105+
106+
it('returns role if set as parameter', () => {
107+
expect(getCanReadAll(adminReadable)).toEqual(UserRole.Admin);
108+
});
109+
});
110+
111+
/**
112+
* getCanWriteAll()
113+
* pointyapi/bodyguard
114+
*/
115+
describe('getCanWriteAll()', () => {
116+
it('returns anyone if no parameter is set', () => {
117+
expect(getCanWriteAll(exampleWritable)).toEqual(BodyguardOwner.Anyone);
118+
});
119+
120+
it('returns role if set as parameter', () => {
121+
expect(getCanWriteAll(adminWritable)).toEqual(UserRole.Admin);
122+
});
123+
});
124+
51125
/**
52126
* isBodyguardKey()
53127
* pointyapi/bodyguard
@@ -91,8 +165,16 @@ describe('getCanRead()', () => {
91165
);
92166
});
93167

94-
it('returns undefined if the member is not readable', () => {
95-
expect(getCanRead(example, 'bodyguardKey')).toBe(undefined);
168+
it('returns anyone if the class has CanReadAll()', () => {
169+
expect(getCanRead(mixedReadable, 'anyoneCanReadThisField')).toEqual(
170+
BodyguardOwner.Anyone
171+
);
172+
});
173+
174+
it('returns UserRole.Admin if CanReadAll() has been overridden', () => {
175+
expect(getCanRead(mixedReadable, 'butOnlyAdminCanReadThisOne')).toEqual(
176+
UserRole.Admin
177+
);
96178
});
97179
});
98180

@@ -128,6 +210,18 @@ describe('getCanWrite()', () => {
128210
it('returns undefined if the member is not writeable', () => {
129211
expect(getCanWrite(example, 'bodyguardKey')).toBe(undefined);
130212
});
213+
214+
it('returns anyone if the class has CanWriteAll()', () => {
215+
expect(getCanWrite(mixedWritable, 'anyoneCanWriteThisField')).toEqual(
216+
BodyguardOwner.Anyone
217+
);
218+
});
219+
220+
it('returns UserRole.Admin if CanWriteAll() has been overridden', () => {
221+
expect(
222+
getCanWrite(mixedWritable, 'butOnlyAdminCanWriteThisOne')
223+
).toEqual(UserRole.Admin);
224+
});
131225
});
132226

133227
/**

0 commit comments

Comments
 (0)