2024-03-26 05:24:17 +03:00
|
|
|
import { TestingModule } from '@nestjs/testing';
|
|
|
|
import { PrismaClient } from '@prisma/client';
|
|
|
|
import ava, { TestFn } from 'ava';
|
|
|
|
|
|
|
|
import { CurrentUser } from '../../src/core/auth';
|
2024-09-03 12:03:39 +03:00
|
|
|
import { AuthService } from '../../src/core/auth/service';
|
2024-03-26 05:24:17 +03:00
|
|
|
import { FeatureModule } from '../../src/core/features';
|
2024-04-12 09:45:18 +03:00
|
|
|
import { QuotaModule } from '../../src/core/quota';
|
2024-03-26 05:24:17 +03:00
|
|
|
import { UserModule, UserService } from '../../src/core/user';
|
2024-09-03 12:03:39 +03:00
|
|
|
import { createTestingModule, initTestingDB } from '../utils';
|
2024-03-26 05:24:17 +03:00
|
|
|
|
|
|
|
const test = ava as TestFn<{
|
|
|
|
auth: AuthService;
|
|
|
|
user: UserService;
|
|
|
|
u1: CurrentUser;
|
|
|
|
db: PrismaClient;
|
|
|
|
m: TestingModule;
|
|
|
|
}>;
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
test.before(async t => {
|
2024-03-26 05:24:17 +03:00
|
|
|
const m = await createTestingModule({
|
2024-04-12 09:45:18 +03:00
|
|
|
imports: [QuotaModule, FeatureModule, UserModule],
|
2024-03-26 05:24:17 +03:00
|
|
|
providers: [AuthService],
|
|
|
|
});
|
|
|
|
|
|
|
|
t.context.auth = m.get(AuthService);
|
|
|
|
t.context.user = m.get(UserService);
|
|
|
|
t.context.db = m.get(PrismaClient);
|
|
|
|
t.context.m = m;
|
|
|
|
});
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
test.beforeEach(async t => {
|
|
|
|
await initTestingDB(t.context.db);
|
|
|
|
t.context.u1 = await t.context.auth.signUp('u1@affine.pro', '1');
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
test.after.always(async t => {
|
|
|
|
await t.context.m.close();
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
test('should be able to sign in by password', async t => {
|
2024-03-26 05:24:17 +03:00
|
|
|
const { auth } = t.context;
|
|
|
|
|
|
|
|
const signedInUser = await auth.signIn('u1@affine.pro', '1');
|
|
|
|
|
|
|
|
t.is(signedInUser.email, 'u1@affine.pro');
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should throw if user not found', async t => {
|
|
|
|
const { auth } = t.context;
|
|
|
|
|
|
|
|
await t.throwsAsync(() => auth.signIn('u2@affine.pro', '1'), {
|
2024-06-17 06:30:58 +03:00
|
|
|
message: 'Wrong user email or password.',
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should throw if password not set', async t => {
|
|
|
|
const { user, auth } = t.context;
|
|
|
|
|
|
|
|
await user.createUser({
|
|
|
|
email: 'u2@affine.pro',
|
|
|
|
name: 'u2',
|
|
|
|
});
|
|
|
|
|
|
|
|
await t.throwsAsync(() => auth.signIn('u2@affine.pro', '1'), {
|
2024-06-17 06:30:58 +03:00
|
|
|
message:
|
|
|
|
'You are trying to sign in by a different method than you signed up with.',
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should throw if password not match', async t => {
|
|
|
|
const { auth } = t.context;
|
|
|
|
|
|
|
|
await t.throwsAsync(() => auth.signIn('u1@affine.pro', '2'), {
|
2024-06-17 06:30:58 +03:00
|
|
|
message: 'Wrong user email or password.',
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should be able to change password', async t => {
|
|
|
|
const { auth, u1 } = t.context;
|
|
|
|
|
|
|
|
let signedInU1 = await auth.signIn('u1@affine.pro', '1');
|
|
|
|
t.is(signedInU1.email, u1.email);
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
await auth.changePassword(u1.id, 'hello world affine');
|
2024-03-26 05:24:17 +03:00
|
|
|
|
|
|
|
await t.throwsAsync(
|
|
|
|
() => auth.signIn('u1@affine.pro', '1' /* old password */),
|
|
|
|
{
|
2024-06-17 06:30:58 +03:00
|
|
|
message: 'Wrong user email or password.',
|
2024-03-26 05:24:17 +03:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
signedInU1 = await auth.signIn('u1@affine.pro', 'hello world affine');
|
2024-03-26 05:24:17 +03:00
|
|
|
t.is(signedInU1.email, u1.email);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should be able to change email', async t => {
|
|
|
|
const { auth, u1 } = t.context;
|
|
|
|
|
|
|
|
let signedInU1 = await auth.signIn('u1@affine.pro', '1');
|
|
|
|
t.is(signedInU1.email, u1.email);
|
|
|
|
|
|
|
|
await auth.changeEmail(u1.id, 'u2@affine.pro');
|
|
|
|
|
|
|
|
await t.throwsAsync(() => auth.signIn('u1@affine.pro' /* old email */, '1'), {
|
2024-06-17 06:30:58 +03:00
|
|
|
message: 'Wrong user email or password.',
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
signedInU1 = await auth.signIn('u2@affine.pro', '1');
|
|
|
|
t.is(signedInU1.email, 'u2@affine.pro');
|
|
|
|
});
|
|
|
|
|
|
|
|
// Tests for Session
|
|
|
|
test('should be able to create user session', async t => {
|
|
|
|
const { auth, u1 } = t.context;
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
const session = await auth.createUserSession(u1.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
|
|
|
t.is(session.userId, u1.id);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should be able to get user from session', async t => {
|
|
|
|
const { auth, u1 } = t.context;
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
const session = await auth.createUserSession(u1.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-08-08 11:30:55 +03:00
|
|
|
const userSession = await auth.getUserSession(session.sessionId);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-08-08 11:30:55 +03:00
|
|
|
t.not(userSession, null);
|
|
|
|
t.is(userSession!.user.id, u1.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
test('should be able to sign out session', async t => {
|
|
|
|
const { auth, u1 } = t.context;
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
const session = await auth.createUserSession(u1.id);
|
|
|
|
await auth.signOut(session.sessionId);
|
|
|
|
const userSession = await auth.getUserSession(session.sessionId);
|
|
|
|
|
|
|
|
t.is(userSession, null);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should not return expired session', async t => {
|
|
|
|
const { auth, u1, db } = t.context;
|
|
|
|
|
|
|
|
const session = await auth.createUserSession(u1.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
await db.userSession.update({
|
|
|
|
where: { id: session.id },
|
|
|
|
data: {
|
|
|
|
expiresAt: new Date(Date.now() - 1000),
|
|
|
|
},
|
|
|
|
});
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
const userSession = await auth.getUserSession(session.sessionId);
|
|
|
|
t.is(userSession, null);
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
// Tests for Multi-Accounts Session
|
|
|
|
test('should be able to sign in different user in a same session', async t => {
|
|
|
|
const { auth, u1 } = t.context;
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
const u2 = await auth.signUp('u2@affine.pro', '1');
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
const session = await auth.createSession();
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
await auth.createUserSession(u1.id, session.id);
|
|
|
|
|
|
|
|
let userList = await auth.getUserList(session.id);
|
|
|
|
t.is(userList.length, 1);
|
|
|
|
t.is(userList[0]!.id, u1.id);
|
|
|
|
|
|
|
|
await auth.createUserSession(u2.id, session.id);
|
|
|
|
|
|
|
|
userList = await auth.getUserList(session.id);
|
|
|
|
|
|
|
|
t.is(userList.length, 2);
|
|
|
|
|
|
|
|
const [signedU1, signedU2] = userList;
|
2024-03-26 05:24:17 +03:00
|
|
|
|
|
|
|
t.not(signedU1, null);
|
|
|
|
t.not(signedU2, null);
|
|
|
|
t.is(signedU1!.id, u1.id);
|
|
|
|
t.is(signedU2!.id, u2.id);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should be able to signout multi accounts session', async t => {
|
|
|
|
const { auth, u1 } = t.context;
|
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
const u2 = await auth.signUp('u2@affine.pro', '1');
|
|
|
|
|
|
|
|
const session = await auth.createSession();
|
|
|
|
|
|
|
|
await auth.createUserSession(u1.id, session.id);
|
|
|
|
await auth.createUserSession(u2.id, session.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
await auth.signOut(session.id, u1.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
let list = await auth.getUserList(session.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
t.is(list.length, 1);
|
|
|
|
t.is(list[0]!.id, u2.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-20 09:37:11 +03:00
|
|
|
const u2Session = await auth.getUserSession(session.id, u1.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-20 09:37:11 +03:00
|
|
|
t.is(u2Session?.session.sessionId, session.id);
|
|
|
|
t.is(u2Session?.user.id, u2.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
await auth.signOut(session.id, u2.id);
|
|
|
|
list = await auth.getUserList(session.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-03 12:03:39 +03:00
|
|
|
t.is(list.length, 0);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-20 09:37:11 +03:00
|
|
|
const nullSession = await auth.getUserSession(session.id, u2.id);
|
2024-03-26 05:24:17 +03:00
|
|
|
|
2024-09-20 09:37:11 +03:00
|
|
|
t.is(nullSession, null);
|
2024-03-26 05:24:17 +03:00
|
|
|
});
|