Post request mysql with foreign keys? - javascript

I´m trying to create a post request that is suppose to check if the person posting the request is the person logged in and then posts the response. I have a table for the customer and a table for address, I want to make a post request to the address so that when the logged in user inserts an address their id will be stored as a foreign key in the address table. My address table looks like this:
module.exports = (sequelize, DataTypes) => {
const Address = sequelize.define("Address", {
address: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
city: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
postcode: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
country: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
}
});
return Address;
};
and my customer table is like this:
module.exports = (sequelize, DataTypes) => {
const Customers = sequelize.define("Customers", {
firstName: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
email: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
password: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
isAdmin: {
type: DataTypes.BOOLEAN,
default: '0',
}
});
Customers.associate = (models) => {
Customers.hasMany(models.Address, {
onDelete: "cascade",
});
Customers.hasMany(models.Orderline, {
onDelete: "cascade",
});
};
return Customers;
};
my post request is like this:
addressRouter.post(
'/:id', isAuth,
expressAsyncHandler( async (req, res) => {
const {id, address, postcode} = req.params;
const customer = await Customers.findOne({where: {id: id}})
const custAddress = await Address.findOne({where: {address,postcode}})
const shippingAddress = {
address: req.body.address,
city: req.body.city,
postcode: req.body.postcode,
country: req.body.country,
}
if (!customer) {
res.status(401).send({
message: "Customer Not Found",
});
}else if(custAddress){
res.status(401).send({
message: "Address already exist",
});
}else{
Address.create(shippingAddress);
res.send({
id: shippingAddress.id,
address: shippingAddress.address,
city: shippingAddress.city,
postcode: shippingAddress.postcode,
country: shippingAddress.country,
});
}
})
please do not mind the isAuth function because that works I was able to update info for user with it. my Api for the post request looks like this:
export const shipping = async({address, city, postcode, country}) => {
try{
const {token} = getCustomerInfo();
const response = await axios({
url: `${apiUrl}/api/${id}`,
method: 'POST',
headers: {
'Content-Type' : 'application/json',
Authorization: `Bearer ${token}`,
},
data:{
address,
city,
postcode,
country,
},
});
if(response.statusText !== 'OK'){
throw new Error(response.data.message);
}
return response.data;
}catch(err){
console.log(err);
return {error: err.response.data.message || err.message};
}
};
Any help is really appreciated.

You need to define an association from 'Address' to Customer:
Address.associate = (models) => {
Address.belongsTo(models.Customer);
};
return Address
and of course indicate customerId in a newly created address:
Address.create(shippingAddress);
res.send({
id: shippingAddress.id,
address: shippingAddress.address,
city: shippingAddress.city,
postcode: shippingAddress.postcode,
country: shippingAddress.country,
customerId: customer.id
});

Related

Create a model with hash password in Sequelize?

I'm trying to create a model in Sequelize with a hash password using bcrypt, and run "sequelize db:migrate" but I can't. I get this error whenever I try to run it. All I need to is have "password" with the hash already done. I don't know where I'm going wrong or what I'm missing. can anybody help me?
== 001-user: migrating =======
ERROR: s.replace is not a function
I'm using: Sequelize: 6.16.2. Database: Postgres. Node: 15. Bcrypt: 5.0.1
Here is my User model:
class User extends Model {
/**
* #param {import("../index")} models
*/
static associate (models) {
User.belongsTo(models.UserRole, { as: "user_role", foreignKey: "id_user_role" });
}
}
/**
* #param {import("sequelize").Sequelize} sequelize Connection with the database
*/
function initUser (sequelize) {
User.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
user: DataTypes.STRING(30),
name: DataTypes.STRING(100),
email: DataTypes.STRING(100),
password: DataTypes.STRING(100),
id_user_role: {
type: DataTypes.INTEGER,
references: {
model: sequelize.models.UserRole,
key: "id"
}
},
deleted: DataTypes.BOOLEAN
},
{
sequelize,
timestamps: false,
modelName: "User",
tableName: "user",
underscored: true,
hooks: {
beforeCreate: async (user) => {
if (user.password) {
const salt = await bcrypt.genSaltSync(11, "a");
user.password = bcrypt.hashSync(user.password, salt);
}
},
beforeUpdate: async (user) => {
if (user.password) {
const salt = await bcrypt.genSaltSync(11, "a");
user.password = bcrypt.hashSync(user.password, salt);
}
}
}
});
return User;
}
module.exports = { initUser };
User migration:
module.exports = {
/**
* #param {import("sequelize").QueryInterface} queryInterface
* #param {import("sequelize").DataTypes} Sequelize
*/
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("user", {
id: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true
},
user: {
type: Sequelize.STRING(30),
allowNull: false
},
name: {
type: Sequelize.STRING(100),
allowNull: false
},
email: {
type: Sequelize.STRING(100),
allowNull: false
},
password: {
type: Sequelize.STRING(100),
allowNull: false
},
id_user_role: {
type: Sequelize.INTEGER,
allowNull: false,
references: { model: UserRole, key: "id" }
},
deleted: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
}
});
await queryInterface.bulkInsert("user", [
{
user: "admin", name: "test", email: "test#admin.com", password: "admin", id_user_role: 1
},
{
user: "comum", name: "test", email: "test#comum.com", password: "comum", id_user_role: 2
},
{
user: "regular", name: "test", email: "test#regular.com", password: "comum", id_user_role: 3
}
]);
}
};

