mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Add verification to AccountStore
This commit is contained in:
parent
6214e0c537
commit
9bb42ddf0d
@ -19,6 +19,14 @@ export interface AccountStore {
|
|||||||
*/
|
*/
|
||||||
create: (email: string, webId: string, password: string) => Promise<void>;
|
create: (email: string, webId: string, password: string) => Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the account creation. This can be used with, for example, e-mail verification.
|
||||||
|
* The account can only be used after it is verified.
|
||||||
|
* In case verification is not required, this should be called immediately after the `create` call.
|
||||||
|
* @param email - the account email
|
||||||
|
*/
|
||||||
|
verify: (email: string) => Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the password
|
* Changes the password
|
||||||
* @param email - the user's email
|
* @param email - the user's email
|
||||||
|
@ -11,6 +11,7 @@ export interface AccountPayload {
|
|||||||
webId: string;
|
webId: string;
|
||||||
email: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
|
verified: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,6 +73,7 @@ export class BaseAccountStore implements AccountStore {
|
|||||||
public async authenticate(email: string, password: string): Promise<string> {
|
public async authenticate(email: string, password: string): Promise<string> {
|
||||||
const { account } = await this.getAccountPayload(email);
|
const { account } = await this.getAccountPayload(email);
|
||||||
assert(account, 'No account by that email');
|
assert(account, 'No account by that email');
|
||||||
|
assert(account.verified, 'Account still needs to be verified');
|
||||||
assert(await compare(password, account.password), 'Incorrect password');
|
assert(await compare(password, account.password), 'Incorrect password');
|
||||||
return account.webId;
|
return account.webId;
|
||||||
}
|
}
|
||||||
@ -83,10 +85,18 @@ export class BaseAccountStore implements AccountStore {
|
|||||||
email,
|
email,
|
||||||
webId,
|
webId,
|
||||||
password: await hash(password, this.saltRounds),
|
password: await hash(password, this.saltRounds),
|
||||||
|
verified: false,
|
||||||
};
|
};
|
||||||
await this.storage.set(key, payload);
|
await this.storage.set(key, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async verify(email: string): Promise<void> {
|
||||||
|
const { key, account } = await this.getAccountPayload(email);
|
||||||
|
assert(account, 'Account does not exist');
|
||||||
|
account.verified = true;
|
||||||
|
await this.storage.set(key, account);
|
||||||
|
}
|
||||||
|
|
||||||
public async changePassword(email: string, password: string): Promise<void> {
|
public async changePassword(email: string, password: string): Promise<void> {
|
||||||
const { key, account } = await this.getAccountPayload(email);
|
const { key, account } = await this.getAccountPayload(email);
|
||||||
assert(account, 'Account does not exist');
|
assert(account, 'Account does not exist');
|
||||||
|
@ -37,13 +37,24 @@ describe('A BaseAccountStore', (): void => {
|
|||||||
await expect(store.authenticate(email, password)).rejects.toThrow('No account by that email');
|
await expect(store.authenticate(email, password)).rejects.toThrow('No account by that email');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('errors when authenticating an unverified account.', async(): Promise<void> => {
|
||||||
|
await expect(store.create(email, webId, password)).resolves.toBeUndefined();
|
||||||
|
await expect(store.authenticate(email, 'wrongPassword')).rejects.toThrow('Account still needs to be verified');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('errors when verifying a non-existent account.', async(): Promise<void> => {
|
||||||
|
await expect(store.verify(email)).rejects.toThrow('Account does not exist');
|
||||||
|
});
|
||||||
|
|
||||||
it('errors when authenticating with the wrong password.', async(): Promise<void> => {
|
it('errors when authenticating with the wrong password.', async(): Promise<void> => {
|
||||||
await expect(store.create(email, webId, password)).resolves.toBeUndefined();
|
await expect(store.create(email, webId, password)).resolves.toBeUndefined();
|
||||||
|
await expect(store.verify(email)).resolves.toBeUndefined();
|
||||||
await expect(store.authenticate(email, 'wrongPassword')).rejects.toThrow('Incorrect password');
|
await expect(store.authenticate(email, 'wrongPassword')).rejects.toThrow('Incorrect password');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can authenticate.', async(): Promise<void> => {
|
it('can authenticate.', async(): Promise<void> => {
|
||||||
await expect(store.create(email, webId, password)).resolves.toBeUndefined();
|
await expect(store.create(email, webId, password)).resolves.toBeUndefined();
|
||||||
|
await expect(store.verify(email)).resolves.toBeUndefined();
|
||||||
await expect(store.authenticate(email, password)).resolves.toBe(webId);
|
await expect(store.authenticate(email, password)).resolves.toBe(webId);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -54,6 +65,7 @@ describe('A BaseAccountStore', (): void => {
|
|||||||
it('can change the password.', async(): Promise<void> => {
|
it('can change the password.', async(): Promise<void> => {
|
||||||
const newPassword = 'newPassword!';
|
const newPassword = 'newPassword!';
|
||||||
await expect(store.create(email, webId, password)).resolves.toBeUndefined();
|
await expect(store.create(email, webId, password)).resolves.toBeUndefined();
|
||||||
|
await expect(store.verify(email)).resolves.toBeUndefined();
|
||||||
await expect(store.changePassword(email, newPassword)).resolves.toBeUndefined();
|
await expect(store.changePassword(email, newPassword)).resolves.toBeUndefined();
|
||||||
await expect(store.authenticate(email, newPassword)).resolves.toBe(webId);
|
await expect(store.authenticate(email, newPassword)).resolves.toBe(webId);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user