Hiding properties from JSON
See original GitHub issueThe problem
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column({ unique: true })
email: string;
@Column()
password: string;
@Column({ nullable: true })
accessToken?: string;
// tslint:disable-next-line:variable-name
private _client?: ThridPartyClient;
get thridPartyClient(): ThridPartyClient | undefined {
if (!this._client && this.accessToken) {
this._client = createThridPartyClient({accessToken: this.accessToken});
}
return this._client;
}
}
Currently, when we return an instance of the above entity (or anything that contains it) from an API endpoint the entire model gets serialized into something like:
{
"id": 1,
"name": "Orkhan",
"email": "myemail@me.com",
"password": "password-hash",
"accessToken": "blah213",
"_client": {...}
}
The last 3 fields must not be inside json. We can of course create a new object and return it but there should be a better solution in general. Does foalts have something to offer in this case?
Workaround
We can override toJSON
method in the User
entity class which is used by JSON.stringify
method:
function hidden(hidden: string[]) {
return function (this: object) {
const result = {};
for (const x in this) {
if (!hidden.includes(x)) {
result[x] = this[x];
}
}
return result;
};
}
@Entity()
export class User extends BaseEntity {
...
toJSON = hidden(['password', 'accessToken', '_client']);
}
Where we call hidden
method with the array of field names to hide and it will return a method that returns a new copy of object by not copying specified fields. This works for arrays and nested objects too.
Proposed solution
Again I put forward laravel’s approach as an example. FoalTS can use a custom replacer to serialize json response, where we can hook in and conditionally hide fields based on some sort of a reserved field on the provided entity (like foal: { hidden: ['password'] }
). This would work for arrays and nested objects too.
Issue Analytics
- State:
- Created 4 years ago
- Comments:14 (8 by maintainers)
You can set a TypeORM configuration on the column like this:
But if it is not a TypeORM column you’d have to manually remove it from the response I guess.
This can be solved at ORM level with single table inheritance. Split
User
in two logic entities but both will live in the same table:Now you can query
SecuredUser
for security tasks (authentication, authorization) andUser
for the rest of the logic, manipulate, and serialize to JSON without worrying about to disclose security properties by mistake.