Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "src/common"]
path = src/common
url = https://github.com/innervate-ru/common.git
[submodule "dscommon"]
path = dscommon
url = https://github.com/delightsoft/DSCommon3.git
28 changes: 28 additions & 0 deletions config/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module.exports = {
node: 'test',
consoleLevel: 5,
graphql: {
description: 'Включен ли graphIql интерфейс на сервере',
enableUI: true,
pathname: '/graphql'
},
http: {
protocol: 'http',
hostname: 'localhost',
port: 3000
},
postgres: {
host: 'localhost',
port: 5432,
user: 'postgres',
password: '12345',
database: 'postgres',
max: 10,
idleTimeoutMillis: 30000
},
externalTestService: {},
secret: 'UKBKhmHGjyg&^y;ogKUVHMgvmjB<kjnIy*&uhJh',
grayLog: {
enabled: false
}
}
1 change: 1 addition & 0 deletions config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"max": 10,
"idleTimeoutMillis": 30000
},
"externalTestService": {},
"grayLog": {
"enabled": false
}
Expand Down
28 changes: 4 additions & 24 deletions db/dump.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,6 @@
-- Dumped from database version 10.4
-- Dumped by pg_dump version 10.3

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: postgres; Type: DATABASE; Schema: -; Owner: postgres
--

CREATE DATABASE postgres WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'Russian_Russia.1251' LC_CTYPE = 'Russian_Russia.1251';


ALTER DATABASE postgres OWNER TO postgres;

\connect postgres

SET statement_timeout = 0;
SET lock_timeout = 0;
Expand All @@ -44,28 +24,28 @@ COMMENT ON DATABASE postgres IS 'default administrative connection database';


--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
--

CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;


--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
--

COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';


--
-- Name: adminpack; Type: EXTENSION; Schema: -; Owner:
-- Name: adminpack; Type: EXTENSION; Schema: -; Owner:
--

CREATE EXTENSION IF NOT EXISTS adminpack WITH SCHEMA pg_catalog;


--
-- Name: EXTENSION adminpack; Type: COMMENT; Schema: -; Owner:
-- Name: EXTENSION adminpack; Type: COMMENT; Schema: -; Owner:
--

COMMENT ON EXTENSION adminpack IS 'administrative functions for PostgreSQL';
Expand Down
19 changes: 19 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: '3.2'
services:

db:
container_name: test-task-db
build: ./docker/container/pgsql
restart: always
image: postgres
ports:
- "5432:5432"
environment:
PGDATA: /var/lib/postgresql/data/pgdata
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: 12345
volumes:
- ./temp/postgres:/var/lib/postgresql/data
- ./db/dump.sql:/docker-entrypoint-initdb.d/dump.sql

2 changes: 2 additions & 0 deletions docker/container/pgsql/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM postgres:10.4

1 change: 0 additions & 1 deletion dscommon
Submodule dscommon deleted from e68673
17 changes: 17 additions & 0 deletions src/api/_helpers/error-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = errorHandler;

function errorHandler(err, req, res, next) {
if (typeof (err) === 'string') {
// custom application error
return res.status(400).json({message: err});
}

if (err.name === 'UnauthorizedError') {
// jwt authentication error
return res.status(401).json({message: 'Invalid Token'});
}

console.log('errorHandler', err, req, res, next)
// default to 500 server error
return res.status(500).json({message: err.message});
}
14 changes: 14 additions & 0 deletions src/api/_helpers/jwt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const expressJwt = require('express-jwt');
const config = require('../../../config/default');

module.exports = jwt;

function jwt() {
const {secret} = config;
return expressJwt({secret}).unless({
path: [
// public routes that don't require authentication
'/users/authenticate'
]
});
}
48 changes: 48 additions & 0 deletions src/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import express from "express";

const bodyParser = require('body-parser');
const jwt = require('./_helpers/jwt');
const errorHandler = require('./_helpers/error-handler');


let restApiRouter = express.Router();

restApiRouter.get('/api/for-kursant-and-zork', function (req, res, next) {
console.log('get: /api', req.params);
res.send({
status: 'ok',
title: 'Сообщение для Курсанта и Зорка',
message: 'Жена пришла. Я собираюсь выходить. Это сообщение генерит мой макбучек. Шурочкин.'
});
});

restApiRouter.post('/api/user', bodyParser.json(), function (req, res, next) {
console.log('post: /api/user', req);
res.send({params: req.body});
});
restApiRouter.delete('/api/user', bodyParser.json(), function (req, res, next) {
console.log('delete: /api/user', req);
res.send({params: req.body});
});

restApiRouter.post('/api/profile', bodyParser.json(), function (req, res, next) {
console.log('post: /api/profile', req);
res.send({params: req.body});
});
restApiRouter.delete('/api/profile', bodyParser.json(), function (req, res, next) {
console.log('delete: /api/profile', req);
res.send({params: req.body});
});

