fix(medusa): hide password hash (#429)
* auth tests * customer auth tests * user auth test * store auth snapshot * auth snapshot * auth with deleted password hashes * manual field input for test scripts * fix circleci with double retrieve of user and customer * add email validation to user * fix: cleanup Co-authored-by: Sebastian Rindom <skrindom@gmail.com>
This commit is contained in:
1 parent
9b64828ec3
commit
cd4afd1576
8 files changed
+186
-13
No files matched your search
@@ -0,0 +1,16 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`/admin/discounts creates admin session correctly 1`] = `
|
||||||
|
Object {
|
||||||
|
"api_token": "test_token",
|
||||||
|
"created_at": Any<String>,
|
||||||
|
"deleted_at": null,
|
||||||
|
"email": "admin@medusa.js",
|
||||||
|
"first_name": null,
|
||||||
|
"id": "admin_user",
|
||||||
|
"last_name": null,
|
||||||
|
"metadata": null,
|
||||||
|
"updated_at": Any<String>,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
const path = require("path")
|
||||||
|
const { Region, DiscountRule, Discount } = require("@medusajs/medusa")
|
||||||
|
|
||||||
|
const setupServer = require("../../../helpers/setup-server")
|
||||||
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
|
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||||
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
|
const { exportAllDeclaration } = require("@babel/types")
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
describe("/admin/auth", () => {
|
||||||
|
let medusaProcess
|
||||||
|
let dbConnection
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
|
dbConnection = await initDb({ cwd })
|
||||||
|
medusaProcess = await setupServer({ cwd })
|
||||||
|
|
||||||
|
try {
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
} catch (e) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.shutdown()
|
||||||
|
medusaProcess.kill()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("creates admin session correctly", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/admin/auth", {
|
||||||
|
email: "admin@medusa.js",
|
||||||
|
password: "secret_password",
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.user.password_hash).toEqual(undefined)
|
||||||
|
expect(response.data.user).toMatchSnapshot({
|
||||||
|
email: "admin@medusa.js",
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`/admin/discounts creates store session correctly 1`] = `
|
||||||
|
Object {
|
||||||
|
"billing_address_id": null,
|
||||||
|
"created_at": Any<String>,
|
||||||
|
"deleted_at": null,
|
||||||
|
"email": "test@testesen.dk",
|
||||||
|
"first_name": "test",
|
||||||
|
"has_account": true,
|
||||||
|
"id": Any<String>,
|
||||||
|
"last_name": "testesen",
|
||||||
|
"metadata": null,
|
||||||
|
"orders": Array [],
|
||||||
|
"phone": "12345678",
|
||||||
|
"updated_at": Any<String>,
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
const path = require("path")
|
||||||
|
const { Region, DiscountRule, Discount } = require("@medusajs/medusa")
|
||||||
|
|
||||||
|
const setupServer = require("../../../helpers/setup-server")
|
||||||
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
|
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||||
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
|
const { exportAllDeclaration } = require("@babel/types")
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
describe("/admin/auth", () => {
|
||||||
|
let medusaProcess
|
||||||
|
let dbConnection
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
|
dbConnection = await initDb({ cwd })
|
||||||
|
medusaProcess = await setupServer({ cwd })
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.shutdown()
|
||||||
|
medusaProcess.kill()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("creates store session correctly", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
await api
|
||||||
|
.post("/store/customers", {
|
||||||
|
email: "test@testesen.dk",
|
||||||
|
password: "secret_password",
|
||||||
|
first_name: "test",
|
||||||
|
last_name: "testesen",
|
||||||
|
phone: "12345678",
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/store/auth", {
|
||||||
|
email: "test@testesen.dk",
|
||||||
|
password: "secret_password",
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.customer.password_hash).toEqual(undefined)
|
||||||
|
expect(response.data.customer).toMatchSnapshot({
|
||||||
|
id: expect.any(String),
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
first_name: "test",
|
||||||
|
last_name: "testesen",
|
||||||
|
phone: "12345678",
|
||||||
|
email: "test@testesen.dk",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -46,7 +46,7 @@ export class Customer {
|
|||||||
)
|
)
|
||||||
shipping_addresses: Address[]
|
shipping_addresses: Address[]
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true, select: false })
|
||||||
password_hash: string
|
password_hash: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export class User {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
last_name: string
|
last_name: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true, select: false })
|
||||||
password_hash: string
|
password_hash: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
|
|||||||
@@ -76,12 +76,17 @@ class AuthService extends BaseService {
|
|||||||
*/
|
*/
|
||||||
async authenticate(email, password) {
|
async authenticate(email, password) {
|
||||||
try {
|
try {
|
||||||
const user = await this.userService_.retrieveByEmail(email)
|
const userPasswordHash = await this.userService_.retrieveByEmail(email, {
|
||||||
|
select: ["password_hash"],
|
||||||
|
})
|
||||||
|
|
||||||
const passwordsMatch = await this.comparePassword_(
|
const passwordsMatch = await this.comparePassword_(
|
||||||
password,
|
password,
|
||||||
user.password_hash
|
userPasswordHash.password_hash
|
||||||
)
|
)
|
||||||
|
|
||||||
if (passwordsMatch) {
|
if (passwordsMatch) {
|
||||||
|
const user = await this.userService_.retrieveByEmail(email)
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
user,
|
user,
|
||||||
@@ -113,8 +118,13 @@ class AuthService extends BaseService {
|
|||||||
*/
|
*/
|
||||||
async authenticateCustomer(email, password) {
|
async authenticateCustomer(email, password) {
|
||||||
try {
|
try {
|
||||||
const customer = await this.customerService_.retrieveByEmail(email)
|
const customerPasswordHash = await this.customerService_.retrieveByEmail(
|
||||||
if (!customer.password_hash) {
|
email,
|
||||||
|
{
|
||||||
|
select: ["password_hash"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (!customerPasswordHash.password_hash) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: "Invalid email or password",
|
error: "Invalid email or password",
|
||||||
@@ -123,9 +133,11 @@ class AuthService extends BaseService {
|
|||||||
|
|
||||||
const passwordsMatch = await this.comparePassword_(
|
const passwordsMatch = await this.comparePassword_(
|
||||||
password,
|
password,
|
||||||
customer.password_hash
|
customerPasswordHash.password_hash
|
||||||
)
|
)
|
||||||
|
|
||||||
if (passwordsMatch) {
|
if (passwordsMatch) {
|
||||||
|
const customer = await this.customerService_.retrieveByEmail(email)
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
customer,
|
customer,
|
||||||
|
|||||||
@@ -48,7 +48,18 @@ class UserService extends BaseService {
|
|||||||
* @return {string} the validated email
|
* @return {string} the validated email
|
||||||
*/
|
*/
|
||||||
validateEmail_(email) {
|
validateEmail_(email) {
|
||||||
return email
|
const schema = Validator.string()
|
||||||
|
.email()
|
||||||
|
.required()
|
||||||
|
const { value, error } = schema.validate(email)
|
||||||
|
if (error) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
"The email is not valid"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,13 +125,11 @@ class UserService extends BaseService {
|
|||||||
* @param {string} email - the email of the user to get.
|
* @param {string} email - the email of the user to get.
|
||||||
* @return {Promise<User>} the user document.
|
* @return {Promise<User>} the user document.
|
||||||
*/
|
*/
|
||||||
async retrieveByEmail(email, relations = []) {
|
async retrieveByEmail(email, config = {}) {
|
||||||
const userRepo = this.manager_.getCustomRepository(this.userRepository_)
|
const userRepo = this.manager_.getCustomRepository(this.userRepository_)
|
||||||
|
|
||||||
const user = await userRepo.findOne({
|
const query = this.buildQuery_({ email: email.toLowerCase() }, config)
|
||||||
where: { email },
|
const user = await userRepo.findOne(query)
|
||||||
relations,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
|
|||||||
Reference in new issue
Block a user