This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"imageSize": 100,
|
||||
"contributorsPerLine": 7,
|
||||
"contributorsSortAlphabetically": false,
|
||||
"skipCi": true,
|
||||
"contributors": [
|
||||
{
|
||||
"login": "phachon",
|
||||
"name": "phachon",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/19726268?v=4",
|
||||
"profile": "https://phachon.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cxgreat2014",
|
||||
"name": "cxgreat2014",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/15062548?v=4",
|
||||
"profile": "https://github.com/cxgreat2014",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cifaz",
|
||||
"name": "ccz",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/4531158?v=4",
|
||||
"profile": "https://github.com/cifaz",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ruoranw",
|
||||
"name": "Ruoran Wang",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/25990237?v=4",
|
||||
"profile": "https://www.linkedin.com/in/wangruoran/",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "eahomliu",
|
||||
"name": "eahomliu",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/50134691?v=4",
|
||||
"profile": "https://github.com/eahomliu",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"projectName": "mm-wiki",
|
||||
"projectOwner": "phachon",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
*.js linguist-language=go
|
||||
*.css linguist-language=go
|
||||
*.html linguist-language=go
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
name: Issue 模版
|
||||
about: 请尽量按照模版去创建 Issue
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
xxxxx这里是问题描述xxxx
|
||||
|
||||
1. 当前使用的版本号
|
||||
vx.x.x
|
||||
|
||||
2. 是否已经升级到新版本
|
||||
xxx
|
||||
|
||||
3. 当前遇到的问题
|
||||
xxx
|
||||
|
||||
4. 错误日志或截图
|
||||
xxx
|
||||
|
||||
5. 希望增加的功能
|
||||
xxx
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Go
|
||||
on: [push]
|
||||
jobs:
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.13
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
if [ -f Gopkg.toml ]; then
|
||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
dep ensure
|
||||
fi
|
||||
|
||||
- name: Build
|
||||
run: go build -v .
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
logs/*.log
|
||||
.DS_Store
|
||||
!.gitignore
|
||||
.gitignore___jb_tmp___
|
||||
*.exe
|
||||
*.exe~
|
||||
mm-wiki
|
||||
*.session/
|
||||
.mmwiki.sessions/
|
||||
conf/mm-wiki.conf
|
||||
mm-wiki.conf
|
||||
release/
|
||||
release-*
|
||||
data/
|
||||
install/install
|
||||
install/install.exe
|
||||
install.lock
|
||||
|
||||
.idea/
|
||||
|
||||
node_modules/
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
# 更新日志:
|
||||
|
||||
## v0.2.1(2020-09)
|
||||
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 暂时去掉全文搜索功能
|
||||
|
||||
#### 新增功能
|
||||
无
|
||||
|
||||
### 升级(Upgrade)
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压 (tar -zxvf mm-wiki-v0.2.0-linux-amd64.tar.gz)
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
4. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
|
||||
## v0.2.0(2020-06)
|
||||
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 修改文档时,文档日志不更新 #215
|
||||
2. 全文搜索重构,优化性能 #197
|
||||
3. markdown语法不规范导致保存后文字丢失 #176
|
||||
4. 修改文档备注可不填写 #184
|
||||
|
||||
#### 新增功能
|
||||
1. 系统联系人可选择现有用户和添加新用户 #80
|
||||
2. 增加 ldap 登录
|
||||
3. 允许配置系统的名称 #183
|
||||
4. 系统文案可配置 #175
|
||||
|
||||
### 升级(Upgrade)
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压 (tar -zxvf mm-wiki-v0.2.0-linux-amd64.tar.gz)
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
4. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
|
||||
## v0.1.9(2020-04)
|
||||
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 修复markdown序号问题
|
||||
|
||||
#### 新增功能
|
||||
无
|
||||
|
||||
### 升级(Upgrade)
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压 (tar -zxvf mm-wiki-v0.1.9-linux-amd64.tar.gz)
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
3. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
|
||||
## v0.1.8(2020-04)
|
||||
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 修复版本号问题
|
||||
2. 首页和登录页面自适应
|
||||
|
||||
#### 新增功能
|
||||
1. 增加在线部署网站
|
||||
2. 增加文档移动排序支持
|
||||
3. 增加目录大纲显示
|
||||
4. 首页最近文档过滤掉无权限的空间文档
|
||||
5. 一些样式调整
|
||||
6. 增加 docker 支持
|
||||
|
||||
### 升级(Upgrade)
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压 (tar -zxvf mm-wiki-v0.1.8-linux-amd64.tar.gz)
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
3. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
### 感谢
|
||||
特别感谢 [@eahomliu](https://github.com/eahomliu) [@cifaz](https://github.com/cifaz) [@cxgreat2014](https://github.com/cxgreat2014) 几位贡献 PR
|
||||
|
||||
## v0.1.7(2020-02)
|
||||
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 修复发送邮件路径不存在
|
||||
|
||||
#### 新增功能
|
||||
无
|
||||
|
||||
### 升级(Upgrade)
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压 (tar -zxvf mm-wiki-v0.1.7-linux-amd64.tar.gz)
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
3. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
|
||||
## v0.1.6(2020-02)
|
||||
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 修复新安装版本号不存在问题
|
||||
|
||||
#### 新增功能
|
||||
1. 完善 pack 打包脚本
|
||||
2. 修复 Windows 下 build 脚本编译问题
|
||||
3. 搜索支持全文搜索功能
|
||||
|
||||
### 升级(Upgrade)
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压 (tar -zxvf mm-wiki-v0.1.5-mac-amd64.tar.gz)
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
3. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
4. 配置文件新增搜索相关配置(增加到自己的配置文件中)
|
||||
```
|
||||
# 搜索配置
|
||||
[search]
|
||||
interval_time=30
|
||||
```
|
||||
|
||||
## v0.1.5(2019-12)
|
||||
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 修复空间修改报错
|
||||
2. 修复用户管理修改用户bug
|
||||
|
||||
#### 新增功能
|
||||
1. 超级管理员可以重置用户密码
|
||||
|
||||
### 升级(Upgrade)
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压 (tar -zxvf mm-wiki-v0.1.5-mac-amd64.tar.gz)
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
3. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
|
||||
## v0.1.4(2019-11)
|
||||
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 邮箱配置发送测试失败问题
|
||||
2. 去掉手机号验证
|
||||
3. 修复版本号不存在问题
|
||||
4. 修复空间修改bug
|
||||
|
||||
#### 新增功能
|
||||
1. 项目改成 go mod 部署
|
||||
2. 代码优化
|
||||
3. linux 下增加启动脚本 run.sh
|
||||
|
||||
### 升级(Upgrade)
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压 (tar -zxvf mm-wiki-v0.1.4-mac-amd64.tar.gz)
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
3. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
|
||||
## v0.1.3(2019-05)
|
||||
### Fix Bug & Add Feature
|
||||
#### 修复bug
|
||||
1. 修复启动命令不支持绝对路径问题
|
||||
2. 安装向导页面优化
|
||||
3. 修复首页快捷链接没有按排序号排序问题
|
||||
4. 代码 go fmt
|
||||
5. 更新 copyright
|
||||
6. 修改系统权限 #55
|
||||
7. 修复私有文档未授权访问漏洞 #55
|
||||
8. 修复文档导出漏洞 #66
|
||||
9. 新建文档可回车提交 #43
|
||||
10. 修复文档编辑窗口过短问题 #46
|
||||
11. 安装的最小环境限制 #45
|
||||
11. 空间名修改后没有更新 #53
|
||||
|
||||
#### 新增功能
|
||||
1. 新增附件上传,附件列表查看,附件删除功能
|
||||
2. 图片上传分目录存储,可查看图片列表并删除
|
||||
3. 分页增加每一页数量控制功能
|
||||
4. 导出文件同时导出附件和图片
|
||||
5. 下载文件同时下载所有的图片和附件
|
||||
|
||||
### Upgrade
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
3. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
|
||||
## v0.1.2 (2018-11)
|
||||
### Fix Bug & Add Feature
|
||||
1. 修复 #16 账号密码回车不能登录问题
|
||||
2. 修复 #22 微信分享标题问题
|
||||
3. 优化 js
|
||||
4. 修复文档内容 a 标签跳转问题
|
||||
5. 修复搜索框回车键不能搜索问题
|
||||
6. 增加邮件测试发送功能
|
||||
7. 修复邮件通知错误日志不能输出到数据库问题
|
||||
8. 修复邮件通知多个发送人失败问题
|
||||
9. 增加新版本自动升级命令 --upgrade
|
||||
10. 增加文档本地保存,意外退出后可恢复本地文档
|
||||
|
||||
### Upgrade
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压
|
||||
3. 执行升级命令
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf --upgrade
|
||||
```
|
||||
3. 重新启动
|
||||
```
|
||||
./mm-wiki --conf conf/mm-wiki.conf
|
||||
```
|
||||
|
||||
|
||||
## v0.1.1(2018-08-08)
|
||||
### Fix Bug & Add Feature
|
||||
1. 添加角色不能删除 #3
|
||||
2. 权限删除问题
|
||||
3. 空间不能删除问题 #12
|
||||
4. js 优化
|
||||
|
||||
### Upgrade
|
||||
1. 下载新版本到部署该项目的根目录
|
||||
2. 覆盖解压
|
||||
3. 重新启动
|
||||
|
||||
## v0.1 (2018-07-22)
|
||||
### 预览版发布
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
FROM alpine/git
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN git clone https://github.com/phachon/mm-wiki.git
|
||||
|
||||
|
||||
FROM golang:1.14.1-alpine
|
||||
|
||||
COPY --from=0 /app/mm-wiki /app/mm-wiki
|
||||
|
||||
WORKDIR /app/mm-wiki
|
||||
|
||||
# 如果国内网络不好,可添加以下环境
|
||||
# RUN go env -w GO111MODULE=on
|
||||
# RUN go env -w GOPROXY=https://goproxy.cn,direct
|
||||
# RUN export GO111MODULE=on
|
||||
# RUN export GOPROXY=https://goproxy.cn
|
||||
|
||||
RUN mkdir /opt/mm-wiki && ls /app/mm-wiki
|
||||
RUN go build -o /opt/mm-wiki/mm-wiki ./ \
|
||||
&& cp -r ./conf/ /opt/mm-wiki \
|
||||
&& cp -r ./install/ /opt/mm-wiki\
|
||||
&& cp ./scripts/run.sh /opt/mm-wiki\
|
||||
&& cp -r ./static/ /opt/mm-wiki\
|
||||
&& cp -r ./views/ /opt/mm-wiki\
|
||||
&& cp -r ./logs/ /opt/mm-wiki\
|
||||
&& cp -r ./docs/ /opt/mm-wiki
|
||||
CMD ["/opt/mm-wiki/mm-wiki", "--conf", "/opt/mm-wiki/conf/mm-wiki.conf"]
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 phachon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,207 @@
|
||||
<h2 align="center">
|
||||
|
||||

|
||||
|
||||
</h2>
|
||||
|
||||
> 首先非常感谢大家的使用,每次看到大家的留言,感到很惭愧,最近几年没有太多精力维护,另外当初在新功能迭代的时候发现 UI 和技术栈都需要彻底的重构,所以就保持在了当前版本未继续更新。后续我决定开始计划全新版本的开发,也希望大家共同参与起来。我在5年前做这个 wiki 的初衷也是期望成为国内免费开源的最好用的wiki系统,期望可以做成和 confluence 一样伟大的产品吧。
|
||||
|
||||
<div align="center">
|
||||
|
||||
MM-Wiki 是一个轻量级的企业知识分享与团队协同软件,可用于快速构建企业 Wiki 和团队知识分享平台。部署方便,使用简单,帮助团队构建一个信息共享、文档管理的协作环境。
|
||||
</br>
|
||||
|
||||
[](https://github.com/phachon/mm-wiki/)
|
||||
[](https://travis-ci.org/phachon/mm-wiki)
|
||||
[](https://raw.githubusercontent.com/phachon/mm-wiki/master/LICENSE)
|
||||
[]()
|
||||
[](https://github.com/phachon/mm-wiki/releases)
|
||||
[](https://github.com/phachon/mm-wiki/releases)
|
||||
|
||||
</div>
|
||||
|
||||
# 特点
|
||||
- 部署方便,基于 golang 编写,只需要下载对于平台下二进制文件执行即可。
|
||||
- 快速安装程序, 提供方便的安装界面程序,无需任何手动操作。
|
||||
- 独立的空间,空间是一组文档的集合,一般为公司部门或者团队,空间下的文档相互独立。空间可根据需求设置空间访问级别。
|
||||
- 支持 markdown 语法写作,支持附件上传。
|
||||
- 完善的系统权限管理,系统可以自定义角色,并为不同角色授予不同的权限。
|
||||
- 集成统一登录,本系统支持通过外部系统认证用户, 比如与公司的 LDAP 登录融合。具体请看登录认证功能。
|
||||
- 邮件通知功能,当开启邮件通知,文档更改会通知所有关注该文档的用户。
|
||||
- 文档具有分享和下载功能,目前只支持下载 MarkDown 源文件。
|
||||
- 支持文档全文搜索
|
||||
|
||||
# 在线快速了解
|
||||
- [mm-wiki企业知识分享与团队协同软件](http://wiki.cifaz.com/), 用户名:admin, 密码:mmwiki, 点击不了请复制http://wiki.cifaz.com/
|
||||
|
||||
# 安装
|
||||
## 1. 自助安装
|
||||
|
||||
打开 https://github.com/phachon/mm-wiki/releases 找到对应平台的版本下载编译好的压缩包
|
||||
|
||||
- Linux 平台
|
||||
|
||||
```
|
||||
# 创建目录
|
||||
$ mkdir mm_wiki
|
||||
$ cd mm_wiki
|
||||
# 以 linux amd64 为例,下载最新版本压缩包
|
||||
# https://github.com/phachon/mm-wiki/releases 自行下载 wget http://
|
||||
# 解压到当前目录
|
||||
$ tar -zxvf mm-wiki-linux-amd64.tar.gz
|
||||
# 进入程序安装目录
|
||||
$ cd install
|
||||
# 执行安装程序,默认端口为 8090,指定其他端口加参数 --port=8087
|
||||
$ ./install
|
||||
# 浏览器访问 http://ip:8090 进入安装界面,完成安装配置
|
||||
# Ctrl + C 停止 install 程序, 启动 MM-Wiki 系统
|
||||
$ cd ..
|
||||
$ ./mm-wiki --conf conf/mm-wiki.conf
|
||||
# 浏览器访问你监听的 ip 和端口
|
||||
# 开始 MM-Wiki 的使用之旅吧!
|
||||
```
|
||||
|
||||
- Windows 平台
|
||||
|
||||
```
|
||||
# 以 windows amd64 为例,下载最新版本压缩包
|
||||
# https://github.com/phachon/mm-wiki/releases 自行下载
|
||||
# 手动解压到当前目录
|
||||
# 进入 install 目录
|
||||
# 双击点开 install.exe 文件
|
||||
# 浏览器访问 http://ip:8090 进入安装界面,完成安装配置
|
||||
# 关闭刚刚点开的 install 窗口
|
||||
# 使用 windows 命令行工具(cmd.exe)进入程序根目录
|
||||
$ 执行 mm-wiki.exe --conf conf/mm-wiki.conf
|
||||
# 浏览器访问你监听的 ip 和端口
|
||||
# 开始 MM-Wiki 的使用之旅吧!
|
||||
```
|
||||
|
||||
- Docker 部署
|
||||
```
|
||||
# 数据库准备
|
||||
# 导入docs/databases/data.sql和docs/databases/table.sql(注:需取消注释data.sql中第一条管理用户插入语句)
|
||||
|
||||
# 两种部署方式可用
|
||||
# DockerHub(推荐)
|
||||
# 从DockerHub下载v0.1.7版本
|
||||
# 新增配置文件,数据存放目录以及Mysql数据库配置在mm-wiki.conf配置文件中设置
|
||||
# 挂载配置文件及数据存放目录,启动端口为8080
|
||||
# docker run -d -p 8080:8081 -v /data/mm-wiki/conf/:/opt/mm-wiki/conf/ -v /data/mm-wiki/data:/data/mm-wiki/data/ --name mm-wiki eahom/mm-wiki:v0.1.7
|
||||
|
||||
# 本地构建最新代码
|
||||
# 构建项目镜像
|
||||
# docker build -t mm-wiki-image .
|
||||
# 新增配置文件,数据存放目录以及Mysql数据库配置在mm-wiki.conf配置文件中设置
|
||||
# 挂载配置文件及数据存放目录,启动端口为8080
|
||||
# docker run -d -p 8080:8081 -v /data/mm-wiki/conf/:/opt/mm-wiki/conf/ -v /data/mm-wiki/data/:/data/mm-wiki/data/ --name mm-wiki mm-wiki-image
|
||||
```
|
||||
## 2. 如果需要,可用 nginx 配置反向代理
|
||||
```
|
||||
upstream frontends {
|
||||
server 127.0.0.1:8088; # MM-Wiki 监听的ip:port
|
||||
}
|
||||
server {
|
||||
listen 80;
|
||||
server_name wiki.intra.xxxxx.com www.wiki.intra.xxxxx.com;
|
||||
location / {
|
||||
proxy_pass_header Server;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Scheme $scheme;
|
||||
proxy_pass http://frontends;
|
||||
}
|
||||
# 静态资源交由nginx管理
|
||||
location /static {
|
||||
root /www/mm-wiki; # MM-Wiki 的根目录
|
||||
expires 1d;
|
||||
add_header Cache-Control public;
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# 系统预览
|
||||
|
||||
### 1 安装
|
||||

|
||||
### 2 登录
|
||||

|
||||
### 3 系统
|
||||

|
||||
### 4 空间文档
|
||||

|
||||
### 5 编辑文档
|
||||

|
||||
### 6 文档分享
|
||||

|
||||
|
||||
# 使用的一些插件
|
||||
|
||||
MM-Wiki 是站在巨人的肩膀上开发的一款软件,是因为系统中使用了非常多优秀的插件,非常感谢这些插件的作者们:
|
||||
|
||||
- [bootstrap](https://github.com/twbs/bootstrap)
|
||||
- [awesome-bootstrap-checkbox](https://github.com/flatlogic/awesome-bootstrap-checkbox)
|
||||
- [bootstrap-iconpicker](https://victor-valencia.github.com/bootstrap-iconpicker)
|
||||
- [bootstrap-select](http://silviomoreto.github.io/bootstrap-select)
|
||||
- [bootstrap-switch](https://bttstrp.github.io/bootstrap-switch)
|
||||
- [bootstrap-tagsinput](https://github.com/bootstrap-tagsinput/bootstrap-tagsinput)
|
||||
- [editor.md](https://github.com/pandao/editor.md)
|
||||
- [layout](http://jquery-dev.com)
|
||||
- [layer](http://layer.layui.com/)
|
||||
- [metisMenu](https://github.com/onokumus/metisMenu)
|
||||
- [morris](http://morrisjs.github.com/morris.js/)
|
||||
- [popover](https://github.com/sandywalker/webui-popover)
|
||||
- [scrollup](http://markgoodyear.com/labs/scrollup/)
|
||||
- [zTreev3](http://treejs.cn/)
|
||||
|
||||
# 二次开发
|
||||
|
||||
环境要求:go 1.8
|
||||
```
|
||||
$ git clone https://github.com/phachon/mm-wiki.git
|
||||
$ cd mm-wiki
|
||||
$ go build ./
|
||||
```
|
||||
|
||||
>如果你想为 mm-wiki 贡献代码,请加开发者交流群:922827699
|
||||
|
||||
## 贡献者列表
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://phachon.com"><img src="https://avatars3.githubusercontent.com/u/19726268?v=4" width="100px;" alt=""/><br /><sub><b>phachon</b></sub></a><br /><a href="https://github.com/phachon/mm-wiki/commits?author=phachon" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/cxgreat2014"><img src="https://avatars2.githubusercontent.com/u/15062548?v=4" width="100px;" alt=""/><br /><sub><b>cxgreat2014</b></sub></a><br /><a href="https://github.com/phachon/mm-wiki/commits?author=cxgreat2014" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/cifaz"><img src="https://avatars0.githubusercontent.com/u/4531158?v=4" width="100px;" alt=""/><br /><sub><b>ccz</b></sub></a><br /><a href="https://github.com/phachon/mm-wiki/commits?author=cifaz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/wangruoran/"><img src="https://avatars3.githubusercontent.com/u/25990237?v=4" width="100px;" alt=""/><br /><sub><b>Ruoran Wang</b></sub></a><br /><a href="https://github.com/phachon/mm-wiki/commits?author=ruoranw" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/eahomliu"><img src="https://avatars3.githubusercontent.com/u/50134691?v=4" width="100px;" alt=""/><br /><sub><b>eahomliu</b></sub></a><br /><a href="https://github.com/phachon/mm-wiki/commits?author=eahomliu" title="Documentation">📖</a> <a href="https://github.com/phachon/mm-wiki/commits?author=eahomliu" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
## 支持
|
||||
请作者喝杯茶吧!
|
||||
|
||||
|
||||
## 反馈
|
||||
- 官方 QQ 交流群:853467682
|
||||
- 如果您喜欢该项目,请 [Star](https://github.com/phachon/mm-wiki/stargazers).
|
||||
- 如果在使用过程中有任何问题, 请提交 [Issue](https://github.com/phachon/mm-wiki/issues).
|
||||
- 如果您发现并解决了bug,请提交 [Pull Request](https://github.com/phachon/mm-wiki/pulls).
|
||||
- 如果您想二次开发,欢迎 [Fork](https://github.com/phachon/mm-wiki/network/members).
|
||||
- 如果你想交个朋友,欢迎发邮件给 [phachon@163.com](mailto:phachon@163.com).
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
谢谢
|
||||
---
|
||||
|
||||
Create By phachon
|
||||
@@ -0,0 +1,7 @@
|
||||
# WeHub 来源说明
|
||||
|
||||
- 原始项目:`phachon/mm-wiki`
|
||||
- 原始仓库:https://github.com/phachon/mm-wiki
|
||||
- 导入方式:上游默认分支的最新快照
|
||||
- 原作者、版权和许可证信息以原始仓库及本仓库 LICENSE 为准
|
||||
- 本文件仅用于记录来源,不代表 WeHub 是原项目作者
|
||||
+152
@@ -0,0 +1,152 @@
|
||||

|
||||
|
||||
MM-Wiki is a light software that enables companies for internal knowledge sharing and for better collaboration. It serves as a platform for information sharing and wiki creating within as well as among teams.
|
||||
|
||||
[](https://github.com/phachon/mm-wiki/)
|
||||
[](https://travis-ci.org/phachon/mm-wiki)
|
||||
[](https://raw.githubusercontent.com/phachon/mm-wiki/master/LICENSE)
|
||||
[]()
|
||||
[](https://github.com/phachon/mm-wiki/releases)
|
||||
[](https://github.com/phachon/mm-wiki/releases)
|
||||
|
||||
# Features
|
||||
- Easy deployment. It’s built with [Go](https://golang.org/doc/). You only need to download the package based on your system and execute the binary file.
|
||||
- Quick installation. It has a clean and concise installing interface that guides you through the process.
|
||||
- Private space for each team and department. By setting permissions, other teams/departments can read, edit files.
|
||||
- Flexible system administration setting. Each user has different roles with various aspects of permissions accordingly.
|
||||
- This app allows users to log in through certified external system such as the company’s LDAP log in system.
|
||||
- Stay synced with your team. You’ll receive email notifications when the file you're following is updated.
|
||||
- Share and download the file. For now you can only download files in the form of Markdown plain text.
|
||||
- Support full text search.
|
||||
|
||||
# Introduction
|
||||
- [mm-wiki](http://wiki.cifaz.com/), userName:admin, password:mmwiki; If cannot click it, Copy the URL: http://wiki.cifaz.com/
|
||||
|
||||
# Installation
|
||||
## Install by downloading it.
|
||||
- Linux
|
||||
```
|
||||
# Make a directory.
|
||||
$ mkdir mm_wiki
|
||||
$ cd mm_wiki
|
||||
# Take linux amd64 as an example: download the latest release of the software.
|
||||
# Downloading address: https://github.com/phachon/mm-wiki/releases
|
||||
# Unzip the file to the directory you just created.
|
||||
$ tar -zxvf mm-wiki-linux-amd64.tar.gz
|
||||
# Enter into the installation directory
|
||||
$ cd install
|
||||
# Execute the file. The default port is 8090. Set another port using: --port=8087
|
||||
$ ./install
|
||||
# Visit http://ip:8090 in a browser. Now you should see the installation interface. Follow the instruction to finish settings.
|
||||
# Ctrl + C to stop installation. Turn on MM-Wiki.
|
||||
$ cd ..
|
||||
$ ./mm-wiki --conf conf/mm-wiki.conf
|
||||
# Now you can visit the ip address with the port the system is listening.
|
||||
# Enjoy using MM-wiki!
|
||||
```
|
||||
- Windows
|
||||
|
||||
1.Take linux amd64 as an example: [download](https://github.com/phachon/mm-wiki/releases) the latest release of the software.<br />
|
||||
2.Unzip the file to a directory that you set before.<br />
|
||||
3.Click into the install directory.<br />
|
||||
4.Double click install.exe. <br />
|
||||
5.Visit http://ip:8090 in a browser and now you should see the installation interface. Follow instructions to finish installations.<br />
|
||||
6.Close the installation window.<br />
|
||||
7.Use command line(cmd.exe)to enter into the root directory.<br />
|
||||
`$ execute mm-wiki.exe --conf conf/mm-wiki.conf`<br />
|
||||
8.Now you can visit the ip address with the port the system is listening. Enjoy using MM-wiki!<br />
|
||||
|
||||
**Note**: If the there's 502 error in the browser when you should see the installation guide instead, change a browser and try it again.<br />
|
||||
|
||||
|
||||
## Install with Nginx reverse proxy
|
||||
```
|
||||
upstream frontends {
|
||||
server 127.0.0.1:8088; # MM-Wiki listening ip:port
|
||||
}
|
||||
server {
|
||||
listen 80;
|
||||
server_name wiki.intra.xxxxx.com www.wiki.intra.xxxxx.com;
|
||||
location / {
|
||||
proxy_pass_header Server;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Scheme $scheme;
|
||||
proxy_pass http://frontends;
|
||||
}
|
||||
# static resources managed by nginx
|
||||
location /static {
|
||||
root /www/mm-wiki; # MM-Wiki root directory
|
||||
expires 1d;
|
||||
add_header Cache-Control public;
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
```
|
||||
# A quick look
|
||||
|
||||
### 1 Installing
|
||||

|
||||
### 2 Log in
|
||||

|
||||
### 3 The system
|
||||

|
||||
### 4 The interface
|
||||

|
||||
### 5 Files editing
|
||||

|
||||
### 6 Files sharing
|
||||

|
||||
|
||||
# Plugins that are used in this app
|
||||
|
||||
MM-Wiki is built with many great plugins. Many thanks to developers of these plugins:
|
||||
|
||||
- [bootstrap](https://github.com/twbs/bootstrap)
|
||||
- [awesome-bootstrap-checkbox](https://github.com/flatlogic/awesome-bootstrap-checkbox)
|
||||
- [bootstrap-iconpicker](https://victor-valencia.github.com/bootstrap-iconpicker)
|
||||
- [bootstrap-select](http://silviomoreto.github.io/bootstrap-select)
|
||||
- [bootstrap-switch](https://bttstrp.github.io/bootstrap-switch)
|
||||
- [bootstrap-tagsinput](https://github.com/bootstrap-tagsinput/bootstrap-tagsinput)
|
||||
- [editor.md](https://github.com/pandao/editor.md)
|
||||
- [layout](http://jquery-dev.com)
|
||||
- [layer](http://layer.layui.com/)
|
||||
- [metisMenu](https://github.com/onokumus/metisMenu)
|
||||
- [morris](http://morrisjs.github.com/morris.js/)
|
||||
- [popover](https://github.com/sandywalker/webui-popover)
|
||||
- [scrollup](http://markgoodyear.com/labs/scrollup/)
|
||||
- [zTreev3](http://treejs.cn/)
|
||||
|
||||
# Contributing
|
||||
|
||||
Requirement:go 1.8
|
||||
```
|
||||
$ git clone https://github.com/phachon/mm-wiki.git
|
||||
$ cd mm-wiki
|
||||
$ go build ./
|
||||
```
|
||||
|
||||
## Supporting
|
||||
If you want to buy me a coffee :)
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Feedback
|
||||
- Official QQ group number:853467682
|
||||
- If you like this app, please [Star](https://github.com/phachon/mm-wiki/stargazers) it.
|
||||
- If there're issues while you're using it, submit a [issue](https://github.com/phachon/mm-wiki/issues).
|
||||
- If you find a bug and solve it, make a [pull request](https://github.com/phachon/mm-wiki/pulls).
|
||||
- If you want to contribute to it, please [fork](https://github.com/phachon/mm-wiki/network/members) it.
|
||||
- If you want to make friends with me,shoot me an email at [phachon@163.com](mailto:phachon@163.com).
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
Many thanks!
|
||||
---
|
||||
|
||||
Created By [phachon](https://github.com/phachon)
|
||||
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-architect
|
||||
@@ -0,0 +1,271 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/fatih/color"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/phachon/mm-wiki/app/work"
|
||||
"github.com/phachon/mm-wiki/global"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultConf = "conf/mm-wiki.conf"
|
||||
|
||||
confPath = flag.String("conf", "", "please set mm-wiki conf path")
|
||||
|
||||
version = flag.Bool("version", false, "mm-wiki version")
|
||||
|
||||
upgrade = flag.Bool("upgrade", false, "mm-wiki upgrade")
|
||||
|
||||
Version = global.SYSTEM_VERSION
|
||||
|
||||
CopyRight = beego.Str2html(global.SYSTEM_COPYRIGHT)
|
||||
|
||||
StartTime = int64(0)
|
||||
|
||||
RootDir = ""
|
||||
|
||||
DocumentAbsDir = ""
|
||||
|
||||
MarkdownAbsDir = ""
|
||||
|
||||
ImageAbsDir = ""
|
||||
|
||||
AttachmentAbsDir = ""
|
||||
|
||||
SearchIndexAbsDir = ""
|
||||
)
|
||||
|
||||
func init() {
|
||||
initFlag()
|
||||
poster()
|
||||
initConfig()
|
||||
initDB()
|
||||
checkUpgrade()
|
||||
initDocumentDir()
|
||||
//initSearch()
|
||||
//initWork()
|
||||
StartTime = time.Now().Unix()
|
||||
}
|
||||
|
||||
// init flag
|
||||
func initFlag() {
|
||||
flag.Parse()
|
||||
// --version
|
||||
if *version == true {
|
||||
fmt.Printf(Version)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
// poster logo
|
||||
func poster() {
|
||||
fg := color.New(color.FgBlue)
|
||||
logo := `
|
||||
_ _ _
|
||||
_ __ ___ _ __ ___ __ __ (_) | | __ (_)
|
||||
| '_ ' _ \ | '_ ' _ \ _____ \ \ /\ / / | | | |/ / | |
|
||||
| | | | | | | | | | | | |_____| \ V V / | | | < | |
|
||||
|_| |_| |_| |_| |_| |_| \_/\_/ |_| |_|\_\ |_|
|
||||
` +
|
||||
"Author: phachon\r\n" +
|
||||
"Version: " + Version + "\r\n" +
|
||||
"Link: https://github.com/phachon/mm-wiki"
|
||||
fg.Println(logo)
|
||||
}
|
||||
|
||||
// init beego config
|
||||
func initConfig() {
|
||||
|
||||
RootDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
||||
if err != nil {
|
||||
log.Println("init config error: " + err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
confFile := *confPath
|
||||
if *confPath == "" {
|
||||
confFile = filepath.Join(RootDir, defaultConf)
|
||||
}
|
||||
ok, _ := utils.NewFile().PathIsExists(confFile)
|
||||
if ok == false {
|
||||
log.Println("conf file " + confFile + " not exists!")
|
||||
os.Exit(1)
|
||||
}
|
||||
// init config file
|
||||
beego.LoadAppConfig("ini", confFile)
|
||||
|
||||
// init name
|
||||
beego.AppConfig.Set("sys.name", "mm-wiki")
|
||||
beego.BConfig.AppName = beego.AppConfig.String("sys.name")
|
||||
beego.BConfig.ServerName = beego.AppConfig.String("sys.name")
|
||||
|
||||
// set static path
|
||||
beego.SetStaticPath("/static/", filepath.Join(RootDir, "./static"))
|
||||
// views path
|
||||
beego.BConfig.WebConfig.ViewsPath = filepath.Join(RootDir, "./views/")
|
||||
|
||||
// session
|
||||
//beego.BConfig.WebConfig.Session.SessionProvider = "memory"
|
||||
//beego.BConfig.WebConfig.Session.SessionProviderConfig = ".session"
|
||||
//beego.BConfig.WebConfig.Session.SessionName = "mmwikissid"
|
||||
//beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
|
||||
// log
|
||||
logConfigs, err := beego.AppConfig.GetSection("log")
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
for adapter, config := range logConfigs {
|
||||
logs.SetLogger(adapter, config)
|
||||
}
|
||||
logs.SetLogFuncCall(true)
|
||||
}
|
||||
|
||||
//init db
|
||||
func initDB() {
|
||||
host := beego.AppConfig.String("db::host")
|
||||
port, _ := beego.AppConfig.Int("db::port")
|
||||
user := beego.AppConfig.String("db::user")
|
||||
pass := beego.AppConfig.String("db::pass")
|
||||
dbname := beego.AppConfig.String("db::name")
|
||||
dbTablePrefix := beego.AppConfig.String("db::table_prefix")
|
||||
maxIdle, _ := beego.AppConfig.Int("db::conn_max_idle")
|
||||
maxConn, _ := beego.AppConfig.Int("db::conn_max_connection")
|
||||
models.G = mysql.NewDBGroup("default")
|
||||
cfg := mysql.NewDBConfigWith(host, port, dbname, user, pass)
|
||||
cfg.SetMaxIdleConns = maxIdle
|
||||
cfg.SetMaxOpenConns = maxConn
|
||||
cfg.TablePrefix = dbTablePrefix
|
||||
cfg.TablePrefixSqlIdentifier = "__PREFIX__"
|
||||
err := models.G.Regist("default", cfg)
|
||||
if err != nil {
|
||||
logs.Error(fmt.Errorf("database error:%s,with config : %v", err, cfg))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// init document dir
|
||||
func initDocumentDir() {
|
||||
docRootDir := beego.AppConfig.String("document::root_dir")
|
||||
if docRootDir == "" {
|
||||
logs.Error("document root dir " + docRootDir + " is not empty!")
|
||||
os.Exit(1)
|
||||
}
|
||||
ok, _ := utils.File.PathIsExists(docRootDir)
|
||||
if !ok {
|
||||
logs.Error("document root dir " + docRootDir + " is not exists!")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
documentAbsDir, err := filepath.Abs(docRootDir)
|
||||
if err != nil {
|
||||
logs.Error("document root dir " + docRootDir + " is error!")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
DocumentAbsDir = documentAbsDir
|
||||
|
||||
// markdown save dir
|
||||
markDownAbsDir := path.Join(documentAbsDir, "markdowns")
|
||||
// image save dir
|
||||
imagesAbsDir := path.Join(documentAbsDir, "images")
|
||||
// attachment save dir
|
||||
attachmentAbsDir := path.Join(documentAbsDir, "attachment")
|
||||
// search index dir
|
||||
searchIndexAbsDir := path.Join(documentAbsDir, "search-index")
|
||||
|
||||
MarkdownAbsDir = markDownAbsDir
|
||||
ImageAbsDir = imagesAbsDir
|
||||
AttachmentAbsDir = attachmentAbsDir
|
||||
SearchIndexAbsDir = searchIndexAbsDir
|
||||
|
||||
dirList := []string{MarkdownAbsDir, ImageAbsDir, AttachmentAbsDir, SearchIndexAbsDir}
|
||||
// create dir
|
||||
for _, dir := range dirList {
|
||||
ok, _ = utils.File.PathIsExists(dir)
|
||||
if !ok {
|
||||
err := os.Mkdir(dir, 0777)
|
||||
if err != nil {
|
||||
logs.Error("create document dir "+dir+" error=%s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// utils document
|
||||
utils.Document.MarkdownAbsDir = markDownAbsDir
|
||||
utils.Document.DocumentAbsDir = documentAbsDir
|
||||
|
||||
beego.SetStaticPath("/images/", ImageAbsDir)
|
||||
// todo
|
||||
beego.SetStaticPath("/images/:space_id/:document_id/", ImageAbsDir)
|
||||
}
|
||||
|
||||
// check upgrade
|
||||
func checkUpgrade() {
|
||||
if *upgrade == true {
|
||||
logs.Info("Start checking whether MM-Wiki needs upgrading.")
|
||||
var versionDb = "v0.0.0"
|
||||
versionConf := models.ConfigModel.GetConfigValueByKey(models.ConfigKeySystemVersion, "v0.0.0")
|
||||
if versionConf != "" {
|
||||
versionDb = versionConf
|
||||
}
|
||||
logs.Info("MM-Wiki Database version:" + versionDb)
|
||||
logs.Info("MM-Wiki Now version: " + Version)
|
||||
|
||||
if versionDb == Version {
|
||||
logs.Info("MM-Wiki does not need updating.")
|
||||
} else {
|
||||
logs.Info("MM-Wiki start upgrading.")
|
||||
err := models.UpgradeModel.Start(versionDb)
|
||||
if err != nil {
|
||||
logs.Error("MM-Wiki upgrade failed.")
|
||||
os.Exit(1)
|
||||
}
|
||||
logs.Info("MM-Wiki upgrade finish.")
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
func initSearch() {
|
||||
|
||||
gseFile := filepath.Join(RootDir, "docs/search_dict/dictionary.txt")
|
||||
stopFile := filepath.Join(RootDir, "docs/search_dict/stop_tokens.txt")
|
||||
ok, _ := utils.File.PathIsExists(gseFile)
|
||||
if !ok {
|
||||
logs.Error("search dict file " + gseFile + " is not exists!")
|
||||
os.Exit(1)
|
||||
}
|
||||
ok, _ = utils.File.PathIsExists(stopFile)
|
||||
if !ok {
|
||||
logs.Error("search stop dict file " + stopFile + " is not exists!")
|
||||
os.Exit(1)
|
||||
}
|
||||
//global.DocSearcher.Init(types.EngineOpts{
|
||||
// UseStore: true,
|
||||
// StoreFolder: SearchIndexAbsDir,
|
||||
// Using: 3,
|
||||
// //GseDict: "zh",
|
||||
// GseDict: gseFile,
|
||||
// StopTokenFile: stopFile,
|
||||
// IndexerOpts: &types.IndexerOpts{
|
||||
// IndexType: types.LocsIndex,
|
||||
// },
|
||||
//})
|
||||
}
|
||||
|
||||
func initWork() {
|
||||
work.DocSearchWorker.Start()
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type AttachmentController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *AttachmentController) Page() {
|
||||
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.ViewError("页面参数错误!", "/space/index")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
isVisit, isEditor, isManager := this.GetDocumentPrivilege(space)
|
||||
if !isVisit {
|
||||
this.ViewError("您没有权限访问该空间下的文档!")
|
||||
}
|
||||
|
||||
// get document attachments
|
||||
attachments, err := models.AttachmentModel.GetAttachmentsByDocumentIdAndSource(documentId, models.Attachment_Source_Default)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 附件失败:" + err.Error())
|
||||
this.ViewError("查找文档附件失败!")
|
||||
}
|
||||
|
||||
// get username
|
||||
userIds := []string{}
|
||||
for _, attachment := range attachments {
|
||||
userIds = append(userIds, attachment["user_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 附件失败:" + err.Error())
|
||||
this.ViewError("查找文档附件失败!")
|
||||
}
|
||||
usernameMap := make(map[string]string)
|
||||
for _, user := range users {
|
||||
usernameMap[user["user_id"]] = user["username"]
|
||||
}
|
||||
for _, attachment := range attachments {
|
||||
attachment["username"] = usernameMap[attachment["user_id"]]
|
||||
}
|
||||
|
||||
this.Data["attachments"] = attachments
|
||||
this.Data["document_id"] = documentId
|
||||
this.Data["is_upload"] = isEditor
|
||||
this.Data["is_delete"] = isManager
|
||||
this.viewLayout("attachment/page", "attachment")
|
||||
}
|
||||
|
||||
func (this *AttachmentController) Upload() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/space/index")
|
||||
}
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.uploadJsonError("参数错误!", "/space/index")
|
||||
}
|
||||
|
||||
// handle document
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间文档 " + documentId + " 失败:" + err.Error())
|
||||
this.uploadJsonError("查找文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.uploadJsonError("文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.uploadJsonError("查找文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.uploadJsonError("文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
_, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isEditor {
|
||||
this.uploadJsonError("您没有权限操作该空间下的文档!")
|
||||
}
|
||||
|
||||
// handle upload
|
||||
f, h, err := this.GetFile("attachment")
|
||||
if err != nil {
|
||||
this.ErrorLog("上传附件数据错误: " + err.Error())
|
||||
this.uploadJsonError("上传附件数据错误")
|
||||
return
|
||||
}
|
||||
if h == nil || f == nil {
|
||||
this.ErrorLog("上传附件错误")
|
||||
this.uploadJsonError("上传附件错误")
|
||||
return
|
||||
}
|
||||
_ = f.Close()
|
||||
|
||||
// file save dir
|
||||
saveDir := fmt.Sprintf("%s/%s/%s", app.AttachmentAbsDir, spaceId, documentId)
|
||||
ok, _ := utils.File.PathIsExists(saveDir)
|
||||
if !ok {
|
||||
err := os.MkdirAll(saveDir, 0777)
|
||||
if err != nil {
|
||||
this.ErrorLog("上传附件错误: " + err.Error())
|
||||
this.uploadJsonError("上传附件失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
// check file is exists
|
||||
attachmentFile := path.Join(saveDir, h.Filename)
|
||||
ok, _ = utils.File.PathIsExists(attachmentFile)
|
||||
if ok {
|
||||
this.uploadJsonError("该附件已经存在!")
|
||||
}
|
||||
// save file
|
||||
err = this.SaveToFile("attachment", attachmentFile)
|
||||
if err != nil {
|
||||
this.ErrorLog("附件保存失败: " + err.Error())
|
||||
this.uploadJsonError("附件保存失败")
|
||||
}
|
||||
|
||||
// insert db
|
||||
attachment := map[string]interface{}{
|
||||
"user_id": this.UserId,
|
||||
"document_id": documentId,
|
||||
"name": h.Filename,
|
||||
"path": fmt.Sprintf("attachment/%s/%s/%s", spaceId, documentId, h.Filename),
|
||||
"source": models.Attachment_Source_Default,
|
||||
}
|
||||
_, err = models.AttachmentModel.Insert(attachment, spaceId)
|
||||
if err != nil {
|
||||
_ = os.Remove(attachmentFile)
|
||||
this.ErrorLog("上传附件错误: " + err.Error())
|
||||
this.uploadJsonError("附件信息保存失败")
|
||||
}
|
||||
|
||||
this.InfoLog(fmt.Sprintf("文档 %s 上传附件 %s 成功", documentId, h.Filename))
|
||||
this.jsonSuccess("附件上传成功", "", "/attachment/page?document_id="+documentId)
|
||||
}
|
||||
|
||||
func (this *AttachmentController) Delete() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/space/index")
|
||||
}
|
||||
attachmentId := this.GetString("attachment_id", "")
|
||||
if attachmentId == "" {
|
||||
this.jsonError("没有选择附件!")
|
||||
}
|
||||
|
||||
attachment, err := models.AttachmentModel.GetAttachmentByAttachmentId(attachmentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除附件 " + attachmentId + " 失败: " + err.Error())
|
||||
this.jsonError("删除附件失败")
|
||||
}
|
||||
if len(attachment) == 0 {
|
||||
this.jsonError("附件不存在")
|
||||
}
|
||||
|
||||
documentId := attachment["document_id"]
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找附件所属空间文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("查找附件所属文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.jsonError("附件所属文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找附件所属文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.jsonError("查找附件所属文档空间失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("附件所属文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
_, _, isManager := this.GetDocumentPrivilege(space)
|
||||
if !isManager {
|
||||
this.jsonError("您没有权限删除该空间下的文档!")
|
||||
}
|
||||
attachmentName := attachment["name"]
|
||||
attachmentSource := attachment["source"]
|
||||
|
||||
// delete db
|
||||
err = models.AttachmentModel.DeleteAttachmentDBFile(attachmentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除附件 " + attachmentId + " 失败: " + err.Error())
|
||||
this.jsonError("删除附件失败")
|
||||
}
|
||||
|
||||
// update document log
|
||||
go func(userId string, documentId string, attachmentName string, spaceId string) {
|
||||
_, _ = models.LogDocumentModel.UpdateAction(userId, documentId, "删除了附件 "+attachmentName, spaceId)
|
||||
}(this.UserId, documentId, attachmentName, spaceId)
|
||||
|
||||
redirect := fmt.Sprintf("/attachment/page?document_id=%s", documentId)
|
||||
if attachmentSource == fmt.Sprintf("%d", models.Attachment_Source_Image) {
|
||||
redirect = fmt.Sprintf("/attachment/image?document_id=%s", documentId)
|
||||
}
|
||||
|
||||
this.InfoLog("删除文档 " + documentId + " 附件 " + attachmentName + " 成功")
|
||||
this.jsonSuccess("删除成功", nil, redirect)
|
||||
}
|
||||
|
||||
func (this *AttachmentController) Download() {
|
||||
|
||||
attachmentId := this.GetString("attachment_id", "")
|
||||
if attachmentId == "" {
|
||||
this.ViewError("没有选择附件!")
|
||||
}
|
||||
|
||||
attachment, err := models.AttachmentModel.GetAttachmentByAttachmentId(attachmentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("下载附件 " + attachmentId + " 失败: " + err.Error())
|
||||
this.ViewError("下载附件失败")
|
||||
}
|
||||
if len(attachment) == 0 {
|
||||
this.ViewError("附件不存在")
|
||||
}
|
||||
|
||||
documentId := attachment["document_id"]
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找附件所属空间文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找附件所属文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.ViewError("附件所属文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找附件所属文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.ViewError("查找附件所属文档空间失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("附件所属文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
isVisit, _, _ := this.GetDocumentPrivilege(space)
|
||||
if !isVisit {
|
||||
this.ViewError("您没有权限访问或下载该空间下的资料!")
|
||||
}
|
||||
attachmentFilePath := path.Join(app.DocumentAbsDir, attachment["path"])
|
||||
attachmentName := attachment["name"]
|
||||
|
||||
this.Ctx.Output.Download(attachmentFilePath, attachmentName)
|
||||
}
|
||||
|
||||
func (this *AttachmentController) Image() {
|
||||
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.ViewError("页面参数错误!", "/space/index")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
isVisit, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isVisit {
|
||||
this.ViewError("您没有权限访问该空间下的文档!")
|
||||
}
|
||||
|
||||
// get document attachment images
|
||||
attachments, err := models.AttachmentModel.GetAttachmentsByDocumentIdAndSource(documentId, models.Attachment_Source_Image)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 图片失败:" + err.Error())
|
||||
this.ViewError("查找文档图片失败!")
|
||||
}
|
||||
|
||||
// get username
|
||||
userIds := []string{}
|
||||
for _, attachment := range attachments {
|
||||
userIds = append(userIds, attachment["user_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 图片失败:" + err.Error())
|
||||
this.ViewError("查找文档图片失败!")
|
||||
}
|
||||
usernameMap := make(map[string]string)
|
||||
for _, user := range users {
|
||||
usernameMap[user["user_id"]] = user["username"]
|
||||
}
|
||||
for _, attachment := range attachments {
|
||||
attachment["username"] = usernameMap[attachment["user_id"]]
|
||||
}
|
||||
|
||||
this.Data["attachments"] = attachments
|
||||
this.Data["document_id"] = documentId
|
||||
this.Data["is_delete"] = isEditor
|
||||
this.viewLayout("attachment/image", "attachment")
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/services"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
)
|
||||
|
||||
type AuthorController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// login index
|
||||
func (this *AuthorController) Index() {
|
||||
|
||||
// is open auth login
|
||||
ssoOpen := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyAuthLogin, "0")
|
||||
this.Data["sso_open"] = ssoOpen
|
||||
this.viewLayout("author/login", "author")
|
||||
}
|
||||
|
||||
// login
|
||||
func (this *AuthorController) Login() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!")
|
||||
}
|
||||
username := strings.TrimSpace(this.GetString("username"))
|
||||
password := strings.TrimSpace(this.GetString("password"))
|
||||
|
||||
if username == "" {
|
||||
this.jsonError("系统用户名不能为空!")
|
||||
}
|
||||
if strings.Contains(username, "_") {
|
||||
this.jsonError("系统用户名不合法!")
|
||||
}
|
||||
if password == "" {
|
||||
this.jsonError("密码不能为空!")
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUsername(username)
|
||||
if err != nil {
|
||||
this.jsonError("登录出错")
|
||||
}
|
||||
if len(user) == 0 || username != user["username"] {
|
||||
this.jsonError("用户名或密码错误!")
|
||||
}
|
||||
if user["is_forbidden"] == fmt.Sprintf("%d", models.User_Forbidden_True) {
|
||||
this.jsonError("用户已被禁用!")
|
||||
}
|
||||
|
||||
password = utils.Encrypt.Md5Encode(password)
|
||||
|
||||
if user["password"] != password {
|
||||
this.jsonError("用户名或密码错误!")
|
||||
}
|
||||
|
||||
// update last_ip and last_login_time
|
||||
updateValue := map[string]interface{}{
|
||||
"last_time": time.Now().Unix(),
|
||||
"last_ip": this.GetClientIp(),
|
||||
}
|
||||
_, err = models.UserModel.Update(user["user_id"], updateValue)
|
||||
if err != nil {
|
||||
this.jsonError("登录出错")
|
||||
}
|
||||
|
||||
// save session
|
||||
this.SetSession("author", user)
|
||||
// save cookie
|
||||
identify := utils.Encrypt.Md5Encode(this.Ctx.Request.UserAgent() + this.GetClientIp() + password)
|
||||
passportValue := utils.Encrypt.Base64Encode(username + "@" + identify)
|
||||
passport := beego.AppConfig.String("author::passport")
|
||||
cookieExpired, _ := beego.AppConfig.Int64("author::cookie_expired")
|
||||
this.Ctx.SetCookie(passport, passportValue, cookieExpired)
|
||||
|
||||
this.Ctx.Request.PostForm.Del("password")
|
||||
|
||||
this.InfoLog("登录成功")
|
||||
this.jsonSuccess("登录成功!", nil, "/main/index")
|
||||
}
|
||||
|
||||
// auth login
|
||||
func (this *AuthorController) AuthLogin() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!")
|
||||
}
|
||||
|
||||
// is open auth login
|
||||
authLoginConf := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyAuthLogin, "0")
|
||||
if authLoginConf != "1" {
|
||||
this.jsonError("系统未开启统一登录功能!")
|
||||
}
|
||||
// get auth login config
|
||||
authLogin, err := models.AuthModel.GetUsedAuth()
|
||||
if err != nil || len(authLogin) == 0 {
|
||||
this.jsonError("统一登录认证配置不可用!")
|
||||
}
|
||||
|
||||
username := strings.TrimSpace(this.GetString("username"))
|
||||
password := strings.TrimSpace(this.GetString("password"))
|
||||
if username == "" {
|
||||
this.jsonError("统一登录用户名不能为空!")
|
||||
}
|
||||
if password == "" {
|
||||
this.jsonError("统一登录密码不能为空!")
|
||||
}
|
||||
authLoginRes, err := services.AuthLogin.AuthLogin(username, password)
|
||||
if err != nil {
|
||||
logs.Error("统一登录失败:", err.Error())
|
||||
this.jsonError("统一登录失败!")
|
||||
return
|
||||
}
|
||||
if authLoginRes == nil {
|
||||
this.jsonError("统一登录失败!")
|
||||
return
|
||||
}
|
||||
realUsername := authLogin["username_prefix"] + "_" + username
|
||||
passwordEncode := models.UserModel.EncodePassword(password)
|
||||
userValue := map[string]interface{}{
|
||||
"username": realUsername,
|
||||
"given_name": authLoginRes.GivenName,
|
||||
"password": passwordEncode,
|
||||
"email": authLoginRes.Email,
|
||||
"mobile": authLoginRes.Mobile,
|
||||
"phone": authLoginRes.Phone,
|
||||
"department": authLoginRes.Department,
|
||||
"position": authLoginRes.Position,
|
||||
"location": authLoginRes.Location,
|
||||
"im": authLoginRes.Im,
|
||||
"last_time": time.Now().Unix(),
|
||||
"last_ip": this.GetClientIp(),
|
||||
}
|
||||
ok, err := models.UserModel.HasUsername(realUsername)
|
||||
if err != nil {
|
||||
this.jsonError("登录失败!")
|
||||
}
|
||||
if ok {
|
||||
// update user info
|
||||
_, err = models.UserModel.UpdateUserByUsername(userValue)
|
||||
} else {
|
||||
// insert user info
|
||||
userValue["role_id"] = models.Role_Default_Id
|
||||
_, err = models.UserModel.Insert(userValue)
|
||||
}
|
||||
if err != nil {
|
||||
this.jsonError("登录失败!" + err.Error())
|
||||
}
|
||||
|
||||
// get user by username
|
||||
user, err := models.UserModel.GetUserByUsername(realUsername)
|
||||
if err != nil {
|
||||
this.jsonError("登录失败:" + err.Error())
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.jsonError("登录失败!")
|
||||
}
|
||||
|
||||
// save session
|
||||
this.SetSession("author", user)
|
||||
// save cookie
|
||||
identify := utils.Encrypt.Md5Encode(this.Ctx.Request.UserAgent() + this.GetClientIp() + passwordEncode)
|
||||
passportValue := utils.Encrypt.Base64Encode(user["username"] + "@" + identify)
|
||||
passport := beego.AppConfig.String("author::passport")
|
||||
cookieExpired, _ := beego.AppConfig.Int64("author::cookie_expired")
|
||||
this.Ctx.SetCookie(passport, passportValue, cookieExpired)
|
||||
|
||||
this.Ctx.Request.PostForm.Del("password")
|
||||
|
||||
this.InfoLog("登录成功")
|
||||
this.jsonSuccess("登录成功!", nil, "/main/index")
|
||||
}
|
||||
|
||||
//logout
|
||||
func (this *AuthorController) Logout() {
|
||||
this.InfoLog("退出成功")
|
||||
passport := beego.AppConfig.String("author::passport")
|
||||
this.Ctx.SetCookie(passport, "")
|
||||
this.SetSession("author", nil)
|
||||
this.DelSession("author")
|
||||
|
||||
this.Redirect("/", 302)
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package controllers
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type BaseController struct {
|
||||
TemplateController
|
||||
}
|
||||
|
||||
// view layout
|
||||
func (this *BaseController) viewLayout(viewName, layout string) {
|
||||
layout = "layouts/" + layout
|
||||
this.ViewLayout(viewName, layout)
|
||||
}
|
||||
|
||||
// return json success
|
||||
func (this *BaseController) jsonSuccess(message interface{}, data ...interface{}) {
|
||||
this.JsonSuccess(message, data...)
|
||||
}
|
||||
|
||||
// return json error
|
||||
func (this *BaseController) jsonError(message interface{}, data ...interface{}) {
|
||||
this.JsonError(message, data...)
|
||||
}
|
||||
|
||||
type UploadJsonResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message interface{} `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
Redirect map[string]interface{} `json:"redirect"`
|
||||
Error interface{} `json:"error"`
|
||||
}
|
||||
|
||||
func (this *BaseController) uploadJsonError(message interface{}, data ...interface{}) {
|
||||
url := ""
|
||||
sleep := 2000
|
||||
var _data interface{}
|
||||
if len(data) > 0 {
|
||||
_data = data[0]
|
||||
}
|
||||
if len(data) > 1 {
|
||||
url = data[1].(string)
|
||||
}
|
||||
if len(data) > 2 {
|
||||
sleep = data[2].(int)
|
||||
}
|
||||
this.Data["json"] = UploadJsonResponse{
|
||||
Code: 0,
|
||||
Message: message,
|
||||
Data: _data,
|
||||
Redirect: map[string]interface{}{
|
||||
"url": url,
|
||||
"sleep": sleep,
|
||||
},
|
||||
Error: message,
|
||||
}
|
||||
j, err := json.MarshalIndent(this.Data["json"], "", " \t")
|
||||
if err != nil {
|
||||
this.Abort(err.Error())
|
||||
} else {
|
||||
this.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
|
||||
this.Abort(string(j))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
)
|
||||
|
||||
type CollectionController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *CollectionController) Add() {
|
||||
|
||||
redirect := this.Ctx.Request.Referer()
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/main/index")
|
||||
}
|
||||
resourceId := this.GetString("resource_id", "")
|
||||
colType, _ := this.GetInt("type", 1)
|
||||
|
||||
if resourceId == "" {
|
||||
this.jsonError("没有选项收藏资源!")
|
||||
}
|
||||
if colType != models.Collection_Type_Doc && colType != models.Collection_Type_Space {
|
||||
this.jsonError("收藏类型错误!")
|
||||
}
|
||||
|
||||
collect, err := models.CollectionModel.GetCollectionByUserIdTypeAndResourceId(this.UserId, colType, resourceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加收藏失败:" + err.Error())
|
||||
this.jsonError("添加收藏失败!")
|
||||
}
|
||||
if len(collect) > 0 {
|
||||
this.jsonError("您已收藏过,不能重复收藏!")
|
||||
}
|
||||
insertCollection := map[string]interface{}{
|
||||
"user_id": this.UserId,
|
||||
"resource_id": resourceId,
|
||||
"type": colType,
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
collectId, err := models.CollectionModel.Insert(insertCollection)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加收藏失败:" + err.Error())
|
||||
this.jsonError("添加收藏失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("添加收藏 " + utils.Convert.IntToString(collectId, 10) + " 成功")
|
||||
this.jsonSuccess("收藏成功!", nil, redirect)
|
||||
}
|
||||
|
||||
func (this *CollectionController) Cancel() {
|
||||
|
||||
redirect := this.Ctx.Request.Referer()
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/space/list")
|
||||
}
|
||||
collectionId := this.GetString("collection_id", "")
|
||||
|
||||
if collectionId == "" {
|
||||
this.jsonError("没有选择收藏资源!")
|
||||
}
|
||||
|
||||
collection, err := models.CollectionModel.GetCollectionByCollectionId(collectionId)
|
||||
if err != nil {
|
||||
this.ErrorLog("取消收藏 " + collectionId + " 失败:" + err.Error())
|
||||
this.jsonError("取消收藏失败!")
|
||||
}
|
||||
if len(collection) == 0 {
|
||||
this.jsonError("收藏资源不存在!")
|
||||
}
|
||||
if collection["user_id"] != this.UserId {
|
||||
this.jsonError("您只能取消自己的收藏!")
|
||||
}
|
||||
|
||||
err = models.CollectionModel.Delete(collectionId)
|
||||
if err != nil {
|
||||
this.ErrorLog("取消收藏 " + collectionId + " 失败:" + err.Error())
|
||||
this.jsonError("取消收藏失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("取消收藏 " + collectionId + " 成功")
|
||||
this.jsonSuccess("已取消收藏!", nil, redirect)
|
||||
}
|
||||
@@ -0,0 +1,492 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app/services"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
)
|
||||
|
||||
type DocumentController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// document index
|
||||
func (this *DocumentController) Index() {
|
||||
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.ViewError("页面参数错误!", "/space/index")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
isVisit, _, _ := this.GetDocumentPrivilege(space)
|
||||
if !isVisit {
|
||||
this.ViewError("您没有权限访问该空间下的文档!")
|
||||
}
|
||||
|
||||
// get default space document
|
||||
spaceDocument, err := models.DocumentModel.GetSpaceDefaultDocument(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(spaceDocument) == 0 {
|
||||
this.ViewError(" 空间首页文档不存在!")
|
||||
}
|
||||
|
||||
// get space all document
|
||||
documents, err := models.DocumentModel.GetAllSpaceDocuments(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
|
||||
// get space privilege
|
||||
_, isEditor, isDelete := this.GetDocumentPrivilege(space)
|
||||
|
||||
this.Data["is_editor"] = isEditor
|
||||
this.Data["is_delete"] = isDelete
|
||||
this.Data["documents"] = documents
|
||||
this.Data["default_document_id"] = documentId
|
||||
this.Data["space"] = space
|
||||
this.Data["space_document"] = spaceDocument
|
||||
this.viewLayout("document/index", "document")
|
||||
}
|
||||
|
||||
// add document
|
||||
func (this *DocumentController) Add() {
|
||||
|
||||
spaceId := this.GetString("space_id", "0")
|
||||
parentId := this.GetString("parent_id", "0")
|
||||
|
||||
if spaceId == "0" {
|
||||
this.ViewError("没有选择空间!")
|
||||
}
|
||||
if parentId == "0" {
|
||||
this.ViewError("没有选择上级!")
|
||||
}
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加文档失败:" + err.Error())
|
||||
this.ViewError("添加文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("空间不存在!")
|
||||
}
|
||||
|
||||
// check space document privilege
|
||||
_, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isEditor {
|
||||
this.ViewError("您没有权限在该空间下创建文档!")
|
||||
}
|
||||
|
||||
parentDocument, err := models.DocumentModel.GetDocumentByDocumentId(parentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加文档 " + parentId + " 失败:" + err.Error())
|
||||
this.ViewError("添加文档失败!")
|
||||
}
|
||||
if len(parentDocument) == 0 {
|
||||
this.ViewError("父文档不存在!")
|
||||
}
|
||||
path := parentDocument["path"] + "," + parentId
|
||||
// get parent documents by path
|
||||
parentDocuments, err := models.DocumentModel.GetParentDocumentsByPath(path)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找父文档失败:" + err.Error())
|
||||
this.ViewError("查找父文档失败!")
|
||||
}
|
||||
if len(parentDocuments) == 0 {
|
||||
this.ViewError("父文档不存在!")
|
||||
}
|
||||
|
||||
this.Data["parent_documents"] = parentDocuments
|
||||
this.Data["parent_id"] = parentId
|
||||
this.Data["space_id"] = spaceId
|
||||
this.viewLayout("document/form", "default")
|
||||
|
||||
}
|
||||
|
||||
// save document
|
||||
func (this *DocumentController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/main/index")
|
||||
}
|
||||
spaceId := strings.TrimSpace(this.GetString("space_id", "0"))
|
||||
parentId := strings.TrimSpace(this.GetString("parent_id", "0"))
|
||||
docType, _ := this.GetInt("type", models.Document_Type_Page)
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
|
||||
if spaceId == "0" {
|
||||
this.jsonError("没有选择空间!")
|
||||
}
|
||||
if parentId == "0" {
|
||||
this.jsonError("没有选择父文档!")
|
||||
}
|
||||
if name == "" {
|
||||
this.jsonError("文档名称不能为空!")
|
||||
}
|
||||
match, err := regexp.MatchString(`[\\\\/:*?\"<>、|]`, name)
|
||||
if err != nil {
|
||||
this.jsonError("文档名称格式不正确!")
|
||||
}
|
||||
if match {
|
||||
this.jsonError("文档名称格式不正确!")
|
||||
}
|
||||
if name == utils.Document_Default_FileName {
|
||||
this.jsonError("文档名称不能为 " + utils.Document_Default_FileName + " !")
|
||||
}
|
||||
if docType != models.Document_Type_Page &&
|
||||
docType != models.Document_Type_Dir {
|
||||
this.jsonError("文档类型错误!")
|
||||
}
|
||||
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("创建保存文档失败:" + err.Error())
|
||||
this.jsonError("创建文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
|
||||
// check space document privilege
|
||||
_, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isEditor {
|
||||
this.jsonError("您没有权限在该空间下创建文档!")
|
||||
}
|
||||
|
||||
parentDocument, err := models.DocumentModel.GetDocumentByDocumentId(parentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("创建保存文档失败:" + err.Error())
|
||||
this.jsonError("创建文档失败!")
|
||||
}
|
||||
if len(parentDocument) == 0 {
|
||||
this.jsonError("父文档不存在!")
|
||||
}
|
||||
if parentDocument["type"] != fmt.Sprintf("%d", models.Document_Type_Dir) {
|
||||
this.jsonError("父文档不是目录!")
|
||||
}
|
||||
|
||||
// check document name
|
||||
document, err := models.DocumentModel.GetDocumentByNameParentIdAndSpaceId(name, parentId, spaceId, docType)
|
||||
if err != nil {
|
||||
this.ErrorLog("创建保存文档失败:" + err.Error())
|
||||
this.jsonError("创建文档失败!")
|
||||
}
|
||||
if len(document) != 0 {
|
||||
this.jsonError("该文档名称已经存在!")
|
||||
}
|
||||
|
||||
insertDocument := map[string]interface{}{
|
||||
"parent_id": parentId,
|
||||
"space_id": spaceId,
|
||||
"name": name,
|
||||
"type": docType,
|
||||
"path": parentDocument["path"] + "," + parentId,
|
||||
"create_user_id": this.UserId,
|
||||
"edit_user_id": this.UserId,
|
||||
}
|
||||
documentId, err := models.DocumentModel.Insert(insertDocument)
|
||||
if err != nil {
|
||||
this.ErrorLog("创建文档失败:" + err.Error())
|
||||
this.jsonError("创建文档失败")
|
||||
}
|
||||
this.InfoLog("创建文档 " + utils.Convert.IntToString(documentId, 10) + " 成功")
|
||||
this.jsonSuccess("创建文档成功", nil, "/document/index?document_id="+utils.Convert.IntToString(documentId, 10))
|
||||
}
|
||||
|
||||
// document history
|
||||
func (this *DocumentController) History() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
documentId := this.GetString("document_id", "0")
|
||||
number, _ := this.GetRangeInt("number", 10, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
|
||||
if documentId == "0" {
|
||||
this.ViewError("没有选择文档目录!")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查看文档 " + documentId + " 修改历史失败:" + err.Error())
|
||||
this.ViewError("查看文档修改历史失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.jsonError("文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("文档所在空间不存在!")
|
||||
}
|
||||
|
||||
// check space visit_level
|
||||
isVisit, _, _ := this.GetDocumentPrivilege(space)
|
||||
if !isVisit {
|
||||
this.ViewError("您没有权限查看该空间修改历史!")
|
||||
}
|
||||
|
||||
logDocuments, err := models.LogDocumentModel.GetLogDocumentsByDocumentIdAndLimit(documentId, limit, number)
|
||||
if err != nil {
|
||||
this.ErrorLog("查看文档 " + documentId + " 修改历史失败:" + err.Error())
|
||||
this.ViewError("查看文档修改历史失败!")
|
||||
}
|
||||
count, err := models.LogDocumentModel.CountLogDocumentsByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查看文档 " + documentId + " 修改历史失败:" + err.Error())
|
||||
this.ViewError("查看文档修改历史失败!")
|
||||
}
|
||||
|
||||
userIds := []string{}
|
||||
for _, logDocument := range logDocuments {
|
||||
userIds = append(userIds, logDocument["user_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查看文档 " + documentId + " 修改历史失败:" + err.Error())
|
||||
this.ViewError("查看文档修改历史失败!")
|
||||
}
|
||||
for _, logDocument := range logDocuments {
|
||||
logDocument["username"] = ""
|
||||
for _, user := range users {
|
||||
if logDocument["user_id"] == user["user_id"] {
|
||||
logDocument["username"] = user["username"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["logDocuments"] = logDocuments
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("document/history", "default")
|
||||
}
|
||||
|
||||
// move document
|
||||
func (this *DocumentController) Move() {
|
||||
|
||||
documentId := this.GetString("document_id", "0")
|
||||
targetId := this.GetString("target_id", "0")
|
||||
moveType := this.GetString("move_type", "") // 同层文件排序
|
||||
|
||||
if documentId == "0" {
|
||||
this.jsonError("没有选择文档节点!")
|
||||
}
|
||||
if targetId == "0" {
|
||||
this.jsonError("没有选择目标文档节点!")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找移动文档失败:" + err.Error())
|
||||
this.jsonError("移动文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.jsonError("文档不存在!")
|
||||
}
|
||||
if moveType != "next" && moveType != "prev" {
|
||||
if document["type"] == fmt.Sprintf("%d", models.Document_Type_Dir) {
|
||||
this.jsonError("不能移动文档目录!")
|
||||
}
|
||||
}
|
||||
|
||||
targetDocument, err := models.DocumentModel.GetDocumentByDocumentId(targetId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找目标文档失败:" + err.Error())
|
||||
this.jsonError("移动文档失败!")
|
||||
}
|
||||
if len(targetDocument) == 0 {
|
||||
this.jsonError("目标文档不存在!")
|
||||
}
|
||||
if document["space_id"] != targetDocument["space_id"] {
|
||||
this.jsonError("文档和目标文档不在同一空间!")
|
||||
}
|
||||
if moveType != "next" && moveType != "prev" {
|
||||
if targetDocument["type"] != fmt.Sprintf("%d", models.Document_Type_Dir) {
|
||||
this.jsonError("目标文档必须是目录!")
|
||||
}
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("移动文档失败:" + err.Error())
|
||||
this.jsonError("移动文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("文档空间不存在!")
|
||||
}
|
||||
// check space document privilege
|
||||
_, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isEditor {
|
||||
this.jsonError("您没有权限移动该空间下的文档!")
|
||||
}
|
||||
|
||||
// 排序逻辑:next-移动到目标文档之后 prev-移动到目标文档之前
|
||||
if moveType == "next" || moveType == "prev" {
|
||||
this.updateDocSequence(moveType, document, targetDocument)
|
||||
return
|
||||
}
|
||||
|
||||
_, oldPageFile, err := models.DocumentModel.GetParentDocumentsByDocument(document)
|
||||
if err != nil {
|
||||
this.ErrorLog("移动文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("移动文档失败!")
|
||||
}
|
||||
newDocument := map[string]string{
|
||||
"space_id": document["space_id"],
|
||||
"parent_id": targetId,
|
||||
"name": document["name"],
|
||||
"type": document["type"],
|
||||
"path": targetDocument["path"] + "," + targetId,
|
||||
}
|
||||
_, newPageFile, err := models.DocumentModel.GetParentDocumentsByDocument(newDocument)
|
||||
if err != nil {
|
||||
this.ErrorLog("移动文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("移动文档失败!")
|
||||
}
|
||||
|
||||
// update database and move document file
|
||||
updateValue := map[string]interface{}{
|
||||
"parent_id": targetId,
|
||||
"path": targetDocument["path"] + "," + targetId,
|
||||
"edit_user_id": this.UserId,
|
||||
}
|
||||
_, err = models.DocumentModel.MoveDBAndFile(documentId, spaceId, updateValue,
|
||||
oldPageFile, newPageFile, document["type"], "移动文档到 "+targetDocument["name"])
|
||||
if err != nil {
|
||||
this.ErrorLog("移动文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("移动文档失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("移动文档 " + documentId + " 成功")
|
||||
this.jsonSuccess("移动文档成功", nil, "/document/index?document_id="+documentId)
|
||||
}
|
||||
|
||||
// 移动文档排序
|
||||
func (this *DocumentController) updateDocSequence(moveType string, document map[string]string, targetDocument map[string]string) {
|
||||
|
||||
sequence := utils.Convert.StringToInt(targetDocument["sequence"])
|
||||
spaceId := targetDocument["space_id"]
|
||||
targetDocumentId := targetDocument["document_id"]
|
||||
movedDocumentId := document["document_id"]
|
||||
|
||||
updateSequence := sequence
|
||||
if moveType == "next" {
|
||||
updateSequence = sequence + 1
|
||||
}
|
||||
|
||||
// 批量修改序号
|
||||
_, err := models.DocumentModel.MoveSequenceBySpaceIdAndGtSequence(spaceId, updateSequence, 1)
|
||||
if err != nil {
|
||||
this.ErrorLog("移动文档 " + movedDocumentId + "到目标文档 " + targetDocumentId + " " + moveType + " 失败:" + err.Error())
|
||||
this.jsonError("移动文档失败!")
|
||||
}
|
||||
|
||||
// 修改当前文档的序号
|
||||
updateValue := map[string]interface{}{
|
||||
"sequence": updateSequence,
|
||||
"edit_user_id": this.UserId,
|
||||
}
|
||||
_, err = models.DocumentModel.Update(movedDocumentId, updateValue, fmt.Sprintf("移动文档"), spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("移动文档 " + movedDocumentId + "到目标文档 " + targetDocumentId + " " + moveType + " 失败:" + err.Error())
|
||||
this.jsonError("移动文档失败!")
|
||||
}
|
||||
this.jsonSuccess("移动文档成功", "", "/document/index?document_id="+movedDocumentId)
|
||||
}
|
||||
|
||||
// delete document
|
||||
func (this *DocumentController) Delete() {
|
||||
|
||||
documentId := this.GetString("document_id", "0")
|
||||
|
||||
if documentId == "0" {
|
||||
this.jsonError("没有选择文档!")
|
||||
}
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除文档失败:" + err.Error())
|
||||
this.jsonError("删除文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.jsonError("文档不存在!")
|
||||
}
|
||||
if document["type"] == fmt.Sprintf("%d", models.Document_Type_Dir) {
|
||||
childDocs, err := models.DocumentModel.GetDocumentsByParentId(document["document_id"])
|
||||
if err != nil {
|
||||
this.ErrorLog("删除文档失败:" + err.Error())
|
||||
this.jsonError("删除文档失败!")
|
||||
}
|
||||
if len(childDocs) > 0 {
|
||||
this.jsonError("请先删除或移动目录下所有文档!")
|
||||
}
|
||||
}
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(document["space_id"])
|
||||
if err != nil {
|
||||
this.ErrorLog("删除文档失败:" + err.Error())
|
||||
this.jsonError("删除文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("文档空间不存在!")
|
||||
}
|
||||
// check space document privilege
|
||||
_, _, isManager := this.GetDocumentPrivilege(space)
|
||||
if !isManager {
|
||||
this.jsonError("您没有权限删除该空间下的文档!")
|
||||
}
|
||||
|
||||
_, pageFile, err := models.DocumentModel.GetParentDocumentsByDocument(document)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("删除文档失败!")
|
||||
}
|
||||
|
||||
err = models.DocumentModel.DeleteDBAndFile(documentId, spaceId, this.UserId, pageFile, document["type"])
|
||||
if err != nil {
|
||||
this.ErrorLog("删除文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("删除文档失败!")
|
||||
}
|
||||
|
||||
// delete attachment
|
||||
err = models.AttachmentModel.DeleteAttachmentsDBFileByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除文档 " + documentId + " 附件失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 删除文档索引
|
||||
go func(documentId string) {
|
||||
services.DocIndexService.ForceDelDocIdIndex(documentId)
|
||||
}(documentId)
|
||||
|
||||
this.InfoLog("删除文档 " + documentId + " 成功")
|
||||
this.jsonSuccess("删除文档成功", "", "/document/index?document_id="+document["parent_id"])
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
)
|
||||
|
||||
type FollowController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *FollowController) Add() {
|
||||
|
||||
redirect := this.Ctx.Request.Referer()
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/main/index")
|
||||
}
|
||||
objectId := this.GetString("object_id", "")
|
||||
followType, _ := this.GetInt("type", 1)
|
||||
if objectId == "" {
|
||||
this.jsonError("没有选择关注对象!")
|
||||
}
|
||||
if followType != models.Follow_Type_Doc && followType != models.Follow_Type_User {
|
||||
this.jsonError("关注类型错误!")
|
||||
}
|
||||
if followType == models.Follow_Type_User && objectId == this.UserId {
|
||||
this.jsonError("不能关注自己!")
|
||||
}
|
||||
|
||||
follow, err := models.FollowModel.GetFollowByUserIdAndTypeAndObjectId(this.UserId, followType, objectId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加关注失败:" + err.Error())
|
||||
this.jsonError("添加关注失败!")
|
||||
}
|
||||
if len(follow) > 0 {
|
||||
this.jsonError("您已关注过,不能重复关注!")
|
||||
}
|
||||
fId, err := models.FollowModel.Insert(this.UserId, followType, objectId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加关注失败:" + err.Error())
|
||||
this.jsonError("添加关注失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("添加关注" + utils.Convert.IntToString(fId, 10) + " 成功")
|
||||
this.jsonSuccess("关注成功!", nil, redirect)
|
||||
}
|
||||
|
||||
func (this *FollowController) Cancel() {
|
||||
|
||||
redirect := this.Ctx.Request.Referer()
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/main/index")
|
||||
}
|
||||
followId := this.GetString("follow_id", "")
|
||||
if followId == "" {
|
||||
this.jsonError("没有选择关注对象!")
|
||||
}
|
||||
|
||||
follow, err := models.FollowModel.GetFollowByFollowId(followId)
|
||||
if err != nil {
|
||||
this.ErrorLog("取消关注失败:" + err.Error())
|
||||
this.jsonError("取消关注失败!")
|
||||
}
|
||||
if len(follow) == 0 {
|
||||
this.jsonError("关注对象不存在!")
|
||||
}
|
||||
if follow["user_id"] != this.UserId {
|
||||
this.jsonError("您只能取消自己的关注!")
|
||||
}
|
||||
|
||||
err = models.FollowModel.Delete(followId)
|
||||
if err != nil {
|
||||
this.ErrorLog("取消关注 " + followId + " 失败:" + err.Error())
|
||||
this.jsonError("取消关注用户失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("取消关注 " + followId + " 成功")
|
||||
this.jsonSuccess("已取消关注!", nil, redirect)
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type UploadResponse struct {
|
||||
Success int `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
type ImageController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *ImageController) Upload() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/space/index")
|
||||
}
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.jsonError("参数错误!")
|
||||
}
|
||||
|
||||
// handle document
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("查找文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.jsonError("文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.jsonError("查找文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
_, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isEditor {
|
||||
this.jsonError("您没有权限操作该空间下的文档!")
|
||||
}
|
||||
|
||||
// handle upload
|
||||
f, h, err := this.GetFile("editormd-image-file")
|
||||
if err != nil {
|
||||
this.ErrorLog("上传图片数据错误: " + err.Error())
|
||||
this.jsonError("上传图片数据错误")
|
||||
return
|
||||
}
|
||||
if h == nil || f == nil {
|
||||
this.ErrorLog("上传图片错误")
|
||||
this.jsonError("上传图片错误")
|
||||
return
|
||||
}
|
||||
_ = f.Close()
|
||||
|
||||
// file save dir
|
||||
saveDir := fmt.Sprintf("%s/%s/%s", app.ImageAbsDir, spaceId, documentId)
|
||||
ok, _ := utils.File.PathIsExists(saveDir)
|
||||
if !ok {
|
||||
err := os.MkdirAll(saveDir, 0777)
|
||||
if err != nil {
|
||||
this.ErrorLog("上传图片错误: " + err.Error())
|
||||
this.jsonError("上传图片失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
// check file is exists
|
||||
imageFile := path.Join(saveDir, h.Filename)
|
||||
ok, _ = utils.File.PathIsExists(imageFile)
|
||||
if ok {
|
||||
this.jsonError("该图片已经上传过!")
|
||||
}
|
||||
// save file
|
||||
err = this.SaveToFile("editormd-image-file", imageFile)
|
||||
if err != nil {
|
||||
this.ErrorLog("图片保存失败: " + err.Error())
|
||||
this.jsonError("图片保存失败")
|
||||
}
|
||||
|
||||
// insert db
|
||||
attachment := map[string]interface{}{
|
||||
"user_id": this.UserId,
|
||||
"document_id": documentId,
|
||||
"name": h.Filename,
|
||||
"path": fmt.Sprintf("images/%s/%s/%s", spaceId, documentId, h.Filename),
|
||||
"source": models.Attachment_Source_Image,
|
||||
}
|
||||
_, err = models.AttachmentModel.Insert(attachment, spaceId)
|
||||
if err != nil {
|
||||
_ = os.Remove(imageFile)
|
||||
this.ErrorLog("上传图片保存信息错误: " + err.Error())
|
||||
this.jsonError("图片信息保存失败")
|
||||
}
|
||||
|
||||
this.InfoLog(fmt.Sprintf("文档 %s 上传图片 %s 成功", documentId, h.Filename))
|
||||
this.jsonSuccess("上传成功", fmt.Sprintf("/%s", attachment["path"]))
|
||||
}
|
||||
|
||||
func (this *ImageController) jsonError(message string) {
|
||||
|
||||
uploadRes := UploadResponse{
|
||||
Success: 0,
|
||||
Message: message,
|
||||
Url: "",
|
||||
}
|
||||
|
||||
j, err := json.Marshal(uploadRes)
|
||||
if err != nil {
|
||||
this.Abort(err.Error())
|
||||
} else {
|
||||
this.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
|
||||
this.Abort(string(j))
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ImageController) jsonSuccess(message string, url string) {
|
||||
|
||||
uploadRes := UploadResponse{
|
||||
Success: 1,
|
||||
Message: message,
|
||||
Url: url,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(uploadRes)
|
||||
if err != nil {
|
||||
this.Abort(err.Error())
|
||||
} else {
|
||||
this.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
|
||||
this.Abort(string(j))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
)
|
||||
|
||||
type MainController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *MainController) Index() {
|
||||
collectDocs, err := models.CollectionModel.GetCollectionsByUserIdAndType(this.UserId, models.Collection_Type_Doc)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找收藏文档错误: " + err.Error())
|
||||
this.ViewError("查找收藏文档错误!")
|
||||
}
|
||||
docIds := []string{}
|
||||
for _, collectDoc := range collectDocs {
|
||||
docIds = append(docIds, collectDoc["resource_id"])
|
||||
}
|
||||
|
||||
documents, err := models.DocumentModel.GetDocumentsByDocumentIds(docIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找收藏文档错误: " + err.Error())
|
||||
this.ViewError("查找收藏文档错误!")
|
||||
}
|
||||
this.Data["documents"] = documents
|
||||
this.Data["count"] = len(documents)
|
||||
this.viewLayout("main/index", "main")
|
||||
}
|
||||
|
||||
func (this *MainController) Default() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
number, _ := this.GetInt("number", 10)
|
||||
maxPage := 10
|
||||
if page >= maxPage {
|
||||
page = maxPage
|
||||
}
|
||||
//number := 8
|
||||
limit := (page - 1) * number
|
||||
|
||||
userId := this.UserId
|
||||
|
||||
logDocuments, err := models.LogDocumentModel.GetLogDocumentsByLimit(userId, limit, number)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找更新文档列表失败:" + err.Error())
|
||||
this.ViewError("查找更新文档列表失败!")
|
||||
}
|
||||
|
||||
count, err := models.LogDocumentModel.CountLogDocuments()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找更新文档总数失败:" + err.Error())
|
||||
this.ViewError("查找更新文档列表失败!")
|
||||
}
|
||||
if count >= int64(maxPage*number) {
|
||||
count = int64(maxPage * number)
|
||||
}
|
||||
|
||||
userIds := []string{}
|
||||
docIds := []string{}
|
||||
for _, logDocument := range logDocuments {
|
||||
userIds = append(userIds, logDocument["user_id"])
|
||||
docIds = append(docIds, logDocument["document_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找更新文档用户失败:" + err.Error())
|
||||
this.ViewError("查找更新文档列表失败!")
|
||||
}
|
||||
docs, err := models.DocumentModel.GetAllDocumentsByDocumentIds(docIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档信息失败:" + err.Error())
|
||||
this.ViewError("查找更新文档列表失败!")
|
||||
}
|
||||
for _, logDocument := range logDocuments {
|
||||
logDocument["username"] = ""
|
||||
for _, user := range users {
|
||||
if logDocument["user_id"] == user["user_id"] {
|
||||
logDocument["username"] = user["username"]
|
||||
logDocument["given_name"] = user["given_name"]
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, doc := range docs {
|
||||
if logDocument["document_id"] == doc["document_id"] {
|
||||
logDocument["document_name"] = doc["name"]
|
||||
logDocument["document_type"] = doc["type"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// link
|
||||
links, err := models.LinkModel.GetLinksOrderBySequence()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找快捷链接失败:" + err.Error())
|
||||
this.ViewError("查找快捷链接失败!")
|
||||
}
|
||||
// contacts
|
||||
contacts, err := models.ContactModel.GetAllContact()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找快捷链接失败:" + err.Error())
|
||||
this.ViewError("查找快捷链接失败!")
|
||||
}
|
||||
|
||||
// main title config
|
||||
mainTitle := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyMainTitle, "")
|
||||
mainDescription := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyMainDescription, "")
|
||||
|
||||
this.Data["panel_title"] = mainTitle
|
||||
this.Data["panel_description"] = mainDescription
|
||||
this.Data["logDocuments"] = logDocuments
|
||||
this.Data["links"] = links
|
||||
this.Data["contacts"] = contacts
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("main/default", "default")
|
||||
}
|
||||
|
||||
func (this *MainController) About() {
|
||||
this.viewLayout("main/about", "default")
|
||||
}
|
||||
|
||||
// 搜索,支持根据标题和内容搜索
|
||||
func (this *MainController) Search() {
|
||||
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
searchType := this.GetString("search_type", "content")
|
||||
|
||||
this.Data["search_type"] = searchType
|
||||
this.Data["keyword"] = keyword
|
||||
this.Data["count"] = 0
|
||||
if keyword == "" {
|
||||
this.viewLayout("main/search", "default")
|
||||
return
|
||||
}
|
||||
var documents = []map[string]string{}
|
||||
var err error
|
||||
// 获取该用户有权限的空间
|
||||
publicSpaces, err := models.SpaceModel.GetSpacesByVisitLevel(models.Space_VisitLevel_Public)
|
||||
if err != nil {
|
||||
this.ErrorLog("搜索文档列表获取用户空间权限出错:" + err.Error())
|
||||
this.ViewError("搜索文档错误!")
|
||||
}
|
||||
spaceUsers, err := models.SpaceUserModel.GetSpaceUsersByUserId(this.UserId)
|
||||
if err != nil {
|
||||
this.ErrorLog("搜索文档列表获取用户空间权限出错:" + err.Error())
|
||||
this.ViewError("搜索文档错误!")
|
||||
}
|
||||
spaceIdsMap := make(map[string]bool)
|
||||
for _, publicSpace := range publicSpaces {
|
||||
spaceIdsMap[publicSpace["space_id"]] = true
|
||||
}
|
||||
for _, spaceUser := range spaceUsers {
|
||||
if _, ok := spaceIdsMap[spaceUser["space_id"]]; !ok {
|
||||
spaceIdsMap[spaceUser["space_id"]] = true
|
||||
}
|
||||
}
|
||||
searchDocContents := make(map[string]string)
|
||||
// 默认根据内容搜索
|
||||
// v0.2.1 下线全文搜索功能
|
||||
searchType = "title"
|
||||
//if searchType == "title" {
|
||||
// documents, err = models.DocumentModel.GetDocumentsByLikeName(keyword)
|
||||
//} else {
|
||||
// searchRes := global.DocSearcher.SearchDoc(types.SearchReq{Text: keyword})
|
||||
// searchDocIds := []string{}
|
||||
// for _, searchDoc := range searchRes.Docs {
|
||||
// if len(searchDoc.TokenSnippetLocs) == 0 {
|
||||
// continue
|
||||
// }
|
||||
// docId := searchDoc.DocId
|
||||
// content := searchDoc.Content
|
||||
// locIndex := searchDoc.TokenSnippetLocs[0]
|
||||
// searchContent := utils.Misc.SubStrUnicodeBySubStrIndex(content, keyword, locIndex, 30, 30)
|
||||
// searchDocContents[docId] = searchContent
|
||||
// searchDocIds = append(searchDocIds, docId)
|
||||
// }
|
||||
// documents, err = models.DocumentModel.GetDocumentsByDocumentIds(searchDocIds)
|
||||
//}
|
||||
documents, err = models.DocumentModel.GetDocumentsByLikeName(keyword)
|
||||
if err != nil {
|
||||
this.ErrorLog("搜索文档出错:" + err.Error())
|
||||
this.ViewError("搜索文档错误!")
|
||||
}
|
||||
// 过滤一下没权限的空间
|
||||
realDocuments := []map[string]string{}
|
||||
for _, document := range documents {
|
||||
spaceId, _ := document["space_id"]
|
||||
documentId, _ := document["document_id"]
|
||||
if _, ok := spaceIdsMap[spaceId]; !ok {
|
||||
continue
|
||||
}
|
||||
if searchType != "title" {
|
||||
searchContent, ok := searchDocContents[documentId]
|
||||
if !ok || searchContent == "" {
|
||||
continue
|
||||
}
|
||||
document["search_content"] = searchContent
|
||||
}
|
||||
realDocuments = append(realDocuments, document)
|
||||
}
|
||||
|
||||
this.Data["search_type"] = searchType
|
||||
this.Data["keyword"] = keyword
|
||||
this.Data["documents"] = realDocuments
|
||||
this.Data["count"] = len(realDocuments)
|
||||
this.viewLayout("main/search", "default")
|
||||
}
|
||||
@@ -0,0 +1,531 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/phachon/mm-wiki/app"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/services"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/logs"
|
||||
)
|
||||
|
||||
type PageController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// document page view
|
||||
func (this *PageController) View() {
|
||||
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.ViewError("文档未找到!")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
isVisit, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isVisit {
|
||||
this.ViewError("您没有权限访问该空间!")
|
||||
}
|
||||
|
||||
// get parent documents by document
|
||||
parentDocuments, pageFile, err := models.DocumentModel.GetParentDocumentsByDocument(document)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找父文档失败:" + err.Error())
|
||||
this.ViewError("查找父文档失败!")
|
||||
}
|
||||
if len(parentDocuments) == 0 {
|
||||
this.ViewError("父文档不存在!")
|
||||
}
|
||||
|
||||
// get document content
|
||||
documentContent, err := utils.Document.GetContentByPageFile(pageFile)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
|
||||
// get edit user and create user
|
||||
users, err := models.UserModel.GetUsersByUserIds([]string{document["create_user_id"], document["edit_user_id"]})
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(users) == 0 {
|
||||
this.ViewError("文档创建用户不存在!")
|
||||
}
|
||||
|
||||
var createUser = map[string]string{}
|
||||
var editUser = map[string]string{}
|
||||
for _, user := range users {
|
||||
if user["user_id"] == document["create_user_id"] {
|
||||
createUser = user
|
||||
}
|
||||
if user["user_id"] == document["edit_user_id"] {
|
||||
editUser = user
|
||||
}
|
||||
}
|
||||
|
||||
collectionId := "0"
|
||||
collection, err := models.CollectionModel.GetCollectionByUserIdTypeAndResourceId(this.UserId, models.Collection_Type_Doc, documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("文档查找失败!")
|
||||
}
|
||||
if len(collection) > 0 {
|
||||
collectionId = collection["collection_id"]
|
||||
}
|
||||
|
||||
this.Data["is_editor"] = isEditor
|
||||
this.Data["space"] = space
|
||||
this.Data["create_user"] = createUser
|
||||
this.Data["edit_user"] = editUser
|
||||
this.Data["document"] = document
|
||||
this.Data["collection_id"] = collectionId
|
||||
this.Data["page_content"] = documentContent
|
||||
this.Data["parent_documents"] = parentDocuments
|
||||
this.viewLayout("page/view", "document_page")
|
||||
}
|
||||
|
||||
// page edit
|
||||
func (this *PageController) Edit() {
|
||||
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.ViewError("文档未找到!")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("修改文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("修改文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("文档所在空间不存在!")
|
||||
}
|
||||
// check space visit_level
|
||||
_, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isEditor {
|
||||
this.ViewError("您没有权限修改该空间下文档!")
|
||||
}
|
||||
|
||||
// get parent documents by document
|
||||
_, pageFile, err := models.DocumentModel.GetParentDocumentsByDocument(document)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找父文档失败:" + err.Error())
|
||||
this.ViewError("查找父文档失败!")
|
||||
}
|
||||
|
||||
// get document content
|
||||
documentContent, err := utils.Document.GetContentByPageFile(pageFile)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
|
||||
autoFollowDoc := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyAutoFollowdoc, "0")
|
||||
sendEmail := models.ConfigModel.GetConfigValueByKey(models.ConfigKeySendEmail, "0")
|
||||
|
||||
this.Data["sendEmail"] = sendEmail
|
||||
this.Data["autoFollowDoc"] = autoFollowDoc
|
||||
this.Data["page_content"] = documentContent
|
||||
this.Data["document"] = document
|
||||
this.viewLayout("page/edit", "document_page")
|
||||
}
|
||||
|
||||
// page modify
|
||||
func (this *PageController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/space/index")
|
||||
}
|
||||
documentId := this.GetString("document_id", "")
|
||||
newName := strings.TrimSpace(this.GetString("name", ""))
|
||||
documentContent := this.GetString("document_page_editor-markdown-doc", "")
|
||||
comment := strings.TrimSpace(this.GetString("comment", ""))
|
||||
isNoticeUser := strings.TrimSpace(this.GetString("is_notice_user", "0"))
|
||||
isFollowDoc := strings.TrimSpace(this.GetString("is_follow_doc", "0"))
|
||||
|
||||
// rm document_page_editor-markdown-doc
|
||||
this.Ctx.Request.PostForm.Del("document_page_editor-markdown-doc")
|
||||
|
||||
if documentId == "" {
|
||||
this.jsonError("您没有选择文档!")
|
||||
}
|
||||
if newName == "" {
|
||||
this.jsonError("文档名称不能为空!")
|
||||
}
|
||||
match, err := regexp.MatchString(`[\\\\/:*?\"<>、|]`, newName)
|
||||
if err != nil {
|
||||
this.jsonError("文档名称格式不正确!")
|
||||
}
|
||||
if match {
|
||||
this.jsonError("文档名称格式不正确!")
|
||||
}
|
||||
if newName == utils.Document_Default_FileName {
|
||||
this.jsonError("文档名称不能为 " + utils.Document_Default_FileName + " !")
|
||||
}
|
||||
//if comment == "" {
|
||||
// this.jsonError("必须输入此次修改的备注!")
|
||||
//}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("保存文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.jsonError("文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("保存文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("文档所在空间不存在!")
|
||||
}
|
||||
// check space document privilege
|
||||
_, isEditor, _ := this.GetDocumentPrivilege(space)
|
||||
if !isEditor {
|
||||
this.jsonError("您没有权限修改该空间下文档!")
|
||||
}
|
||||
|
||||
// not allow update space document home page name
|
||||
if document["parent_id"] == "0" {
|
||||
newName = document["name"]
|
||||
}
|
||||
// check document name
|
||||
if newName != document["name"] {
|
||||
newDocument, err := models.DocumentModel.GetDocumentByNameParentIdAndSpaceId(newName,
|
||||
document["parent_id"], document["space_id"], utils.Convert.StringToInt(document["type"]))
|
||||
if err != nil {
|
||||
this.ErrorLog("修改文档失败:" + err.Error())
|
||||
this.jsonError("保存文档失败!")
|
||||
}
|
||||
if len(newDocument) != 0 {
|
||||
this.jsonError("该文档名称已经存在!")
|
||||
}
|
||||
}
|
||||
|
||||
// update document and file content
|
||||
updateValue := map[string]interface{}{
|
||||
"name": newName,
|
||||
"edit_user_id": this.UserId,
|
||||
}
|
||||
_, err = models.DocumentModel.UpdateDBAndFile(documentId, spaceId, document, documentContent, updateValue, comment)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改文档 " + documentId + " 失败:" + err.Error())
|
||||
this.jsonError("修改文档失败!")
|
||||
}
|
||||
|
||||
// send email to follow user
|
||||
if isNoticeUser == "1" {
|
||||
logInfo := this.GetLogInfoByCtx()
|
||||
url := fmt.Sprintf("%s:%d/document/index?document_id=%s", this.Ctx.Input.Site(), this.Ctx.Input.Port(), documentId)
|
||||
go func(documentId string, username string, comment string, url string) {
|
||||
err := sendEmail(documentId, username, comment, url)
|
||||
if err != nil {
|
||||
logInfo["message"] = "更新文档时发送邮件通知失败:" + err.Error()
|
||||
logInfo["level"] = models.Log_Level_Error
|
||||
models.LogModel.Insert(logInfo)
|
||||
logs.Error("更新文档时发送邮件通知失败:" + err.Error())
|
||||
}
|
||||
}(documentId, this.User["username"], comment, url)
|
||||
}
|
||||
// follow doc
|
||||
if isFollowDoc == "1" {
|
||||
go func(userId string, documentId string) {
|
||||
_, _ = models.FollowModel.FollowDocument(userId, documentId)
|
||||
}(this.UserId, documentId)
|
||||
}
|
||||
// 更新文档索引
|
||||
go func(documentId string) {
|
||||
_ = services.DocIndexService.ForceUpdateDocIndexByDocId(documentId)
|
||||
}(documentId)
|
||||
|
||||
this.InfoLog("修改文档 " + documentId + " 成功")
|
||||
this.jsonSuccess("文档修改成功!", nil, "/document/index?document_id="+documentId)
|
||||
}
|
||||
|
||||
// document share display
|
||||
func (this *PageController) Display() {
|
||||
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.ViewError("文档未找到!")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
|
||||
// get document space
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("分享文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("保存文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("文档所在空间不存在!")
|
||||
}
|
||||
|
||||
// check space is allow display
|
||||
if space["is_share"] != fmt.Sprintf("%d", models.Space_Share_True) {
|
||||
this.ViewError("该文档不能被分享!")
|
||||
}
|
||||
|
||||
// get parent documents by document
|
||||
parentDocuments, pageFile, err := models.DocumentModel.GetParentDocumentsByDocument(document)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找父文档失败:" + err.Error())
|
||||
this.ViewError("查找父文档失败!")
|
||||
}
|
||||
if len(parentDocuments) == 0 {
|
||||
this.ViewError("父文档不存在!")
|
||||
}
|
||||
|
||||
// get document content
|
||||
documentContent, err := utils.Document.GetContentByPageFile(pageFile)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 内容失败:" + err.Error())
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
|
||||
// get edit user and create user
|
||||
users, err := models.UserModel.GetUsersByUserIds([]string{document["create_user_id"], document["edit_user_id"]})
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(users) == 0 {
|
||||
this.ViewError("文档创建用户不存在!")
|
||||
}
|
||||
|
||||
var createUser = map[string]string{}
|
||||
var editUser = map[string]string{}
|
||||
for _, user := range users {
|
||||
if user["user_id"] == document["create_user_id"] {
|
||||
createUser = user
|
||||
}
|
||||
if user["user_id"] == document["edit_user_id"] {
|
||||
editUser = user
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["create_user"] = createUser
|
||||
this.Data["edit_user"] = editUser
|
||||
this.Data["document"] = document
|
||||
this.Data["page_content"] = documentContent
|
||||
this.Data["parent_documents"] = parentDocuments
|
||||
this.viewLayout("page/display", "document_share")
|
||||
}
|
||||
|
||||
// export file
|
||||
func (this *PageController) Export() {
|
||||
|
||||
documentId := this.GetString("document_id", "")
|
||||
if documentId == "" {
|
||||
this.ViewError("文档未找到!")
|
||||
}
|
||||
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(document) == 0 {
|
||||
this.ViewError("文档不存在!")
|
||||
}
|
||||
|
||||
spaceId := document["space_id"]
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档 " + documentId + " 所在空间失败:" + err.Error())
|
||||
this.ViewError("查找文档失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("文档所在空间不存在!")
|
||||
}
|
||||
|
||||
// check space document privilege
|
||||
isVisit, _, _ := this.GetDocumentPrivilege(space)
|
||||
if !isVisit {
|
||||
this.ViewError("您没有权限导出该空间下文档!")
|
||||
}
|
||||
|
||||
// check space is allow export
|
||||
if space["is_export"] != fmt.Sprintf("%d", models.Space_Download_True) {
|
||||
this.ViewError("该文档不允许被导出!")
|
||||
}
|
||||
|
||||
// get parent documents by document
|
||||
parentDocuments, pageFile, err := models.DocumentModel.GetParentDocumentsByDocument(document)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找父文档失败:" + err.Error())
|
||||
this.ViewError("查找父文档失败!")
|
||||
}
|
||||
if len(parentDocuments) == 0 {
|
||||
this.ViewError("父文档不存在!")
|
||||
}
|
||||
|
||||
packFiles := []*utils.CompressFileInfo{}
|
||||
|
||||
absPageFile := utils.Document.GetAbsPageFileByPageFile(pageFile)
|
||||
// pack document file
|
||||
packFiles = append(packFiles, &utils.CompressFileInfo{
|
||||
File: absPageFile,
|
||||
PrefixPath: "",
|
||||
})
|
||||
|
||||
// get document attachments
|
||||
attachments, err := models.AttachmentModel.GetAttachmentsByDocumentId(documentId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档附件失败:" + err.Error())
|
||||
this.ViewError("查找文档附件失败!")
|
||||
}
|
||||
for _, attachment := range attachments {
|
||||
if attachment["path"] == "" {
|
||||
continue
|
||||
}
|
||||
path := attachment["path"]
|
||||
attachmentFile := filepath.Join(app.DocumentAbsDir, path)
|
||||
packFile := &utils.CompressFileInfo{
|
||||
File: attachmentFile,
|
||||
PrefixPath: filepath.Dir(path),
|
||||
}
|
||||
packFiles = append(packFiles, packFile)
|
||||
}
|
||||
var dest = fmt.Sprintf("%s/mm_wiki/%s.zip", os.TempDir(), document["name"])
|
||||
err = utils.Zipx.PackFile(packFiles, dest)
|
||||
if err != nil {
|
||||
this.ErrorLog("导出文档附件失败:" + err.Error())
|
||||
this.ViewError("导出文档失败!")
|
||||
}
|
||||
|
||||
this.Ctx.Output.Download(dest, document["name"]+".zip")
|
||||
}
|
||||
|
||||
func sendEmail(documentId string, username string, comment string, url string) error {
|
||||
|
||||
// get document by documentId
|
||||
document, err := models.DocumentModel.GetDocumentByDocumentId(documentId)
|
||||
if err != nil {
|
||||
return errors.New("发送邮件通知查找文档失败:" + err.Error())
|
||||
}
|
||||
|
||||
// get send email open config
|
||||
sendEmailConfig := models.ConfigModel.GetConfigValueByKey(models.ConfigKeySendEmail, "0")
|
||||
if sendEmailConfig == "0" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// get email config
|
||||
emailConfig, err := models.EmailModel.GetUsedEmail()
|
||||
if err != nil {
|
||||
return errors.New("发送邮件通知查找邮件服务器配置失败:" + err.Error())
|
||||
}
|
||||
if len(emailConfig) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// get follow doc user
|
||||
follows, err := models.FollowModel.GetFollowsByObjectIdAndType(documentId, models.Follow_Type_Doc)
|
||||
if err != nil {
|
||||
return errors.New("发送邮件查找关注文档用户失败:" + err.Error())
|
||||
}
|
||||
if len(follows) == 0 {
|
||||
return nil
|
||||
}
|
||||
userIds := []string{}
|
||||
for _, follow := range follows {
|
||||
userIds = append(userIds, follow["user_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
return errors.New("发送邮件查找关注文档用户失败:" + err.Error())
|
||||
}
|
||||
if len(users) == 0 {
|
||||
return nil
|
||||
}
|
||||
emails := []string{}
|
||||
for _, user := range users {
|
||||
if user["email"] != "" {
|
||||
emails = append(emails, user["email"])
|
||||
}
|
||||
}
|
||||
|
||||
// get parent documents by document
|
||||
parentDocuments, pageFile, err := models.DocumentModel.GetParentDocumentsByDocument(document)
|
||||
if err != nil {
|
||||
return errors.New("查找文档内容失败: " + err.Error())
|
||||
}
|
||||
if len(parentDocuments) == 0 {
|
||||
return errors.New("查找文档内容失败")
|
||||
}
|
||||
// get document content
|
||||
documentContent, err := utils.Document.GetContentByPageFile(pageFile)
|
||||
if err != nil {
|
||||
return errors.New("查找文档内容失败: " + err.Error())
|
||||
}
|
||||
|
||||
if len([]byte(documentContent)) > 500 {
|
||||
documentContent = string([]byte(documentContent)[:500])
|
||||
}
|
||||
|
||||
documentValue := document
|
||||
documentValue["content"] = documentContent
|
||||
documentValue["username"] = username
|
||||
documentValue["comment"] = comment
|
||||
documentValue["url"] = url
|
||||
|
||||
emailTemplate := beego.BConfig.WebConfig.ViewsPath + "/system/email/template.html"
|
||||
body, err := utils.Email.MakeDocumentHtmlBody(documentValue, emailTemplate)
|
||||
if err != nil {
|
||||
return errors.New("发送邮件生成模板失败:" + err.Error())
|
||||
}
|
||||
// start send email
|
||||
return utils.Email.Send(emailConfig, emails, "文档更新通知", body)
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
)
|
||||
|
||||
type SpaceController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *SpaceController) Index() {
|
||||
|
||||
// get space tags
|
||||
spaceTags := map[string]string{}
|
||||
spaces, err := models.SpaceModel.GetSpaces()
|
||||
if err == nil {
|
||||
for _, space := range spaces {
|
||||
tags := space["tags"]
|
||||
if tags == "" {
|
||||
continue
|
||||
}
|
||||
tagList := strings.Split(tags, ",")
|
||||
for _, tagName := range tagList {
|
||||
spaceTags[tagName] = tagName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["spaceTags"] = spaceTags
|
||||
this.viewLayout("space/index", "space")
|
||||
}
|
||||
|
||||
func (this *SpaceController) List() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
|
||||
limit := (page - 1) * number
|
||||
var err error
|
||||
var count int64
|
||||
var spaces []map[string]string
|
||||
if keyword != "" {
|
||||
count, err = models.SpaceModel.CountSpacesByKeyword(keyword)
|
||||
spaces, err = models.SpaceModel.GetSpacesByKeywordAndLimit(keyword, limit, number)
|
||||
} else {
|
||||
count, err = models.SpaceModel.CountSpaces()
|
||||
spaces, err = models.SpaceModel.GetSpacesByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取全部空间列表失败: " + err.Error())
|
||||
this.ViewError("获取空间列表失败", "/main/index")
|
||||
}
|
||||
|
||||
collectionSpaces, err := models.CollectionModel.GetCollectionsByUserIdAndType(this.UserId, models.Collection_Type_Space)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取全部空间列表失败: " + err.Error())
|
||||
this.ViewError("获取全部空间列表失败", "/main/index")
|
||||
}
|
||||
for _, space := range spaces {
|
||||
space["collection"] = "0"
|
||||
space["collection_id"] = "0"
|
||||
for _, collectionSpace := range collectionSpaces {
|
||||
if collectionSpace["resource_id"] == space["space_id"] {
|
||||
space["collection"] = "1"
|
||||
space["collection_id"] = collectionSpace["collection_id"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["spaces"] = spaces
|
||||
this.Data["keyword"] = keyword
|
||||
this.Data["count"] = count
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("space/list", "default")
|
||||
}
|
||||
|
||||
func (this *SpaceController) Member() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
spaceId := strings.TrimSpace(this.GetString("space_id", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
|
||||
if spaceId == "" {
|
||||
this.ViewError("没有选择空间!")
|
||||
}
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间 " + spaceId + " 失败:" + err.Error())
|
||||
this.ViewError("空间不存在!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("空间不存在!")
|
||||
}
|
||||
|
||||
limit := (page - 1) * number
|
||||
|
||||
count, err := models.SpaceUserModel.CountSpaceUsersBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间成员列表失败!", "/space/index")
|
||||
}
|
||||
spaceUsers, err := models.SpaceUserModel.GetSpaceUsersBySpaceIdAndLimit(spaceId, limit, number)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间成员列表失败!", "/space/index")
|
||||
}
|
||||
|
||||
var userIds = []string{}
|
||||
for _, spaceUser := range spaceUsers {
|
||||
userIds = append(userIds, spaceUser["user_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间成员列表失败!", "/space/index")
|
||||
}
|
||||
for _, user := range users {
|
||||
for _, spaceUser := range spaceUsers {
|
||||
if spaceUser["user_id"] == user["user_id"] {
|
||||
user["space_privilege"] = spaceUser["privilege"]
|
||||
user["space_user_id"] = spaceUser["space_user_id"]
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["users"] = users
|
||||
this.Data["space_id"] = spaceId
|
||||
this.SetPaginator(number, count)
|
||||
|
||||
// check user space privilege
|
||||
_, _, isManager := this.GetDocumentPrivilege(space)
|
||||
if isManager {
|
||||
var otherUsers = []map[string]string{}
|
||||
if len(userIds) > 0 {
|
||||
otherUsers, err = models.UserModel.GetUserByNotUserIds(userIds)
|
||||
} else {
|
||||
otherUsers, err = models.UserModel.GetUsers()
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间成员列表失败!", "/space/index")
|
||||
}
|
||||
this.Data["otherUsers"] = otherUsers
|
||||
this.viewLayout("space/manager_member", "default")
|
||||
} else {
|
||||
this.viewLayout("space/member", "default")
|
||||
}
|
||||
}
|
||||
|
||||
func (this *SpaceController) AddMember() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/space/index")
|
||||
}
|
||||
spaceId := strings.TrimSpace(this.GetString("space_id", ""))
|
||||
userId := this.GetString("user_id", "")
|
||||
privilege := strings.TrimSpace(this.GetString("privilege", "0"))
|
||||
|
||||
if spaceId == "" {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
if userId == "" {
|
||||
this.jsonError("没有选择用户!")
|
||||
}
|
||||
if privilege == "" {
|
||||
this.jsonError("没有选择用户空间权限!")
|
||||
}
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加空间 " + spaceId + " 成员失败: " + err.Error())
|
||||
this.jsonError("添加空间成员失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
|
||||
// check login user space member privilege
|
||||
_, _, isManager := this.GetDocumentPrivilege(space)
|
||||
if !isManager {
|
||||
this.jsonError("您没有权限添加该空间成员!", "/space/index")
|
||||
}
|
||||
|
||||
spaceUser, err := models.SpaceUserModel.GetSpaceUserBySpaceIdAndUserId(spaceId, userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加空间 " + spaceId + " 成员 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("添加空间成员失败!")
|
||||
}
|
||||
if len(spaceUser) > 0 {
|
||||
this.jsonError("该用户已经是空间成员!")
|
||||
}
|
||||
|
||||
insertValue := map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"space_id": spaceId,
|
||||
"privilege": privilege,
|
||||
"create_time": time.Now().Unix(),
|
||||
"update_time": time.Now().Unix(),
|
||||
}
|
||||
_, err = models.SpaceUserModel.Insert(insertValue)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加空间 " + spaceId + " 成员 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("添加成员失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("空间 " + spaceId + " 添加成员 " + userId + " 成功")
|
||||
this.jsonSuccess("添加成员成功!", nil, "/space/member?space_id="+spaceId)
|
||||
}
|
||||
|
||||
func (this *SpaceController) RemoveMember() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/space/index")
|
||||
}
|
||||
spaceId := this.GetString("space_id", "")
|
||||
userId := this.GetString("user_id", "")
|
||||
spaceUserId := this.GetString("space_user_id", "")
|
||||
|
||||
if spaceUserId == "" {
|
||||
this.jsonError("空间成员不存在!")
|
||||
}
|
||||
if spaceId == "" {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
if userId == "" {
|
||||
this.jsonError("用户不存在!")
|
||||
}
|
||||
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("移除空间 " + spaceId + " 成员失败: " + err.Error())
|
||||
this.jsonError("移除空间成员失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
|
||||
// check login user space member privilege
|
||||
_, _, isManager := this.GetDocumentPrivilege(space)
|
||||
if !isManager {
|
||||
this.ViewError("您没有权限移除该空间成员!", "/space/index")
|
||||
}
|
||||
|
||||
err = models.SpaceUserModel.Delete(spaceUserId)
|
||||
if err != nil {
|
||||
this.ErrorLog("移除空间 " + spaceId + " 下成员 " + userId + " 失败:" + err.Error())
|
||||
this.jsonError("移除成员失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("移除空间 " + spaceId + " 下成员 " + userId + " 成功")
|
||||
this.jsonSuccess("移除成员成功!", nil, "/space/member?space_id="+spaceId)
|
||||
}
|
||||
|
||||
func (this *SpaceController) ModifyMember() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/space/list")
|
||||
}
|
||||
spaceUserId := this.GetString("space_user_id", "")
|
||||
privilege := this.GetString("privilege", "0")
|
||||
userId := this.GetString("user_id", "")
|
||||
spaceId := this.GetString("space_id", "")
|
||||
|
||||
if spaceUserId == "" {
|
||||
this.jsonError("更新权限错误!")
|
||||
}
|
||||
if privilege == "" {
|
||||
this.jsonError("没有选择权限!")
|
||||
}
|
||||
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("更新空间 " + spaceId + " 成员权限失败: " + err.Error())
|
||||
this.jsonError("更新空间成员权限失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
|
||||
// check login user space member privilege
|
||||
_, _, isManager := this.GetDocumentPrivilege(space)
|
||||
if !isManager {
|
||||
this.ViewError("您没有权限修改该空间成员!", "/space/index")
|
||||
}
|
||||
|
||||
_, err = models.SpaceUserModel.Update(spaceUserId, map[string]interface{}{
|
||||
"privilege": privilege,
|
||||
"update_time": time.Now().Unix(),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorLog("更新空间 " + spaceId + " 下成员 " + userId + " 权限失败:" + err.Error())
|
||||
this.jsonError("更新权限失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("更新空间 " + spaceId + " 下成员 " + userId + " 权限成功")
|
||||
this.jsonSuccess("更新权限成功!", nil)
|
||||
}
|
||||
|
||||
func (this *SpaceController) Collection() {
|
||||
|
||||
collectionSpaces, err := models.CollectionModel.GetCollectionsByUserIdAndType(this.UserId, models.Collection_Type_Space)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取收藏空间列表失败: " + err.Error())
|
||||
this.ViewError("获取收藏空间列表失败", "/space/list")
|
||||
}
|
||||
|
||||
spaceIds := []string{}
|
||||
for _, collectionSpace := range collectionSpaces {
|
||||
spaceIds = append(spaceIds, collectionSpace["resource_id"])
|
||||
}
|
||||
|
||||
spaces, err := models.SpaceModel.GetSpaceBySpaceIds(spaceIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取收藏空间列表失败: " + err.Error())
|
||||
this.ViewError("获取收藏空间列表失败", "/space/list")
|
||||
}
|
||||
|
||||
for _, space := range spaces {
|
||||
space["collection_id"] = "0"
|
||||
for _, collectionSpace := range collectionSpaces {
|
||||
if collectionSpace["resource_id"] == space["space_id"] {
|
||||
space["collection_id"] = collectionSpace["collection_id"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["spaces"] = spaces
|
||||
this.Data["count"] = len(spaces)
|
||||
this.viewLayout("space/collection", "default")
|
||||
}
|
||||
|
||||
func (this *SpaceController) Document() {
|
||||
|
||||
spaceId := this.GetString("space_id", "")
|
||||
if spaceId == "" {
|
||||
this.ViewError("空间不存在")
|
||||
}
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间 " + spaceId + " 失败:" + err.Error())
|
||||
this.ViewError("空间不存在!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("空间不存在!")
|
||||
}
|
||||
|
||||
// check space visit_level
|
||||
isVisit, _, _ := this.GetDocumentPrivilege(space)
|
||||
if !isVisit {
|
||||
this.ViewError("您没有权限访问该空间!")
|
||||
}
|
||||
|
||||
spaceDocument, err := models.DocumentModel.GetSpaceDefaultDocument(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间 " + spaceId + " 失败:" + err.Error())
|
||||
this.ViewError("查找空间页面失败!")
|
||||
}
|
||||
if len(spaceDocument) == 0 {
|
||||
this.ViewError("空间首页不存在!")
|
||||
}
|
||||
|
||||
documentId := spaceDocument["document_id"]
|
||||
|
||||
this.Redirect("/document/index?document_id="+documentId, 302)
|
||||
}
|
||||
|
||||
func (this *SpaceController) Search() {
|
||||
|
||||
tagName := strings.TrimSpace(this.GetString("tag", ""))
|
||||
|
||||
spaces, err := models.SpaceModel.GetSpacesByTags(tagName)
|
||||
if err != nil {
|
||||
this.ErrorLog("搜索空间标签列表失败: " + err.Error())
|
||||
this.ViewError("获取空间列表失败", "/main/index")
|
||||
}
|
||||
|
||||
collectionSpaces, err := models.CollectionModel.GetCollectionsByUserIdAndType(this.UserId, models.Collection_Type_Space)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取全部空间列表失败: " + err.Error())
|
||||
this.ViewError("获取全部空间列表失败", "/main/index")
|
||||
}
|
||||
for _, space := range spaces {
|
||||
space["collection"] = "0"
|
||||
space["collection_id"] = "0"
|
||||
for _, collectionSpace := range collectionSpaces {
|
||||
if collectionSpace["resource_id"] == space["space_id"] {
|
||||
space["collection"] = "1"
|
||||
space["collection_id"] = collectionSpace["collection_id"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["tag"] = tagName
|
||||
this.Data["spaces"] = spaces
|
||||
this.Data["count"] = len(spaces)
|
||||
this.viewLayout("space/search", "default")
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/phachon/mm-wiki/app"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
type TemplateController struct {
|
||||
beego.Controller
|
||||
UserId string
|
||||
User map[string]string
|
||||
controllerName string
|
||||
actionName string
|
||||
}
|
||||
|
||||
type JsonResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message interface{} `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
Redirect map[string]interface{} `json:"redirect"`
|
||||
}
|
||||
|
||||
// prepare
|
||||
func (this *TemplateController) Prepare() {
|
||||
controllerName, action := this.GetControllerAndAction()
|
||||
this.controllerName = strings.ToLower(controllerName[0 : len(controllerName)-10])
|
||||
this.actionName = strings.ToLower(action)
|
||||
this.Data["navName"] = this.controllerName
|
||||
this.Data["version"] = app.Version
|
||||
this.Data["copyright"] = app.CopyRight
|
||||
|
||||
if this.controllerName == "author" {
|
||||
return
|
||||
}
|
||||
|
||||
if !this.isLogin() {
|
||||
if this.IsAjax() {
|
||||
this.JsonError("未登录或登录已失效!", nil, "/author/index")
|
||||
} else {
|
||||
this.Redirect("/author/index", 302)
|
||||
}
|
||||
this.StopRun()
|
||||
}
|
||||
|
||||
if !this.checkAccess() {
|
||||
if this.IsPost() {
|
||||
this.JsonError("抱歉,您没有权限操作!", nil, "/system/main/index")
|
||||
} else {
|
||||
this.ViewError("您没有权限访问该页面!", "/system/main/index")
|
||||
}
|
||||
this.StopRun()
|
||||
}
|
||||
}
|
||||
|
||||
// check is login
|
||||
func (this *TemplateController) isLogin() bool {
|
||||
|
||||
if this.controllerName == "page" && this.actionName == "display" {
|
||||
return true
|
||||
}
|
||||
|
||||
passport := beego.AppConfig.String("author::passport")
|
||||
cookie := this.Ctx.GetCookie(passport)
|
||||
// cookie is empty
|
||||
if cookie == "" {
|
||||
return false
|
||||
}
|
||||
user := this.GetSession("author")
|
||||
// session is empty
|
||||
if user == nil {
|
||||
return false
|
||||
}
|
||||
cookieValue, _ := utils.Encrypt.Base64Decode(cookie)
|
||||
identifyList := strings.Split(cookieValue, "@")
|
||||
if cookieValue == "" || len(identifyList) != 2 {
|
||||
return false
|
||||
}
|
||||
username := identifyList[0]
|
||||
identify := identifyList[1]
|
||||
userValue := user.(map[string]string)
|
||||
|
||||
// cookie session name
|
||||
if username != userValue["username"] {
|
||||
return false
|
||||
}
|
||||
// UAG and IP
|
||||
if identify != utils.Encrypt.Md5Encode(this.Ctx.Request.UserAgent()+this.GetClientIp()+userValue["password"]) {
|
||||
return false
|
||||
}
|
||||
// flush session
|
||||
newUser, err := models.UserModel.GetUserByUserId(userValue["user_id"])
|
||||
if err != nil {
|
||||
this.ErrorLog("登录成功 flush session 失败:" + err.Error())
|
||||
return false
|
||||
}
|
||||
// flush session
|
||||
this.SetSession("author", newUser)
|
||||
this.User = this.GetSession("author").(map[string]string)
|
||||
this.UserId = this.User["user_id"]
|
||||
|
||||
// 查找系统名称
|
||||
systemName := models.ConfigModel.GetConfigValueByKey(models.ConfigKeySystemName, "Markdown Mini Wiki")
|
||||
this.Data["system_name"] = systemName
|
||||
this.Data["login_user_id"] = this.UserId
|
||||
this.Data["login_username"] = this.User["username"]
|
||||
this.Data["login_role_id"] = this.User["role_id"]
|
||||
|
||||
// success
|
||||
return true
|
||||
}
|
||||
|
||||
// check access
|
||||
func (this *TemplateController) checkAccess() bool {
|
||||
path := this.Ctx.Request.URL.Path
|
||||
mca := strings.Split(strings.Trim(path, "/"), "/")
|
||||
|
||||
// must /system/controller/action
|
||||
if (len(mca) >= 3) && (strings.ToLower(mca[0]) == "system") {
|
||||
this.Data["navName"] = "system"
|
||||
// no check '/system/main/index' '/system/main/default'
|
||||
if (this.controllerName == "main" && this.actionName == "index") || this.controllerName == "main" && this.actionName == "default" {
|
||||
return true
|
||||
}
|
||||
if this.IsRoot() {
|
||||
return true
|
||||
}
|
||||
_, controllers, err := models.PrivilegeModel.GetTypePrivilegesByUserId(this.UserId)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户 " + this.UserId + " 权限失败:" + err.Error())
|
||||
return false
|
||||
}
|
||||
for _, controller := range controllers {
|
||||
action := strings.ToLower(controller["action"])
|
||||
controller := strings.ToLower(controller["controller"])
|
||||
if this.controllerName == controller && this.actionName == action {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// view layout
|
||||
func (this *TemplateController) ViewLayout(viewName, layout string) {
|
||||
this.Layout = layout + ".html"
|
||||
this.TplName = viewName + ".html"
|
||||
this.Data["title"] = "MM-Wiki"
|
||||
this.Data["copyright"] = app.CopyRight
|
||||
this.Render()
|
||||
}
|
||||
|
||||
// view layout
|
||||
func (this *TemplateController) ViewError(content string, redirect ...string) {
|
||||
this.Layout = "error/default.html"
|
||||
this.TplName = "layouts/default.html"
|
||||
var url = ""
|
||||
var sleep = "5"
|
||||
if len(redirect) == 1 {
|
||||
url = redirect[0]
|
||||
}
|
||||
if len(redirect) > 1 {
|
||||
sleep = redirect[1]
|
||||
}
|
||||
if content == "" {
|
||||
content = "操作失败"
|
||||
}
|
||||
this.Data["content"] = content
|
||||
this.Data["url"] = url
|
||||
this.Data["sleep"] = sleep
|
||||
this.Data["copyright"] = app.CopyRight
|
||||
this.Render()
|
||||
}
|
||||
|
||||
// return json success
|
||||
func (this *TemplateController) JsonSuccess(message interface{}, data ...interface{}) {
|
||||
url := ""
|
||||
sleep := 2000
|
||||
var _data interface{}
|
||||
if len(data) > 0 {
|
||||
_data = data[0]
|
||||
}
|
||||
if len(data) > 1 {
|
||||
url = data[1].(string)
|
||||
}
|
||||
if len(data) > 2 {
|
||||
sleep = data[2].(int)
|
||||
}
|
||||
this.Data["json"] = JsonResponse{
|
||||
Code: 1,
|
||||
Message: message,
|
||||
Data: _data,
|
||||
Redirect: map[string]interface{}{
|
||||
"url": url,
|
||||
"sleep": sleep,
|
||||
},
|
||||
}
|
||||
|
||||
j, err := json.MarshalIndent(this.Data["json"], "", "\t")
|
||||
if err != nil {
|
||||
this.Abort(err.Error())
|
||||
} else {
|
||||
this.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
|
||||
this.Abort(string(j))
|
||||
}
|
||||
}
|
||||
|
||||
// return json error
|
||||
func (this *TemplateController) JsonError(message interface{}, data ...interface{}) {
|
||||
url := ""
|
||||
sleep := 2000
|
||||
var _data interface{}
|
||||
if len(data) > 0 {
|
||||
_data = data[0]
|
||||
}
|
||||
if len(data) > 1 {
|
||||
url = data[1].(string)
|
||||
}
|
||||
if len(data) > 2 {
|
||||
sleep = data[2].(int)
|
||||
}
|
||||
this.Data["json"] = JsonResponse{
|
||||
Code: 0,
|
||||
Message: message,
|
||||
Data: _data,
|
||||
Redirect: map[string]interface{}{
|
||||
"url": url,
|
||||
"sleep": sleep,
|
||||
},
|
||||
}
|
||||
j, err := json.MarshalIndent(this.Data["json"], "", " \t")
|
||||
if err != nil {
|
||||
this.Abort(err.Error())
|
||||
} else {
|
||||
this.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
|
||||
this.Abort(string(j))
|
||||
}
|
||||
}
|
||||
|
||||
// get client ip
|
||||
func (this *TemplateController) GetClientIp() string {
|
||||
s := strings.Split(this.Ctx.Request.RemoteAddr, ":")
|
||||
return s[0]
|
||||
}
|
||||
|
||||
// paginator
|
||||
func (this *TemplateController) SetPaginator(per int, nums int64) *utils.Paginator {
|
||||
p := utils.NewPaginator(this.Ctx.Request, per, nums)
|
||||
this.Data["paginator"] = p
|
||||
return p
|
||||
}
|
||||
|
||||
// is Post
|
||||
func (this *TemplateController) IsPost() bool {
|
||||
return this.Ctx.Input.Method() == "POST"
|
||||
}
|
||||
|
||||
// is Get
|
||||
func (this *TemplateController) IsGet() bool {
|
||||
return this.Ctx.Input.Method() == "GET"
|
||||
}
|
||||
|
||||
// 是否是超级管理员
|
||||
func (this *TemplateController) IsRoot() bool {
|
||||
return this.User["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id)
|
||||
}
|
||||
|
||||
func (this *TemplateController) GetRangeInt(key string, def int, min int, max int) (n int, err error) {
|
||||
n, err = this.GetInt(key, def)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if n < min {
|
||||
n = min
|
||||
}
|
||||
if n > max {
|
||||
n = max
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (this *TemplateController) GetDocumentPrivilege(space map[string]string) (isVisit, isEditor, isManager bool) {
|
||||
|
||||
if this.IsRoot() {
|
||||
return true, true, true
|
||||
}
|
||||
spaceUser, _ := models.SpaceUserModel.GetSpaceUserBySpaceIdAndUserId(space["space_id"], this.UserId)
|
||||
if len(spaceUser) == 0 {
|
||||
if space["visit_level"] == models.Space_VisitLevel_Private {
|
||||
return false, false, false
|
||||
} else {
|
||||
return true, false, false
|
||||
}
|
||||
}
|
||||
if spaceUser["privilege"] == fmt.Sprintf("%d", models.SpaceUser_Privilege_Editor) {
|
||||
return true, true, false
|
||||
}
|
||||
if spaceUser["privilege"] == fmt.Sprintf("%d", models.SpaceUser_Privilege_Manager) {
|
||||
return true, true, true
|
||||
}
|
||||
return true, false, false
|
||||
}
|
||||
|
||||
// insert action log
|
||||
func (this *TemplateController) RecordLog(message string, level int) {
|
||||
userAgent := this.Ctx.Request.UserAgent()
|
||||
referer := this.Ctx.Request.Referer()
|
||||
getParams := this.Ctx.Request.URL.String()
|
||||
path := this.Ctx.Request.URL.Path
|
||||
this.Ctx.Request.ParseForm()
|
||||
postParamsMap := map[string][]string(this.Ctx.Request.PostForm)
|
||||
postParams, _ := json.Marshal(postParamsMap)
|
||||
user := this.GetSession("author").(map[string]string)
|
||||
|
||||
logValue := map[string]interface{}{
|
||||
"level": level,
|
||||
"path": path,
|
||||
"get": getParams,
|
||||
"post": string(postParams),
|
||||
"message": message,
|
||||
"ip": this.GetClientIp(),
|
||||
"user_agent": userAgent,
|
||||
"referer": referer,
|
||||
"user_id": user["user_id"],
|
||||
"username": user["username"],
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
|
||||
models.LogModel.Insert(logValue)
|
||||
}
|
||||
|
||||
func (this *TemplateController) ErrorLog(message string) {
|
||||
this.RecordLog(message, models.Log_Level_Error)
|
||||
}
|
||||
|
||||
func (this *TemplateController) WarningLog(message string) {
|
||||
this.RecordLog(message, models.Log_Level_Warning)
|
||||
}
|
||||
|
||||
func (this *TemplateController) InfoLog(message string) {
|
||||
this.RecordLog(message, models.Log_Level_Info)
|
||||
}
|
||||
|
||||
func (this *TemplateController) DebugLog(message string) {
|
||||
this.RecordLog(message, models.Log_Level_Debug)
|
||||
}
|
||||
|
||||
func (this *TemplateController) GetLogInfoByCtx() map[string]interface{} {
|
||||
userAgent := this.Ctx.Request.UserAgent()
|
||||
referer := this.Ctx.Request.Referer()
|
||||
getParams := this.Ctx.Request.URL.String()
|
||||
path := this.Ctx.Request.URL.Path
|
||||
this.Ctx.Request.ParseForm()
|
||||
postParamsMap := map[string][]string(this.Ctx.Request.PostForm)
|
||||
postParams, _ := json.Marshal(postParamsMap)
|
||||
user := this.GetSession("author").(map[string]string)
|
||||
logValue := map[string]interface{}{
|
||||
"level": models.Log_Level_Info,
|
||||
"path": path,
|
||||
"get": getParams,
|
||||
"post": string(postParams),
|
||||
"message": "",
|
||||
"ip": this.GetClientIp(),
|
||||
"user_agent": userAgent,
|
||||
"referer": referer,
|
||||
"user_id": user["user_id"],
|
||||
"username": user["username"],
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
return logValue
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *UserController) Index() {
|
||||
this.viewLayout("user/index", "user")
|
||||
}
|
||||
|
||||
func (this *UserController) List() {
|
||||
|
||||
keywords := map[string]string{}
|
||||
page, _ := this.GetInt("page", 1)
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
username := strings.TrimSpace(this.GetString("username", ""))
|
||||
if username != "" {
|
||||
keywords["username"] = username
|
||||
}
|
||||
|
||||
limit := (page - 1) * number
|
||||
var err error
|
||||
var count int64
|
||||
var users []map[string]string
|
||||
if len(keywords) != 0 {
|
||||
count, err = models.UserModel.CountUsersByKeywords(keywords)
|
||||
users, err = models.UserModel.GetUsersByKeywordsAndLimit(keywords, limit, number)
|
||||
} else {
|
||||
count, err = models.UserModel.CountUsers()
|
||||
users, err = models.UserModel.GetUsersByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取全部用户列表失败: " + err.Error())
|
||||
this.ViewError("获取全部用户列表失败", "/main/index")
|
||||
}
|
||||
|
||||
followUsers, err := models.FollowModel.GetFollowsByUserIdAndType(this.UserId, models.Follow_Type_User)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取全部用户列表失败: " + err.Error())
|
||||
this.ViewError("获取全部用户列表失败", "/main/index")
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
user["follow"] = "0"
|
||||
user["follow_id"] = "0"
|
||||
for _, followUser := range followUsers {
|
||||
if followUser["object_id"] == user["user_id"] {
|
||||
user["follow_id"] = followUser["follow_id"]
|
||||
user["follow"] = "1"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["users"] = users
|
||||
this.Data["count"] = count
|
||||
this.Data["login_user_id"] = this.UserId
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("user/list", "default")
|
||||
}
|
||||
|
||||
func (this *UserController) Follow() {
|
||||
|
||||
followUsers, err := models.FollowModel.GetFollowsByUserIdAndType(this.UserId, models.Follow_Type_User)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/user/list")
|
||||
}
|
||||
|
||||
userIds := []string{}
|
||||
for _, followUser := range followUsers {
|
||||
userIds = append(userIds, followUser["object_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/user/list")
|
||||
}
|
||||
for _, user := range users {
|
||||
user["follow_id"] = "0"
|
||||
for _, followUser := range followUsers {
|
||||
if followUser["object_id"] == user["user_id"] {
|
||||
user["follow_id"] = followUser["follow_id"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["users"] = users
|
||||
this.Data["count"] = len(users)
|
||||
this.viewLayout("user/follow", "default")
|
||||
}
|
||||
|
||||
func (this *UserController) Info() {
|
||||
|
||||
userId := this.GetString("user_id", "")
|
||||
if userId == "" {
|
||||
this.ViewError("用户不存在!", "/main/index")
|
||||
}
|
||||
|
||||
if this.UserId == userId {
|
||||
this.Redirect("/system/main/index", 302)
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户出错:" + err.Error())
|
||||
this.ViewError("查找用户出错!", "/main/index")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.ViewError("用户不存在!", "/main/index")
|
||||
}
|
||||
|
||||
logDocuments, err := models.LogDocumentModel.GetLogDocumentsByUserIdAndLimit(userId, 0, 10)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户活动出错:" + err.Error())
|
||||
this.ViewError("查找用户活动出错!", "/main/index")
|
||||
}
|
||||
|
||||
docIds := []string{}
|
||||
for _, logDocument := range logDocuments {
|
||||
docIds = append(docIds, logDocument["document_id"])
|
||||
}
|
||||
documents, err := models.DocumentModel.GetDocumentsByDocumentIds(docIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户活动出错: " + err.Error())
|
||||
this.ViewError("查找用户活动出错", "/main/index")
|
||||
}
|
||||
|
||||
for _, logDocument := range logDocuments {
|
||||
for _, document := range documents {
|
||||
if document["document_id"] == logDocument["document_id"] {
|
||||
logDocument["document_id"] = document["document_id"]
|
||||
logDocument["document_name"] = document["name"]
|
||||
logDocument["document_type"] = document["type"]
|
||||
logDocument["update_time"] = document["update_time"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["user"] = user
|
||||
this.Data["logDocuments"] = logDocuments
|
||||
this.Data["count"] = len(logDocuments)
|
||||
this.viewLayout("user/info", "default")
|
||||
}
|
||||
|
||||
func (this *UserController) FollowUser() {
|
||||
|
||||
userId := this.GetString("user_id", "")
|
||||
if userId == "" {
|
||||
this.ViewError("用户不存在!", "/user/list")
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户出错:" + err.Error())
|
||||
this.ViewError("查找用户出错!", "/user/list")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.ViewError("用户不存在!", "/user/list")
|
||||
}
|
||||
|
||||
// follow users
|
||||
followUsers, err := models.FollowModel.GetFollowsByUserIdAndType(userId, models.Follow_Type_User)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/user/list")
|
||||
}
|
||||
userIds := []string{}
|
||||
for _, followUser := range followUsers {
|
||||
userIds = append(userIds, followUser["object_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/user/list")
|
||||
}
|
||||
for _, user := range users {
|
||||
user["follow_id"] = "0"
|
||||
for _, followUser := range followUsers {
|
||||
if followUser["object_id"] == user["user_id"] {
|
||||
user["follow_id"] = followUser["follow_id"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fans users
|
||||
followedUsers, err := models.FollowModel.GetFollowsByObjectIdAndType(userId, models.Follow_Type_User)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/user/list")
|
||||
}
|
||||
followedUserIds := []string{}
|
||||
for _, followedUser := range followedUsers {
|
||||
followedUserIds = append(followedUserIds, followedUser["user_id"])
|
||||
}
|
||||
fansUsers, err := models.UserModel.GetUsersByUserIds(followedUserIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/user/list")
|
||||
}
|
||||
|
||||
this.Data["users"] = users
|
||||
this.Data["fansUsers"] = fansUsers
|
||||
this.Data["followCount"] = len(users)
|
||||
this.Data["fansCount"] = len(fansUsers)
|
||||
this.Data["user"] = user
|
||||
this.viewLayout("user/follow_user", "default")
|
||||
}
|
||||
|
||||
func (this *UserController) FollowPage() {
|
||||
|
||||
userId := this.GetString("user_id", "")
|
||||
if userId == "" {
|
||||
this.ViewError("用户不存在!", "/user/list")
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户出错:" + err.Error())
|
||||
this.ViewError("查找用户出错!", "/user/list")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.ViewError("用户不存在!", "/user/list")
|
||||
}
|
||||
|
||||
followPages, err := models.FollowModel.GetFollowsByUserIdAndType(userId, models.Follow_Type_Doc)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户关注页面列表失败: " + err.Error())
|
||||
this.ViewError("获取用户关注页面列表失败", "/user/list")
|
||||
}
|
||||
|
||||
documentIds := []string{}
|
||||
for _, followPage := range followPages {
|
||||
documentIds = append(documentIds, followPage["object_id"])
|
||||
}
|
||||
|
||||
pages, err := models.DocumentModel.GetDocumentsByDocumentIds(documentIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户关注页面列表失败: " + err.Error())
|
||||
this.ViewError("获取用户关注页面列表失败", "/user/list")
|
||||
}
|
||||
|
||||
for _, page := range pages {
|
||||
page["follow_id"] = "0"
|
||||
for _, followPage := range followPages {
|
||||
if page["document_id"] == followPage["object_id"] {
|
||||
page["follow_id"] = followPage["follow_id"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["pages"] = pages
|
||||
this.Data["count"] = len(pages)
|
||||
this.Data["user"] = user
|
||||
this.viewLayout("user/collect_page", "default")
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const Table_Attachment_Name = "attachment"
|
||||
|
||||
const (
|
||||
Attachment_Source_Default = 0
|
||||
Attachment_Source_Image = 1
|
||||
)
|
||||
|
||||
type Attachment struct {
|
||||
}
|
||||
|
||||
var AttachmentModel = Attachment{}
|
||||
|
||||
// get attachment by attachment_id
|
||||
func (a *Attachment) GetAttachmentByAttachmentId(attachmentId string) (attachment map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"attachment_id": attachmentId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attachment = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// attachment_id and name is exists
|
||||
func (a *Attachment) HasSameName(attachmentId, name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"attachment_id <>": attachmentId,
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// name is exists
|
||||
func (a *Attachment) HasAttachmentName(name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get attachment by name
|
||||
func (a *Attachment) GetAttachmentByName(name string) (attachment map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attachment = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get attachments by document and source
|
||||
func (a *Attachment) GetAttachmentsByDocumentIdAndSource(documentId string, source int) (attachments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
"source": source,
|
||||
}).OrderBy("attachment_id", "desc"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attachments = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get attachments by document_id
|
||||
func (a *Attachment) GetAttachmentsByDocumentId(documentId string) (attachments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attachments = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get attachments by document_id
|
||||
func (a *Attachment) GetAttachmentsByDocumentIds(documentIds []string) (attachments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"document_id": documentIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attachments = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get attachments by space_id
|
||||
func (a *Attachment) GetAttachmentsBySpaceId(spaceId string) (attachments []map[string]string, err error) {
|
||||
documents, err := DocumentModel.GetDocumentsBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documentIds := []string{}
|
||||
for _, document := range documents {
|
||||
documentIds = append(documentIds, document["document_id"])
|
||||
}
|
||||
|
||||
return a.GetAttachmentsByDocumentIds(documentIds)
|
||||
}
|
||||
|
||||
// delete attachment by attachment_id
|
||||
func (a *Attachment) Delete(attachmentId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Attachment_Name, map[string]interface{}{
|
||||
"attachment_id": attachmentId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// insert attachment
|
||||
func (a *Attachment) Insert(attachmentValue map[string]interface{}, spaceId string) (id int64, err error) {
|
||||
|
||||
attachmentValue["create_time"] = time.Now().Unix()
|
||||
attachmentValue["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Attachment_Name, attachmentValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
|
||||
// create document log
|
||||
go func(attachmentValue map[string]interface{}, spaceId string) {
|
||||
comment := fmt.Sprintf("上传了附件 %s", attachmentValue["name"].(string))
|
||||
if attachmentValue["source"].(int) == Attachment_Source_Image {
|
||||
comment = fmt.Sprintf("上传了图片 %s", attachmentValue["name"].(string))
|
||||
}
|
||||
_, _ = LogDocumentModel.UpdateAction(attachmentValue["user_id"].(string),
|
||||
attachmentValue["document_id"].(string), comment, spaceId)
|
||||
}(attachmentValue, spaceId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get all attachments
|
||||
func (a *Attachment) GetAttachments() (attachments []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Attachment_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attachments = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get attachments by like name
|
||||
func (a *Attachment) GetAttachmentsByLikeName(name string) (attachments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attachments = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get attachment by many attachment_id
|
||||
func (a *Attachment) GetAttachmentByAttachmentIds(attachmentIds []string) (attachments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Attachment_Name).Where(map[string]interface{}{
|
||||
"attachment_id": attachmentIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attachments = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Attachment) DeleteAttachmentsDBFileByDocumentId(documentId string) (err error) {
|
||||
db := G.DB()
|
||||
attachments, err := a.GetAttachmentsByDocumentId(documentId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// delete attachment file
|
||||
err = utils.Document.DeleteAttachment(attachments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete db attachment
|
||||
_, err = db.Exec(db.AR().Delete(Table_Attachment_Name, map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Attachment) DeleteAttachmentDBFile(attachmentId string) (err error) {
|
||||
db := G.DB()
|
||||
attachment, err := a.GetAttachmentByAttachmentId(attachmentId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// delete attachment file
|
||||
err = utils.Document.DeleteAttachment([]map[string]string{attachment})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete db attachment
|
||||
_, err = db.Exec(db.AR().Delete(Table_Attachment_Name, map[string]interface{}{
|
||||
"attachment_id": attachmentId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
)
|
||||
|
||||
const (
|
||||
Auth_Used_True = 1
|
||||
Auth_Used_False = 0
|
||||
)
|
||||
|
||||
const Table_Auth_Name = "login_auth"
|
||||
|
||||
type Auth struct {
|
||||
}
|
||||
|
||||
var AuthModel = Auth{}
|
||||
|
||||
// get auth by auth_id
|
||||
func (a *Auth) GetAuthByAuthId(authId string) (auth map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"login_auth_id": authId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auth = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// auth_id and name is exists
|
||||
func (a *Auth) HasSameName(authId, name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"login_auth_id <>": authId,
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// auth_id and name is exists
|
||||
func (a *Auth) HasSameUsernamePrefix(authId, usernamePrefix string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"login_auth_id <>": authId,
|
||||
"username_prefix": usernamePrefix,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// name is exists
|
||||
func (a *Auth) HasAuthName(name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// name is exists
|
||||
func (a *Auth) HasAuthUsernamePrefix(usernamePrefix string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"username_prefix": usernamePrefix,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get auth by name
|
||||
func (a *Auth) GetAuthByName(name string) (auth map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auth = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete auth by auth_id
|
||||
func (a *Auth) Delete(authId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Auth_Name, map[string]interface{}{
|
||||
"login_auth_id": authId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// insert auth
|
||||
func (a *Auth) Insert(authValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
|
||||
// is_used
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"is_used": Auth_Used_True,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() == 0 {
|
||||
authValue["is_used"] = Auth_Used_True
|
||||
} else {
|
||||
authValue["is_used"] = Auth_Used_False
|
||||
}
|
||||
|
||||
authValue["create_time"] = time.Now().Unix()
|
||||
authValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Auth_Name, authValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// update auth by auth_id
|
||||
func (a *Auth) Update(authId string, authValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
authValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Auth_Name, authValue, map[string]interface{}{
|
||||
"login_auth_id": authId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get limit auths by search keyword
|
||||
func (a *Auth) GetAuthsByKeywordAndLimit(keyword string, limit int, number int) (auths []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
}).Limit(limit, number).OrderBy("auth_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auths = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get limit auths
|
||||
func (a *Auth) GetAuthsByLimit(limit int, number int) (auths []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
From(Table_Auth_Name).
|
||||
Limit(limit, number).
|
||||
OrderBy("login_auth_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auths = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get all auths
|
||||
func (a *Auth) GetAuths() (auths []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Auth_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auths = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get auth count
|
||||
func (a *Auth) CountAuths() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Auth_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get auth count by keyword
|
||||
func (a *Auth) CountAuthsByKeyword(keyword string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Auth_Name).
|
||||
Where(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get auths by like name
|
||||
func (a *Auth) GetAuthsByLikeName(name string) (auths []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auths = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get auth by many auth_id
|
||||
func (a *Auth) GetAuthByAuthIds(authIds []string) (auths []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"login_auth_id": authIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auths = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// set auth used
|
||||
func (a *Auth) SetAuthUsed(authId string) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
|
||||
rs, err = db.Exec(db.AR().Update(Table_Auth_Name, map[string]interface{}{"is_used": Auth_Used_False}, map[string]interface{}{
|
||||
"is_used": Auth_Used_True,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rs, err = db.Exec(db.AR().Update(Table_Auth_Name, map[string]interface{}{"is_used": Auth_Used_True}, map[string]interface{}{
|
||||
"login_auth_id": authId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get used auth
|
||||
func (a *Auth) GetUsedAuth() (auth map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().Select("*").From(Table_Auth_Name).Where(map[string]interface{}{
|
||||
"is_used": Auth_Used_True,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auth = rs.Row()
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
)
|
||||
|
||||
const (
|
||||
Collection_Type_Doc = 1
|
||||
Collection_Type_Space = 2
|
||||
)
|
||||
|
||||
const Table_Collection_Name = "collection"
|
||||
|
||||
type Collection struct {
|
||||
}
|
||||
|
||||
var CollectionModel = Collection{}
|
||||
|
||||
// get collection by collection_id
|
||||
func (c *Collection) GetCollectionByCollectionId(collectionId string) (collection map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Collection_Name).Where(map[string]interface{}{
|
||||
"collection_id": collectionId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collection = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get collections by user_id
|
||||
func (c *Collection) GetCollectionsByUserId(userId string) (collections []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Collection_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collections = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get collections by user_id
|
||||
func (c *Collection) GetCollectionsByUserIdAndType(userId string, typeS int) (collections []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Collection_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"type": typeS,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collections = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get collections by user_id type and resource_id
|
||||
func (c *Collection) GetCollectionByUserIdTypeAndResourceId(userId string, typeS int, resId string) (collection map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Collection_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"type": typeS,
|
||||
"resource_id": resId,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collection = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete collection by collection_id
|
||||
func (c *Collection) Delete(collectionId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Collection_Name, map[string]interface{}{
|
||||
"collection_id": collectionId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// delete collection by type and object_id
|
||||
func (c *Collection) DeleteByResourceIdType(resourceId string, collectType string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Collection_Name, map[string]interface{}{
|
||||
"type": collectType,
|
||||
"resource_id": resourceId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// insert collection
|
||||
func (c *Collection) Insert(collectionValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Collection_Name, collectionValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get all collections
|
||||
func (c *Collection) GetCollections() (collections []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Collection_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collections = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get collection count
|
||||
func (c *Collection) CountCollections() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Collection_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get collections by many collection_id
|
||||
func (c *Collection) GetCollectionsByCollectionIds(collectionIds []string) (collections []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Collection_Name).Where(map[string]interface{}{
|
||||
"collection_id": collectionIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collections = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Collection) GetResourceIdsOrderByCountLimit(limit int, collectType int) (collects []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("resource_id, count('resource_id') as total").
|
||||
From(Table_Collection_Name).Where(map[string]interface{}{
|
||||
"type": collectType,
|
||||
}).
|
||||
GroupBy("resource_id").
|
||||
OrderBy("total", "DESC").
|
||||
Limit(0, limit)
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collects = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Collection) GetCollectionGroupUserId(colType int) (collects []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("user_id, count('user_id') as total").
|
||||
From(Table_Collection_Name).Where(map[string]interface{}{
|
||||
"type": colType,
|
||||
}).GroupBy("user_id")
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collects = rs.Rows()
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const Table_Config_Name = "config"
|
||||
|
||||
const (
|
||||
ConfigKeyMainTitle = "main_title"
|
||||
ConfigKeyMainDescription = "main_description"
|
||||
ConfigKeyAutoFollowdoc = "auto_follow_doc_open"
|
||||
ConfigKeySendEmail = "send_email_open"
|
||||
ConfigKeyAuthLogin = "sso_open"
|
||||
ConfigKeySystemVersion = "system_version"
|
||||
ConfigKeyFulltextSearch = "fulltext_search_open"
|
||||
ConfigKeyDocSearchTimer = "doc_search_timer"
|
||||
ConfigKeySystemName = "system_name"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
}
|
||||
|
||||
var ConfigModel = Config{}
|
||||
|
||||
// get config by config_id
|
||||
func (c *Config) GetConfigByConfigId(configId string) (config map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Config_Name).Where(map[string]interface{}{
|
||||
"config_id": configId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// update config by config_id
|
||||
func (c *Config) Update(configId string, configValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
configValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Config_Name, configValue, map[string]interface{}{
|
||||
"config_id": configId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// update config by key
|
||||
func (c *Config) UpdateByKey(key string, value string) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
configValue := map[string]interface{}{}
|
||||
configValue["value"] = value
|
||||
configValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Config_Name, configValue, map[string]interface{}{
|
||||
"key": key,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get all configs
|
||||
func (c *Config) GetConfigs() (configs []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Config_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
configs = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get all configs key map
|
||||
func (c *Config) GetConfigsKeyMap() (configMaps map[string]map[string]string, err error) {
|
||||
configMaps = make(map[string]map[string]string)
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Config_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
configs := rs.Rows()
|
||||
for _, config := range configs {
|
||||
key, ok := config["key"]
|
||||
if ok {
|
||||
configMaps[key] = config
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get config by many config_id
|
||||
func (c *Config) GetConfigByConfigIds(configIds []string) (configs []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Config_Name).Where(map[string]interface{}{
|
||||
"config_id": configIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
configs = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// insert batch configs
|
||||
func (c *Config) InsertBatch(insertValues []map[string]interface{}) (id int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().InsertBatch(Table_Config_Name, insertValues))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// insert config
|
||||
func (c *Config) Insert(insertValue map[string]interface{}) (id int64, err error) {
|
||||
|
||||
insertValue["create_time"] = time.Now().Unix()
|
||||
insertValue["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Config_Name, insertValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get config by config key
|
||||
func (c *Config) GetConfigByKey(key string) (config map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Config_Name).Where(map[string]interface{}{
|
||||
"key": key,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get config value by config key
|
||||
func (c *Config) GetConfigValueByKey(key string, defaultValue string) (value string) {
|
||||
|
||||
configData, err := c.GetConfigByKey(key)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
if len(configData) == 0 {
|
||||
return defaultValue
|
||||
}
|
||||
if value, ok := configData["value"]; ok {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
)
|
||||
|
||||
const Table_Contact_Name = "contact"
|
||||
|
||||
type Contact struct {
|
||||
}
|
||||
|
||||
var ContactModel = Contact{}
|
||||
|
||||
// 分页获取联系人
|
||||
func (c *Contact) GetContactByLimit(limit, number int) (contact []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Contact_Name).Limit(limit, number))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
contact = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// 获取联系人总数
|
||||
func (c *Contact) CountContact() (count int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().Select("count(*) as total").From(Table_Contact_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// 分页筛选名字查询结果
|
||||
func (c *Contact) GetContactByLimitAndName(name string, limit, number int) (contacts []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Contact_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
}).Limit(limit, number))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
contacts = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// 获取筛选名字查询结果条数
|
||||
func (c *Contact) CountContactByName(name string) (count int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Contact_Name).Select("count(*) as total").Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// 通过 contact_id 获取联系人数据
|
||||
func (c *Contact) GetContactByContactId(contactId string) (contact map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Contact_Name).Where(map[string]interface{}{
|
||||
"contact_id": contactId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
contact = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// 通过 contact_id 更新联系人信息
|
||||
func (c *Contact) UpdateByContactId(contact map[string]interface{}, contactId string) (affect int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Update(Table_Contact_Name, contact, map[string]interface{}{
|
||||
"contact_id": contactId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
affect = rs.RowsAffected
|
||||
return
|
||||
}
|
||||
|
||||
// 通过 contact_id 更新联系人信息
|
||||
func (c *Contact) Insert(contact map[string]interface{}) (contactId int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Contact_Name, contact))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
contactId = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// 通过 contact_id 删除联系人信息
|
||||
func (c *Contact) DeleteByContactId(contactId string) (affect int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Delete(Table_Contact_Name, map[string]interface{}{
|
||||
"contact_id": contactId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
affect = rs.RowsAffected
|
||||
return
|
||||
}
|
||||
|
||||
// 获取所有联系人信息
|
||||
func (c *Contact) GetAllContact() (contacts []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Contact_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
contacts = rs.Rows()
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,757 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Document_Delete_True = 1
|
||||
Document_Delete_False = 0
|
||||
|
||||
Document_Type_Page = 1
|
||||
Document_Type_Dir = 2
|
||||
)
|
||||
|
||||
const Table_Document_Name = "document"
|
||||
|
||||
type Document struct {
|
||||
}
|
||||
|
||||
var DocumentModel = Document{}
|
||||
|
||||
// get document by document_id
|
||||
func (d *Document) GetDocumentByDocumentId(documentId string) (document map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
document = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get documents by parent_id
|
||||
func (d *Document) GetDocumentsByParentId(parentId string) (documents []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"parent_id": parentId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get document by name
|
||||
func (d *Document) GetDocumentsByName(name string) (documents []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get document by name and spaceId
|
||||
func (d *Document) GetDocumentByNameAndSpaceId(name string, spaceId string) (document map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
"space_id": spaceId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
document = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get document by name and spaceId
|
||||
func (d *Document) GetDocumentByNameParentIdAndSpaceId(name string, parentId string, spaceId string, docType int) (document map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
"space_id": spaceId,
|
||||
"parent_id": parentId,
|
||||
"type": docType,
|
||||
"is_delete": Document_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
document = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get document by name and spaceId
|
||||
func (d *Document) GetDocumentByParentIdAndSpaceId(parentId string, spaceId string, docType int) (document map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"parent_id": parentId,
|
||||
"type": docType,
|
||||
"is_delete": Document_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
document = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get document by name and spaceId
|
||||
func (d *Document) GetDocumentsByParentIdAndSpaceIdOnly(parentId string, spaceId string) (document []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"parent_id": parentId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
document = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get max sequence
|
||||
func (d *Document) GetDocumentMaxSequence(parentId string, spaceId string) (sequence int, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"parent_id": parentId,
|
||||
}).OrderBy("sequence", "desc").Limit(0, 1))
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
document := rs.Row()
|
||||
sequenceStr := document["sequence"]
|
||||
sequence, err = strconv.Atoi(sequenceStr)
|
||||
return
|
||||
}
|
||||
|
||||
// delete document by document_id
|
||||
func (d *Document) DeleteDBAndFile(documentId string, spaceId string, userId string, pageFile string, docType string) (err error) {
|
||||
db := G.DB()
|
||||
tx, err := db.Begin(db.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = db.ExecTx(db.AR().Update(Table_Document_Name, map[string]interface{}{
|
||||
"is_delete": Document_Delete_True,
|
||||
"update_time": time.Now().Unix(),
|
||||
"edit_user_id": userId,
|
||||
}, map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
}), tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
// delete document file
|
||||
err = utils.Document.Delete(pageFile, utils.Convert.StringToInt(docType))
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// create document log
|
||||
go func(userId, documentId string, spaceId string) {
|
||||
_, err := LogDocumentModel.DeleteAction(userId, documentId, spaceId)
|
||||
if err != nil {
|
||||
logs.Error("delete document add log err=%s", err.Error())
|
||||
}
|
||||
}(userId, documentId, spaceId)
|
||||
|
||||
// delete follow doc
|
||||
go func(documentId string) {
|
||||
err := FollowModel.DeleteByObjectIdType(documentId, fmt.Sprintf("%d", Follow_Type_Doc))
|
||||
if err != nil {
|
||||
logs.Error("delete follow document err=%s", err.Error())
|
||||
}
|
||||
}(documentId)
|
||||
|
||||
// delete collect doc
|
||||
go func(documentId string) {
|
||||
err := CollectionModel.DeleteByResourceIdType(documentId, fmt.Sprintf("%d", Collection_Type_Doc))
|
||||
if err != nil {
|
||||
logs.Error("delete collect document err=%s", err.Error())
|
||||
}
|
||||
}(documentId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// insert document
|
||||
func (d *Document) Insert(documentValue map[string]interface{}) (id int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
// start db begin
|
||||
tx, err := db.Begin(db.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 处理同级排序编号
|
||||
parentId := documentValue["parent_id"].(string)
|
||||
spaceId := documentValue["space_id"].(string)
|
||||
|
||||
sequence, err := d.GetDocumentMaxSequence(parentId, spaceId)
|
||||
if err != nil {
|
||||
sequence = 0
|
||||
}
|
||||
|
||||
sequence += 1
|
||||
documentValue["sequence"] = strconv.Itoa(sequence)
|
||||
|
||||
var rs *mysql.ResultSet
|
||||
documentValue["create_time"] = time.Now().Unix()
|
||||
documentValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.ExecTx(db.AR().Insert(Table_Document_Name, documentValue), tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
|
||||
// create document page file
|
||||
document := map[string]string{
|
||||
"space_id": documentValue["space_id"].(string),
|
||||
"parent_id": documentValue["parent_id"].(string),
|
||||
"name": documentValue["name"].(string),
|
||||
"type": fmt.Sprintf("%d", documentValue["type"].(int)),
|
||||
"path": documentValue["path"].(string),
|
||||
}
|
||||
_, pageFile, err := d.GetParentDocumentsByDocument(document)
|
||||
err = utils.Document.Create(pageFile)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
userId := documentValue["create_user_id"].(string)
|
||||
// create document log
|
||||
go func(userId, documentId, spaceId string) {
|
||||
_, err := LogDocumentModel.CreateAction(userId, documentId, spaceId)
|
||||
if err != nil {
|
||||
logs.Error("create document add log err=%s", err.Error())
|
||||
}
|
||||
}(userId, fmt.Sprintf("%d", id), spaceId)
|
||||
|
||||
// follow document
|
||||
go func(userId, documentId string) {
|
||||
_, err := FollowModel.CreateAutoFollowDocument(userId, documentId)
|
||||
if err != nil {
|
||||
logs.Error("follow document err=%s", err.Error())
|
||||
}
|
||||
}(userId, fmt.Sprintf("%d", id))
|
||||
return
|
||||
}
|
||||
|
||||
// update document by document_id
|
||||
func (d *Document) Update(documentId string, documentValue map[string]interface{}, comment string, spaceId string) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
documentValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Document_Name, documentValue, map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
|
||||
// update document log
|
||||
go func(editUserId string, documentId string, comment string, spaceId string) {
|
||||
_, err := LogDocumentModel.UpdateAction(editUserId, documentId, comment, spaceId)
|
||||
if err != nil {
|
||||
logs.Error("update document add log err=%s", err.Error())
|
||||
}
|
||||
}(documentValue["edit_user_id"].(string), documentId, comment, spaceId)
|
||||
|
||||
// follow document
|
||||
go func(editUserId string, documentId string) {
|
||||
_, err := FollowModel.CreateAutoFollowDocument(editUserId, documentId)
|
||||
if err != nil {
|
||||
logs.Error("follow document err=%s", err.Error())
|
||||
}
|
||||
}(documentValue["edit_user_id"].(string), documentId)
|
||||
return
|
||||
}
|
||||
|
||||
// update document by spaceId and >= sequence
|
||||
// 批量移动更新文档序号
|
||||
func (d *Document) MoveSequenceBySpaceIdAndGtSequence(spaceId string, startSequence int, n int) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
//documentValue := map[string]interface{}{
|
||||
// "sequence": fmt.Sprintf("(sequence+%d)", n),
|
||||
// "update_time": time.Now().Unix(),
|
||||
//}
|
||||
updateTime := time.Now().Unix()
|
||||
sql := fmt.Sprintf(
|
||||
"update mw_%s set sequence=sequence+%d, update_time=%d where space_id=%s and sequence >= %d and is_delete=%d",
|
||||
Table_Document_Name, n, updateTime, spaceId, startSequence, Document_Delete_False,
|
||||
)
|
||||
rs, err = db.ExecSQL(sql)
|
||||
if err != nil {
|
||||
logs.Error(err.Error())
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// move document
|
||||
func (d *Document) MoveDBAndFile(documentId string, spaceId string, updateValue map[string]interface{},
|
||||
oldPageFile string, newPageFile string, docType string, comment string) (id int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
tx, err := db.Begin(db.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var rs *mysql.ResultSet
|
||||
updateValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.ExecTx(db.AR().Update(Table_Document_Name, updateValue, map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}), tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
|
||||
err = utils.Document.Move(oldPageFile, newPageFile, utils.Convert.StringToInt(docType))
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// create document log
|
||||
go func(userId, documentId, comment string, spaceId string) {
|
||||
_, err := LogDocumentModel.UpdateAction(updateValue["edit_user_id"].(string), documentId, comment, spaceId)
|
||||
if err != nil {
|
||||
logs.Error("update document add log err=%s", err.Error())
|
||||
}
|
||||
}(updateValue["edit_user_id"].(string), documentId, comment, spaceId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// update document by document_id
|
||||
func (d *Document) UpdateDBAndFile(documentId string, spaceId string, document map[string]string, documentContent string, updateValue map[string]interface{}, comment string) (id int64, err error) {
|
||||
|
||||
// get document page file
|
||||
_, oldPageFile, err := DocumentModel.GetParentDocumentsByDocument(document)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// begin update
|
||||
db := G.DB()
|
||||
tx, err := db.Begin(db.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var rs *mysql.ResultSet
|
||||
updateValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.ExecTx(db.AR().Update(Table_Document_Name, updateValue, map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}), tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
|
||||
// update document file
|
||||
docType := utils.Convert.StringToInt(document["type"])
|
||||
nameIsChange := false
|
||||
if updateValue["name"].(string) != document["name"] {
|
||||
nameIsChange = true
|
||||
}
|
||||
err = utils.Document.Update(oldPageFile, updateValue["name"].(string), documentContent, docType, nameIsChange)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
// commit
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// create document log
|
||||
go func(documentId string, comment string, spaceId string) {
|
||||
_, _ = LogDocumentModel.UpdateAction(updateValue["edit_user_id"].(string), documentId, comment, spaceId)
|
||||
}(documentId, comment, spaceId)
|
||||
|
||||
// create follow doc
|
||||
go func(documentId string) {
|
||||
_, _ = FollowModel.CreateAutoFollowDocument(updateValue["edit_user_id"].(string), documentId)
|
||||
}(documentId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get all documents
|
||||
func (d *Document) GetDocumentsBySpaceId(spaceId string) (documents []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get document by spaceId and parentId
|
||||
func (d *Document) GetDocumentsBySpaceIdAndParentId(spaceId string, parentId string) (documents []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"parent_id": parentId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get document by spaceId
|
||||
func (d *Document) GetSpaceDefaultDocument(spaceId string) (document map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"parent_id": "0",
|
||||
"is_delete": Document_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
document = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get document by spaceId
|
||||
func (d *Document) GetAllSpaceDocuments(spaceId string) (documents []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"parent_id >": "0",
|
||||
"is_delete": Document_Delete_False,
|
||||
}).OrderBy("sequence", "ASC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get document count
|
||||
func (d *Document) CountDocumentsBySpaceId(spaceId string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Document_Name).
|
||||
Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get document count
|
||||
func (d *Document) CountDocuments() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Document_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get document by name
|
||||
func (d *Document) GetDocumentsByLikeName(name string) (documents []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get document link name and limit
|
||||
func (d *Document) GetDocumentsByLikeNameAndLimit(name string, limit int, number int) (documents []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
"is_delete": Document_Delete_False,
|
||||
}).Limit(limit, number))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// count document like name
|
||||
func (d *Document) CountDocumentsLikeName(name string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Document_Name).
|
||||
Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get document by spaceId and document_ids
|
||||
func (d *Document) GetDocumentsByDocumentIds(documentIds []string) (documents []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"document_id": documentIds,
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Document) GetAllDocumentsByDocumentIds(documentIds []string) (documents []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"document_id": documentIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Document) GetAllDocuments() (documents []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"is_delete": Document_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Document) GetParentDocumentsByDocument(document map[string]string) (parentDocuments []map[string]string, pageFile string, err error) {
|
||||
|
||||
if document["parent_id"] == "0" {
|
||||
parentDocuments = append(parentDocuments, document)
|
||||
pageFile = utils.Document.GetDefaultPageFileBySpaceName(document["name"])
|
||||
} else {
|
||||
documentsIds := strings.Split(document["path"], ",")
|
||||
parentDocuments, err = d.GetDocumentsByDocumentIds(documentsIds)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var parentPath = ""
|
||||
for _, parentDocument := range parentDocuments {
|
||||
parentPath += parentDocument["name"] + "/"
|
||||
}
|
||||
parentPath = strings.TrimRight(parentPath, "/")
|
||||
pageFile = utils.Document.GetPageFileByParentPath(document["name"], utils.Convert.StringToInt(document["type"]), parentPath)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Document) GetParentDocumentsByPath(path string) (parentDocuments []map[string]string, err error) {
|
||||
documentsIds := strings.Split(path, ",")
|
||||
parentDocuments, err = d.GetDocumentsByDocumentIds(documentsIds)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Document) GetSpaceIdsOrderByCountDocumentLimit(limit int) (documents []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("space_id, count('space_id') as total").
|
||||
From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"is_delete": Document_Delete_False,
|
||||
}).
|
||||
GroupBy("space_id").
|
||||
OrderBy("total", "DESC").
|
||||
Limit(0, limit)
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Document) GetCountGroupByCreateTime(startTime int64) (documents []map[string]string, err error) {
|
||||
/*select month(FROM_UNIXTIME(time)) from table_name group by month(FROM_UNIXTIME(time))*/
|
||||
|
||||
/*select DATE_FORMAT(FROM_UNIXTIME(time),"%Y-%m") from tcm_fund_list group by DATE_FORMAT(FROM_UNIXTIME(time),"%Y-%m")*/
|
||||
/*select FROM_UNIXTIME(time,"%Y-%m") from tcm_fund_list group by FROM_UNIXTIME(time,"%Y-%m")*/
|
||||
|
||||
/*select DATE_FORMAT(FROM_UNIXTIME(time),"%Y-%m-%d") from tcm_fund_list group by DATE_FORMAT(FROM_UNIXTIME(time),"%Y-%m-%d")*/
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("DATE_FORMAT(FROM_UNIXTIME(create_time),'%Y-%m-%d') as date, count('date') as total").
|
||||
From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"is_delete": Document_Delete_False,
|
||||
"create_time >=": startTime,
|
||||
}).GroupBy("DATE_FORMAT(FROM_UNIXTIME(create_time),'%Y-%m-%d')")
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Document) GetDocumentGroupCreateUserId() (documents []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("create_user_id, count('create_user_id') as total").
|
||||
From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"is_delete": Document_Delete_False,
|
||||
}).GroupBy("create_user_id")
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Document) GetDocumentGroupEditUserId() (documents []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("edit_user_id, count('edit_user_id') as total").
|
||||
From(Table_Document_Name).Where(map[string]interface{}{
|
||||
"is_delete": Document_Delete_False,
|
||||
}).GroupBy("edit_user_id")
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
documents = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// 根据文档信息获取文档内容和文件地址
|
||||
func (d *Document) GetDocumentContentByDocument(doc map[string]string) (content string, pageFile string, err error) {
|
||||
// get document page file
|
||||
_, pageFile, err = DocumentModel.GetParentDocumentsByDocument(doc)
|
||||
if err != nil {
|
||||
return content, pageFile, err
|
||||
}
|
||||
// get document content
|
||||
content, err = utils.Document.GetContentByPageFile(pageFile)
|
||||
if err != nil {
|
||||
return content, pageFile, err
|
||||
}
|
||||
return content, pageFile, nil
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Email_Used_True = 1
|
||||
Email_Used_False = 0
|
||||
)
|
||||
|
||||
const Table_Email_Name = "email"
|
||||
|
||||
type Email struct {
|
||||
}
|
||||
|
||||
var EmailModel = Email{}
|
||||
|
||||
// get email by email_id
|
||||
func (u *Email) GetEmailByEmailId(emailId string) (email map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"email_id": emailId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
email = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// email_id and name is exists
|
||||
func (u *Email) HasSameName(emailId, name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"email_id <>": emailId,
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// name is exists
|
||||
func (u *Email) HasEmailName(name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get email by name
|
||||
func (u *Email) GetEmailByName(name string) (email map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
email = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete email by email_id
|
||||
func (u *Email) Delete(emailId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Email_Name, map[string]interface{}{
|
||||
"email_id": emailId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// insert email
|
||||
func (u *Email) Insert(emailValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
|
||||
// is_used
|
||||
rs, err = db.Query(db.AR().From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"is_used": Email_Used_True,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() == 0 {
|
||||
emailValue["is_used"] = Email_Used_True
|
||||
} else {
|
||||
emailValue["is_used"] = Email_Used_False
|
||||
}
|
||||
emailValue["create_time"] = time.Now().Unix()
|
||||
emailValue["update_time"] = time.Now().Unix()
|
||||
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Email_Name, emailValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// update email by email_id
|
||||
func (u *Email) Update(emailId string, emailValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
emailValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Email_Name, emailValue, map[string]interface{}{
|
||||
"email_id": emailId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get limit emails by search keyword
|
||||
func (u *Email) GetEmailsByKeywordAndLimit(keyword string, limit int, number int) (emails []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
}).Limit(limit, number).OrderBy("email_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
emails = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get limit emails
|
||||
func (u *Email) GetEmailsByLimit(limit int, number int) (emails []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
From(Table_Email_Name).
|
||||
Limit(limit, number).
|
||||
OrderBy("email_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
emails = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get all emails
|
||||
func (u *Email) GetEmails() (emails []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Email_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
emails = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get used email
|
||||
func (u *Email) GetUsedEmail() (email map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().Select("*").From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"is_used": Email_Used_True,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
email = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get email count
|
||||
func (u *Email) CountEmails() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Email_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get email count by keyword
|
||||
func (u *Email) CountEmailsByKeyword(keyword string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Email_Name).
|
||||
Where(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get emails by like name
|
||||
func (u *Email) GetEmailsByLikeName(name string) (emails []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
emails = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get email by many email_id
|
||||
func (u *Email) GetEmailByEmailIds(emailIds []string) (emails []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Email_Name).Where(map[string]interface{}{
|
||||
"email_id": emailIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
emails = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// set email used
|
||||
func (u *Email) SetEmailUsed(emailId string) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
|
||||
rs, err = db.Exec(db.AR().Update(Table_Email_Name, map[string]interface{}{"is_used": Email_Used_False}, map[string]interface{}{
|
||||
"is_used": Email_Used_True,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rs, err = db.Exec(db.AR().Update(Table_Email_Name, map[string]interface{}{"is_used": Email_Used_True}, map[string]interface{}{
|
||||
"email_id": emailId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Follow_Type_Doc = 1
|
||||
Follow_Type_User = 2
|
||||
)
|
||||
|
||||
const Table_Follow_Name = "follow"
|
||||
|
||||
type Follow struct {
|
||||
}
|
||||
|
||||
var FollowModel = Follow{}
|
||||
|
||||
// get follow by follow_id
|
||||
func (f *Follow) GetFollowByFollowId(followId string) (follow map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"follow_id": followId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
follow = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get follows by user_id and type
|
||||
func (f *Follow) GetFollowsByUserIdAndType(userId string, followType int) (follows []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"type": followType,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
follows = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get follows by user_id and type limit
|
||||
func (f *Follow) GetFollowsByUserIdTypeAndLimit(userId string, followType int, limit int, number int) (follows []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"type": followType,
|
||||
}).Limit(limit, number).OrderBy("follow_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
follows = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get followed follows
|
||||
func (f *Follow) GetFollowsByObjectIdAndType(objectId string, followType int) (follows []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"object_id": objectId,
|
||||
"type": followType,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
follows = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get followed follow
|
||||
func (f *Follow) GetFollowByUserIdAndTypeAndObjectId(userId string, followType int, objectId string) (follow map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"type": followType,
|
||||
"object_id": objectId,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
follow = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete follow by follow_id
|
||||
func (f *Follow) Delete(followId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Follow_Name, map[string]interface{}{
|
||||
"follow_id": followId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// delete follow by type and object_id
|
||||
func (f *Follow) DeleteByObjectIdType(objectId string, followType string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Follow_Name, map[string]interface{}{
|
||||
"type": followType,
|
||||
"object_id": objectId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// insert follow user
|
||||
func (f *Follow) Insert(userId string, fType int, objectId string) (id int64, err error) {
|
||||
followValue := map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"type": fType,
|
||||
"object_id": objectId,
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Follow_Name, followValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get all follows
|
||||
func (f *Follow) GetFollows() (follows []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Follow_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
follows = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get follow count
|
||||
func (f *Follow) CountFollows() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Follow_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get follow count
|
||||
func (f *Follow) CountFollowsByUserIdAndType(userId string, followType int) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().Select("count(*) as total").From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"type": followType,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get follows by many follow_id
|
||||
func (f *Follow) GetFollowsByFollowIds(followIds []string) (follows []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"follow_id": followIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
follows = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// create auto follow document
|
||||
func (f *Follow) CreateAutoFollowDocument(userId string, documentId string) (id int64, err error) {
|
||||
|
||||
autoFollowConf := ConfigModel.GetConfigValueByKey(ConfigKeyAutoFollowdoc, "0")
|
||||
if autoFollowConf == "1" {
|
||||
follow, err := f.GetFollowByUserIdAndTypeAndObjectId(userId, Follow_Type_Doc, documentId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(follow) == 0 {
|
||||
return f.Insert(userId, Follow_Type_Doc, documentId)
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (f *Follow) FollowDocument(userId string, documentId string) (id int64, err error) {
|
||||
|
||||
follow, err := f.GetFollowByUserIdAndTypeAndObjectId(userId, Follow_Type_Doc, documentId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(follow) == 0 {
|
||||
return f.Insert(userId, Follow_Type_Doc, documentId)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (f *Follow) GetFollowGroupUserId(fType int) (collects []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("user_id, count('user_id') as total").
|
||||
From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"type": fType,
|
||||
}).GroupBy("user_id")
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collects = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (f *Follow) GetFansUserGroupUserId() (collects []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("object_id, count('object_id') as total").
|
||||
From(Table_Follow_Name).Where(map[string]interface{}{
|
||||
"type": Follow_Type_User,
|
||||
}).GroupBy("object_id")
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
collects = rs.Rows()
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
)
|
||||
|
||||
var G *mysql.DBGroup
|
||||
@@ -0,0 +1,241 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const Table_Link_Name = "link"
|
||||
|
||||
type Link struct {
|
||||
}
|
||||
|
||||
var LinkModel = Link{}
|
||||
|
||||
// get link by link_id
|
||||
func (l *Link) GetLinkByLinkId(linkId string) (link map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Link_Name).Where(map[string]interface{}{
|
||||
"link_id": linkId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
link = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// link_id and name is exists
|
||||
func (l *Link) HasSameName(linkId, name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Link_Name).Where(map[string]interface{}{
|
||||
"link_id <>": linkId,
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// name is exists
|
||||
func (l *Link) HasLinkName(name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Link_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get link by name
|
||||
func (l *Link) GetLinkByName(name string) (link map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Link_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
link = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete link by link_id
|
||||
func (l *Link) Delete(linkId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Link_Name, map[string]interface{}{
|
||||
"link_id": linkId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// insert link
|
||||
func (l *Link) Insert(linkValue map[string]interface{}) (id int64, err error) {
|
||||
|
||||
linkValue["create_time"] = time.Now().Unix()
|
||||
linkValue["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Link_Name, linkValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// update link by link_id
|
||||
func (l *Link) Update(linkId string, linkValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
linkValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Link_Name, linkValue, map[string]interface{}{
|
||||
"link_id": linkId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get limit links by search keyword
|
||||
func (l *Link) GetLinksByKeywordAndLimit(keyword string, limit int, number int) (links []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Link_Name).Where(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
}).Limit(limit, number).OrderBy("link_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
links = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get limit links
|
||||
func (l *Link) GetLinksByLimit(limit int, number int) (links []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
From(Table_Link_Name).
|
||||
Limit(limit, number).
|
||||
OrderBy("link_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
links = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get all links
|
||||
func (l *Link) GetLinks() (links []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Link_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
links = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get all links by sequence
|
||||
func (l *Link) GetLinksOrderBySequence() (links []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Link_Name).OrderBy("sequence", "ASC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
links = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get link count
|
||||
func (l *Link) CountLinks() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Link_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get link count by keyword
|
||||
func (l *Link) CountLinksByKeyword(keyword string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Link_Name).
|
||||
Where(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get links by like name
|
||||
func (l *Link) GetLinksByLikeName(name string) (links []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Link_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
links = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get link by many link_id
|
||||
func (l *Link) GetLinkByLinkIds(linkIds []string) (links []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Link_Name).Where(map[string]interface{}{
|
||||
"link_id": linkIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
links = rs.Rows()
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/astaxie/beego/context"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Log_Level_Emegergency = iota
|
||||
Log_Level_Alaert
|
||||
Log_Level_Critical
|
||||
Log_Level_Error
|
||||
Log_Level_Warning
|
||||
Log_Level_Notice
|
||||
Log_Level_Info
|
||||
Log_Level_Debug
|
||||
)
|
||||
|
||||
const Table_Log_Name = "log"
|
||||
|
||||
type Log struct {
|
||||
}
|
||||
|
||||
var LogModel = Log{}
|
||||
|
||||
// 根据 log_id 获取日志
|
||||
func (l *Log) GetLogByLogId(logId string) (log map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Log_Name).Where(map[string]interface{}{
|
||||
"log_id": logId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
log = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// 插入
|
||||
func (l *Log) Insert(log map[string]interface{}) (id int64, err error) {
|
||||
|
||||
log["create_time"] = time.Now().Unix()
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Log_Name, log))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// 根据关键字分页获取日志
|
||||
func (l *Log) GetLogsByKeywordAndLimit(level, message, username string, limit int, number int) (logs []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
where := make(map[string]interface{})
|
||||
if level != "" {
|
||||
where["level"] = level
|
||||
}
|
||||
if message != "" {
|
||||
where["message LIKE"] = "%" + message + "%"
|
||||
}
|
||||
if username != "" {
|
||||
where["username LIKE"] = "%" + username + "%"
|
||||
}
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Log_Name).Where(where).Limit(limit, number).OrderBy("log_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logs = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 分页获取日志
|
||||
func (l *Log) GetLogsByLimit(limit int, number int) (logs []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
From(Table_Log_Name).
|
||||
Limit(limit, number).
|
||||
OrderBy("log_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logs = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取日志总数
|
||||
func (l *Log) CountLogs() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Log_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
func (l *Log) CountLogsByLevel(level int) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
Where(map[string]interface{}{
|
||||
"level": level,
|
||||
}).
|
||||
From(Table_Log_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// 根据关键字获取日志总数
|
||||
func (l *Log) CountLogsByKeyword(level, message, username string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
where := make(map[string]interface{})
|
||||
if level != "" {
|
||||
where["level"] = level
|
||||
}
|
||||
if message != "" {
|
||||
where["message LIKE"] = "%" + message + "%"
|
||||
}
|
||||
if username != "" {
|
||||
where["username LIKE"] = "%" + username + "%"
|
||||
}
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Log_Name).
|
||||
Where(where))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
func (l *Log) RecordLog(message string, level int, userId string, username string, ctx context.Context) (id int64, err error) {
|
||||
userAgent := ctx.Request.UserAgent()
|
||||
referer := ctx.Request.Referer()
|
||||
getParams := ctx.Request.URL.String()
|
||||
path := ctx.Request.URL.Path
|
||||
ctx.Request.ParseForm()
|
||||
postParamsMap := map[string][]string(ctx.Request.PostForm)
|
||||
postParams, _ := json.Marshal(postParamsMap)
|
||||
|
||||
logValue := map[string]interface{}{
|
||||
"level": level,
|
||||
"path": path,
|
||||
"get": getParams,
|
||||
"post": string(postParams),
|
||||
"message": message,
|
||||
"ip": strings.Split(ctx.Request.RemoteAddr, ":"),
|
||||
"user_agent": userAgent,
|
||||
"referer": referer,
|
||||
"user_id": userId,
|
||||
"username": username,
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
return LogModel.Insert(logValue)
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
LogDocument_Action_Create = 1
|
||||
LogDocument_Action_Update = 2
|
||||
LogDocument_Action_Delete = 3
|
||||
)
|
||||
|
||||
const Table_LogDocument_Name = "log_document"
|
||||
|
||||
type LogDocument struct {
|
||||
}
|
||||
|
||||
var LogDocumentModel = LogDocument{}
|
||||
|
||||
func (ld *LogDocument) GetLogDocumentByLogDocumentId(logDocId string) (logDocuments map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"log_document_id": logDocId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logDocuments = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) Insert(logDocument map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_LogDocument_Name, logDocument))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) CreateAction(userId string, documentId string, spaceId string) (id int64, err error) {
|
||||
logDocument := map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"document_id": documentId,
|
||||
"space_id": spaceId,
|
||||
"comment": "创建了文档",
|
||||
"action": LogDocument_Action_Create,
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
return ld.Insert(logDocument)
|
||||
}
|
||||
|
||||
func (ld *LogDocument) UpdateAction(userId string, documentId string, comment string, spaceId string) (id int64, err error) {
|
||||
logDocument := map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"document_id": documentId,
|
||||
"space_id": spaceId,
|
||||
"comment": comment,
|
||||
"action": LogDocument_Action_Update,
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
return ld.Insert(logDocument)
|
||||
}
|
||||
|
||||
func (ld *LogDocument) DeleteAction(userId string, documentId string, spaceId string) (id int64, err error) {
|
||||
logDocument := map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"document_id": documentId,
|
||||
"space_id": spaceId,
|
||||
"comment": "删除了该文档",
|
||||
"action": LogDocument_Action_Delete,
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
return ld.Insert(logDocument)
|
||||
}
|
||||
|
||||
func (ld *LogDocument) GetLogDocumentsByDocumentId(documentId string) (logDocuments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logDocuments = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) GetLogDocumentsByUserId(userId string) (logDocuments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logDocuments = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) GetLogDocumentsByDocumentIdAndLimit(documentId string, limit int, number int) (logDocuments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
}).Limit(limit, number).OrderBy("log_document_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logDocuments = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) GetLogDocumentsByUserIdAndLimit(userId string, limit int, number int) (logDocuments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
}).Limit(limit, number).OrderBy("log_document_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logDocuments = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) GetLogDocumentsByUserIdKeywordAndLimit(userId string, keyword string, limit int, number int) (logDocuments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"comment LIKE": "%" + keyword + "%",
|
||||
"user_id": userId,
|
||||
}).Limit(limit, number).OrderBy("log_document_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logDocuments = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) GetLogDocumentsByKeywordAndLimit(keyword string, limit int, number int) (logDocuments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"comment LIKE": "%" + keyword + "%",
|
||||
}).Limit(limit, number).OrderBy("log_document_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logDocuments = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) GetLogDocumentsByLimit(userId string, limit int, number int) (logDocuments []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
where := db.AR().From(Table_LogDocument_Name)
|
||||
|
||||
// 查询用户空间权限
|
||||
spaceUserRs, err := db.Query(db.AR().From(Table_SpaceUser_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
}))
|
||||
|
||||
spaceUsers := spaceUserRs.Rows()
|
||||
spaceUsersLen := len(spaceUsers)
|
||||
|
||||
for i := 0; i < spaceUsersLen; i++ {
|
||||
spaceUser := spaceUsers[i]
|
||||
if i == 0 {
|
||||
where.WhereWrap(map[string]interface{}{
|
||||
"space_id": spaceUser["space_id"],
|
||||
}, "", "")
|
||||
} else {
|
||||
where.WhereWrap(map[string]interface{}{
|
||||
"space_id": spaceUser["space_id"],
|
||||
}, "or", "")
|
||||
}
|
||||
}
|
||||
|
||||
// 查询公共空间
|
||||
spaceRs, err := db.Query(db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"visit_level": "public",
|
||||
}))
|
||||
|
||||
spaces := spaceRs.Rows()
|
||||
|
||||
for i := 0; i < len(spaces); i++ {
|
||||
space := spaces[i]
|
||||
if i == 0 && spaceUsersLen == 0 {
|
||||
where.WhereWrap(map[string]interface{}{
|
||||
"space_id": space["space_id"],
|
||||
}, "", "")
|
||||
} else {
|
||||
where.WhereWrap(map[string]interface{}{
|
||||
"space_id": space["space_id"],
|
||||
}, "or", "")
|
||||
}
|
||||
}
|
||||
|
||||
rs, err = db.Query(where.Limit(limit, number).OrderBy("log_document_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logDocuments = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) CountLogDocumentsByDocumentId(documentId string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().Select("count(*) as total").From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"document_id": documentId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) CountLogDocumentsByUserId(userId string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().Select("count(*) as total").From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) CountLogDocumentsByUserIdAndKeyword(userId string, keyword string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().Select("count(*) as total").From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"comment LIKE": "%" + keyword + "%",
|
||||
"user_id": userId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) CountLogDocumentsByKeyword(keyword string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().Select("count(*) as total").From(Table_LogDocument_Name).Where(map[string]interface{}{
|
||||
"comment LIKE": "%" + keyword + "%",
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
func (ld *LogDocument) CountLogDocuments() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_LogDocument_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const TablePluginName = "plugin"
|
||||
|
||||
type Plugin struct {
|
||||
}
|
||||
|
||||
var PluginModel = Plugin{}
|
||||
|
||||
// get plugin by plugin_id
|
||||
func (p *Plugin) GetPluginByPluginId(pluginId string) (plugin map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(TablePluginName).Where(map[string]interface{}{
|
||||
"plugin_id": pluginId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plugin = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// update plugin by plugin_id
|
||||
func (p *Plugin) Update(pluginId string, pluginValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
pluginValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(TablePluginName, pluginValue, map[string]interface{}{
|
||||
"plugin_id": pluginId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get limit plugins by search keyword
|
||||
func (p *Plugin) GetPluginsByKeywordAndLimit(keyword string, limit int, number int) (plugins []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(TablePluginName).Where(map[string]interface{}{
|
||||
"title LIKE": "%" + keyword + "%",
|
||||
}).Limit(limit, number).OrderBy("plugin_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plugins = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get limit plugins
|
||||
func (p *Plugin) GetPluginsByLimit(limit int, number int) (plugins []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(TablePluginName).
|
||||
Limit(limit, number).
|
||||
OrderBy("plugin_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plugins = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// update plugin conf value by pluginKey
|
||||
func (p *Plugin) UpdateConfValueByKey(pluginKey string, confValue string) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
pluginValue := map[string]interface{}{}
|
||||
pluginValue["conf_value"] = confValue
|
||||
pluginValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(TablePluginName, pluginValue, map[string]interface{}{
|
||||
"plugin_key": pluginKey,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// update plugin conf value by pluginId
|
||||
func (p *Plugin) UpdateConfValueByPluginId(pluginId string, confValue string) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
pluginValue := map[string]interface{}{}
|
||||
pluginValue["conf_value"] = confValue
|
||||
pluginValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(TablePluginName, pluginValue, map[string]interface{}{
|
||||
"plugin_id": pluginId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get all plugins
|
||||
func (p *Plugin) GetPlugins() (plugins []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(TablePluginName))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plugins = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get all plugins key map
|
||||
func (p *Plugin) GetPluginsKeyMap() (pluginMaps map[string]map[string]string, err error) {
|
||||
pluginMaps = make(map[string]map[string]string)
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(TablePluginName))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plugins := rs.Rows()
|
||||
for _, plugin := range plugins {
|
||||
key, ok := plugin["key"]
|
||||
if ok {
|
||||
pluginMaps[key] = plugin
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get plugin by many plugin_id
|
||||
func (p *Plugin) GetPluginByPluginIds(pluginIds []string) (plugins []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(TablePluginName).Where(map[string]interface{}{
|
||||
"plugin_id": pluginIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plugins = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// insert plugin
|
||||
func (p *Plugin) Insert(insertValue map[string]interface{}) (id int64, err error) {
|
||||
|
||||
insertValue["create_time"] = time.Now().Unix()
|
||||
insertValue["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(TablePluginName, insertValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get plugin by pluginKey
|
||||
func (p *Plugin) GetPluginByKey(pluginKey string) (plugin map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(TablePluginName).Where(map[string]interface{}{
|
||||
"plugin_key": pluginKey,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plugin = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get plugin value by plugin key
|
||||
func (p *Plugin) GetConfValueByKey(pluginKey string, defaultValue string) (value string) {
|
||||
|
||||
pluginData, err := p.GetPluginByKey(pluginKey)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
if len(pluginData) == 0 {
|
||||
return defaultValue
|
||||
}
|
||||
if value, ok := pluginData["conf_value"]; ok {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// get plugin count
|
||||
func (p *Plugin) CountPlugins() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(TablePluginName))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get role count by keyword
|
||||
func (p *Plugin) CountPluginsByKeyword(keyword string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().
|
||||
Select("count(*) as total").
|
||||
From(TablePluginName).
|
||||
Where(map[string]interface{}{
|
||||
"title LIKE": "%" + keyword + "%",
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Privilege struct {
|
||||
}
|
||||
|
||||
const Table_Privilege_Name = "privilege"
|
||||
|
||||
const (
|
||||
Privilege_Type_Menu = "menu"
|
||||
Privilege_Type_Controller = "controller"
|
||||
|
||||
Privilege_DisPlay_True = "1"
|
||||
Privilege_DisPlay_False = "0"
|
||||
)
|
||||
|
||||
var Privilege_Default_Ids = []string{"1", "2", "3", "4", "5", "6", "7", "8", "9"}
|
||||
|
||||
var PrivilegeModel = Privilege{}
|
||||
|
||||
func (p *Privilege) GetTypePrivileges() (menus, controllers []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Privilege_Name).OrderBy("sequence", "ASC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
menus = []map[string]string{}
|
||||
controllers = []map[string]string{}
|
||||
for _, row := range rs.Rows() {
|
||||
switch row["type"] {
|
||||
case Privilege_Type_Menu:
|
||||
menus = append(menus, row)
|
||||
case Privilege_Type_Controller:
|
||||
controllers = append(controllers, row)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Privilege) GetPrivileges() (privileges []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Privilege_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
privileges = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Privilege) GetPrivilegeByTypeControllerAndAction(ty, controller, action string) (privilege map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Privilege_Name).Where(map[string]interface{}{
|
||||
"type": ty,
|
||||
"controller": controller,
|
||||
"action": action,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
privilege = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Privilege) GetTypePrivilegesByUserId(userId string) (menus, controllers []map[string]string, err error) {
|
||||
|
||||
user, err := UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(user) == 0 {
|
||||
return
|
||||
}
|
||||
roleId := user["role_id"]
|
||||
|
||||
if roleId == fmt.Sprintf("%d", Role_Root_Id) {
|
||||
return PrivilegeModel.GetTypePrivileges()
|
||||
}
|
||||
rolePrivileges := []map[string]string{}
|
||||
rolePrivileges, err = RolePrivilegeModel.GetRolePrivilegesByRoleId(roleId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var privilegeIds = []string{}
|
||||
for _, rolePrivilege := range rolePrivileges {
|
||||
privilegeIds = append(privilegeIds, rolePrivilege["privilege_id"])
|
||||
}
|
||||
return PrivilegeModel.GetTypePrivilegesByPrivilegeIds(privilegeIds)
|
||||
}
|
||||
|
||||
func (p *Privilege) GetTypePrivilegesByDisplay(display string) (menus, controllers []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Privilege_Name).Where(map[string]interface{}{
|
||||
"is_display": display,
|
||||
}).OrderBy("sequence", "ASC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
menus = []map[string]string{}
|
||||
controllers = []map[string]string{}
|
||||
for _, row := range rs.Rows() {
|
||||
switch row["type"] {
|
||||
case Privilege_Type_Menu:
|
||||
menus = append(menus, row)
|
||||
case Privilege_Type_Controller:
|
||||
controllers = append(controllers, row)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Privilege) GetTypePrivilegesByDisplayPrivilegeIds(display string, privilegeIds []string) (menus, controllers []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Privilege_Name).Where(map[string]interface{}{
|
||||
"is_display": display,
|
||||
"privilege_id": privilegeIds,
|
||||
}).OrderBy("sequence", "ASC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
menus = []map[string]string{}
|
||||
controllers = []map[string]string{}
|
||||
for _, row := range rs.Rows() {
|
||||
switch row["type"] {
|
||||
case Privilege_Type_Menu:
|
||||
menus = append(menus, row)
|
||||
case Privilege_Type_Controller:
|
||||
controllers = append(controllers, row)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Privilege) GetTypePrivilegesByPrivilegeIds(privilegeIds []string) (menus, controllers []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Privilege_Name).Where(map[string]interface{}{
|
||||
"privilege_id": privilegeIds,
|
||||
}).OrderBy("sequence", "ASC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
menus = []map[string]string{}
|
||||
controllers = []map[string]string{}
|
||||
for _, row := range rs.Rows() {
|
||||
switch row["type"] {
|
||||
case Privilege_Type_Menu:
|
||||
menus = append(menus, row)
|
||||
case Privilege_Type_Controller:
|
||||
controllers = append(controllers, row)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Privilege) GetPrivilegeByPrivilegeId(privilegeId string) (privilege map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Privilege_Name).Where(map[string]interface{}{
|
||||
"privilege_id": privilegeId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
privilege = rs.Row()
|
||||
return
|
||||
}
|
||||
func (p *Privilege) HasSub(privilegeId string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Privilege_Name).Where(map[string]interface{}{
|
||||
"parent_id": privilegeId,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
func (p *Privilege) Delete(privilegeId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_Privilege_Name, map[string]interface{}{
|
||||
"privilege_id": privilegeId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
func (p *Privilege) Insert(privilege map[string]interface{}) (id int64, err error) {
|
||||
|
||||
privilege["create_time"] = time.Now().Unix()
|
||||
privilege["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Privilege_Name, privilege))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Privilege) InsertNotExists(privilege map[string]interface{}) (id int64, err error) {
|
||||
|
||||
privilege["create_time"] = time.Now().Unix()
|
||||
privilege["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
rs, err := db.Query(db.AR().From(Table_Privilege_Name).Where(map[string]interface{}{
|
||||
"type": privilege["type"],
|
||||
"controller": privilege["controller"],
|
||||
"action": privilege["action"],
|
||||
}))
|
||||
if rs.Len() == 0 {
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Privilege_Name, privilege))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Privilege) Update(privilegeId string, privilege map[string]interface{}) (id int64, err error) {
|
||||
|
||||
privilege["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Update(Table_Privilege_Name, privilege, map[string]interface{}{
|
||||
"privilege_id": privilegeId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Role_Delete_True = 1
|
||||
Role_Delete_False = 0
|
||||
|
||||
Role_Type_System = 1
|
||||
Role_Type_Default = 0
|
||||
|
||||
Role_Root_Id = 1 // 超级管理员
|
||||
Role_Admin_Id = 2 // 管理员
|
||||
Role_Default_Id = 3 // 普通用户
|
||||
)
|
||||
|
||||
const Table_Role_Name = "role"
|
||||
|
||||
type Role struct {
|
||||
}
|
||||
|
||||
var RoleModel = Role{}
|
||||
|
||||
// get role by role_id
|
||||
func (r *Role) GetRoleByRoleId(roleId string) (role map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"role_id": roleId,
|
||||
"is_delete": Role_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
role = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// role_id and name is exists
|
||||
func (r *Role) HasSameName(roleId, name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"role_id <>": roleId,
|
||||
"name": name,
|
||||
"is_delete": Role_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// name is exists
|
||||
func (r *Role) HasRoleName(name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
"is_delete": Role_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get role by name
|
||||
func (r *Role) GetRoleByName(name string) (role map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
"is_delete": Role_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
role = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete role by role_id
|
||||
func (r *Role) Delete(roleId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Update(Table_Role_Name, map[string]interface{}{
|
||||
"is_delete": Role_Delete_True,
|
||||
"update_time": time.Now().Unix(),
|
||||
}, map[string]interface{}{
|
||||
"role_id": roleId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// insert role
|
||||
func (r *Role) Insert(roleValue map[string]interface{}) (id int64, err error) {
|
||||
|
||||
roleValue["create_time"] = time.Now().Unix()
|
||||
roleValue["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
tx, err := db.Begin(db.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.ExecTx(db.AR().Insert(Table_Role_Name, roleValue), tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
|
||||
// add default privileges
|
||||
rolePrivileges := []map[string]interface{}{}
|
||||
for _, privilegeId := range Privilege_Default_Ids {
|
||||
rolePrivilege := map[string]interface{}{
|
||||
"role_id": id,
|
||||
"privilege_id": privilegeId,
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
rolePrivileges = append(rolePrivileges, rolePrivilege)
|
||||
}
|
||||
_, err = db.ExecTx(db.AR().InsertBatch(Table_RolePrivilege_Name, rolePrivileges), tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// update role by role_id
|
||||
func (r *Role) Update(roleId string, roleValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
roleValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Role_Name, roleValue, map[string]interface{}{
|
||||
"role_id": roleId,
|
||||
"is_delete": Role_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get limit roles by search keyword
|
||||
func (r *Role) GetRolesByKeywordAndLimit(keyword string, limit int, number int) (roles []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
"is_delete": Role_Delete_False,
|
||||
}).Limit(limit, number).OrderBy("role_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
roles = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get limit roles
|
||||
func (r *Role) GetRolesByLimit(limit int, number int) (roles []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
From(Table_Role_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_delete": Role_Delete_False,
|
||||
}).
|
||||
Limit(limit, number).
|
||||
OrderBy("role_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
roles = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get all roles
|
||||
func (r *Role) GetRoles() (roles []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"is_delete": Role_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
roles = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get all roles not contain root
|
||||
func (r *Role) GetRolesNotContainRoot() (roles []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"role_id !=": Role_Root_Id,
|
||||
"is_delete": Role_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
roles = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get role count
|
||||
func (r *Role) CountRoles() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Role_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_delete": Role_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get role count by keyword
|
||||
func (r *Role) CountRolesByKeyword(keyword string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Role_Name).
|
||||
Where(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
"is_delete": Role_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get role by name
|
||||
func (r *Role) GetRoleByLikeName(name string) (roles []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
"is_delete": Role_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
roles = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get role by many role_id
|
||||
func (r *Role) GetRoleByRoleIds(roleIds []string) (roles []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"role_id": roleIds,
|
||||
"is_delete": Role_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
roles = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// update role by name
|
||||
func (r *Role) UpdateRoleByName(role map[string]interface{}) (affect int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
role["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Role_Name, role, map[string]interface{}{
|
||||
"name": role["name"],
|
||||
"is_delete": Role_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
affect = rs.RowsAffected
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
var RolePrivilegeModel = RolePrivilege{}
|
||||
|
||||
const Table_RolePrivilege_Name = "role_privilege"
|
||||
|
||||
type RolePrivilege struct {
|
||||
}
|
||||
|
||||
func (rolePrivilege *RolePrivilege) GetRolePrivilegesByRoleId(roleId string) (rolePrivileges []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
res, err := db.Query(db.AR().From(Table_RolePrivilege_Name).Where(map[string]interface{}{
|
||||
"role_id": roleId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rolePrivileges = res.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
func (rolePrivilege *RolePrivilege) GetRootRolePrivileges() (rolePrivileges []map[string]string, err error) {
|
||||
|
||||
privileges, err := PrivilegeModel.GetPrivileges()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, privilege := range privileges {
|
||||
rolePrivilege := map[string]string{
|
||||
"role_privilege_id": "",
|
||||
"role_id": fmt.Sprintf("%d", Role_Root_Id),
|
||||
"privilege_id": privilege["privilege_id"],
|
||||
}
|
||||
rolePrivileges = append(rolePrivileges, rolePrivilege)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (rolePrivilege *RolePrivilege) GrantRolePrivileges(roleId string, privilegeIds []string) (res bool, err error) {
|
||||
|
||||
res = false
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_RolePrivilege_Name, map[string]interface{}{
|
||||
"role_id": roleId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rolePrivileges := []map[string]interface{}{}
|
||||
for _, privilegeId := range privilegeIds {
|
||||
rolePrivilege := map[string]interface{}{
|
||||
"role_id": roleId,
|
||||
"privilege_id": privilegeId,
|
||||
"create_time": time.Now().Unix(),
|
||||
}
|
||||
rolePrivileges = append(rolePrivileges, rolePrivilege)
|
||||
}
|
||||
_, err = db.Exec(db.AR().InsertBatch(Table_RolePrivilege_Name, rolePrivileges))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = true
|
||||
return
|
||||
}
|
||||
|
||||
// delete role privilege by role_id
|
||||
func (rolePrivilege *RolePrivilege) DeleteByRoleId(roleId string) (err error) {
|
||||
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_RolePrivilege_Name, map[string]interface{}{
|
||||
"role_id": roleId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// delete role privilege by privilege_id
|
||||
func (rolePrivilege *RolePrivilege) DeleteByPrivilegeId(privilegeId string) (err error) {
|
||||
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_RolePrivilege_Name, map[string]interface{}{
|
||||
"privilege_id": privilegeId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Space_Share_False = 0
|
||||
Space_Share_True = 1
|
||||
|
||||
Space_Download_False = 0
|
||||
Space_Download_True = 1
|
||||
|
||||
Space_Delete_True = 1
|
||||
Space_Delete_False = 0
|
||||
|
||||
Space_Root_Id = 1
|
||||
Space_Admin_Id = 2
|
||||
Space_Default_Id = 3
|
||||
|
||||
Space_VisitLevel_Public = "public"
|
||||
Space_VisitLevel_Private = "private"
|
||||
)
|
||||
|
||||
const Table_Space_Name = "space"
|
||||
|
||||
type Space struct {
|
||||
}
|
||||
|
||||
var SpaceModel = Space{}
|
||||
|
||||
// get space by space_id
|
||||
func (s *Space) GetSpaceBySpaceId(spaceId string) (space map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"is_delete": Space_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
space = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// space_id and name is exists
|
||||
func (s *Space) HasSameName(spaceId, name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"space_id <>": spaceId,
|
||||
"name": name,
|
||||
"is_delete": Space_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// name is exists
|
||||
func (s *Space) HasSpaceName(name string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
"is_delete": Space_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get space by name
|
||||
func (s *Space) GetSpaceByName(name string) (space map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"name": name,
|
||||
"is_delete": Space_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
space = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete space by space_id
|
||||
func (s *Space) Delete(spaceId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Update(Table_Space_Name, map[string]interface{}{
|
||||
"is_delete": Space_Delete_True,
|
||||
"update_time": time.Now().Unix(),
|
||||
}, map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// delete collect space
|
||||
go func() {
|
||||
CollectionModel.DeleteByResourceIdType(spaceId, fmt.Sprintf("%d", Collection_Type_Space))
|
||||
}()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// insert space
|
||||
func (s *Space) Insert(spaceValue map[string]interface{}) (id int64, err error) {
|
||||
|
||||
spaceValue["create_time"] = time.Now().Unix()
|
||||
spaceValue["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_Space_Name, spaceValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// update space by space_id
|
||||
func (s *Space) Update(spaceId string, spaceValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
spaceValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Space_Name, spaceValue, map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"is_delete": Space_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// update space db and file name by space_id
|
||||
func (s *Space) UpdateDBAndSpaceFileName(spaceId string, spaceValue map[string]interface{}, oldName string) (id int64, err error) {
|
||||
// begin update
|
||||
db := G.DB()
|
||||
tx, err := db.Begin(db.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var rs *mysql.ResultSet
|
||||
|
||||
// get real old space name (v0.1.2 #53 bug)
|
||||
defaultDocument, err := DocumentModel.GetDocumentByParentIdAndSpaceId("0", spaceId, Document_Type_Dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if oldName != defaultDocument["name"] {
|
||||
oldName = defaultDocument["name"]
|
||||
}
|
||||
|
||||
// update space db
|
||||
spaceValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.ExecTx(db.AR().Update(Table_Space_Name, spaceValue, map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"is_delete": Space_Delete_False,
|
||||
}), tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
|
||||
documentValue := map[string]interface{}{
|
||||
"name": spaceValue["name"],
|
||||
"update_time": time.Now().Unix(),
|
||||
}
|
||||
// update space document name
|
||||
_, err = db.ExecTx(db.AR().Update(Table_Document_Name, documentValue, map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"parent_id": 0,
|
||||
"type": Document_Type_Dir,
|
||||
}), tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
// update space name
|
||||
err = utils.Document.UpdateSpaceName(oldName, spaceValue["name"].(string))
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
err = tx.Commit()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get limit spaces by search keyword
|
||||
func (s *Space) GetSpacesByKeywordAndLimit(keyword string, limit int, number int) (spaces []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"is_delete": Space_Delete_False,
|
||||
}).WhereWrap(map[string]interface{}{
|
||||
"name LIKE": "%" + keyword + "%",
|
||||
}, "AND (", "").WhereWrap(map[string]interface{}{
|
||||
"description LIKE": "%" + keyword + "%",
|
||||
}, "OR", ")").Limit(limit, number).OrderBy("space_id", "DESC")
|
||||
rs, err = db.Query(sql)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaces = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get limit spaces
|
||||
func (s *Space) GetSpacesByLimit(limit int, number int) (spaces []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
From(Table_Space_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_delete": Space_Delete_False,
|
||||
}).
|
||||
Limit(limit, number).
|
||||
OrderBy("space_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaces = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get all spaces
|
||||
func (s *Space) GetSpaces() (spaces []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"is_delete": Space_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaces = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get spaces by visitLevel
|
||||
func (s *Space) GetSpacesByVisitLevel(visitLevel string) (spaces []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"visit_level": visitLevel,
|
||||
"is_delete": Space_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaces = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get space count
|
||||
func (s *Space) CountSpaces() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Space_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_delete": Space_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get space count
|
||||
func (s *Space) CountSpacesByTags(tag string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_Space_Name).
|
||||
Where(map[string]interface{}{
|
||||
"tags LIKE": "%" + tag + "%",
|
||||
"is_delete": Space_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get space count by keyword
|
||||
func (s *Space) CountSpacesByKeyword(keyword string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
sql := db.AR().Select("count(*) as total").From(Table_Space_Name).
|
||||
Where(map[string]interface{}{"is_delete": Space_Delete_False}).
|
||||
WhereWrap(map[string]interface{}{"name LIKE": "%" + keyword + "%"}, "AND (", "").
|
||||
WhereWrap(map[string]interface{}{"description LIKE": "%" + keyword + "%"}, "OR", ")")
|
||||
rs, err = db.Query(sql)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get space count by tags
|
||||
func (s *Space) GetSpacesByTags(tag string) (spaces []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"tags LIKE": "%" + tag + "%",
|
||||
"is_delete": Space_Delete_False,
|
||||
}).OrderBy("space_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaces = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get space by name
|
||||
func (s *Space) GetSpaceByLikeName(name string) (spaces []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"name Like": "%" + name + "%",
|
||||
"is_delete": Space_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaces = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get space by many space_id
|
||||
func (s *Space) GetSpaceBySpaceIds(spaceIds []string) (spaces []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Space_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceIds,
|
||||
"is_delete": Space_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaces = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// update space by name
|
||||
func (s *Space) UpdateSpaceByName(space map[string]interface{}) (affect int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
space["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_Space_Name, space, map[string]interface{}{
|
||||
"name": space["name"],
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
affect = rs.RowsAffected
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const Table_SpaceUser_Name = "space_user"
|
||||
|
||||
const (
|
||||
SpaceUser_Privilege_Visitor = 0
|
||||
SpaceUser_Privilege_Editor = 1
|
||||
SpaceUser_Privilege_Manager = 2
|
||||
)
|
||||
|
||||
type SpaceUser struct {
|
||||
}
|
||||
|
||||
var SpaceUserModel = SpaceUser{}
|
||||
|
||||
// get space_user by space_user_id
|
||||
func (s *SpaceUser) GetSpaceUserBySpaceUserId(spaceUserId string) (spaceUser map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_SpaceUser_Name).Where(map[string]interface{}{
|
||||
"space_user_id": spaceUserId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaceUser = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// get space_user by name
|
||||
func (s *SpaceUser) GetSpaceUsersByUserId(userId string) (spaceUsers []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_SpaceUser_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaceUsers = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get space_user by name
|
||||
func (s *SpaceUser) GetSpaceUsersBySpaceId(spaceId string) (spaceUsers []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_SpaceUser_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaceUsers = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get space_user count by keyword
|
||||
func (s *SpaceUser) GetSpaceUserBySpaceIdAndUserId(spaceId string, userId string) (spaceUser map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_SpaceUser_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"user_id": userId,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaceUser = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete space_user by space_user_id
|
||||
func (s *SpaceUser) Delete(spaceUserId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_SpaceUser_Name, map[string]interface{}{
|
||||
"space_user_id": spaceUserId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// delete space_user by space_user_id
|
||||
func (s *SpaceUser) DeleteBySpaceId(spaceId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_SpaceUser_Name, map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// delete space_user by space_user_id
|
||||
func (s *SpaceUser) DeleteByUserId(userId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_SpaceUser_Name, map[string]interface{}{
|
||||
"user_id": userId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// delete space_user by space_id and user_id
|
||||
func (s *SpaceUser) DeleteBySpaceIdAndUserId(spaceId string, userId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Delete(Table_SpaceUser_Name, map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"user_id": userId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// insert space_user
|
||||
func (s *SpaceUser) Insert(spaceUserValue map[string]interface{}) (id int64, err error) {
|
||||
|
||||
spaceUserValue["create_time"] = time.Now().Unix()
|
||||
spaceUserValue["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_SpaceUser_Name, spaceUserValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// update space_user by space_user_id
|
||||
func (s *SpaceUser) Update(spaceUserId string, spaceUserValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
spaceUserValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_SpaceUser_Name, spaceUserValue, map[string]interface{}{
|
||||
"space_user_id": spaceUserId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// get limit space_users by spaceId
|
||||
func (s *SpaceUser) GetSpaceUsersBySpaceIdAndLimit(spaceId string, limit int, number int) (spaceUsers []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_SpaceUser_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
}).Limit(limit, number))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaceUsers = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get all space_users
|
||||
func (s *SpaceUser) GetSpaceUsers() (spaceUsers []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().From(Table_SpaceUser_Name))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaceUsers = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get space_user count by keyword
|
||||
func (s *SpaceUser) CountSpaceUsersBySpaceId(spaceId string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_SpaceUser_Name).
|
||||
Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.Convert.StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get space_user by many space_user_id
|
||||
func (s *SpaceUser) GetSpaceUsersBySpaceUserIds(spaceUserIds []string) (spaceUsers []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_SpaceUser_Name).Where(map[string]interface{}{
|
||||
"space_user_id": spaceUserIds,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
spaceUsers = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// space user is exists
|
||||
func (s *SpaceUser) HasSpaceUser(spaceId string, userId string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_Role_Name).Where(map[string]interface{}{
|
||||
"space_id": spaceId,
|
||||
"user_id": userId,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/phachon/mm-wiki/global"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Upgrade struct {
|
||||
}
|
||||
|
||||
type upgradeHandleFunc func() error
|
||||
|
||||
type upgradeHandle struct {
|
||||
Version string
|
||||
Func upgradeHandleFunc
|
||||
}
|
||||
|
||||
var (
|
||||
UpgradeModel = Upgrade{}
|
||||
|
||||
upgradeMap = []*upgradeHandle{}
|
||||
)
|
||||
|
||||
// upgrade handle func
|
||||
func (up *Upgrade) initHandleFunc() {
|
||||
// v0 ~ v0.1.2
|
||||
upgradeMap = append(upgradeMap, &upgradeHandle{Version: "v0.1.2", Func: up.v0ToV012})
|
||||
|
||||
// v0.1.2 ~ v0.1.3
|
||||
upgradeMap = append(upgradeMap, &upgradeHandle{Version: "v0.1.3", Func: up.v012ToV013})
|
||||
|
||||
// v0.1.3 ~ v0.1.8
|
||||
upgradeMap = append(upgradeMap, &upgradeHandle{Version: "v0.1.8", Func: up.v013ToV018})
|
||||
|
||||
// v0.1.8 ~ v0.2.0
|
||||
upgradeMap = append(upgradeMap, &upgradeHandle{Version: "v0.2.0", Func: up.v018ToV020})
|
||||
|
||||
// v0.2.1 ~ v0.2.7
|
||||
//upgradeMap = append(upgradeMap, &upgradeHandle{Version: "v0.2.7", Func: up.v021ToV027})
|
||||
// v0.2.7 ~ v0.3.3
|
||||
//upgradeMap = append(upgradeMap, &upgradeHandle{Version: "v0.3.3", Func: up.v027ToV033})
|
||||
}
|
||||
|
||||
// upgrade start
|
||||
func (up *Upgrade) Start(dbVersion string) (err error) {
|
||||
up.initHandleFunc()
|
||||
|
||||
var tmpVersion = dbVersion
|
||||
for _, upHandle := range upgradeMap {
|
||||
// upgrade now version, exit
|
||||
if tmpVersion == global.SYSTEM_VERSION {
|
||||
break
|
||||
}
|
||||
// tmpVersion < upHandle.version
|
||||
if utils.VersionCompare.Lt(tmpVersion, upHandle.Version) {
|
||||
// upgrade handle
|
||||
err = upHandle.Func()
|
||||
if err != nil {
|
||||
logs.Error("upgrade to " + upHandle.Version + " error: " + err.Error())
|
||||
return errors.New("upgrade to " + upHandle.Version + " error: " + err.Error())
|
||||
}
|
||||
// update system database version
|
||||
err = up.upgradeAfter(upHandle.Version)
|
||||
if err != nil {
|
||||
logs.Error("upgrade to database " + upHandle.Version + " error: " + err.Error())
|
||||
return errors.New("upgrade to database " + upHandle.Version + " error: " + err.Error())
|
||||
}
|
||||
logs.Info("upgrade to " + upHandle.Version + " success")
|
||||
// update version record
|
||||
tmpVersion = upHandle.Version
|
||||
}
|
||||
}
|
||||
// last update current version
|
||||
err = up.upgradeAfter(global.SYSTEM_VERSION)
|
||||
if err != nil {
|
||||
logs.Error("upgrade to database " + global.SYSTEM_VERSION + " error: " + err.Error())
|
||||
return errors.New("upgrade to database " + global.SYSTEM_VERSION + " error: " + err.Error())
|
||||
}
|
||||
logs.Info("upgrade finish, version: " + global.SYSTEM_VERSION)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgrade v0.0.0 ~ v0.1.2
|
||||
func (up *Upgrade) v0ToV012() (err error) {
|
||||
|
||||
// 1. add privilege '/email/test'
|
||||
// INSERT INTO mw_privilege (name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES ('测试邮件服务器', 53, 'controller', 'email', 'test', 'glyphicon-list', 0, 80, unix_timestamp(now()), unix_timestamp(now()));
|
||||
privilege := map[string]interface{}{
|
||||
"name": "测试邮件服务器",
|
||||
"type": "controller",
|
||||
"parent_id": 53,
|
||||
"controller": "email",
|
||||
"action": "test",
|
||||
"target": "",
|
||||
"icon": "glyphicon-list",
|
||||
"is_display": 0,
|
||||
"sequence": 80,
|
||||
}
|
||||
_, err = PrivilegeModel.InsertNotExists(privilege)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 2. table mw_email add field 'is_ssl'
|
||||
// alter table mw_email add `is_ssl` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用ssl, 0 默认不使用 1 使用' after `password`
|
||||
db := G.DB()
|
||||
db.Exec(db.AR().Raw("alter table mw_email DROP COLUMN `is_ssl`"))
|
||||
_, err = db.Exec(db.AR().Raw("alter table mw_email add `is_ssl` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用ssl, 0 默认不使用 1 使用' after `password`"))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// upgrade v0.1.2 ~ v0.1.3
|
||||
func (up *Upgrade) v012ToV013() error {
|
||||
|
||||
// create attachment table
|
||||
sql := "DROP TABLE IF EXISTS `mw_attachment`;" +
|
||||
"CREATE TABLE `mw_attachment` (" +
|
||||
"`attachment_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '附件 id'," +
|
||||
"`user_id` int(10) NOT NULL DEFAULT '0' COMMENT '创建用户id'," +
|
||||
"`document_id` int(10) NOT NULL DEFAULT '0' COMMENT '所属文档id'," +
|
||||
"`name` varchar(50) NOT NULL DEFAULT '' COMMENT '附件名称'," +
|
||||
"`path` varchar(100) NOT NULL DEFAULT '' COMMENT '附件路径'," +
|
||||
"`source` tinyint(1) NOT NULL DEFAULT '0' COMMENT '附件来源, 0 默认是附件 1 图片'," +
|
||||
"`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间'," +
|
||||
"`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间'," +
|
||||
"PRIMARY KEY (`attachment_id`)," +
|
||||
"KEY (`document_id`, `source`)" +
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='附件信息表';"
|
||||
|
||||
return up.createTable(sql)
|
||||
}
|
||||
|
||||
// upgrade v0.1.3 ~ v0.1.8
|
||||
func (up *Upgrade) v013ToV018() error {
|
||||
db := G.DB()
|
||||
|
||||
// 1. 文档日志表增加 space_id 字段
|
||||
// `space_id` int(10) NOT NULL DEFAULT '0' COMMENT '空间id'
|
||||
_, err := db.Exec(db.AR().Raw("alter table mw_log_document add `space_id` int(10) NOT NULL DEFAULT '0' COMMENT '空间ID'"))
|
||||
if err == nil {
|
||||
// 文档日志表里的 space_id
|
||||
_, err = db.Exec(db.AR().Raw("update mw_log_document as logDocment, mw_document as document set logDocment.space_id = document.space_id WHERE logDocment.document_id = document.document_id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 修改文档表里的排序号,需要先判断排序号是否已经修改过(只修改sequence=0)
|
||||
_, err = db.Exec(db.AR().Raw("update mw_document set mw_document.sequence = mw_document.document_id WHERE sequence=0"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgrade v0.1.8 ~ v0.2.0
|
||||
func (up *Upgrade) v018ToV020() error {
|
||||
// 配置表增加数据
|
||||
db := G.DB()
|
||||
updateTime := time.Now().Unix()
|
||||
// 1. 配置表增加全文搜索开关
|
||||
insertSql := fmt.Sprintf("INSERT INTO `mw_config` (name, `key`, value, create_time, update_time) VALUES ('开启全文搜索', 'fulltext_search_open', '1', %d, %d)", updateTime, updateTime)
|
||||
_, err := db.Exec(db.AR().Raw(insertSql))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 2. 配置表增加搜索索引时间间隔
|
||||
insertSql = fmt.Sprintf("INSERT INTO `mw_config` (name, `key`, value, create_time, update_time) VALUES ('索引更新间隔', 'doc_search_timer', '3600', %d, %d)", updateTime, updateTime)
|
||||
_, err = db.Exec(db.AR().Raw(insertSql))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 3. 配置表增加系统名称配置
|
||||
insertSql = fmt.Sprintf("INSERT INTO `mw_config` (name, `key`, value, create_time, update_time) VALUES ('系统名称', 'system_name', 'Markdown Mini Wiki', %d, %d)", updateTime, updateTime)
|
||||
_, err = db.Exec(db.AR().Raw(insertSql))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 4. 权限表增加导入联系人权限
|
||||
// INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (93, '导入联系人', 71, 'controller', 'contact', 'import', 'glyphicon-list', '', 0, 97, unix_timestamp(now()), unix_timestamp(now()));
|
||||
privilege := map[string]interface{}{
|
||||
"name": "导入联系人",
|
||||
"type": "controller",
|
||||
"parent_id": 71,
|
||||
"controller": "contact",
|
||||
"action": "import",
|
||||
"target": "",
|
||||
"icon": "glyphicon-list",
|
||||
"is_display": 0,
|
||||
"sequence": 97,
|
||||
}
|
||||
_, err = PrivilegeModel.InsertNotExists(privilege)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgrade v0.2.1 ~ v0.2.7
|
||||
func (up *Upgrade) v021ToV027() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgrade v0.2.7 ~ v0.3.3
|
||||
func (up *Upgrade) v027ToV033() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (up *Upgrade) createTable(sqlTable string) error {
|
||||
host := beego.AppConfig.String("db::host")
|
||||
port, _ := beego.AppConfig.Int("db::port")
|
||||
user := beego.AppConfig.String("db::user")
|
||||
pass := beego.AppConfig.String("db::pass")
|
||||
name := beego.AppConfig.String("db::name")
|
||||
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&multiStatements=true", user, pass, host, port, name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
_, err = db.Exec(sqlTable)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (up *Upgrade) upgradeAfter(version string) (err error) {
|
||||
// update system version
|
||||
config, err := ConfigModel.GetConfigByKey(ConfigKeySystemVersion)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(config) == 0 {
|
||||
configValue := map[string]interface{}{
|
||||
"name": "系统版本号",
|
||||
"key": "system_version",
|
||||
"value": version,
|
||||
}
|
||||
_, err = ConfigModel.Insert(configValue)
|
||||
} else {
|
||||
_, err = ConfigModel.UpdateByKey(ConfigKeySystemVersion, version)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/snail007/go-activerecord/mysql"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
User_Delete_True = 1
|
||||
User_Delete_False = 0
|
||||
|
||||
User_Forbidden_True = 1
|
||||
User_Is_Forbidden_False = 0
|
||||
)
|
||||
|
||||
const Table_User_Name = "user"
|
||||
|
||||
type User struct {
|
||||
}
|
||||
|
||||
var UserModel = User{}
|
||||
|
||||
// get user by user_id
|
||||
func (u *User) GetUserByUserId(userId string) (user map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// user_id and username is exists
|
||||
func (u *User) HasSameUsername(userId, username string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"user_id <>": userId,
|
||||
"username": username,
|
||||
"is_delete": User_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// username is exists
|
||||
func (u *User) HasUsername(username string) (has bool, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"username": username,
|
||||
"is_delete": User_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rs.Len() > 0 {
|
||||
has = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get user by username
|
||||
func (u *User) GetUserByUsername(username string) (user map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"username": username,
|
||||
"is_delete": User_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user = rs.Row()
|
||||
return
|
||||
}
|
||||
|
||||
// delete user by user_id
|
||||
func (u *User) Delete(userId string) (err error) {
|
||||
db := G.DB()
|
||||
_, err = db.Exec(db.AR().Update(Table_User_Name, map[string]interface{}{
|
||||
"is_delete": User_Delete_False,
|
||||
"update_time": time.Now().Unix(),
|
||||
}, map[string]interface{}{
|
||||
"user_id": userId,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// insert user
|
||||
func (u *User) Insert(userValue map[string]interface{}) (id int64, err error) {
|
||||
|
||||
userValue["create_time"] = time.Now().Unix()
|
||||
userValue["update_time"] = time.Now().Unix()
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Exec(db.AR().Insert(Table_User_Name, userValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// update user by user_id
|
||||
func (u *User) Update(userId string, userValue map[string]interface{}) (id int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
userValue["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_User_Name, userValue, map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id = rs.LastInsertId
|
||||
return
|
||||
}
|
||||
|
||||
// update user password
|
||||
func (u *User) ChangePassword(userId, newPassword, oldPassword string) (err error) {
|
||||
db := G.DB()
|
||||
userValue, err := u.GetUserByUserId(userId)
|
||||
if userValue["password"] != u.EncodePassword(oldPassword) {
|
||||
return errors.New("旧密码错误")
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = db.Exec(db.AR().Update(Table_User_Name, map[string]interface{}{
|
||||
"password": u.EncodePassword(newPassword),
|
||||
"update_time": time.Now().Unix(),
|
||||
}, map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// encode password
|
||||
func (u *User) EncodePassword(password string) (passwordHash string) {
|
||||
hasher := md5.New()
|
||||
hasher.Write([]byte(password))
|
||||
passwordHash = strings.ToLower(hex.EncodeToString(hasher.Sum(nil)))
|
||||
return
|
||||
}
|
||||
|
||||
// get limit users by search keyword
|
||||
func (u *User) GetUsersByKeywordsAndLimit(keywords map[string]string, limit int, number int) (users []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
var whereValue = map[string]interface{}{
|
||||
"is_delete": User_Delete_False,
|
||||
}
|
||||
username, ok := keywords["username"]
|
||||
if ok && username != "" {
|
||||
whereValue["username LIKE"] = "%" + username + "%"
|
||||
}
|
||||
roleId, ok := keywords["role_id"]
|
||||
if ok && roleId != "" {
|
||||
whereValue["role_id"] = roleId
|
||||
}
|
||||
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(whereValue).Limit(limit, number).OrderBy("user_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get limit users
|
||||
func (u *User) GetUsersByLimit(limit int, number int) (users []map[string]string, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
From(Table_User_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_delete": User_Delete_False,
|
||||
}).
|
||||
Limit(limit, number).
|
||||
OrderBy("user_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users = rs.Rows()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get user count
|
||||
func (u *User) CountUsers() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_User_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get user count by lastTime
|
||||
func (u *User) CountUsersByLastTime(lastTime int64) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_User_Name).
|
||||
Where(map[string]interface{}{
|
||||
"last_time >=": lastTime,
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get normal user count
|
||||
func (u *User) CountNormalUsers() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_User_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_forbidden": User_Is_Forbidden_False,
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get forbidden user count
|
||||
func (u *User) CountForbiddenUsers() (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(
|
||||
db.AR().
|
||||
Select("count(*) as total").
|
||||
From(Table_User_Name).
|
||||
Where(map[string]interface{}{
|
||||
"is_forbidden": User_Forbidden_True,
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get user count by keyword
|
||||
func (u *User) CountUsersByKeywords(keywords map[string]string) (count int64, err error) {
|
||||
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
var whereValue = map[string]interface{}{
|
||||
"is_delete": User_Delete_False,
|
||||
}
|
||||
username, ok := keywords["username"]
|
||||
if ok && username != "" {
|
||||
whereValue["username LIKE"] = "%" + username + "%"
|
||||
}
|
||||
roleId, ok := keywords["role_id"]
|
||||
if ok && roleId != "" {
|
||||
whereValue["role_id"] = roleId
|
||||
}
|
||||
|
||||
rs, err = db.Query(db.AR().Select("count(*) as total").From(Table_User_Name).Where(whereValue))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count = utils.NewConvert().StringToInt64(rs.Value("total"))
|
||||
return
|
||||
}
|
||||
|
||||
// get user by username
|
||||
func (u *User) GetUserByLikeName(username string) (users []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"username Like": "%" + username + "%",
|
||||
"is_delete": User_Delete_False,
|
||||
}).Limit(0, 1))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get user by many user_id
|
||||
func (u *User) GetUsersByUserIds(userIds []string) (users []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"user_id": userIds,
|
||||
"is_delete": User_Delete_False,
|
||||
}).OrderBy("user_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get user by many user_id
|
||||
func (u *User) GetUsersByRoleId(roleId string) (users []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"role_id": roleId,
|
||||
"is_delete": User_Delete_False,
|
||||
}).OrderBy("user_id", "DESC"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get user by not in user_ids
|
||||
func (u *User) GetUserByNotUserIds(userIds []string) (users []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"user_id NOT": userIds,
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// get all users
|
||||
func (u *User) GetUsers() (users []map[string]string, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
rs, err = db.Query(db.AR().From(Table_User_Name).Where(map[string]interface{}{
|
||||
"is_delete": User_Delete_False,
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users = rs.Rows()
|
||||
return
|
||||
}
|
||||
|
||||
// update user by username
|
||||
func (u *User) UpdateUserByUsername(user map[string]interface{}) (affect int64, err error) {
|
||||
db := G.DB()
|
||||
var rs *mysql.ResultSet
|
||||
user["update_time"] = time.Now().Unix()
|
||||
rs, err = db.Exec(db.AR().Update(Table_User_Name, user, map[string]interface{}{
|
||||
"username": user["username"],
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
affect = rs.RowsAffected
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/services"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
|
||||
"github.com/astaxie/beego/validation"
|
||||
)
|
||||
|
||||
type AuthController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *AuthController) List() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
|
||||
var err error
|
||||
var count int64
|
||||
var auths []map[string]string
|
||||
if keyword != "" {
|
||||
count, err = models.AuthModel.CountAuthsByKeyword(keyword)
|
||||
auths, err = models.AuthModel.GetAuthsByKeywordAndLimit(keyword, limit, number)
|
||||
} else {
|
||||
count, err = models.AuthModel.CountAuths()
|
||||
auths, err = models.AuthModel.GetAuthsByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取登录认证列表失败: " + err.Error())
|
||||
this.ViewError("获取登录认证列表失败", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["auths"] = auths
|
||||
this.Data["keyword"] = keyword
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("auth/list", "auth")
|
||||
}
|
||||
|
||||
func (this *AuthController) Add() {
|
||||
this.viewLayout("auth/form", "auth")
|
||||
}
|
||||
|
||||
func (this *AuthController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/auth/list")
|
||||
}
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
authUrl := strings.TrimSpace(this.GetString("url", ""))
|
||||
usernamePrefix := strings.TrimSpace(this.GetString("username_prefix", ""))
|
||||
extData := strings.TrimSpace(this.GetString("ext_data", ""))
|
||||
|
||||
v := validation.Validation{}
|
||||
if name == "" {
|
||||
this.jsonError("登录认证名称不能为空!")
|
||||
}
|
||||
if usernamePrefix == "" {
|
||||
this.jsonError("用户名前缀不能为空!")
|
||||
}
|
||||
if !v.AlphaNumeric(usernamePrefix, "username_prefix").Ok {
|
||||
this.jsonError("用户名前缀格式不正确!")
|
||||
}
|
||||
if authUrl == "" {
|
||||
this.jsonError("认证URL不能为空!")
|
||||
}
|
||||
u, err := url.Parse(authUrl)
|
||||
if err != nil || u == nil {
|
||||
this.jsonError("认证 URL 解析错误!")
|
||||
return
|
||||
}
|
||||
if !services.AuthLogin.UrlIsSupport(u.Scheme) {
|
||||
this.jsonError("认证 URL 协议不支持!")
|
||||
}
|
||||
|
||||
ok, err := models.AuthModel.HasAuthName(name)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加登录认证失败:" + err.Error())
|
||||
this.jsonError("添加登录认证失败!")
|
||||
}
|
||||
if ok {
|
||||
this.jsonError("登录认证名称已经存在!")
|
||||
}
|
||||
|
||||
ok, err = models.AuthModel.HasAuthUsernamePrefix(usernamePrefix)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加登录认证失败:" + err.Error())
|
||||
this.jsonError("添加登录认证失败!")
|
||||
}
|
||||
if ok {
|
||||
this.jsonError("用户名前缀已经存在!")
|
||||
}
|
||||
|
||||
authId, err := models.AuthModel.Insert(map[string]interface{}{
|
||||
"name": name,
|
||||
"url": authUrl,
|
||||
"username_prefix": usernamePrefix,
|
||||
"ext_data": extData,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("添加登录认证失败:" + err.Error())
|
||||
this.jsonError("添加登录认证失败")
|
||||
}
|
||||
this.InfoLog("添加登录认证 " + utils.Convert.IntToString(authId, 10) + " 成功")
|
||||
this.jsonSuccess("添加登录认证成功", nil, "/system/auth/list")
|
||||
}
|
||||
|
||||
func (this *AuthController) Edit() {
|
||||
|
||||
authId := this.GetString("login_auth_id", "")
|
||||
if authId == "" {
|
||||
this.ViewError("登录认证不存在", "/system/auth/list")
|
||||
}
|
||||
|
||||
auth, err := models.AuthModel.GetAuthByAuthId(authId)
|
||||
if err != nil {
|
||||
this.ViewError("登录认证不存在", "/system/auth/list")
|
||||
}
|
||||
|
||||
this.Data["auth"] = auth
|
||||
this.viewLayout("auth/form", "auth")
|
||||
}
|
||||
|
||||
func (this *AuthController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/auth/list")
|
||||
}
|
||||
authId := this.GetString("login_auth_id", "")
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
authUrl := strings.TrimSpace(this.GetString("url", ""))
|
||||
usernamePrefix := strings.TrimSpace(this.GetString("username_prefix", ""))
|
||||
extData := strings.TrimSpace(this.GetString("ext_data", ""))
|
||||
|
||||
v := validation.Validation{}
|
||||
if authId == "" {
|
||||
this.jsonError("登录认证不存在!")
|
||||
}
|
||||
if name == "" {
|
||||
this.jsonError("登录认证名称不能为空!")
|
||||
}
|
||||
if usernamePrefix == "" {
|
||||
this.jsonError("用户名前缀不能为空!")
|
||||
}
|
||||
if !v.AlphaNumeric(usernamePrefix, "username_prefix").Ok {
|
||||
this.jsonError("用户名前缀格式不正确!")
|
||||
}
|
||||
if authUrl == "" {
|
||||
this.jsonError("认证URL不能为空!")
|
||||
}
|
||||
u, err := url.Parse(authUrl)
|
||||
if err != nil || u == nil {
|
||||
this.jsonError("认证 URL 解析错误!")
|
||||
return
|
||||
}
|
||||
if !services.AuthLogin.UrlIsSupport(u.Scheme) {
|
||||
this.jsonError("认证 URL 协议不支持!")
|
||||
}
|
||||
|
||||
auth, err := models.AuthModel.GetAuthByAuthId(authId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改登录认证 " + authId + " 失败: " + err.Error())
|
||||
this.jsonError("修改登录认证失败!")
|
||||
}
|
||||
if len(auth) == 0 {
|
||||
this.jsonError("登录认证不存在!")
|
||||
}
|
||||
|
||||
ok, _ := models.AuthModel.HasSameName(authId, name)
|
||||
if ok {
|
||||
this.jsonError("登录认证名称已经存在!")
|
||||
}
|
||||
ok, _ = models.AuthModel.HasSameUsernamePrefix(authId, usernamePrefix)
|
||||
if ok {
|
||||
this.jsonError("用户名前缀已经存在!")
|
||||
}
|
||||
|
||||
_, err = models.AuthModel.Update(authId, map[string]interface{}{
|
||||
"name": name,
|
||||
"url": authUrl,
|
||||
"username_prefix": usernamePrefix,
|
||||
"ext_data": extData,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("修改登录认证 " + authId + " 失败:" + err.Error())
|
||||
this.jsonError("修改登录认证失败")
|
||||
}
|
||||
this.InfoLog("修改登录认证 " + authId + " 成功")
|
||||
this.jsonSuccess("修改登录认证成功", nil, "/system/auth/list")
|
||||
}
|
||||
|
||||
func (this *AuthController) Delete() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/auth/list")
|
||||
}
|
||||
authId := this.GetString("login_auth_id", "")
|
||||
if authId == "" {
|
||||
this.jsonError("没有选择登录认证!")
|
||||
}
|
||||
|
||||
auth, err := models.AuthModel.GetAuthByAuthId(authId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除登录认证 " + authId + " 失败: " + err.Error())
|
||||
this.jsonError("删除登录认证失败")
|
||||
}
|
||||
if len(auth) == 0 {
|
||||
this.jsonError("登录认证不存在")
|
||||
}
|
||||
|
||||
err = models.AuthModel.Delete(authId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除登录认证 " + authId + " 失败: " + err.Error())
|
||||
this.jsonError("删除登录认证失败")
|
||||
}
|
||||
|
||||
this.InfoLog("删除登录认证 " + authId + " 成功")
|
||||
this.jsonSuccess("删除登录认证成功", nil, "/system/auth/list")
|
||||
}
|
||||
|
||||
func (this *AuthController) Used() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/auth/list")
|
||||
}
|
||||
authId := this.GetString("login_auth_id", "")
|
||||
if authId == "" {
|
||||
this.jsonError("没有选择登录认证!")
|
||||
}
|
||||
|
||||
auth, err := models.AuthModel.GetAuthByAuthId(authId)
|
||||
if err != nil {
|
||||
this.ErrorLog("登录认证 " + authId + " 启用失败: " + err.Error())
|
||||
this.jsonError("登录认证启用失败")
|
||||
}
|
||||
if len(auth) == 0 {
|
||||
this.jsonError("登录认证不存在")
|
||||
}
|
||||
_, err = models.AuthModel.SetAuthUsed(authId)
|
||||
if err != nil {
|
||||
this.ErrorLog("登录认证 " + authId + " 启用失败: " + err.Error())
|
||||
this.jsonError("登录认证启用失败")
|
||||
}
|
||||
|
||||
this.InfoLog("启用登录认证 " + authId + " 成功")
|
||||
this.jsonSuccess("启用登录认证成功", nil, "/system/auth/list")
|
||||
}
|
||||
|
||||
func (this *AuthController) Doc() {
|
||||
this.viewLayout("auth/doc", "auth")
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/controllers"
|
||||
)
|
||||
|
||||
type BaseController struct {
|
||||
controllers.TemplateController
|
||||
}
|
||||
|
||||
// view layout
|
||||
func (this *BaseController) viewLayout(viewName, layout string) {
|
||||
viewName = "system/" + viewName
|
||||
layout = "system/layouts/" + layout
|
||||
this.ViewLayout(viewName, layout)
|
||||
}
|
||||
|
||||
// return json success
|
||||
func (this *BaseController) jsonSuccess(message interface{}, data ...interface{}) {
|
||||
this.JsonSuccess(message, data...)
|
||||
}
|
||||
|
||||
// return json error
|
||||
func (this *BaseController) jsonError(message interface{}, data ...interface{}) {
|
||||
this.JsonError(message, data...)
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app/work"
|
||||
"strings"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
)
|
||||
|
||||
type ConfigController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *ConfigController) Global() {
|
||||
|
||||
configs, err := models.ConfigModel.GetConfigs()
|
||||
if err != nil {
|
||||
this.ErrorLog("获取全局配置失败: " + err.Error())
|
||||
this.ViewError("邮件服务器不存在", "/system/main/index")
|
||||
}
|
||||
|
||||
var configValue = map[string]string{}
|
||||
for _, config := range configs {
|
||||
if config["key"] == models.ConfigKeyAutoFollowdoc && config["value"] != "1" {
|
||||
config["value"] = "0"
|
||||
}
|
||||
if config["key"] == models.ConfigKeySendEmail && config["value"] != "1" {
|
||||
config["value"] = "0"
|
||||
}
|
||||
if config["key"] == models.ConfigKeyAuthLogin && config["value"] != "1" {
|
||||
config["value"] = "0"
|
||||
}
|
||||
configValue[config["key"]] = config["value"]
|
||||
}
|
||||
|
||||
this.Data["configValue"] = configValue
|
||||
this.viewLayout("config/form", "config")
|
||||
}
|
||||
|
||||
func (this *ConfigController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/email/list")
|
||||
}
|
||||
mainTitle := this.GetString(models.ConfigKeyMainTitle, "")
|
||||
mainDescription := strings.TrimSpace(this.GetString(models.ConfigKeyMainDescription, ""))
|
||||
autoFollowDocOpen := strings.TrimSpace(this.GetString(models.ConfigKeyAutoFollowdoc, "0"))
|
||||
sendEmailOpen := strings.TrimSpace(this.GetString(models.ConfigKeySendEmail, "0"))
|
||||
ssoOpen := strings.TrimSpace(this.GetString(models.ConfigKeyAuthLogin, "0"))
|
||||
fulltextSearch := strings.TrimSpace(this.GetString(models.ConfigKeyFulltextSearch, "0"))
|
||||
docSearchTimer := strings.TrimSpace(this.GetString(models.ConfigKeyDocSearchTimer, "3600"))
|
||||
systemName := strings.TrimSpace(this.GetString(models.ConfigKeySystemName, "Markdown Mini Wiki"))
|
||||
|
||||
if sendEmailOpen == "1" {
|
||||
email, err := models.EmailModel.GetUsedEmail()
|
||||
if err != nil {
|
||||
this.ErrorLog("获取可用的邮箱配置失败: " + err.Error())
|
||||
this.jsonError("配置出错!")
|
||||
}
|
||||
if len(email) == 0 {
|
||||
this.jsonError("开启邮件通知必须先启用一个邮件服务器配置!")
|
||||
}
|
||||
}
|
||||
|
||||
if ssoOpen == "1" {
|
||||
auth, err := models.AuthModel.GetUsedAuth()
|
||||
if err != nil {
|
||||
this.ErrorLog("获取可用的登录认证失败: " + err.Error())
|
||||
this.jsonError("配置出错!")
|
||||
}
|
||||
if len(auth) == 0 {
|
||||
this.jsonError("开启统一登录必须先添加并启用一个登录认证!")
|
||||
}
|
||||
}
|
||||
updateValues := map[string]string{
|
||||
models.ConfigKeyMainTitle: mainTitle,
|
||||
models.ConfigKeyMainDescription: mainDescription,
|
||||
models.ConfigKeyAutoFollowdoc: autoFollowDocOpen,
|
||||
models.ConfigKeySendEmail: sendEmailOpen,
|
||||
models.ConfigKeyAuthLogin: ssoOpen,
|
||||
models.ConfigKeyFulltextSearch: fulltextSearch,
|
||||
models.ConfigKeyDocSearchTimer: docSearchTimer,
|
||||
models.ConfigKeySystemName: systemName,
|
||||
}
|
||||
// 有修改再更新
|
||||
configs, err := models.ConfigModel.GetConfigs()
|
||||
if err != nil {
|
||||
this.ErrorLog("获取配置信息失败: " + err.Error())
|
||||
this.jsonError("获取配置出错!")
|
||||
}
|
||||
updateKeys := make(map[string]string)
|
||||
for _, config := range configs {
|
||||
if len(config) == 0 {
|
||||
continue
|
||||
}
|
||||
name := config["name"]
|
||||
key := config["key"]
|
||||
value := config["value"]
|
||||
updateValue, ok := updateValues[key]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// 没有修改不更新
|
||||
if value == updateValue {
|
||||
continue
|
||||
}
|
||||
_, err := models.ConfigModel.UpdateByKey(key, updateValue)
|
||||
if err != nil {
|
||||
this.ErrorLog(fmt.Sprintf("修改配置 %s 失败: %s", name, err.Error()))
|
||||
this.jsonError(fmt.Sprintf("修改配置 %s 失败", name))
|
||||
}
|
||||
updateKeys[key] = updateValue
|
||||
}
|
||||
|
||||
// 更新后的回调
|
||||
//this.configUpdateCallback(updateKeys)
|
||||
this.InfoLog("修改全局配置成功")
|
||||
this.jsonSuccess("修改全局配置成功", nil, "/system/config/global")
|
||||
}
|
||||
|
||||
// 配置更新通知回调
|
||||
func (this *ConfigController) configUpdateCallback(updateKeyMaps map[string]string) {
|
||||
fullTextOpenUpdate := false
|
||||
updateValue, ok := updateKeyMaps[models.ConfigKeyFulltextSearch]
|
||||
if ok {
|
||||
fullTextOpenUpdate = true
|
||||
}
|
||||
docSearchTimerUpdate := false
|
||||
_, ok = updateKeyMaps[models.ConfigKeyDocSearchTimer]
|
||||
if ok {
|
||||
docSearchTimerUpdate = true
|
||||
}
|
||||
// 索引时间更新,开关没有更新,重启一下 worker
|
||||
if docSearchTimerUpdate && !fullTextOpenUpdate {
|
||||
work.DocSearchWorker.Restart()
|
||||
return
|
||||
}
|
||||
// 开关更新
|
||||
if fullTextOpenUpdate {
|
||||
if updateValue == "1" {
|
||||
work.DocSearchWorker.Start()
|
||||
return
|
||||
}
|
||||
work.DocSearchWorker.Stop()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
|
||||
"github.com/astaxie/beego/validation"
|
||||
)
|
||||
|
||||
type ContactController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *ContactController) Add() {
|
||||
this.viewLayout("contact/form", "contact")
|
||||
}
|
||||
|
||||
func (this *ContactController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/contact/list")
|
||||
}
|
||||
name := strings.Trim(this.GetString("name", ""), "")
|
||||
mobile := strings.Trim(this.GetString("mobile", ""), "")
|
||||
position := strings.Trim(this.GetString("position", ""), "")
|
||||
email := strings.Trim(this.GetString("email", ""), "")
|
||||
|
||||
v := validation.Validation{}
|
||||
if name == "" {
|
||||
this.jsonError("联系人姓名不能为空!")
|
||||
}
|
||||
if email == "" {
|
||||
this.jsonError("邮箱不能为空!")
|
||||
}
|
||||
if !v.Email(email, "email").Ok {
|
||||
this.jsonError("邮箱格式不正确!")
|
||||
}
|
||||
|
||||
contact := map[string]interface{}{
|
||||
"name": name,
|
||||
"mobile": mobile,
|
||||
"position": position,
|
||||
"email": email,
|
||||
}
|
||||
|
||||
contactId, err := models.ContactModel.Insert(contact)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加联系人失败:" + err.Error())
|
||||
this.jsonError("添加联系人失败")
|
||||
}
|
||||
this.InfoLog("添加联系人 " + utils.Convert.IntToString(contactId, 10) + " 成功")
|
||||
this.jsonSuccess("添加联系人成功", nil, "/system/contact/list")
|
||||
}
|
||||
|
||||
func (this *ContactController) List() {
|
||||
|
||||
var err error
|
||||
var contacts []map[string]string
|
||||
contacts, err = models.ContactModel.GetAllContact()
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("获取联系人列表出错: " + err.Error())
|
||||
this.ViewError("获取联系人列表出错", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["contacts"] = contacts
|
||||
this.viewLayout("contact/list", "contact")
|
||||
}
|
||||
|
||||
func (this *ContactController) Edit() {
|
||||
|
||||
contactId := this.GetString("contact_id", "")
|
||||
if contactId == "" {
|
||||
this.ViewError("联系人不存在", "/system/contact/list")
|
||||
}
|
||||
|
||||
contact, err := models.ContactModel.GetContactByContactId(contactId)
|
||||
if err != nil {
|
||||
this.ViewError("联系人不存在", "/system/contact/list")
|
||||
}
|
||||
|
||||
this.Data["contact"] = contact
|
||||
this.viewLayout("contact/form", "contact")
|
||||
}
|
||||
|
||||
func (this *ContactController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/contact/list")
|
||||
}
|
||||
contactId := strings.Trim(this.GetString("contact_id", ""), "")
|
||||
name := strings.Trim(this.GetString("name", ""), "")
|
||||
mobile := strings.Trim(this.GetString("mobile", ""), "")
|
||||
position := strings.Trim(this.GetString("position", ""), "")
|
||||
email := strings.Trim(this.GetString("email", ""), "")
|
||||
|
||||
v := validation.Validation{}
|
||||
if contactId == "" {
|
||||
this.jsonError("参数错误!")
|
||||
}
|
||||
if name == "" {
|
||||
this.jsonError("联系人姓名不能为空!")
|
||||
}
|
||||
if position == "" {
|
||||
this.jsonError("职位不能为空!")
|
||||
}
|
||||
if mobile == "" {
|
||||
this.jsonError("联系电话不能为空!")
|
||||
}
|
||||
if !v.Phone(mobile, "mobile").Ok {
|
||||
this.jsonError("联系电话格式不正确!")
|
||||
}
|
||||
if email == "" {
|
||||
this.jsonError("邮箱不能为空!")
|
||||
}
|
||||
if !v.Email(email, "email").Ok {
|
||||
this.jsonError("邮箱格式不正确!")
|
||||
}
|
||||
|
||||
contact := map[string]interface{}{
|
||||
"name": name,
|
||||
"mobile": mobile,
|
||||
"position": position,
|
||||
"email": email,
|
||||
"update_time": time.Now().Unix(),
|
||||
}
|
||||
_, err := models.ContactModel.UpdateByContactId(contact, contactId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改联系人 " + contactId + " 失败:" + err.Error())
|
||||
this.jsonError("修改联系人失败")
|
||||
}
|
||||
this.InfoLog("修改联系人 " + contactId + " 成功")
|
||||
this.jsonSuccess("修改联系人成功", nil, "/system/contact/list")
|
||||
}
|
||||
|
||||
func (this *ContactController) Delete() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/contact/list")
|
||||
}
|
||||
contactId := this.GetString("contact_id", "")
|
||||
if contactId == "" {
|
||||
this.jsonError("没有选择联系人!")
|
||||
}
|
||||
|
||||
contact, err := models.ContactModel.GetContactByContactId(contactId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除联系人 " + contactId + " 失败: " + err.Error())
|
||||
this.jsonError("删除联系人失败")
|
||||
}
|
||||
if len(contact) == 0 {
|
||||
this.jsonError("联系人不存在")
|
||||
}
|
||||
|
||||
_, err = models.ContactModel.DeleteByContactId(contactId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除联系人 " + contactId + " 失败: " + err.Error())
|
||||
this.jsonError("删除联系人失败")
|
||||
}
|
||||
|
||||
this.InfoLog("删除联系人 " + contactId + " 成功")
|
||||
this.jsonSuccess("删除联系人成功", nil, "/system/contact/list")
|
||||
}
|
||||
|
||||
// 从用户导入联系人
|
||||
func (this *ContactController) Import() {
|
||||
|
||||
keywords := map[string]string{}
|
||||
page, _ := this.GetInt("page", 1)
|
||||
username := strings.TrimSpace(this.GetString("username", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
if username != "" {
|
||||
keywords["username"] = username
|
||||
}
|
||||
limit := (page - 1) * number
|
||||
|
||||
var err error
|
||||
var count int64
|
||||
var users []map[string]string
|
||||
if len(keywords) != 0 {
|
||||
count, err = models.UserModel.CountUsersByKeywords(keywords)
|
||||
users, err = models.UserModel.GetUsersByKeywordsAndLimit(keywords, limit, number)
|
||||
} else {
|
||||
count, err = models.UserModel.CountUsers()
|
||||
users, err = models.UserModel.GetUsersByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户列表失败: " + err.Error())
|
||||
this.ViewError("获取用户列表失败", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["users"] = users
|
||||
this.Data["username"] = username
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("contact/import", "contact")
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/go-ozzo/ozzo-validation"
|
||||
"github.com/go-ozzo/ozzo-validation/is"
|
||||
)
|
||||
|
||||
type EmailController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *EmailController) List() {
|
||||
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
var err error
|
||||
var emails []map[string]string
|
||||
if keyword != "" {
|
||||
emails, err = models.EmailModel.GetEmailsByLikeName(keyword)
|
||||
} else {
|
||||
emails, err = models.EmailModel.GetEmails()
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取邮件服务器列表失败: " + err.Error())
|
||||
this.ViewError("获取邮件服务器列表失败", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["emails"] = emails
|
||||
this.Data["keyword"] = keyword
|
||||
this.viewLayout("email/list", "email")
|
||||
}
|
||||
|
||||
func (this *EmailController) Add() {
|
||||
this.viewLayout("email/form", "email")
|
||||
}
|
||||
|
||||
func (this *EmailController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/email/list")
|
||||
}
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
senderAddress := strings.TrimSpace(this.GetString("sender_address", ""))
|
||||
senderName := strings.TrimSpace(this.GetString("sender_name", ""))
|
||||
senderTitlePrefix := strings.TrimSpace(this.GetString("sender_title_prefix", ""))
|
||||
host := strings.TrimSpace(this.GetString("host", ""))
|
||||
port := strings.TrimSpace(this.GetString("port", "25"))
|
||||
username := strings.TrimSpace(this.GetString("username", ""))
|
||||
password := strings.TrimSpace(this.GetString("password", ""))
|
||||
isSsl := strings.TrimSpace(this.GetString("is_ssl", "0"))
|
||||
|
||||
if name == "" {
|
||||
this.jsonError("邮件服务器名称不能为空!")
|
||||
}
|
||||
if host == "" {
|
||||
this.jsonError("邮件服务器主机不能为空!")
|
||||
}
|
||||
if validation.Validate(host, is.Host) != nil {
|
||||
this.jsonError("邮件服务器主机格式不正确!")
|
||||
}
|
||||
if port == "" {
|
||||
this.jsonError("邮件服务器端口不能为空!")
|
||||
}
|
||||
if validation.Validate(port, is.Port) != nil {
|
||||
this.jsonError("邮件服务器端口格式不正确!")
|
||||
}
|
||||
if senderAddress == "" {
|
||||
this.jsonError("发件人邮箱不能为空!")
|
||||
}
|
||||
if username == "" {
|
||||
this.jsonError("发件用户名不能为空!")
|
||||
}
|
||||
if password == "" {
|
||||
this.jsonError("发件人密码不能为空!")
|
||||
}
|
||||
|
||||
ok, err := models.EmailModel.HasEmailName(name)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加邮件服务器失败:" + err.Error())
|
||||
this.jsonError("添加邮件服务器失败!")
|
||||
}
|
||||
if ok {
|
||||
this.jsonError("邮件服务器名称已经存在!")
|
||||
}
|
||||
|
||||
emailId, err := models.EmailModel.Insert(map[string]interface{}{
|
||||
"name": name,
|
||||
"sender_address": senderAddress,
|
||||
"sender_name": senderName,
|
||||
"sender_title_prefix": senderTitlePrefix,
|
||||
"host": host,
|
||||
"port": port,
|
||||
"username": username,
|
||||
"password": password,
|
||||
"is_ssl": isSsl,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("添加邮件服务器失败:" + err.Error())
|
||||
this.jsonError("添加邮件服务器失败")
|
||||
}
|
||||
this.InfoLog("添加邮件服务器 " + utils.Convert.IntToString(emailId, 10) + " 成功")
|
||||
this.jsonSuccess("添加邮件服务器成功", nil, "/system/email/list")
|
||||
}
|
||||
|
||||
func (this *EmailController) Edit() {
|
||||
|
||||
emailId := this.GetString("email_id", "")
|
||||
if emailId == "" {
|
||||
this.ViewError("邮件服务器不存在", "/system/email/list")
|
||||
}
|
||||
|
||||
email, err := models.EmailModel.GetEmailByEmailId(emailId)
|
||||
if err != nil {
|
||||
this.ViewError("邮件服务器不存在", "/system/email/list")
|
||||
}
|
||||
|
||||
this.Data["email"] = email
|
||||
this.viewLayout("email/form", "email")
|
||||
}
|
||||
|
||||
func (this *EmailController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/email/list")
|
||||
}
|
||||
emailId := this.GetString("email_id", "")
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
senderAddress := strings.TrimSpace(this.GetString("sender_address", ""))
|
||||
senderName := strings.TrimSpace(this.GetString("sender_name", ""))
|
||||
senderTitlePrefix := strings.TrimSpace(this.GetString("sender_title_prefix", ""))
|
||||
host := strings.TrimSpace(this.GetString("host", ""))
|
||||
port := strings.TrimSpace(this.GetString("port", ""))
|
||||
username := strings.TrimSpace(this.GetString("username", ""))
|
||||
password := strings.TrimSpace(this.GetString("password", ""))
|
||||
isSsl := strings.TrimSpace(this.GetString("is_ssl", "0"))
|
||||
|
||||
if emailId == "" {
|
||||
this.jsonError("邮件服务器不存在!")
|
||||
}
|
||||
if name == "" {
|
||||
this.jsonError("邮件服务器名称不能为空!")
|
||||
}
|
||||
if host == "" {
|
||||
this.jsonError("邮件服务器主机不能为空!")
|
||||
}
|
||||
if validation.Validate(host, is.Host) != nil {
|
||||
this.jsonError("邮件服务器主机格式不正确!")
|
||||
}
|
||||
if port == "" {
|
||||
this.jsonError("邮件服务器端口不能为空!")
|
||||
}
|
||||
if validation.Validate(port, is.Port) != nil {
|
||||
this.jsonError("邮件服务器端口格式不正确!")
|
||||
}
|
||||
if senderAddress == "" {
|
||||
this.jsonError("发件人邮箱不能为空!")
|
||||
}
|
||||
if username == "" {
|
||||
this.jsonError("发件用户名不能为空!")
|
||||
}
|
||||
if password == "" {
|
||||
this.jsonError("发件人密码不能为空!")
|
||||
}
|
||||
|
||||
email, err := models.EmailModel.GetEmailByEmailId(emailId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改邮件服务器 " + emailId + " 失败: " + err.Error())
|
||||
this.jsonError("修改邮件服务器失败!")
|
||||
}
|
||||
if len(email) == 0 {
|
||||
this.jsonError("邮件服务器不存在!")
|
||||
}
|
||||
|
||||
ok, _ := models.EmailModel.HasSameName(emailId, name)
|
||||
if ok {
|
||||
this.jsonError("邮件服务器名称已经存在!")
|
||||
}
|
||||
_, err = models.EmailModel.Update(emailId, map[string]interface{}{
|
||||
"name": name,
|
||||
"sender_address": senderAddress,
|
||||
"sender_name": senderName,
|
||||
"sender_title_prefix": senderTitlePrefix,
|
||||
"host": host,
|
||||
"port": port,
|
||||
"username": username,
|
||||
"password": password,
|
||||
"is_ssl": isSsl,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("修改邮件服务器 " + emailId + " 失败:" + err.Error())
|
||||
this.jsonError("修改邮件服务器失败")
|
||||
}
|
||||
this.InfoLog("修改邮件服务器 " + emailId + " 成功")
|
||||
this.jsonSuccess("修改邮件服务器成功", nil, "/system/email/list")
|
||||
}
|
||||
|
||||
func (this *EmailController) Used() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/email/list")
|
||||
}
|
||||
emailId := this.GetString("email_id", "")
|
||||
if emailId == "" {
|
||||
this.jsonError("没有选择邮件服务器!")
|
||||
}
|
||||
|
||||
email, err := models.EmailModel.GetEmailByEmailId(emailId)
|
||||
if err != nil {
|
||||
this.ErrorLog("邮件服务器 " + emailId + " 启用失败: " + err.Error())
|
||||
this.jsonError("邮件服务器启用失败")
|
||||
}
|
||||
if len(email) == 0 {
|
||||
this.jsonError("邮件服务器不存在")
|
||||
}
|
||||
_, err = models.EmailModel.SetEmailUsed(emailId)
|
||||
if err != nil {
|
||||
this.ErrorLog("邮件服务器 " + emailId + " 启用失败: " + err.Error())
|
||||
this.jsonError("邮件服务器启用失败")
|
||||
}
|
||||
|
||||
this.InfoLog("启用邮件服务器 " + emailId + " 成功")
|
||||
this.jsonSuccess("启用邮件服务器成功", nil, "/system/email/list")
|
||||
}
|
||||
|
||||
func (this *EmailController) Delete() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/email/list")
|
||||
}
|
||||
emailId := this.GetString("email_id", "")
|
||||
if emailId == "" {
|
||||
this.jsonError("没有选择邮件服务器!")
|
||||
}
|
||||
|
||||
email, err := models.EmailModel.GetEmailByEmailId(emailId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除邮件服务器 " + emailId + " 失败: " + err.Error())
|
||||
this.jsonError("删除邮件服务器失败")
|
||||
}
|
||||
if len(email) == 0 {
|
||||
this.jsonError("邮件服务器不存在")
|
||||
}
|
||||
err = models.EmailModel.Delete(emailId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除邮件服务器 " + emailId + " 失败: " + err.Error())
|
||||
this.jsonError("删除邮件服务器失败")
|
||||
}
|
||||
|
||||
this.InfoLog("删除邮件服务器 " + emailId + " 成功")
|
||||
this.jsonSuccess("删除邮件服务器成功", nil, "/system/email/list")
|
||||
}
|
||||
|
||||
func (this *EmailController) Test() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/email/list")
|
||||
}
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
senderAddress := strings.TrimSpace(this.GetString("sender_address", ""))
|
||||
senderName := strings.TrimSpace(this.GetString("sender_name", ""))
|
||||
senderTitlePrefix := strings.TrimSpace(this.GetString("sender_title_prefix", ""))
|
||||
host := strings.TrimSpace(this.GetString("host", ""))
|
||||
port := strings.TrimSpace(this.GetString("port", "25"))
|
||||
username := strings.TrimSpace(this.GetString("username", ""))
|
||||
password := strings.TrimSpace(this.GetString("password", ""))
|
||||
isSsl := strings.TrimSpace(this.GetString("is_ssl", "0"))
|
||||
emails := strings.TrimSpace(this.GetString("emails", ""))
|
||||
|
||||
if name == "" {
|
||||
this.jsonError("邮件服务器名称不能为空!")
|
||||
}
|
||||
if host == "" {
|
||||
this.jsonError("邮件服务器主机不能为空!")
|
||||
}
|
||||
if validation.Validate(host, is.Host) != nil {
|
||||
this.jsonError("邮件服务器主机格式不正确!")
|
||||
}
|
||||
if port == "" {
|
||||
this.jsonError("邮件服务器端口不能为空!")
|
||||
}
|
||||
if validation.Validate(port, is.Port) != nil {
|
||||
this.jsonError("邮件服务器端口格式不正确!")
|
||||
}
|
||||
if senderAddress == "" {
|
||||
this.jsonError("发件人邮箱不能为空!")
|
||||
}
|
||||
if username == "" {
|
||||
this.jsonError("发件用户名不能为空!")
|
||||
}
|
||||
if password == "" {
|
||||
this.jsonError("发件人密码不能为空!")
|
||||
}
|
||||
if emails == "" {
|
||||
this.jsonError("要发送的邮件地址不能为空!")
|
||||
}
|
||||
|
||||
emailConfig := map[string]string{
|
||||
"sender_address": senderAddress,
|
||||
"port": port,
|
||||
"password": password,
|
||||
"host": host,
|
||||
"sender_name": senderName,
|
||||
"username": username,
|
||||
"sender_title_prefix": senderTitlePrefix,
|
||||
"is_ssl": isSsl,
|
||||
}
|
||||
|
||||
to := strings.Split(emails, ";")
|
||||
documentValue := map[string]string{
|
||||
"name": "MM-Wiki测试邮件",
|
||||
"username": this.User["username"],
|
||||
"update_time": fmt.Sprintf("%d", time.Now().Unix()),
|
||||
"comment": "",
|
||||
"document_url": "",
|
||||
"content": "欢迎使用 <a href='https://github.com/phachon/mm-wiki'>MM-Wiki</a>,这是一封测试邮件,请勿回复!",
|
||||
}
|
||||
|
||||
emailTemplate := beego.BConfig.WebConfig.ViewsPath + "/system/email/template_test.html"
|
||||
body, err := utils.Email.MakeDocumentHtmlBody(documentValue, emailTemplate)
|
||||
if err != nil {
|
||||
this.ErrorLog("发送测试邮件失败:" + err.Error())
|
||||
this.jsonError("发送测试邮件失败!")
|
||||
}
|
||||
// start send email
|
||||
err = utils.Email.Send(emailConfig, to, "测试邮件", body)
|
||||
if err != nil {
|
||||
this.ErrorLog("发送测试邮件失败:" + err.Error())
|
||||
this.jsonError("发送测试邮件失败!")
|
||||
}
|
||||
|
||||
this.jsonSuccess("发送测试邮件成功", nil)
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
|
||||
valid "github.com/go-ozzo/ozzo-validation"
|
||||
"github.com/go-ozzo/ozzo-validation/is"
|
||||
)
|
||||
|
||||
type LinkController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *LinkController) Add() {
|
||||
this.viewLayout("link/form", "link")
|
||||
}
|
||||
|
||||
func (this *LinkController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/link/list")
|
||||
}
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
url := strings.TrimSpace(this.GetString("url", ""))
|
||||
sequence := strings.TrimSpace(this.GetString("sequence", "0"))
|
||||
if name == "" {
|
||||
this.jsonError("链接名称不能为空!")
|
||||
}
|
||||
if url == "" {
|
||||
this.jsonError("链接地址不能为空!")
|
||||
}
|
||||
if valid.Validate(url, is.URL) != nil {
|
||||
this.jsonError("链接地址格式不正确!")
|
||||
}
|
||||
ok, err := models.LinkModel.HasLinkName(name)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加链接失败:" + err.Error())
|
||||
this.jsonError("添加链接失败!")
|
||||
}
|
||||
if ok {
|
||||
this.jsonError("链接名已经存在!")
|
||||
}
|
||||
|
||||
linkId, err := models.LinkModel.Insert(map[string]interface{}{
|
||||
"name": name,
|
||||
"url": url,
|
||||
"sequence": sequence,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("添加链接失败:" + err.Error())
|
||||
this.jsonError("添加链接失败")
|
||||
}
|
||||
this.InfoLog("添加链接 " + utils.Convert.IntToString(linkId, 10) + " 成功")
|
||||
this.jsonSuccess("添加链接成功", nil, "/system/link/list")
|
||||
}
|
||||
|
||||
func (this *LinkController) List() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
|
||||
var err error
|
||||
var count int64
|
||||
var links []map[string]string
|
||||
if keyword != "" {
|
||||
count, err = models.LinkModel.CountLinksByKeyword(keyword)
|
||||
links, err = models.LinkModel.GetLinksByKeywordAndLimit(keyword, limit, number)
|
||||
} else {
|
||||
count, err = models.LinkModel.CountLinks()
|
||||
links, err = models.LinkModel.GetLinksByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取链接列表失败: " + err.Error())
|
||||
this.ViewError("获取链接列表失败", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["links"] = links
|
||||
this.Data["keyword"] = keyword
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("link/list", "link")
|
||||
}
|
||||
|
||||
func (this *LinkController) Edit() {
|
||||
|
||||
linkId := this.GetString("link_id", "")
|
||||
if linkId == "" {
|
||||
this.ViewError("链接不存在", "/system/link/list")
|
||||
}
|
||||
|
||||
link, err := models.LinkModel.GetLinkByLinkId(linkId)
|
||||
if err != nil {
|
||||
this.ViewError("链接不存在", "/system/link/list")
|
||||
}
|
||||
|
||||
this.Data["link"] = link
|
||||
this.viewLayout("link/form", "link")
|
||||
}
|
||||
|
||||
func (this *LinkController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/link/list")
|
||||
}
|
||||
linkId := this.GetString("link_id", "")
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
url := strings.TrimSpace(this.GetString("url", ""))
|
||||
sequence := strings.TrimSpace(this.GetString("sequence", ""))
|
||||
|
||||
if linkId == "" {
|
||||
this.jsonError("链接不存在!")
|
||||
}
|
||||
if name == "" {
|
||||
this.jsonError("链接名称不能为空!")
|
||||
}
|
||||
if url == "" {
|
||||
this.jsonError("链接地址不能为空!")
|
||||
}
|
||||
if valid.Validate(url, is.URL) != nil {
|
||||
this.jsonError("链接地址格式不正确!")
|
||||
}
|
||||
|
||||
link, err := models.LinkModel.GetLinkByLinkId(linkId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改链接 " + linkId + " 失败: " + err.Error())
|
||||
this.jsonError("修改链接失败!")
|
||||
}
|
||||
if len(link) == 0 {
|
||||
this.jsonError("链接不存在!")
|
||||
}
|
||||
|
||||
ok, _ := models.LinkModel.HasSameName(linkId, name)
|
||||
if ok {
|
||||
this.jsonError("链接名已经存在!")
|
||||
}
|
||||
_, err = models.LinkModel.Update(linkId, map[string]interface{}{
|
||||
"name": name,
|
||||
"url": url,
|
||||
"sequence": sequence,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("修改链接 " + linkId + " 失败:" + err.Error())
|
||||
this.jsonError("修改链接失败")
|
||||
}
|
||||
this.InfoLog("修改链接 " + linkId + " 成功")
|
||||
this.jsonSuccess("修改链接成功", nil, "/system/link/list")
|
||||
}
|
||||
|
||||
func (this *LinkController) Delete() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/link/list")
|
||||
}
|
||||
linkId := this.GetString("link_id", "")
|
||||
if linkId == "" {
|
||||
this.jsonError("没有选择链接!")
|
||||
}
|
||||
|
||||
link, err := models.LinkModel.GetLinkByLinkId(linkId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除链接 " + linkId + " 失败: " + err.Error())
|
||||
this.jsonError("删除链接失败")
|
||||
}
|
||||
if len(link) == 0 {
|
||||
this.jsonError("链接不存在")
|
||||
}
|
||||
|
||||
err = models.LinkModel.Delete(linkId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除链接 " + linkId + " 失败: " + err.Error())
|
||||
this.jsonError("删除链接失败")
|
||||
}
|
||||
|
||||
this.InfoLog("删除链接 " + linkId + " 成功")
|
||||
this.jsonSuccess("删除链接成功", nil, "/system/link/list")
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LogController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *LogController) System() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
level := strings.TrimSpace(this.GetString("level", ""))
|
||||
message := strings.TrimSpace(this.GetString("message", ""))
|
||||
username := strings.TrimSpace(this.GetString("username", ""))
|
||||
|
||||
limit := (page - 1) * number
|
||||
var err error
|
||||
var count int64
|
||||
var logs []map[string]string
|
||||
if level != "" || message != "" || username != "" {
|
||||
count, err = models.LogModel.CountLogsByKeyword(level, message, username)
|
||||
logs, err = models.LogModel.GetLogsByKeywordAndLimit(level, message, username, limit, number)
|
||||
} else {
|
||||
count, err = models.LogModel.CountLogs()
|
||||
logs, err = models.LogModel.GetLogsByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("查找系统日志出错:" + err.Error())
|
||||
this.ViewError("查找系统日志出错", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["logs"] = logs
|
||||
this.Data["username"] = username
|
||||
this.Data["level"] = level
|
||||
this.Data["message"] = message
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("log/system", "log")
|
||||
}
|
||||
|
||||
func (this *LogController) Info() {
|
||||
|
||||
logId := this.GetString("log_id", "")
|
||||
if logId == "" {
|
||||
this.ViewError("日志不存在", "/system/log/system")
|
||||
}
|
||||
|
||||
log, err := models.LogModel.GetLogByLogId(logId)
|
||||
if err != nil {
|
||||
this.ViewError("日志不存在", "/system/log/system")
|
||||
}
|
||||
|
||||
this.Data["log"] = log
|
||||
this.viewLayout("log/info", "log")
|
||||
}
|
||||
|
||||
func (this *LogController) Document() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
userId := strings.TrimSpace(this.GetString("user_id", ""))
|
||||
|
||||
limit := (page - 1) * number
|
||||
var logDocuments = []map[string]string{}
|
||||
var err error
|
||||
var count int64
|
||||
if keyword != "" && userId != "" {
|
||||
logDocuments, err = models.LogDocumentModel.GetLogDocumentsByUserIdKeywordAndLimit(userId, keyword, limit, number)
|
||||
count, err = models.LogDocumentModel.CountLogDocumentsByUserIdAndKeyword(userId, keyword)
|
||||
} else if userId != "" {
|
||||
logDocuments, err = models.LogDocumentModel.GetLogDocumentsByUserIdAndLimit(userId, limit, number)
|
||||
count, err = models.LogDocumentModel.CountLogDocumentsByUserId(userId)
|
||||
} else if keyword != "" {
|
||||
logDocuments, err = models.LogDocumentModel.GetLogDocumentsByKeywordAndLimit(keyword, limit, number)
|
||||
count, err = models.LogDocumentModel.CountLogDocumentsByKeyword(userId)
|
||||
} else {
|
||||
logDocuments, err = models.LogDocumentModel.GetLogDocumentsByLimit(this.UserId, limit, number)
|
||||
count, err = models.LogDocumentModel.CountLogDocuments()
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("文档日志查找失败:" + err.Error())
|
||||
this.ViewError("文档日志查找失败!", "/system/main/index")
|
||||
}
|
||||
|
||||
userIds := []string{}
|
||||
docIds := []string{}
|
||||
for _, logDocument := range logDocuments {
|
||||
userIds = append(userIds, logDocument["user_id"])
|
||||
docIds = append(docIds, logDocument["document_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("文档日志查找失败:" + err.Error())
|
||||
this.ViewError("文档日志查找失败!", "/system/main/index")
|
||||
}
|
||||
docs, err := models.DocumentModel.GetAllDocumentsByDocumentIds(docIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("文档日志查找失败:" + err.Error())
|
||||
this.ViewError("文档日志查找失败!", "/system/main/index")
|
||||
}
|
||||
for _, logDocument := range logDocuments {
|
||||
logDocument["username"] = ""
|
||||
for _, user := range users {
|
||||
if logDocument["user_id"] == user["user_id"] {
|
||||
logDocument["username"] = user["username"]
|
||||
logDocument["given_name"] = user["given_name"]
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, doc := range docs {
|
||||
if logDocument["document_id"] == doc["document_id"] {
|
||||
logDocument["document_name"] = doc["name"]
|
||||
logDocument["document_type"] = doc["type"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
users, err = models.UserModel.GetUsers()
|
||||
if err != nil {
|
||||
this.ErrorLog("文档日志查找失败:" + err.Error())
|
||||
this.ViewError("文档日志查找失败!", "/system/main/index")
|
||||
}
|
||||
this.Data["logDocuments"] = logDocuments
|
||||
this.Data["keyword"] = keyword
|
||||
this.Data["userId"] = userId
|
||||
this.Data["users"] = users
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("log/document", "log")
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
)
|
||||
|
||||
type MainController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *MainController) Index() {
|
||||
|
||||
var err error
|
||||
var menus = []map[string]string{}
|
||||
var controllers = []map[string]string{}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(this.UserId)
|
||||
if err != nil {
|
||||
this.ViewError("查找用户失败!")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.ViewError("用户不存在!")
|
||||
}
|
||||
roleId := user["role_id"]
|
||||
|
||||
if roleId == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
menus, controllers, err = models.PrivilegeModel.GetTypePrivilegesByDisplay(models.Privilege_DisPlay_True)
|
||||
if err != nil {
|
||||
this.ViewError("查找用户权限失败!")
|
||||
}
|
||||
} else {
|
||||
rolePrivileges, err := models.RolePrivilegeModel.GetRolePrivilegesByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ViewError("查找用户权限出错")
|
||||
}
|
||||
var privilegeIds = []string{}
|
||||
for _, rolePrivilege := range rolePrivileges {
|
||||
privilegeIds = append(privilegeIds, rolePrivilege["privilege_id"])
|
||||
}
|
||||
menus, controllers, err = models.PrivilegeModel.GetTypePrivilegesByDisplayPrivilegeIds(models.Privilege_DisPlay_True, privilegeIds)
|
||||
if err != nil {
|
||||
this.ViewError("查找用户权限失败!")
|
||||
}
|
||||
}
|
||||
this.Data["menus"] = menus
|
||||
this.Data["controllers"] = controllers
|
||||
this.viewLayout("main/index", "main")
|
||||
}
|
||||
|
||||
func (this *MainController) Default() {
|
||||
|
||||
this.viewLayout("main/default", "default")
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PluginController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *PluginController) List() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
|
||||
var err error
|
||||
var count int64
|
||||
var plugins []map[string]string
|
||||
if keyword != "" {
|
||||
count, err = models.PluginModel.CountPluginsByKeyword(keyword)
|
||||
plugins, err = models.PluginModel.GetPluginsByKeywordAndLimit(keyword, limit, number)
|
||||
} else {
|
||||
count, err = models.PluginModel.CountPlugins()
|
||||
plugins, err = models.PluginModel.GetPluginsByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取插件列表失败: " + err.Error())
|
||||
this.ViewError("获取插件列表失败", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["plugins"] = plugins
|
||||
this.Data["keyword"] = keyword
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("plugin/list", "plugin")
|
||||
}
|
||||
|
||||
func (this *PluginController) Config() {
|
||||
|
||||
pluginId := this.GetString("plugin_id", "")
|
||||
if pluginId == "" {
|
||||
this.ViewError("参数错误", "/system/plugin/list")
|
||||
}
|
||||
|
||||
plugin, err := models.PluginModel.GetPluginByPluginId(pluginId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找插件错误:" + err.Error())
|
||||
this.ViewError("查找插件错误", "/system/plugin/list")
|
||||
}
|
||||
if len(plugin) == 0 {
|
||||
this.ViewError("插件不存在", "/system/plugin/list")
|
||||
}
|
||||
pluginKey, ok := plugin["plugin_key"]
|
||||
if !ok || pluginKey == "" {
|
||||
this.ViewError("插件数据不完整 Key 不存在", "/system/plugin/list")
|
||||
}
|
||||
configValue := make(map[string]string)
|
||||
configValueStr, ok := plugin["conf_value"]
|
||||
if ok && configValueStr != "" {
|
||||
json.Unmarshal([]byte(configValueStr), &configValue)
|
||||
}
|
||||
// 根据不同的插件,显示不同的配置页面
|
||||
this.Data["plugin_config"] = configValue
|
||||
this.Data["plugin"] = plugin
|
||||
this.viewLayout("plugin/"+pluginKey, "plugin")
|
||||
}
|
||||
|
||||
func (this *PluginController) ConfigModify() {
|
||||
|
||||
pluginId := this.GetString("plugin_id", "")
|
||||
confValue := this.GetString("conf_value", "")
|
||||
if pluginId == "" {
|
||||
this.jsonError("参数错误")
|
||||
}
|
||||
if confValue == "" {
|
||||
this.jsonError("配置参数为空")
|
||||
}
|
||||
|
||||
plugin, err := models.PluginModel.GetPluginByPluginId(pluginId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找插件错误:" + err.Error())
|
||||
this.jsonError("查找插件错误")
|
||||
}
|
||||
if len(plugin) == 0 {
|
||||
this.jsonError("插件不存在")
|
||||
}
|
||||
|
||||
// 更新插件
|
||||
_, err = models.PluginModel.UpdateConfValueByPluginId(pluginId, confValue)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改插件配置错误:" + err.Error())
|
||||
this.jsonError("修改插件配置失败")
|
||||
}
|
||||
this.jsonSuccess("修改插件配置成功", nil, "/system/plugin/list")
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PrivilegeController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *PrivilegeController) Add() {
|
||||
|
||||
menus, _, err := models.PrivilegeModel.GetTypePrivileges()
|
||||
if err != nil {
|
||||
this.ViewError("查找权限菜单失败!")
|
||||
}
|
||||
|
||||
this.Data["menus"] = menus
|
||||
this.Data["mode"] = beego.BConfig.RunMode
|
||||
this.viewLayout("privilege/form", "privilege")
|
||||
}
|
||||
|
||||
func (this *PrivilegeController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式错误", "/system/privilege/add")
|
||||
}
|
||||
if beego.BConfig.RunMode != "dev" {
|
||||
this.jsonError("只允许在开发模式下添加权限!")
|
||||
}
|
||||
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
privilegeType := strings.TrimSpace(this.GetString("type", ""))
|
||||
parentId := strings.TrimSpace(this.GetString("parent_id", "0"))
|
||||
controller := strings.TrimSpace(this.GetString("controller", ""))
|
||||
action := strings.TrimSpace(this.GetString("action", ""))
|
||||
target := strings.TrimSpace(this.GetString("target", ""))
|
||||
icon := strings.TrimSpace(this.GetString("icon", ""))
|
||||
isDisplay := strings.TrimSpace(this.GetString("is_display", "0"))
|
||||
sequence := strings.TrimSpace(this.GetString("sequence", "0"))
|
||||
|
||||
if name == "" {
|
||||
this.jsonError("权限名称不能为空!")
|
||||
}
|
||||
if privilegeType == "" {
|
||||
this.jsonError("没有选择权限类型!")
|
||||
}
|
||||
if privilegeType == "controller" {
|
||||
if parentId == "" {
|
||||
this.jsonError("控制器必须选择上级菜单!")
|
||||
}
|
||||
if controller == "" {
|
||||
this.jsonError("控制器名称不能为空!")
|
||||
}
|
||||
if action == "" {
|
||||
this.jsonError("方法名称不能为空!")
|
||||
}
|
||||
}
|
||||
|
||||
privilegeId, err := models.PrivilegeModel.Insert(map[string]interface{}{
|
||||
"name": name,
|
||||
"type": privilegeType,
|
||||
"parent_id": parentId,
|
||||
"controller": controller,
|
||||
"action": action,
|
||||
"target": target,
|
||||
"icon": icon,
|
||||
"is_display": isDisplay,
|
||||
"sequence": sequence,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("添加权限失败:" + err.Error())
|
||||
this.jsonError("添加权限失败")
|
||||
}
|
||||
this.InfoLog("添加权限 " + utils.Convert.IntToString(privilegeId, 10) + " 成功")
|
||||
this.jsonSuccess("添加权限成功", nil, "/system/privilege/list")
|
||||
}
|
||||
|
||||
func (this *PrivilegeController) List() {
|
||||
|
||||
menus, controllers, err := models.PrivilegeModel.GetTypePrivileges()
|
||||
if err != nil {
|
||||
this.ViewError("查找权限失败!")
|
||||
}
|
||||
|
||||
this.Data["menus"] = menus
|
||||
this.Data["controllers"] = controllers
|
||||
this.Data["mode"] = beego.BConfig.RunMode
|
||||
this.viewLayout("privilege/list", "privilege")
|
||||
}
|
||||
|
||||
func (this *PrivilegeController) Edit() {
|
||||
|
||||
privilegeId := this.GetString("privilege_id", "")
|
||||
if privilegeId == "" {
|
||||
this.ViewError("没有选择权限!", "/system/privilege/list")
|
||||
}
|
||||
|
||||
privilege, err := models.PrivilegeModel.GetPrivilegeByPrivilegeId(privilegeId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找权限失败:" + err.Error())
|
||||
this.ViewError("查找权限失败!", "/system/privilege/list")
|
||||
}
|
||||
if len(privilege) == 0 {
|
||||
this.ViewError("权限不存在!", "/system/privilege/list")
|
||||
}
|
||||
|
||||
menus, _, err := models.PrivilegeModel.GetTypePrivileges()
|
||||
if err != nil {
|
||||
this.ViewError("查找权限失败!", "/system/privilege/list")
|
||||
}
|
||||
|
||||
this.Data["menus"] = menus
|
||||
this.Data["privilege"] = privilege
|
||||
this.Data["mode"] = beego.BConfig.RunMode
|
||||
this.viewLayout("privilege/form", "privilege")
|
||||
}
|
||||
|
||||
func (this *PrivilegeController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式错误", "/system/privilege/list")
|
||||
}
|
||||
if beego.BConfig.RunMode != "dev" {
|
||||
this.jsonError("只允许在开发模式下修改权限!")
|
||||
}
|
||||
privilegeId := strings.TrimSpace(this.GetString("privilege_id", ""))
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
privilegeType := strings.TrimSpace(this.GetString("type", ""))
|
||||
parentId := strings.TrimSpace(this.GetString("parent_id", "0"))
|
||||
controller := strings.TrimSpace(this.GetString("controller", ""))
|
||||
action := strings.TrimSpace(this.GetString("action", ""))
|
||||
target := strings.TrimSpace(this.GetString("target", ""))
|
||||
icon := strings.TrimSpace(this.GetString("icon", "glyphicon-list"))
|
||||
isDisplay := strings.TrimSpace(this.GetString("is_display", "0"))
|
||||
sequence := strings.TrimSpace(this.GetString("sequence", "0"))
|
||||
|
||||
if name == "" {
|
||||
this.jsonError("权限名称不能为空!")
|
||||
}
|
||||
if privilegeType == "" {
|
||||
this.jsonError("没有选择权限类型!")
|
||||
}
|
||||
if privilegeType == "controller" {
|
||||
if parentId == "" {
|
||||
this.jsonError("控制器必须选择上级菜单!")
|
||||
}
|
||||
if controller == "" {
|
||||
this.jsonError("控制器名称不能为空!")
|
||||
}
|
||||
if action == "" {
|
||||
this.jsonError("方法名称不能为空!")
|
||||
}
|
||||
}
|
||||
|
||||
_, err := models.PrivilegeModel.Update(privilegeId, map[string]interface{}{
|
||||
"name": name,
|
||||
"type": privilegeType,
|
||||
"parent_id": parentId,
|
||||
"controller": controller,
|
||||
"action": action,
|
||||
"target": target,
|
||||
"icon": icon,
|
||||
"is_display": isDisplay,
|
||||
"sequence": sequence,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("修改权限 " + privilegeId + " 失败:" + err.Error())
|
||||
this.jsonError("修改权限失败!")
|
||||
}
|
||||
this.InfoLog("修改权限 " + privilegeId + " 成功")
|
||||
this.jsonSuccess("修改权限成功", nil, "/system/privilege/list")
|
||||
}
|
||||
|
||||
func (this *PrivilegeController) Delete() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/privilege/list")
|
||||
}
|
||||
if beego.BConfig.RunMode != "dev" {
|
||||
this.jsonError("只允许在开发模式下删除权限!")
|
||||
}
|
||||
privilegeId := this.GetString("privilege_id", "")
|
||||
if privilegeId == "" {
|
||||
this.jsonError("没有选择权限!")
|
||||
}
|
||||
|
||||
privilege, err := models.PrivilegeModel.GetPrivilegeByPrivilegeId(privilegeId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除权限 " + privilegeId + " 失败: " + err.Error())
|
||||
this.jsonError("删除权限失败")
|
||||
}
|
||||
if len(privilege) == 0 {
|
||||
this.jsonError("权限不存在")
|
||||
}
|
||||
|
||||
// delete role_privilege by privilegeId
|
||||
err = models.RolePrivilegeModel.DeleteByPrivilegeId(privilegeId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除角色权限 " + privilegeId + " 失败: " + err.Error())
|
||||
this.jsonError("删除权限失败")
|
||||
}
|
||||
|
||||
// delete privilege
|
||||
err = models.PrivilegeModel.Delete(privilegeId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除权限 " + privilegeId + " 失败: " + err.Error())
|
||||
this.jsonError("删除权限失败")
|
||||
}
|
||||
|
||||
this.InfoLog("删除权限 " + privilegeId + " 成功")
|
||||
this.jsonSuccess("删除权限成功", nil, "/system/privilege/list")
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego/validation"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ProfileController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *ProfileController) Info() {
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(this.UserId)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取我的资料失败: " + err.Error())
|
||||
this.ViewError("获取资料失败")
|
||||
}
|
||||
|
||||
logDocuments, err := models.LogDocumentModel.GetLogDocumentsByUserIdAndLimit(this.UserId, 0, 10)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户活动出错:" + err.Error())
|
||||
this.ViewError("查找用户活动出错!", "/main/index")
|
||||
}
|
||||
|
||||
docIds := []string{}
|
||||
for _, logDocument := range logDocuments {
|
||||
docIds = append(docIds, logDocument["document_id"])
|
||||
}
|
||||
documents, err := models.DocumentModel.GetAllDocumentsByDocumentIds(docIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户活动出错: " + err.Error())
|
||||
this.ViewError("查找用户活动出错", "/main/index")
|
||||
}
|
||||
|
||||
for _, logDocument := range logDocuments {
|
||||
for _, document := range documents {
|
||||
if document["document_id"] == logDocument["document_id"] {
|
||||
logDocument["document_id"] = document["document_id"]
|
||||
logDocument["document_name"] = document["name"]
|
||||
logDocument["document_type"] = document["type"]
|
||||
logDocument["update_time"] = document["update_time"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["logDocuments"] = logDocuments
|
||||
this.Data["count"] = len(logDocuments)
|
||||
this.Data["user"] = user
|
||||
this.viewLayout("profile/info", "profile")
|
||||
}
|
||||
|
||||
func (this *ProfileController) Edit() {
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(this.UserId)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取我的资料失败: " + err.Error())
|
||||
this.ViewError("获取资料失败")
|
||||
}
|
||||
this.Data["user"] = user
|
||||
this.viewLayout("profile/edit", "profile")
|
||||
}
|
||||
|
||||
func (this *ProfileController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/profile/info")
|
||||
}
|
||||
givenName := strings.TrimSpace(this.GetString("given_name", ""))
|
||||
email := strings.TrimSpace(this.GetString("email", ""))
|
||||
mobile := strings.TrimSpace(this.GetString("mobile", ""))
|
||||
phone := strings.TrimSpace(this.GetString("phone", ""))
|
||||
department := strings.TrimSpace(this.GetString("department", ""))
|
||||
position := strings.TrimSpace(this.GetString("position", ""))
|
||||
location := strings.TrimSpace(this.GetString("location", ""))
|
||||
im := strings.TrimSpace(this.GetString("im", ""))
|
||||
|
||||
v := validation.Validation{}
|
||||
if givenName == "" {
|
||||
this.jsonError("姓名不能为空!")
|
||||
}
|
||||
if email == "" {
|
||||
this.jsonError("邮箱不能为空!")
|
||||
}
|
||||
if !v.Email(email, "email").Ok {
|
||||
this.jsonError("邮箱格式不正确!")
|
||||
}
|
||||
if mobile == "" {
|
||||
this.jsonError("手机号不能为空!")
|
||||
}
|
||||
//if !v.Mobile(mobile, "mobile").Ok {
|
||||
// this.jsonError("手机号格式不正确!")
|
||||
//}
|
||||
//if phone != "" && !v.Phone(phone, "phone").Ok {
|
||||
// this.jsonError("电话格式不正确!")
|
||||
//}
|
||||
|
||||
_, err := models.UserModel.Update(this.UserId, map[string]interface{}{
|
||||
"given_name": givenName,
|
||||
"email": email,
|
||||
"mobile": mobile,
|
||||
"phone": phone,
|
||||
"department": department,
|
||||
"position": position,
|
||||
"location": location,
|
||||
"im": im,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("修改我的资料失败:" + err.Error())
|
||||
this.jsonError("修改我的资料失败")
|
||||
}
|
||||
this.InfoLog("修改我的资料成功")
|
||||
this.jsonSuccess("我的资料修改成功", nil, "/system/profile/info")
|
||||
}
|
||||
|
||||
func (this *ProfileController) FollowUser() {
|
||||
|
||||
// follow users
|
||||
followUsers, err := models.FollowModel.GetFollowsByUserIdAndType(this.UserId, models.Follow_Type_User)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取我的关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/system/profile/info")
|
||||
}
|
||||
userIds := []string{}
|
||||
for _, followUser := range followUsers {
|
||||
userIds = append(userIds, followUser["object_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取我的关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/system/profile/info")
|
||||
}
|
||||
for _, user := range users {
|
||||
user["follow_id"] = "0"
|
||||
for _, followUser := range followUsers {
|
||||
if followUser["object_id"] == user["user_id"] {
|
||||
user["follow_id"] = followUser["follow_id"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fans users
|
||||
followedUsers, err := models.FollowModel.GetFollowsByObjectIdAndType(this.UserId, models.Follow_Type_User)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/system/profile/info")
|
||||
}
|
||||
followedUserIds := []string{}
|
||||
for _, followedUser := range followedUsers {
|
||||
followedUserIds = append(followedUserIds, followedUser["user_id"])
|
||||
}
|
||||
fansUsers, err := models.UserModel.GetUsersByUserIds(followedUserIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/system/profile/info")
|
||||
}
|
||||
|
||||
this.Data["users"] = users
|
||||
this.Data["fansUsers"] = fansUsers
|
||||
this.Data["followCount"] = len(users)
|
||||
this.Data["fansCount"] = len(fansUsers)
|
||||
this.Data["user"] = this.User
|
||||
this.viewLayout("profile/follow_user", "profile")
|
||||
}
|
||||
|
||||
func (this *ProfileController) FollowDoc() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
number, _ := this.GetRangeInt("number", 10, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
|
||||
// follow docs limit
|
||||
followDocuments, err := models.FollowModel.GetFollowsByUserIdTypeAndLimit(this.UserId, models.Follow_Type_Doc, limit, number)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注文档列表失败: " + err.Error())
|
||||
this.ViewError("获取关注文档列表失败", "/system/profile/info")
|
||||
}
|
||||
count, err := models.FollowModel.CountFollowsByUserIdAndType(this.UserId, models.Follow_Type_Doc)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取关注文档列表失败: " + err.Error())
|
||||
this.ViewError("获取关注文档列表失败", "/system/profile/info")
|
||||
}
|
||||
|
||||
docIds := []string{}
|
||||
for _, followDocument := range followDocuments {
|
||||
docIds = append(docIds, followDocument["object_id"])
|
||||
}
|
||||
documents, err := models.DocumentModel.GetDocumentsByDocumentIds(docIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取我的关注用户列表失败: " + err.Error())
|
||||
this.ViewError("获取关注用户列表失败", "/system/profile/info")
|
||||
}
|
||||
|
||||
for _, followDocument := range followDocuments {
|
||||
for _, document := range documents {
|
||||
if document["document_id"] == followDocument["object_id"] {
|
||||
followDocument["document_id"] = document["document_id"]
|
||||
followDocument["document_name"] = document["name"]
|
||||
followDocument["update_time"] = document["update_time"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
autoFollowDoc := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyAutoFollowdoc, "0")
|
||||
|
||||
this.Data["followDocuments"] = followDocuments
|
||||
this.Data["count"] = len(documents)
|
||||
this.Data["user"] = this.User
|
||||
this.Data["autoFollowDoc"] = autoFollowDoc
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("profile/follow_doc", "profile")
|
||||
}
|
||||
|
||||
func (this *ProfileController) Activity() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
number, _ := this.GetRangeInt("number", 15, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
|
||||
var logDocuments = []map[string]string{}
|
||||
var err error
|
||||
var count int64
|
||||
if keyword != "" {
|
||||
logDocuments, err = models.LogDocumentModel.GetLogDocumentsByUserIdKeywordAndLimit(this.UserId, keyword, limit, number)
|
||||
count, err = models.LogDocumentModel.CountLogDocumentsByUserIdAndKeyword(this.UserId, keyword)
|
||||
} else {
|
||||
logDocuments, err = models.LogDocumentModel.GetLogDocumentsByUserIdAndLimit(this.UserId, limit, number)
|
||||
count, err = models.LogDocumentModel.CountLogDocumentsByUserId(this.UserId)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("我的活动查找失败:" + err.Error())
|
||||
this.ViewError("我的活动查找失败!", "/system/main/index")
|
||||
}
|
||||
|
||||
userIds := []string{}
|
||||
docIds := []string{}
|
||||
for _, logDocument := range logDocuments {
|
||||
userIds = append(userIds, logDocument["user_id"])
|
||||
docIds = append(docIds, logDocument["document_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("我的活动查找失败:" + err.Error())
|
||||
this.ViewError("我的活动查找失败!", "/system/main/index")
|
||||
}
|
||||
docs, err := models.DocumentModel.GetAllDocumentsByDocumentIds(docIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("我的活动查找失败:" + err.Error())
|
||||
this.ViewError("我的活动查找失败!", "/system/main/index")
|
||||
}
|
||||
for _, logDocument := range logDocuments {
|
||||
logDocument["username"] = ""
|
||||
for _, user := range users {
|
||||
if logDocument["user_id"] == user["user_id"] {
|
||||
logDocument["username"] = user["username"]
|
||||
logDocument["given_name"] = user["given_name"]
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, doc := range docs {
|
||||
if logDocument["document_id"] == doc["document_id"] {
|
||||
logDocument["document_name"] = doc["name"]
|
||||
logDocument["document_type"] = doc["type"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["logDocuments"] = logDocuments
|
||||
this.Data["keyword"] = keyword
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("profile/activity", "profile")
|
||||
}
|
||||
|
||||
func (this *ProfileController) Password() {
|
||||
|
||||
this.viewLayout("profile/password", "profile")
|
||||
}
|
||||
|
||||
func (this *ProfileController) SavePass() {
|
||||
|
||||
pwd := strings.TrimSpace(this.GetString("pwd", ""))
|
||||
pwdNew := strings.TrimSpace(this.GetString("pwd_new", ""))
|
||||
pwdConfirm := strings.TrimSpace(this.GetString("pwd_confirm", ""))
|
||||
|
||||
if (pwd == "") || (pwdNew == "") || (pwdConfirm == "") {
|
||||
this.jsonError("密码不能为空!")
|
||||
}
|
||||
|
||||
p := models.UserModel.EncodePassword(pwd)
|
||||
if p != this.User["password"] {
|
||||
this.jsonError("当前密码错误")
|
||||
}
|
||||
if pwdConfirm != pwdNew {
|
||||
this.jsonError("确认密码和新密码不一致")
|
||||
}
|
||||
|
||||
_, err := models.UserModel.Update(this.UserId, map[string]interface{}{
|
||||
"password": models.UserModel.EncodePassword(pwdNew),
|
||||
})
|
||||
|
||||
// 阻止日志记录 password
|
||||
this.Ctx.Request.PostForm.Del("pwd")
|
||||
this.Ctx.Request.PostForm.Del("pwd_new")
|
||||
this.Ctx.Request.PostForm.Del("pwd_confirm")
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("修改密码失败:" + err.Error())
|
||||
this.jsonError("修改密码失败")
|
||||
}
|
||||
|
||||
this.InfoLog("修改密码成功")
|
||||
this.jsonSuccess("修改密码成功, 下次登录时生效", nil, "/system/profile/password")
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type RoleController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *RoleController) Add() {
|
||||
this.viewLayout("role/form", "role")
|
||||
}
|
||||
|
||||
func (this *RoleController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/role/list")
|
||||
}
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
if name == "" {
|
||||
this.jsonError("角色名称不能为空!")
|
||||
}
|
||||
|
||||
ok, err := models.RoleModel.HasRoleName(name)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加角色失败:" + err.Error())
|
||||
this.jsonError("添加角色失败!")
|
||||
}
|
||||
if ok {
|
||||
this.jsonError("角色名已经存在!")
|
||||
}
|
||||
|
||||
roleId, err := models.RoleModel.Insert(map[string]interface{}{
|
||||
"name": name,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("添加角色失败:" + err.Error())
|
||||
this.jsonError("添加角色失败")
|
||||
}
|
||||
this.InfoLog("添加角色 " + utils.Convert.IntToString(roleId, 10) + " 成功")
|
||||
this.jsonSuccess("添加角色成功", nil, "/system/role/list")
|
||||
}
|
||||
|
||||
func (this *RoleController) List() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
|
||||
var err error
|
||||
var count int64
|
||||
var roles []map[string]string
|
||||
if keyword != "" {
|
||||
count, err = models.RoleModel.CountRolesByKeyword(keyword)
|
||||
roles, err = models.RoleModel.GetRolesByKeywordAndLimit(keyword, limit, number)
|
||||
} else {
|
||||
count, err = models.RoleModel.CountRoles()
|
||||
roles, err = models.RoleModel.GetRolesByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取角色列表失败: " + err.Error())
|
||||
this.ViewError("获取角色列表失败", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["roles"] = roles
|
||||
this.Data["keyword"] = keyword
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("role/list", "role")
|
||||
}
|
||||
|
||||
func (this *RoleController) Edit() {
|
||||
|
||||
roleId := this.GetString("role_id", "")
|
||||
if roleId == "" {
|
||||
this.ViewError("角色不存在", "/system/role/list")
|
||||
}
|
||||
if roleId == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
this.ViewError("不能修改超级管理员", "/system/role/list")
|
||||
}
|
||||
|
||||
role, err := models.RoleModel.GetRoleByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找角色错误:" + err.Error())
|
||||
this.ViewError("查找角色错误", "/system/role/list")
|
||||
}
|
||||
if len(role) == 0 {
|
||||
this.ViewError("角色不存在", "/system/role/list")
|
||||
}
|
||||
|
||||
this.Data["role"] = role
|
||||
this.viewLayout("role/form", "role")
|
||||
}
|
||||
|
||||
func (this *RoleController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/role/list")
|
||||
}
|
||||
roleId := this.GetString("role_id", "")
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
|
||||
if roleId == "" {
|
||||
this.jsonError("角色不存在!")
|
||||
}
|
||||
if roleId == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
this.jsonError("超级管理员不能修改!")
|
||||
}
|
||||
if name == "" {
|
||||
this.jsonError("角色名称不能为空!")
|
||||
}
|
||||
|
||||
role, err := models.RoleModel.GetRoleByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改角色 " + roleId + " 失败: " + err.Error())
|
||||
this.jsonError("修改角色失败!")
|
||||
}
|
||||
if len(role) == 0 {
|
||||
this.jsonError("角色不存在!")
|
||||
}
|
||||
if role["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
this.jsonError("超级管理员角色不能修改!")
|
||||
}
|
||||
|
||||
ok, _ := models.RoleModel.HasSameName(roleId, name)
|
||||
if ok {
|
||||
this.jsonError("角色名已经存在!")
|
||||
}
|
||||
_, err = models.RoleModel.Update(roleId, map[string]interface{}{
|
||||
"name": name,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("修改角色 " + roleId + " 失败:" + err.Error())
|
||||
this.jsonError("修改角色" + roleId + "失败")
|
||||
}
|
||||
this.InfoLog("修改角色 " + roleId + " 成功")
|
||||
this.jsonSuccess("修改角色成功", nil, "/system/role/list")
|
||||
}
|
||||
|
||||
func (this *RoleController) User() {
|
||||
|
||||
keywords := map[string]string{}
|
||||
page, _ := this.GetInt("page", 1)
|
||||
roleId := strings.TrimSpace(this.GetString("role_id", ""))
|
||||
|
||||
if roleId == "" {
|
||||
this.ViewError("没有选择角色!")
|
||||
}
|
||||
keywords["role_id"] = roleId
|
||||
|
||||
number, _ := this.GetRangeInt("number", 15, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
var err error
|
||||
var count int64
|
||||
var users []map[string]string
|
||||
count, err = models.UserModel.CountUsersByKeywords(keywords)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取角色用户列表失败: " + err.Error())
|
||||
this.ViewError("获取角色用户列表失败!", "/system/role/list")
|
||||
}
|
||||
users, err = models.UserModel.GetUsersByKeywordsAndLimit(keywords, limit, number)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户列表失败: " + err.Error())
|
||||
this.ViewError("获取用户列表失败!", "/system/role/list")
|
||||
}
|
||||
|
||||
role, err := models.RoleModel.GetRoleByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户列表失败: " + err.Error())
|
||||
this.ViewError("获取角色用户列表失败!", "/system/main/index")
|
||||
}
|
||||
for _, user := range users {
|
||||
user["role_name"] = role["name"]
|
||||
}
|
||||
|
||||
this.Data["users"] = users
|
||||
this.Data["roleId"] = roleId
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("role/user", "role")
|
||||
}
|
||||
|
||||
func (this *RoleController) Privilege() {
|
||||
|
||||
roleId := this.GetString("role_id", "")
|
||||
if roleId == "" {
|
||||
this.ViewError("角色不存在", "/system/role/list")
|
||||
}
|
||||
|
||||
role, err := models.RoleModel.GetRoleByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找角色权限失败:" + err.Error())
|
||||
this.ViewError("查看角色权限失败!", "/system/role/list")
|
||||
}
|
||||
if len(role) == 0 {
|
||||
this.ViewError("角色不存在", "/system/role/list")
|
||||
}
|
||||
|
||||
menus, controllers, err := models.PrivilegeModel.GetTypePrivileges()
|
||||
if err != nil {
|
||||
this.ViewError("查找角色权限失败!")
|
||||
}
|
||||
|
||||
var rolePrivileges = []map[string]string{}
|
||||
if role["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
rolePrivileges, err = models.RolePrivilegeModel.GetRootRolePrivileges()
|
||||
} else {
|
||||
rolePrivileges, err = models.RolePrivilegeModel.GetRolePrivilegesByRoleId(roleId)
|
||||
}
|
||||
if err != nil {
|
||||
this.ViewError("查找用户权限出错")
|
||||
}
|
||||
|
||||
this.Data["role"] = role
|
||||
this.Data["menus"] = menus
|
||||
this.Data["controllers"] = controllers
|
||||
this.Data["rolePrivileges"] = rolePrivileges
|
||||
this.Data["disabledPrivilegeIds"] = models.Privilege_Default_Ids
|
||||
|
||||
this.viewLayout("role/privilege", "role")
|
||||
}
|
||||
|
||||
func (this *RoleController) GrantPrivilege() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/role/list")
|
||||
}
|
||||
privilegeIds := this.GetStrings("privilege_id", []string{})
|
||||
roleId := this.GetString("role_id", "")
|
||||
|
||||
if roleId == "" {
|
||||
this.jsonError("没有选择角色!")
|
||||
}
|
||||
//if len(privilegeIds) == 0 {
|
||||
// this.jsonError("没有选择权限!")
|
||||
//}
|
||||
// add default privileges
|
||||
privilegeIds = append(privilegeIds, models.Privilege_Default_Ids...)
|
||||
|
||||
role, err := models.RoleModel.GetRoleByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("角色 " + roleId + " 授权失败:" + err.Error())
|
||||
this.jsonError("角色不存在")
|
||||
}
|
||||
if len(role) == 0 {
|
||||
this.jsonError("角色不存在")
|
||||
}
|
||||
|
||||
if role["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
this.jsonError("超级管理员不需要授权!")
|
||||
}
|
||||
|
||||
res, err := models.RolePrivilegeModel.GrantRolePrivileges(roleId, privilegeIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("角色 " + roleId + " 授权失败:" + err.Error())
|
||||
this.jsonError("角色授权失败!")
|
||||
}
|
||||
if !res {
|
||||
this.jsonError("角色授权失败")
|
||||
}
|
||||
|
||||
this.InfoLog("角色 " + roleId + " 授权成功")
|
||||
this.jsonSuccess("角色授权成功", nil, "/system/role/list")
|
||||
}
|
||||
|
||||
func (this *RoleController) Delete() {
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/role/list")
|
||||
}
|
||||
|
||||
roleId := this.GetString("role_id", "")
|
||||
if roleId == "" {
|
||||
this.jsonError("没有选择角色!")
|
||||
}
|
||||
if roleId == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
this.jsonError("超级管理员不能删除!")
|
||||
}
|
||||
|
||||
role, err := models.RoleModel.GetRoleByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除角色 " + roleId + " 失败: " + err.Error())
|
||||
this.jsonError("删除角色失败")
|
||||
}
|
||||
if len(role) == 0 {
|
||||
this.jsonError("角色不存在")
|
||||
}
|
||||
if role["type"] == fmt.Sprintf("%d", models.Role_Type_System) {
|
||||
this.jsonError("系统角色不能删除!")
|
||||
}
|
||||
|
||||
// check role user
|
||||
users, err := models.UserModel.GetUsersByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除角色 " + roleId + " 失败: " + err.Error())
|
||||
this.jsonError("删除角色失败")
|
||||
}
|
||||
if len(users) > 0 {
|
||||
this.jsonError("不能删除角色,请先移除该角色下用户!")
|
||||
}
|
||||
|
||||
// delete role privilege by role id
|
||||
err = models.RolePrivilegeModel.DeleteByRoleId(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除角色 " + roleId + " 权限失败: " + err.Error())
|
||||
this.jsonError("删除角色失败")
|
||||
}
|
||||
|
||||
// delete role by role id
|
||||
err = models.RoleModel.Delete(roleId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除角色 " + roleId + " 失败: " + err.Error())
|
||||
this.jsonError("删除角色失败")
|
||||
}
|
||||
|
||||
this.InfoLog("删除角色 " + roleId + " 成功")
|
||||
this.jsonSuccess("删除角色成功", nil, "/system/role/list")
|
||||
}
|
||||
|
||||
func (this *RoleController) ResetUser() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/role/list")
|
||||
}
|
||||
userId := this.GetString("user_id", "")
|
||||
if userId == "" {
|
||||
this.jsonError("用户不存在")
|
||||
}
|
||||
|
||||
if this.UserId == "1" {
|
||||
this.jsonError("root 用户不能重置角色!")
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("重置用户 " + userId + " 角色失败: " + err.Error())
|
||||
this.jsonError("重置用户角色失败")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.jsonError("用户不存在")
|
||||
}
|
||||
|
||||
_, err = models.UserModel.Update(userId, map[string]interface{}{
|
||||
"role_id": models.Role_Default_Id,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorLog("重置用户 " + userId + " 角色失败: " + err.Error())
|
||||
this.jsonError("重置用户角色失败")
|
||||
}
|
||||
|
||||
this.InfoLog("重置用户 " + userId + " 角色成功")
|
||||
this.jsonSuccess("重置用户角色成功", nil, "/system/role/list")
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/phachon/mm-wiki/app"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
)
|
||||
|
||||
type SpaceController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *SpaceController) Add() {
|
||||
this.viewLayout("space/form", "space")
|
||||
}
|
||||
|
||||
func (this *SpaceController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/space/list")
|
||||
}
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
description := strings.TrimSpace(this.GetString("description", ""))
|
||||
tags := strings.TrimSpace(this.GetString("tags", ""))
|
||||
visitLevel := strings.TrimSpace(this.GetString("visit_level", "public"))
|
||||
isShare := strings.TrimSpace(this.GetString("is_share", "0"))
|
||||
isExport := strings.TrimSpace(this.GetString("is_export", "0"))
|
||||
|
||||
if name == "" {
|
||||
this.jsonError("空间名称不能为空!")
|
||||
}
|
||||
match, err := regexp.MatchString(`[\\\\/:*?\"<>、|]`, name)
|
||||
if err != nil {
|
||||
this.jsonError("空间名称格式不正确!")
|
||||
}
|
||||
if match {
|
||||
this.jsonError("空间名称格式不正确!")
|
||||
}
|
||||
ok, err := models.SpaceModel.HasSpaceName(name)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加空间失败:" + err.Error())
|
||||
this.jsonError("添加空间失败!")
|
||||
}
|
||||
if ok {
|
||||
this.jsonError("空间名已经存在!")
|
||||
}
|
||||
|
||||
// create space database
|
||||
spaceId, err := models.SpaceModel.Insert(map[string]interface{}{
|
||||
"name": name,
|
||||
"description": description,
|
||||
"tags": tags,
|
||||
"visit_level": strings.ToLower(visitLevel),
|
||||
"is_share": isShare,
|
||||
"is_export": isExport,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorLog("添加空间失败:" + err.Error())
|
||||
this.jsonError("添加空间失败")
|
||||
}
|
||||
|
||||
// create space document
|
||||
spaceDocument := map[string]interface{}{
|
||||
"space_id": fmt.Sprintf("%d", spaceId),
|
||||
"parent_id": "0",
|
||||
"name": name,
|
||||
"type": models.Document_Type_Dir,
|
||||
"path": "0",
|
||||
"create_user_id": this.UserId,
|
||||
"edit_user_id": this.UserId,
|
||||
}
|
||||
_, err = models.DocumentModel.Insert(spaceDocument)
|
||||
if err != nil {
|
||||
// delete space
|
||||
models.SpaceModel.Delete(fmt.Sprintf("%d", spaceId))
|
||||
this.ErrorLog("添加空间文档失败:" + err.Error())
|
||||
this.jsonError("添加空间失败!")
|
||||
}
|
||||
|
||||
// add space member
|
||||
insertValue := map[string]interface{}{
|
||||
"user_id": this.UserId,
|
||||
"space_id": spaceId,
|
||||
"privilege": models.SpaceUser_Privilege_Manager,
|
||||
}
|
||||
_, err = models.SpaceUserModel.Insert(insertValue)
|
||||
if err != nil {
|
||||
// delete space
|
||||
models.SpaceModel.Delete(fmt.Sprintf("%d", spaceId))
|
||||
this.ErrorLog("添加空间添加空间成员失败: " + err.Error())
|
||||
this.jsonError("添加空间失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("添加空间 " + utils.Convert.IntToString(spaceId, 10) + " 成功")
|
||||
this.jsonSuccess("添加空间成功", nil, "/system/space/list")
|
||||
}
|
||||
|
||||
func (this *SpaceController) List() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
keyword := strings.TrimSpace(this.GetString("keyword", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
limit := (page - 1) * number
|
||||
|
||||
var err error
|
||||
var count int64
|
||||
var spaces []map[string]string
|
||||
if keyword != "" {
|
||||
count, err = models.SpaceModel.CountSpacesByKeyword(keyword)
|
||||
spaces, err = models.SpaceModel.GetSpacesByKeywordAndLimit(keyword, limit, number)
|
||||
} else {
|
||||
count, err = models.SpaceModel.CountSpaces()
|
||||
spaces, err = models.SpaceModel.GetSpacesByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间列表失败: " + err.Error())
|
||||
this.ViewError("获取空间列表失败", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["spaces"] = spaces
|
||||
this.Data["keyword"] = keyword
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("space/list", "space")
|
||||
}
|
||||
|
||||
func (this *SpaceController) Edit() {
|
||||
|
||||
spaceId := this.GetString("space_id", "")
|
||||
if spaceId == "" {
|
||||
this.ViewError("空间不存在", "/system/space/list")
|
||||
}
|
||||
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间失败: " + err.Error())
|
||||
this.ViewError("查找空间失败", "/system/space/list")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("空间不存在", "/system/space/list")
|
||||
}
|
||||
|
||||
this.Data["space"] = space
|
||||
this.viewLayout("space/form", "space")
|
||||
}
|
||||
|
||||
func (this *SpaceController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/space/list")
|
||||
}
|
||||
spaceId := this.GetString("space_id", "")
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
description := strings.TrimSpace(this.GetString("description", ""))
|
||||
tags := strings.TrimSpace(this.GetString("tags", ""))
|
||||
visitLevel := strings.TrimSpace(this.GetString("visit_level", "public"))
|
||||
isShare := strings.TrimSpace(this.GetString("is_share", "0"))
|
||||
isExport := strings.TrimSpace(this.GetString("is_export", "0"))
|
||||
|
||||
if spaceId == "" {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
if name == "" {
|
||||
this.jsonError("空间名称不能为空!")
|
||||
}
|
||||
match, err := regexp.MatchString(`[\\\\/:*?\"<>、|]`, name)
|
||||
if err != nil {
|
||||
this.jsonError("空间名称格式不正确!")
|
||||
}
|
||||
if match {
|
||||
this.jsonError("空间名称格式不正确!")
|
||||
}
|
||||
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改空间 " + spaceId + " 失败: " + err.Error())
|
||||
this.jsonError("修改空间失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
|
||||
ok, _ := models.SpaceModel.HasSameName(spaceId, name)
|
||||
if ok {
|
||||
this.jsonError("空间名已经存在!")
|
||||
}
|
||||
|
||||
spaceValue := map[string]interface{}{
|
||||
"name": name,
|
||||
"description": description,
|
||||
"tags": tags,
|
||||
"visit_level": visitLevel,
|
||||
"is_share": isShare,
|
||||
"is_export": isExport,
|
||||
}
|
||||
// update space document dir name if name update
|
||||
_, err = models.SpaceModel.UpdateDBAndSpaceFileName(spaceId, spaceValue, space["name"])
|
||||
if err != nil {
|
||||
this.ErrorLog("修改空间 " + spaceId + " 失败:" + err.Error())
|
||||
this.jsonError("修改空间失败")
|
||||
}
|
||||
this.InfoLog("修改空间 " + spaceId + " 成功")
|
||||
this.jsonSuccess("修改空间成功", nil, "/system/space/list")
|
||||
}
|
||||
|
||||
func (this *SpaceController) Member() {
|
||||
|
||||
page, _ := this.GetInt("page", 1)
|
||||
spaceId := strings.TrimSpace(this.GetString("space_id", ""))
|
||||
number, _ := this.GetRangeInt("number", 15, 10, 100)
|
||||
|
||||
if spaceId == "" {
|
||||
this.ViewError("没有选择空间!")
|
||||
}
|
||||
|
||||
limit := (page - 1) * number
|
||||
|
||||
count, err := models.SpaceUserModel.CountSpaceUsersBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间成员列表失败!", "/system/space/list")
|
||||
}
|
||||
spaceUsers, err := models.SpaceUserModel.GetSpaceUsersBySpaceIdAndLimit(spaceId, limit, number)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间成员列表失败!", "/system/space/list")
|
||||
}
|
||||
|
||||
var userIds = []string{}
|
||||
for _, spaceUser := range spaceUsers {
|
||||
userIds = append(userIds, spaceUser["user_id"])
|
||||
}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间成员列表失败!", "/system/main/index")
|
||||
}
|
||||
for _, user := range users {
|
||||
for _, spaceUser := range spaceUsers {
|
||||
if spaceUser["user_id"] == user["user_id"] {
|
||||
user["space_privilege"] = spaceUser["privilege"]
|
||||
user["space_user_id"] = spaceUser["space_user_id"]
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获取当前空间下的所有user
|
||||
spaceAllUsers, err := models.SpaceUserModel.GetSpaceUsersBySpaceId(spaceId);
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间所有成员列表失败!", "/system/space/list")
|
||||
}
|
||||
var allUserIds = []string{}
|
||||
for _, spaceUser := range spaceAllUsers {
|
||||
allUserIds = append(allUserIds, spaceUser["user_id"])
|
||||
}
|
||||
var otherUsers = []map[string]string{}
|
||||
if len(allUserIds) > 0 {
|
||||
otherUsers, err = models.UserModel.GetUserByNotUserIds(allUserIds)
|
||||
} else {
|
||||
otherUsers, err = models.UserModel.GetUsers()
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取空间 " + spaceId + " 成员列表失败: " + err.Error())
|
||||
this.ViewError("获取空间成员列表失败!", "/system/main/index")
|
||||
}
|
||||
|
||||
this.Data["users"] = users
|
||||
this.Data["space_id"] = spaceId
|
||||
this.Data["otherUsers"] = otherUsers
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("space/member", "space")
|
||||
}
|
||||
|
||||
func (this *SpaceController) Delete() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/space/list")
|
||||
}
|
||||
spaceId := this.GetString("space_id", "")
|
||||
if spaceId == "" {
|
||||
this.jsonError("没有选择空间!")
|
||||
}
|
||||
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除空间 " + spaceId + " 失败: " + err.Error())
|
||||
this.jsonError("删除空间失败")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("空间不存在")
|
||||
}
|
||||
|
||||
// check space documents
|
||||
documents, err := models.DocumentModel.GetDocumentsBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除空间 " + spaceId + " 失败: " + err.Error())
|
||||
this.jsonError("删除空间失败")
|
||||
}
|
||||
if len(documents) > 1 {
|
||||
this.jsonError("不能删除空间,请先删除该空间下文档!")
|
||||
} else if len(documents) == 1 {
|
||||
if documents[0]["name"] != space["name"] {
|
||||
this.jsonError("不能删除空间,请先删除该空间下文档!")
|
||||
} else {
|
||||
// delete space dir and documentId
|
||||
_, pageFile, err := models.DocumentModel.GetParentDocumentsByDocument(documents[0])
|
||||
if err != nil {
|
||||
this.ErrorLog("删除空间 " + spaceId + " 获取空间文件失败: " + err.Error())
|
||||
this.jsonError("删除空间失败")
|
||||
}
|
||||
err = models.DocumentModel.DeleteDBAndFile(documents[0]["document_id"], spaceId, this.UserId,
|
||||
pageFile, fmt.Sprintf("%d", models.Document_Type_Dir))
|
||||
// delete space document attachments
|
||||
_ = models.AttachmentModel.DeleteAttachmentsDBFileByDocumentId(documents[0]["document_id"])
|
||||
}
|
||||
} else {
|
||||
// delete space dir
|
||||
err = utils.Document.DeleteSpace(space["name"])
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("删除空间 " + spaceId + " 失败: " + err.Error())
|
||||
this.jsonError("删除空间失败")
|
||||
}
|
||||
|
||||
// delete space user
|
||||
err = models.SpaceUserModel.DeleteBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除空间 " + spaceId + " 失败: " + err.Error())
|
||||
this.jsonError("删除空间失败")
|
||||
}
|
||||
// delete space and space document
|
||||
err = models.SpaceModel.Delete(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("删除空间 " + spaceId + " 失败: " + err.Error())
|
||||
this.jsonError("删除空间失败")
|
||||
}
|
||||
|
||||
this.InfoLog("删除空间 " + spaceId + " 成功")
|
||||
this.jsonSuccess("删除空间成功", nil, "/system/space/list")
|
||||
}
|
||||
|
||||
func (this *SpaceController) Download() {
|
||||
|
||||
spaceId := this.GetString("space_id", "")
|
||||
if spaceId == "" {
|
||||
this.ViewError("空间不存在", "/system/space/list")
|
||||
}
|
||||
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间失败: " + err.Error())
|
||||
this.ViewError("查找空间失败", "/system/space/list")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.ViewError("空间不存在", "/system/space/list")
|
||||
}
|
||||
|
||||
spaceName := space["name"]
|
||||
spacePath := utils.Document.GetAbsPageFileByPageFile(spaceName)
|
||||
|
||||
packFiles := []*utils.CompressFileInfo{}
|
||||
|
||||
// pack space all markdown file
|
||||
packFiles = append(packFiles, &utils.CompressFileInfo{
|
||||
File: spacePath,
|
||||
PrefixPath: "",
|
||||
})
|
||||
|
||||
// get space all document attachments
|
||||
attachments, err := models.AttachmentModel.GetAttachmentsBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间文档附件失败:" + err.Error())
|
||||
this.ViewError("查找空间文档附件失败!")
|
||||
}
|
||||
for _, attachment := range attachments {
|
||||
if attachment["path"] == "" {
|
||||
continue
|
||||
}
|
||||
path := attachment["path"]
|
||||
attachmentFile := filepath.Join(app.DocumentAbsDir, path)
|
||||
packFile := &utils.CompressFileInfo{
|
||||
File: attachmentFile,
|
||||
PrefixPath: filepath.Dir(path),
|
||||
}
|
||||
packFiles = append(packFiles, packFile)
|
||||
}
|
||||
var dest = fmt.Sprintf("%s/mm_wiki/%s.zip", os.TempDir(), spaceName)
|
||||
err = utils.Zipx.PackFile(packFiles, dest)
|
||||
if err != nil {
|
||||
this.ErrorLog("下载空间文档失败:" + err.Error())
|
||||
this.ViewError("下载空间文档失败!")
|
||||
}
|
||||
|
||||
this.Ctx.Output.Download(dest, spaceName+".zip")
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Space_UserController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *Space_UserController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/space/list")
|
||||
}
|
||||
spaceId := strings.TrimSpace(this.GetString("space_id", ""))
|
||||
userId := this.GetString("user_id", "")
|
||||
privilege := strings.TrimSpace(this.GetString("privilege", "0"))
|
||||
|
||||
if spaceId == "" {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
if userId == "" {
|
||||
this.jsonError("没有选择用户!")
|
||||
}
|
||||
if privilege == "" {
|
||||
this.jsonError("没有选择用户空间权限!")
|
||||
}
|
||||
space, err := models.SpaceModel.GetSpaceBySpaceId(spaceId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加空间 " + spaceId + " 成员 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("添加空间成员失败!")
|
||||
}
|
||||
if len(space) == 0 {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
|
||||
spaceUser, err := models.SpaceUserModel.GetSpaceUserBySpaceIdAndUserId(spaceId, userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加空间 " + spaceId + " 成员 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("添加空间成员失败!")
|
||||
}
|
||||
if len(spaceUser) > 0 {
|
||||
this.jsonError("该用户已经是空间成员!")
|
||||
}
|
||||
|
||||
insertValue := map[string]interface{}{
|
||||
"user_id": userId,
|
||||
"space_id": spaceId,
|
||||
"privilege": privilege,
|
||||
}
|
||||
_, err = models.SpaceUserModel.Insert(insertValue)
|
||||
if err != nil {
|
||||
this.ErrorLog("空间 " + spaceId + " 添加成员 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("添加成员失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("空间 " + spaceId + " 添加成员 " + userId + " 成功")
|
||||
this.jsonSuccess("添加成员成功!", nil, "/system/space/member?space_id="+spaceId)
|
||||
}
|
||||
|
||||
func (this *Space_UserController) Remove() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/space/list")
|
||||
}
|
||||
spaceId := this.GetString("space_id", "")
|
||||
userId := this.GetString("user_id", "")
|
||||
spaceUserId := this.GetString("space_user_id", "")
|
||||
|
||||
if spaceUserId == "" {
|
||||
this.jsonError("空间成员不存在!")
|
||||
}
|
||||
if spaceId == "" {
|
||||
this.jsonError("空间不存在!")
|
||||
}
|
||||
if userId == "" {
|
||||
this.jsonError("用户不存在!")
|
||||
}
|
||||
|
||||
err := models.SpaceUserModel.Delete(spaceUserId)
|
||||
if err != nil {
|
||||
this.ErrorLog("移除空间 " + spaceId + " 下成员 " + userId + " 失败:" + err.Error())
|
||||
this.jsonError("移除成员失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("移除空间 " + spaceId + " 下成员 " + userId + " 成功")
|
||||
this.jsonSuccess("移除成员成功!", nil, "/system/space/member?space_id="+spaceId)
|
||||
}
|
||||
|
||||
func (this *Space_UserController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/space/list")
|
||||
}
|
||||
spaceUserId := this.GetString("space_user_id", "")
|
||||
privilege := this.GetString("privilege", "0")
|
||||
userId := this.GetString("user_id", "")
|
||||
spaceId := this.GetString("space_id", "")
|
||||
|
||||
if spaceUserId == "" {
|
||||
this.jsonError("更新权限错误!")
|
||||
}
|
||||
if privilege == "" {
|
||||
this.jsonError("没有选择权限!")
|
||||
}
|
||||
|
||||
_, err := models.SpaceUserModel.Update(spaceUserId, map[string]interface{}{
|
||||
"privilege": privilege,
|
||||
"update_time": time.Now().Unix(),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorLog("更新空间 " + spaceId + " 下成员 " + userId + " 权限失败:" + err.Error())
|
||||
this.jsonError("更新权限失败!")
|
||||
}
|
||||
|
||||
this.InfoLog("更新空间 " + spaceId + " 下成员 " + userId + " 权限成功")
|
||||
this.jsonSuccess("更新权限成功!", nil)
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/phachon/mm-wiki/app"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StaticController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *StaticController) Default() {
|
||||
|
||||
normalUserCount, err := models.UserModel.CountNormalUsers()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找正常用户数出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
|
||||
forbiddenUserCount, err := models.UserModel.CountForbiddenUsers()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找屏蔽用户数出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
|
||||
spaceCount, err := models.SpaceModel.CountSpaces()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间总数出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
|
||||
documentCount, err := models.DocumentModel.CountDocuments()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档总数出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
|
||||
time.Now().Unix()
|
||||
today := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Local).Unix()
|
||||
todayLoginUserCount, err := models.UserModel.CountUsersByLastTime(today)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找今日登录用户数出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
|
||||
createUserId := "0"
|
||||
createUserIds, err := models.DocumentModel.GetDocumentGroupCreateUserId()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找创建文档最多用户出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
if len(createUserIds) > 0 {
|
||||
createUserId = createUserIds[0]["create_user_id"]
|
||||
}
|
||||
|
||||
editUserId := "0"
|
||||
editUserIds, err := models.DocumentModel.GetDocumentGroupEditUserId()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找修改文档最多用户出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
if len(editUserIds) > 0 {
|
||||
editUserId = editUserIds[0]["edit_user_id"]
|
||||
}
|
||||
|
||||
collectUserId := "0"
|
||||
collectUserIds, err := models.CollectionModel.GetCollectionGroupUserId(models.Collection_Type_Doc)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找收藏文档最多用户出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
if len(collectUserIds) > 0 {
|
||||
collectUserId = collectUserIds[0]["user_id"]
|
||||
}
|
||||
|
||||
fansUserId := "0"
|
||||
fansUserIds, err := models.FollowModel.GetFansUserGroupUserId()
|
||||
if err != nil {
|
||||
this.ErrorLog("查找粉丝数最多用户出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
if len(fansUserIds) > 0 {
|
||||
fansUserId = fansUserIds[0]["object_id"]
|
||||
}
|
||||
|
||||
userIds := []string{createUserId, editUserId, collectUserId, fansUserId}
|
||||
users, err := models.UserModel.GetUsersByUserIds(userIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档总数出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
|
||||
var createMaxUser = map[string]string{"user_id": createUserId, "username": ""}
|
||||
var editMaxUser = map[string]string{"user_id": editUserId, "username": ""}
|
||||
var collectMaxUser = map[string]string{"user_id": collectUserId, "username": ""}
|
||||
var fansMaxUser = map[string]string{"user_id": fansUserId, "username": ""}
|
||||
for _, user := range users {
|
||||
if user["user_id"] == createUserId {
|
||||
createMaxUser["username"] = user["username"]
|
||||
}
|
||||
if user["user_id"] == editUserId {
|
||||
editMaxUser["username"] = user["username"]
|
||||
}
|
||||
if user["user_id"] == collectUserId {
|
||||
collectMaxUser["username"] = user["username"]
|
||||
}
|
||||
if user["user_id"] == fansUserId {
|
||||
fansMaxUser["username"] = user["username"]
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["normalUserCount"] = normalUserCount
|
||||
this.Data["forbiddenUserCount"] = forbiddenUserCount
|
||||
this.Data["spaceCount"] = spaceCount
|
||||
this.Data["documentCount"] = documentCount
|
||||
|
||||
this.Data["todayLoginUserCount"] = todayLoginUserCount
|
||||
this.Data["createMaxUser"] = createMaxUser
|
||||
this.Data["editMaxUser"] = editMaxUser
|
||||
this.Data["collectMaxUser"] = collectMaxUser
|
||||
this.Data["fansMaxUser"] = fansMaxUser
|
||||
|
||||
this.viewLayout("static/default", "static")
|
||||
}
|
||||
|
||||
func (this *StaticController) SpaceDocsRank() {
|
||||
|
||||
number, _ := this.GetInt("number", 15)
|
||||
spaceDocsRank := []map[string]string{}
|
||||
spaceDocCountIds, err := models.DocumentModel.GetSpaceIdsOrderByCountDocumentLimit(number)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间文档排行出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
if len(spaceDocCountIds) > 0 {
|
||||
spaceIds := []string{}
|
||||
for _, spaceDocCountId := range spaceDocCountIds {
|
||||
spaceIds = append(spaceIds, spaceDocCountId["space_id"])
|
||||
}
|
||||
spaces, err := models.SpaceModel.GetSpaceBySpaceIds(spaceIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找空间文档排行出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
for _, spaceDocCountId := range spaceDocCountIds {
|
||||
spaceDocCount := map[string]string{
|
||||
"space_name": "",
|
||||
"total": spaceDocCountId["total"],
|
||||
}
|
||||
for _, space := range spaces {
|
||||
if spaceDocCountId["space_id"] == space["space_id"] {
|
||||
spaceDocCount["space_name"] = space["name"]
|
||||
break
|
||||
}
|
||||
}
|
||||
spaceDocsRank = append(spaceDocsRank, spaceDocCount)
|
||||
}
|
||||
}
|
||||
|
||||
this.jsonSuccess("ok", spaceDocsRank)
|
||||
}
|
||||
|
||||
func (this *StaticController) CollectDocRank() {
|
||||
|
||||
number, _ := this.GetInt("number", 10)
|
||||
collectDocsRank := []map[string]string{}
|
||||
collectionDocIds, err := models.CollectionModel.GetResourceIdsOrderByCountLimit(number, models.Collection_Type_Doc)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找收藏文档排行出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
if len(collectionDocIds) > 0 {
|
||||
documentIds := []string{}
|
||||
for _, collectionDocId := range collectionDocIds {
|
||||
documentIds = append(documentIds, collectionDocId["resource_id"])
|
||||
}
|
||||
documents, err := models.DocumentModel.GetDocumentsByDocumentIds(documentIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找收藏文档排行出错:" + err.Error())
|
||||
this.jsonError("查找数据出错")
|
||||
}
|
||||
for _, collectionDocId := range collectionDocIds {
|
||||
collectDocCount := map[string]string{
|
||||
"document_name": "",
|
||||
"total": collectionDocId["total"],
|
||||
}
|
||||
for _, document := range documents {
|
||||
if collectionDocId["resource_id"] == document["document_id"] {
|
||||
collectDocCount["document_name"] = document["name"]
|
||||
break
|
||||
}
|
||||
}
|
||||
collectDocsRank = append(collectDocsRank, collectDocCount)
|
||||
}
|
||||
}
|
||||
|
||||
this.jsonSuccess("ok", collectDocsRank)
|
||||
}
|
||||
|
||||
func (this *StaticController) DocCountByTime() {
|
||||
|
||||
limitDay, _ := this.GetInt("limit_day", 10)
|
||||
startTime := time.Now().Unix() - int64(limitDay*3600*24)
|
||||
|
||||
documentCountDate, err := models.DocumentModel.GetCountGroupByCreateTime(startTime)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找文档数量增长趋势出错:" + err.Error())
|
||||
this.jsonError("查找文档数量增长趋势出错")
|
||||
}
|
||||
|
||||
this.jsonSuccess("ok", documentCountDate)
|
||||
}
|
||||
|
||||
func (this *StaticController) Monitor() {
|
||||
|
||||
hostInfo, err := host.Info()
|
||||
if err != nil {
|
||||
this.ErrorLog("获取服务器数据错误")
|
||||
}
|
||||
|
||||
serverInfo := map[string]string{
|
||||
"localIp": utils.Misc.GetLocalIp(),
|
||||
"hostname": hostInfo.Hostname,
|
||||
"os": hostInfo.OS,
|
||||
"platform": hostInfo.Platform,
|
||||
"platformFamily": hostInfo.PlatformFamily,
|
||||
}
|
||||
|
||||
errorLogCount, err := models.LogModel.CountLogsByLevel(models.Log_Level_Error)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取数据错误")
|
||||
}
|
||||
|
||||
errLogs, err := models.LogModel.GetLogsByKeywordAndLimit(fmt.Sprintf("%d", models.Log_Level_Error), "", "", 0, 5)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取数据错误")
|
||||
}
|
||||
this.Data["serverInfo"] = serverInfo
|
||||
this.Data["errorLogCount"] = errorLogCount
|
||||
this.Data["errLogs"] = errLogs
|
||||
this.viewLayout("static/monitor", "static")
|
||||
}
|
||||
|
||||
func (this *StaticController) ServerStatus() {
|
||||
memoryUsedPercent := 0
|
||||
cpuUsedPercent := 0
|
||||
diskUsedPercent := 0
|
||||
vm, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
logs.Error("get memory err=%s", err.Error())
|
||||
}
|
||||
if vm != nil {
|
||||
memoryUsedPercent = int(vm.UsedPercent)
|
||||
}
|
||||
cpuPercent, _ := cpu.Percent(0, false)
|
||||
if len(cpuPercent) > 0 {
|
||||
cpuUsedPercent = int(cpuPercent[0])
|
||||
}
|
||||
d, err := disk.Usage("/")
|
||||
if err != nil {
|
||||
logs.Error("get disk err=%s", err.Error())
|
||||
}
|
||||
if d != nil {
|
||||
diskUsedPercent = int(d.UsedPercent)
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"memory_used_percent": memoryUsedPercent,
|
||||
"cpu_used_percent": cpuUsedPercent,
|
||||
"disk_used_percent": diskUsedPercent,
|
||||
}
|
||||
|
||||
this.jsonSuccess("ok", data)
|
||||
}
|
||||
|
||||
func (this *StaticController) ServerTime() {
|
||||
data := map[string]interface{}{
|
||||
"server_time": time.Now().Unix(),
|
||||
"run_time": time.Now().Unix() - app.StartTime,
|
||||
}
|
||||
|
||||
this.jsonSuccess("ok", data)
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/validation"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (this *UserController) Add() {
|
||||
|
||||
roles := []map[string]string{}
|
||||
var err error
|
||||
|
||||
if this.IsRoot() {
|
||||
roles, err = models.RoleModel.GetRoles()
|
||||
} else {
|
||||
roles, err = models.RoleModel.GetRolesNotContainRoot()
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户角色失败:" + err.Error())
|
||||
this.ViewError("获取用户角色失败!")
|
||||
}
|
||||
this.Data["roles"] = roles
|
||||
this.viewLayout("user/form", "user")
|
||||
}
|
||||
|
||||
func (this *UserController) Save() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/user/add")
|
||||
}
|
||||
username := strings.TrimSpace(this.GetString("username", ""))
|
||||
givenName := strings.TrimSpace(this.GetString("given_name", ""))
|
||||
password := strings.TrimSpace(this.GetString("password", ""))
|
||||
email := strings.TrimSpace(this.GetString("email", ""))
|
||||
mobile := strings.TrimSpace(this.GetString("mobile", ""))
|
||||
roleId := strings.TrimSpace(this.GetString("role_id", ""))
|
||||
phone := strings.TrimSpace(this.GetString("phone", ""))
|
||||
department := strings.TrimSpace(this.GetString("department", ""))
|
||||
position := strings.TrimSpace(this.GetString("position", ""))
|
||||
location := strings.TrimSpace(this.GetString("location", ""))
|
||||
im := strings.TrimSpace(this.GetString("im", ""))
|
||||
this.Ctx.Request.PostForm.Del("password")
|
||||
|
||||
v := validation.Validation{}
|
||||
if username == "" {
|
||||
this.jsonError("用户名不能为空!")
|
||||
}
|
||||
if !v.AlphaNumeric(username, "username").Ok {
|
||||
this.jsonError("用户名格式不正确!")
|
||||
}
|
||||
if givenName == "" {
|
||||
this.jsonError("姓名不能为空!")
|
||||
}
|
||||
if password == "" {
|
||||
this.jsonError("密码不能为空!")
|
||||
}
|
||||
if email == "" {
|
||||
this.jsonError("邮箱不能为空!")
|
||||
}
|
||||
if !v.Email(email, "email").Ok {
|
||||
this.jsonError("邮箱格式不正确!")
|
||||
}
|
||||
if mobile == "" {
|
||||
this.jsonError("手机号不能为空!")
|
||||
}
|
||||
//if !v.Mobile(mobile, "mobile").Ok {
|
||||
// this.jsonError("手机号格式不正确!")
|
||||
//}
|
||||
if roleId == "" {
|
||||
this.jsonError("没有选择角色!")
|
||||
}
|
||||
//if phone != "" && !v.Phone(phone, "phone").Ok {
|
||||
// this.jsonError("电话格式不正确!")
|
||||
//}
|
||||
|
||||
ok, err := models.UserModel.HasUsername(username)
|
||||
if err != nil {
|
||||
this.ErrorLog("添加用户失败:" + err.Error())
|
||||
this.jsonError("添加用户失败!")
|
||||
}
|
||||
if ok {
|
||||
this.jsonError("用户名已经存在!")
|
||||
}
|
||||
|
||||
if !this.IsRoot() && roleId == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
this.jsonError("没有权限添加超级管理员!")
|
||||
}
|
||||
|
||||
userId, err := models.UserModel.Insert(map[string]interface{}{
|
||||
"username": username,
|
||||
"given_name": givenName,
|
||||
"password": models.UserModel.EncodePassword(password),
|
||||
"email": email,
|
||||
"mobile": mobile,
|
||||
"phone": phone,
|
||||
"department": department,
|
||||
"position": position,
|
||||
"location": location,
|
||||
"im": im,
|
||||
"role_id": roleId,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
this.ErrorLog("添加用户失败:" + err.Error())
|
||||
this.jsonError("添加用户失败")
|
||||
}
|
||||
this.InfoLog("添加用户 " + utils.Convert.IntToString(userId, 10) + " 成功")
|
||||
this.jsonSuccess("添加用户成功", nil, "/system/user/list")
|
||||
}
|
||||
|
||||
func (this *UserController) List() {
|
||||
|
||||
keywords := map[string]string{}
|
||||
page, _ := this.GetInt("page", 1)
|
||||
username := strings.TrimSpace(this.GetString("username", ""))
|
||||
roleId := strings.TrimSpace(this.GetString("role_id", ""))
|
||||
number, _ := this.GetRangeInt("number", 20, 10, 100)
|
||||
|
||||
if username != "" {
|
||||
keywords["username"] = username
|
||||
}
|
||||
if roleId != "" {
|
||||
keywords["role_id"] = roleId
|
||||
}
|
||||
|
||||
limit := (page - 1) * number
|
||||
var err error
|
||||
var count int64
|
||||
var users []map[string]string
|
||||
if len(keywords) != 0 {
|
||||
count, err = models.UserModel.CountUsersByKeywords(keywords)
|
||||
users, err = models.UserModel.GetUsersByKeywordsAndLimit(keywords, limit, number)
|
||||
} else {
|
||||
count, err = models.UserModel.CountUsers()
|
||||
users, err = models.UserModel.GetUsersByLimit(limit, number)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户列表失败: " + err.Error())
|
||||
this.ViewError("获取用户列表失败", "/system/main/index")
|
||||
}
|
||||
|
||||
var roleIds = []string{}
|
||||
if roleId != "" {
|
||||
roleIds = append(roleIds, roleId)
|
||||
} else {
|
||||
for _, user := range users {
|
||||
roleIds = append(roleIds, user["role_id"])
|
||||
}
|
||||
}
|
||||
roles, err := models.RoleModel.GetRoleByRoleIds(roleIds)
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户列表失败: " + err.Error())
|
||||
this.ViewError("获取用户列表失败!", "/system/main/index")
|
||||
}
|
||||
var roleUsers = []map[string]string{}
|
||||
for _, user := range users {
|
||||
roleUser := user
|
||||
for _, role := range roles {
|
||||
if role["role_id"] == user["role_id"] {
|
||||
roleUser["role_name"] = role["name"]
|
||||
break
|
||||
}
|
||||
}
|
||||
roleUsers = append(roleUsers, roleUser)
|
||||
}
|
||||
|
||||
allRoles, err := models.RoleModel.GetRoles()
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户列表失败: " + err.Error())
|
||||
this.ViewError("获取用户列表失败!", "/system/main/index")
|
||||
}
|
||||
this.Data["users"] = roleUsers
|
||||
this.Data["username"] = username
|
||||
this.Data["roleId"] = roleId
|
||||
this.Data["roles"] = allRoles
|
||||
this.SetPaginator(number, count)
|
||||
this.viewLayout("user/list", "user")
|
||||
}
|
||||
|
||||
func (this *UserController) Edit() {
|
||||
|
||||
userId := this.GetString("user_id", "")
|
||||
if userId == "" {
|
||||
this.ViewError("用户不存在!", "/system/user/list")
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户出错:" + err.Error())
|
||||
this.ViewError("查找用户出错!", "/system/user/list")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.ViewError("用户不存在!", "/system/user/list")
|
||||
}
|
||||
// 登录非 root 用户不能修改 root 用户信息
|
||||
if user["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id) && !this.IsRoot() {
|
||||
this.ViewError("没有权限修改!", "/system/user/list")
|
||||
}
|
||||
|
||||
roles := []map[string]string{}
|
||||
if this.IsRoot() {
|
||||
roles, err = models.RoleModel.GetRoles()
|
||||
} else {
|
||||
roles, err = models.RoleModel.GetRolesNotContainRoot()
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorLog("获取用户角色失败:" + err.Error())
|
||||
this.ViewError("获取用户角色失败!")
|
||||
}
|
||||
|
||||
this.Data["user"] = user
|
||||
this.Data["roles"] = roles
|
||||
this.viewLayout("user/edit", "user")
|
||||
}
|
||||
|
||||
func (this *UserController) Modify() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/user/list")
|
||||
}
|
||||
userId := strings.TrimSpace(this.GetString("user_id", ""))
|
||||
givenName := strings.TrimSpace(this.GetString("given_name", ""))
|
||||
email := strings.TrimSpace(this.GetString("email", ""))
|
||||
mobile := strings.TrimSpace(this.GetString("mobile", ""))
|
||||
roleId := strings.TrimSpace(this.GetString("role_id", ""))
|
||||
phone := strings.TrimSpace(this.GetString("phone", ""))
|
||||
department := strings.TrimSpace(this.GetString("department", ""))
|
||||
position := strings.TrimSpace(this.GetString("position", ""))
|
||||
location := strings.TrimSpace(this.GetString("location", ""))
|
||||
im := strings.TrimSpace(this.GetString("im", ""))
|
||||
password := strings.TrimSpace(this.GetString("password", ""))
|
||||
this.Ctx.Request.PostForm.Del("password")
|
||||
|
||||
v := validation.Validation{}
|
||||
if givenName == "" {
|
||||
this.jsonError("姓名不能为空!")
|
||||
}
|
||||
if email == "" {
|
||||
this.jsonError("邮箱不能为空!")
|
||||
}
|
||||
if !v.Email(email, "email").Ok {
|
||||
this.jsonError("邮箱格式不正确!")
|
||||
}
|
||||
if mobile == "" {
|
||||
this.jsonError("手机号不能为空!")
|
||||
}
|
||||
//if !v.Mobile(mobile, "mobile").Ok {
|
||||
// this.jsonError("手机号格式不正确!")
|
||||
//}
|
||||
//if roleId == "" {
|
||||
// this.jsonError("没有选择角色!")
|
||||
//}
|
||||
//if phone != "" && !v.Phone(phone, "phone").Ok {
|
||||
// this.jsonError("电话格式不正确!")
|
||||
//}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改用户 " + userId + " 失败:" + err.Error())
|
||||
this.jsonError("修改用户出错!")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.jsonError("用户不存在!")
|
||||
}
|
||||
if user["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
roleId = fmt.Sprintf("%d", models.Role_Root_Id)
|
||||
}
|
||||
// 登录非 root 用户不能修改 root 用户信息
|
||||
if user["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id) && !this.IsRoot() {
|
||||
this.jsonError("没有权限修改!")
|
||||
}
|
||||
|
||||
updateUser := map[string]interface{}{
|
||||
"given_name": givenName,
|
||||
"email": email,
|
||||
"mobile": mobile,
|
||||
"phone": phone,
|
||||
"department": department,
|
||||
"position": position,
|
||||
"location": location,
|
||||
"im": im,
|
||||
}
|
||||
// 超级管理员才可以修改其他用户密码
|
||||
if password != "" && this.IsRoot() {
|
||||
updateUser["password"] = models.UserModel.EncodePassword(password)
|
||||
}
|
||||
if roleId != "" {
|
||||
updateUser["role_id"] = roleId
|
||||
}
|
||||
_, err = models.UserModel.Update(userId, updateUser)
|
||||
if err != nil {
|
||||
this.ErrorLog("修改用户 " + userId + " 失败:" + err.Error())
|
||||
this.jsonError("修改用户失败")
|
||||
}
|
||||
this.InfoLog("修改用户 " + userId + " 成功")
|
||||
this.jsonSuccess("修改用户成功", nil, "/system/user/list")
|
||||
}
|
||||
|
||||
func (this *UserController) Forbidden() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/user/list")
|
||||
}
|
||||
userId := this.GetString("user_id", "")
|
||||
if userId == "" {
|
||||
this.jsonError("用户不存在")
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("屏蔽用户 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("屏蔽用户失败")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.jsonError("用户不存在")
|
||||
}
|
||||
if user["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
this.jsonError("不能操作超级管理员")
|
||||
}
|
||||
_, err = models.UserModel.Update(userId, map[string]interface{}{
|
||||
"is_forbidden": models.User_Forbidden_True,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorLog("屏蔽用户 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("屏蔽用户失败")
|
||||
}
|
||||
|
||||
this.InfoLog("屏蔽用户 " + userId + " 成功")
|
||||
this.jsonSuccess("屏蔽用户成功", nil, "/system/user/list")
|
||||
}
|
||||
|
||||
func (this *UserController) Recover() {
|
||||
|
||||
if !this.IsPost() {
|
||||
this.ViewError("请求方式有误!", "/system/user/list")
|
||||
}
|
||||
userId := this.GetString("user_id", "")
|
||||
if userId == "" {
|
||||
this.jsonError("用户不存在")
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("恢复用户 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("恢复用户失败")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.jsonError("用户不存在")
|
||||
}
|
||||
if user["role_id"] == fmt.Sprintf("%d", models.Role_Root_Id) {
|
||||
this.jsonError("不能操作超级管理员")
|
||||
}
|
||||
_, err = models.UserModel.Update(userId, map[string]interface{}{
|
||||
"is_forbidden": models.User_Is_Forbidden_False,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorLog("恢复用户 " + userId + " 失败: " + err.Error())
|
||||
this.jsonError("恢复用户失败")
|
||||
}
|
||||
|
||||
this.InfoLog("恢复用户 " + userId + " 成功")
|
||||
this.jsonSuccess("恢复用户成功", nil, "/system/user/list")
|
||||
}
|
||||
|
||||
func (this *UserController) Info() {
|
||||
|
||||
userId := this.GetString("user_id", "")
|
||||
if userId == "" {
|
||||
this.ViewError("用户不存在!", "/system/user/list")
|
||||
}
|
||||
|
||||
user, err := models.UserModel.GetUserByUserId(userId)
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户出错:" + err.Error())
|
||||
this.ViewError("查找用户出错!", "/system/user/list")
|
||||
}
|
||||
if len(user) == 0 {
|
||||
this.ViewError("用户不存在!", "/system/user/list")
|
||||
}
|
||||
role, err := models.RoleModel.GetRoleByRoleId(user["role_id"])
|
||||
if err != nil {
|
||||
this.ErrorLog("查找用户角色出错:" + err.Error())
|
||||
this.ViewError("查找用户出错!", "/system/user/list")
|
||||
}
|
||||
this.Data["user"] = user
|
||||
this.Data["role"] = role
|
||||
this.viewLayout("user/info", "user")
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// AuthLoginResponse auth login response result
|
||||
type AuthLoginResponse struct {
|
||||
GivenName string `json:"given_name"`
|
||||
Email string `json:"email"`
|
||||
Mobile string `json:"mobile"`
|
||||
Phone string `json:"phone"`
|
||||
Department string `json:"department"`
|
||||
Position string `json:"position"`
|
||||
Location string `json:"location"`
|
||||
Im string `json:"im"`
|
||||
}
|
||||
|
||||
const (
|
||||
AuthLoginProtocolHttp = "http"
|
||||
AuthLoginProtocolHttps = "https"
|
||||
AuthLoginProtocolLdap = "ldap"
|
||||
AuthLoginProtocolLdaps = "ldaps"
|
||||
)
|
||||
|
||||
// AuthLoginService auth login service
|
||||
type AuthLoginService interface {
|
||||
|
||||
// Init init login config
|
||||
InitConf(url string, conf string) error
|
||||
|
||||
// GetServiceName get auth login service name
|
||||
GetServiceName() string
|
||||
|
||||
// AuthLogin auth login request
|
||||
AuthLogin(username string, password string) (*AuthLoginResponse, error)
|
||||
}
|
||||
|
||||
var AuthLogin = NewAuthLoginManager()
|
||||
|
||||
// AuthLoginManager auth login manager
|
||||
type AuthLoginManager struct {
|
||||
AuthLoginServices map[string]AuthLoginService
|
||||
}
|
||||
|
||||
// NewAuthLoginManager new a auth login manager
|
||||
func NewAuthLoginManager() *AuthLoginManager {
|
||||
authLoginManager := &AuthLoginManager{
|
||||
AuthLoginServices: make(map[string]AuthLoginService),
|
||||
}
|
||||
return authLoginManager
|
||||
}
|
||||
|
||||
// RegisterService register a auth login service
|
||||
func (am *AuthLoginManager) RegisterService(serviceName string, authLoginService AuthLoginService) {
|
||||
if authLoginService == nil {
|
||||
return
|
||||
}
|
||||
if _, ok := am.AuthLoginServices[serviceName]; ok {
|
||||
panic(fmt.Sprintf("[AuthLoginManager] RegisterService '%s' already exists", serviceName))
|
||||
}
|
||||
am.AuthLoginServices[serviceName] = authLoginService
|
||||
}
|
||||
|
||||
func (am *AuthLoginManager) UrlIsSupport(serviceName string) bool {
|
||||
if _, ok := am.AuthLoginServices[serviceName]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AuthLogin start auth login
|
||||
func (am *AuthLoginManager) AuthLogin(username, password string) (*AuthLoginResponse, error) {
|
||||
|
||||
// get auth login config
|
||||
authLogin, err := models.AuthModel.GetUsedAuth()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查找登录配置失败")
|
||||
}
|
||||
if len(authLogin) == 0 {
|
||||
return nil, fmt.Errorf("没有可用的统一登录配置")
|
||||
}
|
||||
// parse url protocol
|
||||
authUrl, ok := authLogin["url"]
|
||||
if !ok || authUrl == "" {
|
||||
return nil, fmt.Errorf("登录配置 url 无效")
|
||||
}
|
||||
u, err := url.Parse(authUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("登录配置 url 不合法:%s", err.Error())
|
||||
}
|
||||
serviceName := u.Scheme
|
||||
authLoginService, ok := am.AuthLoginServices[serviceName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("登录配置 url 协议不支持")
|
||||
}
|
||||
serviceConf := ""
|
||||
if extData, ok := authLogin["ext_data"]; ok {
|
||||
serviceConf = extData
|
||||
}
|
||||
// init auth login service config
|
||||
err = authLoginService.InitConf(authUrl, serviceConf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("登录配置初始化失败:%s", err.Error())
|
||||
}
|
||||
// start auth login
|
||||
return authLoginService.AuthLogin(username, password)
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
)
|
||||
|
||||
type AuthLoginHttpRes struct {
|
||||
Message string `json:"message"`
|
||||
Data *AuthLoginResponse `json:"data"`
|
||||
}
|
||||
|
||||
// AuthLoinHttpService http auth login
|
||||
type AuthLoinHttpService struct {
|
||||
url string
|
||||
extData string
|
||||
}
|
||||
|
||||
// NewAuthLoginHttpService
|
||||
func NewAuthLoginHttpService() AuthLoginService {
|
||||
return &AuthLoinHttpService{}
|
||||
}
|
||||
|
||||
// InitConf init http auth login config
|
||||
func (ah *AuthLoinHttpService) InitConf(url string, conf string) error {
|
||||
ah.url = url
|
||||
ah.extData = conf
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthLogin send http request
|
||||
func (ah *AuthLoinHttpService) AuthLogin(username string, password string) (*AuthLoginResponse, error) {
|
||||
if ah.url == "" {
|
||||
return nil, fmt.Errorf("authLogin url is empty")
|
||||
}
|
||||
queryValue := map[string]string{
|
||||
"username": username,
|
||||
"password": password,
|
||||
"ext_data": ah.extData,
|
||||
}
|
||||
// request auth login api
|
||||
body, code, err := utils.Request.HttpPost(ah.url, queryValue, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(body) == 0 {
|
||||
return nil, fmt.Errorf("登录认证失败, httpCode=%d", code)
|
||||
}
|
||||
v := &AuthLoginHttpRes{}
|
||||
err = json.Unmarshal(body, &v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("登录认证失败,返回结果不合法 err=%s", err.Error())
|
||||
}
|
||||
if v.Message != "" {
|
||||
return nil, fmt.Errorf("登录认证失败, message=%s", v.Message)
|
||||
}
|
||||
return v.Data, nil
|
||||
}
|
||||
|
||||
// GetServiceName http
|
||||
func (ah *AuthLoinHttpService) GetServiceName() string {
|
||||
return AuthLoginProtocolHttp
|
||||
}
|
||||
|
||||
func init() {
|
||||
// http://xxx
|
||||
AuthLogin.RegisterService(AuthLoginProtocolHttp, NewAuthLoginHttpService())
|
||||
// https://xxx
|
||||
AuthLogin.RegisterService(AuthLoginProtocolHttps, NewAuthLoginHttpService())
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
LdapDefaultAccountPattern = "(&(objectClass=User)(userPrincipalName=%s))"
|
||||
LdapDefaultAttributeGivenName = "displayName"
|
||||
)
|
||||
|
||||
var (
|
||||
LdapUserSearchNotFoundErr = errors.New("用户不存在或密码错误")
|
||||
)
|
||||
|
||||
type AuthLoginConfig struct {
|
||||
BaseDn string `json:"basedn"`
|
||||
BindUsername string `json:"bind_username"`
|
||||
BindPassword string `json:"bind_password"`
|
||||
AccountPattern string `json:"account_pattern"`
|
||||
GivenNameKey string `json:"given_name_key"`
|
||||
EmailKey string `json:"email_key"`
|
||||
MobileKey string `json:"mobile_key"`
|
||||
PhoneKey string `json:"phone_key"`
|
||||
DepartmentKey string `json:"department_key"`
|
||||
PositionKey string `json:"position_key"`
|
||||
LocationKey string `json:"location_key"`
|
||||
ImKey string `json:"im_key"`
|
||||
}
|
||||
|
||||
// AuthLoginLdapService ldap auth login
|
||||
type AuthLoginLdapService struct {
|
||||
url string
|
||||
conf string
|
||||
config *AuthLoginConfig
|
||||
}
|
||||
|
||||
// NewAuthLoginLdapService
|
||||
func NewAuthLoginLdapService() AuthLoginService {
|
||||
return &AuthLoginLdapService{}
|
||||
}
|
||||
|
||||
// InitConf init ldap auth login config
|
||||
func (al *AuthLoginLdapService) InitConf(url string, conf string) error {
|
||||
al.url = url
|
||||
al.conf = conf
|
||||
authLoginConfig := &AuthLoginConfig{}
|
||||
err := json.Unmarshal([]byte(conf), &authLoginConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
al.config = authLoginConfig
|
||||
if al.config.AccountPattern == "" {
|
||||
al.config.AccountPattern = LdapDefaultAccountPattern
|
||||
}
|
||||
if al.config.GivenNameKey == "" {
|
||||
al.config.GivenNameKey = LdapDefaultAttributeGivenName
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthLogin ldap auth
|
||||
func (al *AuthLoginLdapService) AuthLogin(username string, password string) (*AuthLoginResponse, error) {
|
||||
|
||||
if al.url == "" {
|
||||
return nil, fmt.Errorf("LDAP URL is empty")
|
||||
}
|
||||
if al.config == nil || al.conf == "" {
|
||||
return nil, fmt.Errorf("LDAP 配置数据错误")
|
||||
}
|
||||
if al.config.GivenNameKey == "" {
|
||||
return nil, fmt.Errorf("LDAP 配置 given_name_key 错误")
|
||||
}
|
||||
|
||||
lc, err := ldap.DialURL(al.url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("连接 LDAP 服务失败, err=%s", err.Error())
|
||||
}
|
||||
defer lc.Close()
|
||||
|
||||
// bind 用户
|
||||
if al.config.BindPassword != "" {
|
||||
err = lc.Bind(al.config.BindUsername, al.config.BindPassword)
|
||||
} else {
|
||||
err = lc.UnauthenticatedBind(al.config.BindUsername)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("绑定 LDAP 用户失败, err=%s", err.Error())
|
||||
}
|
||||
|
||||
// 搜索下用户信息
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
al.config.BaseDn,
|
||||
ldap.ScopeWholeSubtree,
|
||||
ldap.NeverDerefAliases,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
fmt.Sprintf(al.config.AccountPattern, username),
|
||||
al.GetAttributes(),
|
||||
nil,
|
||||
)
|
||||
searchResult, err := lc.Search(searchRequest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查找 LDAP 用户失败, err=%s", err.Error())
|
||||
}
|
||||
if len(searchResult.Entries) != 1 {
|
||||
return nil, LdapUserSearchNotFoundErr
|
||||
}
|
||||
|
||||
// 验证下用户密码
|
||||
userDN := searchResult.Entries[0].DN
|
||||
err = lc.Bind(userDN, password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &AuthLoginResponse{
|
||||
GivenName: searchResult.Entries[0].GetAttributeValue(al.config.GivenNameKey),
|
||||
Email: searchResult.Entries[0].GetAttributeValue(al.config.EmailKey),
|
||||
Mobile: searchResult.Entries[0].GetAttributeValue(al.config.MobileKey),
|
||||
Phone: searchResult.Entries[0].GetAttributeValue(al.config.PhoneKey),
|
||||
Department: searchResult.Entries[0].GetAttributeValue(al.config.DepartmentKey),
|
||||
Position: searchResult.Entries[0].GetAttributeValue(al.config.PositionKey),
|
||||
Location: searchResult.Entries[0].GetAttributeValue(al.config.LocationKey),
|
||||
Im: searchResult.Entries[0].GetAttributeValue(al.config.ImKey),
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetAttributes get config attribute name
|
||||
func (al *AuthLoginLdapService) GetAttributes() []string {
|
||||
|
||||
attributes := []string{"dn"}
|
||||
confAttributes := []string{
|
||||
"dn", al.config.GivenNameKey, al.config.EmailKey,
|
||||
al.config.MobileKey, al.config.PhoneKey, al.config.DepartmentKey,
|
||||
al.config.PositionKey, al.config.LocationKey, al.config.ImKey,
|
||||
}
|
||||
for _, confAttribute := range confAttributes {
|
||||
if confAttribute == "" {
|
||||
continue
|
||||
}
|
||||
attributes = append(attributes, confAttribute)
|
||||
}
|
||||
return attributes
|
||||
}
|
||||
|
||||
// GetServiceName ldap
|
||||
func (al *AuthLoginLdapService) GetServiceName() string {
|
||||
return AuthLoginProtocolLdap
|
||||
}
|
||||
|
||||
func init() {
|
||||
// ldap://xxx
|
||||
AuthLogin.RegisterService(AuthLoginProtocolLdap, NewAuthLoginLdapService())
|
||||
// ldaps://xxx
|
||||
AuthLogin.RegisterService(AuthLoginProtocolLdaps, NewAuthLoginLdapService())
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
)
|
||||
|
||||
var DocIndexService = NewDocIndexService()
|
||||
|
||||
type DocIndex struct {
|
||||
}
|
||||
|
||||
func NewDocIndexService() *DocIndex {
|
||||
return &DocIndex{}
|
||||
}
|
||||
|
||||
func (di *DocIndex) IsUpdateDocIndex() bool {
|
||||
//fulltextSearchOpen := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyFulltextSearch, "0")
|
||||
//if fulltextSearchOpen == "1" {
|
||||
// return true
|
||||
//}
|
||||
return false
|
||||
}
|
||||
|
||||
// ForceDelDocIdIndex 强制删除索引
|
||||
func (di *DocIndex) ForceDelDocIdIndex(docId string) {
|
||||
if docId == "" {
|
||||
return
|
||||
}
|
||||
if !di.IsUpdateDocIndex() {
|
||||
return
|
||||
}
|
||||
// todo add search index
|
||||
|
||||
}
|
||||
|
||||
// UpdateDocIndex 更新单个文件的索引
|
||||
func (di *DocIndex) ForceUpdateDocIndexByDocId(docId string) error {
|
||||
if docId == "" {
|
||||
return nil
|
||||
}
|
||||
if !di.IsUpdateDocIndex() {
|
||||
return nil
|
||||
}
|
||||
doc, err := models.DocumentModel.GetDocumentByDocumentId(docId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, err = models.DocumentModel.GetDocumentContentByDocument(doc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// todo add search index
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateDocIndex 更新单个文件的索引
|
||||
func (di *DocIndex) UpdateDocIndex(doc map[string]string) {
|
||||
docId, ok := doc["document_id"]
|
||||
if !ok || docId == "" {
|
||||
return
|
||||
}
|
||||
if !di.IsUpdateDocIndex() {
|
||||
return
|
||||
}
|
||||
_, _, err := models.DocumentModel.GetDocumentContentByDocument(doc)
|
||||
if err != nil {
|
||||
logs.Error("[UpdateDocIndex] get documentId=%s content err: %s", docId, err.Error())
|
||||
return
|
||||
}
|
||||
// todo add search index
|
||||
}
|
||||
|
||||
// UpdateDocsIndex 批量更新多个文件的索引
|
||||
func (di *DocIndex) UpdateDocsIndex(docs []map[string]string) {
|
||||
if len(docs) == 0 {
|
||||
return
|
||||
}
|
||||
wait := sync.WaitGroup{}
|
||||
for _, doc := range docs {
|
||||
if len(doc) == 0 {
|
||||
continue
|
||||
}
|
||||
wait.Add(1)
|
||||
go func(doc map[string]string) {
|
||||
docId, _ := doc["document_id"]
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
logs.Error("[UpdateAllDocIndex] get documentId=%s content panic: %v", docId, e)
|
||||
}
|
||||
wait.Done()
|
||||
}()
|
||||
di.UpdateDocIndex(doc)
|
||||
}(doc)
|
||||
}
|
||||
wait.Wait()
|
||||
}
|
||||
|
||||
// UpdateAllDocIndex 更新所有的文档
|
||||
func (di *DocIndex) UpdateAllDocIndex(batchNum int) {
|
||||
if !di.IsUpdateDocIndex() {
|
||||
return
|
||||
}
|
||||
allDocs, err := models.DocumentModel.GetAllDocuments()
|
||||
if err != nil {
|
||||
logs.Error("[UpdateAllDocIndex] getAllDocuments err: %s", err.Error())
|
||||
return
|
||||
}
|
||||
batchDocs := di.getBatchDocs(allDocs, batchNum)
|
||||
for _, docs := range batchDocs {
|
||||
di.UpdateDocsIndex(docs)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取分批文档
|
||||
func (di *DocIndex) getBatchDocs(allDocs []map[string]string, n int) [][]map[string]string {
|
||||
|
||||
groupNum := len(allDocs) / n
|
||||
remainder := len(allDocs) % n
|
||||
res := [][]map[string]string{}
|
||||
if groupNum == 0 {
|
||||
res = append(res, allDocs)
|
||||
return res
|
||||
}
|
||||
for i := 0; i < groupNum; i++ {
|
||||
offset := i * n
|
||||
resItem := allDocs[offset : n+offset]
|
||||
res = append(res, resItem)
|
||||
}
|
||||
if remainder > 0 {
|
||||
res = append(res, allDocs[len(allDocs)-remainder:])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// FlushIndex 所有索引
|
||||
func (di *DocIndex) Flush() {
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var Convert = NewConvert()
|
||||
|
||||
type convert struct{}
|
||||
|
||||
func NewConvert() *convert {
|
||||
return &convert{}
|
||||
}
|
||||
|
||||
// bool 转化为字符串
|
||||
func (c *convert) BoolToString(boolValue bool) string {
|
||||
if boolValue == true {
|
||||
return "true"
|
||||
} else {
|
||||
return "false"
|
||||
}
|
||||
}
|
||||
|
||||
//bool 转化为 int
|
||||
func (c *convert) BoolToInt(boolValue bool) int {
|
||||
if boolValue == true {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
//int 转化为 bool
|
||||
func (c *convert) IntToBool(number int) bool {
|
||||
if number == 0 {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
//int 转化为字符串
|
||||
//base 范围 2-32 进制
|
||||
func (c *convert) IntToString(number int64, base int) string {
|
||||
return strconv.FormatInt(number, base)
|
||||
}
|
||||
|
||||
//string to int(10进制)
|
||||
func (c *convert) StringToInt(str string) int {
|
||||
intValue, _ := strconv.Atoi(str)
|
||||
return intValue
|
||||
}
|
||||
|
||||
// string to int64(10进制)
|
||||
func (c *convert) StringToInt64(str string) int64 {
|
||||
intValue, _ := strconv.ParseInt(str, 10, 64)
|
||||
return intValue
|
||||
}
|
||||
|
||||
// int 转化为10进制字符串 IntToString(number, 10)
|
||||
func (c *convert) IntToTenString(number int) string {
|
||||
return strconv.Itoa(number)
|
||||
}
|
||||
|
||||
// float 转化为字符串
|
||||
func (c *convert) FloatToString(f float64, fmt byte, prec, bitSize int) string {
|
||||
return strconv.FormatFloat(f, fmt, prec, bitSize)
|
||||
}
|
||||
|
||||
// 转化任何的数为 int64
|
||||
func (c *convert) ToInt64(value interface{}) (d int64, err error) {
|
||||
val := reflect.ValueOf(value)
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
d = val.Int()
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
d = int64(val.Uint())
|
||||
default:
|
||||
err = fmt.Errorf("ToInt64 need numeric not `%T`", value)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Date = NewDate()
|
||||
|
||||
type date struct{}
|
||||
|
||||
func NewDate() *date {
|
||||
return &date{}
|
||||
}
|
||||
|
||||
//格式化 unix 时间戳
|
||||
func (date *date) Format(unixTime interface{}, format string) string {
|
||||
convert := NewConvert()
|
||||
var convertTime int64
|
||||
switch unixTime.(type) {
|
||||
case string:
|
||||
convertTime = convert.StringToInt64(unixTime.(string))
|
||||
case int:
|
||||
convertTime = int64(unixTime.(int))
|
||||
case int8:
|
||||
convertTime = int64(unixTime.(int8))
|
||||
case int16:
|
||||
convertTime = int64(unixTime.(int16))
|
||||
case int32:
|
||||
convertTime = int64(unixTime.(int32))
|
||||
}
|
||||
return beego.Date(time.Unix(convertTime, 0), format)
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var Document = NewDocument("./data", "./data/markdowns")
|
||||
|
||||
const (
|
||||
Document_Default_FileName = "README"
|
||||
Document_Page_Suffix = ".md"
|
||||
)
|
||||
|
||||
const (
|
||||
Document_Type_Page = 1
|
||||
Document_Type_Dir = 2
|
||||
)
|
||||
|
||||
func NewDocument(documentAbsDir string, markdownAbsDir string) *document {
|
||||
return &document{
|
||||
DocumentAbsDir: documentAbsDir,
|
||||
MarkdownAbsDir: markdownAbsDir,
|
||||
}
|
||||
}
|
||||
|
||||
type document struct {
|
||||
DocumentAbsDir string
|
||||
MarkdownAbsDir string
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// get document page file by parentPath
|
||||
func (d *document) GetPageFileByParentPath(name string, docType int, parentPath string) (pageFile string) {
|
||||
if docType == Document_Type_Page {
|
||||
pageFile = fmt.Sprintf("%s/%s%s", parentPath, name, Document_Page_Suffix)
|
||||
} else {
|
||||
pageFile = fmt.Sprintf("%s/%s/%s%s", parentPath, name, Document_Default_FileName, Document_Page_Suffix)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//get document path by spaceName
|
||||
func (d *document) GetDefaultPageFileBySpaceName(name string) string {
|
||||
return fmt.Sprintf("%s/%s%s", name, Document_Default_FileName, Document_Page_Suffix)
|
||||
}
|
||||
|
||||
// get document abs pageFile
|
||||
func (d *document) GetAbsPageFileByPageFile(pageFile string) string {
|
||||
return d.MarkdownAbsDir + "/" + pageFile
|
||||
}
|
||||
|
||||
// get document content by pageFile
|
||||
func (d *document) GetContentByPageFile(pageFile string) (content string, err error) {
|
||||
return File.GetFileContents(d.GetAbsPageFileByPageFile(pageFile))
|
||||
}
|
||||
|
||||
// create document
|
||||
func (d *document) Create(pageFile string) error {
|
||||
if pageFile == "" {
|
||||
return nil
|
||||
}
|
||||
d.lock.Lock()
|
||||
absFilePath := d.GetAbsPageFileByPageFile(pageFile)
|
||||
absDir := filepath.Dir(absFilePath)
|
||||
err := os.MkdirAll(absDir, 0777)
|
||||
if err != nil {
|
||||
d.lock.Unlock()
|
||||
return err
|
||||
}
|
||||
d.lock.Unlock()
|
||||
return File.CreateFile(absFilePath)
|
||||
}
|
||||
|
||||
// create and write document
|
||||
func (d *document) CreateAndWrite(pageFile string, content string) error {
|
||||
if pageFile == "" {
|
||||
return nil
|
||||
}
|
||||
d.lock.Lock()
|
||||
absFilePath := d.GetAbsPageFileByPageFile(pageFile)
|
||||
absDir := filepath.Dir(absFilePath)
|
||||
err := os.MkdirAll(absDir, 0777)
|
||||
if err != nil {
|
||||
d.lock.Unlock()
|
||||
return err
|
||||
}
|
||||
d.lock.Unlock()
|
||||
return File.WriteFile(absFilePath, content)
|
||||
}
|
||||
|
||||
// replace document content
|
||||
func (d *document) Replace(pageFile string, content string) error {
|
||||
if pageFile == "" {
|
||||
return nil
|
||||
}
|
||||
d.lock.Lock()
|
||||
absFilePath := d.GetAbsPageFileByPageFile(pageFile)
|
||||
absDir := filepath.Dir(absFilePath)
|
||||
err := os.MkdirAll(absDir, 0777)
|
||||
if err != nil {
|
||||
d.lock.Unlock()
|
||||
return err
|
||||
}
|
||||
d.lock.Unlock()
|
||||
return ioutil.WriteFile(absFilePath, []byte(content), os.ModePerm)
|
||||
}
|
||||
|
||||
// update document
|
||||
func (d *document) Update(oldPageFile string, name string, content string, docType int, nameIsChange bool) (err error) {
|
||||
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
|
||||
absOldPageFile := d.GetAbsPageFileByPageFile(oldPageFile)
|
||||
|
||||
err = ioutil.WriteFile(absOldPageFile, []byte(content), os.ModePerm)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if nameIsChange {
|
||||
filePath := filepath.Dir(absOldPageFile)
|
||||
if docType == Document_Type_Page {
|
||||
err = os.Rename(absOldPageFile, filePath+"/"+name+Document_Page_Suffix)
|
||||
} else {
|
||||
err = os.Rename(filePath, filepath.Dir(filePath)+"/"+name)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *document) UpdateSpaceName(oldSpaceName string, newName string) error {
|
||||
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
|
||||
spaceOldDir := d.GetAbsPageFileByPageFile(oldSpaceName)
|
||||
spaceNewDir := d.GetAbsPageFileByPageFile(newName)
|
||||
if spaceNewDir == spaceOldDir {
|
||||
return nil
|
||||
}
|
||||
err := os.Rename(spaceOldDir, spaceNewDir)
|
||||
return err
|
||||
}
|
||||
|
||||
// delete document
|
||||
func (d *document) Delete(path string, docType int) error {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
|
||||
absPageFile := d.GetAbsPageFileByPageFile(path)
|
||||
|
||||
ok, _ := File.PathIsExists(absPageFile)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if docType == Document_Type_Page {
|
||||
return os.Remove(absPageFile)
|
||||
}
|
||||
|
||||
return os.RemoveAll(filepath.Dir(absPageFile))
|
||||
}
|
||||
|
||||
func (d *document) DeleteSpace(name string) error {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
|
||||
absSpaceDir := d.GetAbsPageFileByPageFile(name)
|
||||
|
||||
ok, _ := File.PathIsExists(absSpaceDir)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return os.RemoveAll(absSpaceDir)
|
||||
}
|
||||
|
||||
func (d *document) Move(movePath string, targetPath string, docType int) error {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
|
||||
absOldPageFile := d.GetAbsPageFileByPageFile(movePath)
|
||||
absTargetPageFile := d.GetAbsPageFileByPageFile(targetPath)
|
||||
|
||||
if docType == Document_Type_Page {
|
||||
return os.Rename(absOldPageFile, absTargetPageFile)
|
||||
}
|
||||
return os.Rename(filepath.Dir(absOldPageFile), filepath.Dir(absTargetPageFile))
|
||||
}
|
||||
|
||||
// delete document attachment
|
||||
func (d *document) DeleteAttachment(attachments []map[string]string) error {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
|
||||
if len(attachments) == 0 {
|
||||
return nil
|
||||
}
|
||||
// delete attachment file
|
||||
for _, attachment := range attachments {
|
||||
if len(attachment) == 0 || attachment["path"] == "" {
|
||||
continue
|
||||
}
|
||||
file := filepath.Join(d.DocumentAbsDir, attachment["path"])
|
||||
_ = os.Remove(file)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/phachon/mm-wiki/global"
|
||||
"gopkg.in/gomail.v2"
|
||||
"gopkg.in/russross/blackfriday.v2"
|
||||
"net/smtp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Email = NewEmail()
|
||||
|
||||
type email struct {
|
||||
}
|
||||
|
||||
func NewEmail() *email {
|
||||
return &email{}
|
||||
}
|
||||
|
||||
func (e *email) Send(emailConf map[string]string, toList []string, subject string, body string) error {
|
||||
|
||||
from := emailConf["sender_address"]
|
||||
if emailConf["sender_name"] != "" {
|
||||
from = fmt.Sprintf("%s <%s>", emailConf["sender_name"], emailConf["sender_address"])
|
||||
}
|
||||
var tt []*gomail.Message
|
||||
for _, toAddress := range toList {
|
||||
m := gomail.NewMessage()
|
||||
m.SetHeader("From", from)
|
||||
m.SetHeader("To", toAddress)
|
||||
m.SetHeader("Subject", emailConf["sender_title_prefix"]+subject)
|
||||
m.SetBody("text/html", body)
|
||||
tt = append(tt, m)
|
||||
}
|
||||
portInt, _ := strconv.Atoi(emailConf["port"])
|
||||
d := gomail.NewDialer(emailConf["host"], portInt, emailConf["username"], emailConf["password"])
|
||||
if emailConf["is_ssl"] == "1" {
|
||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
return d.DialAndSend(tt...)
|
||||
}
|
||||
|
||||
func (e *email) SendByEmail(email map[string]string, to []string, subject string, body string, contentType string) error {
|
||||
|
||||
userEmail := email["sender_address"]
|
||||
addr := fmt.Sprintf("%s:%s", email["host"], email["port"])
|
||||
auth := smtp.PlainAuth("", userEmail, email["password"], email["host"])
|
||||
user := email["username"]
|
||||
nickname := email["sender_name"]
|
||||
subject = email["sender_title_prefix"] + subject
|
||||
|
||||
msg := fmt.Sprintf("To: %s \r\nFrom: %s <%s>\r\nSubject: %s \r\nContent-Type: text/%s; charset=UTF-8\r\n\r\n%s",
|
||||
strings.Join(to, ","), nickname, user, subject, contentType, body)
|
||||
|
||||
err := smtp.SendMail(addr, auth, user, to, []byte(msg))
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *email) MakeDocumentHtmlBody(document map[string]string, view string) (body string, err error) {
|
||||
viewTemplate, err := File.GetFileContents(view)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body = strings.Replace(viewTemplate, "{{.now_time}}", beego.Date(time.Now(), "Y-m-d H:i:s"), 1)
|
||||
body = strings.Replace(body, "{{.document_name}}", document["name"], 1)
|
||||
body = strings.Replace(body, "{{.username}}", document["username"], 1)
|
||||
body = strings.Replace(body, "{{.update_time}}", Date.Format(document["update_time"], "Y-m-d H:i:s"), 1)
|
||||
body = strings.Replace(body, "{{.comment}}", document["comment"], 1)
|
||||
body = strings.Replace(body, "{{.document_url}}", document["url"], 1)
|
||||
body = strings.Replace(body, "{{.copyright}}", global.SYSTEM_COPYRIGHT, 1)
|
||||
|
||||
content := string(blackfriday.Run([]byte(document["content"])))
|
||||
body = strings.Replace(body, "{{.document_content}}", content, 1)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
var Encrypt = NewEncrypt()
|
||||
|
||||
const (
|
||||
BASE_64_TABLE = "1234567890poiuytreqwasdfghjklmnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM-_"
|
||||
)
|
||||
|
||||
type encrypt struct{}
|
||||
|
||||
func NewEncrypt() *encrypt {
|
||||
return &encrypt{}
|
||||
}
|
||||
|
||||
//base64 加密
|
||||
func (encrypt *encrypt) Base64Encode(str string) string {
|
||||
var coder = base64.NewEncoding(BASE_64_TABLE)
|
||||
var src []byte = []byte(str)
|
||||
return string([]byte(coder.EncodeToString(src)))
|
||||
}
|
||||
|
||||
//base64 加密
|
||||
func (encrypt *encrypt) Base64EncodeBytes(bytes []byte) []byte {
|
||||
var coder = base64.NewEncoding(BASE_64_TABLE)
|
||||
return []byte(coder.EncodeToString(bytes))
|
||||
}
|
||||
|
||||
//base64 解密
|
||||
func (encrypt *encrypt) Base64Decode(str string) (string, error) {
|
||||
var src []byte = []byte(str)
|
||||
var coder = base64.NewEncoding(BASE_64_TABLE)
|
||||
by, err := coder.DecodeString(string(src))
|
||||
return string(by), err
|
||||
}
|
||||
|
||||
//base64 解密
|
||||
func (encrypt *encrypt) Base64DecodeBytes(str string) ([]byte, error) {
|
||||
var coder = base64.NewEncoding(BASE_64_TABLE)
|
||||
return coder.DecodeString(str)
|
||||
}
|
||||
|
||||
//md5加密
|
||||
func (encrypt *encrypt) Md5Encode(str string) string {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(str))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var File = NewFile()
|
||||
|
||||
func NewFile() *file {
|
||||
return &file{}
|
||||
}
|
||||
|
||||
type file struct {
|
||||
}
|
||||
|
||||
// get file contents
|
||||
func (f *file) GetFileContents(filePath string) (content string, err error) {
|
||||
defer func(err *error) {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
*err = fmt.Errorf("%s", e)
|
||||
}
|
||||
}(&err)
|
||||
bytes, err := ioutil.ReadFile(filePath)
|
||||
content = string(bytes)
|
||||
return
|
||||
}
|
||||
|
||||
// file or path is exists
|
||||
func (f *file) PathIsExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// path is empty
|
||||
func (f *file) PathIsEmpty(path string) bool {
|
||||
fs, e := filepath.Glob(filepath.Join(path, "*"))
|
||||
if e != nil {
|
||||
return false
|
||||
}
|
||||
if len(fs) > 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// is write permission
|
||||
func (f *file) IsWritable(filename string) error {
|
||||
file, err := os.OpenFile(filename, os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
return errors.New("Error: Write permission denied.")
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
file.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// is read permission
|
||||
func (f *file) IsReadable(filename string) error {
|
||||
file, err := os.OpenFile(filename, os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
return errors.New("Error: Read permission denied.")
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
file.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// is read and write permission
|
||||
func (f *file) IsWriterReadable(file string) error {
|
||||
err := f.IsWritable(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = f.IsReadable(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// read file data
|
||||
func (f *file) ReadAll(path string) (data string, err error) {
|
||||
fi, err := os.Open(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
fd, err := ioutil.ReadAll(fi)
|
||||
return string(fd), nil
|
||||
}
|
||||
|
||||
// write file
|
||||
func (f *file) WriteFile(filename string, data string) (err error) {
|
||||
var dataByte = []byte(data)
|
||||
err = ioutil.WriteFile(filename, dataByte, 0666)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// create file
|
||||
func (f *file) CreateFile(filename string) error {
|
||||
newFile, err := os.Create(filename)
|
||||
defer newFile.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// get dir all files
|
||||
func (f *file) WalkDir(dirPth, suffix string) (files []string, err error) {
|
||||
files = make([]string, 0, 30)
|
||||
suffix = strings.ToUpper(suffix)
|
||||
err = filepath.Walk(dirPth, func(filename string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) {
|
||||
files = append(files, filename)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return files, err
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package utils
|
||||
|
||||
import "strconv"
|
||||
|
||||
func MapInterface2String(inputData map[string]interface{}) map[string]string {
|
||||
outputData := map[string]string{}
|
||||
for key, value := range inputData {
|
||||
switch value.(type) {
|
||||
case string:
|
||||
outputData[key] = value.(string)
|
||||
case int:
|
||||
tmp := value.(int)
|
||||
outputData[key] = strconv.Itoa(tmp)
|
||||
case int64:
|
||||
tmp := value.(int64)
|
||||
outputData[key] = strconv.FormatInt(tmp, 10)
|
||||
}
|
||||
}
|
||||
return outputData
|
||||
}
|
||||
|
||||
func MapString2Interface(fromMaps []map[string]string) (toMaps []map[string]interface{}) {
|
||||
var dest []map[string]interface{}
|
||||
|
||||
for fromIndex := range fromMaps {
|
||||
fromMap := fromMaps[fromIndex]
|
||||
toMap := make(map[string]interface{})
|
||||
|
||||
for key, value := range fromMap {
|
||||
toMap[key] = interface{}(value)
|
||||
}
|
||||
|
||||
dest = append(dest, toMap)
|
||||
}
|
||||
|
||||
return dest
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Misc = NewMisc()
|
||||
|
||||
type misc struct{}
|
||||
|
||||
func NewMisc() *misc {
|
||||
return &misc{}
|
||||
}
|
||||
|
||||
// get map default
|
||||
func (m *misc) GetMapDefault(mapValue map[string]interface{}, key string, def interface{}) interface{} {
|
||||
value, ok := mapValue[key]
|
||||
if ok {
|
||||
return value
|
||||
} else {
|
||||
return def
|
||||
}
|
||||
}
|
||||
|
||||
// rand string
|
||||
func (m *misc) RandString(strlen int) string {
|
||||
codes := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
codeLen := len(codes)
|
||||
data := make([]byte, strlen)
|
||||
rand.Seed(time.Now().UnixNano() + rand.Int63() + rand.Int63() + rand.Int63() + rand.Int63())
|
||||
for i := 0; i < strlen; i++ {
|
||||
idx := rand.Intn(codeLen)
|
||||
data[i] = byte(codes[idx])
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// rand int
|
||||
func (m *misc) RandInt(strLen int) string {
|
||||
codes := "0123456789"
|
||||
codeLen := len(codes)
|
||||
data := make([]byte, strLen)
|
||||
rand.Seed(time.Now().UnixNano() + rand.Int63() + rand.Int63() + rand.Int63() + rand.Int63())
|
||||
for i := 0; i < strLen; i++ {
|
||||
idx := rand.Intn(codeLen)
|
||||
data[i] = byte(codes[idx])
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// get local ip
|
||||
func (m *misc) GetLocalIp() string {
|
||||
addrSlice, err := net.InterfaceAddrs()
|
||||
if nil != err {
|
||||
return "localhost"
|
||||
}
|
||||
for _, addr := range addrSlice {
|
||||
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||
if nil != ipnet.IP.To4() {
|
||||
return ipnet.IP.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
return "localhost"
|
||||
}
|
||||
|
||||
// 分页方法
|
||||
// total: 一共多少记录
|
||||
// page: 当前是第几页
|
||||
// pagesize: 每页多少
|
||||
// url: url里面的{page}会被替换成页码
|
||||
// args:
|
||||
// order 分页条的组成,是一个数组,可以按着1-6的序号,选择分页条组成部分和每个部分的顺序
|
||||
// a_count 分页条中a页码链接的总数量,不包含当前页的a标签,默认10个。
|
||||
//
|
||||
func (m *misc) Page(total, page, pagesize int, url string, args ...interface{}) string {
|
||||
order := []int{1, 2, 3, 4, 5, 6}
|
||||
a_count := 10
|
||||
if len(args) >= 1 {
|
||||
order = args[0].([]int)
|
||||
}
|
||||
if len(args) >= 2 {
|
||||
a_count = args[1].(int)
|
||||
}
|
||||
a_num := a_count
|
||||
first := "首页"
|
||||
last := "尾页"
|
||||
pre := "上页"
|
||||
next := "下页"
|
||||
if a_num%2 == 0 {
|
||||
a_num++
|
||||
}
|
||||
pages := int(math.Ceil(float64(total) / float64(pagesize)))
|
||||
curpage := page
|
||||
if curpage > pages || curpage <= 0 {
|
||||
curpage = 1
|
||||
}
|
||||
body := `<span class="page_body">`
|
||||
prefix := ""
|
||||
subfix := ""
|
||||
start := curpage - ((a_num - 1) / 2)
|
||||
end := curpage + ((a_num - 1) / 2)
|
||||
if start <= 0 {
|
||||
start = 1
|
||||
}
|
||||
if end > pages {
|
||||
end = pages
|
||||
}
|
||||
if pages >= a_num {
|
||||
if curpage <= (a_num-1)/2 {
|
||||
end = a_num
|
||||
}
|
||||
if end-curpage <= (a_num-1)/2 {
|
||||
start -= int(math.Floor(float64(a_num)/float64(2))) - (end - curpage)
|
||||
}
|
||||
}
|
||||
for i := start; i <= end; i++ {
|
||||
if i == curpage {
|
||||
body += fmt.Sprintf(`<a class="page_cur_page" href="javascript:void(0);"><b>%d</b></a>`, i)
|
||||
} else {
|
||||
body += fmt.Sprintf(`<a href="%s">%d</a>`, strings.Replace(url, "{page}", fmt.Sprintf("%d", i), 1), i)
|
||||
|
||||
}
|
||||
}
|
||||
body += "</span>"
|
||||
if curpage > 1 {
|
||||
prefix = fmt.Sprintf(`<span class="page_bar_prefix"><a href="%s">%s</a><a href="%s">%s</a></span>`, strings.Replace(url, "{page}", fmt.Sprintf("%d", 1), 1), first, strings.Replace(url, "{page}", fmt.Sprintf("%d", curpage-1), 1), pre)
|
||||
}
|
||||
if curpage != pages {
|
||||
subfix = fmt.Sprintf(`<span class="page_bar_subfix"><a href="%s">%s</a><a href="%s">%s</a></span>`, strings.Replace(url, "{page}", fmt.Sprintf("%d", curpage+1), 1), next, strings.Replace(url, "{page}", fmt.Sprintf("%d", pages), 1), last)
|
||||
}
|
||||
info := fmt.Sprintf(`<span class="page_cur">第%d/%d页</span>`, curpage, pages)
|
||||
id := fmt.Sprintf("gsd09fhas9d%d%d%d", rand.Intn(1000), rand.Intn(1000), rand.Intn(1000))
|
||||
gostr := fmt.Sprintf(`<script>function ekup(){if(event.keyCode==13){clkyup();}}function clkyup(){var num=document.getElementById('%s').value;if(!/^\d+$/.test(num)||num<=0||num>%d){alert('请输入正确页码!');return;};location='%s'.replace(/\{page\}/,document.getElementById('%s').value);}</script><span class="page_input_num"><input onkeyup="ekup()" type="text" id="%s" style="width:40px;vertical-align:text-baseline;padding:0 2px;font-size:10px;border:1px solid gray;"/></span><span class="page_btn_go" onclick="clkyup();" style="cursor:pointer;">转到</span>`, id, pages, url, id, id)
|
||||
totalstr := fmt.Sprintf(`<span class="page_total">共%d条</span>`, total)
|
||||
pagenation := []string{totalstr, info, prefix, body, subfix, gostr}
|
||||
output := []string{}
|
||||
for _, v := range order {
|
||||
if v-1 < len(pagenation) && v-1 >= 0 {
|
||||
output = append(output, pagenation[v-1])
|
||||
}
|
||||
}
|
||||
if pages > 1 {
|
||||
return strings.Join(output, "")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 获取字符串子串的位置
|
||||
func (m *misc) GetStrUnicodeIndex(str string, substr string) int {
|
||||
// 子串在字符串的字节位置
|
||||
result := strings.Index(str, substr)
|
||||
if result >= 0 {
|
||||
return m.GetStrUnicodeIndexByByteIndex(str, result)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// 根据字符串字节位置获取字符串位置
|
||||
func (m *misc) GetStrUnicodeIndexByByteIndex(str string, subStrByteIndex int) int {
|
||||
if subStrByteIndex > len(str)-1 {
|
||||
return -1
|
||||
}
|
||||
// 获得子串之前的字符串并转换成[]byte
|
||||
prefix := []byte(str)[0:subStrByteIndex]
|
||||
// 将子串之前的字符串转换成[]rune
|
||||
rs := []rune(string(prefix))
|
||||
// 获得子串之前的字符串的长度,便是子串在字符串的字符位置
|
||||
result := len(rs)
|
||||
return result
|
||||
}
|
||||
|
||||
// 截取包含子字符串的一段字符串,前后截取
|
||||
func (m *misc) SubStrUnicode(str string, subStr string, preLen int, sufLen int) string {
|
||||
subStrRune := []rune(subStr)
|
||||
strRune := []rune(str)
|
||||
count := len(strRune)
|
||||
subStrUnicodeIndex := m.GetStrUnicodeIndex(str, subStr)
|
||||
startIndex := 0
|
||||
endIndex := count - 1
|
||||
if subStrUnicodeIndex-preLen > 0 {
|
||||
startIndex = subStrUnicodeIndex - preLen
|
||||
}
|
||||
if subStrUnicodeIndex+len(subStrRune)+sufLen < count-1 {
|
||||
endIndex = subStrUnicodeIndex + len(subStrRune) + sufLen
|
||||
}
|
||||
return string(strRune[startIndex:endIndex])
|
||||
}
|
||||
|
||||
// 截取包含子字符串的一段字符串,前后截取
|
||||
// subStrIndex 已只子串的字节位置
|
||||
func (m *misc) SubStrUnicodeBySubStrIndex(str string, subStr string, subStrIndex int, preLen int, sufLen int) string {
|
||||
subStrRune := []rune(subStr)
|
||||
strRune := []rune(str)
|
||||
count := len(strRune)
|
||||
subStrUnicodeIndex := m.GetStrUnicodeIndexByByteIndex(str, subStrIndex)
|
||||
startIndex := 0
|
||||
endIndex := count - 1
|
||||
if subStrUnicodeIndex-preLen > 0 {
|
||||
startIndex = subStrUnicodeIndex - preLen
|
||||
}
|
||||
if subStrUnicodeIndex+len(subStrRune)+sufLen < count-1 {
|
||||
endIndex = subStrUnicodeIndex + len(subStrRune) + sufLen
|
||||
}
|
||||
return string(strRune[startIndex:endIndex])
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// Copyright 2013 wetalk authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 默认的每页条数的选择范围
|
||||
var defaultPerPageNumsSelect = []int{10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 100}
|
||||
|
||||
type Paginator struct {
|
||||
Request *http.Request
|
||||
PerPageNums int
|
||||
PerPageNumsSelect []int
|
||||
MaxPages int
|
||||
nums int64
|
||||
pageRange []int
|
||||
pageNums int
|
||||
page int
|
||||
pageParamName string
|
||||
perPageNumParamName string
|
||||
}
|
||||
|
||||
func (p *Paginator) PageNums() int {
|
||||
if p.pageNums != 0 {
|
||||
return p.pageNums
|
||||
}
|
||||
pageNums := math.Ceil(float64(p.nums) / float64(p.PerPageNums))
|
||||
if p.MaxPages > 0 {
|
||||
pageNums = math.Min(pageNums, float64(p.MaxPages))
|
||||
}
|
||||
p.pageNums = int(pageNums)
|
||||
return p.pageNums
|
||||
}
|
||||
|
||||
func (p *Paginator) Nums() int64 {
|
||||
return p.nums
|
||||
}
|
||||
|
||||
func (p *Paginator) SetNums(nums interface{}) {
|
||||
p.nums, _ = NewConvert().ToInt64(nums)
|
||||
}
|
||||
|
||||
func (p *Paginator) SetPrePageNumsSelect(selectNums []int) {
|
||||
p.PerPageNumsSelect = selectNums
|
||||
}
|
||||
|
||||
func (p *Paginator) SetPerPageNums(perPageNums int) {
|
||||
|
||||
if perPageNums < p.PerPageNumsSelect[0] {
|
||||
perPageNums = p.PerPageNumsSelect[0]
|
||||
}
|
||||
if perPageNums > p.PerPageNumsSelect[len(p.PerPageNumsSelect)-1] {
|
||||
perPageNums = p.PerPageNumsSelect[len(p.PerPageNumsSelect)-1]
|
||||
}
|
||||
p.PerPageNums = perPageNums
|
||||
}
|
||||
|
||||
func (p *Paginator) Page() int {
|
||||
if p.page != 0 {
|
||||
return p.page
|
||||
}
|
||||
if p.Request.Form == nil {
|
||||
p.Request.ParseForm()
|
||||
}
|
||||
p.page, _ = strconv.Atoi(p.Request.Form.Get(p.pageParamName))
|
||||
if p.page > p.PageNums() {
|
||||
p.page = p.PageNums()
|
||||
}
|
||||
if p.page <= 0 {
|
||||
p.page = 1
|
||||
}
|
||||
return p.page
|
||||
}
|
||||
|
||||
func (p *Paginator) Pages() []int {
|
||||
if p.pageRange == nil && p.nums > 0 {
|
||||
var pages []int
|
||||
pageNums := p.PageNums()
|
||||
page := p.Page()
|
||||
switch {
|
||||
case page >= pageNums-4 && pageNums > 9:
|
||||
start := pageNums - 9 + 1
|
||||
pages = make([]int, 9)
|
||||
for i, _ := range pages {
|
||||
pages[i] = start + i
|
||||
}
|
||||
case page >= 5 && pageNums > 9:
|
||||
start := page - 5 + 1
|
||||
pages = make([]int, int(math.Min(9, float64(page+4+1))))
|
||||
for i, _ := range pages {
|
||||
pages[i] = start + i
|
||||
}
|
||||
default:
|
||||
pages = make([]int, int(math.Min(9, float64(pageNums))))
|
||||
for i, _ := range pages {
|
||||
pages[i] = i + 1
|
||||
}
|
||||
}
|
||||
p.pageRange = pages
|
||||
}
|
||||
return p.pageRange
|
||||
}
|
||||
|
||||
func (p *Paginator) PageLink(page int) string {
|
||||
link, _ := url.ParseRequestURI(p.Request.RequestURI)
|
||||
values := link.Query()
|
||||
if page == 1 {
|
||||
values.Del(p.pageParamName)
|
||||
} else {
|
||||
values.Set(p.pageParamName, strconv.Itoa(page))
|
||||
}
|
||||
|
||||
if p.PerPageNums < p.PerPageNumsSelect[0] {
|
||||
p.PerPageNums = p.PerPageNumsSelect[0]
|
||||
}
|
||||
if p.PerPageNums > p.PerPageNumsSelect[len(p.PerPageNumsSelect)-1] {
|
||||
p.PerPageNums = p.PerPageNumsSelect[len(p.PerPageNumsSelect)-1]
|
||||
}
|
||||
values.Set(p.perPageNumParamName, strconv.Itoa(p.PerPageNums))
|
||||
link.RawQuery = values.Encode()
|
||||
return link.String()
|
||||
}
|
||||
|
||||
func (p *Paginator) PrePageNumLink(perPageNum int) string {
|
||||
link, _ := url.ParseRequestURI(p.Request.RequestURI)
|
||||
values := link.Query()
|
||||
|
||||
if perPageNum < p.PerPageNumsSelect[0] {
|
||||
perPageNum = p.PerPageNumsSelect[0]
|
||||
}
|
||||
if perPageNum > p.PerPageNumsSelect[len(p.PerPageNumsSelect)-1] {
|
||||
perPageNum = p.PerPageNumsSelect[len(p.PerPageNumsSelect)-1]
|
||||
}
|
||||
values.Set(p.perPageNumParamName, strconv.Itoa(perPageNum))
|
||||
link.RawQuery = values.Encode()
|
||||
return link.String()
|
||||
}
|
||||
|
||||
func (p *Paginator) PageLinkPrev() (link string) {
|
||||
if p.HasPrev() {
|
||||
link = p.PageLink(p.Page() - 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Paginator) PageLinkNext() (link string) {
|
||||
if p.HasNext() {
|
||||
link = p.PageLink(p.Page() + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Paginator) PageLinkFirst() (link string) {
|
||||
return p.PageLink(1)
|
||||
}
|
||||
|
||||
func (p *Paginator) PageLinkLast() (link string) {
|
||||
return p.PageLink(p.PageNums())
|
||||
}
|
||||
|
||||
func (p *Paginator) HasPrev() bool {
|
||||
return p.Page() > 1
|
||||
}
|
||||
|
||||
func (p *Paginator) HasNext() bool {
|
||||
return p.Page() < p.PageNums()
|
||||
}
|
||||
|
||||
func (p *Paginator) IsActive(page int) bool {
|
||||
return p.Page() == page
|
||||
}
|
||||
|
||||
func (p *Paginator) Offset() int {
|
||||
return (p.Page() - 1) * p.PerPageNums
|
||||
}
|
||||
|
||||
func (p *Paginator) HasPages() bool {
|
||||
return p.PageNums() > 1
|
||||
}
|
||||
|
||||
func NewPaginator(req *http.Request, per int, nums interface{}) *Paginator {
|
||||
p := Paginator{}
|
||||
p.Request = req
|
||||
// 翻页参数名,默认为 page
|
||||
p.pageParamName = "page"
|
||||
// 每页条数参数名,默认为 "number"
|
||||
p.perPageNumParamName = "number"
|
||||
if per <= 0 {
|
||||
per = 10
|
||||
}
|
||||
p.SetPrePageNumsSelect(defaultPerPageNumsSelect)
|
||||
p.SetPerPageNums(per)
|
||||
p.SetNums(nums)
|
||||
return &p
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var Request = NewRequest()
|
||||
|
||||
func NewRequest() *request {
|
||||
return &request{}
|
||||
}
|
||||
|
||||
type request struct {
|
||||
}
|
||||
|
||||
// http get request
|
||||
func (r *request) HttpGet(queryUrl string, queryValues map[string]string, headerValues map[string]string) (body []byte, code int, err error) {
|
||||
|
||||
req, err := http.NewRequest("GET", r.QueryBuilder(queryUrl, queryValues), nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if (headerValues != nil) && (len(headerValues) > 0) {
|
||||
for key, value := range headerValues {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
code = resp.StatusCode
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyByte, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return bodyByte, code, nil
|
||||
}
|
||||
|
||||
// http post request
|
||||
func (r *request) HttpPost(queryUrl string, queryValues map[string]string, headerValues map[string]string) (body []byte, code int, err error) {
|
||||
if !strings.Contains(queryUrl, "?") {
|
||||
queryUrl += "?"
|
||||
}
|
||||
queryString := ""
|
||||
for queryKey, queryValue := range queryValues {
|
||||
queryString = queryString + "&" + queryKey + "=" + url.QueryEscape(queryValue)
|
||||
}
|
||||
queryString = strings.Replace(queryString, "&", "", 1)
|
||||
|
||||
req, err := http.NewRequest("POST", queryUrl, strings.NewReader(queryString))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
if (headerValues != nil) && (len(headerValues) > 0) {
|
||||
for key, value := range headerValues {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
}
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
code = resp.StatusCode
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyByte, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return bodyByte, code, nil
|
||||
}
|
||||
|
||||
// build query params
|
||||
func (r *request) QueryBuilder(queryUrl string, queryValues map[string]string) string {
|
||||
if !strings.Contains(queryUrl, "?") {
|
||||
queryUrl += "?"
|
||||
}
|
||||
|
||||
queryString := ""
|
||||
for queryKey, queryValue := range queryValues {
|
||||
queryString = queryString + "&" + queryKey + "=" + url.QueryEscape(queryValue)
|
||||
}
|
||||
queryString = strings.Replace(queryString, "&", "", 1)
|
||||
queryUrl += queryString
|
||||
|
||||
return queryUrl
|
||||
}
|
||||
|
||||
// parse params(name=nick&pass=123)
|
||||
func (r *request) ParseString(params string) map[string]string {
|
||||
|
||||
paramsMap := map[string]string{}
|
||||
for _, param := range strings.Split(params, "&") {
|
||||
if !strings.Contains(param, "=") {
|
||||
continue
|
||||
}
|
||||
paramList := strings.Split(param, "=")
|
||||
paramsMap[paramList[0]] = paramList[1]
|
||||
}
|
||||
return paramsMap
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// version compare
|
||||
// version example: v0.1.1
|
||||
|
||||
var (
|
||||
defaultPrefix = "v"
|
||||
VersionCompare = NewVersionCompare(defaultPrefix)
|
||||
)
|
||||
|
||||
// struct
|
||||
type versionCompare struct {
|
||||
prefix string
|
||||
}
|
||||
|
||||
// new versionCompare
|
||||
func NewVersionCompare(prefix string) *versionCompare {
|
||||
return &versionCompare{
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
// version1 == version2
|
||||
func (vc *versionCompare) Eq(version1 string, version2 string) bool {
|
||||
return version1 == version2
|
||||
}
|
||||
|
||||
// version1 != version2
|
||||
func (vc *versionCompare) Neq(version1 string, version2 string) bool {
|
||||
return version1 != version2
|
||||
}
|
||||
|
||||
// version1 > version2
|
||||
func (vc *versionCompare) Gt(version1 string, version2 string) bool {
|
||||
v1Number := vc.ConvertIntList(version1)
|
||||
v2Number := vc.ConvertIntList(version2)
|
||||
for i, v := range v1Number {
|
||||
if v > v2Number[i] {
|
||||
return true
|
||||
}
|
||||
if v == v2Number[i] {
|
||||
continue
|
||||
}
|
||||
if v < v2Number[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// version1 < version2
|
||||
func (vc *versionCompare) Lt(version1 string, version2 string) bool {
|
||||
return vc.Gt(version2, version1)
|
||||
}
|
||||
|
||||
// version1 >= version2
|
||||
func (vc *versionCompare) Gte(version1 string, version2 string) bool {
|
||||
v1Number := vc.ConvertIntList(version1)
|
||||
v2Number := vc.ConvertIntList(version2)
|
||||
for i, v := range v1Number {
|
||||
if v > v2Number[i] {
|
||||
return true
|
||||
}
|
||||
if v == v2Number[i] {
|
||||
continue
|
||||
}
|
||||
if v < v2Number[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// version1 <= version2
|
||||
func (vc *versionCompare) Lte(version1 string, version2 string) bool {
|
||||
return vc.Gte(version2, version1)
|
||||
}
|
||||
|
||||
// version string convert int list
|
||||
func (vc *versionCompare) ConvertIntList(version string) []int {
|
||||
var realVersion = version
|
||||
if version[0:len(vc.prefix)] == vc.prefix {
|
||||
realVersion = version[len(vc.prefix):]
|
||||
}
|
||||
versionList := strings.Split(realVersion, ".")
|
||||
var l = make([]int, len(versionList))
|
||||
for i, v := range versionList {
|
||||
intValue, _ := strconv.Atoi(v)
|
||||
l[i] = intValue
|
||||
}
|
||||
return l
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewVersionCompare(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestVersionCompare_ConvertIntList(t *testing.T) {
|
||||
vc := NewVersionCompare("v")
|
||||
l := vc.ConvertIntList("v3.25.10")
|
||||
fmt.Println(l)
|
||||
}
|
||||
|
||||
func TestVersionCompare_Eq(t *testing.T) {
|
||||
vc := NewVersionCompare("v")
|
||||
if vc.Eq("v3.25.10", "v1.10.9") {
|
||||
t.Fail()
|
||||
}
|
||||
if !vc.Eq("v1.10.9", "v1.10.9") {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionCompare_Neq(t *testing.T) {
|
||||
vc := NewVersionCompare("v")
|
||||
if !vc.Neq("v3.25.10", "v1.10.9") {
|
||||
t.Fail()
|
||||
}
|
||||
if vc.Neq("v1.10.9", "v1.10.9") {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionCompare_Gt(t *testing.T) {
|
||||
vc := NewVersionCompare("v")
|
||||
if !vc.Gt("v3.25.10", "v1.10.9") {
|
||||
t.Fatal()
|
||||
}
|
||||
if !vc.Gt("v3.25.10", "v3.10.9") {
|
||||
t.Fatal()
|
||||
}
|
||||
if !vc.Gt("v3.25.10", "v3.25.9") {
|
||||
t.Fatal()
|
||||
}
|
||||
if vc.Gt("v3.25.10", "v3.25.10") {
|
||||
t.Fatal()
|
||||
}
|
||||
if vc.Gt("v3.25.10", "v3.75.10") {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionCompare_Gte(t *testing.T) {
|
||||
vc := NewVersionCompare("v")
|
||||
if !vc.Gte("v3.25.10", "v1.10.9") {
|
||||
t.Fatal()
|
||||
}
|
||||
if !vc.Gte("v3.25.10", "v3.10.9") {
|
||||
t.Fatal()
|
||||
}
|
||||
if !vc.Gte("v3.25.10", "v3.25.9") {
|
||||
t.Fatal()
|
||||
}
|
||||
if !vc.Gte("v3.25.10", "v3.25.10") {
|
||||
t.Fatal()
|
||||
}
|
||||
if vc.Gte("v3.25.10", "v3.75.10") {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var Zipx = NewZipx()
|
||||
|
||||
type zipx struct {
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func NewZipx() *zipx {
|
||||
return &zipx{}
|
||||
}
|
||||
|
||||
type CompressFileInfo struct {
|
||||
File string
|
||||
PrefixPath string
|
||||
osFile *os.File
|
||||
}
|
||||
|
||||
func (z *zipx) PackFile(files []*CompressFileInfo, dest string) error {
|
||||
|
||||
z.lock.Lock()
|
||||
defer z.lock.Unlock()
|
||||
|
||||
// create dest file
|
||||
destDir := filepath.Dir(dest)
|
||||
err := os.RemoveAll(destDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.MkdirAll(destDir, 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer d.Close()
|
||||
|
||||
// file handle
|
||||
for _, f := range files {
|
||||
f3, err := os.Open(f.File)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
f.osFile = f3
|
||||
}
|
||||
defer func() {
|
||||
for _, f := range files {
|
||||
if f.osFile == nil {
|
||||
continue
|
||||
}
|
||||
_ = f.osFile.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// zip writer
|
||||
w := zip.NewWriter(d)
|
||||
defer w.Close()
|
||||
for _, file := range files {
|
||||
err := z.compress(file.osFile, file.PrefixPath, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *zipx) Compress(files []*os.File, dest string) error {
|
||||
d, _ := os.Create(dest)
|
||||
defer d.Close()
|
||||
w := zip.NewWriter(d)
|
||||
defer w.Close()
|
||||
for _, file := range files {
|
||||
err := z.compress(file, "images/1/4", w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *zipx) compress(file *os.File, prefix string, zw *zip.Writer) error {
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
prefix = prefix + "/" + info.Name()
|
||||
fileInfos, err := file.Readdir(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, fi := range fileInfos {
|
||||
f, err := os.Open(file.Name() + "/" + fi.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = z.compress(f, prefix, zw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
header.Name = prefix + "/" + header.Name
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writer, err := zw.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(writer, file)
|
||||
file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//解压
|
||||
func (z *zipx) DeCompress(zipFile, dest string) error {
|
||||
reader, err := zip.OpenReader(zipFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer reader.Close()
|
||||
for _, file := range reader.File {
|
||||
rc, err := file.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
filename := dest + file.Name
|
||||
err = os.MkdirAll(z.getDir(filename), 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Close()
|
||||
_, err = io.Copy(w, rc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Close()
|
||||
rc.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *zipx) getDir(path string) string {
|
||||
return z.subString(path, 0, strings.LastIndex(path, "/"))
|
||||
}
|
||||
|
||||
func (z *zipx) subString(str string, start, end int) string {
|
||||
rs := []rune(str)
|
||||
length := len(rs)
|
||||
|
||||
if start < 0 || start > length {
|
||||
panic("start is wrong")
|
||||
}
|
||||
|
||||
if end < start || end > length {
|
||||
panic("end is wrong")
|
||||
}
|
||||
|
||||
return string(rs[start:end])
|
||||
}
|
||||
|
||||
// srcFile could be a single file or a directory
|
||||
func (z *zipx) Zip(srcFile string, destZip string) error {
|
||||
zipfile, err := os.Create(destZip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipfile.Close()
|
||||
|
||||
archive := zip.NewWriter(zipfile)
|
||||
defer archive.Close()
|
||||
|
||||
_ = filepath.Walk(srcFile, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name = strings.TrimPrefix(path, filepath.Dir(srcFile)+"/")
|
||||
// header.Name = path
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
|
||||
writer, err := archive.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(writer, file)
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestZipx_Zip(t *testing.T) {
|
||||
|
||||
err := Zipx.Zip("~/Code/data/mm_wiki/attachment/1/4/", "/Users/phachon/Downloads/test.zip")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestZipx_Compress(t *testing.T) {
|
||||
|
||||
osFiles := []*os.File{}
|
||||
f3, err := os.Open("/Users/phachon/Code/data/mm_wiki/images/1/4/redis2.jpeg")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
defer f3.Close()
|
||||
osFiles = append(osFiles, f3)
|
||||
|
||||
err = Zipx.Compress(osFiles, "/Users/phachon/Downloads/demo.zip")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package work
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/phachon/mm-wiki/app/models"
|
||||
"github.com/phachon/mm-wiki/app/services"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
DocSearchWorker = NewDocSearchWork()
|
||||
)
|
||||
|
||||
const (
|
||||
// work 未启动或已停止
|
||||
RunStatusStop = 0
|
||||
// work 运行中
|
||||
RunStatusRunning = 1
|
||||
)
|
||||
|
||||
type DocSearch struct {
|
||||
// 并发锁,理论上不存在并发的情况,为了安全
|
||||
lock sync.RWMutex
|
||||
// work 运行状态
|
||||
runStatus int
|
||||
// work 中是否有任务正在运行
|
||||
isTaskRunning bool
|
||||
// work 退出信号
|
||||
quit chan bool
|
||||
}
|
||||
|
||||
func NewDocSearchWork() *DocSearch {
|
||||
return &DocSearch{
|
||||
runStatus: RunStatusStop,
|
||||
isTaskRunning: false,
|
||||
quit: make(chan bool, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// Start 开始 work
|
||||
func (d *DocSearch) Start() {
|
||||
// 已经在运行
|
||||
if d.runStatus == RunStatusRunning {
|
||||
return
|
||||
}
|
||||
timer, ok := d.getFullTextSearchConf()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
d.updateAllDocIndex()
|
||||
go func(d *DocSearch, t time.Duration) {
|
||||
defer func() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
logs.Info("[DocSearchWork] load all doc index panic: %v", e)
|
||||
}
|
||||
d.lock.Lock()
|
||||
d.runStatus = RunStatusStop
|
||||
d.isTaskRunning = false
|
||||
d.lock.Unlock()
|
||||
}()
|
||||
d.lock.Lock()
|
||||
d.runStatus = RunStatusRunning
|
||||
d.lock.Unlock()
|
||||
for {
|
||||
select {
|
||||
case <-time.Tick(t):
|
||||
if !d.isTaskRunning {
|
||||
d.updateAllDocIndex()
|
||||
}
|
||||
case <-d.quit:
|
||||
logs.Info("[DocSearchWork] stop doc index")
|
||||
return
|
||||
}
|
||||
}
|
||||
}(d, time.Duration(timer)*time.Second)
|
||||
}
|
||||
|
||||
// Restart 重新启动 work
|
||||
func (d *DocSearch) Restart() {
|
||||
d.Stop()
|
||||
time.Sleep(time.Millisecond)
|
||||
d.Start()
|
||||
}
|
||||
|
||||
// Stop 停止 work
|
||||
func (d *DocSearch) Stop() {
|
||||
d.quit <- true
|
||||
}
|
||||
|
||||
// 查找是否开启全文索引并获取配置
|
||||
func (d *DocSearch) getFullTextSearchConf() (timer int64, isOpen bool) {
|
||||
fulltextSearchOpen := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyFulltextSearch, "0")
|
||||
docSearchTimer := models.ConfigModel.GetConfigValueByKey(models.ConfigKeyDocSearchTimer, "3600")
|
||||
timer = utils.Convert.StringToInt64(docSearchTimer)
|
||||
// 默认 3600 s
|
||||
if timer <= 0 {
|
||||
timer = int64(3600)
|
||||
}
|
||||
if fulltextSearchOpen == "1" {
|
||||
return timer, true
|
||||
}
|
||||
return timer, false
|
||||
}
|
||||
|
||||
func (d *DocSearch) updateAllDocIndex() {
|
||||
|
||||
logs.Info("[DocSearchWork] start load all doc index")
|
||||
|
||||
d.lock.Lock()
|
||||
d.isTaskRunning = true
|
||||
d.lock.Unlock()
|
||||
|
||||
// 分批次更新,每批次 100
|
||||
batchUpdateDocNum, _ := beego.AppConfig.Int("search::batch_update_doc_num")
|
||||
if batchUpdateDocNum <= 0 {
|
||||
batchUpdateDocNum = 100
|
||||
}
|
||||
services.DocIndexService.UpdateAllDocIndex(batchUpdateDocNum)
|
||||
services.DocIndexService.Flush()
|
||||
|
||||
d.lock.Lock()
|
||||
d.isTaskRunning = false
|
||||
d.lock.Unlock()
|
||||
|
||||
logs.Info("[DocSearchWork] finish all doc index flush")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/bin/sh
|
||||
|
||||
# start go mod
|
||||
export GO111MODULE=on
|
||||
# set goproxy
|
||||
export GOPROXY=https://goproxy.cn
|
||||
|
||||
PROJECT_NAME="mm-wiki"
|
||||
INSTALL_NAME="install"
|
||||
BUILD_DIR="release"
|
||||
ROOT_DIR=$(pwd)
|
||||
|
||||
# windows .exe
|
||||
if [ "${GOOS}" = "" ]; then
|
||||
UNAME=$( command -v uname)
|
||||
case $( "${UNAME}" | tr '[:upper:]' '[:lower:]') in
|
||||
msys*|cygwin*|mingw*|nt|win*)
|
||||
PROJECT_NAME=${PROJECT_NAME}".exe"
|
||||
INSTALL_NAME=${INSTALL_NAME}".exe"
|
||||
;;
|
||||
esac
|
||||
elif [ "${GOOS}" = "windows" ]; then
|
||||
PROJECT_NAME=${PROJECT_NAME}".exe"
|
||||
INSTALL_NAME=${INSTALL_NAME}".exe"
|
||||
fi
|
||||
|
||||
rm -rf ${BUILD_DIR}
|
||||
|
||||
build_app() {
|
||||
mkdir -p "${ROOT_DIR}"/${BUILD_DIR}/conf
|
||||
mkdir -p "${ROOT_DIR}"/${BUILD_DIR}/logs
|
||||
mkdir -p "${ROOT_DIR}"/${BUILD_DIR}/static
|
||||
mkdir -p "${ROOT_DIR}"/${BUILD_DIR}/views
|
||||
mkdir -p "${ROOT_DIR}"/${BUILD_DIR}/docs
|
||||
|
||||
/bin/cp -r "${ROOT_DIR}"/conf/default.conf "${ROOT_DIR}"/${BUILD_DIR}/conf/
|
||||
/bin/cp -r "${ROOT_DIR}"/conf/template.conf "${ROOT_DIR}"/${BUILD_DIR}/conf/
|
||||
/bin/cp -r "${ROOT_DIR}"/scripts/* "${ROOT_DIR}"/${BUILD_DIR}/
|
||||
/bin/cp -r "${ROOT_DIR}"/docs/* "${ROOT_DIR}"/${BUILD_DIR}/docs/
|
||||
/bin/cp -r "${ROOT_DIR}"/views/* "${ROOT_DIR}"/${BUILD_DIR}/views/
|
||||
/bin/cp -r "${ROOT_DIR}"/static/* "${ROOT_DIR}"/${BUILD_DIR}/static/
|
||||
|
||||
/bin/cp -r "${ROOT_DIR}"/CHANGELOG.md "${ROOT_DIR}"/${BUILD_DIR}
|
||||
/bin/cp -r "${ROOT_DIR}"/README.md "${ROOT_DIR}"/${BUILD_DIR}
|
||||
/bin/cp -r "${ROOT_DIR}"/README_eng.md "${ROOT_DIR}"/${BUILD_DIR}
|
||||
/bin/cp -r "${ROOT_DIR}"/LICENSE "${ROOT_DIR}"/${BUILD_DIR}
|
||||
|
||||
chmod -R 755 "${ROOT_DIR}"/${BUILD_DIR}/conf/
|
||||
chmod -R 755 "${ROOT_DIR}"/${BUILD_DIR}/logs/
|
||||
chmod -R 755 "${ROOT_DIR}"/${BUILD_DIR}/static/
|
||||
chmod -R 755 "${ROOT_DIR}"/${BUILD_DIR}/views/
|
||||
chmod -R 755 "${ROOT_DIR}"/${BUILD_DIR}/*.sh
|
||||
|
||||
go build -o ${PROJECT_NAME} ./
|
||||
|
||||
if [ -f "${ROOT_DIR}/${PROJECT_NAME}" ]; then
|
||||
mv "${ROOT_DIR}"/${PROJECT_NAME} "${ROOT_DIR}"/${BUILD_DIR}/
|
||||
fi
|
||||
return
|
||||
}
|
||||
|
||||
build_install() {
|
||||
|
||||
mkdir -p "${ROOT_DIR}"/${BUILD_DIR}/install
|
||||
# Todo: 目录切换失败时输出错误信息
|
||||
cd "${ROOT_DIR}"/install || exit
|
||||
go build -o ${INSTALL_NAME} ./
|
||||
chmod -R 755 "${ROOT_DIR}"/${BUILD_DIR}/install/
|
||||
|
||||
if [ -f "${ROOT_DIR}/install/${INSTALL_NAME}" ]; then
|
||||
mv "${ROOT_DIR}"/install/${INSTALL_NAME} "${ROOT_DIR}"/${BUILD_DIR}/install
|
||||
fi
|
||||
|
||||
cd ../
|
||||
return
|
||||
}
|
||||
|
||||
build() {
|
||||
echo ">> MM-Wiki start build!"
|
||||
build_app
|
||||
build_install
|
||||
return
|
||||
}
|
||||
|
||||
build
|
||||
@@ -0,0 +1,100 @@
|
||||
# MM-Wiki 配置文件
|
||||
# ----------------------------------------------------------------------
|
||||
# 由 MM-Wiki 安装向导配置生成
|
||||
# beego 参数配置请参考:https://beego.me/docs/mvc/controller/config.md
|
||||
|
||||
|
||||
# 安装说明
|
||||
# ----------------------------------------------------------------------
|
||||
# 在 install 目录,执行安装向导程序
|
||||
# ./install --port=8090
|
||||
# 浏览器访问 http://ip:8090 进入安装界面,完成安装配置
|
||||
|
||||
|
||||
# 运行说明
|
||||
# ----------------------------------------------------------------------
|
||||
# 无论是 Linux 或 Windows, MM-Wiki 启动的默认的配置文件为 conf/mm-wiki.conf
|
||||
# 若要从命令行运行服务器,请在命令行运行
|
||||
# ./mm-wiki 或指定文件运行
|
||||
# ./mm-wiki --conf conf/mm-wiki.conf
|
||||
#
|
||||
# 后台运行
|
||||
# ----------------------------------------------------------------------
|
||||
# 如果你想关闭 shell 窗口后台运行 mm-wiki,Linux 执行命令
|
||||
# nohup ./mm-wiki --conf conf/mm-wiki.conf &
|
||||
|
||||
# 全局配置
|
||||
# ----------------------------------------------------------------------
|
||||
# 运行模式,可选值为 prod(生产模式), dev(开发模式) 或者 test(测试模式). 默认是 prod, 为生产模式
|
||||
runmode = "prod"
|
||||
# 软件名称
|
||||
appname = mm-wiki
|
||||
# httpaddr mm-wiki 程序监听的 ip
|
||||
# 0.0.0.0 是对外开放,通过服务域名、ip 可以访问的端口
|
||||
# 127.0.0.1 只能对本机 localhost访问,可以保护此端口安全性
|
||||
httpaddr = "0.0.0.0"
|
||||
# mm-wiki 程序监听的端口
|
||||
httpport = 8081
|
||||
|
||||
|
||||
# session 配置
|
||||
# ----------------------------------------------------------------------
|
||||
# 开启 session
|
||||
sessionon=true
|
||||
# 客户端存储 cookie 的名字
|
||||
sessionname="mmwikissid"
|
||||
# session 的引擎,默认是 file,支持 file, memory, memcache, redis, redis_cluster
|
||||
sessionprovider="file"
|
||||
# session 引擎的配置,
|
||||
# file: sessionproviderconfig=".mmwiki.sessions" 是指保存 session 数据文件的目录
|
||||
# memory: sessionproviderconfig="" 为空
|
||||
# memcache: sessionproviderconfig="127.0.0.1:7080" memcache 服务的 ip:端口
|
||||
# redis: sessionproviderconfig="127.0.0.1:6379" redis 实例的 ip:端口
|
||||
# redis_cluster: sessionproviderconfig="127.0.0.1:6379;127.0.0.1:6380,100,test,0"(addr..., pool size, password, dbnum)
|
||||
sessionproviderconfig=".mmwiki.sessions"
|
||||
# session 过期时间,单位秒
|
||||
sessiongcmaxlifetime=72000
|
||||
|
||||
|
||||
# cookie 配置
|
||||
# ----------------------------------------------------------------------
|
||||
[author]
|
||||
# 保存 cookie 的 passport
|
||||
passport="mmwikipassport"
|
||||
# cookie 的过期时间,单位秒
|
||||
cookie_expired=72000
|
||||
|
||||
|
||||
# mysql 数据库配置
|
||||
# ----------------------------------------------------------------------
|
||||
[db]
|
||||
host="127.0.0.1"
|
||||
port="3306"
|
||||
name="mm_wiki"
|
||||
user="root"
|
||||
pass="123456"
|
||||
table_prefix="mw_"
|
||||
conn_max_idle=30
|
||||
conn_max_connection=200
|
||||
|
||||
|
||||
# 日志配置
|
||||
# ----------------------------------------------------------------------
|
||||
[log]
|
||||
console="{"level":7, "color":true}"
|
||||
file="{"level":7, "filename":"logs/mm-wiki.log"}"
|
||||
|
||||
|
||||
# 文档配置
|
||||
# ----------------------------------------------------------------------
|
||||
[document]
|
||||
# 文档的根目录,最好写绝对路径
|
||||
root_dir="./data"
|
||||
|
||||
# 搜索配置
|
||||
# ----------------------------------------------------------------------
|
||||
[search]
|
||||
# 搜索索引更新间隔时间(单位秒),默认为 30;如果文档数过多,建议增加时长
|
||||
interval_time=30
|
||||
# 每批次更新的文档数,默认 100,不能太大,一次更新占用内存和链接数过多
|
||||
batch_update_doc_num=100
|
||||
@@ -0,0 +1,100 @@
|
||||
# MM-Wiki 配置文件
|
||||
# ----------------------------------------------------------------------
|
||||
# 由 MM-Wiki 安装向导配置生成
|
||||
# beego 参数配置请参考:https://beego.me/docs/mvc/controller/config.md
|
||||
|
||||
|
||||
# 安装说明
|
||||
# ----------------------------------------------------------------------
|
||||
# 在 install 目录,执行安装向导程序
|
||||
# ./install --port=8090
|
||||
# 浏览器访问 http://ip:8090 进入安装界面,完成安装配置
|
||||
|
||||
|
||||
# 运行说明
|
||||
# ----------------------------------------------------------------------
|
||||
# 无论是 Linux 或 Windows, MM-Wiki 启动的默认的配置文件为 conf/mm-wiki.conf
|
||||
# 若要从命令行运行服务器,请在命令行运行
|
||||
# ./mm-wiki 或指定文件运行
|
||||
# ./mm-wiki --conf conf/mm-wiki.conf
|
||||
#
|
||||
# 后台运行
|
||||
# ----------------------------------------------------------------------
|
||||
# 如果你想关闭 shell 窗口后台运行 mm-wiki,Linux 执行命令
|
||||
# nohup ./mm-wiki --conf conf/mm-wiki.conf &
|
||||
|
||||
# 全局配置
|
||||
# ----------------------------------------------------------------------
|
||||
# 运行模式,可选值为 prod(生产模式), dev(开发模式) 或者 test(测试模式). 默认是 prod, 为生产模式
|
||||
runmode = "prod"
|
||||
# 软件名称
|
||||
appname = mm-wiki
|
||||
# httpaddr mm-wiki 程序监听的 ip
|
||||
# 0.0.0.0 是对外开放,通过服务域名、ip 可以访问的端口
|
||||
# 127.0.0.1 只能对本机 localhost访问,可以保护此端口安全性
|
||||
httpaddr = "#httpaddr#"
|
||||
# mm-wiki 程序监听的端口
|
||||
httpport = #httpport#
|
||||
|
||||
|
||||
# session 配置
|
||||
# ----------------------------------------------------------------------
|
||||
# 开启 session
|
||||
sessionon=true
|
||||
# 客户端存储 cookie 的名字
|
||||
sessionname="mmwikissid"
|
||||
# session 的引擎,默认是 file,支持 file, memory, memcache, redis, redis_cluster
|
||||
sessionprovider="file"
|
||||
# session 引擎的配置,
|
||||
# file: sessionproviderconfig=".mmwiki.sessions" 是指保存 session 数据文件的目录
|
||||
# memory: sessionproviderconfig="" 为空
|
||||
# memcache: sessionproviderconfig="127.0.0.1:7080" memcache 服务的 ip:端口
|
||||
# redis: sessionproviderconfig="127.0.0.1:6379" redis 实例的 ip:端口
|
||||
# redis_cluster: sessionproviderconfig="127.0.0.1:6379;127.0.0.1:6380,100,test,0"(addr..., pool size, password, dbnum)
|
||||
sessionproviderconfig=".mmwiki.sessions"
|
||||
# session 过期时间,单位秒
|
||||
sessiongcmaxlifetime=72000
|
||||
|
||||
|
||||
# cookie 配置
|
||||
# ----------------------------------------------------------------------
|
||||
[author]
|
||||
# 保存 cookie 的 passport
|
||||
passport="mmwikipassport"
|
||||
# cookie 的过期时间,单位秒
|
||||
cookie_expired=72000
|
||||
|
||||
|
||||
# mysql 数据库配置
|
||||
# ----------------------------------------------------------------------
|
||||
[db]
|
||||
host="#db.host#"
|
||||
port="#db.port#"
|
||||
name="#db.name#"
|
||||
user="#db.user#"
|
||||
pass="#db.pass#"
|
||||
table_prefix="mw_"
|
||||
conn_max_idle=#db.conn_max_idle#
|
||||
conn_max_connection=#db.conn_max_connection#
|
||||
|
||||
|
||||
# 日志配置
|
||||
# ----------------------------------------------------------------------
|
||||
[log]
|
||||
console="{"level":7, "color":true}"
|
||||
file="{"level":7, "filename":"#log.filename#"}"
|
||||
|
||||
|
||||
# 文档配置
|
||||
# ----------------------------------------------------------------------
|
||||
[document]
|
||||
# 文档的根目录,最好写绝对路径
|
||||
root_dir="#document_dir#"
|
||||
|
||||
# 搜索配置
|
||||
# ----------------------------------------------------------------------
|
||||
[search]
|
||||
# 搜索索引更新间隔时间(单位秒),默认为 30;如果文档数过多,建议增加时长
|
||||
interval_time=30
|
||||
# 每批次更新的文档数,默认 100,不能太大,一次更新占用内存和链接数过多
|
||||
batch_update_doc_num=100
|
||||
@@ -0,0 +1,168 @@
|
||||
-- --------------------------------------
|
||||
-- MM-Wiki 安装数据
|
||||
-- warning:执行前需保证表里没有任何数据
|
||||
-- author: phachon
|
||||
-- --------------------------------------
|
||||
|
||||
|
||||
-- --------------------------------------
|
||||
-- 系统用户(root), password:123456, 自动安装不需要插入,手动安装时需要插入该数据
|
||||
-- --------------------------------------
|
||||
-- INSERT INTO `mw_user` (`user_id`, `username`, `password`, `given_name`, `email`, `mobile`, `role_id`, `is_delete`, `create_time`, `update_time`)
|
||||
-- VALUES ('1', 'root', 'e10adc3949ba59abbe56e057f20f883e', 'root', 'root@123456.com', '1102222', '1', '0', unix_timestamp(now()), unix_timestamp(now()));
|
||||
|
||||
|
||||
-- --------------------------------------
|
||||
-- 系统角色 1 超级管理员,2 管理员,3 普通用户
|
||||
-- --------------------------------------
|
||||
INSERT INTO `mw_role` (`role_id`, `name`, `type`, `is_delete`, `create_time`, `update_time`) VALUES ('1', '超级管理员', '1', '0', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_role` (`role_id`, `name`, `type`, `is_delete`, `create_time`, `update_time`) VALUES ('2', '管理员', '1', '0', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_role` (`role_id`, `name`, `type`, `is_delete`, `create_time`, `update_time`) VALUES ('3', '普通用户', '1', '0', unix_timestamp(now()), unix_timestamp(now()));
|
||||
|
||||
|
||||
-- --------------------------------------
|
||||
-- 系统权限
|
||||
-- --------------------------------------
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (1, '个人中心', 0, 'menu', '', '', 'glyphicon-leaf', '', 1, 1, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (2, '个人资料', 1, 'controller', 'profile', 'info', 'glyphicon-list', '', 1, 11, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (3, '修改资料', 1, 'controller', 'profile', 'edit', 'glyphicon-list', '', 0, 12, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (4, '修改资料保存', 1, 'controller', 'profile', 'modify', 'glyphicon-list', '', 0, 13, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (5, '关注用户列表', 1, 'controller', 'profile', 'followUser', 'glyphicon-list', '', 0, 14, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (6, '关注文档列表', 1, 'controller', 'profile', 'followDoc', 'glyphicon-list', '', 0, 15, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (7, '我的活动', 1, 'controller', 'profile', 'activity', 'glyphicon-list', '', 1, 16, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (8, '修改密码', 1, 'controller', 'profile', 'password', 'glyphicon-list', '', 1, 17, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (9, '修改密码保存', 1, 'controller', 'profile', 'savePass', 'glyphicon-list', '', 0, 18, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (10, '用户管理', 1, 'menu', '', '', 'glyphicon-user', '', 1, 2, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (11, '添加用户', 10, 'controller', 'user', 'add', 'glyphicon-list', '', 1, 21, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (12, '添加用户保存', 10, 'controller', 'user', 'save', 'glyphicon-list', '', 0, 22, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (13, '用户列表', 10, 'controller', 'user', 'list', 'glyphicon-list', '', 1, 23, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (14, '修改用户', 10, 'controller', 'user', 'edit', 'glyphicon-list', '', 0, 24, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (15, '修改用户保存', 10, 'controller', 'user', 'modify', 'glyphicon-list', '', 0, 25, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (16, '屏蔽用户', 10, 'controller', 'user', 'forbidden', 'glyphicon-list', '', 0, 26, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (17, '恢复用户', 10, 'controller', 'user', 'recover', 'glyphicon-list', '', 0, 27, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (18, '用户详情', 10, 'controller', 'user', 'info', 'glyphicon-list', '', 0, 28, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (19, '角色管理', 1, 'menu', '', '', 'glyphicon-gift', '', 1, 3, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (20, '添加角色', 19, 'controller', 'role', 'add', 'glyphicon-list', '', 1, 31, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (21, '添加角色保存', 19, 'controller', 'role', 'save', 'glyphicon-list', '', 0, 32, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (22, '角色列表', 19, 'controller', 'role', 'list', 'glyphicon-list', '', 1, 33, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (23, '修改角色', 19, 'controller', 'role', 'edit', 'glyphicon-list', '', 0, 34, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (24, '修改角色保存', 19, 'controller', 'role', 'modify', 'glyphicon-list', '', 0, 35, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (25, '角色用户列表', 19, 'controller', 'role', 'user', 'glyphicon-list', '', 0, 36, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (26, '角色权限', 19, 'controller', 'role', 'privilege', 'glyphicon-list', '', 0, 37, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (27, '角色权限保存', 19, 'controller', 'role', 'grantPrivilege', 'glyphicon-list', '', 0, 38, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (28, '删除角色', 19, 'controller', 'role', 'delete', 'glyphicon-list', '', 0, 29, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (29, '重置用户角色', 19, 'controller', 'role', 'resetUser', 'glyphicon-list', '', 0, 310, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (30, '权限管理', 1, 'menu', '', '', 'glyphicon-lock', '', 1, 4, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (31, '添加权限', 30, 'controller', 'privilege', 'add', 'glyphicon-list', '', 1, 41, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (32, '添加权限保存', 30, 'controller', 'privilege', 'save', 'glyphicon-list', '', 0, 42, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (33, '权限列表', 30, 'controller', 'privilege', 'list', 'glyphicon-list', '', 1, 43, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (34, '修改权限', 30, 'controller', 'privilege', 'edit', 'glyphicon-list', '', 0, 44, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (35, '修改权限保存', 30, 'controller', 'privilege', 'modify', 'glyphicon-list', '', 0, 45, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (36, '删除权限', 30, 'controller', 'privilege', 'delete', 'glyphicon-list', '', 0, 46, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (37, '空间管理', 1, 'menu', '', '', 'glyphicon-th-large', '', 1, 5, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (38, '添加空间', 37, 'controller', 'space', 'add', 'glyphicon-list', '', 1, 51, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (39, '添加空间保存', 37, 'controller', 'space', 'save', 'glyphicon-list', '', 0, 52, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (40, '空间列表', 37, 'controller', 'space', 'list', 'glyphicon-list', '', 1, 53, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (41, '修改空间', 37, 'controller', 'space', 'edit', 'glyphicon-list', '', 0, 54, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (42, '修改空间保存', 37, 'controller', 'space', 'modify', 'glyphicon-list', '', 0, 55, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (43, '空间成员列表', 37, 'controller', 'space', 'member', 'glyphicon-list', '', 0, 56, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (44, '添加空间成员', 37, 'controller', 'space_user', 'save', 'glyphicon-list', '', 0, 57, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (45, '移除空间成员', 37, 'controller', 'space_user', 'remove', 'glyphicon-list', '', 0, 58, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (46, '更新空间成员权限', 37, 'controller', 'space_user', 'modify', 'glyphicon-list', '', 0, 59, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (47, '删除空间', 37, 'controller', 'space', 'delete', 'glyphicon-list', '', 0, 510, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (48, '空间备份', 37, 'controller', 'space', 'download', 'glyphicon-list', '', 0, 512, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (49, '日志管理', 1, 'menu', '', '', 'glyphicon-list-alt', '', 1, 6, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (50, '系统日志', 49, 'controller', 'log', 'system', 'glyphicon-list', '', 1, 61, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (51, '系统日志详情', 49, 'controller', 'log', 'info', 'glyphicon-list', '', 0, 62, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (52, '文档日志', 49, 'controller', 'log', 'document', 'glyphicon-list', '', 1, 63, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (53, '配置管理', 1, 'menu', '', '', 'glyphicon-cog', '', 1, 7, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (54, '全局配置', 53, 'controller', 'config', 'global', 'glyphicon-list', '', 1, 71, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (55, '全局配置保存', 53, 'controller', 'config', 'modify', 'glyphicon-list', '', 0, 72, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (56, '邮箱配置', 53, 'controller', 'email', 'list', 'glyphicon-list', '', 1, 73, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (57, '添加邮件服务器', 53, 'controller', 'email', 'add', 'glyphicon-list', '', 0, 74, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (58, '添加邮件服务器保存', 53, 'controller', 'email', 'save', 'glyphicon-list', '', 0, 75, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (59, '修改邮件服务器', 53, 'controller', 'email', 'edit', 'glyphicon-list', '', 0, 76, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (60, '修改邮件服务器保存', 53, 'controller', 'email', 'modify', 'glyphicon-list', '', 0, 77, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (61, '启用邮件服务器', 53, 'controller', 'email', 'used', 'glyphicon-list', '', 0, 78, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (62, '删除邮件服务器', 53, 'controller', 'email', 'delete', 'glyphicon-list', '', 0, 79, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (63, '登录认证', 53, 'controller', 'auth', 'list', 'glyphicon-list', '', 1, 81, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (64, '添加登录认证', 53, 'controller', 'auth', 'add', 'glyphicon-list', '', 0, 82, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (65, '添加登录认证保存', 53, 'controller', 'auth', 'save', 'glyphicon-list', '', 0, 83, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (66, '修改登录认证', 53, 'controller', 'auth', 'edit', 'glyphicon-list', '', 0, 84, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (67, '修改登录认证保存', 53, 'controller', 'auth', 'modify', 'glyphicon-list', '', 0, 85, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (68, '删除登录认证', 53, 'controller', 'auth', 'delete', 'glyphicon-list', '', 0, 86, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (69, '启用登录认证', 53, 'controller', 'auth', 'used', 'glyphicon-list', '', 0, 87, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (70, '登录认证文档', 53, 'controller', 'auth', 'doc', 'glyphicon-list', '', 0, 88, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (71, '系统管理', 1, 'menu', '', '', 'glyphicon-link', '', 1, 8, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (72, '快捷链接', 71, 'controller', 'link', 'list', 'glyphicon-list', '', 1, 81, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (73, '添加链接', 71, 'controller', 'link', 'add', 'glyphicon-list', '', 0, 82, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (74, '添加链接保存', 71, 'controller', 'link', 'save', 'glyphicon-list', '', 0, 83, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (75, '修改链接', 71, 'controller', 'link', 'edit', 'glyphicon-list', '', 0, 84, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (76, '修改链接保存', 71, 'controller', 'link', 'modify', 'glyphicon-list', '', 0, 85, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (77, '删除链接', 71, 'controller', 'link', 'delete', 'glyphicon-list', '', 0, 86, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (78, '系统联系人', 71, 'controller', 'contact', 'list', 'glyphicon-list', '', 1, 91, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (79, '添加联系人', 71, 'controller', 'contact', 'add', 'glyphicon-list', '', 0, 92, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (80, '添加联系人保存', 71, 'controller', 'contact', 'save', 'glyphicon-list', '', 0, 93, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (81, '修改联系人', 71, 'controller', 'contact', 'edit', 'glyphicon-list', '', 0, 94, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (82, '修改联系人保存', 71, 'controller', 'contact', 'modify', 'glyphicon-list', '', 0, 95, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (83, '删除联系人', 71, 'controller', 'contact', 'delete', 'glyphicon-list', '', 0, 96, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (84, '统计管理', 1, 'menu', '', '', 'glyphicon-signal', '', 1, 9, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (85, '数据统计', 84, 'controller', 'static', 'default', 'glyphicon-list', '', 1, 91, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (86, 'ajax获取空间文档排行', 84, 'controller', 'static', 'spaceDocsRank', 'glyphicon-list', '', 0, 92, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (87, 'ajax获取收藏文档排行', 84, 'controller', 'static', 'collectDocRank', 'glyphicon-list', '', 0, 93, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (88, 'ajax获取文档数量增长趋势', 84, 'controller', 'static', 'docCountByTime', 'glyphicon-list', '', 0, 94, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (89, '系统监控', 84, 'controller', 'static', 'monitor', 'glyphicon-list', '', 1, 95, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (90, 'ajax获取服务器状态', 84, 'controller', 'static', 'serverStatus', 'glyphicon-list', '', 0, 96, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (91, 'ajax获取服务器时间', 84, 'controller', 'static', 'serverTime', 'glyphicon-list', '', 0, 97, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (92, '测试邮件服务器', 53, 'controller', 'email', 'test', 'glyphicon-list', '', 0, 80, unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO mw_privilege (privilege_id, name, parent_id, type, controller, action, icon, target, is_display, sequence, create_time, update_time) VALUES (93, '导入联系人', 71, 'controller', 'contact', 'import', 'glyphicon-list', '', 0, 97, unix_timestamp(now()), unix_timestamp(now()));
|
||||
|
||||
|
||||
|
||||
-- ---------------------------------------------
|
||||
-- 系统角色权限关系数据
|
||||
-- ---------------------------------------------
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (1, 3, 1, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (2, 3, 2, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (3, 3, 3, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (4, 3, 4, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (5, 3, 5, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (6, 3, 6, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (7, 3, 7, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (8, 3, 8, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (9, 3, 9, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (10, 2, 1, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (11, 2, 2, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (12, 2, 3, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (13, 2, 4, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (14, 2, 5, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (15, 2, 6, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (16, 2, 7, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (17, 2, 8, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (18, 2, 9, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (19, 2, 37, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (20, 2, 38, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (21, 2, 39, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (22, 2, 40, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (23, 2, 41, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (24, 2, 42, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (25, 2, 43, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (26, 2, 44, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (27, 2, 45, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (28, 2, 46, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (29, 2, 47, unix_timestamp(now()));
|
||||
INSERT INTO mw_role_privilege (role_privilege_id, role_id, privilege_id, create_time) VALUES (30, 2, 48, unix_timestamp(now()));
|
||||
|
||||
|
||||
-- -------------------------------------------
|
||||
-- 系统配置
|
||||
-- -------------------------------------------
|
||||
INSERT INTO `mw_config` VALUES ('1', '主页标题', 'main_title', '这里可以填写公司名称,例如:欢迎来到 XXXX 科技公司 wiki 平台!', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_config` VALUES ('2', '主页描述', 'main_description', '这是写一些描述:请使用域账号登录,使用中有任何问题请联系管理员 root@xxx.com!', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_config` VALUES ('3', '是否开启自动关注', 'auto_follow_doc_open', '', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_config` VALUES ('4', '是否开启邮件通知', 'send_email_open', '', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_config` VALUES ('5', '是否开启统一登录', 'sso_open', '', unix_timestamp(now()), unix_timestamp(now()));
|
||||
-- INSERT INTO `mw_config` (name, key, value, create_time, update_time) VALUES ('系统版本号', 'system_version', 'v0.0.0', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_config` (name, `key`, value, create_time, update_time) VALUES ('开启全文搜索', 'fulltext_search_open', '1', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_config` (name, `key`, value, create_time, update_time) VALUES ('索引更新间隔', 'doc_search_timer', '3600', unix_timestamp(now()), unix_timestamp(now()));
|
||||
INSERT INTO `mw_config` (name, `key`, value, create_time, update_time) VALUES ('系统名称', 'system_name', 'Markdown Mini Wiki', unix_timestamp(now()), unix_timestamp(now()));
|
||||
@@ -0,0 +1,305 @@
|
||||
-- --------------------------------
|
||||
-- MM-Wiki 表结构
|
||||
-- author: phachon
|
||||
-- --------------------------------
|
||||
|
||||
-- 手动安装时首先需要创建数据库
|
||||
-- CREATE DATABASE IF NOT EXISTS mm_wiki DEFAULT CHARSET utf8;
|
||||
|
||||
-- --------------------------------
|
||||
-- 用户表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_user`;
|
||||
CREATE TABLE `mw_user` (
|
||||
`user_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '用户 id',
|
||||
`username` varchar(100) NOT NULL DEFAULT '' COMMENT '用户名',
|
||||
`password` char(32) NOT NULL DEFAULT '' COMMENT '密码',
|
||||
`given_name` varchar(50) NOT NULL DEFAULT '' COMMENT '姓名',
|
||||
`mobile` char(13) NOT NULL DEFAULT '' COMMENT '手机号',
|
||||
`phone` char(13) NOT NULL DEFAULT '' COMMENT '电话',
|
||||
`email` varchar(50) NOT NULL DEFAULT '' COMMENT '邮箱',
|
||||
`department` char(50) NOT NULL DEFAULT '' COMMENT '部门',
|
||||
`position` char(50) NOT NULL DEFAULT '' COMMENT '职位',
|
||||
`location` char(50) NOT NULL DEFAULT '' COMMENT '位置',
|
||||
`im` char(50) NOT NULL DEFAULT '' COMMENT '即时聊天工具',
|
||||
`last_ip` varchar(15) NOT NULL DEFAULT '' COMMENT '最后登录ip',
|
||||
`last_time` int(11) NOT NULL DEFAULT '0' COMMENT '最后登录时间',
|
||||
`role_id` tinyint(3) NOT NULL DEFAULT '0' COMMENT '角色 id',
|
||||
`is_forbidden` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否屏蔽,0 否 1 是',
|
||||
`is_delete` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否删除,0 否 1 是',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
|
||||
|
||||
-- ---------------------------------------------------------------
|
||||
-- 系统角色表
|
||||
-- ---------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS `mw_role`;
|
||||
CREATE TABLE `mw_role` (
|
||||
`role_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '角色 id',
|
||||
`name` char(10) NOT NULL DEFAULT '' COMMENT '角色名称',
|
||||
`type` tinyint(3) NOT NULL DEFAULT '0' COMMENT '角色类型 0 自定义角色,1 系统角色',
|
||||
`is_delete` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否删除,0 否 1 是',
|
||||
`create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`role_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统角色表';
|
||||
|
||||
-- -------------------------------------------------------
|
||||
-- 系统权限表
|
||||
-- -------------------------------------------------------
|
||||
DROP TABLE IF EXISTS `mw_privilege`;
|
||||
CREATE TABLE `mw_privilege` (
|
||||
`privilege_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '权限id',
|
||||
`name` char(30) NOT NULL DEFAULT '' COMMENT '权限名',
|
||||
`parent_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '上级',
|
||||
`type` enum('controller','menu') DEFAULT 'controller' COMMENT '权限类型:控制器、菜单',
|
||||
`controller` char(100) NOT NULL DEFAULT '' COMMENT '控制器',
|
||||
`action` char(100) NOT NULL DEFAULT '' COMMENT '动作',
|
||||
`icon` char(100) NOT NULL DEFAULT '' COMMENT '图标(用于展示)',
|
||||
`target` char(200) NOT NULL DEFAULT '' COMMENT '目标地址',
|
||||
`is_display` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否显示:0不显示 1显示',
|
||||
`sequence` int(10) NOT NULL DEFAULT '0' COMMENT '排序(越小越靠前)',
|
||||
`create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`privilege_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统权限表';
|
||||
|
||||
-- ------------------------------------------------------------------
|
||||
-- 系统角色权限对应关系表
|
||||
-- ------------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS `mw_role_privilege`;
|
||||
CREATE TABLE `mw_role_privilege` (
|
||||
`role_privilege_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '角色权限关系 id',
|
||||
`role_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '角色id',
|
||||
`privilege_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '权限id',
|
||||
`create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
PRIMARY KEY (`role_privilege_id`),
|
||||
KEY (`role_id`),
|
||||
KEY (`privilege_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统角色权限对应关系表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 空间表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_space`;
|
||||
CREATE TABLE `mw_space` (
|
||||
`space_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '空间 id',
|
||||
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',
|
||||
`description` varchar(100) NOT NULL DEFAULT '' COMMENT '描述',
|
||||
`tags` varchar(255) NOT NULL DEFAULT '' COMMENT '标签',
|
||||
`visit_level` enum('private','public') NOT NULL DEFAULT 'public' COMMENT '访问级别:private,public',
|
||||
`is_share` tinyint(3) NOT NULL DEFAULT '1' COMMENT '文档是否允许分享 0 否 1 是',
|
||||
`is_export` tinyint(3) NOT NULL DEFAULT '1' COMMENT '文档是否允许导出 0 否 1 是',
|
||||
`is_delete` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否删除 0 否 1 是',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`space_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='空间表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 空间成员表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_space_user`;
|
||||
CREATE TABLE `mw_space_user` (
|
||||
`space_user_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '用户空间关系 id',
|
||||
`user_id` int(10) NOT NULL DEFAULT '0' COMMENT '用户 id',
|
||||
`space_id` int(10) NOT NULL DEFAULT '0' COMMENT '空间 id',
|
||||
`privilege` tinyint(3) NOT NULL DEFAULT '0' COMMENT '空间成员操作权限 0 浏览者 1 编辑者 2 管理员',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间',
|
||||
PRIMARY KEY (`space_user_id`),
|
||||
UNIQUE KEY (`user_id`, `space_id`),
|
||||
KEY (`user_id`),
|
||||
KEY (`space_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='空间成员表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 文档表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_document`;
|
||||
CREATE TABLE `mw_document` (
|
||||
`document_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '文档 id',
|
||||
`parent_id` int(10) NOT NULL DEFAULT '0' COMMENT '文档父 id',
|
||||
`space_id` int(10) NOT NULL DEFAULT '0' COMMENT '空间id',
|
||||
`name` varchar(150) NOT NULL DEFAULT '' COMMENT '文档名称',
|
||||
`type` tinyint(3) NOT NULL DEFAULT '1' COMMENT '文档类型 1 page 2 dir',
|
||||
`path` char(30) NOT NULL DEFAULT '0' COMMENT '存储根文档到父文档的 document_id 值, 格式 0,1,2,...',
|
||||
`sequence` int(10) NOT NULL DEFAULT '0' COMMENT '排序号(越小越靠前)',
|
||||
`create_user_id` int(10) NOT NULL DEFAULT '0' COMMENT '创建用户 id',
|
||||
`edit_user_id` int(10) NOT NULL DEFAULT '0' COMMENT '最后修改用户 id',
|
||||
`is_delete` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否删除 0 否 1 是',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`document_id`),
|
||||
KEY (`parent_id`),
|
||||
KEY (`space_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文档表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 用户收藏表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_collection`;
|
||||
CREATE TABLE `mw_collection` (
|
||||
`collection_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '用户收藏关系 id',
|
||||
`user_id` int(10) NOT NULL DEFAULT '0' COMMENT '用户id',
|
||||
`type` tinyint(3) NOT NULL DEFAULT '1' COMMENT '收藏类型 1 文档 2 空间',
|
||||
`resource_id` int(10) NOT NULL DEFAULT '0' COMMENT '收藏资源 id ',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
PRIMARY KEY (`collection_id`),
|
||||
KEY (`user_id`),
|
||||
UNIQUE key (`user_id`, `resource_id`, `type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户收藏表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 用户关注表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_follow`;
|
||||
CREATE TABLE `mw_follow` (
|
||||
`follow_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '关注 id',
|
||||
`user_id` int(10) NOT NULL DEFAULT '0' COMMENT '用户id',
|
||||
`type` tinyint(3) NOT NULL DEFAULT '1' COMMENT '关注类型 1 文档 2 用户',
|
||||
`object_id` int(10) NOT NULL DEFAULT '0' COMMENT '关注对象 id',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
PRIMARY KEY (`follow_id`),
|
||||
KEY (`user_id`),
|
||||
KEY (`object_id`),
|
||||
UNIQUE key (`user_id`, `object_id`, `type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户关注表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 文档日志表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_log_document`;
|
||||
CREATE TABLE `mw_log_document` (
|
||||
`log_document_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '文档日志 id',
|
||||
`document_id` int(10) NOT NULL DEFAULT '0' COMMENT '文档id',
|
||||
`space_id` int(10) NOT NULL DEFAULT '0' COMMENT '空间id',
|
||||
`user_id` int(10) NOT NULL DEFAULT '0' COMMENT '用户id',
|
||||
`action` tinyint(3) NOT NULL DEFAULT '1' COMMENT '动作 1 创建 2 修改 3 删除',
|
||||
`comment` varchar(255) NOT NULL DEFAULT '' COMMENT '备注信息',
|
||||
`create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
PRIMARY KEY (`log_document_id`),
|
||||
KEY (`document_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文档日志表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 系统操作日志表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_log`;
|
||||
CREATE TABLE `mw_log` (
|
||||
`log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '系统操作日志 id',
|
||||
`level` tinyint(3) NOT NULL DEFAULT '6' COMMENT '日志级别',
|
||||
`path` char(100) NOT NULL DEFAULT '' COMMENT '请求路径',
|
||||
`get` text NOT NULL COMMENT 'get参数',
|
||||
`post` text NOT NULL COMMENT 'post参数',
|
||||
`message` varchar(255) NOT NULL DEFAULT '' COMMENT '信息',
|
||||
`ip` char(100) NOT NULL DEFAULT '' COMMENT 'ip地址',
|
||||
`user_agent` char(200) NOT NULL DEFAULT '' COMMENT '用户代理',
|
||||
`referer` char(100) NOT NULL DEFAULT '' COMMENT 'referer',
|
||||
`user_id` int(10) NOT NULL DEFAULT '0' COMMENT '用户id',
|
||||
`username` char(100) NOT NULL DEFAULT '' COMMENT '用户名',
|
||||
`create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
PRIMARY KEY (`log_id`),
|
||||
KEY (`level`, `username`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统操作日志表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 邮件服务器表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_email`;
|
||||
CREATE TABLE `mw_email` (
|
||||
`email_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '邮箱 id',
|
||||
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '邮箱服务器名称',
|
||||
`sender_address` varchar(100) NOT NULL DEFAULT '' COMMENT '发件人邮件地址',
|
||||
`sender_name` varchar(100) NOT NULL DEFAULT '' COMMENT '发件人显示名',
|
||||
`sender_title_prefix` varchar(100) NOT NULL DEFAULT '' COMMENT '发送邮件标题前缀',
|
||||
`host` char(100) NOT NULL DEFAULT '' COMMENT '服务器主机名',
|
||||
`port` int(5) NOT NULL DEFAULT '25' COMMENT '服务器端口',
|
||||
`username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',
|
||||
`password` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
|
||||
`is_ssl` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用ssl, 0 默认不使用 1 使用',
|
||||
`is_used` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否被使用, 0 默认不使用 1 使用',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`email_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='邮件服务器表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 快捷链接表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_link`;
|
||||
CREATE TABLE `mw_link` (
|
||||
`link_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '链接 id',
|
||||
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '链接名称',
|
||||
`url` varchar(100) NOT NULL DEFAULT '' COMMENT '链接地址',
|
||||
`sequence` int(10) NOT NULL DEFAULT '0' COMMENT '排序号(越小越靠前)',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`link_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='快捷链接表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 统一登录认证表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_login_auth`;
|
||||
CREATE TABLE `mw_login_auth` (
|
||||
`login_auth_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '认证表主键ID',
|
||||
`name` varchar(30) NOT NULL COMMENT '登录认证名称',
|
||||
`username_prefix` varchar(30) NOT NULL COMMENT '用户名前缀',
|
||||
`url` varchar(200) NOT NULL COMMENT '认证接口 url',
|
||||
`ext_data` varchar(500) NOT NULL DEFAULT '' COMMENT '额外数据: token=aaa&key=bbb',
|
||||
`is_used` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否被使用, 0 默认不使用 1 使用',
|
||||
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 0 否 1 是',
|
||||
`create_time` int(11) NOT NULL COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`login_auth_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='统一登录认证表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 全局配置表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_config`;
|
||||
CREATE TABLE `mw_config` (
|
||||
`config_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '配置表主键Id',
|
||||
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '配置名称',
|
||||
`key` char(50) NOT NULL DEFAULT '' COMMENT '配置键',
|
||||
`value` text NOT NULL COMMENT '配置值',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`config_id`),
|
||||
unique KEY (`key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='全局配置表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 系统联系人表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_contact`;
|
||||
CREATE TABLE `mw_contact` (
|
||||
`contact_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '联系人 id',
|
||||
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '联系人名称',
|
||||
`mobile` char(13) NOT NULL DEFAULT '' COMMENT '联系电话',
|
||||
`email` varchar(50) NOT NULL DEFAULT '' COMMENT '邮箱',
|
||||
`position` varchar(100) NOT NULL DEFAULT '' COMMENT '联系人职位',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`contact_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='联系人表';
|
||||
|
||||
-- --------------------------------
|
||||
-- 附件信息表
|
||||
-- --------------------------------
|
||||
DROP TABLE IF EXISTS `mw_attachment`;
|
||||
CREATE TABLE `mw_attachment` (
|
||||
`attachment_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '附件 id',
|
||||
`user_id` int(10) NOT NULL DEFAULT '0' COMMENT '创建用户id',
|
||||
`document_id` int(10) NOT NULL DEFAULT '0' COMMENT '所属文档id',
|
||||
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '附件名称',
|
||||
`path` varchar(100) NOT NULL DEFAULT '' COMMENT '附件路径',
|
||||
`source` tinyint(1) NOT NULL DEFAULT '0' COMMENT '附件来源, 0 默认是附件 1 图片',
|
||||
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`attachment_id`),
|
||||
KEY (`document_id`, `source`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='附件信息表';
|
||||
@@ -0,0 +1,10 @@
|
||||
## 开发日志
|
||||
|
||||
准备开发的日志 2020-04-06 21:41:44
|
||||
1.空间排序, 空间内目录, 文件自由排序, 取消创建文档时的类型选择, 直接在树形中填写文档名称, 后台自动判定, OK 2020-04-07 03:24:48
|
||||
不需要升级, 无数据库更改
|
||||
1.1遗留问题, 不能直接拖到其它目录, 移动并自动排序
|
||||
2.修复首页最近更新文档, 不是自己权限范围内的也能查看
|
||||
增加字段, alter table mw_log_document add space_id int
|
||||
同步数据, update mw_log_document as logDocment, mw_document as document set logDocment.space_id = document.space_id WHERE logDocment.document_id = document.document_id
|
||||
2.文档分享地址加密
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
// 获取数据
|
||||
$username = isset($_POST["username"]) ? $_POST["username"] : "";
|
||||
$password = isset($_POST["password"]) ? $_POST["password"] : "";
|
||||
$extData = isset($_POST["ext_data"]) ? $_POST["ext_data"] : "";
|
||||
|
||||
if (!$username || !$password) {
|
||||
echo json_encode(['message'=>'参数错误', 'data'=>[]], JSON_UNESCAPED_UNICODE);
|
||||
exit();
|
||||
}
|
||||
// 1. ext_data 可用于接口安全验证
|
||||
if ($extData != "login api token") {
|
||||
$result = [
|
||||
'message' => '登录接口验证失败',
|
||||
'data' => [],
|
||||
];
|
||||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||||
exit();
|
||||
}
|
||||
|
||||
// 2. 验证用户名密码是否正确
|
||||
// ....
|
||||
// ....
|
||||
|
||||
// 3. 成功返回
|
||||
$result = [
|
||||
'message' => '',
|
||||
'data' => [
|
||||
'given_name' => '王哈哈',
|
||||
'mobile' => '111111111111',
|
||||
'phone' => '010-9929921',
|
||||
'email' => 'root@mmWiki.com',
|
||||
'department' => '广告事业部.技术部.系统开发组',
|
||||
'position' => '高级JAVA开发工程师',
|
||||
'location' => 'B座32层E区1002',
|
||||
'im' => 'QQ:12211',
|
||||
],
|
||||
];
|
||||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
dictionary.txt 词典拷贝自 [github.com/fxsjy/jieba](https://github.com/fxsjy/jieba)
|
||||
|
||||
stop_tokens.txt 停用词列表来自网络
|
||||
Executable
+589032
File diff suppressed because it is too large
Load Diff
Executable
+1161
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
//"github.com/go-ego/riot"
|
||||
)
|
||||
|
||||
// 文档搜索
|
||||
var (
|
||||
//DocSearcher = riot.Engine{}
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package global
|
||||
|
||||
const (
|
||||
SYSTEM_VERSION = "v0.2.2" // system version code
|
||||
SYSTEM_COPYRIGHT = "2018 - 2022 phachon" // system copyright
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
module github.com/phachon/mm-wiki
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
|
||||
github.com/astaxie/beego v1.12.0
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/go-ldap/ldap/v3 v3.1.11
|
||||
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible
|
||||
github.com/go-sql-driver/mysql v1.4.1
|
||||
github.com/mattn/go-colorable v0.1.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.10 // indirect
|
||||
github.com/onsi/ginkgo v1.10.3 // indirect
|
||||
github.com/onsi/gomega v1.7.1 // indirect
|
||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
|
||||
github.com/shirou/gopsutil v2.19.11+incompatible
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/snail007/go-activerecord v0.0.0-20190813031814-2ac2f3d7cff0
|
||||
github.com/stretchr/testify v1.7.1 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/russross/blackfriday.v2 v2.0.0
|
||||
)
|
||||
@@ -0,0 +1,127 @@
|
||||
github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
|
||||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/astaxie/beego v1.12.0 h1:MRhVoeeye5N+Flul5PoVfD9CslfdoH+xqC/xvSQ5u2Y=
|
||||
github.com/astaxie/beego v1.12.0/go.mod h1:fysx+LZNZKnvh4GED/xND7jWtjCR6HzydR2Hh2Im57o=
|
||||
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
|
||||
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737 h1:rRISKWyXfVxvoa702s91Zl5oREZTrR3yv+tXrrX7G/g=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
|
||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||
github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
|
||||
github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
|
||||
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.0 h1:/S4hO/AO6tLMlPX0oftGSOcdGJJN/MuYzfgWRMn199E=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.0/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-ldap/ldap/v3 v3.1.11 h1:EojIR9zHvfQS8LEz+EjvnPSvsfPYS3UioBezeOOskIA=
|
||||
github.com/go-ldap/ldap/v3 v3.1.11/go.mod h1:dtLsnBXnSLIsMRbCBuRpHflCGaYzZ5jn+x1q7XqMTKU=
|
||||
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible h1:msy24VGS42fKO9K1vLz82/GeYW1cILu7Nuuj1N3BBkE=
|
||||
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
|
||||
github.com/go-redis/redis v6.14.2+incompatible h1:UE9pLhzmWf+xHNmZsoccjXosPicuiNaInPgym8nzfg0=
|
||||
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
|
||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
|
||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
||||
github.com/shirou/gopsutil v2.19.11+incompatible h1:lJHR0foqAjI4exXqWsU3DbH7bX1xvdhGdnXTIARA9W4=
|
||||
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||
github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
github.com/snail007/go-activerecord v0.0.0-20190813031814-2ac2f3d7cff0 h1:zru9A2cEdHTi1ly8KaAMMw8sS93U2nB1LSvc+YwUCc4=
|
||||
github.com/snail007/go-activerecord v0.0.0-20190813031814-2ac2f3d7cff0/go.mod h1:2oXFU20cqErcrOV0B5VjMDuEZBcT9RUUL89uBR3QjsE=
|
||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||
golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 h1:et7+NAX3lLIk5qUCTA9QelBjGE/NkhzYw/mhnr0s7nI=
|
||||
golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
gopkg.in/russross/blackfriday.v2 v2.0.0 h1:+FlnIV8DSQnT7NZ43hcVKcdJdzZoeCmJj4Ql8gq5keA=
|
||||
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -0,0 +1,179 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/phachon/mm-wiki/install/storage"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type BaseController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type JsonResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message interface{} `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
Redirect map[string]interface{} `json:"redirect"`
|
||||
}
|
||||
|
||||
// prepare
|
||||
func (this *BaseController) Prepare() {
|
||||
controllerName, actionName := this.GetControllerAndAction()
|
||||
controllerName = strings.ToLower(controllerName[0 : len(controllerName)-10])
|
||||
methodName := strings.ToLower(actionName)
|
||||
if (methodName == "index") || (methodName == "end") || (methodName == "status") {
|
||||
return
|
||||
}
|
||||
if storage.Data.Status == storage.Install_Start {
|
||||
if methodName == "ready" && this.isPost() {
|
||||
return
|
||||
}
|
||||
this.Redirect("/install/end", 302)
|
||||
this.StopRun()
|
||||
}
|
||||
if storage.Data.Status == storage.Install_End {
|
||||
if storage.Data.IsSuccess == storage.Install_Failed {
|
||||
// 重置
|
||||
storage.Data.IsSuccess = storage.Install_Default
|
||||
storage.Data.Status = storage.Install_Ready
|
||||
storage.Data.Result = ""
|
||||
} else {
|
||||
this.StopRun()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// view layout title
|
||||
func (this *BaseController) viewLayoutTitle(title, viewName, layout string) {
|
||||
this.Layout = "install/layout.html"
|
||||
this.TplName = viewName + ".html"
|
||||
this.Data["title"] = title
|
||||
this.Data["copyright"] = storage.CopyRight
|
||||
this.Render()
|
||||
}
|
||||
|
||||
// view layout
|
||||
func (this *BaseController) viewLayout(viewName, layout string) {
|
||||
this.Layout = "install/layout.html"
|
||||
this.TplName = viewName + ".html"
|
||||
this.Data["title"] = ""
|
||||
this.Data["copyright"] = storage.CopyRight
|
||||
this.Render()
|
||||
}
|
||||
|
||||
// view
|
||||
func (this *BaseController) view(viewName string) {
|
||||
this.Layout = "install/layout.html"
|
||||
this.TplName = viewName + ".html"
|
||||
this.Data["title"] = ""
|
||||
this.Data["copyright"] = storage.CopyRight
|
||||
this.Render()
|
||||
}
|
||||
|
||||
// error view
|
||||
func (this *BaseController) viewError(errorMessage string, data ...interface{}) {
|
||||
this.Layout = "layout/install.html"
|
||||
redirect := "/"
|
||||
sleep := 2000
|
||||
if len(data) > 0 {
|
||||
redirect = data[0].(string)
|
||||
}
|
||||
if len(data) > 1 {
|
||||
sleep = data[1].(int)
|
||||
}
|
||||
_, actionName := this.GetControllerAndAction()
|
||||
methodName := strings.ToLower(actionName)
|
||||
this.TplName = "install/error.html"
|
||||
this.Data["title"] = "error"
|
||||
this.Data["method"] = methodName
|
||||
this.Data["message"] = errorMessage
|
||||
this.Data["redirect"] = redirect
|
||||
this.Data["sleep"] = sleep
|
||||
this.Data["copyright"] = storage.CopyRight
|
||||
this.Render()
|
||||
}
|
||||
|
||||
// view title
|
||||
func (this *BaseController) viewTitle(title, viewName string) {
|
||||
this.Layout = "install/layout.html"
|
||||
this.TplName = viewName + ".html"
|
||||
this.Data["title"] = title
|
||||
this.Data["copyright"] = storage.CopyRight
|
||||
this.Render()
|
||||
}
|
||||
|
||||
// return json success
|
||||
func (this *BaseController) jsonSuccess(message interface{}, data ...interface{}) {
|
||||
url := ""
|
||||
sleep := 300
|
||||
var _data interface{}
|
||||
if len(data) > 0 {
|
||||
_data = data[0]
|
||||
}
|
||||
if len(data) > 1 {
|
||||
url = data[1].(string)
|
||||
}
|
||||
if len(data) > 2 {
|
||||
sleep = data[2].(int)
|
||||
}
|
||||
this.Data["json"] = JsonResponse{
|
||||
Code: 1,
|
||||
Message: message,
|
||||
Data: _data,
|
||||
Redirect: map[string]interface{}{
|
||||
"url": url,
|
||||
"sleep": sleep,
|
||||
},
|
||||
}
|
||||
|
||||
j, err := json.MarshalIndent(this.Data["json"], "", "\t")
|
||||
if err != nil {
|
||||
this.Abort(err.Error())
|
||||
} else {
|
||||
this.Abort(string(j))
|
||||
}
|
||||
}
|
||||
|
||||
// return json error
|
||||
func (this *BaseController) jsonError(message interface{}, data ...interface{}) {
|
||||
url := ""
|
||||
sleep := 2000
|
||||
var _data interface{}
|
||||
if len(data) > 0 {
|
||||
_data = data[0]
|
||||
}
|
||||
if len(data) > 1 {
|
||||
url = data[1].(string)
|
||||
}
|
||||
if len(data) > 2 {
|
||||
sleep = data[2].(int)
|
||||
}
|
||||
this.Data["json"] = JsonResponse{
|
||||
Code: 0,
|
||||
Message: message,
|
||||
Data: _data,
|
||||
Redirect: map[string]interface{}{
|
||||
"url": url,
|
||||
"sleep": sleep,
|
||||
},
|
||||
}
|
||||
j, err := json.MarshalIndent(this.Data["json"], "", " \t")
|
||||
if err != nil {
|
||||
this.Abort(err.Error())
|
||||
} else {
|
||||
this.Abort(string(j))
|
||||
}
|
||||
}
|
||||
|
||||
// get client ip
|
||||
func (this *BaseController) getClientIp() string {
|
||||
s := strings.Split(this.Ctx.Request.RemoteAddr, ":")
|
||||
return s[0]
|
||||
}
|
||||
|
||||
// is post
|
||||
func (this *BaseController) isPost() bool {
|
||||
return this.Ctx.Input.IsPost()
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego/validation"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/phachon/mm-wiki/global"
|
||||
"github.com/phachon/mm-wiki/install/storage"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type InstallController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// 安装首页
|
||||
func (this *InstallController) Index() {
|
||||
this.view("install/index")
|
||||
}
|
||||
|
||||
// 许可协议
|
||||
func (this *InstallController) License() {
|
||||
|
||||
if this.isPost() {
|
||||
licenseAgree := this.GetString("license_agree", "")
|
||||
if licenseAgree == "" || licenseAgree == "0" {
|
||||
this.jsonError("请先同意协议后再继续")
|
||||
}
|
||||
storage.Data.License = storage.License_Agree
|
||||
this.jsonSuccess("", nil, "/install/env")
|
||||
} else {
|
||||
bytes, _ := ioutil.ReadFile(filepath.Join(storage.RootDir, "./LICENSE"))
|
||||
license := string(bytes)
|
||||
this.Data["license"] = license
|
||||
this.Data["license_agree"] = storage.Data.License
|
||||
|
||||
this.view("install/license")
|
||||
}
|
||||
}
|
||||
|
||||
// 环境检测
|
||||
func (this *InstallController) Env() {
|
||||
|
||||
if this.isPost() {
|
||||
if storage.Data.Env == storage.Env_NotAccess {
|
||||
this.jsonError("环境检测未通过")
|
||||
}
|
||||
storage.Data.Env = storage.Env_Access
|
||||
this.jsonSuccess("", nil, "/install/config")
|
||||
}
|
||||
storage.Data.Env = storage.Env_Access
|
||||
//获取服务器信息
|
||||
host := utils.Misc.GetLocalIp()
|
||||
osSys := runtime.GOOS
|
||||
server := map[string]string{
|
||||
"host": host,
|
||||
"sys": osSys,
|
||||
"install_dir": storage.RootDir,
|
||||
"version": global.SYSTEM_VERSION,
|
||||
}
|
||||
|
||||
// 环境检测
|
||||
vm, _ := mem.VirtualMemory()
|
||||
vmTotal := vm.Total / 1024 / 1024
|
||||
cpuCount, _ := cpu.Counts(true)
|
||||
memData := map[string]interface{}{
|
||||
"name": "内存",
|
||||
"require": "400M",
|
||||
"value": strconv.FormatInt(int64(vmTotal), 10) + "M",
|
||||
"result": "1",
|
||||
}
|
||||
if int(vmTotal) < 400 {
|
||||
storage.Data.Env = storage.Env_NotAccess
|
||||
memData["result"] = "0"
|
||||
}
|
||||
cpuData := map[string]interface{}{
|
||||
"name": "CPU",
|
||||
"require": "1核",
|
||||
"value": strconv.Itoa(cpuCount) + "核",
|
||||
"result": "1",
|
||||
}
|
||||
if cpuCount < 1 {
|
||||
storage.Data.Env = storage.Env_NotAccess
|
||||
cpuData["result"] = "0"
|
||||
}
|
||||
envData := []map[string]interface{}{}
|
||||
envData = append(envData, memData)
|
||||
envData = append(envData, cpuData)
|
||||
|
||||
// 目录文件检测
|
||||
fileTool := utils.NewFile()
|
||||
templateConfDir := map[string]string{
|
||||
"path": "conf/template.conf",
|
||||
"require": "读/写",
|
||||
"result": "1",
|
||||
}
|
||||
err := fileTool.IsWriterReadable(filepath.Join(storage.RootDir, templateConfDir["path"]))
|
||||
if err != nil {
|
||||
storage.Data.Env = storage.Env_NotAccess
|
||||
templateConfDir["result"] = "0"
|
||||
}
|
||||
|
||||
databaseTable := map[string]string{
|
||||
"path": "docs/databases/table.sql",
|
||||
"require": "读/写",
|
||||
"result": "1",
|
||||
}
|
||||
err = fileTool.IsWriterReadable(filepath.Join(storage.RootDir, databaseTable["path"]))
|
||||
if err != nil {
|
||||
storage.Data.Env = storage.Env_NotAccess
|
||||
databaseTable["result"] = "0"
|
||||
}
|
||||
|
||||
databaseData := map[string]string{
|
||||
"path": "docs/databases/data.sql",
|
||||
"require": "读/写",
|
||||
"result": "1",
|
||||
}
|
||||
err = fileTool.IsWriterReadable(filepath.Join(storage.RootDir, databaseData["path"]))
|
||||
if err != nil {
|
||||
storage.Data.Env = storage.Env_NotAccess
|
||||
databaseData["result"] = "0"
|
||||
}
|
||||
|
||||
viewsDir := map[string]string{
|
||||
"path": "views",
|
||||
"require": "存在且不为空",
|
||||
"result": "1",
|
||||
}
|
||||
isEmpty := utils.File.PathIsEmpty(filepath.Join(storage.RootDir, viewsDir["path"]))
|
||||
if isEmpty == true {
|
||||
storage.Data.Env = storage.Env_NotAccess
|
||||
viewsDir["result"] = "0"
|
||||
}
|
||||
|
||||
staticDir := map[string]string{
|
||||
"path": "static",
|
||||
"require": "存在且不为空",
|
||||
"result": "1",
|
||||
}
|
||||
isEmpty = utils.File.PathIsEmpty(filepath.Join(storage.RootDir, staticDir["path"]))
|
||||
if isEmpty == true {
|
||||
storage.Data.Env = storage.Env_NotAccess
|
||||
staticDir["result"] = "0"
|
||||
}
|
||||
|
||||
dirData := []map[string]string{}
|
||||
dirData = append(dirData, templateConfDir)
|
||||
dirData = append(dirData, databaseTable)
|
||||
dirData = append(dirData, databaseData)
|
||||
dirData = append(dirData, viewsDir)
|
||||
dirData = append(dirData, staticDir)
|
||||
|
||||
this.Data["server"] = server
|
||||
this.Data["envData"] = envData
|
||||
this.Data["dirData"] = dirData
|
||||
this.view("install/env")
|
||||
}
|
||||
|
||||
// 系统配置
|
||||
func (this *InstallController) Config() {
|
||||
|
||||
if this.isPost() {
|
||||
addr := strings.TrimSpace(this.GetString("addr", ""))
|
||||
documentDir := strings.TrimSpace(this.GetString("document_dir", ""))
|
||||
port, _ := this.GetInt32("port", 0)
|
||||
|
||||
if addr == "" {
|
||||
this.jsonError("addr 不能为空,默认请填写 0.0.0.0")
|
||||
}
|
||||
if port == 0 {
|
||||
this.jsonError("启动端口不能为空")
|
||||
}
|
||||
if port > int32(65535) {
|
||||
this.jsonError("端口超出范围")
|
||||
}
|
||||
if documentDir == "" {
|
||||
this.jsonError("文档保存目录不能为空")
|
||||
}
|
||||
if !filepath.IsAbs(documentDir) {
|
||||
this.jsonError("文档保存目录不是绝对路径")
|
||||
}
|
||||
docAbsDir, err := filepath.Abs(documentDir)
|
||||
if err != nil {
|
||||
this.jsonError("文档保存目录错误!")
|
||||
}
|
||||
ok, _ := utils.File.PathIsExists(docAbsDir)
|
||||
if !ok {
|
||||
this.jsonError("文档保存目录不存在!")
|
||||
}
|
||||
|
||||
storage.Data.SystemConf = map[string]string{
|
||||
"addr": addr,
|
||||
"port": strconv.FormatInt(int64(port), 10),
|
||||
"document_dir": documentDir,
|
||||
}
|
||||
storage.Data.System = storage.Sys_Access
|
||||
this.jsonSuccess("", nil, "/install/database")
|
||||
}
|
||||
|
||||
sysConf := storage.Data.SystemConf
|
||||
this.Data["sysConf"] = sysConf
|
||||
this.view("install/config")
|
||||
}
|
||||
|
||||
// 数据库配置
|
||||
func (this *InstallController) Database() {
|
||||
|
||||
if !this.isPost() {
|
||||
this.Data["databaseConf"] = storage.Data.DatabaseConf
|
||||
this.viewLayoutTitle("mm-wiki-安装-数据库配置", "install/database", "install")
|
||||
return
|
||||
}
|
||||
|
||||
host := strings.TrimSpace(this.GetString("host", ""))
|
||||
port := strings.TrimSpace(this.GetString("port", ""))
|
||||
name := strings.TrimSpace(this.GetString("name", ""))
|
||||
user := strings.TrimSpace(this.GetString("user", ""))
|
||||
pass := strings.TrimSpace(this.GetString("pass", ""))
|
||||
connMaxIdle := strings.TrimSpace(this.GetString("conn_max_idle", "0"))
|
||||
connMaxConn := strings.TrimSpace(this.GetString("conn_max_connection", "0"))
|
||||
adminName := strings.TrimSpace(this.GetString("admin_name", ""))
|
||||
adminPass := strings.TrimSpace(this.GetString("admin_pass", ""))
|
||||
|
||||
if host == "" {
|
||||
this.jsonError("数据库 host 不能为空!")
|
||||
}
|
||||
if port == "" {
|
||||
this.jsonError("数据库端口不能为空!")
|
||||
}
|
||||
if name == "" {
|
||||
this.jsonError("数据库名不能为空!")
|
||||
}
|
||||
if user == "" {
|
||||
this.jsonError("数据库用户名不能为空!")
|
||||
}
|
||||
if pass == "" {
|
||||
this.jsonError("数据库密码不能为空!")
|
||||
}
|
||||
if connMaxIdle == "0" {
|
||||
this.jsonError("数据库连接数不能为0!")
|
||||
}
|
||||
if connMaxConn == "0" {
|
||||
this.jsonError("最大连接数不能为0!")
|
||||
}
|
||||
if adminName == "" {
|
||||
this.jsonError("超级管理员用户名不能为空!")
|
||||
} else {
|
||||
v := validation.Validation{}
|
||||
if !v.AlphaNumeric(adminName, "admin_name").Ok {
|
||||
this.jsonError("用户名格式不正确!")
|
||||
}
|
||||
}
|
||||
|
||||
if adminPass == "" {
|
||||
this.jsonError("超级管理员密码不能为空!")
|
||||
}
|
||||
|
||||
storage.Data.DatabaseConf = map[string]string{
|
||||
"host": host,
|
||||
"port": port,
|
||||
"name": name,
|
||||
"user": user,
|
||||
"pass": pass,
|
||||
"conn_max_idle": connMaxIdle,
|
||||
"conn_max_connection": connMaxConn,
|
||||
"admin_name": adminName,
|
||||
"admin_pass": adminPass,
|
||||
}
|
||||
storage.Data.Database = storage.Database_Access
|
||||
this.jsonSuccess("", nil, "/install/ready")
|
||||
}
|
||||
|
||||
// 安装准备
|
||||
func (this *InstallController) Ready() {
|
||||
|
||||
if this.isPost() {
|
||||
if (storage.Data.License != storage.License_Agree) ||
|
||||
(storage.Data.Env != storage.Env_Access) ||
|
||||
(storage.Data.System != storage.Sys_Access) ||
|
||||
(storage.Data.Database != storage.Database_Access) {
|
||||
this.jsonError("请先完成安装准备")
|
||||
}
|
||||
storage.StartInstall()
|
||||
this.jsonSuccess("", nil, "/install/end")
|
||||
}
|
||||
|
||||
// 协议
|
||||
licenseConf := map[string]interface{}{
|
||||
"name": "许可协议",
|
||||
"value": "同意",
|
||||
"result": "1",
|
||||
"url": "/install/license",
|
||||
}
|
||||
if storage.Data.License != storage.License_Agree {
|
||||
licenseConf["value"] = "未同意"
|
||||
licenseConf["result"] = "0"
|
||||
}
|
||||
//环境检测
|
||||
envConf := map[string]interface{}{
|
||||
"name": "环境检测",
|
||||
"value": "通过",
|
||||
"result": "1",
|
||||
"url": "/install/env",
|
||||
}
|
||||
if storage.Data.Env != storage.Env_Access {
|
||||
envConf["value"] = "未通过"
|
||||
envConf["result"] = "0"
|
||||
}
|
||||
//系统配置
|
||||
sysConf := map[string]interface{}{
|
||||
"name": "系统配置",
|
||||
"value": "完成",
|
||||
"result": "1",
|
||||
"url": "/install/config",
|
||||
}
|
||||
if storage.Data.System != storage.Sys_Access {
|
||||
sysConf["value"] = "未完成"
|
||||
sysConf["result"] = "0"
|
||||
}
|
||||
//数据库配置
|
||||
databaseConf := map[string]interface{}{
|
||||
"name": "数据库配置",
|
||||
"value": "完成",
|
||||
"result": "1",
|
||||
"url": "/install/database",
|
||||
}
|
||||
if storage.Data.Database != storage.Database_Access {
|
||||
databaseConf["value"] = "未完成"
|
||||
databaseConf["result"] = "0"
|
||||
}
|
||||
|
||||
readyConf := []map[string]interface{}{}
|
||||
readyConf = append(readyConf, licenseConf)
|
||||
readyConf = append(readyConf, envConf)
|
||||
readyConf = append(readyConf, sysConf)
|
||||
readyConf = append(readyConf, databaseConf)
|
||||
|
||||
this.Data["readyConf"] = readyConf
|
||||
this.view("install/ready")
|
||||
}
|
||||
|
||||
// 安装完成
|
||||
func (this *InstallController) End() {
|
||||
|
||||
if storage.Data.Status == storage.Install_Ready {
|
||||
this.Redirect("/install/ready", 302)
|
||||
}
|
||||
|
||||
this.view("install/end")
|
||||
}
|
||||
|
||||
// 获取状态
|
||||
func (this *InstallController) Status() {
|
||||
|
||||
data := map[string]interface{}{
|
||||
"status": storage.Data.Status,
|
||||
"is_success": storage.Data.IsSuccess,
|
||||
"result": storage.Data.Result,
|
||||
}
|
||||
|
||||
this.jsonSuccess("ok", data)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/phachon/mm-wiki/install/storage"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// install
|
||||
|
||||
var (
|
||||
port = flag.String("port", "8090", "please input listen port")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
_, err := os.Stat(filepath.Join(storage.RootDir, "./install.lock"))
|
||||
if err == nil || !os.IsNotExist(err) {
|
||||
log.Println("MM-Wiki already installed!")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
//beego.BConfig.RunMode = "prod"
|
||||
beego.Run(":" + *port)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/phachon/mm-wiki/install/controllers"
|
||||
"github.com/phachon/mm-wiki/install/storage"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
storage.InstallDir, _ = filepath.Abs(filepath.Dir(os.Args[0]))
|
||||
storage.RootDir = filepath.Join(storage.InstallDir, "../")
|
||||
|
||||
beego.AppConfig.Set("sys.name", "mm-wiki-installer")
|
||||
beego.BConfig.AppName = beego.AppConfig.String("sys.name")
|
||||
beego.BConfig.ServerName = beego.AppConfig.String("sys.name")
|
||||
|
||||
// set static path
|
||||
beego.SetStaticPath("/static/", filepath.Join(storage.InstallDir, "../static"))
|
||||
// views path
|
||||
beego.BConfig.WebConfig.ViewsPath = filepath.Join(storage.InstallDir, "../views/")
|
||||
|
||||
// session
|
||||
beego.BConfig.WebConfig.Session.SessionName = "mmwikiinstallssid"
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
|
||||
// router
|
||||
beego.BConfig.WebConfig.AutoRender = false
|
||||
beego.BConfig.RouterCaseSensitive = false
|
||||
|
||||
beego.AutoRouter(&controllers.InstallController{})
|
||||
beego.Router("/", &controllers.InstallController{}, "*:Index")
|
||||
beego.ErrorHandler("404", http_404)
|
||||
beego.ErrorHandler("500", http_500)
|
||||
|
||||
// add template func
|
||||
beego.AddFuncMap("dateFormat", utils.NewDate().Format)
|
||||
|
||||
}
|
||||
|
||||
func http_404(rs http.ResponseWriter, req *http.Request) {
|
||||
rs.Write([]byte("404 not found!"))
|
||||
}
|
||||
|
||||
func http_500(rs http.ResponseWriter, req *http.Request) {
|
||||
rs.Write([]byte("500 server error!"))
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/phachon/mm-wiki/app/utils"
|
||||
"github.com/phachon/mm-wiki/global"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Data = NewData()
|
||||
|
||||
installChan = make(chan int, 1)
|
||||
|
||||
InstallDir = ""
|
||||
|
||||
RootDir = ""
|
||||
|
||||
CopyRight = global.SYSTEM_COPYRIGHT
|
||||
)
|
||||
|
||||
const License_Disagree = 0 // 协议不同意
|
||||
const License_Agree = 1 // 协议同意
|
||||
|
||||
const Env_NotAccess = 0 // 环境检测不通过
|
||||
const Env_Access = 1 // 环境检测通过
|
||||
|
||||
const Sys_NotAccess = 0 // 系统配置不通过
|
||||
const Sys_Access = 1 // 系统配置通过
|
||||
|
||||
const Database_NotAccess = 0 // 数据库配置不通过
|
||||
const Database_Access = 1 // 数据库配置通过
|
||||
|
||||
const Install_Ready = 0 // 安装准备阶段
|
||||
const Install_Start = 1 // 安装开始
|
||||
const Install_End = 2 // 安装完成
|
||||
|
||||
const Install_Default = 0 // 默认
|
||||
const Install_Failed = 1 // 安装失败
|
||||
const Install_Success = 2 // 安装成功
|
||||
|
||||
var defaultSystemConf = map[string]string{
|
||||
"addr": "0.0.0.0",
|
||||
"port": "8080",
|
||||
"document_dir": "",
|
||||
}
|
||||
|
||||
var defaultDatabaseConf = map[string]string{
|
||||
"host": "127.0.0.1",
|
||||
"port": "3306",
|
||||
"name": "mm_wiki",
|
||||
"user": "",
|
||||
"pass": "",
|
||||
"conn_max_idle": "30",
|
||||
"conn_max_connection": "200",
|
||||
"admin_name": "",
|
||||
"admin_pass": "",
|
||||
}
|
||||
|
||||
func NewData() *data {
|
||||
return &data{
|
||||
License: License_Disagree,
|
||||
Env: Env_NotAccess,
|
||||
System: Sys_NotAccess,
|
||||
Database: Database_NotAccess,
|
||||
SystemConf: defaultSystemConf,
|
||||
DatabaseConf: defaultDatabaseConf,
|
||||
Status: Install_Ready,
|
||||
Result: "",
|
||||
IsSuccess: Install_Default,
|
||||
}
|
||||
}
|
||||
|
||||
type data struct {
|
||||
License int
|
||||
Env int
|
||||
System int
|
||||
Database int
|
||||
SystemConf map[string]string
|
||||
DatabaseConf map[string]string
|
||||
Status int
|
||||
Result string
|
||||
IsSuccess int
|
||||
}
|
||||
|
||||
// check db
|
||||
func checkDB() (err error) {
|
||||
|
||||
host := Data.DatabaseConf["host"]
|
||||
port := Data.DatabaseConf["port"]
|
||||
user := Data.DatabaseConf["user"]
|
||||
pass := Data.DatabaseConf["pass"]
|
||||
|
||||
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.Ping()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// create db
|
||||
func createDB() (err error) {
|
||||
host := Data.DatabaseConf["host"]
|
||||
port := Data.DatabaseConf["port"]
|
||||
user := Data.DatabaseConf["user"]
|
||||
pass := Data.DatabaseConf["pass"]
|
||||
name := Data.DatabaseConf["name"]
|
||||
|
||||
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
_, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + name + " CHARACTER SET utf8")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// create table
|
||||
func createTable() (err error) {
|
||||
|
||||
host := Data.DatabaseConf["host"]
|
||||
port := Data.DatabaseConf["port"]
|
||||
user := Data.DatabaseConf["user"]
|
||||
pass := Data.DatabaseConf["pass"]
|
||||
name := Data.DatabaseConf["name"]
|
||||
|
||||
sqlBytes, err := ioutil.ReadFile(filepath.Join(RootDir, "docs/databases/table.sql"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sqlTable := string(sqlBytes)
|
||||
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/"+name+"?charset=utf8&multiStatements=true")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
_, err = db.Exec(sqlTable)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// create admin
|
||||
func createAdmin() (err error) {
|
||||
host := Data.DatabaseConf["host"]
|
||||
port := Data.DatabaseConf["port"]
|
||||
user := Data.DatabaseConf["user"]
|
||||
pass := Data.DatabaseConf["pass"]
|
||||
name := Data.DatabaseConf["name"]
|
||||
adminName := Data.DatabaseConf["admin_name"]
|
||||
adminPass := utils.NewEncrypt().Md5Encode(Data.DatabaseConf["admin_pass"])
|
||||
|
||||
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/"+name+"?charset=utf8")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
stmt, err := db.Prepare("INSERT mw_user SET username=?,password=?,given_name=?,role_id=?, create_time=?,update_time=?")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer stmt.Close()
|
||||
_, err = stmt.Exec(adminName, adminPass, adminName, 1, time.Now().Unix(), time.Now().Unix())
|
||||
return
|
||||
}
|
||||
|
||||
// write database install data
|
||||
func writeInstallData() (err error) {
|
||||
host := Data.DatabaseConf["host"]
|
||||
port := Data.DatabaseConf["port"]
|
||||
user := Data.DatabaseConf["user"]
|
||||
pass := Data.DatabaseConf["pass"]
|
||||
name := Data.DatabaseConf["name"]
|
||||
|
||||
sqlBytes, err := ioutil.ReadFile(filepath.Join(RootDir, "docs/databases/data.sql"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sqlTable := string(sqlBytes)
|
||||
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/"+name+"?charset=utf8&multiStatements=true")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
_, err = db.Exec(sqlTable)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// insert version
|
||||
stmt, err := db.Prepare("INSERT mw_config SET `name`=?,`key`=?,`value`=?,create_time=?,update_time=?;")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer stmt.Close()
|
||||
_, err = stmt.Exec("系统版本号", "system_version", global.SYSTEM_VERSION, time.Now().Unix(), time.Now().Unix())
|
||||
return err
|
||||
}
|
||||
|
||||
// write conf
|
||||
func makeConf() (err error) {
|
||||
|
||||
templateConf, err := utils.NewFile().GetFileContents(filepath.Join(RootDir, "conf/template.conf"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// replace conf tag
|
||||
templateConf = strings.Replace(templateConf, "#httpaddr#", Data.SystemConf["addr"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#httpport#", Data.SystemConf["port"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#document_dir#", Data.SystemConf["document_dir"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#db.host#", Data.DatabaseConf["host"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#db.port#", Data.DatabaseConf["port"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#db.name#", Data.DatabaseConf["name"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#db.user#", Data.DatabaseConf["user"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#db.pass#", Data.DatabaseConf["pass"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#db.conn_max_idle#", Data.DatabaseConf["conn_max_idle"], 1)
|
||||
templateConf = strings.Replace(templateConf, "#db.conn_max_connection#", Data.DatabaseConf["conn_max_connection"], 1)
|
||||
|
||||
logFilename := strings.Replace(filepath.Join(RootDir, "logs/mm-wiki.log"), `\`, `/`, -1)
|
||||
templateConf = strings.Replace(templateConf, "#log.filename#", logFilename, 1)
|
||||
|
||||
fileObject, err := os.OpenFile(filepath.Join(RootDir, "conf/mm-wiki.conf"), os.O_RDWR|os.O_CREATE, 0777)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer fileObject.Close()
|
||||
|
||||
_, err = fileObject.Write([]byte(templateConf))
|
||||
return
|
||||
}
|
||||
|
||||
func installFailed(err string) {
|
||||
Data.Result = err
|
||||
Data.Status = Install_End
|
||||
Data.IsSuccess = Install_Failed
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
func installSuccess() {
|
||||
|
||||
Data.Status = Install_End
|
||||
Data.IsSuccess = Install_Success
|
||||
result := map[string]string{
|
||||
"cmd": "",
|
||||
"url": "http://127.0.0.1:" + Data.SystemConf["port"],
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
result["cmd"] = "mm-wiki.exe --conf conf/mm-wiki.conf"
|
||||
} else {
|
||||
result["cmd"] = "./mm-wiki --conf conf/mm-wiki.conf"
|
||||
}
|
||||
resByte, _ := json.Marshal(result)
|
||||
Data.Result = string(resByte)
|
||||
|
||||
// create install lock file
|
||||
file, _ := os.Create(filepath.Join(RootDir, "./install.lock"))
|
||||
file.Close()
|
||||
}
|
||||
|
||||
func StartInstall() {
|
||||
installChan <- 1
|
||||
}
|
||||
|
||||
func ListenInstall() {
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("install crash: %v", err))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-installChan:
|
||||
Data.Status = Install_Start
|
||||
// 开始安装
|
||||
log.Println("mm-wiki start install")
|
||||
// 检查db
|
||||
err := checkDB()
|
||||
if err != nil {
|
||||
installFailed("连接数据库出错:" + err.Error())
|
||||
continue
|
||||
}
|
||||
log.Println("database connect success")
|
||||
// 创建数据库
|
||||
err = createDB()
|
||||
if err != nil {
|
||||
installFailed("创建数据库出错:" + err.Error())
|
||||
continue
|
||||
}
|
||||
log.Println("create database success")
|
||||
// 创建表
|
||||
err = createTable()
|
||||
if err != nil {
|
||||
installFailed("创建表出错:" + err.Error())
|
||||
continue
|
||||
}
|
||||
log.Println("create table success")
|
||||
// 创建超级管理员
|
||||
err = createAdmin()
|
||||
if err != nil {
|
||||
installFailed("创建管理员账号出错:" + err.Error())
|
||||
continue
|
||||
}
|
||||
log.Println("create admin user success")
|
||||
// 写入安装数据
|
||||
err = writeInstallData()
|
||||
if err != nil {
|
||||
installFailed("导入安装数据出错:" + err.Error())
|
||||
continue
|
||||
}
|
||||
log.Println("write install data success")
|
||||
// 写入 conf 文件
|
||||
err = makeConf()
|
||||
if err != nil {
|
||||
installFailed("生成配置文件出错:" + err.Error())
|
||||
continue
|
||||
}
|
||||
log.Println("make conf file success")
|
||||
installSuccess()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func init() {
|
||||
ListenInstall()
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
*.log
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user