Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion controllers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ HTTP Response:
}
```

### Apply for a temporary password (Forgot Password)

POST "/reset-password"

Request Body:
```
{
"username": string,
"phone": string,
}
```

HTTP Response:
```
{
"temporaryPassword": string
}
```

## Users

### Getting responders of a user
Expand Down Expand Up @@ -126,7 +145,7 @@ HTTP Response:
}
```

## Updating location of a user
### Updating location of a user

PUT "/users/:id/location"

Expand All @@ -141,6 +160,16 @@ Request Body:
}
```

### Update attributes of a user

PUT "/users/:id/password"

Request Body:
```
{
password: string
}
```

### Getting Responder Count

Expand Down
133 changes: 92 additions & 41 deletions controllers/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ let jwt = require("jsonwebtoken");
var bcrypt = require("bcrypt");
const randToken = require("rand-token");

const { customValidationResult } = require("../utils/error_handling");
const { customValidationResult } = require("../utils/validations");
var handle = require("../utils/error_handling");

var UserModel = require("../models/user").model;
Expand All @@ -12,6 +12,8 @@ var RefreshTokenService = require("../services/refresh-token.service");
var AvailbilityService = require("../services/availability.service");
var OnlineService = require("../services/online.service");
var UserService = require("../services/user.service");
var ResetPasswordService = require("../services/reset-password.service");
var TextMessagingService = require("../services/text-messaging.service");

const TOKEN_DURATION = "15m";

Expand All @@ -31,45 +33,60 @@ async function login(req, res) {
handle.notFound(res, err.message);
}

let temporaryPassword = await ResetPasswordService.getTemporaryPassword(
username
);

try {
if (bcrypt.compareSync(password, result.password)) {
let token = jwt.sign({ id: result._id }, process.env.SECRET, {
expiresIn: TOKEN_DURATION
});

let refreshToken = randToken.uid(128)
RefreshTokenService.deleteRefreshToken(result._id)
RefreshTokenService.addRefreshToken(result._id, refreshToken)

try {
await OnlineService.setOnline(result._id.toString());
var onlineStatus = await OnlineService.checkOnlineStatus(result._id.toString());
if (onlineStatus && result.naloxoneAvailability) {
AvailbilityService.setAvailable(result._id.toString());
} else {
AvailbilityService.setUnavailable(result._id.toString());
}
} catch (err) {
console.log("redis error: ", err.message);
}
let passwordCompare = bcrypt.compareSync(password, result.password);
let temporaryPasswordCompare = bcrypt.compareSync(
password,
temporaryPassword
);

if (!passwordCompare && !temporaryPasswordCompare) {
return handle.unauthorized(res, "Username or password incorrect");
}

try {
await metricService.updateUserLoginTime(username);
} catch (err) {
handle.notFound(res, 'Cannot find user in metrics database');
let token = jwt.sign({ id: result._id }, process.env.SECRET, {
expiresIn: TOKEN_DURATION,
});

let refreshToken = randToken.uid(128);
RefreshTokenService.deleteRefreshToken(result._id);
RefreshTokenService.addRefreshToken(result._id, refreshToken);

try {
await OnlineService.setOnline(result._id.toString());
var onlineStatus = await OnlineService.checkOnlineStatus(
result._id.toString()
);
if (onlineStatus && result.naloxoneAvailability) {
AvailbilityService.setAvailable(result._id.toString());
} else {
AvailbilityService.setUnavailable(result._id.toString());
}
} catch (err) {
console.log("redis error: ", err.message);
}

res.status(200).json({
success: true,
message: "Authentication successful!",
token: token,
refreshToken: refreshToken,
id: result._id,
naloxoneAvailability: result.naloxoneAvailability
});
} else {
handle.unauthorized(res, "Username or password incorrect");
try {
await metricService.updateUserLoginTime(username);
} catch (err) {
handle.notFound(res, "Cannot find user in metrics database");
}

await ResetPasswordService.removeTemporaryPassword(username);

res.status(200).json({
success: true,
message: "Authentication successful!",
token: token,
refreshToken: refreshToken,
id: result._id,
naloxoneAvailability: result.naloxoneAvailability,
usedTemporaryPassword: temporaryPasswordCompare,
});
} catch (err) {
handle.internalServerError(res, "Bcrypt compareSync failed");
}
Expand Down Expand Up @@ -99,7 +116,7 @@ async function signup(req, res) {
email: email,
password: bcrypt.hashSync(pass, 10),
phone: phone,
naloxoneAvailability: false
naloxoneAvailability: false,
});

try {
Expand All @@ -115,8 +132,11 @@ async function signup(req, res) {
try {
await metricService.addNewUserToMetrics(result.id, username);
} catch (err) {
console.log(err)
handle.internalServerError(res, "Cannot add new user to metrics database")
console.log(err);
handle.internalServerError(
res,
"Cannot add new user to metrics database"
);
}

res.status(200).json(result);
Expand All @@ -132,19 +152,50 @@ async function useRefreshToken(req, res) {
let refreshToken = req.body.refreshToken;
if (await RefreshTokenService.checkRefreshToken(userId, refreshToken)) {
let token = jwt.sign({ id: userId }, process.env.SECRET, {
expiresIn: TOKEN_DURATION
expiresIn: TOKEN_DURATION,
});

// Consider generating new refresh token and returning it so that refresh token will also expire
res.status(200).json({ token: token });
} else {
handle.unauthorized(res, "Refresh token and user id do not match")
handle.unauthorized(res, "Refresh token and user id do not match");
}
}
}

async function resetPassword(req, res) {
const errors = customValidationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
} else {
let username = req.body.username;
let phone = req.body.phone;

let user = null;
try {
user = await UserService.findUserByUsername(username);
} catch (err) {
return handle.notFound(res, err.message);
}

if (phone != user.phone)
return handle.notFound(res, "Username and phone number do not match");

const temporaryPassword = await ResetPasswordService.applyTemporaryPassword(
user.username
);

// Send text message with temporary password to the specified phone number
TextMessagingService.sendTemporaryPassword(user.phone, temporaryPassword);

res.status(200).json({
temporaryPassword: temporaryPassword,
});
}
}
module.exports = {
login,
signup,
useRefreshToken,
}
resetPassword,
};
Loading