mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Add a cache to the AgentGroupAccessChecker
This commit is contained in:
@@ -4,6 +4,7 @@ import { AgentGroupAccessChecker } from '../../../../src/authorization/access-ch
|
||||
import { BasicRepresentation } from '../../../../src/ldp/representation/BasicRepresentation';
|
||||
import type { Representation } from '../../../../src/ldp/representation/Representation';
|
||||
import type { RepresentationConverter } from '../../../../src/storage/conversion/RepresentationConverter';
|
||||
import type { ExpiringStorage } from '../../../../src/storage/keyvalue/ExpiringStorage';
|
||||
import { INTERNAL_QUADS } from '../../../../src/util/ContentTypes';
|
||||
import * as fetchUtil from '../../../../src/util/FetchUtil';
|
||||
import { ACL, VCARD } from '../../../../src/util/Vocabularies';
|
||||
@@ -18,6 +19,7 @@ describe('An AgentGroupAccessChecker', (): void => {
|
||||
let fetchMock: jest.SpyInstance;
|
||||
let representation: Representation;
|
||||
const converter: RepresentationConverter = {} as any;
|
||||
let cache: ExpiringStorage<string, Promise<Store>>;
|
||||
let checker: AgentGroupAccessChecker;
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
@@ -25,8 +27,11 @@ describe('An AgentGroupAccessChecker', (): void => {
|
||||
representation = new BasicRepresentation(groupQuads, INTERNAL_QUADS, false);
|
||||
fetchMock = jest.spyOn(fetchUtil, 'fetchDataset');
|
||||
fetchMock.mockResolvedValue(representation);
|
||||
fetchMock.mockClear();
|
||||
|
||||
checker = new AgentGroupAccessChecker(converter);
|
||||
cache = new Map() as any;
|
||||
|
||||
checker = new AgentGroupAccessChecker(converter, cache);
|
||||
});
|
||||
|
||||
it('can handle all requests.', async(): Promise<void> => {
|
||||
@@ -47,4 +52,11 @@ describe('An AgentGroupAccessChecker', (): void => {
|
||||
const input: AccessCheckerArgs = { acl, rule: namedNode('groupMatch'), credentials: {}};
|
||||
await expect(checker.handle(input)).resolves.toBe(false);
|
||||
});
|
||||
|
||||
it('caches fetched results.', async(): Promise<void> => {
|
||||
const input: AccessCheckerArgs = { acl, rule: namedNode('groupMatch'), credentials: { webId }};
|
||||
await expect(checker.handle(input)).resolves.toBe(true);
|
||||
await expect(checker.handle(input)).resolves.toBe(true);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,8 +15,7 @@ describe('An ExpiringAdapterFactory', (): void => {
|
||||
let storage: ExpiringStorage<string, unknown>;
|
||||
let adapter: ExpiringAdapter;
|
||||
let factory: ExpiringAdapterFactory;
|
||||
const expiresIn = 333;
|
||||
const expireDate = new Date(Date.now() + (expiresIn * 1000));
|
||||
const expiresIn = 333 * 1000;
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
payload = { data: 'data!' };
|
||||
@@ -35,7 +34,7 @@ describe('An ExpiringAdapterFactory', (): void => {
|
||||
it('can find payload by id.', async(): Promise<void> => {
|
||||
await expect(adapter.upsert(id, payload, 333)).resolves.toBeUndefined();
|
||||
expect(storage.set).toHaveBeenCalledTimes(1);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), payload, expireDate);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), payload, expiresIn);
|
||||
await expect(adapter.find(id)).resolves.toBe(payload);
|
||||
});
|
||||
|
||||
@@ -50,8 +49,8 @@ describe('An ExpiringAdapterFactory', (): void => {
|
||||
payload.userCode = userCode;
|
||||
await expect(adapter.upsert(id, payload, 333)).resolves.toBeUndefined();
|
||||
expect(storage.set).toHaveBeenCalledTimes(2);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), payload, expireDate);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), id, expireDate);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), payload, expiresIn);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), id, expiresIn);
|
||||
await expect(adapter.findByUserCode(userCode)).resolves.toBe(payload);
|
||||
});
|
||||
|
||||
@@ -60,8 +59,8 @@ describe('An ExpiringAdapterFactory', (): void => {
|
||||
payload.uid = uid;
|
||||
await expect(adapter.upsert(id, payload, 333)).resolves.toBeUndefined();
|
||||
expect(storage.set).toHaveBeenCalledTimes(2);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), payload, expireDate);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), id, expireDate);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), payload, expiresIn);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), id, expiresIn);
|
||||
await expect(adapter.findByUid(uid)).resolves.toBe(payload);
|
||||
});
|
||||
|
||||
@@ -69,8 +68,8 @@ describe('An ExpiringAdapterFactory', (): void => {
|
||||
payload.grantId = grantId;
|
||||
await expect(adapter.upsert(id, payload, 333)).resolves.toBeUndefined();
|
||||
expect(storage.set).toHaveBeenCalledTimes(2);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), payload, expireDate);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), [ expect.anything() ], expireDate);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), payload, expiresIn);
|
||||
expect(storage.set).toHaveBeenCalledWith(expect.anything(), [ expect.anything() ], expiresIn);
|
||||
await expect(adapter.find(id)).resolves.toBe(payload);
|
||||
await expect(adapter.revokeByGrantId(grantId)).resolves.toBeUndefined();
|
||||
expect(storage.delete).toHaveBeenCalledTimes(2);
|
||||
|
||||
@@ -17,7 +17,7 @@ describe('A WrappedExpiringStorage', (): void => {
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
const yesterday = new Date();
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
let source: KeyValueStorage<string, Internal>;
|
||||
let source: jest.Mocked<KeyValueStorage<string, Internal>>;
|
||||
let storage: WrappedExpiringStorage<string, string>;
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
@@ -42,12 +42,12 @@ describe('A WrappedExpiringStorage', (): void => {
|
||||
});
|
||||
|
||||
it('returns data if it has not expired.', async(): Promise<void> => {
|
||||
(source.get as jest.Mock).mockResolvedValueOnce(createExpires('data!', tomorrow));
|
||||
source.get.mockResolvedValueOnce(createExpires('data!', tomorrow));
|
||||
await expect(storage.get('key')).resolves.toEqual('data!');
|
||||
});
|
||||
|
||||
it('deletes expired data when trying to get it.', async(): Promise<void> => {
|
||||
(source.get as jest.Mock).mockResolvedValueOnce(createExpires('data!', yesterday));
|
||||
source.get.mockResolvedValueOnce(createExpires('data!', yesterday));
|
||||
await expect(storage.get('key')).resolves.toBeUndefined();
|
||||
expect(source.delete).toHaveBeenCalledTimes(1);
|
||||
expect(source.delete).toHaveBeenLastCalledWith('key');
|
||||
@@ -60,12 +60,12 @@ describe('A WrappedExpiringStorage', (): void => {
|
||||
});
|
||||
|
||||
it('true on `has` checks if there is non-expired data.', async(): Promise<void> => {
|
||||
(source.get as jest.Mock).mockResolvedValueOnce(createExpires('data!', tomorrow));
|
||||
source.get.mockResolvedValueOnce(createExpires('data!', tomorrow));
|
||||
await expect(storage.has('key')).resolves.toBe(true);
|
||||
});
|
||||
|
||||
it('deletes expired data when checking if it exists.', async(): Promise<void> => {
|
||||
(source.get as jest.Mock).mockResolvedValueOnce(createExpires('data!', yesterday));
|
||||
source.get.mockResolvedValueOnce(createExpires('data!', yesterday));
|
||||
await expect(storage.has('key')).resolves.toBe(false);
|
||||
expect(source.delete).toHaveBeenCalledTimes(1);
|
||||
expect(source.delete).toHaveBeenLastCalledWith('key');
|
||||
@@ -77,6 +77,12 @@ describe('A WrappedExpiringStorage', (): void => {
|
||||
expect(source.set).toHaveBeenLastCalledWith('key', createExpires('data!', tomorrow));
|
||||
});
|
||||
|
||||
it('can store data with an expiration duration.', async(): Promise<void> => {
|
||||
await storage.set('key', 'data!', tomorrow.getTime() - Date.now());
|
||||
expect(source.set).toHaveBeenCalledTimes(1);
|
||||
expect(source.set).toHaveBeenLastCalledWith('key', createExpires('data!', tomorrow));
|
||||
});
|
||||
|
||||
it('can store data without expiry date.', async(): Promise<void> => {
|
||||
await storage.set('key', 'data!');
|
||||
expect(source.set).toHaveBeenCalledTimes(1);
|
||||
@@ -99,7 +105,7 @@ describe('A WrappedExpiringStorage', (): void => {
|
||||
[ 'key2', createExpires('data2', yesterday) ],
|
||||
[ 'key3', createExpires('data3') ],
|
||||
];
|
||||
(source.entries as jest.Mock).mockImplementationOnce(function* (): any {
|
||||
source.entries.mockImplementationOnce(function* (): any {
|
||||
yield* data;
|
||||
});
|
||||
const it = storage.entries();
|
||||
@@ -123,7 +129,7 @@ describe('A WrappedExpiringStorage', (): void => {
|
||||
[ 'key2', createExpires('data2', yesterday) ],
|
||||
[ 'key3', createExpires('data3') ],
|
||||
];
|
||||
(source.entries as jest.Mock).mockImplementationOnce(function* (): any {
|
||||
source.entries.mockImplementationOnce(function* (): any {
|
||||
yield* data;
|
||||
});
|
||||
|
||||
@@ -150,7 +156,7 @@ describe('A WrappedExpiringStorage', (): void => {
|
||||
[ 'key2', createExpires('data2', yesterday) ],
|
||||
[ 'key3', createExpires('data3') ],
|
||||
];
|
||||
(source.entries as jest.Mock).mockImplementationOnce(function* (): any {
|
||||
source.entries.mockImplementationOnce(function* (): any {
|
||||
yield* data;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user