restApiRouter.post('/api/shippings', bodyParser.json(), function (req, res, next) {
console.log('post: /api/shippings', req);
res.send({params: req.body});
});
restApiRouter.delete('/api/shippings', bodyParser.json(), function (req, res, next) {
console.log('delete: /api/shippings', req);
res.send({params: req.body});
});



module.exports = restApiRouter;
51 changes: 51 additions & 0 deletions src/api/users/user.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// const MongoClient = require('mongodb').MongoClient;
const config = require('config.json');
const jwt = require('jsonwebtoken');

// users hardcoded for simplicity, store in a db for production applications
const users = [
{user_id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User'}
];

// const mongoClient = new MongoClient(config.db.url, {useNewUrlParser: true});
// mongoClient.connect(function (err, client) {
//
// const db = client.db(config.db.name);
// // console.log('connect :: clent: ', client, err, db);
// const collection = db.collection("users");
//
// collection.insertMany(users, function (err, results) {
//
// console.log(results);
// client.close();
// });
// });


module.exports = {
authenticate,
getAll
};

async function authenticate({username, password}) {
const user = users.find(u => u.username === username && u.password === password);
if (user) {
const {password, ...userWithoutPassword} = user;
const token = jwt.sign(
{...userWithoutPassword},
config.secret,
{expiresIn: '24h'}
);
return {
...userWithoutPassword,
token
};
}
}

async function getAll() {
return users.map(u => {
const {password, ...userWithoutPassword} = u;
return userWithoutPassword;
});
}
21 changes: 21 additions & 0 deletions src/api/users/users.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const express = require('express');
const router = express.Router();
const userService = require('./user.service');

// routes
router.post('/authenticate', authenticate);
router.get('/', getAll);

module.exports = router;

function authenticate(req, res, next) {
userService.authenticate(req.body)
.then(user => user ? res.json(user) : res.status(400).json({message: 'Username or password is incorrect'}))
.catch(err => next(err));
}

function getAll(req, res, next) {
userService.getAll()
.then(users => res.json(users))
.catch(err => next(err));
}
4 changes: 2 additions & 2 deletions src/graphqlSchemaV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export default oncePerServices(function (services = missingArgument('services'))
const resolvers = Object.create(null);

await (new SchemaBuilder({
test: require('./services/test/graphql').default(services)

test: require('./services/test/graphql').default(services),
user: require('./services/user/graphql').default(services),
}).build({typeDefs, resolvers}));

return makeExecutableSchema({
Expand Down
20 changes: 15 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {missingExport} from './common/services'
import errorDataToEvent from './common/errors/errorDataToEvent'
const schema = require('./index.schema');
const realConsole = console;
// const errorHandler = require('../api/_helpers/error-handler')

(async function () {

Expand All @@ -38,17 +39,25 @@ const realConsole = console;
manager = new (require('./common/services').NodeManager(consoleAndBusServicesOnly))({ // далее consoleAndBusServicesOnly нельзя. нужно пользоваться manager.services
name: nodeName,
services: [
require('./services/postgres')
require('./services/postgres'),
require('./services/user')
]
});

// ждем пока NodeManager скажет что он готов. при этом часть сервисов может быть в состоянии failed
await manager.started;

let expressApp = express();

expressApp.use(cors());

// expressApp.use(bodyParser.urlencoded({extended: false}));
// expressApp.use(bodyParser.json());

expressApp.use('/', require('./api'));

expressApp.use(require('./api/_helpers/error-handler'));


let graphqlRouterV2 = express.Router();
const graphqlSchemaV2 = await (require('./graphqlSchemaV2').default(manager.services)());
graphqlRouterV2.post('/graphql/v2', bodyParser.json(), graphqlExpress(request => ({
Expand All @@ -57,7 +66,8 @@ const realConsole = console;
})));
graphqlRouterV2.get('/graphql/v2', graphiqlExpress({endpointURL: '/graphql/v2'}));
expressApp.use('/', graphqlRouterV2);



// Запускаем сервер
let httpServer = http.Server(expressApp);
await new Promise(function (resolve, reject) {
Expand All @@ -66,7 +76,7 @@ const realConsole = console;
else resolve(data);
})
});

bus.event({
type: 'webserver.started',
service: nodeName,
Expand Down
44 changes: 44 additions & 0 deletions src/services/user/graphql.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {oncePerServices, missingService} from '../../common/services/index'

const PREFIX = 'User';

export default oncePerServices(function (services) {

const graphqlBuilderSchema = require('../../common/graphql/LevelBuilder.schema');

const {
user = missingService('user')
} = services;

return async function builder(args) {

graphqlBuilderSchema.build_options(args);
const { parentLevelBuilder, typeDefs, builderContext } = args;

typeDefs.push(`

type ${PREFIX}QueryElement {
user_id: Int,
login: String,
email: String,
name: String,
manager: Boolean,
blocked: Boolean,
birthday: String
}

`);

parentLevelBuilder.addQuery({
name: `usersQuery`,
type: `[${PREFIX}QueryElement]`,
args: `
user_id: Int
`,
resolver: function (args, request) {
return user.getAllUsers(args)
},
});

}
});
Loading