create-sip 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/create-sip.js +16 -1
- package/expressapi/README.md +69 -0
- package/expressapi/app/controllers/authcontroller.js +103 -0
- package/expressapi/app/controllers/usercontroller.js +27 -0
- package/expressapi/app/database/database.js +22 -0
- package/expressapi/app/index.js +19 -0
- package/expressapi/app/middleware/authjwt.js +22 -0
- package/expressapi/app/models/user.js +19 -0
- package/expressapi/app/routes/api.js +12 -0
- package/expressapi/config/default.json.example +15 -0
- package/expressapi/docs/dev_doc.md +15 -0
- package/expressapi/docs/user_doc.md +57 -0
- package/expressapi/nodemon.json +4 -0
- package/expressapi/package.json +32 -0
- package/expressapi/test/test.js +43 -0
- package/expressapi/tools/genkey.js +19 -0
- package/manager.js +9 -1
- package/package.json +1 -1
package/create-sip.js
CHANGED
|
@@ -7,7 +7,8 @@ const {
|
|
|
7
7
|
genNodejs,
|
|
8
8
|
genWebEsbuildJs,
|
|
9
9
|
genWebEsbuildTs,
|
|
10
|
-
genMockApi
|
|
10
|
+
genMockApi,
|
|
11
|
+
genExpressApi
|
|
11
12
|
} = require('./manager');
|
|
12
13
|
const prompts = require('prompts');
|
|
13
14
|
|
|
@@ -57,6 +58,15 @@ const questions = [
|
|
|
57
58
|
title: 'MockAPI',
|
|
58
59
|
description: 'API server with hai-server 0.0.4',
|
|
59
60
|
value: 'mockapi'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
title: 'Express API',
|
|
64
|
+
description: 'Express API with simple Sequelize',
|
|
65
|
+
value: 'expressapi'
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
title: 'Cancel',
|
|
69
|
+
value: 'cancel'
|
|
60
70
|
}
|
|
61
71
|
],
|
|
62
72
|
initial: 0
|
|
@@ -100,5 +110,10 @@ const questions = [
|
|
|
100
110
|
genMockApi(res.name);
|
|
101
111
|
return;
|
|
102
112
|
}
|
|
113
|
+
if(res.type === 'expressapi') {
|
|
114
|
+
console.log('Create a new Express API...');
|
|
115
|
+
genExpressApi(res.name);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
103
118
|
|
|
104
119
|
})();
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# exapi
|
|
2
|
+
|
|
3
|
+
Exapi framework
|
|
4
|
+
|
|
5
|
+
Express based REST API sablon
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```cmd
|
|
10
|
+
npm install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Copy config file
|
|
14
|
+
|
|
15
|
+
Copy **config/default.json.example** to **config/default.json** file.
|
|
16
|
+
|
|
17
|
+
## APP KEY generation
|
|
18
|
+
|
|
19
|
+
Run the genkey tools:
|
|
20
|
+
|
|
21
|
+
```cmd
|
|
22
|
+
node tools/genkey.js
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Database settings
|
|
26
|
+
|
|
27
|
+
The database settings can be found at the following location:
|
|
28
|
+
|
|
29
|
+
* config/default.json
|
|
30
|
+
|
|
31
|
+
### Database dialect
|
|
32
|
+
|
|
33
|
+
The default database is an in-memory database. Its contents are cleared after the server is restarted.
|
|
34
|
+
|
|
35
|
+
One of:
|
|
36
|
+
|
|
37
|
+
* sqlite
|
|
38
|
+
* mariadb
|
|
39
|
+
|
|
40
|
+
After installing the appropriate dependencies, it can be used:
|
|
41
|
+
|
|
42
|
+
* mysql
|
|
43
|
+
* postgres
|
|
44
|
+
* mssql
|
|
45
|
+
* db2
|
|
46
|
+
* snowflake
|
|
47
|
+
* oracle
|
|
48
|
+
|
|
49
|
+
With the `sqlite` option, the database is stored in the `database.sqlite` file, or you can add :memory:, then the database is stored in memory.
|
|
50
|
+
|
|
51
|
+
## Starting
|
|
52
|
+
|
|
53
|
+
For development:
|
|
54
|
+
|
|
55
|
+
```cmd
|
|
56
|
+
npm run dev
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Run productum:
|
|
60
|
+
|
|
61
|
+
```cmd
|
|
62
|
+
npm start
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Licence
|
|
66
|
+
|
|
67
|
+
May be freely distributed under the MIT license.
|
|
68
|
+
|
|
69
|
+
Copyright (c) 2023 Sallai András
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const bcrypt = require('bcryptjs')
|
|
2
|
+
const jwt = require('jsonwebtoken')
|
|
3
|
+
const User = require('../models/user')
|
|
4
|
+
const config = require('../../config/default.json')
|
|
5
|
+
|
|
6
|
+
const AuthController = {
|
|
7
|
+
async register(req, res) {
|
|
8
|
+
var clientError = false;
|
|
9
|
+
try {
|
|
10
|
+
if(!req.body.name ||
|
|
11
|
+
!req.body.email ||
|
|
12
|
+
!req.body.password ||
|
|
13
|
+
!req.body.password_confirmation) {
|
|
14
|
+
clientError = true
|
|
15
|
+
throw new Error('Error! Bad request data!')
|
|
16
|
+
}
|
|
17
|
+
if(req.body.password != req.body.password_confirmation) {
|
|
18
|
+
clientError = true
|
|
19
|
+
throw new Error('Error! The two password is not same!')
|
|
20
|
+
}
|
|
21
|
+
const user = await User.findOne({
|
|
22
|
+
where: { name: req.body.name }
|
|
23
|
+
})
|
|
24
|
+
if(user) {
|
|
25
|
+
clientError = true
|
|
26
|
+
throw new Error('Error! User already exists: ' + user.name)
|
|
27
|
+
}
|
|
28
|
+
AuthController.tryRegister(req, res)
|
|
29
|
+
} catch (error) {
|
|
30
|
+
if (clientError) {
|
|
31
|
+
res.status(400)
|
|
32
|
+
}else {
|
|
33
|
+
res.status(500)
|
|
34
|
+
}
|
|
35
|
+
await res.json({
|
|
36
|
+
success: false,
|
|
37
|
+
message: 'Error! User creation failed!',
|
|
38
|
+
error: error.message
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
async tryRegister(req, res) {
|
|
43
|
+
const user = {
|
|
44
|
+
name: req.body.name,
|
|
45
|
+
email: req.body.email,
|
|
46
|
+
password: bcrypt.hashSync(req.body.password)
|
|
47
|
+
}
|
|
48
|
+
await User.create(user)
|
|
49
|
+
.then( result => {
|
|
50
|
+
res.status(201)
|
|
51
|
+
res.json({
|
|
52
|
+
succes: true,
|
|
53
|
+
data: result
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
},
|
|
57
|
+
async login(req, res) {
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
if(!req.body.name || !req.body.password) {
|
|
61
|
+
res.status(400)
|
|
62
|
+
throw new Error('Error! Bad name or password!')
|
|
63
|
+
}
|
|
64
|
+
const user = await User.findOne({
|
|
65
|
+
where: { name: req.body.name }
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
if(!user) {
|
|
69
|
+
res.status(404)
|
|
70
|
+
throw new Error('Error! User not found!')
|
|
71
|
+
}
|
|
72
|
+
var passwordIsValid = await bcrypt.compare(
|
|
73
|
+
req.body.password,
|
|
74
|
+
user.dataValues.password
|
|
75
|
+
);
|
|
76
|
+
if(!passwordIsValid) {
|
|
77
|
+
res.status(401)
|
|
78
|
+
throw new Error('Error! Password is not valid!')
|
|
79
|
+
}
|
|
80
|
+
AuthController.tryLogin(req, res, user)
|
|
81
|
+
|
|
82
|
+
} catch (error) {
|
|
83
|
+
res.json({
|
|
84
|
+
success: false,
|
|
85
|
+
message: 'Error! The login is failed!',
|
|
86
|
+
error: error.message
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
async tryLogin(req, res, user) {
|
|
91
|
+
var token = jwt.sign({ id: user.id }, config.app.key, {
|
|
92
|
+
expiresIn: 86400 //24 óra
|
|
93
|
+
})
|
|
94
|
+
res.status(200).json({
|
|
95
|
+
id: user.id,
|
|
96
|
+
name: user.name,
|
|
97
|
+
email: user.email,
|
|
98
|
+
accessToken: token
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = AuthController
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const User = require('../models/user')
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const UserController = {
|
|
6
|
+
async index(req, res) {
|
|
7
|
+
try {
|
|
8
|
+
UserController.tryIndex(req, res)
|
|
9
|
+
}catch(error) {
|
|
10
|
+
res.status(500)
|
|
11
|
+
res.json({
|
|
12
|
+
success: false,
|
|
13
|
+
message: 'Error! The query is failed!'
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
async tryIndex(req, res) {
|
|
18
|
+
const users = await User.findAll()
|
|
19
|
+
res.status(200)
|
|
20
|
+
res.json({
|
|
21
|
+
success: true,
|
|
22
|
+
data: users
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = UserController
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const Sequelize = require('sequelize')
|
|
2
|
+
const config = require('../../config/default.json')
|
|
3
|
+
|
|
4
|
+
if(config.app.log != false) {
|
|
5
|
+
var log = console.log
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
console.log(typeof console.log)
|
|
9
|
+
const sequelize = new Sequelize(
|
|
10
|
+
config.db.name,
|
|
11
|
+
config.db.user,
|
|
12
|
+
config.db.pass,
|
|
13
|
+
{
|
|
14
|
+
logging: log,
|
|
15
|
+
dialect: config.db.dialect,
|
|
16
|
+
storage: config.db.path,
|
|
17
|
+
host: config.db.host,
|
|
18
|
+
dialectOptions: {}
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
module.exports = sequelize
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const express = require('express')
|
|
2
|
+
const morgan = require('morgan')
|
|
3
|
+
const app = express()
|
|
4
|
+
const fs = require('fs')
|
|
5
|
+
const router = require('./routes/api')
|
|
6
|
+
const config = require('../config/default.json')
|
|
7
|
+
|
|
8
|
+
const PORT = config.app.port || 8000
|
|
9
|
+
|
|
10
|
+
const logfile = 'access.log'
|
|
11
|
+
var accessLogStream = fs.createWriteStream(logfile, { flags: 'a' })
|
|
12
|
+
app.use(morgan('dev', { stream: accessLogStream }))
|
|
13
|
+
|
|
14
|
+
app.use(express.json())
|
|
15
|
+
app.use('/api', router);
|
|
16
|
+
|
|
17
|
+
app.listen(PORT, () => {
|
|
18
|
+
console.log(`Listening on port: ${PORT}`)
|
|
19
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const jwt = require("jsonwebtoken");
|
|
2
|
+
const config = require('../../config/default.json')
|
|
3
|
+
|
|
4
|
+
exports.verifyToken = (req, res, next) => {
|
|
5
|
+
let authData = req.headers.authorization;
|
|
6
|
+
if(!authData) {
|
|
7
|
+
return res.status(403).send({
|
|
8
|
+
message: 'No token provided!'
|
|
9
|
+
})
|
|
10
|
+
}
|
|
11
|
+
let token = authData.split(' ')[1];
|
|
12
|
+
|
|
13
|
+
jwt.verify(token, config.app.key, (err, decoded) => {
|
|
14
|
+
if(err) {
|
|
15
|
+
return res.status(401).send({
|
|
16
|
+
message: "Unauthorized!"
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
req.userId = decoded.id;
|
|
20
|
+
next()
|
|
21
|
+
})
|
|
22
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const { DataTypes } = require('sequelize')
|
|
2
|
+
const sequelize = require('../database/database')
|
|
3
|
+
|
|
4
|
+
const User = sequelize.define('User', {
|
|
5
|
+
id: {
|
|
6
|
+
type: DataTypes.INTEGER,
|
|
7
|
+
autoIncrement: true,
|
|
8
|
+
primaryKey: true
|
|
9
|
+
},
|
|
10
|
+
name: { type: DataTypes.STRING, allowNull: false },
|
|
11
|
+
email: { type: DataTypes.STRING, allowNull: true },
|
|
12
|
+
password: { type: DataTypes.STRING , allowNull: false }
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
sequelize.sync({
|
|
17
|
+
force: false
|
|
18
|
+
})
|
|
19
|
+
module.exports = User
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const Router = require('express')
|
|
2
|
+
const router = Router()
|
|
3
|
+
|
|
4
|
+
const AuthController = require('../controllers/authcontroller')
|
|
5
|
+
const UserController = require('../controllers/usercontroller')
|
|
6
|
+
const { verifyToken } = require('../middleware/authjwt')
|
|
7
|
+
|
|
8
|
+
router.post('/register', AuthController.register)
|
|
9
|
+
router.post('/login', AuthController.login)
|
|
10
|
+
router.get('/users', [verifyToken], UserController.index)
|
|
11
|
+
|
|
12
|
+
module.exports = router
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# User documentation
|
|
2
|
+
|
|
3
|
+
## Install dependencies
|
|
4
|
+
|
|
5
|
+
```cmd
|
|
6
|
+
pnpm install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Copy config file
|
|
10
|
+
|
|
11
|
+
Copy **config/default.json.example** to **config/default.json** file.
|
|
12
|
+
|
|
13
|
+
## App key generation
|
|
14
|
+
|
|
15
|
+
```cmd
|
|
16
|
+
node tools/genkey.js
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Database setup
|
|
20
|
+
|
|
21
|
+
Edit the config/default.json file.
|
|
22
|
+
|
|
23
|
+
## Endpoints
|
|
24
|
+
|
|
25
|
+
All endpoint have a /api prefix.
|
|
26
|
+
|
|
27
|
+
| Endpoint | Method | Auth | Description |
|
|
28
|
+
|-|-|-|-|
|
|
29
|
+
| /register | POST | no | create user |
|
|
30
|
+
| /login | POST | no | login |
|
|
31
|
+
| /users | GET | yes | read users |
|
|
32
|
+
|
|
33
|
+
## The register endpoint
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"name": "joe",
|
|
38
|
+
"email": "joe@green.lan",
|
|
39
|
+
"password": "secret",
|
|
40
|
+
"password_confirmation": "secret"
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## The login endpoint
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"name": "joe",
|
|
49
|
+
"password": "secret"
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
You receive the bearear token with accessToken key.
|
|
54
|
+
|
|
55
|
+
## The users endpoint
|
|
56
|
+
|
|
57
|
+
Send the bearer token.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "expressapi",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Express API with simple Sequelize",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "mocha",
|
|
8
|
+
"dev": "nodemon app",
|
|
9
|
+
"start": "node app"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"express",
|
|
13
|
+
"api"
|
|
14
|
+
],
|
|
15
|
+
"author": "Sallai András",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"bcryptjs": "^2.4.3",
|
|
19
|
+
"express": "^4.18.2",
|
|
20
|
+
"generate-api-key": "^1.0.2",
|
|
21
|
+
"jsonwebtoken": "^9.0.0",
|
|
22
|
+
"mariadb": "^3.1.2",
|
|
23
|
+
"morgan": "^1.10.0",
|
|
24
|
+
"replace": "^1.2.2",
|
|
25
|
+
"sequelize": "^6.32.0",
|
|
26
|
+
"sqlite3": "^5.1.6"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"nodemon": "^2.0.22",
|
|
30
|
+
"supertest": "^6.3.3"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const supertest = require('supertest')
|
|
2
|
+
|
|
3
|
+
describe('GET /api/users', () => {
|
|
4
|
+
|
|
5
|
+
const host = 'http://localhost:8000/api'
|
|
6
|
+
const restype= 'application/json; charset=utf-8'
|
|
7
|
+
var token = null
|
|
8
|
+
|
|
9
|
+
it('post /register ', function(done) {
|
|
10
|
+
supertest(host)
|
|
11
|
+
.post('/register')
|
|
12
|
+
.set('Accept', 'application/json')
|
|
13
|
+
.send({
|
|
14
|
+
name: 'mari',
|
|
15
|
+
email: 'mari@zold.lan',
|
|
16
|
+
password: 'titok',
|
|
17
|
+
password_confirmation: 'titok'
|
|
18
|
+
})
|
|
19
|
+
.expect('Content-Type', restype)
|
|
20
|
+
.expect(201, done)
|
|
21
|
+
})
|
|
22
|
+
it('post /login ', (done) => {
|
|
23
|
+
supertest(host)
|
|
24
|
+
.post('/login')
|
|
25
|
+
.set('Accept', 'application/json')
|
|
26
|
+
.send({
|
|
27
|
+
name: 'mari',
|
|
28
|
+
password: 'titok'
|
|
29
|
+
})
|
|
30
|
+
.expect('Content-Type', restype)
|
|
31
|
+
.expect(200, done)
|
|
32
|
+
.expect(res => {
|
|
33
|
+
token = res.body.accessToken
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
it('get /users ', function(done) {
|
|
37
|
+
supertest(host)
|
|
38
|
+
.get('/users')
|
|
39
|
+
.set('Accept', 'application/json')
|
|
40
|
+
.set('Authorization', 'Bearer ' + token)
|
|
41
|
+
.expect(200, done)
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const fs = require('fs').promises
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const fileName = '../config/default.json'
|
|
4
|
+
const { generateApiKey } = require('generate-api-key')
|
|
5
|
+
|
|
6
|
+
function generateKey(size = 32, format = 'base64') {
|
|
7
|
+
const buffer = crypto.randomBytes(size);
|
|
8
|
+
return buffer.toString(format);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
fs.readFile(path.join(__dirname, fileName))
|
|
12
|
+
.then(body => JSON.parse(body))
|
|
13
|
+
.then(json => {
|
|
14
|
+
json.app.key = generateApiKey({method: 'bytes', length: 32})
|
|
15
|
+
return json
|
|
16
|
+
})
|
|
17
|
+
.then(json => JSON.stringify(json, null, 4))
|
|
18
|
+
.then(body => fs.writeFile(path.join(__dirname, fileName), body, 'utf8'))
|
|
19
|
+
.catch(error => console.log(error))
|
package/manager.js
CHANGED
|
@@ -57,6 +57,13 @@ const genMockApi = (target) => {
|
|
|
57
57
|
console.log('npm start');
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
const genExpressApi = (target) => {
|
|
61
|
+
copyDir(`${dir}/expressapi`, target);
|
|
62
|
+
updatePackageName(`${target}/package.json`, target);
|
|
63
|
+
console.log('ExpressJS REST API sablon created');
|
|
64
|
+
console.log('Read docs/user_doc.md');
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
const updatePackageName = (filePath, newName) => {
|
|
61
68
|
const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
62
69
|
if (content.name) {
|
|
@@ -87,5 +94,6 @@ module.exports = {
|
|
|
87
94
|
genNodejs,
|
|
88
95
|
genWebEsbuildJs,
|
|
89
96
|
genWebEsbuildTs,
|
|
90
|
-
genMockApi
|
|
97
|
+
genMockApi,
|
|
98
|
+
genExpressApi
|
|
91
99
|
}
|