Moved to chinook + added .env
This commit is contained in:
113
chinook/srv/user-service.js
Normal file
113
chinook/srv/user-service.js
Normal file
@@ -0,0 +1,113 @@
|
||||
const cds = require("@sap/cds");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const bcrypt = require("bcryptjs");
|
||||
|
||||
const { ACCESS_TOKEN_SECRET, REFRESH_TOKEN_SECRET } = process.env;
|
||||
|
||||
const ACCESS_TOKEN_EXP_IN = "10m";
|
||||
const REFRESH_TOKEN_EXPIRES_IN = "20m";
|
||||
|
||||
const comparePasswords = async (password, hashedPassword) => {
|
||||
return new Promise((resolve, reject) =>
|
||||
bcrypt.compare(password, hashedPassword, (err, res) => {
|
||||
if (err || res === false) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const createTokens = (email, ID, roles) => {
|
||||
const accessToken = jwt.sign({ email, ID, roles }, ACCESS_TOKEN_SECRET, {
|
||||
expiresIn: ACCESS_TOKEN_EXP_IN,
|
||||
});
|
||||
const refreshToken = jwt.sign({ email, ID, roles }, REFRESH_TOKEN_SECRET, {
|
||||
expiresIn: REFRESH_TOKEN_EXPIRES_IN,
|
||||
});
|
||||
return [accessToken, refreshToken];
|
||||
};
|
||||
|
||||
module.exports = async function () {
|
||||
const db = await cds.connect.to("db");
|
||||
const { Employees, Customers } = db.entities;
|
||||
|
||||
async function getUser(email) {
|
||||
let userFromDb = await db.run(SELECT.one(Employees).where({ email }));
|
||||
let roles = ["employee"];
|
||||
if (!userFromDb) {
|
||||
userFromDb = await db.run(SELECT.one(Customers).where({ email }));
|
||||
roles = ["customer"];
|
||||
}
|
||||
return Object.assign({}, userFromDb, { roles });
|
||||
}
|
||||
|
||||
/**
|
||||
* User can only update and read his data
|
||||
*/
|
||||
this.before("UPDATE", "*", async (req) => {
|
||||
req.query = req.query.where({ ID: req.user.attr.ID });
|
||||
});
|
||||
this.before("READ", "*", async (req) => {
|
||||
req.query = req.query.where({ ID: req.user.attr.ID });
|
||||
});
|
||||
|
||||
this.on("login", async (req) => {
|
||||
const { email, password } = req.data;
|
||||
|
||||
const userFromDb = await getUser(email);
|
||||
if (!userFromDb) {
|
||||
req.reject(401);
|
||||
}
|
||||
|
||||
try {
|
||||
await comparePasswords(password, userFromDb.password);
|
||||
} catch (error) {
|
||||
req.reject(401);
|
||||
}
|
||||
|
||||
const [accessToken, refreshToken] = createTokens(
|
||||
userFromDb.email,
|
||||
userFromDb.ID,
|
||||
userFromDb.roles
|
||||
);
|
||||
|
||||
return {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
ID: userFromDb.ID,
|
||||
email: userFromDb.email,
|
||||
roles: userFromDb.roles,
|
||||
};
|
||||
});
|
||||
|
||||
this.on("refreshTokens", async (req) => {
|
||||
let decodedUser;
|
||||
try {
|
||||
const { refreshToken } = req.data;
|
||||
decodedUser = jwt.verify(refreshToken, REFRESH_TOKEN_SECRET);
|
||||
} catch (error) {
|
||||
req.reject(401);
|
||||
}
|
||||
|
||||
const userFromDb = await getUser(decodedUser.email);
|
||||
if (!userFromDb) {
|
||||
req.reject(401);
|
||||
}
|
||||
|
||||
const [accessToken, refreshToken] = createTokens(
|
||||
userFromDb.email,
|
||||
userFromDb.ID,
|
||||
userFromDb.roles
|
||||
);
|
||||
|
||||
return {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
ID: userFromDb.ID,
|
||||
email: userFromDb.email,
|
||||
roles: userFromDb.roles,
|
||||
};
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user