Bcrypt Error: data and salt arguments required

I'm just learning about NodeJS and am I'm trying to create data using sequelize Postgres. but I've got some error
bcrypt UnhandledPromiseRejectionWarning: Error: data and salt arguments required.
Here is my code
model user.js
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of the Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
User.init({
full_name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: {
msg: 'Nama tidak boleh kosong'
}
}
},
email: {
type: DataTypes.STRING,
allowNull: false,
validate: {
isEmail: true,
notEmpty: {
msg: 'Email tidak boleh kosong'
},
unique: {
args: true,
msg: 'Email address already in use!'
}
}
},
username: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: {
msg: 'Username tidak boleh kosong'
}
}
},
password: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: {
msg: 'Password tidak boleh kosong'
}
}
},
profile_image_url: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: 'www.image.com',
validate: {
notEmpty: {
msg: 'Url tidak boleh kosong'
}
}
},
age: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
notEmpty: {
msg: 'Umur tidak boleh kosong'
}
}
},
phone_number: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: {
msg: 'No telp tidak boleh kosong'
}
}
}
}, {
sequelize,
modelName: 'User',
});
return User;
};
I've been looking for answers from several other sources, but I haven't found it yet. Here is my controller createUser.js.
const {
User
} = require('../../models/user');
const bcrypt = require('bcrypt');
module.exports = async (req, res) => {
const {
full_name,
email,
username,
password,
age,
phone_number
} = req.body;
const hash = await bcrypt.hash(password, 10);
await User.create({
full_name,
email,
username,
password: hash,
age,
phone_number
}).then(success => {
return res.status(201).json({
status: 'success',
message: 'Success register',
data: success
})
}).catch(error => {
return res.status(400).json({
status: 'error',
message: error.message
});
});
}

How to merge Included Model Attributes on Sequelize Query

