Skip to content

Commit

Permalink
[Feature] 新增暂停功能以及多表字段升级 (#434)
Browse files Browse the repository at this point in the history
* feat:新增暂停功能  (#416)

* feat:新增暂停功能

* feat: 修改状态相关功能 (#433)

Co-authored-by: luchunhui <[email protected]>

* fix: 修改刷数据逻辑错误和环境变量问题

* fix: 解决lint问题

---------

Co-authored-by: chaorenluo <[email protected]>
Co-authored-by: luchunhui <[email protected]>
  • Loading branch information
3 people authored Sep 27, 2024
1 parent 054095e commit 351f18f
Show file tree
Hide file tree
Showing 110 changed files with 1,287 additions and 525 deletions.
22 changes: 22 additions & 0 deletions DATA_COLLECTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Important Disclosure re:XIAOJUSURVEY Data Collection

XIAOJUSURVEY is open-source software developed and maintained by XIAOJUSURVEY Team and available at https://github.com/didi/xiaoju-survey.
We hereby state the purpose and reason for collecting data.

## Purpose of data collection

Data collected is used to help improve XIAOJUSURVEY for all users. It is important that our team understands the usage patterns as soon as possible, so we can best decide how to design future features and prioritize current work.

## Types of data collected

XIAOJUSURVEY just collects data about version's information. The data collected is subsequently reported to the XIAOJUSURVEY's backend services.

All data collected will be used exclusively by the XIAOJUSURVEY team for analytical purposes only. The data will be neither accessible nor sold to any third party.

## Sensitive data

XIAOJUSURVEY will never collect and/or report sensitive information, such as private keys, API keys, or passwords.

## How do I opt-in to or opt-out of data sharing?

See [docs](https://xiaojusurvey.didi.cn/docs/next/community/%E6%95%B0%E6%8D%AE%E4%B8%8A%E6%8A%A5%E5%A3%B0%E6%98%8E) for information on configuring this functionality.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,4 @@ _任何问题和合作可以联系小助手。_

## CHANGELOG

关注重大项目变更:[MAJOR CHANGELOG](https://github.com/didi/xiaoju-survey/issues/48)
关注重大项目变更:[MAJOR CHANGELOG](https://github.com/didi/xiaoju-survey/issues/48)
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ services:
- xiaoju-survey

xiaoju-survey:
image: "xiaojusurvey/xiaoju-survey:1.1.6-slim" # 最新版本:https://hub.docker.com/r/xiaojusurvey/xiaoju-survey/tags
image: "xiaojusurvey/xiaoju-survey:1.2.0-slim" # 最新版本:https://hub.docker.com/r/xiaojusurvey/xiaoju-survey/tags
container_name: xiaoju-survey
restart: always
ports:
Expand Down
2 changes: 1 addition & 1 deletion server/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
XIAOJU_SURVEY_MONGO_DB_NAME=xiaojuSurvey
XIAOJU_SURVEY_MONGO_URL=mongodb://127.0.0.1:27017
XIAOJU_SURVEY_MONGO_URL=
XIAOJU_SURVEY_MONGO_AUTH_SOURCE=admin

XIAOJU_SURVEY_REDIS_HOST=
Expand Down
20 changes: 20 additions & 0 deletions server/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
XIAOJU_SURVEY_MONGO_DB_NAME=xiaojuSurvey
XIAOJU_SURVEY_MONGO_URL=mongodb://127.0.0.1:27017
XIAOJU_SURVEY_MONGO_AUTH_SOURCE=admin

XIAOJU_SURVEY_REDIS_HOST=
XIAOJU_SURVEY_REDIS_PORT=
XIAOJU_SURVEY_REDIS_USERNAME=
XIAOJU_SURVEY_REDIS_PASSWORD=
XIAOJU_SURVEY_REDIS_DB=


XIAOJU_SURVEY_RESPONSE_AES_ENCRYPT_SECRET_KEY=dataAesEncryptSecretKey
XIAOJU_SURVEY_HTTP_DATA_ENCRYPT_TYPE=rsa

XIAOJU_SURVEY_JWT_SECRET=xiaojuSurveyJwtSecret
XIAOJU_SURVEY_JWT_EXPIRES_IN=8h

XIAOJU_SURVEY_LOGGER_FILENAME=./logs/app.log

XIAOJU_SURVEY_REPORT=true
9 changes: 5 additions & 4 deletions server/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "server",
"version": "0.0.1",
"description": "",
"name": "xiaoju-survey-server",
"version": "1.3.0",
"description": "XIAOJUSURVEY的server端",
"author": "",
"scripts": {
"build": "nest build",
Expand All @@ -22,6 +22,7 @@
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.0.0",
"@nestjs/microservices": "^10.4.4",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/serve-static": "^4.0.0",
"@nestjs/swagger": "^7.3.0",
Expand Down Expand Up @@ -75,7 +76,7 @@
"prettier": "^3.0.0",
"redis-memory-server": "^0.11.0",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"supertest": "^7.0.0",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
Expand Down
62 changes: 62 additions & 0 deletions server/scripts/run-report.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import fs, { promises as fsa } from 'fs-extra';
import path from 'path';
import fetch from 'node-fetch';

interface PackageJson {
type?: string;
name?: string;
version?: string;
description?: string;
id?: string;
msg?: string;
}

const getId = () => {
const id = new Date().getTime().toString();
process.env.XIAOJU_SURVEY_REPORT_ID = id;

return id;
};

const readData = async (directory: string): Promise<PackageJson | null> => {
const packageJsonPath = path.join(directory, 'package.json');
const id = process.env.XIAOJU_SURVEY_REPORT_ID || getId();
try {
if (!fs.existsSync(directory)) {
return {
type: 'server',
name: '',
version: '',
description: '',
id,
msg: '文件不存在',
};
}
const data = await fsa.readFile(packageJsonPath, 'utf8').catch((e) => e);
const { name, version, description } = JSON.parse(data) as PackageJson;
return { type: 'server', name, version, description, id };
} catch (error) {
return error;
}
};

(async (): Promise<void> => {
if (
process.env.NODE_ENV === 'development' &&
!process.env.XIAOJU_SURVEY_REPORT
) {
return;
}

const res = await readData(path.join(process.cwd()));

// 上报
fetch('https://xiaojusurveysrc.didi.cn/reportSourceData', {
method: 'POST',
headers: {
Accept: 'application/json, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify(res),
}).catch(() => {});
})();
11 changes: 8 additions & 3 deletions server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { AuthModule } from './modules/auth/auth.module';
import { MessageModule } from './modules/message/message.module';
import { FileModule } from './modules/file/file.module';
import { WorkspaceModule } from './modules/workspace/workspace.module';
import { UpgradeModule } from './modules/upgrade/upgrade.module';

import { join } from 'path';

Expand All @@ -35,18 +36,21 @@ import { MessagePushingLog } from './models/messagePushingLog.entity';
import { WorkspaceMember } from './models/workspaceMember.entity';
import { Workspace } from './models/workspace.entity';
import { Collaborator } from './models/collaborator.entity';
import { DownloadTask } from './models/downloadTask.entity';
import { Session } from './models/session.entity';

import { LoggerProvider } from './logger/logger.provider';
import { PluginManagerProvider } from './securityPlugin/pluginManager.provider';
import { LogRequestMiddleware } from './middlewares/logRequest.middleware';
import { PluginManager } from './securityPlugin/pluginManager';
import { Logger } from './logger';
import { DownloadTask } from './models/downloadTask.entity';
import { Session } from './models/session.entity';

@Module({
imports: [
ConfigModule.forRoot({}),
ConfigModule.forRoot({
envFilePath: `.env.${process.env.NODE_ENV}`, // 根据 NODE_ENV 动态加载对应的 .env 文件
isGlobal: true, // 使配置模块在应用的任何地方可用
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
Expand Down Expand Up @@ -104,6 +108,7 @@ import { Session } from './models/session.entity';
MessageModule,
FileModule,
WorkspaceModule,
UpgradeModule,
],
controllers: [AppController],
providers: [
Expand Down
6 changes: 6 additions & 0 deletions server/src/enums/downloadTaskStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum DOWNLOAD_TASK_STATUS {
WAITING = 'waiting', // 排队中
COMPUTING = 'computing', // 计算中
SUCCEED = 'succeed', // 导出成功
FAILED = 'failed', // 导出失败
}
1 change: 1 addition & 0 deletions server/src/enums/exceptionCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export enum EXCEPTION_CODE {
RESPONSE_OVER_LIMIT = 9003, // 超出限制
RESPONSE_SCHEMA_REMOVED = 9004, // 问卷已删除
RESPONSE_DATA_DECRYPT_ERROR = 9005, // 问卷已删除
RESPONSE_PAUSING = 9006, // 问卷已暂停

UPLOAD_FILE_ERROR = 5001, // 上传文件错误
}
15 changes: 8 additions & 7 deletions server/src/enums/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// 状态类型
export enum RECORD_STATUS {
NEW = 'new', // 新建
NEW = 'new', // 新建 | 未发布
PUBLISHED = 'published', // 发布
EDITING = 'editing', // 编辑
FINISHED = 'finished', // 已结束
REMOVED = 'removed',
}

export const enum RECORD_SUB_STATUS {
DEFAULT = '', // 默认
PAUSING = 'pausing', // 暂停
PUBLISHED = 'published', // 发布
REMOVED = 'removed', // 删除
FORCE_REMOVED = 'forceRemoved', // 从回收站删除
COMPUTING = 'computing', // 计算中
FINISHED = 'finished', // 已完成
ERROR = 'error', // 错误
}

// 历史类型
Expand Down
4 changes: 4 additions & 0 deletions server/src/enums/surveySessionStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum SESSION_STATUS {
ACTIVATED = 'activated',
DEACTIVATED = 'deactivated',
}
1 change: 1 addition & 0 deletions server/src/guards/session.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class SessionGuard implements CanActivate {
}
const sessionInfo = await this.sessionService.findOne(sessionId);
request.sessionInfo = sessionInfo;
request.surveyId = sessionInfo.surveyId;
return true;
}
}
2 changes: 1 addition & 1 deletion server/src/interfaces/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export enum MemberType {
}

export interface BaseConf {
begTime: string;
beginTime: string;
endTime: string;
answerBegTime: string;
answerEndTime: string;
Expand Down
15 changes: 8 additions & 7 deletions server/src/logger/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import * as log4js from 'log4js';
import moment from 'moment';
import { Injectable, Scope } from '@nestjs/common';
import { Injectable, Scope, Inject } from '@nestjs/common';
import { CONTEXT, RequestContext } from '@nestjs/microservices';

const log4jsLogger = log4js.getLogger();

@Injectable({ scope: Scope.REQUEST })
export class Logger {
private static inited = false;
private traceId: string;

constructor(@Inject(CONTEXT) private readonly ctx: RequestContext) {}

static init(config: { filename: string }) {
if (Logger.inited) {
Expand Down Expand Up @@ -37,16 +40,14 @@ export class Logger {
const datetime = moment().format('YYYY-MM-DD HH:mm:ss.SSS');
const level = options?.level;
const dltag = options?.dltag ? `${options.dltag}||` : '';
const traceIdStr = this.traceId ? `traceid=${this.traceId}||` : '';
const traceIdStr = this.ctx?.['traceId']
? `traceid=${this.ctx?.['traceId']}||`
: '';
return log4jsLogger[level](
`[${datetime}][${level.toUpperCase()}]${dltag}${traceIdStr}${message}`,
);
}

setTraceId(traceId: string) {
this.traceId = traceId;
}

info(message, options?: { dltag?: string }) {
return this._log(message, { ...options, level: 'info' });
}
Expand Down
4 changes: 3 additions & 1 deletion server/src/logger/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export const genTraceId = ({ ip }) => {
} else {
ipArr = ip
.split('.')
.map((item) => parseInt(item).toString(16).padStart(2, '0'));
.map((item) =>
item ? parseInt(item).toString(16).padStart(2, '0') : '',
);
}

return `${ipArr.join('')}${Date.now().toString()}${getCountStr()}${process.pid.toString().slice(-5)}`;
Expand Down
1 change: 1 addition & 0 deletions server/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import 'scripts/run-report';

async function bootstrap() {
const PORT = process.env.PORT || 3000;
Expand Down
2 changes: 1 addition & 1 deletion server/src/middlewares/logRequest.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class LogRequestMiddleware implements NestMiddleware {
const userAgent = req.get('user-agent') || '';
const startTime = Date.now();
const traceId = genTraceId({ ip });
this.logger.setTraceId(traceId);
req['traceId'] = traceId;
const query = JSON.stringify(req.query);
const body = JSON.stringify(req.body);
this.logger.info(
Expand Down
40 changes: 5 additions & 35 deletions server/src/models/base.entity.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,13 @@
import { Column, ObjectIdColumn, BeforeInsert, BeforeUpdate } from 'typeorm';
import { ObjectIdColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';
import { ObjectId } from 'mongodb';
import { RECORD_STATUS } from '../enums';

export class BaseEntity {
@ObjectIdColumn()
_id: ObjectId;

@Column()
curStatus: {
status: RECORD_STATUS;
date: number;
};
@CreateDateColumn({ type: 'timestamp', precision: 3 })
createdAt: Date;

@Column()
statusList: Array<{
status: RECORD_STATUS;
date: number;
}>;

@Column()
createDate: number;

@Column()
updateDate: number;

@BeforeInsert()
initDefaultInfo() {
const now = Date.now();
if (!this.curStatus) {
const curStatus = { status: RECORD_STATUS.NEW, date: now };
this.curStatus = curStatus;
this.statusList = [curStatus];
}
this.createDate = now;
this.updateDate = now;
}

@BeforeUpdate()
onUpdate() {
this.updateDate = Date.now();
}
@UpdateDateColumn({ type: 'timestamp', precision: 3 })
updatedAt: Date;
}
12 changes: 12 additions & 0 deletions server/src/models/collaborator.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,16 @@ export class Collaborator extends BaseEntity {

@Column('jsonb')
permissions: Array<string>;

@Column()
creator: string;

@Column()
creatorId: string;

@Column()
operator: string;

@Column()
operatorId: string;
}
Loading

0 comments on commit 351f18f

Please sign in to comment.