mirror of
https://github.com/OutlineFoundation/outline-server.git
synced 2026-08-04 14:37:34 +00:00
Expand test scenarios for key generation to createAccessKey.
This commit is contained in:
parent
f9f70c2045
commit
d18bfd0107
1 changed files with 205 additions and 232 deletions
|
|
@ -306,251 +306,224 @@ describe('ShadowsocksManagerService', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('createNewAccessKey', () => {
|
||||
it('generates a unique ID', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
describe('creating new access key', () => {
|
||||
let repo: ServerAccessKeyRepository;
|
||||
let service: ShadowsocksManagerService;
|
||||
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.id).toEqual('0');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createNewAccessKey({params: {}}, res, done);
|
||||
beforeEach(() => {
|
||||
repo = getAccessKeyRepository();
|
||||
service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
});
|
||||
it('rejects requests with ID parameter set', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createNewAccessKey({params: {id: 'foobar'}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
describe('handling the access key identifier', () => {
|
||||
describe("with 'createNewAccessKey'", () => {
|
||||
it('generates a unique ID', (done) => {
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.id).toEqual('0');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createNewAccessKey({params: {}}, res, done);
|
||||
});
|
||||
it('rejects requests with ID parameter set', (done) => {
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createNewAccessKey({params: {id: 'foobar'}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
it('verify default method', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
// Verify that response returns a key with the expected properties.
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(Object.keys(data).sort()).toEqual(EXPECTED_ACCESS_KEY_PROPERTIES);
|
||||
expect(data.method).toEqual('chacha20-ietf-poly1305');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createNewAccessKey({params: {}}, res, done);
|
||||
});
|
||||
it('non-default method gets set', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
// Verify that response returns a key with the expected properties.
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(Object.keys(data).sort()).toEqual(EXPECTED_ACCESS_KEY_PROPERTIES);
|
||||
expect(data.method).toEqual('aes-256-gcm');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createNewAccessKey({params: {method: 'aes-256-gcm'}}, res, done);
|
||||
});
|
||||
it('use default name is params is not defined', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.name).toEqual('');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createNewAccessKey({params: {}}, res, done);
|
||||
});
|
||||
it('rejects non-string name', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createNewAccessKey({params: {name: Number('9876')}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('defined name is equal to stored', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const ACCESSKEY_NAME = 'accesskeyname';
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.name).toEqual(ACCESSKEY_NAME);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createNewAccessKey({params: {name: ACCESSKEY_NAME}}, res, done);
|
||||
});
|
||||
it('limit can be undefined', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.limit).toBeUndefined();
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createNewAccessKey({params: {}}, res, done);
|
||||
});
|
||||
it('rejects non-numeric limits', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const ACCESSKEY_LIMIT = {bytes: '9876'};
|
||||
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createNewAccessKey({params: {limit: ACCESSKEY_LIMIT}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('defined limit is equal to stored', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const ACCESSKEY_LIMIT = {bytes: 9876};
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.dataLimit).toEqual(ACCESSKEY_LIMIT);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createNewAccessKey({params: {limit: ACCESSKEY_LIMIT}}, res, done);
|
||||
});
|
||||
it('method must be of type string', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createNewAccessKey({params: {method: Number('9876')}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('method must be valid', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createNewAccessKey({params: {method: 'abcdef'}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('Create returns a 500 when the repository throws an exception', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
spyOn(repo, 'createNewAccessKey').and.throwError('cannot write to disk');
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createNewAccessKey({params: {method: 'aes-192-gcm'}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(500);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
describe("with 'createAccessKey'", () => {
|
||||
it('rejects requests without ID parameter set', (done) => {
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createAccessKey({params: {}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('rejects non-string ID', (done) => {
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createAccessKey({params: {id: Number('9876')}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('creates key with provided ID', (done) => {
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.id).toEqual('myKeyId');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createAccessKey({params: {id: 'myKeyId'}}, res, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('generates a new password when no password is provided', async (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
const conditions = [
|
||||
{methodName: 'createNewAccessKey', accessKeyId: undefined},
|
||||
{methodName: 'createAccessKey', accessKeyId: 'myKeyId'},
|
||||
];
|
||||
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.password).toBeDefined();
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
await service.createNewAccessKey({params: {}}, res, done);
|
||||
});
|
||||
for (const {methodName, accessKeyId} of conditions) {
|
||||
describe(`with '${methodName}'`, () => {
|
||||
let serviceMethod: (req, res, next) => Promise<void>;
|
||||
|
||||
it('uses the provided password when one is provided', async (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
beforeEach(() => {
|
||||
serviceMethod = service[methodName].bind(service);
|
||||
});
|
||||
|
||||
const PASSWORD = '8iu8V8EeoFVpwQvQeS9wiD';
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.password).toEqual(PASSWORD);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
await service.createNewAccessKey({params: {password: PASSWORD}}, res, done);
|
||||
});
|
||||
it('verify default method', (done) => {
|
||||
// Verify that response returns a key with the expected properties.
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(Object.keys(data).sort()).toEqual(EXPECTED_ACCESS_KEY_PROPERTIES);
|
||||
expect(data.method).toEqual('chacha20-ietf-poly1305');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
serviceMethod({params: {id: accessKeyId}}, res, done);
|
||||
});
|
||||
it('non-default method gets set', (done) => {
|
||||
// Verify that response returns a key with the expected properties.
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(Object.keys(data).sort()).toEqual(EXPECTED_ACCESS_KEY_PROPERTIES);
|
||||
expect(data.method).toEqual('aes-256-gcm');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
serviceMethod({params: {id: accessKeyId, method: 'aes-256-gcm'}}, res, done);
|
||||
});
|
||||
it('use default name is params is not defined', (done) => {
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.name).toEqual('');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
serviceMethod({params: {id: accessKeyId}}, res, done);
|
||||
});
|
||||
it('rejects non-string name', (done) => {
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
serviceMethod({params: {id: accessKeyId, name: Number('9876')}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('defined name is equal to stored', (done) => {
|
||||
const ACCESSKEY_NAME = 'accesskeyname';
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.name).toEqual(ACCESSKEY_NAME);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
serviceMethod({params: {id: accessKeyId, name: ACCESSKEY_NAME}}, res, done);
|
||||
});
|
||||
it('limit can be undefined', (done) => {
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.limit).toBeUndefined();
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
serviceMethod({params: {id: accessKeyId}}, res, done);
|
||||
});
|
||||
it('rejects non-numeric limits', (done) => {
|
||||
const ACCESSKEY_LIMIT = {bytes: '9876'};
|
||||
|
||||
it('rejects a password that is not a string', async (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
const PASSWORD = Number.MAX_SAFE_INTEGER;
|
||||
const res = {send: SEND_NOTHING};
|
||||
await service.createNewAccessKey({params: {password: PASSWORD}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
serviceMethod({params: {id: accessKeyId, limit: ACCESSKEY_LIMIT}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('defined limit is equal to stored', (done) => {
|
||||
const ACCESSKEY_LIMIT = {bytes: 9876};
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.dataLimit).toEqual(ACCESSKEY_LIMIT);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
serviceMethod({params: {id: accessKeyId, limit: ACCESSKEY_LIMIT}}, res, done);
|
||||
});
|
||||
it('method must be of type string', (done) => {
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
serviceMethod({params: {id: accessKeyId, method: Number('9876')}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('method must be valid', (done) => {
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
serviceMethod({params: {id: accessKeyId, method: 'abcdef'}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('Create returns a 500 when the repository throws an exception', (done) => {
|
||||
spyOn(repo, 'createNewAccessKey').and.throwError('cannot write to disk');
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
serviceMethod({params: {id: accessKeyId, method: 'aes-192-gcm'}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(500);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('generates a new password when no password is provided', async (done) => {
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.password).toBeDefined();
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
await serviceMethod({params: {id: accessKeyId}}, res, done);
|
||||
});
|
||||
|
||||
it('uses the provided password when one is provided', async (done) => {
|
||||
const PASSWORD = '8iu8V8EeoFVpwQvQeS9wiD';
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.password).toEqual(PASSWORD);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
await serviceMethod({params: {id: accessKeyId, password: PASSWORD}}, res, done);
|
||||
});
|
||||
|
||||
it('rejects a password that is not a string', async (done) => {
|
||||
const PASSWORD = Number.MAX_SAFE_INTEGER;
|
||||
const res = {send: SEND_NOTHING};
|
||||
await serviceMethod({params: {id: accessKeyId, password: PASSWORD}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('createAccessKey', () => {
|
||||
it('rejects requests without ID parameter set', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createAccessKey({params: {}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('rejects non-string ID', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {send: (_httpCode, _data) => {}};
|
||||
service.createAccessKey({params: {id: Number('9876')}}, res, (error) => {
|
||||
expect(error.statusCode).toEqual(400);
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('creates key with provided ID', (done) => {
|
||||
const repo = getAccessKeyRepository();
|
||||
const service = new ShadowsocksManagerServiceBuilder().accessKeys(repo).build();
|
||||
|
||||
const res = {
|
||||
send: (httpCode, data) => {
|
||||
expect(httpCode).toEqual(201);
|
||||
expect(data.id).toEqual('myKeyId');
|
||||
responseProcessed = true; // required for afterEach to pass.
|
||||
},
|
||||
};
|
||||
service.createAccessKey({params: {id: 'myKeyId'}}, res, done);
|
||||
});
|
||||
}
|
||||
});
|
||||
describe('setPortForNewAccessKeys', () => {
|
||||
it('changes ports for new access keys', async (done) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue