service project with demo and testcase
This commit is contained in:
commit
03407638bd
40
api/user.js
Normal file
40
api/user.js
Normal file
@ -0,0 +1,40 @@
|
||||
import s from "service"
|
||||
import u from 'util'
|
||||
import db from 'db'
|
||||
import verifies from "../lib/verifies"
|
||||
|
||||
function main() {
|
||||
s.register({ method: 'POST', path: '/register', verifies, requires: ['id', 'password', 'name'] }, ({ args }) => {
|
||||
// 生成随机盐,加密密码
|
||||
let salt = u.token(20)
|
||||
let password = u.hex(u.sha256(u.unHex(args.password), salt))
|
||||
|
||||
// 插入用户信息
|
||||
let r = db.insert('User', { id: args.id, password, salt, name: args.name })
|
||||
|
||||
return r.changes > 0 ? { code: 1, message: 'OK' } : { code: 500, message: '注册失败' }
|
||||
})
|
||||
|
||||
s.register({ method: 'POST', path: '/login', verifies, requires: ['id', 'password'] }, ({ args, session }) => {
|
||||
// 读取用户信息
|
||||
let userInfo = db.query1('SELECT `name`,`salt`,`password` FROM User WHERE `id` =?', args.id).result
|
||||
if (!userInfo) return { code: 401, message: '用户或密码验证失败' }
|
||||
|
||||
// 验证密码
|
||||
let password = u.hex(u.sha256(u.unHex(args.password), userInfo.salt))
|
||||
if (password !== userInfo.password) return { code: 401, message: '用户或密码验证失败' }
|
||||
|
||||
// 登录成功,设置session
|
||||
session.set('id', args.id)
|
||||
session.set('name', userInfo.name)
|
||||
session.setAuthLevel(1) // 设置权限等级,其他权限等级为1的接口必须登录成功后才能访问
|
||||
session.save() // 保存session
|
||||
|
||||
return { code: 1, message: 'OK' }
|
||||
})
|
||||
|
||||
s.register({ method: 'GET', path: '/userInfo', authLevel: 1 }, ({ session }) => {
|
||||
// 返回用户信息
|
||||
return { code: 1, message: 'OK', data: session.get('id', 'name') }
|
||||
})
|
||||
}
|
34
apigo.yml
Normal file
34
apigo.yml
Normal file
@ -0,0 +1,34 @@
|
||||
name:
|
||||
version: v0.0.1
|
||||
main: main.js
|
||||
target:
|
||||
darwin: amd64 arm64
|
||||
linux: amd64 arm64
|
||||
windows: amd64
|
||||
module:
|
||||
apigo.cc/gojs/console: latest
|
||||
apigo.cc/gojs/util: latest
|
||||
apigo.cc/gojs/log: latest
|
||||
apigo.cc/gojs/file: latest
|
||||
apigo.cc/gojs/http: latest
|
||||
apigo.cc/gojs/db: latest
|
||||
apigo.cc/gojs/service: latest
|
||||
modulealias:
|
||||
extraimport:
|
||||
github.com/go-sql-driver/mysql: latest
|
||||
modernc.org/sqlite: latest
|
||||
cachefile:
|
||||
- api
|
||||
- lib
|
||||
- www
|
||||
sskey:
|
||||
cgoenable: false
|
||||
buildfrom: golang
|
||||
buildenv:
|
||||
linux:
|
||||
darwin:
|
||||
windows:
|
||||
buildldflags:
|
||||
linux:
|
||||
darwin:
|
||||
windows:
|
5
lib/verifies.js
Normal file
5
lib/verifies.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
id: /^\w{3,20}$/,
|
||||
password: /^[a-z0-9]{64}$/,
|
||||
name: /^[a-zA-Z0-9_\-\u4e00-\u9fff]{4,100}$/u,
|
||||
}
|
22
main.js
Normal file
22
main.js
Normal file
@ -0,0 +1,22 @@
|
||||
import s from 'service'
|
||||
import db from 'db'
|
||||
|
||||
function main() {
|
||||
// 初始化数据库
|
||||
db.make(`
|
||||
User
|
||||
id v20 PK
|
||||
password c64
|
||||
salt c20
|
||||
name v100
|
||||
`)
|
||||
|
||||
s.config({
|
||||
verifyFieldMessage: '参数验证失败:{{FAILED_FIELDS}}'
|
||||
})
|
||||
// 注册服务
|
||||
s.load('api/user.js', { min: 10, max: 100, idle: 20 })
|
||||
|
||||
// 启动服务
|
||||
s.start()
|
||||
}
|
72
main_test.js
Normal file
72
main_test.js
Normal file
@ -0,0 +1,72 @@
|
||||
import http from 'http'
|
||||
import u from 'util'
|
||||
import file from 'file'
|
||||
|
||||
let bakDB = false
|
||||
|
||||
// 用于测试的http客户端,设置默认URL前缀方便后续调用
|
||||
let hc = http.new({ baseURL: 'http://localhost:8080', timeout: 1000 })
|
||||
|
||||
// 测试开始前,启动服务
|
||||
function onStart() {
|
||||
// 备份数据库文件
|
||||
bakDB = file.exists('user.db')
|
||||
if (bakDB) file.rename('user.db', 'user.db.bak')
|
||||
// 启动服务
|
||||
u.shell(__startExec, 'start')
|
||||
// 等待服务启动
|
||||
u.sleep(100)
|
||||
}
|
||||
|
||||
// 测试结束后,停止服务
|
||||
function onStop() {
|
||||
// 停止服务
|
||||
u.shell(__startExec, 'stop')
|
||||
// 恢复数据库文件
|
||||
file.remove('user.db')
|
||||
if (bakDB) file.rename('user.db.bak', 'user.db')
|
||||
}
|
||||
|
||||
function testNotLoggedIn() {
|
||||
// 未登录,应该返回403
|
||||
let r = hc.get('/userInfo')
|
||||
return r.statusCode === 403 || r.status + ' ' + r.string()
|
||||
}
|
||||
|
||||
function testBadUserId() {
|
||||
// 注册时传入错误的用户ID,应该返回400
|
||||
let r = hc.post('/register', { id: 'test.User', password: u.hex(u.sha256('123456')), name: '测试用户' })
|
||||
return r.statusCode === 400 || r.status + ' ' + r.string()
|
||||
}
|
||||
|
||||
function testRegister() {
|
||||
// 注册一个新用户,,code应该返回1
|
||||
let r = hc.post('/register', { id: 'testUser', password: u.hex(u.sha256('123456')), name: '测试用户' })
|
||||
if (r.statusCode !== 200) return r.status + ' ' + r.string()
|
||||
let o = r.object()
|
||||
return o.code === 1 || o
|
||||
}
|
||||
|
||||
function testLoginWithBadPassword() {
|
||||
// 登录时传入错误的密码,code应该返回401
|
||||
let r = hc.post('/login', { id: 'testUser', password: u.hex(u.sha256('1234567')) })
|
||||
if (r.statusCode !== 200) return r.status + ' ' + r.string()
|
||||
let o = r.object()
|
||||
return o.code === 401 || o
|
||||
}
|
||||
|
||||
function testLogin() {
|
||||
// 登录,code应该返回1
|
||||
let r = hc.post('/login', { id: 'testUser', password: u.hex(u.sha256('123456')) })
|
||||
if (r.statusCode !== 200) return r.status + ' ' + r.string()
|
||||
let o = r.object()
|
||||
return o.code === 1 || o
|
||||
}
|
||||
|
||||
function testGetUserInfo() {
|
||||
// 获取用户信息,code应该返回1,id和name应该正确
|
||||
let r = hc.get('/userInfo')
|
||||
if (r.statusCode !== 200) return r.status + ' ' + r.string()
|
||||
let o = r.object()
|
||||
return o.code === 1 && o.data.id === 'testUser' && o.data.name === '测试用户' || o
|
||||
}
|
15
service.yml
Normal file
15
service.yml
Normal file
@ -0,0 +1,15 @@
|
||||
listen: 8080 # 监听端口
|
||||
ssl: # 设置SSL证书
|
||||
# ____:
|
||||
# certFile:
|
||||
# keyFile:
|
||||
app: '' # 指定应用名称将自动注册为服务,需要配置 registry
|
||||
registry: '' # 服务发现注册中心,请配置一个 redis://:password@127.0.0.1:6379/15
|
||||
accessTokens: # 设置访问令牌,对应的token将获得对应的权限等级
|
||||
# ___: 1
|
||||
calls: # 配置将要调用的服务和访问时使用的令牌
|
||||
# ___: '___'
|
||||
userIdKey: 'id' # 设置存储在Session中的用户ID字段,会将用户ID记录在日志中
|
||||
static: # 设置静态文件目录
|
||||
# '/': 'www/'
|
||||
verifyFieldMessage: 参数验证失败:{{FAILED_FIELDS}}
|
17
www/index.html
Normal file
17
www/index.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>
|
||||
Hello World
|
||||
</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>
|
||||
Hello World
|
||||
</h1>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user