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:
@@ -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>,
|
||||
}
|
||||
`;
|
||||
|
||||
54
integration-tests/api/__tests__/admin/auth.js
Normal file
54
integration-tests/api/__tests__/admin/auth.js
Normal file
@@ -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>,
|
||||
}
|
||||
`;
|
||||
64
integration-tests/api/__tests__/store/auth.js
Normal file
64
integration-tests/api/__tests__/store/auth.js
Normal file
@@ -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[]
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, select: false })
|
||||
password_hash: string
|
||||
|
||||
@Column({ nullable: true })
|
||||
|
||||
@@ -26,7 +26,7 @@ export class User {
|
||||
@Column({ nullable: true })
|
||||
last_name: string
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, select: false })
|
||||
password_hash: string
|
||||
|
||||
@Column({ nullable: true })
|
||||
|
||||
@@ -76,12 +76,17 @@ class AuthService extends BaseService {
|
||||
*/
|
||||
async authenticate(email, password) {
|
||||
try {
|
||||
const user = await this.userService_.retrieveByEmail(email)
|
||||
const userPasswordHash = await this.userService_.retrieveByEmail(email, {
|
||||
select: ["password_hash"],
|
||||
})
|
||||
|
||||
const passwordsMatch = await this.comparePassword_(
|
||||
password,
|
||||
user.password_hash
|
||||
userPasswordHash.password_hash
|
||||
)
|
||||
|
||||
if (passwordsMatch) {
|
||||
const user = await this.userService_.retrieveByEmail(email)
|
||||
return {
|
||||
success: true,
|
||||
user,
|
||||
@@ -113,8 +118,13 @@ class AuthService extends BaseService {
|
||||
*/
|
||||
async authenticateCustomer(email, password) {
|
||||
try {
|
||||
const customer = await this.customerService_.retrieveByEmail(email)
|
||||
if (!customer.password_hash) {
|
||||
const customerPasswordHash = await this.customerService_.retrieveByEmail(
|
||||
email,
|
||||
{
|
||||
select: ["password_hash"],
|
||||
}
|
||||
)
|
||||
if (!customerPasswordHash.password_hash) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Invalid email or password",
|
||||
@@ -123,9 +133,11 @@ class AuthService extends BaseService {
|
||||
|
||||
const passwordsMatch = await this.comparePassword_(
|
||||
password,
|
||||
customer.password_hash
|
||||
customerPasswordHash.password_hash
|
||||
)
|
||||
|
||||
if (passwordsMatch) {
|
||||
const customer = await this.customerService_.retrieveByEmail(email)
|
||||
return {
|
||||
success: true,
|
||||
customer,
|
||||
|
||||
@@ -48,7 +48,18 @@ class UserService extends BaseService {
|
||||
* @return {string} the validated 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.
|
||||
* @return {Promise<User>} the user document.
|
||||
*/
|
||||
async retrieveByEmail(email, relations = []) {
|
||||
async retrieveByEmail(email, config = {}) {
|
||||
const userRepo = this.manager_.getCustomRepository(this.userRepository_)
|
||||
|
||||
const user = await userRepo.findOne({
|
||||
where: { email },
|
||||
relations,
|
||||
})
|
||||
const query = this.buildQuery_({ email: email.toLowerCase() }, config)
|
||||
const user = await userRepo.findOne(query)
|
||||
|
||||
if (!user) {
|
||||
throw new MedusaError(
|
||||
|
||||
Reference in New Issue
Block a user