-
-
Notifications
You must be signed in to change notification settings - Fork 671
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(system-server): add account apis;
- Loading branch information
Showing
32 changed files
with
1,595 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,5 +59,10 @@ | |
"sys_admin": "laf-sys", | ||
"sys_password": "laf-sys" | ||
} | ||
} | ||
}, | ||
"cSpell.words": [ | ||
"appid", | ||
"signin", | ||
"uids" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import * as dotenv from 'dotenv' | ||
dotenv.config() | ||
|
||
/** | ||
* Configuration Collection | ||
*/ | ||
export default class Config { | ||
/** | ||
* the mongodb connection configuration of sys db | ||
*/ | ||
static get sys_db() { | ||
if (!process.env['SYS_DB']) { | ||
throw new Error('env: `SYS_DB` is missing') | ||
} | ||
|
||
if (!process.env['SYS_DB_URI']) { | ||
throw new Error('env: `SYS_DB_URI` is missing') | ||
} | ||
|
||
return { | ||
database: process.env['SYS_DB'], | ||
uri: process.env['SYS_DB_URI'], | ||
poolSize: (process.env['SYS_DB_POOL_LIMIT'] ?? 10) as number, | ||
} | ||
} | ||
|
||
/** | ||
* the devops server secret salt, mainly used for generating devops tokens | ||
*/ | ||
static get SYS_SERVER_SECRET_SALT(): string { | ||
const secret_salt = process.env['SYS_SERVER_SECRET_SALT'] | ||
if (!secret_salt) { | ||
throw new Error('env: `SYS_SERVER_SECRET_SALT` is missing') | ||
} | ||
return secret_salt | ||
} | ||
|
||
/** | ||
* the logger level : 'fatal', 'error', 'warning', 'info', 'debug', 'trace' | ||
*/ | ||
static get LOG_LEVEL(): string { | ||
return process.env['LOG_LEVEL'] ?? (this.isProd ? 'info' : 'debug') | ||
} | ||
|
||
/** | ||
* the serving port, default is 9000 | ||
*/ | ||
static get PORT(): number { | ||
return (process.env.PORT ?? 9000) as number | ||
} | ||
|
||
/** | ||
* the expiration duration time of devops server token, default is 24 hours (units in hour) | ||
*/ | ||
static get TOKEN_EXPIRED_TIME(): number { | ||
return (process.env.TOKEN_EXPIRED_TIME ?? 24) as number | ||
} | ||
|
||
/** | ||
* in production deploy or not | ||
*/ | ||
static get isProd(): boolean { | ||
return process.env.NODE_ENV === 'production' | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* @Author: Maslow<wangfugen@126.com> | ||
* @Date: 2021-07-30 10:30:29 | ||
* @LastEditTime: 2021-08-28 22:53:24 | ||
* @Description: | ||
*/ | ||
|
||
import { Request, Response } from 'express' | ||
import { hashPassword } from '../../lib/utils/hash' | ||
import { DatabaseAgent } from '../../lib/db-agent' | ||
import { Constants } from '../../constants' | ||
|
||
|
||
/** | ||
* The handler of editing account | ||
*/ | ||
export async function handleEdit(req: Request, res: Response) { | ||
const uid = req['auth']?.uid | ||
const db = DatabaseAgent.sys_db | ||
|
||
// check if params valid | ||
const { password, avatar, name, roles } = req.body | ||
if (!uid) { | ||
return res.status(401) | ||
} | ||
|
||
// check if uid valid | ||
const { data: account } = await db.collection(Constants.cn.accounts) | ||
.where({ _id: uid }) | ||
.getOne() | ||
|
||
if (!account) { | ||
return res.status(422).send('account not found') | ||
} | ||
|
||
// check if roles are valid | ||
const { total: valid_count } = await db.collection(Constants.cn.roles) | ||
.where({ name: db.command.in(roles) }) | ||
.count() | ||
|
||
if (valid_count !== roles.length) { | ||
return res.status(422).send('invalid roles') | ||
} | ||
|
||
// update account | ||
const data = { | ||
updated_at: Date.now() | ||
} | ||
|
||
// update password if provided | ||
if (password) { | ||
data['password'] = hashPassword(password) | ||
} | ||
|
||
// update avatar if provided | ||
if (avatar && avatar != account.avatar) { | ||
data['avatar'] = avatar | ||
} | ||
|
||
// update name if provided | ||
if (name && name != account.name) { | ||
data['name'] = name | ||
} | ||
|
||
// update roles if provided | ||
if (roles) { | ||
data['roles'] = roles | ||
} | ||
|
||
const r = await db.collection(Constants.cn.accounts) | ||
.where({ _id: uid }) | ||
.update(data) | ||
|
||
return res.send({ | ||
code: 0, | ||
data: { | ||
...r, | ||
uid | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* @Author: Maslow<wangfugen@126.com> | ||
* @Date: 2021-07-30 10:30:29 | ||
* @LastEditTime: 2021-08-29 11:33:26 | ||
* @Description: | ||
*/ | ||
|
||
import { Router } from 'express' | ||
import { handleEdit } from './edit' | ||
import { handleProfile } from './profile' | ||
import { handleSignIn } from './signin' | ||
import { handleSignUp } from './signup' | ||
|
||
export const AccountRouter = Router() | ||
|
||
/** | ||
* account login | ||
*/ | ||
AccountRouter.post('/login', handleSignIn) | ||
|
||
|
||
/** | ||
* get account profile | ||
*/ | ||
AccountRouter.get('/profile', handleProfile) | ||
|
||
/** | ||
* account | ||
*/ | ||
AccountRouter.post('/signup', handleSignUp) | ||
|
||
/** | ||
* edit admin | ||
*/ | ||
AccountRouter.post('/edit', handleEdit) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* @Author: Maslow<wangfugen@126.com> | ||
* @Date: 2021-07-30 10:30:29 | ||
* @LastEditTime: 2021-08-28 22:52:21 | ||
* @Description: | ||
*/ | ||
|
||
import { Request, Response } from 'express' | ||
import { getPermissionsByAccountId } from '../../api/permission' | ||
import { DatabaseAgent } from '../../lib/db-agent' | ||
import { Constants } from '../../constants' | ||
|
||
/** | ||
* The handler of getting profile | ||
*/ | ||
export async function handleProfile(req: Request, res: Response) { | ||
const uid = req['auth']?.uid | ||
if (!uid) { | ||
return res.status(401) | ||
} | ||
|
||
const db = DatabaseAgent.sys_db | ||
|
||
const { data: account } = await db.collection(Constants.cn.accounts) | ||
.where({ _id: uid }) | ||
.getOne() | ||
|
||
if (!account) { | ||
return res.status(422).send('account not found') | ||
} | ||
|
||
const { permissions } = await getPermissionsByAccountId(account._id) | ||
|
||
return res.send({ | ||
code: 0, | ||
data: { | ||
...account, | ||
permissions | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* @Author: Maslow<wangfugen@126.com> | ||
* @Date: 2021-07-30 10:30:29 | ||
* @LastEditTime: 2021-08-30 15:25:39 | ||
* @Description: | ||
*/ | ||
|
||
import { Request, Response } from 'express' | ||
import { getToken } from '../../lib/utils/token' | ||
import { hashPassword } from '../../lib/utils/hash' | ||
import { DatabaseAgent } from '../../lib/db-agent' | ||
import Config from '../../config' | ||
import { Constants } from '../../constants' | ||
import * as assert from 'assert' | ||
|
||
/** | ||
* The handler of sign in | ||
*/ | ||
export async function handleSignIn(req: Request, res: Response) { | ||
const { username, password } = req.body | ||
|
||
const login_failed_error = { | ||
code: 1, | ||
error: 'invalid username or password' | ||
} | ||
|
||
if (!username || !password) { | ||
return res.send(login_failed_error) | ||
} | ||
const db = DatabaseAgent.sys_db | ||
const ret = await db.collection(Constants.cn.accounts) | ||
.withOne({ | ||
query: db | ||
.collection(Constants.cn.password) | ||
.where({ password: hashPassword(password), type: 'login' }), | ||
localField: '_id', | ||
foreignField: 'uid' | ||
}) | ||
.where({ username }) | ||
.merge({ intersection: true }) | ||
|
||
assert.ok(ret.ok) | ||
|
||
if (!ret.data.length) { | ||
return res.send(login_failed_error) | ||
} | ||
|
||
const account = ret.data[0] | ||
|
||
const expire = Math.floor(Date.now() / 1000) + 60 * 60 * Config.TOKEN_EXPIRED_TIME | ||
const payload = { | ||
uid: account._id, | ||
exp: expire | ||
} | ||
const access_token = getToken(payload) | ||
|
||
return res.send({ | ||
code: 0, | ||
data: { | ||
access_token, | ||
username, | ||
uid: account._id, | ||
expire | ||
} | ||
}) | ||
} |
Oops, something went wrong.