@@ -34,8 +34,11 @@ const {
3434const { checkIfPageCountResets } = require ( '../../api/main_endpoints/util/userHelpers.js' ) ;
3535const { mockDayMonthAndYear, revertClock } = require ( '../util/mocks/Date.js' ) ;
3636const { MEMBERSHIP_STATE } = require ( '../../api/util/constants' ) ;
37- chai . should ( ) ;
3837
38+ const AuditLogActions = require ( '../../api/main_endpoints/util/auditLogActions.js' ) ;
39+ const AuditLog = require ( '../../api/main_endpoints/models/AuditLog.js' ) ;
40+
41+ chai . should ( ) ;
3942chai . use ( chaiHttp ) ;
4043
4144// Our parent block
@@ -141,39 +144,6 @@ describe('Auth', () => {
141144 expect ( verificationArgs ) . to . eql ( [ user . firstName + ' ' + user . lastName , user . email ] ) ;
142145 expect ( result ) . to . have . status ( OK ) ;
143146 } ) ;
144- } ) ;
145-
146- describe ( '/POST login' , ( ) => {
147- it ( 'Should return statusCode 400 if an email and/or ' +
148- 'password is not provided' , async ( ) => {
149- const user = { } ;
150- const result = await test . sendPostRequest (
151- '/api/Auth/login' , user ) ;
152- expect ( result ) . to . have . status ( BAD_REQUEST ) ;
153- } ) ;
154-
155- it ( 'Should return statusCode 401 if an email/pass combo ' +
156- 'does not match a record in the DB' , async ( ) => {
157- const user = {
158- email : 'nota@b.c' ,
159- password : 'Passwd'
160- } ;
161- const result = await test . sendPostRequest (
162- '/api/Auth/login' , user ) ;
163- expect ( result ) . to . have . status ( UNAUTHORIZED ) ;
164- } ) ;
165-
166- it ( 'Should return statusCode 401 if the email exists ' +
167- 'but password is incorrect' , async ( ) => {
168- const user = {
169- email : 'a@b.c' ,
170- password : 'password'
171- } ;
172- const result = await test . sendPostRequest (
173- '/api/Auth/login' , user ) ;
174- expect ( result ) . to . have . status ( UNAUTHORIZED ) ;
175- } ) ;
176-
177147 it ( 'Should allow login with correct credentials after registering a user' , async ( ) => {
178148 const user = {
179149 email : 'logintest@gmail.com' ,
@@ -228,6 +198,114 @@ describe('Auth', () => {
228198 } ) ;
229199 } ) ;
230200
201+ describe ( '/POST login' , ( ) => {
202+ it ( 'Should return statusCode 400 if an email and/or ' +
203+ 'password is not provided' , async ( ) => {
204+ const user = { } ;
205+ const result = await test . sendPostRequest (
206+ '/api/Auth/login' , user ) ;
207+ expect ( result ) . to . have . status ( BAD_REQUEST ) ;
208+ } ) ;
209+
210+ it ( 'Should return statusCode 401 if an email/pass combo ' +
211+ 'does not match a record in the DB' , async ( ) => {
212+ const user = {
213+ email : 'nota@b.c' ,
214+ password : 'Passwd'
215+ } ;
216+ const result = await test . sendPostRequest (
217+ '/api/Auth/login' , user ) ;
218+ expect ( result ) . to . have . status ( UNAUTHORIZED ) ;
219+ } ) ;
220+
221+ it ( 'Should return statusCode 401 if the email exists ' +
222+ 'but password is incorrect' , async ( ) => {
223+ const user = {
224+ email : 'a@b.c' ,
225+ password : 'password'
226+ } ;
227+ const result = await test . sendPostRequest (
228+ '/api/Auth/login' , user ) ;
229+ expect ( result ) . to . have . status ( UNAUTHORIZED ) ;
230+ } ) ;
231+
232+ describe ( 'with an existing user' , ( ) => {
233+ let user ;
234+
235+ before ( async ( ) => {
236+ user = new User ( {
237+ _id : new mongoose . Types . ObjectId ( ) ,
238+ firstName : 'Test' ,
239+ lastName : 'User' ,
240+ email : 'logintest@gmail.com' ,
241+ password : 'Passw0rd' ,
242+ emailVerified : true ,
243+ accessLevel : MEMBERSHIP_STATE . MEMBER ,
244+ apiKey : null
245+ } ) ;
246+ await user . save ( ) ;
247+ } ) ;
248+
249+ after ( async ( ) => {
250+ await User . deleteOne ( { email : 'logintest@gmail.com' } ) ;
251+ } ) ;
252+
253+ beforeEach ( async ( ) => {
254+ await AuditLog . deleteMany ( { } ) ;
255+ } ) ;
256+
257+ afterEach ( async ( ) => {
258+ await AuditLog . deleteMany ( { } ) ;
259+ sinon . restore ( ) ;
260+ } ) ;
261+
262+ it ( 'Should create an audit log entry on successful login' , async ( ) => {
263+ const loginPayload = {
264+ email : 'logintest@gmail.com' ,
265+ password : 'Passw0rd' ,
266+ } ;
267+
268+ const res = await test . sendPostRequest ( '/api/Auth/login' , loginPayload ) ;
269+ expect ( res ) . to . have . status ( OK ) ;
270+ expect ( res . body ) . to . have . property ( 'token' ) ;
271+
272+ const auditEntry = await AuditLog . findOne ( {
273+ action : AuditLogActions . LOG_IN ,
274+ details : { email : loginPayload . email } ,
275+ } ) ;
276+
277+ expect ( auditEntry ) . to . exist ;
278+ expect ( auditEntry ) . to . have . property ( 'userId' ) ;
279+ expect ( auditEntry . details ) . to . have . property ( 'email' , loginPayload . email ) ;
280+ } ) ;
281+
282+ it ( 'Should return 200 even if audit logging fails' , async ( ) => {
283+ const auditStub = sinon . stub ( AuditLog , 'create' ) . rejects ( new Error ( 'Simulated audit log failure' ) ) ;
284+
285+ const loginPayload = {
286+ email : 'logintest@gmail.com' ,
287+ password : 'Passw0rd' ,
288+ } ;
289+
290+ try {
291+
292+ const res = await test . sendPostRequest ( '/api/Auth/login' , loginPayload ) ;
293+ expect ( res ) . to . have . status ( OK ) ;
294+ expect ( res . body ) . to . have . property ( 'token' ) ;
295+
296+ const auditEntry = await AuditLog . findOne ( {
297+ action : AuditLogActions . LOG_IN ,
298+ 'details.email' : loginPayload . email ,
299+ } ) ;
300+
301+ expect ( auditEntry ) . to . not . exist ;
302+ } finally {
303+ auditStub . restore ( ) ;
304+ }
305+ } ) ;
306+ } ) ;
307+ } ) ;
308+
231309 describe ( '/POST sendPasswordReset' , ( ) => {
232310 it ( 'Should return statusCode 401 if the email is invalid' , async ( ) => {
233311 const data = {
@@ -427,5 +505,4 @@ describe('Auth', () => {
427505 expect ( result ) . to . be . false ;
428506 } ) ;
429507 } ) ;
430-
431508} ) ;
0 commit comments