diff --git a/apps/server/src/modules/authentication/controllers/api-test/login.api.spec.ts b/apps/server/src/modules/authentication/controllers/api-test/login.api.spec.ts index 253d692055d..7da3c21eab9 100644 --- a/apps/server/src/modules/authentication/controllers/api-test/login.api.spec.ts +++ b/apps/server/src/modules/authentication/controllers/api-test/login.api.spec.ts @@ -1,16 +1,17 @@ import { EntityManager } from '@mikro-orm/core'; +import { SSOErrorCode } from '@modules/oauth/loggable'; +import { OauthTokenResponse } from '@modules/oauth/service/dto'; +import { ServerTestModule } from '@modules/server/server.module'; import { HttpStatus, INestApplication } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { Account, RoleName, SchoolEntity, SystemEntity, User } from '@shared/domain'; import { accountFactory, roleFactory, schoolFactory, systemFactory, userFactory } from '@shared/testing'; -import { SSOErrorCode } from '@modules/oauth/loggable'; -import { OauthTokenResponse } from '@modules/oauth/service/dto'; -import { ServerTestModule } from '@modules/server/server.module'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import crypto, { KeyPairKeyObjectResult } from 'crypto'; import jwt from 'jsonwebtoken'; import request, { Response } from 'supertest'; +import { ICurrentUser } from '../../interface'; import { LdapAuthorizationBodyParams, LocalAuthorizationBodyParams, OauthLoginResponse } from '../dto'; const ldapAccountUserName = 'ldapAccountUserName'; @@ -145,41 +146,38 @@ describe('Login Controller (api)', () => { }); describe('loginLdap', () => { - let account: Account; - let user: User; - let school: SchoolEntity; - let system: SystemEntity; - - beforeAll(async () => { - const schoolExternalId = 'mockSchoolExternalId'; - system = systemFactory.withLdapConfig().buildWithId({}); - school = schoolFactory.buildWithId({ systems: [system], externalId: schoolExternalId }); - const studentRoles = roleFactory.build({ name: RoleName.STUDENT, permissions: [] }); + describe('when user login succeeds', () => { + const setup = async () => { + const schoolExternalId = 'mockSchoolExternalId'; + const system: SystemEntity = systemFactory.withLdapConfig().buildWithId({}); + const school: SchoolEntity = schoolFactory.buildWithId({ systems: [system], externalId: schoolExternalId }); + const studentRoles = roleFactory.build({ name: RoleName.STUDENT, permissions: [] }); - user = userFactory.buildWithId({ school, roles: [studentRoles], ldapDn: mockUserLdapDN }); + const user: User = userFactory.buildWithId({ school, roles: [studentRoles], ldapDn: mockUserLdapDN }); - account = accountFactory.buildWithId({ - userId: user.id, - username: `${schoolExternalId}/${ldapAccountUserName}`.toLowerCase(), - systemId: system.id, - }); + const account: Account = accountFactory.buildWithId({ + userId: user.id, + username: `${schoolExternalId}/${ldapAccountUserName}`.toLowerCase(), + systemId: system.id, + }); - em.persist(system); - em.persist(school); - em.persist(studentRoles); - em.persist(user); - em.persist(account); - await em.flush(); - }); + await em.persistAndFlush([system, school, studentRoles, user, account]); - describe('when user login succeeds', () => { - it('should return jwt', async () => { const params: LdapAuthorizationBodyParams = { username: ldapAccountUserName, password: defaultPassword, schoolId: school.id, systemId: system.id, }; + + return { + params, + }; + }; + + it('should return jwt', async () => { + const { params } = await setup(); + const response = await request(app.getHttpServer()).post(`${basePath}/ldap`).send(params); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access @@ -199,14 +197,99 @@ describe('Login Controller (api)', () => { }); describe('when user login fails', () => { - it('should return error response', async () => { + const setup = async () => { + const schoolExternalId = 'mockSchoolExternalId'; + const system: SystemEntity = systemFactory.withLdapConfig().buildWithId({}); + const school: SchoolEntity = schoolFactory.buildWithId({ systems: [system], externalId: schoolExternalId }); + const studentRoles = roleFactory.build({ name: RoleName.STUDENT, permissions: [] }); + + const user: User = userFactory.buildWithId({ school, roles: [studentRoles], ldapDn: mockUserLdapDN }); + + const account: Account = accountFactory.buildWithId({ + userId: user.id, + username: `${schoolExternalId}/${ldapAccountUserName}`.toLowerCase(), + systemId: system.id, + }); + + await em.persistAndFlush([system, school, studentRoles, user, account]); + const params: LdapAuthorizationBodyParams = { username: 'nonExistentUser', password: 'wrongPassword', schoolId: school.id, systemId: system.id, }; - await request(app.getHttpServer()).post(`${basePath}/ldap`).send(params).expect(401); + + return { + params, + }; + }; + + it('should return error response', async () => { + const { params } = await setup(); + + const response = await request(app.getHttpServer()).post(`${basePath}/ldap`).send(params); + + expect(response.status).toEqual(HttpStatus.UNAUTHORIZED); + }); + }); + + describe('when logging in as a user of the Central LDAP of Brandenburg', () => { + const setup = async () => { + const officialSchoolNumber = '01234'; + const system: SystemEntity = systemFactory.withLdapConfig().buildWithId({}); + const school: SchoolEntity = schoolFactory.buildWithId({ + systems: [system], + externalId: officialSchoolNumber, + officialSchoolNumber, + }); + const studentRole = roleFactory.build({ name: RoleName.STUDENT, permissions: [] }); + + const user: User = userFactory.buildWithId({ school, roles: [studentRole], ldapDn: mockUserLdapDN }); + + const account: Account = accountFactory.buildWithId({ + userId: user.id, + username: `${officialSchoolNumber}/${ldapAccountUserName}`.toLowerCase(), + systemId: system.id, + }); + + await em.persistAndFlush([system, school, studentRole, user, account]); + + const params: LdapAuthorizationBodyParams = { + username: ldapAccountUserName, + password: defaultPassword, + schoolId: school.id, + systemId: system.id, + }; + + return { + params, + user, + account, + school, + system, + studentRole, + }; + }; + + it('should return a jwt', async () => { + const { params, user, account, school, system, studentRole } = await setup(); + + const response = await request(app.getHttpServer()).post(`${basePath}/ldap`).send(params); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + expect(response.body.accessToken).toBeDefined(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument + const decodedToken = jwt.decode(response.body.accessToken); + expect(decodedToken).toMatchObject({ + userId: user.id, + systemId: system.id, + roles: [studentRole.id], + schoolId: school.id, + accountId: account.id, + isExternalUser: false, + }); + expect(decodedToken).not.toHaveProperty('externalIdToken'); }); }); });