Skip to content

Commit

Permalink
Requisito 01 - OK
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasravache committed Feb 17, 2022
1 parent 11f3557 commit 5d09f8d
Show file tree
Hide file tree
Showing 19 changed files with 2,888 additions and 88 deletions.
25 changes: 25 additions & 0 deletions config/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require('dotenv').config();

module.exports = {
development: {
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: 'blogs_api',
host: process.env.HOSTNAME,
dialect: 'mysql',
},
test: {
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: 'blogs_api',
host: process.env.HOSTNAME,
dialect: 'mysql',
},
production: {
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: 'blogs_api',
host: process.env.HOSTNAME,
dialect: 'mysql',
},
};
35 changes: 35 additions & 0 deletions controllers/UserController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const express = require('express');
const userSchema = require('./schemas/userSchema');
const UserService = require('../services/UserService');

const userRouter = express.Router();

const validateUser = (body) => {
const { error } = userSchema.validate(body);

if (error) throw error;
};

const create = async (req, res, next) => {
try {
const {
displayName,
email,
password,
image,
} = req.body;

validateUser(req.body);

const token = await UserService.create({ displayName, email, password, image });

return res.status(201).json({ token });
} catch (e) {
return next(e);
}
};

/* ROUTES */
userRouter.post('/', create);

module.exports = userRouter;
13 changes: 13 additions & 0 deletions controllers/errorsHandler/domainError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const statusCodes = {
'User already registered': 409,
};

module.exports = (err, _req, res, next) => {
if (err.message) {
const statusCode = statusCodes[err.message] || 400;

return res.status(statusCode).json({ message: err.message });
}

return next(err);
};
9 changes: 9 additions & 0 deletions controllers/errorsHandler/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const inputError = require('./inputError');
const domainError = require('./domainError');
const serverError = require('./serverError');

module.exports = {
inputError,
domainError,
serverError,
};
11 changes: 11 additions & 0 deletions controllers/errorsHandler/inputError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = (err, _req, res, next) => {
if (err.isJoi) {
console.log(err);
const { details } = err;
const { message } = details[0];

return res.status(400).json({ message });
}

return next(err);
};
3 changes: 3 additions & 0 deletions controllers/errorsHandler/serverError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = (_err, _req, res, _next) => (
res.status(500).json({ message: 'Internal server error' })
);
5 changes: 5 additions & 0 deletions controllers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const userRouter = require('./UserController');

module.exports = {
userRouter,
};
15 changes: 15 additions & 0 deletions controllers/schemas/userSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const Joi = require('joi');

const userSchema = Joi.object({
displayName: Joi.string().min(8).not().empty()
.required(),
email: Joi.string().email().not().empty()
.required(),
password: Joi.string().min(6).required()
.messages({
'string.min': '"password" length must be 6 characters long',
}),
image: Joi.string(),
});

module.exports = userSchema;
12 changes: 12 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
const express = require('express');
const bodyParser = require('body-parser');
const { userRouter } = require('./controllers');
const { inputError, domainError, serverError } = require('./controllers/errorsHandler');

const app = express();

app.use(bodyParser.json());

app.use('/user', userRouter);

/* Error Handlers */
app.use(inputError);
app.use(domainError);
app.use(serverError);

app.listen(3000, () => console.log('ouvindo porta 3000!'));

// não remova esse endpoint, e para o avaliador funcionar
Expand Down
35 changes: 35 additions & 0 deletions migrations/20220217143540-create-users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict';

module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Users', {
id: {
primaryKey: true,
autoIncrement: true,
allowNull: false,
type: Sequelize.INTEGER,
},
displayName: {
allowNull: false,
type: Sequelize.STRING,
},
email: {
allowNull: false,
unique: true,
type: Sequelize.STRING,
},
password: {
allowNull: false,
type: Sequelize.STRING,
},
image: {
allowNull: false,
type: Sequelize.STRING,
}
});
},

down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Users');
}
};
22 changes: 22 additions & 0 deletions migrations/20220217144751-create-categories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict';

module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Categories', {
id: {
primaryKey: true,
allowNull: false,
autoIncrement: true,
type: Sequelize.INTEGER,
},
name: {
allowNull: false,
type: Sequelize.STRING,
},
});
},

down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Categories');
}
};
44 changes: 44 additions & 0 deletions migrations/20220217173741-create-blogposts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';

module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('BlogPosts', {
id: {
primaryKey: true,
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
},
title: {
allowNull: false,
type: Sequelize.STRING,
},
content: {
allowNull: false,
type: Sequelize.STRING,
},
userId: {
type: Sequelize.INTEGER,
references: {
model: 'Users',
key: 'id',
},
onDelete: 'CASCADE',
},
published: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
},
updated: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
}
});
},

down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('BlogPosts');
}
};
30 changes: 30 additions & 0 deletions migrations/20220217173742-create-postscategories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('PostsCategories', {
postId: {
type: Sequelize.INTEGER,
primaryKey: true,
references: {
model: 'BlogPosts',
key: 'id',
},
onDelete: 'CASCADE',
},
categoryId: {
type: Sequelize.INTEGER,
primaryKey: true,
references: {
model: 'Categories',
key: 'id',
},
onDelete: 'CASCADE',
}
})
},

down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('PostsCategories');
}
};
22 changes: 22 additions & 0 deletions models/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
displayName: DataTypes.STRING,
email: {
type: DataTypes.STRING,
unique: true,
},
password: DataTypes.STRING,
image: DataTypes.STRING,
}, {
timestamps: false,
tableName: 'Users',
});

// User.associate = (models) => {
// User.hasMany(models.BlogPost, {
// foreignKey: 'userId', as: 'blogPosts',
// });
// };

return User;
};
37 changes: 37 additions & 0 deletions models/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.js')[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});

Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;
Loading

0 comments on commit 5d09f8d

Please sign in to comment.