Does anyone know how to perform a query in Sequelize where (no SQL pun intended) included model attributes are merged onto the parent model? The user model, user_profile model, and query are below. I'd like to return a single object with the following attributes: ['id', 'username', 'role', 'is_active', 'email', 'first_name', 'last_name']. Thanks!
export default function (sequelize, DataTypes) {
var User = sequelize.define(
'User',
{
username: { type: DataTypes.STRING, unique: true },
email: { type: DataTypes.STRING, unique: true },
password_hash: { type: DataTypes.STRING },
role: { type: DataTypes.STRING, defaultValue: 'user' },
is_active: { type: DataTypes.BOOLEAN, defaultValue: true }
},
{ timestamps: true, freezeTableName: true }
);
User.associate = function (models) {
models.User.hasOne(models.UserProfile, {
foreignKey: 'user_id'
});
};
return User;
}
'use strict';
export default function (sequelize, DataTypes) {
var UserProfile = sequelize.define(
'UserProfile',
{
first_name: DataTypes.STRING,
last_name: DataTypes.STRING
},
{ timestamps: true, freezeTableName: true }
);
UserProfile.associate = function () {
// associations can be defined here
};
return UserProfile;
}
async getUserByUsername(username) {
return await db.User.findOne({
attributes: [
'id',
'username',
'role',
'is_active',
'email',
['userProfile.first_name', 'first_name'],
['userProfile.last_name', 'last_name']
],
include: [{ model: db.UserProfile, as: 'userProfile', required: true }],
where: { username }
})
}
Both models need to defined in the same sequelize object.
const User = sequelize.define(
'User',
{
username: { type: DataTypes.STRING, unique: true },
email: { type: DataTypes.STRING, unique: true },
password_hash: { type: DataTypes.STRING },
role: { type: DataTypes.STRING, defaultValue: 'user' },
is_active: { type: DataTypes.BOOLEAN, defaultValue: true }
},
{ timestamps: true, freezeTableName: true }
);
const UserProfile = sequelize.define(
'UserProfile',
{
first_name: DataTypes.STRING,
last_name: DataTypes.STRING
},
{ timestamps: true, freezeTableName: true }
);
user.hasOne(user_profile, {foreignKey: 'user_id'})
Query data like:
sequelize.models.user.findAll({
include: [
{
model: sequelize.models.user_profile,
}
]
}).then((user) => {
console.log(user);
}).catch((err) => {
console.log(err);
});

Sequelize 1:N no association found

I have 2 models: User and Foto where each User can have N Fotos and each Foto is assciate with 1 User.
So what i need is to eager load the Foto(i pass a specific id to retrive the foto) and the user associated to that foto.
My User model
"use strict";
var sequelize = require('./index');
var bcrypt = require('bcrypt-nodejs');
var Foto = require('./Foto');
module.exports = function (sequelize, DataTypes) {
var User = sequelize.define("User", {
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isUnique: function (value, next) {
var self = this;
User.find({ where: { username: value } })
.then(function (user) {
// reject if a different user wants to use the same username
if (user && self.id !== user.id) {
return next('username already in use!');
}
return next();
})
.catch(function (err) {
return next(err);
});
}
}
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isUnique: function (value, next) {
var self = this;
User.find({ where: { email: value } })
.then(function (user) {
// reject if a different user wants to use the same email
if (user && self.id !== user.id) {
return next('Email already in use!');
}
return next();
})
.catch(function (err) {
return next(err);
});
}
}
},
typeOfUser: {
type: DataTypes.INTEGER,
allowNull:true,
defaultValue:null
},
country: {
type: DataTypes.STRING,
allowNull:true,
defaultValue:null
},
birthDate:{
type: DataTypes.DATEONLY,
allowNull:true,
defaultValue:null
},
reports: {
type: DataTypes.INTEGER,
defaultValue: 0
},
points: {
type: DataTypes.INTEGER,
defaultValue: 0
},
password: {
type: DataTypes.STRING,
allowNull:false
},
numberFotos: {
type: DataTypes.INTEGER,
defaultValue: 0
}
}, {
classMethods: {
generateHash: function (password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
},
associate: function(models){
User.hasMany(models.Foto,{foreignKey: "userId"});
}
},
instanceMethods: {
validPassword: function (password) {
return bcrypt.compareSync(password, this.password);
}
}
});
return User;
}
important part:
associate: function(models){
User.hasMany(models.Foto,{foreignKey: "userId"});
}
My Foto model:
"use strict";
var sequelize = require('./index');
var bcrypt = require('bcrypt-nodejs');
var User = require('./User');
module.exports = function (sequelize, DataTypes) {
var Foto = sequelize.define("Foto", {
reports: {
type: DataTypes.INTEGER,
defaultValue: 0
},
image: {
type: DataTypes.STRING,
allowNull: false
},
date: {
type: DataTypes.DATE,
allowNull: true
},
lat: {
type: DataTypes.STRING,
allowNull: true
},
lon: {
type: DataTypes.STRING,
allowNull: true
},
altitude: {
type: DataTypes.STRING,
allowNull: true
},
userId: {
type: DataTypes.INTEGER,
allowNull: false
},
plantId: {
type: DataTypes.INTEGER,
allowNull: true
},
},
{
associate: function (models) {
Foto.belongsTo(models.User);
}
}
);
return Foto;
}
important part:
{
associate: function (models) {
Foto.belongsTo(models.User);
}
}
And in my controller i try to eager load like this:
allPictures: function (req, res) {
Foto.findAll({include: [{model: User, as: 'User'}]})
.then(function (fotos) {
res.send(fotos);
})
}

