From e3ed6541979175a3be0b8dc6b71965d7fe82f06d Mon Sep 17 00:00:00 2001 From: "huoyong.msb" Date: Wed, 21 Aug 2019 11:19:18 +0800 Subject: [PATCH] daily update, for more details, please ref to github release page --- docker-compose.yml | 1 - src/routes/account.ts | 15 +++++++++-- src/routes/analytics.ts | 9 ++++--- src/routes/base.ts | 15 +++++++++++ src/routes/organization.ts | 55 +++++++++++++++++++++----------------- src/routes/postman.ts | 5 ++++ src/routes/utils/access.ts | 23 +++++++++++++++- 7 files changed, 90 insertions(+), 33 deletions(-) create mode 100644 src/routes/base.ts diff --git a/docker-compose.yml b/docker-compose.yml index c485e74..6e04484 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,6 @@ services: # build from ./Dockerfile # build: . # build from images - # you can find last tag from https://hub.docker.com/r/blackdog1987/rap2-delos image: blackdog1987/rap2-delos:2.6.aa3be03 environment: # if you have your own mysql, config it here, and disable the 'mysql' config blow diff --git a/src/routes/account.ts b/src/routes/account.ts index a321df4..336ca16 100644 --- a/src/routes/account.ts +++ b/src/routes/account.ts @@ -7,6 +7,9 @@ import { QueryInclude } from '../models' import { Op } from 'sequelize' import MailService from '../service/mail' import * as md5 from 'md5' +import { isLoggedIn } from './base' +import { AccessUtils } from './utils/access' +import { COMMON_ERROR_RES } from './utils/const' @@ -36,7 +39,11 @@ router.get('/account/count', async (ctx) => { } }) -router.get('/account/list', async (ctx) => { +router.get('/account/list', isLoggedIn, async (ctx) => { + if (!AccessUtils.isAdmin(ctx.session.id)) { + ctx.body = COMMON_ERROR_RES.ACCESS_DENY + return + } let where = {} let { name } = ctx.query if (name) { @@ -172,7 +179,11 @@ router.post('/account/update', async (ctx) => { } }) -router.get('/account/remove', async (ctx) => { +router.get('/account/remove', isLoggedIn, async (ctx) => { + if (!AccessUtils.isAdmin(ctx.session.id)) { + ctx.body = COMMON_ERROR_RES.ACCESS_DENY + return + } if (process.env.TEST_MODE === 'true') { ctx.body = { data: await User.destroy({ diff --git a/src/routes/analytics.ts b/src/routes/analytics.ts index 36cc372..407ec2b 100644 --- a/src/routes/analytics.ts +++ b/src/routes/analytics.ts @@ -6,10 +6,11 @@ const moment = require('moment') const Sequelize = require('sequelize') const SELECT = { type: Sequelize.QueryTypes.SELECT } import sequelize from '../models/sequelize' +import { isLoggedIn } from './base' const YYYY_MM_DD = 'YYYY-MM-DD' // 最近 30 天新建仓库数 -router.get('/app/analytics/repositories/created', async (ctx) => { +router.get('/app/analytics/repositories/created', isLoggedIn, async (ctx) => { let start = moment().startOf('day').subtract(30, 'days').format(YYYY_MM_DD) let end = moment().startOf('day').format(YYYY_MM_DD) let sql = ` @@ -34,7 +35,7 @@ router.get('/app/analytics/repositories/created', async (ctx) => { }) // 最近 30 天活跃仓库数 -router.get('/app/analytics/repositories/updated', async (ctx) => { +router.get('/app/analytics/repositories/updated', isLoggedIn, async (ctx) => { let start = moment().startOf('day').subtract(30, 'days').format(YYYY_MM_DD) let end = moment().startOf('day').format(YYYY_MM_DD) let sql = ` @@ -59,7 +60,7 @@ router.get('/app/analytics/repositories/updated', async (ctx) => { }) // 最近 30 天活跃用户 -router.get('/app/analytics/users/activation', async (ctx) => { +router.get('/app/analytics/users/activation', isLoggedIn, async (ctx) => { let start = moment().startOf('day').subtract(30, 'days').format(YYYY_MM_DD) let end = moment().startOf('day').format(YYYY_MM_DD) let sql = ` @@ -84,7 +85,7 @@ router.get('/app/analytics/users/activation', async (ctx) => { }) // 最近 30 天活跃仓库 -router.get('/app/analytics/repositories/activation', async (ctx) => { +router.get('/app/analytics/repositories/activation', isLoggedIn, async (ctx) => { let start = moment().startOf('day').subtract(30, 'days').format(YYYY_MM_DD) let end = moment().startOf('day').format(YYYY_MM_DD) let sql = ` diff --git a/src/routes/base.ts b/src/routes/base.ts new file mode 100644 index 0000000..64fca54 --- /dev/null +++ b/src/routes/base.ts @@ -0,0 +1,15 @@ +import * as _ from 'lodash' +import { ParameterizedContext } from 'koa' +const inTestMode = process.env.TEST_MODE === 'true' + + +export async function isLoggedIn(ctx: ParameterizedContext, next: () => Promise) { + if (!inTestMode && (!ctx.session || !ctx.session.id)) { + ctx.body = { + isOk: false, + errMsg: 'need login', + } + } else { + await next() + } +} \ No newline at end of file diff --git a/src/routes/organization.ts b/src/routes/organization.ts index 9cbd785..59bbefc 100644 --- a/src/routes/organization.ts +++ b/src/routes/organization.ts @@ -5,6 +5,9 @@ import * as _ from 'lodash' import Pagination from './utils/pagination' import OrganizationService from '../service/organization' import { Op, FindOptions } from 'sequelize' +import { isLoggedIn } from './base' +import { AccessUtils, ACCESS_TYPE } from './utils/access' +import { COMMON_ERROR_RES } from './utils/const' router.get('/app/get', async (ctx, next) => { let data: any = {} @@ -56,16 +59,7 @@ router.get('/organization/list', async (ctx) => { pagination, } }) -router.get('/organization/owned', async (ctx) => { - if (!ctx.session.id) { - ctx.body = { - data: { - isOk: false, - errMsg: 'not login' - } - } - return - } +router.get('/organization/owned', isLoggedIn, async (ctx) => { let where = {} let { name } = ctx.query if (name) { @@ -90,16 +84,7 @@ router.get('/organization/owned', async (ctx) => { pagination: undefined, } }) -router.get('/organization/joined', async (ctx) => { - if (!ctx.session.id) { - ctx.body = { - data: { - isOk: false, - errMsg: 'not login' - } - } - return - } +router.get('/organization/joined', isLoggedIn, async (ctx) => { let where = {} let { name } = ctx.query if (name) { @@ -127,7 +112,12 @@ router.get('/organization/joined', async (ctx) => { } }) router.get('/organization/get', async (ctx) => { - let organization = await Organization.findByPk(ctx.query.id, { + const organizationId = +ctx.query.id + if (!await AccessUtils.canUserAccess(ACCESS_TYPE.ORGANIZATION, ctx.session.id, organizationId)) { + ctx.body = COMMON_ERROR_RES.ACCESS_DENY + return + } + const organization = await Organization.findByPk(ctx.query.id, { attributes: { exclude: [] }, include: [QueryInclude.Creator, QueryInclude.Owner, QueryInclude.Members], } as any) @@ -135,7 +125,7 @@ router.get('/organization/get', async (ctx) => { data: organization, } }) -router.post('/organization/create', async (ctx) => { +router.post('/organization/create', isLoggedIn, async (ctx) => { let creatorId = ctx.session.id let body = Object.assign({}, ctx.request.body, { creatorId, ownerId: creatorId }) let created = await Organization.create(body) @@ -151,8 +141,13 @@ router.post('/organization/create', async (ctx) => { data: filled, } }) -router.post('/organization/update', async (ctx, next) => { +router.post('/organization/update', isLoggedIn, async (ctx, next) => { let body = Object.assign({}, ctx.request.body) + const organizationId = +body.id + if (!await AccessUtils.canUserAccess(ACCESS_TYPE.ORGANIZATION, ctx.session.id, organizationId)) { + ctx.body = COMMON_ERROR_RES.ACCESS_DENY + return + } delete body.creatorId // DONE 2.2 支持转移团队 // delete body.ownerId @@ -190,16 +185,26 @@ router.post('/organization/update', async (ctx, next) => { await Logger.create({ creatorId, userId, type: 'exit', organizationId: id }) } }) -router.post('/organization/transfer', async (ctx) => { +router.post('/organization/transfer', isLoggedIn, async (ctx) => { let { id, ownerId } = ctx.request.body + const organizationId = +id + if (!await AccessUtils.canUserAccess(ACCESS_TYPE.ORGANIZATION, ctx.session.id, organizationId)) { + ctx.body = COMMON_ERROR_RES.ACCESS_DENY + return + } let body = { ownerId } let result = await Organization.update(body, { where: { id } }) ctx.body = { data: result[0], } }) -router.get('/organization/remove', async (ctx, next) => { +router.get('/organization/remove', isLoggedIn, async (ctx, next) => { let { id } = ctx.query + const organizationId = +id + if (!await AccessUtils.canUserAccess(ACCESS_TYPE.ORGANIZATION, ctx.session.id, organizationId)) { + ctx.body = COMMON_ERROR_RES.ACCESS_DENY + return + } let result = await Organization.destroy({ where: { id } }) let repositories = await Repository.findAll({ where: { organizationId: id }, diff --git a/src/routes/postman.ts b/src/routes/postman.ts index 3d342c6..99dc852 100644 --- a/src/routes/postman.ts +++ b/src/routes/postman.ts @@ -1,9 +1,14 @@ import router from './router' import { COMMON_ERROR_RES } from './utils/const' import PostmanService from '../service/postman' +import { AccessUtils, ACCESS_TYPE } from './utils/access' router.get('/postman/export', async (ctx) => { const repoId = +ctx.query.id + if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, repoId)) { + ctx.body = COMMON_ERROR_RES.ACCESS_DENY + return + } if (!(repoId > 0)) { ctx.data = COMMON_ERROR_RES.ERROR_PARAMS } diff --git a/src/routes/utils/access.ts b/src/routes/utils/access.ts index 4ef2a6a..b18f65c 100644 --- a/src/routes/utils/access.ts +++ b/src/routes/utils/access.ts @@ -1,15 +1,36 @@ import OrganizationService from '../../service/organization' import RepositoryService from '../../service/repository' +import { Module, Interface, Property } from '../../models' -export enum ACCESS_TYPE { ORGANIZATION, REPOSITORY, USER } +export enum ACCESS_TYPE { ORGANIZATION, REPOSITORY, MODULE, INTERFACE, PROPERTY, USER, ADMIN } +const inTestMode = process.env.TEST_MODE === 'true' export class AccessUtils { public static async canUserAccess(accessType: ACCESS_TYPE, curUserId: number, entityId: number): Promise { + if (inTestMode) { + return true + } if (accessType === ACCESS_TYPE.ORGANIZATION) { return await OrganizationService.canUserAccessOrganization(curUserId, entityId) } else if (accessType === ACCESS_TYPE.REPOSITORY) { return await RepositoryService.canUserAccessRepository(curUserId, entityId) + } else if (accessType === ACCESS_TYPE.MODULE) { + const mod = await Module.findByPk(entityId) + return await RepositoryService.canUserAccessRepository(curUserId, mod.repositoryId) + } else if (accessType === ACCESS_TYPE.INTERFACE) { + const itf = await Interface.findByPk(entityId) + return await RepositoryService.canUserAccessRepository(curUserId, itf.repositoryId) + } else if (accessType === ACCESS_TYPE.PROPERTY) { + const p = await Property.findByPk(entityId) + return await RepositoryService.canUserAccessRepository(curUserId, p.repositoryId) } return false } + + public static isAdmin(curUserId: number) { + if (inTestMode) { + return true + } + return curUserId === 1 + } } \ No newline at end of file