diff --git a/.gitignore b/.gitignore index 57902c5..c4d34a2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ npm-debug.log .env +*.iml diff --git a/docker-compose.yml b/docker-compose.yml index f515350..1d9d285 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,12 @@ services: depends_on: - database container_name: server + environment: + - MYSQL_USER=${DATABASE_USER} + - MYSQL_PASSWORD=${DATABASE_PASSWORD} + - MYSQL_DATABASE=${DATABASE_SCHEMA} + - PORT=3000 + - SOCKETS_PORT=8443 build: context: . dockerfile: server/Dockerfile diff --git a/server/database.js b/server/database.js index 1e5712a..2612009 100644 --- a/server/database.js +++ b/server/database.js @@ -1,6 +1,11 @@ const Sequelize = require('sequelize'); -const database = new Sequelize('mysql://toor:hei6voYi@database:3306/circles', {}); +let username = process.env.MYSQL_USER || ''; +let password = process.env.MYSQL_PASSWORD || ''; +let host = 'database'; +let dbName = process.env.MYSQL_DATABASE || ''; + +const database = new Sequelize('mysql://' + username + ':' + password + '@' + host + ':3306/' + dbName, {}); function connection() { return database; diff --git a/server/databaseModels/User.js b/server/databaseModels/User.js new file mode 100644 index 0000000..d4de886 --- /dev/null +++ b/server/databaseModels/User.js @@ -0,0 +1,92 @@ +const makeUserModel = function (database, types) { + return database().define('user', { + id: { + type: types.INTEGER, + primaryKey: true, + autoIncrement: true + }, + uuid: { + type: types.STRING(36), + allowNull: true, + defaultValue: null + }, + dateRegistered: { + type: 'TIMESTAMP', + allowNull: false, + defaultValue: types.literal('CURRENT_TIMESTAMP') + }, + name: { + type: types.STRING(255), + allowNull: true, + defaultValue: null + }, + email: { + type: types.STRING(255), + allowNull: true, + defaultValue: null + }, + birthday: { + type: 'TIMESTAMP', + allowNull: true, + defaultValue: null + }, + sex: { + type: types.STRING(6), + allowNull: true, + defaultValue: null + }, + status: { + type: types.STRING(11), + allowNull: true, + defaultValue: null + }, + aim: { + type: types.STRING(6), + allowNull: true, + defaultValue: null + }, + education: { + type: types.STRING(6), + allowNull: true, + defaultValue: null + }, + phone: { + type: types.INTEGER(10), + allowNull: true, + defaultValue: null + }, + about: { + type: types.TEXT, + allowNull: true, + defaultValue: null + }, + needSex: { + type: types.STRING(6), + allowNull: true, + defaultValue: null + }, + needStatus: { + type: types.STRING(11), + allowNull: true, + defaultValue: null + }, + needAim: { + type: types.STRING(6), + allowNull: true, + defaultValue: null + }, + needEducation: { + type: types.STRING(6), + allowNull: true, + defaultValue: null + } + }, + { + timestamps: true, + createdAt: 'dateRegistered', + updatedAt: false, + deletedAt: false + }); +}; + +module.exports = makeUserModel; \ No newline at end of file diff --git a/server/mappers/User.js b/server/mappers/User.js new file mode 100644 index 0000000..adec1bc --- /dev/null +++ b/server/mappers/User.js @@ -0,0 +1,62 @@ +let makeUserModel = require('../databaseModels/User.js'); + +function deepClone(objectToClone) { + return JSON.parse(JSON.stringify(objectToClone)); +} + +function UserMapper(database, types) { + this.database = database; + this.types = types; + + this.createTable = function () { + let user = makeUserModel(database, types); + return user.sync(); + }; + + this.create = function (uuid, userProps) { + let createProps = deepClone(userProps); + createProps.uuid = uuid; + + let user = makeUserModel(this.database, this.types); + + return new Promise(function (resolve, reject) { + user.create(createProps) + .then(function () { + return user.find({where: {uuid: uuid}}); + }) + .then(function (foundUser) { + resolve(foundUser); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + + this.update = function (uuid, propsToUpdate) { + let updateProps = deepClone(propsToUpdate); + let user = makeUserModel(this.database, this.types); + + return new Promise(function (resolve, reject) { + user.find({where: {uuid: uuid}}) + .then(function (foundUser) { + return foundUser.updateAttributes(updateProps); + }) + .then(function (updatedUser) { + resolve(updatedUser); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + + this.find = function (uuid) { + let user = makeUserModel(this.database, this.types); + return user.find({where: {uuid: uuid}}); + } +} + +module.exports = function (database, types) { + return new UserMapper(database, types); +}; \ No newline at end of file diff --git a/server/mappers/User.test.js b/server/mappers/User.test.js new file mode 100644 index 0000000..ddc3260 --- /dev/null +++ b/server/mappers/User.test.js @@ -0,0 +1,97 @@ +const makeUserMapper = require('./User'); +const database = require('../testDatabase.js'); +const types = require('sequelize'); + +beforeAll(function () { + let userMapper = makeUserMapper(database, types); + return userMapper.createTable(); +}); + +test('Метод create', function () { + let userMapper = makeUserMapper(database, types); + let uuid = "49642b99-edd1-4a4d-ae7f-407f36d665dc"; + let userProps = { + name: "Константин Константинопольский" + }; + + return new Promise(function (resolve, reject) { + userMapper.create(uuid, userProps) + .then(function (createdUser) { + try { + expect(createdUser.id).toBeGreaterThan(0); + expect(createdUser.name).toEqual(userProps.name); + resolve(); + } catch (exception) + { + reject(exception); + } + }); + }); +}); + +test('Метод update', function () { + let userMapper = makeUserMapper(database, types); + let uuid = "f99ac8bf-9ed4-4504-8eb3-413d01c89969"; + let initialProps = { + name: "Константин Константинопольский" + }; + + let updatedProps = { + name: "Сергей Сергиевский" + }; + + let newUserId = false; + + return new Promise(function (resolve, reject) { + userMapper.create(uuid, initialProps) + .then(function (createdUser) { + try { + newUserId = createdUser.id; + expect(createdUser.id).toBeGreaterThan(0); + expect(createdUser.name).toEqual(initialProps.name); + } catch (exception) + { + reject(exception); + } + }) + .then(function () { + return userMapper.update(uuid, updatedProps); + }) + .then(function (updatedUser) { + try { + expect(updatedUser.id).toEqual(newUserId); + expect(updatedUser.name).toEqual(updatedProps.name); + resolve(); + } catch (exception) + { + reject(exception); + } + }); + }); +}); + +test('Метод find', function () { + let userMapper = makeUserMapper(database, types); + let uuid = "e27b3196-18fd-48a0-84e0-25afaa8160a1"; + let userProps = { + name: "Константин Константинопольский" + }; + + return new Promise(function (resolve, reject) { + userMapper.create(uuid, userProps) + .then(function () { + return userMapper.find(uuid); + }) + .then(function (foundUser) { + try { + expect(foundUser.uuid).toEqual(uuid); + expect(foundUser.name).toEqual(userProps.name); + resolve(); + } + catch (error) { + reject(error); + } + }); + }); + +}); \ No newline at end of file diff --git a/server/mappers/user.js b/server/mappers/user.js deleted file mode 100644 index 2b7c258..0000000 --- a/server/mappers/user.js +++ /dev/null @@ -1,93 +0,0 @@ -const database = require('../database.js'); -const Sequelize = require('sequelize'); - -const User = database().define('user', { - id: { - type: Sequelize.INTEGER, - primaryKey: true, - autoIncrement: true - }, - uuid: { - type: Sequelize.STRING(36), - allowNull: true, - defaultValue: null - }, - dateRegistered: { - type: 'TIMESTAMP', - allowNull: false, - defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') - }, - name: { - type: Sequelize.STRING(255), - allowNull: true, - defaultValue: null - }, - email: { - type: Sequelize.STRING(255), - allowNull: true, - defaultValue: null - }, - birthday: { - type: 'TIMESTAMP', - allowNull: true, - defaultValue: null - }, - sex: { - type: Sequelize.STRING(6), - allowNull: true, - defaultValue: null - }, - status: { - type: Sequelize.STRING(11), - allowNull: true, - defaultValue: null - }, - aim: { - type: Sequelize.STRING(6), - allowNull: true, - defaultValue: null - }, - education: { - type: Sequelize.STRING(6), - allowNull: true, - defaultValue: null - }, - phone: { - type: Sequelize.INTEGER(10), - allowNull: true, - defaultValue: null - }, - about: { - type: Sequelize.TEXT, - allowNull: true, - defaultValue: null - }, - needSex: { - type: Sequelize.STRING(6), - allowNull: true, - defaultValue: null - }, - needStatus: { - type: Sequelize.STRING(11), - allowNull: true, - defaultValue: null - }, - needAim: { - type: Sequelize.STRING(6), - allowNull: true, - defaultValue: null - }, - needEducation: { - type: Sequelize.STRING(6), - allowNull: true, - defaultValue: null - } -}, -{ - timestamps: true, - createdAt: 'dateRegistered', - updatedAt: false, - deletedAt: false -}); - -module.exports = User; \ No newline at end of file diff --git a/server/package.json b/server/package.json index b3f0081..7b8bf13 100644 --- a/server/package.json +++ b/server/package.json @@ -19,9 +19,13 @@ }, "devDependencies": { "jest": "^23.4.0", - "nodemon": "^1.17.5" + "nodemon": "^1.17.5", + "sqlite3": "^4.0.2" }, "jest": { - "modulePaths": ["./"] + "modulePaths": [ + "./" + ], + "testURL": "http://localhost" } } diff --git a/server/routes/user.js b/server/routes/user.js index 0b09392..7eaef2f 100644 --- a/server/routes/user.js +++ b/server/routes/user.js @@ -1,5 +1,7 @@ let express = require('express'); -let User = require('../mappers/user.js'); +const database = require('../database.js'); +const types = require('sequelize'); +let makeUserMapper = require('../mappers/User.js'); let router = express.Router(); function uuid4() { @@ -9,18 +11,51 @@ function uuid4() { }); } -router.post('/create', function(req, res, next) { +router.post('/create', function(req, res) { let uuid = req.param('uuid', uuid4()); let userProps = req.body; - userProps.uuid = uuid; - - User.create(userProps) - .then(function () { - return User.findOrCreate({where: {uuid: uuid}}); - }) - .spread(function (user, isCreated) { - res.json(user); - }); + + makeUserMapper(database, types).create(uuid, userProps) + .then(function (createdUser) { + res.json(createdUser); + }) + .catch(function (error) { + res.json({ + success: false, + error: error + }); + }); +}); + +router.post('/update', function(req, res) { + let uuid = req.param('uuid', uuid4()); + let userProps = req.body; + + makeUserMapper(database, types).update(uuid, userProps) + .then(function (updatedUser) { + res.json(updatedUser); + }) + .catch(function (error) { + res.json({ + success: false, + error: error + }); + }); +}); + +router.get('/info', function(req, res) { + let uuid = req.param('uuid', uuid4()); + + makeUserMapper(database, types).find(uuid) + .then(function (foundUser) { + res.json(foundUser); + }) + .catch(function (error) { + res.json({ + success: false, + error: error + }); + }); }); module.exports = router; diff --git a/server/testApiRequests.sh b/server/testApiRequests.sh new file mode 100755 index 0000000..3164016 --- /dev/null +++ b/server/testApiRequests.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +uuid=`uuidgen` +echo "USER CREATE" +curl -k -X POST -H "Content-Type: application/json" --data-raw '{"name": "Сергей Сергиенко"}' http://localhost:8082/api/user/create?uuid=${uuid} +echo -e "\nUSER UPDATE" +curl -k -X POST -H "Content-Type: application/json" --data-raw '{"sex": "male", "needSex": "female"}' http://localhost:8082/api/user/update?uuid=${uuid} +echo -e "\nUSER INFO" +curl http://localhost:8082/api/user/info?uuid=${uuid} \ No newline at end of file diff --git a/server/testDatabase.js b/server/testDatabase.js new file mode 100644 index 0000000..ef2acc7 --- /dev/null +++ b/server/testDatabase.js @@ -0,0 +1,9 @@ +const Sequelize = require('sequelize'); + +const database = new Sequelize('sqlite::memory:', {}); + +function connection() { + return database; +} + +module.exports=connection; \ No newline at end of file