Graphql: Query returns null for all fields except ID

When I run the following Query:
{
viewer {
id
firstName
lastName
}
}
I get the following object which displays the incorrect query results:
{
"data": {
"viewer": {
"id": "VXNlcjo=",
"firstName": null,
"lastName": null
}
}
}
I have set up the following database.js:
import Sequelize from 'sequelize';
import bcrypt from 'bcrypt';
// Create a Sequelize instance
var connection = new Sequelize('dev', 'mary', 'password', {
host: 'localhost',
dialect: 'postgres',
pool: {
max: 5,
min: 0,
idle: 10000
}
});
// User model
var User = connection.define('user', {
// First name
firstName: {
type: Sequelize.STRING,
allowNull: false,
validate: {
is: {
args: /^[a-z]+$/i,
msg: 'First name is invalid'
}
}
},
// Last name
lastName: {
type: Sequelize.STRING,
allowNull: false,
validate: {
is: {
args: /^[a-z]+$/i,
msg: 'Last name is invalid'
}
}
},
// Username
username: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate: {
is: {
args: /^#?(\w){3,15}$/,
msg: 'Username can not exceed 15 characters or contain spaces.'
}
}
},
// Email
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true
}
},
// Password
password: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate: {
// Validate Password
}
}
}, {
// Use plural names in database.
freezeTableName: false,
// Timestamps
timestamps: true,
// hooks
hooks: {
afterValidate: user => {
user.password = bcrypt.hashSync(user.password, 8);
}
}
});
// Group model
var Group = connection.define('group', {
// Owner Id
ownerId: {
type: Sequelize.INTEGER,
allowNull: false
},
// Group name
name: {
type: Sequelize.STRING,
allowNull: false
},
// Domain
domain: {
type: Sequelize.STRING,
allowNull: false
},
// Topic
topic: {
type: Sequelize.STRING,
validate: {
len: {
args: [0, 150],
msg: 'Topic can not exceed 150 characters.'
}
}
},
// Access
private: {
type: Sequelize.BOOLEAN
},
// Password
password: {
type: Sequelize.STRING,
defaultValue: null,
validate: {
// Validate Password
}
}
}, {
freezeTableName: false,
// Timestamps
timestamps: true,
// hooks
hooks: {
afterValidate: user => {
if (user.password) {
user.password = bcrypt.hashSync(user.password, 8);
}
}
}
});
// Relationships
User.belongsToMany(Group, { through: 'UserGroup' });
Group.belongsToMany(User, { through: 'UserGroup' });
// Insert some data by calling sync
connection.sync({
force: true
}).then ( () => {
// First user dummy
User.create( {
firstName: 'Sam',
lastName: 'Smith',
username: 'samsmith',
email: 'samsith#some.com',
password: 'somepassword'
})
.then(user => {
user.createGroup({
ownerId: user.id,
name: 'Engineering',
topic: 'A group',
domain: user.email.split('#')[1],
private: true,
password: ''
});
});
// Second user dummy
User.create( {
firstName: 'Sam',
lastName: 'Joshua',
username: 'samjoshua',
email: 'samjoshua#gmail.com',
password: 'somepassword'
})
.then(user => {
user.createGroup({
ownerId: user.id,
name: 'Design',
topic: 'This is some group',
domain: user.email.split('#')[1],
private: false,
password: ''
});
});
})
.catch(error => {
console.log(error);
});
export default connection;
and the following schema.js file:
import {
GraphQLBoolean,
GraphQLFloat,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
} from 'graphql';
import {
connectionArgs,
connectionDefinitions,
connectionFromArray,
fromGlobalId,
globalIdField,
mutationWithClientMutationId,
nodeDefinitions,
} from 'graphql-relay';
import db from './database';
/**
* We get the node interface and field from the Relay library.
*
* The first method defines the way we resolve an ID to its object.
* The second defines the way we resolve an object to its GraphQL type.
*/
var {nodeInterface, nodeField} = nodeDefinitions(
(globalId) => {
var {type, id} = fromGlobalId(globalId);
if (type === 'User') {
return db.models.user.getUser(id);
} else if (type === 'Group') {
return db.models.group.getGroup(id);
} else {
return null;
}
},
(obj) => {
if (obj instanceof User) {
return userType;
} else if (obj instanceof Group) {
return groupType;
} else {
return null;
}
}
);
/**
* We define our own types here.
*/
var userType = new GraphQLObjectType({
name: 'User',
description: 'A person who users our app',
fields: () => ({
id: globalIdField('User'),
firstName: {
type: GraphQLString,
description: 'A users first name',
resolve(user) {
return user.firstName;
}
},
lastName: {
type: GraphQLString,
resolve(user) {
return user.lastName;
}
},
username: {
type: GraphQLString,
resolve(user) {
return user.username;
}
},
email: {
type: GraphQLString,
resolve(user) {
return user.email;
}
},
groups: {
type: new GraphQLList(groupType),
resolve(user) {
return user.getGroups();
}
},
}),
interfaces: [nodeInterface],
});
// Group query
var groupType = new GraphQLObjectType({
name: 'Group',
description: 'A users group',
fields: () => ({
id: globalIdField('Group'),
ownerId: {
type: GraphQLInt,
resolve(group) {
return group.ownerId;
}
},
name: {
type: GraphQLString,
resolve(group) {
return group.name;
}
},
topic: {
type: GraphQLString,
resolve(group) {
return group.topic;
}
},
domain: {
type: GraphQLString,
resolve(group) {
return group.domain;
}
},
private: {
type: GraphQLBoolean,
resolve(group) {
return group.private;
}
},
users: {
type: new GraphQLList(userType),
resolve(group) {
return group.getUsers();
}
}
}),
interfaces: [nodeInterface],
});
/**
* This is the type that will be the root of our query,
* and the entry point into our schema.
*/
var queryType = new GraphQLObjectType({
name: 'Query',
description: 'This is the root query',
fields: () => ({
node: nodeField,
// Add our own root fields here
viewer: {
type: userType,
args: {
id: {
type: GraphQLInt
},
email: {
type: GraphQLString
}
},
resolve: (root, args) => {
return db.models.user.findAll({ where: args });
}
},
}),
});
/**
* This is the type that will be the root of our mutations,
* and the entry point into performing writes in our schema.
*/
var mutationType = new GraphQLObjectType({
name: 'Mutation',
description: 'Data insertion',
fields: () => ({
addUser: {
type: userType,
args: {
firstName: {
type: new GraphQLNonNull(GraphQLString),
},
lastName: {
type: new GraphQLNonNull(GraphQLString),
},
username: {
type: new GraphQLNonNull(GraphQLString),
},
email: {
type: new GraphQLNonNull(GraphQLString),
},
password: {
type: new GraphQLNonNull(GraphQLString),
}
},
resolve(_, args) {
return Db.models.user.create({
firstName: args.firstName,
lastName: args.lastName,
username: args.username,
email: args.email.toLowerCase(),
password: args.password
});
}
}
})
});
/**
* Finally, we construct our schema (whose starting query type is the query
* type we defined above) and export it.
*/
export var Schema = new GraphQLSchema({
query: queryType,
mutation: mutationType
});
I can't seem to find where I have made a mistake. The database file seems fine since I can see the data in the dev table so I guess my error is somewhere in the schema.js file. Thank you for the help.

Categories