From e262248a6631a8d8cf34cad669adf481cff3d468 Mon Sep 17 00:00:00 2001 From: rekoe Date: Tue, 22 Mar 2016 17:51:42 +0800 Subject: [PATCH] add --- src/main/java/com/rekoe/domain/Usr.java | 11 + .../rekoe/module/admin/AdminProjectAct.java | 56 ++ .../rekoe/module/admin/AdminSvnUserAct.java | 55 ++ .../java/com/rekoe/module/admin/FrameAct.java | 170 +---- .../com/rekoe/module/admin/WelcomeAct.java | 1 + .../java/com/rekoe/service/ChangePackage.java | 42 ++ .../com/rekoe/service/PermissionService.java | 9 +- .../com/rekoe/service/ProjectAuthService.java | 361 ++++++++++ .../rekoe/service/ProjectGroupService.java | 34 + .../rekoe/service/ProjectGroupUsrService.java | 206 ++++++ .../com/rekoe/service/ProjectService.java | 152 +++++ .../com/rekoe/service/ProjectUserService.java | 49 ++ .../com/rekoe/service/RepositoryService.java | 224 +++++++ .../java/com/rekoe/service/RoleService.java | 8 +- .../java/com/rekoe/service/SvnService.java | 531 +++++++++++++++ .../com/rekoe/service/SvnUserService.java | 47 ++ .../java/com/rekoe/service/UsrService.java | 79 +++ src/main/java/com/rekoe/utils/Constants.java | 47 +- .../msg/zh_CN/MessageResources.properties | 618 ++++++------------ .../webapp/WEB-INF/template/admin/top.ftl | 10 +- 20 files changed, 2129 insertions(+), 581 deletions(-) create mode 100644 src/main/java/com/rekoe/module/admin/AdminProjectAct.java create mode 100644 src/main/java/com/rekoe/module/admin/AdminSvnUserAct.java create mode 100644 src/main/java/com/rekoe/service/ChangePackage.java create mode 100644 src/main/java/com/rekoe/service/ProjectAuthService.java create mode 100644 src/main/java/com/rekoe/service/ProjectGroupService.java create mode 100644 src/main/java/com/rekoe/service/ProjectGroupUsrService.java create mode 100644 src/main/java/com/rekoe/service/ProjectService.java create mode 100644 src/main/java/com/rekoe/service/ProjectUserService.java create mode 100644 src/main/java/com/rekoe/service/RepositoryService.java create mode 100644 src/main/java/com/rekoe/service/SvnService.java create mode 100644 src/main/java/com/rekoe/service/SvnUserService.java create mode 100644 src/main/java/com/rekoe/service/UsrService.java diff --git a/src/main/java/com/rekoe/domain/Usr.java b/src/main/java/com/rekoe/domain/Usr.java index 808646b..6f3f913 100644 --- a/src/main/java/com/rekoe/domain/Usr.java +++ b/src/main/java/com/rekoe/domain/Usr.java @@ -38,6 +38,9 @@ public class Usr implements Serializable { @Comment private String role; + @Comment + private String email; + /** * @return 用户ID */ @@ -45,6 +48,14 @@ public class Usr implements Serializable { return usr; } + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + /** * @param usr * 用户ID diff --git a/src/main/java/com/rekoe/module/admin/AdminProjectAct.java b/src/main/java/com/rekoe/module/admin/AdminProjectAct.java new file mode 100644 index 0000000..bdf1699 --- /dev/null +++ b/src/main/java/com/rekoe/module/admin/AdminProjectAct.java @@ -0,0 +1,56 @@ +package com.rekoe.module.admin; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import com.rekoe.annotation.PermissionTag; +import com.rekoe.common.Message; +import com.rekoe.common.page.Pagination; +import com.rekoe.domain.Pj; +import com.rekoe.module.BaseAction; +import com.rekoe.service.ProjectService; + +@IocBean +@At("/admin/project") +public class AdminProjectAct extends BaseAction{ + + @Inject + private ProjectService projectService; + + @At + @Ok("fm:template.admin.project.list") + @RequiresPermissions({ "svn.project:view" }) + @PermissionTag(name = "SVN浏览项目", tag = "SVN项目管理") + public Pagination list(@Param(value = "pageNumber", df = "1") int page) { + return projectService.getObjListByPager(page, 20, null); + } + + + @At + @Ok("fm:template.admin.project.add") + @RequiresPermissions({ "svn.project:add" }) + @PermissionTag(name = "SVN添加项目", tag = "SVN项目管理", enable = true) + public void add() { + } + + @At + @Ok("json") + @RequiresPermissions("svn.project:add") + @PermissionTag(name = "SVN添加项目", tag = "SVN项目管理", enable = false) + public Message o_save(@Param("::pj.") Pj pj, HttpServletRequest req) { + boolean isOk = projectService.nameOk(pj.getPj()); + if (isOk) { + isOk = projectService.insert(pj); + } + if (isOk) { + return Message.success("ok", req); + } + return Message.error("error", req); + } +} diff --git a/src/main/java/com/rekoe/module/admin/AdminSvnUserAct.java b/src/main/java/com/rekoe/module/admin/AdminSvnUserAct.java new file mode 100644 index 0000000..58ed2d7 --- /dev/null +++ b/src/main/java/com/rekoe/module/admin/AdminSvnUserAct.java @@ -0,0 +1,55 @@ +package com.rekoe.module.admin; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import com.rekoe.annotation.PermissionTag; +import com.rekoe.common.Message; +import com.rekoe.common.page.Pagination; +import com.rekoe.domain.Usr; +import com.rekoe.module.BaseAction; +import com.rekoe.service.SvnUserService; + +@IocBean +@At("/admin/svn/user") +public class AdminSvnUserAct extends BaseAction { + + @Inject + private SvnUserService svnUserService; + + @At + @Ok("fm:template.admin.svn_user.list") + @RequiresPermissions({ "svn.user:view" }) + @PermissionTag(name = "SVN浏览账号", tag = "SVN账号管理") + public Pagination list(@Param(value = "pageNumber", df = "1") int page) { + return svnUserService.getObjListByPager(page, 20, null); + } + + @At + @Ok("fm:template.admin.svn_user.add") + @RequiresPermissions({ "svn.user:add" }) + @PermissionTag(name = "SVN添加账号", tag = "SVN账号管理", enable = true) + public void add() { + } + + @At + @Ok("json") + @RequiresPermissions("svn.user:add") + @PermissionTag(name = "SVN添加账号", tag = "SVN账号管理", enable = false) + public Message o_save(@Param("::user.") Usr user, HttpServletRequest req) { + boolean isOk = svnUserService.nameOk(user.getUsr()); + if (isOk) { + isOk = svnUserService.insert(user); + } + if (isOk) { + return Message.success("ok", req); + } + return Message.error("error", req); + } +} diff --git a/src/main/java/com/rekoe/module/admin/FrameAct.java b/src/main/java/com/rekoe/module/admin/FrameAct.java index c485a73..5f969c9 100644 --- a/src/main/java/com/rekoe/module/admin/FrameAct.java +++ b/src/main/java/com/rekoe/module/admin/FrameAct.java @@ -23,26 +23,9 @@ public class FrameAct { public void userRight() { } - // Server - @At("/admin/frame/server/main") - @Ok("fm:template.admin.server.frame.main") - public void serverMain() { - } - - @At("/admin/frame/server/left") - @Ok("fm:template.admin.server.frame.left") - public void serverLeft() { - } - - @At("/admin/frame/server/right") - @Ok("fm:template.admin.server.frame.right") - public void serverRight() { - } - /* * 修改密码 */ - // 系统配置 @At("/admin/frame/account/main") @Ok("fm:template.admin.account.frame.main") public void accountPwdMain() { @@ -58,150 +41,39 @@ public class FrameAct { public void gamePwdRight() { } - /** - * 用户操作日志 + /*** + * SVN 账号 */ - - @At("/admin/frame/system/log/main") - @Ok("fm:template.admin.system.log.frame.main") - public void system_log_main() { + @At("/admin/frame/svn/user/main") + @Ok("fm:template.admin.svn_user.frame.main") + public void svn_user_main() { } - @At("/admin/frame/system/log/left") - @Ok("fm:template.admin.system.log.frame.left") - public void system_log_left() { + @At("/admin/frame/svn/user/left") + @Ok("fm:template.admin.svn_user.frame.left") + public void svn_user_left() { } - @At("/admin/frame/system/log/right") - @Ok("fm:template.admin.system.log.frame.right") - public void system_log_right() { - } - - /** - * 账号处理 - */ - - @At("/admin/frame/pay_refund/main") - @Ok("fm:template.admin.pay_refund.frame.main") - public void pay_refund_main() { - } - - @At("/admin/frame/pay_refund/left") - @Ok("fm:template.admin.pay_refund.frame.left") - public void pay_refund_left() { - } - - @At("/admin/frame/pay_refund/right") - @Ok("fm:template.admin.pay_refund.frame.right") - public void pay_refund_right() { - } - - /** - * 退单处理 - */ - - @At("/admin/app/frame/account/main") - @Ok("fm:template.admin.app.account.frame.main") - public void app_account_main() { - } - - @At("/admin/app/frame/account/left") - @Ok("fm:template.admin.app.account.frame.left") - public void app_account_left() { - } - - @At("/admin/app/frame/account/right") - @Ok("fm:template.admin.app.account.frame.right") - public void app_account_right() { - } - - /** - * CDKEY - */ - @At("/admin/frame/cdkey/main") - @Ok("fm:template.admin.cdkey.frame.main") - public void cdkey_main() { - } - - @At("/admin/frame/cdkey/left") - @Ok("fm:template.admin.cdkey.frame.left") - public void cdkey_left() { - } - - @At("/admin/frame/cdkey/right") - @Ok("fm:template.admin.cdkey.frame.right") - public void cdkey_right() { + @At("/admin/frame/svn/user/right") + @Ok("fm:template.admin.svn_user.frame.right") + public void svn_user_right() { } /*** - * oauth_client + * SVN Project */ - @At("/admin/frame/oauth_client/main") - @Ok("fm:template.admin.oauth_client.frame.main") - public void oauth_client_main() { + @At("/admin/frame/project/main") + @Ok("fm:template.admin.project.frame.main") + public void project_main() { } - @At("/admin/frame/oauth_client/left") - @Ok("fm:template.admin.oauth_client.frame.left") - public void oauth_client_left() { + @At("/admin/frame/project/left") + @Ok("fm:template.admin.project.frame.left") + public void project_left() { } - @At("/admin/frame/oauth_client/right") - @Ok("fm:template.admin.oauth_client.frame.right") - public void oauth_client_right() { - } - - /*** - * oauth_user - */ - @At("/admin/frame/oauth_user/main") - @Ok("fm:template.admin.oauth_user.frame.main") - public void oauth_user_main() { - } - - @At("/admin/frame/oauth_user/left") - @Ok("fm:template.admin.oauth_user.frame.left") - public void oauth_user_left() { - } - - @At("/admin/frame/oauth_user/right") - @Ok("fm:template.admin.oauth_user.frame.right") - public void oauth_user_right() { - } - - /** - * 公告 - */ - @At("/admin/frame/notice/main") - @Ok("fm:template.admin.notice.frame.main") - public void notice_main() { - } - - @At("/admin/frame/notice/left") - @Ok("fm:template.admin.notice.frame.left") - public void notice_left() { - } - - @At("/admin/frame/notice/right") - @Ok("fm:template.admin.notice.frame.right") - public void notice_right() { - } - - /** - * 数据汇报 - */ - @At("/admin/frame/report/main") - @Ok("fm:template.admin.report.frame.main") - public void report_main() { - } - - @At("/admin/frame/report/left") - @Ok("fm:template.admin.report.frame.left") - public void report_left() { - } - - @At("/admin/frame/report/right") - @Ok("fm:template.admin.report.frame.right") - public void report_right() { + @At("/admin/frame/project/right") + @Ok("fm:template.admin.project.frame.right") + public void project_right() { } } diff --git a/src/main/java/com/rekoe/module/admin/WelcomeAct.java b/src/main/java/com/rekoe/module/admin/WelcomeAct.java index 6308025..1d63f14 100644 --- a/src/main/java/com/rekoe/module/admin/WelcomeAct.java +++ b/src/main/java/com/rekoe/module/admin/WelcomeAct.java @@ -38,4 +38,5 @@ public class WelcomeAct extends BaseAction { @Ok("fm:template.admin.right") public void right() { } + } diff --git a/src/main/java/com/rekoe/service/ChangePackage.java b/src/main/java/com/rekoe/service/ChangePackage.java new file mode 100644 index 0000000..69b2a50 --- /dev/null +++ b/src/main/java/com/rekoe/service/ChangePackage.java @@ -0,0 +1,42 @@ +package com.rekoe.service; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; + + + +import java.util.HashSet; +import java.util.Set; + +import org.nutz.lang.Files; +import org.nutz.lang.util.Disks; +import org.nutz.lang.util.FileVisitor; + +public class ChangePackage { + + public static void main(String[] args) throws IOException { + + final Set suffix = new HashSet(); + suffix.add("csd"); + FileFilter ff = new FileFilter() { + public boolean accept(File pathname) { + if (pathname.isDirectory()) + return true; + return suffix.contains(Files.getSuffixName(pathname)); + } + }; + FileVisitor fv = new FileVisitor() { + public void visit(File file) { + if (file.isDirectory()) + return; + String origin = Files.read(file); + String output = origin.replaceAll("WenQuanYi Micro Hei.ttf", "FZY4JW_0.ttf"); + if (origin.equals(output)) + return; + Files.write(file, output); + } + }; + Disks.visitFile(new File("D:/sources"), fv, ff); + } +} diff --git a/src/main/java/com/rekoe/service/PermissionService.java b/src/main/java/com/rekoe/service/PermissionService.java index dec66bd..fda8ded 100644 --- a/src/main/java/com/rekoe/service/PermissionService.java +++ b/src/main/java/com/rekoe/service/PermissionService.java @@ -14,11 +14,12 @@ import org.nutz.service.IdEntityService; import com.rekoe.common.page.Pagination; import com.rekoe.domain.Permission; + /** - * @author 科技㊣²º¹³ - * 2014年2月3日 下午4:48:45 - * http://www.rekoe.com - * QQ:5382211 + * @author 科技㊣²º¹³
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 */ @IocBean(args = { "refer:dao" }) public class PermissionService extends IdEntityService { diff --git a/src/main/java/com/rekoe/service/ProjectAuthService.java b/src/main/java/com/rekoe/service/ProjectAuthService.java new file mode 100644 index 0000000..862a760 --- /dev/null +++ b/src/main/java/com/rekoe/service/ProjectAuthService.java @@ -0,0 +1,361 @@ +package com.rekoe.service; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.sql.SqlCallback; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; + +import com.rekoe.domain.Pj; +import com.rekoe.domain.PjAuth; +import com.rekoe.utils.Constants; + +/** + * @author 科技㊣²º¹³
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 + */ +@IocBean(args = { "refer:dao" }) +public class ProjectAuthService extends BaseService { + + @Inject + private SvnService svnService; + + @Inject + private ProjectService projectService; + + public ProjectAuthService(Dao dao) { + super(dao); + } + + /** + * @param pj + * 项目 + * @return 项目的资源列表 + */ + public List getResList(String pj) { + Sql sql = Sqls.create("select distinct res from pj_gr_auth where pj=? UNION select distinct res from pj_usr_auth where pj=$pj order by res"); + sql.setCallback(Sqls.callback.strList()); + sql.setVar("pj", pj); + dao().execute(sql); + return sql.getList(String.class); + } + + /** + * @param pj + * 项目 + * @param res + * 资源 + * @return 项目资源的权限列表 + */ + public List list(String pj, String res) { + if (StringUtils.isBlank(res)) { + return getList(pj); + } + return getList(pj, res); + } + + /** + * @param pj + * 项目 + * @param res + * 资源 + * @return 项目资源的权限列表 + */ + private List getList(String pj, String res) { + String sqlStr = "select pj,res,rw,gr,' ' usr,' ' usrname from pj_gr_auth where pj=$pj and res = $res " + " UNION " + " select a.pj,a.res,a.rw,' ' gr,a.usr,b.name as usrname from pj_usr_auth a left join usr b on (a.usr=b.usr) where a.pj=$tpj and a.res = $tres " + " order by res,gr,usr"; + Sql sql = Sqls.create(sqlStr); + sql.setVar("pj", pj).setVar("res", res).setVar("tpj", pj).setVar("tres", res); + final List list = new ArrayList(); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + while (rs.next()) { + list.add(readPjAuth(rs)); + } + return list; + } + }); + return list; + } + + PjAuth readPjAuth(ResultSet rs) throws SQLException { + PjAuth result = new PjAuth(); + result.setPj(rs.getString("pj")); + result.setGr(rs.getString("gr")); + result.setUsr(rs.getString("usr")); + result.setUsrName(rs.getString("usrname")); + result.setRes(rs.getString("res")); + String rw = rs.getString("rw"); + if (StringUtils.isBlank(rw)) { + rw = ""; + } + result.setRw(rw); + return result; + } + + /** + * @param pj + * 项目 + * @return 项目资源的权限列表 + */ + public List getList(String pj) { + String sqlStr = "select pj,res,rw,gr,' ' usr,' ' usrname from pj_gr_auth where pj=$pj " + " UNION " + " select a.pj,a.res,a.rw,' ' gr,a.usr,b.name as usrname from pj_usr_auth a left join usr b on (a.usr = b.usr) where a.pj=$tpj " + " order by res,gr,usr"; + Sql sql = Sqls.create(sqlStr); + sql.setVar("pj", pj).setVar("tpj", pj); + final List list = new ArrayList(); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + while (rs.next()) { + list.add(readPjAuth(rs)); + } + return list; + } + }); + return list; + } + + /** + * 删除项目 组资源的权限 + * + * @param pj + * 项目 + * @param gr + * 组 + * @param res + * 资源 + */ + public void deleteByGr(String pj, String gr, String res) { + Sql sql = Sqls.create("delete from pj_gr_auth $condition"); + sql.setCondition(Cnd.where("pj", "=", pj).and("gr", "=", gr).and("res", "=", res)); + dao().execute(sql); + svnService.exportConfig(pj); + } + + /** + * 删除项目用户资源的权限 + * + * @param pj + * 项目 + * @param usr + * 用户 + * @param res + * 资源 + */ + public void deleteByUsr(String pj, String usr, String res) { + deleteByUsr(pj, usr, res); + svnService.exportConfig(pj); + } + + /** + * 保存 + * + * @param pj + * 项目 + * @param res + * 资源 + * @param rw + * 可读可写 + * @param grs + * 组 + * @param usrs + * 用户 + */ + public void save(String pj, String res, String rw, String[] grs, String[] usrs) { + res = this.formatRes(pj, res);// 如果资源没有[],自动加上 + // gr + if (grs != null) { + for (String gr : grs) { + if (StringUtils.isBlank(gr)) { + continue; + } + PjAuth pjAuth = new PjAuth(); + pjAuth.setPj(pj); + pjAuth.setRes(res); + pjAuth.setRw(rw); + pjAuth.setGr(gr); + saveByGr(pjAuth); + } + } + // usr + if (usrs != null) { + for (String usr : usrs) { + if (StringUtils.isBlank(usr)) { + continue; + } + PjAuth pjAuth = new PjAuth(); + pjAuth.setPj(pj); + pjAuth.setRes(res); + pjAuth.setRw(rw); + pjAuth.setUsr(usr); + saveByUsr(pjAuth); + } + } + // export + svnService.exportConfig(pj); + } + + /** + * @param pj + * 项目 + * @param usr + * 用户 + * @param res + * 资源 + * @return 项目用户资源的权限 + */ + public PjAuth getByUsr(String pj, String usr, String res) { + Sql sql = Sqls.create("select a.pj,a.res,a.rw,b.usr,b.name as usrname,' ' gr from pj_usr_auth a left join usr b on (a.usr=b.usr) where a.pj =$pj and a.usr=$usr and a.res=$res"); + sql.setVar("pj", pj).setVar("usr", usr).setVar("res", res); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + if (rs.next()) { + return readPjAuth(rs); + } + return null; + } + }); + dao().execute(sql); + return sql.getObject(PjAuth.class); + } + + /** + * 保存项目用户权限 + * + * @param pjAuth + * 项目用户权限 + */ + public void saveByUsr(PjAuth pjAuth) { + if (this.getByUsr(pjAuth.getPj(), pjAuth.getUsr(), pjAuth.getRes()) == null) { + dao().insert(pjAuth); + } else { + dao().update(getEntityClass(), Chain.make("rw", pjAuth.getRw()), Cnd.where("pj", "=", pjAuth.getPj()).and("usr", "=", pjAuth.getUsr()).and("res", "=", pjAuth.getRes())); + } + } + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @param res + * 资源 + * @return 项目组资源的权限 + */ + public PjAuth getByGr(String pj, String gr, String res) { + Sql sql = Sqls.create("select pj,res,rw,gr,' ' usr,' ' usrname from pj_gr_auth"); + sql.setCondition(Cnd.where("pj", "=", pj).and("gr", "=", gr).and("res", "=", res)); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + if (rs.next()) { + return readPjAuth(rs); + } + return null; + } + }); + dao().execute(sql); + return sql.getObject(PjAuth.class); + } + + /** + * 保存项目组权限 + * + * @param pjAuth + * 项目组权限 + */ + public void saveByGr(PjAuth pjAuth) { + if (this.getByGr(pjAuth.getPj(), pjAuth.getGr(), pjAuth.getRes()) == null) { + dao().insert(pjAuth); + } else { + dao().update(getEntityClass(), Chain.make("rw", pjAuth.getRw()), Cnd.where("pj", "=", pjAuth.getPj()).and("gr", "=", pjAuth.getGr()).and("res", "=", pjAuth.getRes())); + } + } + + /** + * 格式化资源.如果资源没有[],自动加上[relateRoot:/] + * + * @param pj + * 项目id + * @param res + * 资源 + * @return 格式化后的资源 + * @since 3.0.3 + */ + public String formatRes(String pj, String res) { + // 如果资源没有[],自动加上 + // if(!res.startsWith("[") && !res.endsWith("]")){ + return this.formatRes(this.projectService.get(pj), res); + // } + // return res; + } + + /** + * 格式化资源.如果资源没有[],自动加上[relateRoot:/] + * + * @param pj + * 项目 + * @param res + * 资源 + * @return 格式化后的资源 + * @since 3.0.3 + */ + public String formatRes(Pj pj, String res) { + // 去除[xxx:],重新加上[relateRoot:/],防止跨项目授权 + res = StringUtils.replaceEach(res, new String[] { "[", "]" }, new String[] { "", "" }); + if (res.indexOf(":") != -1) { + res = StringUtils.substringAfter(res, ":"); + } + + // 如果资源没有[],自动加上 + String relateRoot = projectService.getRelateRootPath(pj); + if (!res.startsWith("[") && !res.endsWith("]")) { + if (res.startsWith("/")) { + return "[" + relateRoot + ":" + res + "]"; + } else { + return "[" + relateRoot + ":/" + res + "]"; + } + } + return res; + } + + /** + * @param rootPath + * svn root path + * @return 具有相同svn root的项目资源的权限列表 + */ + public List getListByRootPath(String rootPath) { + Sql sql = Sqls.create("select pj,res,rw,gr,' ' usr,' ' usrname from pj_gr_auth where pj in (select distinct pj from pj where type=$type and path like $like) " + " UNION " + " select a.pj,a.res,a.rw,' ' gr,a.usr,b.name usrname from pj_usr_auth a left join usr b on (a.usr=b.usr) where a.pj in (select distinct pj from pj where type=$type and path like $like) " + " order by res,gr,usr"); + sql.setVar("type", Constants.HTTP_MUTIL).setVar("like", rootPath + "%"); + final List list = new ArrayList(); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + while (rs.next()) { + list.add(readPjAuth(rs)); + } + return list; + } + }); + dao().execute(sql); + return list; + } +} diff --git a/src/main/java/com/rekoe/service/ProjectGroupService.java b/src/main/java/com/rekoe/service/ProjectGroupService.java new file mode 100644 index 0000000..34c0879 --- /dev/null +++ b/src/main/java/com/rekoe/service/ProjectGroupService.java @@ -0,0 +1,34 @@ +package com.rekoe.service; + +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +import com.rekoe.domain.PjGr; + +/** + * @author 科技㊣²º¹³
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 + */ +@IocBean(args = { "refer:dao" }) +public class ProjectGroupService extends BaseService { + + public ProjectGroupService(Dao dao) { + super(dao); + } + + public PjGr get(String pj, String gr) { + return dao().fetch(getEntityClass(), Cnd.where("pj", "=", pj).and("gr", "=", gr)); + } + + public void save(PjGr pjGr) { + if (this.get(pjGr.getPj(), pjGr.getGr()) == null) { + dao().insert(pjGr); + } else { + dao().update(getEntityClass(), Chain.make("des", pjGr.getDes()), Cnd.where("pj", "=", pjGr.getPj()).and("gr", "=", pjGr.getGr())); + } + } +} diff --git a/src/main/java/com/rekoe/service/ProjectGroupUsrService.java b/src/main/java/com/rekoe/service/ProjectGroupUsrService.java new file mode 100644 index 0000000..22b0e07 --- /dev/null +++ b/src/main/java/com/rekoe/service/ProjectGroupUsrService.java @@ -0,0 +1,206 @@ +package com.rekoe.service; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.sql.SqlCallback; +import org.nutz.ioc.loader.annotation.IocBean; + +import com.rekoe.domain.PjGrUsr; +import com.rekoe.utils.Constants; + +/** + * @author 科技㊣²º¹³
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 + */ +@IocBean(args = { "refer:dao" }) +public class ProjectGroupUsrService extends BaseService { + + public ProjectGroupUsrService(Dao dao) { + super(dao); + } + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @param usr + * 用户 + * @return 组用户 + */ + public PjGrUsr get(String pj, String gr, String usr) { + Sql sql = Sqls.create("select a.pj,a.usr,a.gr,b.name as usrname from pj_gr_usr a left join usr b on (a.usr=b.usr) where a.pj = $pj and a.gr=$gr and a.usr=$usr"); + sql.setVar("pj", pj).setVar("gr", gr).setVar("usr", usr); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + if (rs.next()) { + return readPjGrUsr(rs); + } + return null; + } + }); + dao().execute(sql); + return sql.getObject(PjGrUsr.class); + } + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @return 组用户列表 + */ + public List getList(String pj, String gr) { + Sql sql = Sqls.create("select a.pj,a.usr,a.gr,b.name as usrname from pj_gr_usr a left join usr b on (a.usr = b.usr) where a.pj=$pj and a.gr=$gr order by a.usr"); + sql.setVar("pj", pj).setVar("gr", gr); + final List list = new ArrayList(); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + while (rs.next()) { + list.add(readPjGrUsr(rs)); + } + return list; + } + }); + dao().execute(sql); + return list; + } + + /** + * 项目的组用户列表(用户可能为空),导出authz文件时使用 + * + * @param pj + * 项目 + * @return 项目的组用户列表 + */ + public List getList(String pj) { + Sql sql = Sqls.create("select a.pj,a.gr,b.usr,c.name as usrname from pj_gr a left join pj_gr_usr b on (a.pj=b.pj and a.gr=b.gr) left join usr c on (b.usr = c.usr) where a.pj=$pj order by a.gr,b.usr"); + sql.setVar("pj", pj); + final List list = new ArrayList(); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + while (rs.next()) { + list.add(readPjGrUsr(rs)); + } + return list; + } + }); + dao().execute(sql); + return list; + } + + /** + * 有相同的svn root的项目的组用户列表(用户可能为空),导出authz文件时使用 + * + * @param rootPath + * svn root + * @return 有相同的svn root的项目组用户 + */ + public List getListByRootPath(String rootPath) { + Sql sql = Sqls.create("select a.pj,a.gr,b.usr,c.name as usrname from pj_gr a left join pj_gr_usr b on (a.pj=b.pj and a.gr=b.gr) left join usr c on (b.usr=c.usr) " + " where a.pj in (select distinct pj from pj where type=$type and path like $like) order by a.pj,a.gr,b.usr"); + sql.setVar("type", Constants.HTTP_MUTIL).setVar("like", rootPath + "%"); + final List list = new ArrayList(); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + while (rs.next()) { + list.add(readPjGrUsr(rs)); + } + return list; + } + }); + dao().execute(sql); + return list; + } + + /** + * @param rs + * ResultSet + * @return 组用户 + * @throws SQLException + * jdbc异常 + */ + PjGrUsr readPjGrUsr(ResultSet rs) throws SQLException { + PjGrUsr result = new PjGrUsr(); + result.setPj(rs.getString("pj")); + result.setUsr(rs.getString("usr")); + result.setGr(rs.getString("gr")); + result.setUsrName(rs.getString("usrname")); + return result; + } + + /** + * 删除 + * + * @param pj + * 项目 + * @param gr + * 组 + * @param usr + * 用户 + */ + public void delete(String pj, String gr, String usr) { + dao().clear(getEntityClass(), Cnd.where("pj", "=", pj).and("gr", "=", gr).and("usr", "=", usr)); + } + + /** + * 删除 + * + * @param usr + * 用户 + */ + public void deleteUsr(String usr) { + dao().clear(getEntityClass(), Cnd.where("usr", "=", usr)); + } + + /** + * 删除 + * + * @param pj + * 项目 + * @param gr + * 组 + */ + public void deletePjGr(String pj, String gr) { + dao().clear(getEntityClass(), Cnd.where("pj", "=", pj).and("gr", "=", gr)); + } + + /** + * 删除 + * + * @param pj + * 项目 + */ + public void deletePj(String pj) { + dao().clear(getEntityClass(), Cnd.where("pj", "=", pj)); + } + + /** + * 保存 + * + * @param pjGrUsr + * 项目用户 + */ + public void save(PjGrUsr pjGrUsr) { + if (this.get(pjGrUsr.getPj(), pjGrUsr.getGr(), pjGrUsr.getUsr()) == null) { + dao().insert(pjGrUsr); + } + } +} diff --git a/src/main/java/com/rekoe/service/ProjectService.java b/src/main/java/com/rekoe/service/ProjectService.java new file mode 100644 index 0000000..3ca0cdd --- /dev/null +++ b/src/main/java/com/rekoe/service/ProjectService.java @@ -0,0 +1,152 @@ +package com.rekoe.service; + +import java.io.File; + +import org.apache.commons.lang3.StringUtils; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.Strings; + +import com.rekoe.domain.Pj; +import com.rekoe.domain.PjAuth; +import com.rekoe.domain.PjGr; +import com.rekoe.utils.Constants; + +/** + * @author 科技㊣²º¹³
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 + */ +@IocBean(args = { "refer:dao" }) +public class ProjectService extends BaseService { + + public ProjectService(Dao dao) { + super(dao); + } + + @Inject + private ProjectGroupService projectGroupService; + + @Inject + private SvnService svnService; + + @Inject + private ProjectAuthService projectAuthService; + + public Pj get(String pj) { + return dao().fetch(getEntityClass(), Cnd.where("pj", "=", pj)); + } + + public boolean nameOk(String name) { + if (StringUtils.isBlank(name)) { + return false; + } + char[] chars = name.toCharArray(); + for (char c : chars) { + if (Strings.isChineseCharacter(c)) { + return false; + } + } + return Lang.isEmpty(dao().fetch(getEntityClass(), Cnd.where("pj", "=", name))); + } + + public int getCount(String path, String url) { + int num = dao().count(getEntityClass(), Cnd.where("path", "=", path).or("url", "=", url)); + return num; + } + + /** + * 保存。
+ * 数据库里已经存在相同的路径或url的项目,不可以保存。
+ * 如果仓库不存在,自动创建。
+ * 如果是增加项目,自动创建默认3个组。 + * + * @param pj + * 项目 + */ + public void save(Pj pj) { + // 路径 把\替换为/ + if (StringUtils.isNotBlank(pj.getPath())) { + pj.setPath(StringUtils.replace(pj.getPath(), "\\", "/")); + } + // url 把\替换为/ + if (StringUtils.isNotBlank(pj.getUrl())) { + pj.setUrl(StringUtils.replace(pj.getUrl(), "\\", "/")); + } + + // 是否可以增加项目 + boolean insert = nameOk(pj.getPj()); + if (insert) { + // 数据库里已经存在相同的路径或url的项目 + if (this.getCount(pj.getPath(), pj.getUrl()) > 0) { + throw new RuntimeException("数据库里已经存在相同的路径或url的仓库项目,请检查路径或url"); + } + } else { + // 数据库里已经存在相同的路径或url的项目 + if (this.getCount(pj.getPath(), pj.getUrl()) > 1) { + throw new RuntimeException("数据库里已经存在多个相同的路径或url的仓库项目,请检查路径或url"); + } + } + // 创建仓库 + File respository = new File(pj.getPath()); + if (!respository.exists() || !respository.isDirectory()) {// 不存在仓库 + RepositoryService.createLocalRepository(respository); + } + if (insert) { + // 增加默认的组 + insert(pj); + for (String gr : Constants.GROUPS) { + PjGr pjGr = new PjGr(); + pjGr.setPj(pj.getPj()); + pjGr.setGr(gr); + pjGr.setDes(gr); + projectGroupService.save(pjGr); + } + // 增加默认的权限 @see Issue 29 + PjAuth pjAuth = new PjAuth(); + pjAuth.setPj(pj.getPj()); + pjAuth.setRes(this.projectAuthService.formatRes(pj, "/")); + pjAuth.setRw("rw"); + pjAuth.setGr(Constants.GROUP_MANAGER); + projectAuthService.saveByGr(pjAuth); + } else { + dao().update(pj); + } + svnService.exportConfig(pj.getPj()); + } + + /** + * 获取项目的相对根路径.例如项目的path=e:/svn/projar,则返回projar。如果path为空,则返回项目ID + * @param pj 项目id + * @return 项目的相对根路径 + * @since 3.0.3 + */ + public String getRelateRootPath(String pj){ + Pj p = this.get(pj); + if(p == null || StringUtils.isBlank(p.getPath())){ + return pj; + } + return getRelateRootPath(pj); + } + /** + * 获取项目的相对根路径.例如项目的path=e:/svn/projar,则返回projar。如果path为空,则返回项目ID + * @param pj 项目 + * @return 项目的相对根路径 + * @since 3.0.3 + */ + public String getRelateRootPath(Pj pj){ + String path = pj.getPath(); + if(StringUtils.isBlank(path)){ + return pj.getPj(); + } + path = StringUtils.replace(path, "\\", "/"); + while(path.endsWith("/")){ + path = path.substring(0, path.length()-1); + } + return StringUtils.substringAfterLast(path, "/"); + } +} \ No newline at end of file diff --git a/src/main/java/com/rekoe/service/ProjectUserService.java b/src/main/java/com/rekoe/service/ProjectUserService.java new file mode 100644 index 0000000..fd968f4 --- /dev/null +++ b/src/main/java/com/rekoe/service/ProjectUserService.java @@ -0,0 +1,49 @@ +package com.rekoe.service; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.sql.SqlCallback; +import org.nutz.ioc.loader.annotation.IocBean; + +import com.rekoe.domain.PjUsr; + +/** + * @author 科技㊣²º¹³
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 + */ +@IocBean(args = { "refer:dao" }) +public class ProjectUserService extends BaseService { + + public ProjectUserService(Dao dao) { + super(dao); + } + + public PjUsr get(String pj, String usr) { + Sql sql = Sqls.create("select a.pj,a.usr,a.psw,b.name as usrname from pj_usr a left join usr b on (a.usr = b.usr) where a.pj = $pj and a.usr=$usr"); + sql.setVar("pf", pj).setVar("usr", usr); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + if (rs.next()) { + PjUsr result = new PjUsr(); + result.setPj(rs.getString("pj")); + result.setUsr(rs.getString("usr")); + result.setName(rs.getString("usrname")); + result.setPsw(rs.getString("psw")); + return result; + } + return null; + } + }); + dao().execute(sql); + return sql.getObject(PjUsr.class); + } +} diff --git a/src/main/java/com/rekoe/service/RepositoryService.java b/src/main/java/com/rekoe/service/RepositoryService.java new file mode 100644 index 0000000..0331d43 --- /dev/null +++ b/src/main/java/com/rekoe/service/RepositoryService.java @@ -0,0 +1,224 @@ +/** + * + */ +package com.rekoe.service; + +import java.io.File; +import java.util.Collection; + +import org.apache.commons.lang3.StringUtils; +import org.nutz.dao.Cnd; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.log.Log; +import org.nutz.log.Logs; +import org.tmatesoft.svn.core.SVNAuthenticationException; +import org.tmatesoft.svn.core.SVNDirEntry; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNProperties; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; +import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; +import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; +import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; +import org.tmatesoft.svn.core.io.SVNRepository; +import org.tmatesoft.svn.core.io.SVNRepositoryFactory; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNWCUtil; + +import com.rekoe.domain.Pj; +import com.rekoe.domain.PjUsr; +import com.rekoe.domain.Usr; +import com.rekoe.utils.EncryptUtil; +import com.rekoe.utils.UsrProvider; + +/** + * 仓库服务层 + */ +@IocBean(create = "init") +public class RepositoryService { + + /** + * 日志 + */ + private final Log LOG = Logs.get(); + + @Inject + private ProjectService projectService; + + @Inject + private ProjectUserService projectUserService; + + /** + * 获取svn仓库 + * + * @param pjId + * 项目ID + * @return svn仓库 + * @throws SVNException + * svn异常,例如没有权限等 + */ + public SVNRepository getRepository(String pjId) throws SVNException { + Pj pj = projectService.fetch(Cnd.where("pj", "=", pjId)); + if (pj == null) { + LOG.warn("Not found project: " + pjId); + return null; + } + return this.getRepository(pj); + } + + /** + * 从项目的url中获取svn的url + * + * @param url + * 项目url + * @return svn url + */ + public static String parseURL(String url) { + if (StringUtils.isBlank(url)) { + return null; + } + String result = url.trim();// 去空格 + result = StringUtils.replace(result, "\t", " "); + result = StringUtils.replace(result, "\r", " "); + result = StringUtils.replace(result, "\n", " "); + result = StringUtils.replace(result, "\b", " "); + result = StringUtils.replace(result, "<", " ");// eg.
+ result = StringUtils.replace(result, "(", " ");// eg. () + + result = result.trim(); + int blank = result.indexOf(" "); + if (blank != -1) { + result = result.substring(0, blank); + } + + return result; + } + + /** + * 获取svn仓库 + * + * @param pj + * 项目 + * @return svn仓库 + * @throws SVNException + * svn异常,例如没有权限等 + */ + @SuppressWarnings("deprecation") + public SVNRepository getRepository(Pj pj) throws SVNException { + Usr usr = UsrProvider.getCurrentUsr(); + String svnUrl = parseURL(pj.getUrl()); + if (StringUtils.isBlank(svnUrl)) { + throw new RuntimeException("URL不可以为空"); + } + String svnUserName = usr.getUsr(); + String svnPassword = usr.getPsw(); + if (!com.rekoe.utils.Constants.HTTP_MUTIL.equals(pj.getType())) { + // pj_usr覆盖用户的密码 + PjUsr pjUsr = projectUserService.get(pj.getPj(), svnUserName); + if (pjUsr != null) { + svnPassword = pjUsr.getPsw(); + } + } + svnPassword = EncryptUtil.decrypt(svnPassword);// 解密 + SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(svnUrl)); + ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(svnUserName, svnPassword); + repository.setAuthenticationManager(authManager); + return repository; + } + + /** + * 返回项目仓库的根 + * + * @param pj + * 项目 + * @return 仓库根 + */ + public String getRepositoryRoot(Pj pj) { + SVNRepository repository = null; + try { + repository = this.getRepository(pj); + return repository.getRepositoryRoot(true).toString(); + } catch (SVNAuthenticationException e) { + LOG.error(e.getMessage()); + return null; + } catch (SVNException e) { + LOG.error(e.getMessage()); + return null; + } finally { + if (repository != null) { + repository.closeSession(); + } + } + } + + /** + * 获取项目指定路径的svn仓库文件系统 + * + * @param pj + * 项目 + * @param path + * 相对仓库根目录的路径 + * @return 目录或文件系统 + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Collection getDir(String pj, String path) { + if (StringUtils.isBlank(path)) { + path = "/";// root + } + if (!path.startsWith("/")) { + path = "/" + path; + } + SVNRepository repository = null; + try { + repository = this.getRepository(pj); + SVNProperties properties = new SVNProperties(); + return repository.getDir(path, SVNRevision.HEAD.getNumber(), properties, (Collection) null); + } catch (SVNAuthenticationException e) { + LOG.error(e); + throw new RuntimeException("认证失败"); + } catch (SVNException e) { + LOG.error(e); + throw new RuntimeException(e.getMessage()); + } finally { + if (repository != null) { + repository.closeSession(); + } + } + } + + /** + * Creates a local blank FSFS-type repository. A call to this routine is + * equivalent to + * createLocalRepository(path, null, enableRevisionProperties, force) + * . + * + * @param respository + * a repository root location + * @return a local URL (file:///) of a newly created repository + */ + public static SVNURL createLocalRepository(File respository) { + try { + return SVNRepositoryFactory.createLocalRepository(respository, true, false); + } catch (SVNException e) { + throw new RuntimeException(String.format("pj.save.error.createRepository", "创建仓库失败.{0}", new Object[] { respository.getAbsolutePath() }) + " : " + e.getMessage()); + } + } + + public void init() { + /* + * For using over http:// and https:// + */ + DAVRepositoryFactory.setup(); + /* + * For using over svn:// and svn+xxx:// + */ + SVNRepositoryFactoryImpl.setup(); + + /* + * For using over file:/// + */ + FSRepositoryFactory.setup(); + } + +} diff --git a/src/main/java/com/rekoe/service/RoleService.java b/src/main/java/com/rekoe/service/RoleService.java index 456d5e0..2ee0bf5 100644 --- a/src/main/java/com/rekoe/service/RoleService.java +++ b/src/main/java/com/rekoe/service/RoleService.java @@ -16,10 +16,10 @@ import com.rekoe.domain.Permission; import com.rekoe.domain.Role; /** - * @author 科技㊣²º¹³ - * 2014年2月3日 下午4:48:45 - * http://www.rekoe.com - * QQ:5382211 + * @author 科技㊣²º¹³M
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 */ @IocBean(args = { "refer:dao" }) public class RoleService extends BaseService { diff --git a/src/main/java/com/rekoe/service/SvnService.java b/src/main/java/com/rekoe/service/SvnService.java new file mode 100644 index 0000000..6876f19 --- /dev/null +++ b/src/main/java/com/rekoe/service/SvnService.java @@ -0,0 +1,531 @@ +package com.rekoe.service; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.nutz.dao.Cnd; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.log.Log; +import org.nutz.log.Logs; + +import com.rekoe.domain.Pj; +import com.rekoe.domain.PjAuth; +import com.rekoe.domain.PjGrUsr; +import com.rekoe.domain.Usr; +import com.rekoe.utils.Constants; +import com.rekoe.utils.EncryptUtil; + +/** + * 导出svn配置信息服务层 + * + */ +@IocBean +public class SvnService { + + /** + * 分隔符 + */ + private static final String SEP = System.getProperty("line.separator"); + /** + * 日志 + */ + private final Log LOG = Logs.get(); + + @Inject + private ProjectService projectService; + + @Inject + private ProjectUserService projectUserService; + + @Inject + private ProjectAuthService projectAuthService; + + @Inject + private ProjectGroupService projectGroupService; + + @Inject + private ProjectGroupUsrService projectGroupUsrService; + + /** + * 导出到配置文件 + * + * @param pj + * 项目id + */ + public synchronized void exportConfig(String pj) { + this.exportConfig(projectService.fetch(Cnd.where("pj", "=", pj))); + } + + /** + * 导出到配置文件 + * + * @param pj + * 项目 + */ + public synchronized void exportConfig(Pj pj) { + if (pj == null) { + return; + } + File parent = new File(pj.getPath()); + if (!parent.exists() || !parent.isDirectory()) { + throw new RuntimeException(String.format("找不到仓库 路径{0}", new Object[] { pj.getPath() })); + } + if (Constants.HTTP.equalsIgnoreCase(pj.getType())) {// HTTP(单库) SVNPath + this.exportHTTP(pj); + } else if (Constants.HTTP_MUTIL.equalsIgnoreCase(pj.getType())) {// HTTP(多库) + // SVNParentPath + File root = new File(pj.getPath()).getParentFile(); + this.exportHTTPMutil(root); + } else if (Constants.SVN.equalsIgnoreCase(pj.getType())) {// SVN + this.exportSVN(pj); + } + } + + @Inject + private UsrService usrService; + + /** + * 导出svn协议的配置信息 + * + * @param pj + * 项目 + */ + private void exportSVN(Pj pj) { + // 项目的用户 + List usrList = this.usrService.getList(pj.getPj()); + // 项目的用户组 + Map> pjGrUsrMap = this.getPjGrUsrs(pj.getPj()); + // 项目的权限 + Map> pjAuthMap = this.getPjAuths(pj.getPj()); + this.exportSvnConf(pj); + this.exportPasswdSVN(pj, usrList); + this.exportAuthz(pj, pjGrUsrMap, pjAuthMap); + } + + /** + * 导出http(单库)的配置信息 + * + * @param pj + * 项目 + */ + private void exportHTTP(Pj pj) { + // 项目的用户 + List usrList = usrService.getList(pj.getPj()); + // 项目的用户组 + Map> pjGrUsrMap = this.getPjGrUsrs(pj.getPj()); + // 项目的权限 + Map> pjAuthMap = this.getPjAuths(pj.getPj()); + this.exportSVNPathConf(pj); + this.exportPasswdHTTP(pj, usrList); + this.exportAuthz(pj, pjGrUsrMap, pjAuthMap); + } + + /** + * 导出http(多库)的配置信息 + * + * @param root + * svn root + */ + private void exportHTTPMutil(File root) { + String svnRoot = StringUtils.replace(root.getAbsolutePath(), "\\", "/"); + if (!svnRoot.endsWith("/")) { + svnRoot += "/"; + } + // 和这个项目在同一个父目录的所有项目的用户 + List usrList = this.usrService.getListByRootPath(svnRoot); + // 和这个项目在同一个父目录的所有项目的用户组 + Map> pjGrUsrMap = this.getPjGrUsrsByRootPath(svnRoot); + // 和这个项目在同一个父目录的所有项目的权限 + Map> pjAuthMap = this.getPjAuthsByRootPath(svnRoot); + this.exportSVNParentPathConf(root); + this.exportPasswdHTTPMutil(root, usrList); + this.exportAuthzHTTPMutil(root, pjGrUsrMap, pjAuthMap); + } + + /** + * 获取有相同svn root的项目的权限列表 + * + * @param rootPath + * svn root + * @return 有相同svn root的项目的权限列表 + */ + private Map> getPjAuthsByRootPath(String rootPath) { + Map> results = new LinkedHashMap>();// > + List pjAuthList = this.projectAuthService.getListByRootPath(rootPath); + // 格式化返回数据 + for (PjAuth pjAuth : pjAuthList) { + List authList = results.get(pjAuth.getRes()); + if (authList == null) { + authList = new ArrayList(); + results.put(pjAuth.getRes(), authList); + } + authList.add(pjAuth); + } + return results; + } + + /** + * 获取项目的权限列表 + * + * @param pj + * 项目 + * @return 项目的权限列表 + */ + private Map> getPjAuths(String pj) { + Map> results = new LinkedHashMap>();// > + List pjAuthList = this.projectAuthService.getList(pj); + // 格式化返回数据 + for (PjAuth pjAuth : pjAuthList) { + List authList = results.get(pjAuth.getRes()); + if (authList == null) { + authList = new ArrayList(); + results.put(pjAuth.getRes(), authList); + } + authList.add(pjAuth); + + } + return results; + } + + /** + * 获取项目的组列表 + * + * @param pj + * 项目 + * @return 项目的组列表 + */ + private Map> getPjGrUsrs(String pj) { + Map> results = new LinkedHashMap>();// > + List pjGrUsrs = this.projectGroupUsrService.getList(pj); + // 格式化返回数据 + for (PjGrUsr pjGrUsr : pjGrUsrs) { + List grUsrList = results.get(pjGrUsr.getGr()); + if (grUsrList == null) { + grUsrList = new ArrayList(); + results.put(pjGrUsr.getGr(), grUsrList); + } + grUsrList.add(pjGrUsr); + } + return results; + } + + /** + * 获取有相同svn root的项目的权限列表 + * + * @param rootPath + * svn root + * @return 有相同svn root的项目的权限列表 + */ + private Map> getPjGrUsrsByRootPath(String rootPath) { + Map> results = new LinkedHashMap>();// > + List pjGrUsrs = this.projectGroupUsrService.getListByRootPath(rootPath); + // 格式化返回数据 + for (PjGrUsr pjGrUsr : pjGrUsrs) { + String key = pjGrUsr.getPj() + "_" + pjGrUsr.getGr(); + List grUsrList = results.get(key);// 项目ID_组ID see: Issue 4 + if (grUsrList == null) { + grUsrList = new ArrayList(); + results.put(key, grUsrList); + } + grUsrList.add(pjGrUsr); + } + + return results; + + } + + /** + * 输出http多库方式的密码文件 + * + * @param root + * svn root + * @param usrList + * 所有用户列表 + */ + private void exportPasswdHTTPMutil(File root, List usrList) { + File outFile = new File(root, "passwd.http"); + StringBuffer contents = new StringBuffer(); + for (Usr usr : usrList) { + // 采用SHA加密 + // http://httpd.apache.org/docs/2.2/misc/password_encryptions.html + String shaPsw = "{SHA}" + EncryptUtil.encriptSHA1(EncryptUtil.decrypt(usr.getPsw())); + contents.append(usr.getUsr()).append(":").append(shaPsw).append(SEP); + } + this.write(outFile, contents.toString()); + } + + /** + * 输出http单库方式的密码文件 + * + * @param pj + * 项目 + * @param usrList + * 项目用户列表 + */ + private void exportPasswdHTTP(Pj pj, List usrList) { + File outFile = new File(pj.getPath(), "/conf/passwd.http"); + StringBuffer contents = new StringBuffer(); + for (Usr usr : usrList) { + // 采用SHA加密 + // http://httpd.apache.org/docs/2.2/misc/password_encryptions.html + String shaPsw = "{SHA}" + EncryptUtil.encriptSHA1(EncryptUtil.decrypt(usr.getPsw())); + contents.append(usr.getUsr()).append(":").append(shaPsw).append(SEP); + } + this.write(outFile, contents.toString()); + } + + /** + * 输出svn方式的密码文件 + * + * @param pj + * 项目 + * @param usrList + * 项目用户列表 + */ + private void exportPasswdSVN(Pj pj, List usrList) { + File outFile = new File(pj.getPath(), "/conf/passwd"); + StringBuffer contents = new StringBuffer(); + contents.append("[users]").append(SEP); + for (Usr usr : usrList) { + contents.append(usr.getUsr()).append("=").append(EncryptUtil.decrypt(usr.getPsw())).append(SEP);// 解密 + } + this.write(outFile, contents.toString()); + } + + /** + * 输出http多库方式的权限文件 + * + * @param root + * svn root + * @param pjGrUsrMap + * 所有的项目组用户列表 + * @param resMap + * 所有的权限列表 + */ + private void exportAuthzHTTPMutil(File root, Map> pjGrUsrMap, Map> resMap) { + if (root == null) { + return; + } + File outFile = new File(root, "authz"); + StringBuffer contents = new StringBuffer(); + contents.append("[aliases]").append(SEP); + contents.append("[groups]").append(SEP); + + for (Iterator grIterator = pjGrUsrMap.keySet().iterator(); grIterator.hasNext();) { + String gr = grIterator.next();// 项目ID_组ID see: Issue 4 + contents.append(gr).append("="); + List pjGrUsrList = pjGrUsrMap.get(gr); + for (int i = 0; i < pjGrUsrList.size(); i++) { + PjGrUsr pjGrUsr = pjGrUsrList.get(i); + if (pjGrUsr.getUsr() == null) { + continue; + } + if (i != 0) { + contents.append(","); + } + contents.append(pjGrUsr.getUsr()); + } + contents.append(SEP); + } + contents.append(SEP); + for (Iterator resIterator = resMap.keySet().iterator(); resIterator.hasNext();) { + String res = resIterator.next(); + contents.append(res).append(SEP); + for (PjAuth pjAuth : resMap.get(res)) { + if (StringUtils.isNotBlank(pjAuth.getGr())) { + // 项目ID_组ID see: Issue 4 + contents.append("@").append(pjAuth.getPj() + "_" + pjAuth.getGr()).append("=").append(pjAuth.getRw()).append(SEP); + } else if (StringUtils.isNotBlank(pjAuth.getUsr())) { + contents.append(pjAuth.getUsr()).append("=").append(pjAuth.getRw()).append(SEP); + } + } + contents.append(SEP); + } + this.write(outFile, contents.toString()); + } + + /** + * 输出权限配置文件 + * + * @param pj + * 项目 + * @param pjGrUsrMap + * 项目的组列表 + * @param resMap + * 项目的权限列表 + */ + private void exportAuthz(Pj pj, Map> pjGrUsrMap, Map> resMap) { + if (pj == null || StringUtils.isBlank(pj.getPj())) { + return; + } + /* + * if(pjGrList == null || pjGrList.size() == 0){ return; } if(pjAuthMap + * == null || pjAuthMap.size() == 0){ return; } + */ + File outFile = new File(pj.getPath(), "/conf/authz"); + StringBuffer contents = new StringBuffer(); + contents.append("[aliases]").append(SEP); + contents.append("[groups]").append(SEP); + + for (Iterator grIterator = pjGrUsrMap.keySet().iterator(); grIterator.hasNext();) { + String gr = grIterator.next(); + contents.append(gr).append("="); + List pjGrUsrList = pjGrUsrMap.get(gr); + for (int i = 0; i < pjGrUsrList.size(); i++) { + PjGrUsr pjGrUsr = pjGrUsrList.get(i); + if (pjGrUsr.getUsr() == null) { + continue; + } + if (i != 0) { + contents.append(","); + } + contents.append(pjGrUsr.getUsr()); + } + contents.append(SEP); + } + contents.append(SEP); + for (Iterator resIterator = resMap.keySet().iterator(); resIterator.hasNext();) { + String res = resIterator.next(); + contents.append(res).append(SEP); + for (PjAuth pjAuth : resMap.get(res)) { + if (StringUtils.isNotBlank(pjAuth.getGr())) { + contents.append("@").append(pjAuth.getGr()).append("=").append(pjAuth.getRw()).append(SEP); + } else if (StringUtils.isNotBlank(pjAuth.getUsr())) { + contents.append(pjAuth.getUsr()).append("=").append(pjAuth.getRw()).append(SEP); + } + } + contents.append(SEP); + } + this.write(outFile, contents.toString()); + } + + /** + * 输出svn方式的svnserve.conf + * + * @param pj + * 项目 + */ + private void exportSvnConf(Pj pj) { + if (pj == null || StringUtils.isBlank(pj.getPj())) { + return; + } + File outFile = new File(pj.getPath(), "/conf/svnserve.conf"); + StringBuffer contents = new StringBuffer(); + contents.append("[general]").append(SEP); + contents.append("anon-access = none").append(SEP); + contents.append("auth-access = write").append(SEP); + contents.append("password-db = passwd").append(SEP); + contents.append("authz-db = authz").append(SEP); + contents.append("[sasl]").append(SEP); + this.write(outFile, contents.toString()); + } + + /** + * 输出http单库方式的httpd.conf文件 + * + * @param pj + * 项目 + */ + private void exportSVNPathConf(Pj pj) { + if (pj == null || StringUtils.isBlank(pj.getPj())) { + return; + } + File outFile = new File(pj.getPath(), "/conf/httpd.conf"); + StringBuffer contents = new StringBuffer(); + contents.append("#Include ").append(pj.getPath()).append("/conf/httpd.conf").append(SEP); + String location = pj.getPj(); + // 例如 http://192.168.1.100/svn/projar/trunk + if (StringUtils.isNotBlank(pj.getUrl()) && pj.getUrl().indexOf("//") != -1) { + String svnUrl = RepositoryService.parseURL(pj.getUrl()); + location = StringUtils.substringAfter(svnUrl, "//");// 192.168.1.100/svn/projar/trunk + location = StringUtils.substringAfter(location, "/");// svn/projar/trunk + location = StringUtils.substringBeforeLast(location, "/trunk");// svn/projar + } + contents.append("").append(SEP); + contents.append("DAV svn").append(SEP); + contents.append("SVNPath ").append(pj.getPath()).append(SEP); + contents.append("AuthType Basic").append(SEP); + contents.append("AuthName ").append("\"").append(pj.getPj()).append("\"").append(SEP); + contents.append("AuthUserFile ").append(pj.getPath()).append("/conf/passwd.http").append(SEP); + contents.append("AuthzSVNAccessFile ").append(pj.getPath()).append("/conf/authz").append(SEP); + contents.append("Require valid-user").append(SEP); + contents.append("").append(SEP); + this.write(outFile, contents.toString()); + + } + + /** + * 输出http多库方式的httpd.conf文件 + * + * @param root + * svn root + */ + private void exportSVNParentPathConf(File root) { + String svnRoot = StringUtils.replace(root.getAbsolutePath(), "\\", "/"); + File outFile = new File(root, "httpd.conf"); + StringBuffer contents = new StringBuffer(); + contents.append("#Include ").append(svnRoot).append("/httpd.conf").append(SEP); + String location = root.getName(); + contents.append("").append(SEP); + contents.append("DAV svn").append(SEP); + contents.append("SVNListParentPath on").append(SEP); + contents.append("SVNParentPath ").append(svnRoot).append(SEP); + contents.append("AuthType Basic").append(SEP); + contents.append("AuthName ").append("\"").append("Subversion repositories").append("\"").append(SEP); + contents.append("AuthUserFile ").append(svnRoot).append("/passwd.http").append(SEP); + contents.append("AuthzSVNAccessFile ").append(svnRoot).append("/authz").append(SEP); + contents.append("Require valid-user").append(SEP); + contents.append("").append(SEP); + contents.append("RedirectMatch ^(/").append(location).append(")$ $1/").append(SEP); + this.write(outFile, contents.toString()); + } + + /** + * 写文件流 + * + * @param outFile + * 输出文件 + * @param contents + * 内容 + */ + private void write(File outFile, String contents) { + BufferedWriter writer = null; + try { + if (contents == null) { + contents = ""; + } + if (!outFile.getParentFile().exists()) { + outFile.getParentFile().mkdirs(); + } + writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));// UTF-8 + writer.write(contents); + LOG.debug(outFile); + } catch (Exception e) { + LOG.error(e); + throw new RuntimeException(e.getMessage()); + } finally { + if (writer != null) { + try { + writer.flush(); + } catch (IOException e) { + LOG.error(e); + } + try { + writer.close(); + } catch (IOException e) { + LOG.error(e); + } + } + } + } +} diff --git a/src/main/java/com/rekoe/service/SvnUserService.java b/src/main/java/com/rekoe/service/SvnUserService.java new file mode 100644 index 0000000..6b1ef7d --- /dev/null +++ b/src/main/java/com/rekoe/service/SvnUserService.java @@ -0,0 +1,47 @@ +package com.rekoe.service; + +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; + +import com.rekoe.domain.Usr; + +/** + * @author 科技㊣²º¹³M
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 + */ +@IocBean(args = { "refer:dao" }) +public class SvnUserService extends BaseService { + + private final String REGEX_USERNAME = "^[a-zA-Z0-9]{1,16}$"; + + public SvnUserService(Dao dao) { + super(dao); + } + + public boolean nameOk(String name) { + if (StringUtils.isBlank(name)) { + return false; + } + if (!isUsername(name)) { + return false; + } + return Lang.isEmpty(dao().fetch(getEntityClass(), Cnd.where("usr", "=", name))); + } + + /** + * 校验用户名 + * + * @param username + * @return 校验通过返回true,否则返回false + */ + public boolean isUsername(String username) { + return Pattern.matches(REGEX_USERNAME, username); + } +} diff --git a/src/main/java/com/rekoe/service/UsrService.java b/src/main/java/com/rekoe/service/UsrService.java new file mode 100644 index 0000000..30431e2 --- /dev/null +++ b/src/main/java/com/rekoe/service/UsrService.java @@ -0,0 +1,79 @@ +package com.rekoe.service; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.sql.SqlCallback; +import org.nutz.ioc.loader.annotation.IocBean; + +import com.rekoe.domain.Usr; + +/** + * @author 科技㊣²º¹³
+ * 2014年2月3日 下午4:48:45
+ * http://www.rekoe.com
+ * QQ:5382211 + */ +@IocBean(args = { "refer:dao" }) +public class UsrService extends BaseService { + + public UsrService(Dao dao) { + super(dao); + } + + /** + * @param pj + * 项目 + * @return 所有项目用户列表(不包括*) + */ + public List getList(String pj) { + Sql sql = Sqls.create("select p.usr,p.name,p.role,CASE WHEN pu.psw IS NOT NULL THEN pu.psw ELSE p.psw END psw from (" + " select a.usr,a.role,a.psw,a.name from usr a " + " where " + " exists (select d.usr from pj_gr_usr d where d.usr=a.usr and d.pj=$pj) " + " or exists(select c.usr from pj_usr_auth c where a.usr=c.usr and c.pj=$pj) " + " ) p " + " left join pj_usr pu on (p.usr=pu.usr and pu.pj=$pj) where p.usr <> '*'" + " order by p.usr "); + sql.setVar("pj", pj); + final List list = new ArrayList(); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + while (rs.next()) { + list.add(readUsr(rs)); + } + return list; + } + }); + dao().execute(sql); + return list; + } + + Usr readUsr(ResultSet rs) throws SQLException { + Usr result = new Usr(); + result.setUsr(rs.getString("usr")); + result.setName(rs.getString("name")); + result.setPsw(rs.getString("psw")); + result.setRole(rs.getString("role")); + return result; + } + + public List getListByRootPath(String rootPath) { + Sql sql = Sqls.create("select p.usr,p.name,p.role,CASE WHEN pu.psw IS NOT NULL THEN pu.psw ELSE p.psw END psw from (" + " select a.usr,a.role,a.psw,a.name from usr a " + " where " + " exists (select d.usr from pj_gr_usr d where d.usr=a.usr and d.pj in (select distinct pj from pj where type=$type and path like $like)) " + " or exists(select c.usr from pj_usr_auth c where a.usr=c.usr and c.pj in (select distinct pj from pj where type=$type and path like $like)) " + " ) p " + " left join pj_usr pu on (p.usr=pu.usr) where p.usr <> '*'" + " order by p.usr "); + sql.setVar("like", rootPath + "%").setVar("type", com.rekoe.utils.Constants.HTTP_MUTIL); + final List list = new ArrayList(); + sql.setCallback(new SqlCallback() { + + @Override + public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { + while (rs.next()) { + list.add(readUsr(rs)); + } + return list; + } + }); + dao().execute(sql); + return list; + } +} diff --git a/src/main/java/com/rekoe/utils/Constants.java b/src/main/java/com/rekoe/utils/Constants.java index 4804981..625a6b2 100644 --- a/src/main/java/com/rekoe/utils/Constants.java +++ b/src/main/java/com/rekoe/utils/Constants.java @@ -32,7 +32,6 @@ public class Constants { */ public static final String XIAOMI = "xiaomi"; - /** * 360 */ @@ -77,7 +76,7 @@ public class Constants { * 自己平台 */ public static final String SG = "sg"; - + public static final String RK = "rk"; /** * 游客登陆 @@ -88,6 +87,48 @@ public class Constants { * Mac */ public static final String APPLE = "apple"; - + public static final String FACEBOOK = "facebook"; + + /** + * lang 保存在session中得key + */ + public static final String SESSION_KEY_LANG = "_session_key_lang_"; + /** + * 用户在session中key + */ + public static final String SESSION_KEY_USER = "_session_key_user_"; + + /** + * + */ + public static final String ERROR = "error"; + + /** + * svn协议 + */ + public static final String SVN = "svn"; + /** + * http单库 + */ + public static final String HTTP = "http"; + /** + * http多库 + */ + public static final String HTTP_MUTIL = "http-mutil"; + + /** + * 管理组 + */ + public static final String GROUP_MANAGER = "manager"; + + /** + * 项目默认的组 + */ + public static final String[] GROUPS = { GROUP_MANAGER, "developer", "tester" }; + + /** + * 管理员角色代码 + */ + public static final String USR_ROLE_ADMIN = "admin"; } diff --git a/src/main/resources/msg/zh_CN/MessageResources.properties b/src/main/resources/msg/zh_CN/MessageResources.properties index f1a0db9..ab42122 100644 --- a/src/main/resources/msg/zh_CN/MessageResources.properties +++ b/src/main/resources/msg/zh_CN/MessageResources.properties @@ -1,423 +1,203 @@ -login.username=??? -login.password=?? -login.input.request.password=?????? -login.input.request.password.len=??????{0}??? -login.input.request.password.same=?????????? -login.input.old.password=????? -login.input.new.password=????? -login.input.re.password=???? -user.lastlogintime=?????? -user.lastloginip=????IP -user.lock=?? -user.reg.number=???? -user.all.presion.number=?? -user.unlock=?? -user.change.pwd=???? -global.confirm.logout=?? -global.confirm.send.thesame=???? -global.admin.welcome=?? -global.admin.viewFrontIndex=?? -global.admin.index=??? -global.position=???? -global.platform=???? -global.platform.all=???? -global.add=?? -global.admin.home=?? -global.admin.logout=?? -cms.function.channel=?? -cms.function.user=?? -cms.function.add.user=???? -common.error.lock.account.empty=????? -common.error.lock.account.system=????????? -cmsMember.function=???? -cmsGroup.function=????? -cmsAdminGlobal.function=????? -cmsRole.function=???? -cmsRole.function.open=? -cmsRole.function.forbit=?? -cmsRole.name=???? -cmsRole.forfirst=????? -cmsRole.group=??? -cms.server.set=????? -cms.server.select=????? -cms.server.list=(?????) -cmsRole.setrole.err.function=?????? -cmsLog.function.operating=?????? -cmsLog.function.loginSuccess=?????? -cmsLog.function.loginFailure=?????? -cmsMessage.function=????? -global.edit=?? -global.server=??? -global.rate=?? -global.name=?? -global.status=?? -global.type=?? -global.operator.type=???? -global.number=?? -global.date=?? -global.happen.date=???? -global.list=?? -global.delete=?? -global.reset=?? -global.beginTime=???? -global.endTime=???? -global.coin.type=???? -cmsRole.perms=?? -global.true=? -global.false=? -global.help.douhao=?????????? -global.select=??? -cmsRole.priority=??? -cmsRole.priority.help=????????????,????,?????????????? -cmsRole.super=?????? -cmsPersonal.function=???? -global.submit=?? -global.author=?? -global.link=?? -global.error=?? -global.operator.time=???? -global.submit.true=??????? -global.backToList=???? -global.sendedList=????? -global.templateList=???? -global.edit.role.permission=?????? -global.edit.role=???? -global.operate=???? -global.param=?? -global.param2=??2 -global.message.same=???? -error.usernameExist=??????? -cmsUser.username=??? -cmsUser.password=?? -cmsUser.level=?? -cmsUser.status=????? -cmsUser.reg.date=???? -cmsUser.status.help=????? ?? -global.role.edit=???? -global.confirm.delete=??????? -art.title=???? -article.function=?? -art.keywords=??? -help.art.keywords=?????? ?? -art.source=???? -help.art.source=???????,???????? -art.author=??? -help.art.author=??????????? -art.createDate=???? -help.art.createDate=?????????? -art.click=??? -help.art.click=???????? -help.style.help=????????????? -help.module.navid=??????????????,?????????????Shift???? -channel.top=???? -login_error=???????? -top.frame.server=??? -top.frame.announcement=?? +login.username=用户名 +login.password=密码 +login.input.request.password=没有填写密码 +login.input.request.password.len=密码不能小于{0}个字符 +login.input.request.password.same=两次输入密码不一致嘛 +login.input.old.password=输入旧密码 +login.input.new.password=输入新密码 +login.input.re.password=重新输入 +user.lastlogintime=最后登录时间 +user.lastloginip=最后登录IP +user.lock=锁定 +user.reg.number=注册人数 +user.all.presion.number=人数 +user.unlock=解锁 +user.change.pwd=修改密码 +global.confirm.logout=退出 +global.confirm.send.thesame=重复发布 +global.admin.welcome=欢迎 +global.admin.viewFrontIndex=首页 +global.admin.index=欢迎页 +global.position=当前位置 +global.platform=平台选择 +global.platform.all=所有平台 +global.add=添加 +global.admin.home=首页 +global.admin.logout=退出 +cms.function.channel=栏目 +cms.function.user=用户 +cms.function.add.user=添加账号 +common.error.lock.account.empty=账号未找到 +common.error.lock.account.system=系统账号不可以编辑 +cmsMember.function=会员管理 +cmsGroup.function=会员组管理 +cmsAdminGlobal.function=管理员管理 +cmsRole.function=角色管理 +cmsRole.function.open=启 +cmsRole.function.forbit=禁用 +cmsRole.name=角色名称 +cmsRole.forfirst=角色优先级 +cmsRole.group=用户组 +cms.server.set=设置服务器 +cms.server.select=选择服务器 +cms.server.list=(服务器列表) +cmsRole.setrole.err.function=分配角色失败 +cmsLog.function.operating=后台操作日志 +cmsLog.function.loginSuccess=登录成功日志 +cmsLog.function.loginFailure=登录失败日志 +cmsMessage.function=站内信管理 +global.edit=编辑 +global.server=服务器 +global.rate=占比 +global.name=名称 +global.status=状态 +global.type=类型 +global.operator.type=操作类型 +global.number=数量 +global.date=日期 +global.happen.date=发生时间 +global.list=列表 +global.delete=删除 +global.reset=重置 +global.beginTime=开始时间 +global.endTime=结束时间 +global.coin.type=金币类型 +cmsRole.perms=权限 +global.true=是 +global.false=否 +global.help.douhao=多个用户已逗号,隔开 +global.select=请选择 +cmsRole.priority=优先级 +cmsRole.priority.help=在用户拥有几个角色的时候,产生冲突,优先选择优先级高的角色的权限 +cmsRole.super=拥有所有权限 +cmsPersonal.function=个人资料 +global.submit=提交 +global.author=作者 +global.link=链接 +global.error=错误 +global.operator.time=操作时间 +global.submit.true=确定要删除么? +global.backToList=返回列表 +global.sendedList=已发布列表 +global.templateList=模板列表 +global.edit.role.permission=编辑角色权限 +global.edit.role=编辑角色 +global.operate=操作选项 +global.param=参数 +global.param2=参数2 +global.message.same=相关信息 +error.usernameExist=用户名已被使用 +cmsUser.username=用户名 +cmsUser.password=密码 +cmsUser.level=级别 +cmsUser.status=启用该帐号 +cmsUser.reg.date=注册时间 +cmsUser.status.help=默认为禁用 状态 +global.role.edit=设置角色 +global.confirm.delete=确定要删除操作 +art.title=文章标题 +article.function=文章 +art.keywords=关键字 +help.art.keywords=文章的关键字 信息 +art.source=文章来源 +help.art.source=文章的来源信息,如:原创、转载等 +art.author=发布者 +help.art.author=文章的发布人或者是作者 +art.createDate=发布日期 +help.art.createDate=本网站发布文章的日期 +art.click=点击率 +help.art.click=文章被浏览的次数 +help.style.help=文章内容在网站上展示的风格 +help.module.navid=文章内容在网站上属于哪个模块,只能选择最后的子模块,按住Shift可以多选 +channel.top=顶级栏目 +login_error=用户名或密码错误 top.frame.gmlog=GMLog -top.frame.system=?? -top.frame.letter=?? -top.frame.query=?? -top.frame.game=?? -top.frame.gameConfig=???? -left.date.now=?? -left.gameConfig.sysLetter=???? -top.frame.gmlog.guid=?????? -top.frame.gmlog.useItem=???? -top.frame.gmlog.coinstat=???? -top.frame.gmlog.roleRelate=???? -top.frame.gmlog.reg=???? -top.frame.gmlog.newUserStatics=??????? -top.frame.gmlog.userStatics=?????? -top.frame.gmlog.coinDetail=?????? -top.frame.gmlog.orderDetail=???? -top.frame.gmlog.vipInfo=vip????? -top.frame.gmlog.heroStat=???? -top.frame.gmlog.turnStat=???? -button.submit.operator=???? -button.submit.success=?? -button.submit.error.duplicated=?? -button.submit=?? -button.submit.cancel=?? -button.submit.opt=?? -system.isopen=???? -system.context=?? -system.alarm.email=???? -system.open=?? -system.close=?? -system.whiteopen=????? -system.time.open=???? -system.time.end=???? -system.character.length=?? -system.reward=?? -system.add=?? -system.delete=?? -system.download=?? -system.view=?? -system.desc=?? -system.public=?? -system.sql.select=???? -system.sql.sh=????? -system.sql.database=??? -system.server.select=????? -system.server.list=????? -system.server=??????? -system.server.name=????? -system.server.name.help=???????? -system.server.other.server=????? -system.server.logic=????? -system.server.log=????? -system.server.index=????? -active.announce=???? -active.buss.name=???? -active.id=??ID -active.buss.help=???? -active.name=?? -active.image.id=??ID -active.desc=???? -active.type=???? -active.take.num.everyday=?????? -active.take.num.total=?????? -active.manager=???? -item.type=???? -item.name=???? -item.id=??ID -item.number=???? -create.number=???? -letter.list=???? -letter.index=?????? -letter.system=???? -letter.system.set=???? -game.user.id=??ID -game.user.level.on=???? -game.user.add.resource=???? -game.user.set=???? -game.user.set.equip=???? -game.user.set.pve=??pve -global.start=? -global.wave=?? -game.user.equip=?? -game.user.equip.suipian=???? -game.user.set.black=????? -game.user.set.unblack=???? -game.user.set.black.expired.time=?????? -game.user.set.black.time=?N?? -game.user.set.black.time.help=?N?? -game.user.black.list=????? -game.user.add.exp=???? -game.user.exp=?? -game.user.add.money=??? -game.user.glod=?? -game.user.sliver=?? -game.user.gongxun=?? -game.user.junling=?? -game.user.tiaozhan.ling=??? -game.user.zhengshou=?? -game.user.qiangzheng=?? -game.user.wave.max=???? -game.user.add.power=??? -game.user.add.item=???? -game.user.guide=???? -game.user.pay.numbers=???? -game.user.curr.map=???? -game.user.last.map=???? -game.user.curr.wave=???? -game.user.last.wave=???? -game.user.level=???? -game.user.vip.money=VIP?? -game.user.friends=?? -game.user.invited.friends=???? -game.user.cost.moneys=???? -game.user.get.gold=????? -game.user.pvp.number=pvp?? -game.user.item.gift.take.day.7=??7??? -game.user.item.gift.take.day.3.1=??3?1??? -game.user.item.gift.take.day.3.2=??3?2??? -game.user.item.gift.take.day.3.3=??3?3??? -game.user.item.gift.take.day.3.4=??3?4??? -game.user.item.gift.take.day.3.5=??3?5??? -game.user.item.gift.take.day.3.6=??3?6??? -game.user.item.junling.used.number=????? -game.system.resource.id=??id -game.system.resource.name=???? -game.system.resource.number=???? -game.system.resource.buy.users=??? -game.system.resource.source=?? -game.system.glod.set=???? -game.system.glod.number=???? -game.system.glod.last=???? -game.system.glod.type=???? -game.system.item.sell.num=?????? -game.system.item=?? -game.system.item.sell.money=???? -game.system.pay.users=????? -game.system.pay.moneys=????? -game.system.pay.day=???? -game.system.pay.day.rate=????? -game.system.pay.first.day.total=????? -game.system.pay.first.day.users=??????? -game.system.pay.first.day.rate=????? -game.system.pay.total=???? -game.system.pay.users.total=?????? -game.system.pay.users.total.rate=????? -game.system.pay.arpu.total.rate=??Arpu -game.system.pay.day.total=????? -game.system.glod.change.total=?????? -game.system.item.buy.persion.num=????? -game.user.vip.level=VIP?? -global.game.user.index=???????? -game.system.guid.step.number=??????? -game.system.guid.step.last.number=??????? -game.system.guid.step.last.number.rate=???? -game.system.new.guid.step.last.number.rate=????????? -game.system.hero.code=??code -game.system.hero=?? -game.system.hero.suipian=???? -game.system.hero.name=???? -game.system.hero.level=???? -game.system.hero.quality=???? -game.system.pay.order.id=??? -game.system.pay.number=???? -game.system.pay.date=???? -game.system.task=?? -game.system.gift=?? -game.system.junqi=?? -game.system.curr.data.reg.number=?????? -game.system.all.pass.numbers=?????? -game.system.all.numbers=???? -game.system.zonghe.total=??????? -game.system.platform.turkey=??? -game.system.platform=?? -game.letter.publish.type=???? -game.letter.publish.type.user=???? -game.letter.publish.type.system=???? -game.letter.title=?? -game.letter.title.help=????40?? -game.letter.overview=?? -game.letter.overview.help=????50?? -game.letter.content=?? -game.letter.content.help=????140?? -game.letter.add.goods=???? -game.letter.goods=?? -game.letter.reward=?? -game.letter.time.select=???? -game.letter.time.begin=???? -game.letter.time.end=???? -game.letter.user.list=???? -game.letter.user.list.help=?????? "??" "," ?? -game.letter.limit.actid=???? -game.letter.limit.recharge=???? -game.letter.limit.add=???? -game.letter.limit.scope=???? -game.letter.limit.type=???? -game.letter.limit.begin=???? -game.letter.limit.end=???? -game.letter.type.act=????????? -game.letter.type.newact=????? -game.letter.type.standard=????????????? -game.letter.type.relogin=????????? -game.letter.type.limitbylv=?????? -game.letter.type.limitbywave=?????? -game.letter.type.recharge=????? -game.letter.type.special=???????? -game.letter.sender=??? -game.letter.isopen=???? -game.letter.creatTime=???? -game.letter.lastUpdateTime=?????? -game.letter.send=?? -game.letter.sended=??? -game.letter.publish=?? -game.letter.published=??? -game.letter.preview=?? -game.position=???? -game.position.id=??id -game.position.status=?? -game.position.platform=?? -permission.permissionCategory=???? -permission.permissionCategoryId=???? -admin.main.permissionCategory=???? -admin.common.edit=?? -admin.common.delete=?? -admin.common.view=?? -admin.permissionCategory.list=???? -permissionCategory.name=?? -permission.description=???? -cmsUser.name=??? -admin.validate.illegal=???? -admin.validate.exist=??? -admin.validate.not.exist=???? -admin.common.ok=?? -admin.path.index=?? -admin.member.reg=????? -Member.username=??? -Member.password=?? -admin.member.rePassword=???? -admin.common.submit=?  ? -admin.common.back=?  ? -admin.common.error=????? -admin.common.error.connect=????? -admin.common.error.no.server=???????? -admin.error.title=???? -admin.error.message=????????????? -admin.error.message.forbit=??????????? -admin.error.back=????? -admin.message.error=????? -admin.dialog.deleteConfirm=?????? +top.frame.system=系统 +top.frame.letter=邮件 +top.frame.query=查询 +top.frame.game=游戏 +left.date.now=时间 +left.gameConfig.sysLetter=系统邮件 +top.frame.gmlog.guid=强制引导存留 +top.frame.gmlog.useItem=使用道具 +top.frame.gmlog.coinstat=金币统计 +top.frame.gmlog.roleRelate=角色信息 +top.frame.gmlog.reg=注册用户 +top.frame.gmlog.newUserStatics=新用户综合统计 +top.frame.gmlog.userStatics=付费存留回收 +top.frame.gmlog.coinDetail=金币变化明细 +top.frame.gmlog.orderDetail=订单明细 +top.frame.gmlog.vipInfo=vip和积分信息 +top.frame.gmlog.heroStat=英雄统计 +top.frame.gmlog.turnStat=寻宝统计 +button.submit.operator=操作提示 +button.submit.success=成功 +button.submit.error.duplicated=重复 +button.submit=确定 +button.submit.cancel=取消 +button.submit.opt=操作 +system.isopen=是否开启 +system.context=内容 +system.alarm.email=邮件提醒 +system.open=开启 +system.close=关闭 +permission.permissionCategory=权限分类 +permission.permissionCategoryId=分类描述 +admin.main.permissionCategory=权限分类 +admin.common.edit=编辑 +admin.common.delete=删除 +admin.common.view=查看 +admin.permissionCategory.list=分类列表 +permissionCategory.name=名称 +permission.description=权限描述 +cmsUser.name=用户名 +admin.validate.illegal=非法字符 +admin.validate.exist=已存在 +admin.validate.not.exist=已不存在 +admin.common.ok=成功 +admin.path.index=首页 +admin.member.reg=设置用户名 +Member.username=用户名 +Member.password=密码 +admin.member.rePassword=确认密码 +admin.common.submit=确  定 +admin.common.back=返  回 +admin.common.error=好像出错了 +admin.common.error.connect=网络无响应 +admin.common.error.no.server=请选择一台服务器 +admin.error.title=错误提示 +admin.error.message=对不起,您的操作出现错误! +admin.error.message.forbit=没有权限进行下一步操作 +admin.error.back=返回上一页 +admin.message.error=好像出错了 +admin.dialog.deleteConfirm=确定要删除? admin.dialog.ok=OK admin.dialog.cancel=Cancel -admin.common.error.act.exist=?????? -admin.dialog.updateConfirm=?????????? -admin.dialog.publishConfirm=?????????? -admin.common.resopnse.error=?????? -top.frame.gmlog.online=???? -top.frame.gmlog.payhighcharts=????? -top.frame.gmlog.wavecount=???? -admin.common.error.notexits=????? -admin.common.error.not.change=????? -cmsAdmin.log.function=???? -admin.dialog.addConfirm=??????? -admin.common.error.letter.send=?????????? -admin.common.error.close=????? -common.error.pay.null=????? -common.error.pay.isflag=????? -game.salvage.data.register=???? -admin.main.activityCategory=???? -admin.common.error.connect.net=???????? -game.system.upload.record=???? -admin.validate.notexist=?????? -content.title=?? -content.user=??? +admin.common.error.act.exist=此活动不存在 +admin.dialog.updateConfirm=确定要修改此条记录? +admin.dialog.publishConfirm=确定要发布此条记录? +admin.common.resopnse.error=服务器无响应 +top.frame.gmlog.online=统计在线 +top.frame.gmlog.payhighcharts=充值统计图 +top.frame.gmlog.wavecount=波次统计 +admin.common.error.notexits=数据不存在 +admin.common.error.not.change=不可以修改 +cmsAdmin.log.function=用户日志 +admin.dialog.addConfirm=你确定要添加? +admin.common.error.letter.send=此邮件已经邮递出去了 +admin.common.error.close=功能未开启 +common.error.pay.null=订单未记录 +common.error.pay.isflag=订单已处理 +game.salvage.data.register=注册账号 +admin.main.activityCategory=活动分类 +admin.common.error.connect.net=无法连接到服务器 +game.system.upload.record=批量发奖 +admin.validate.notexist=数据已不存在 +content.title=标题 +content.user=发布者 payment.uid=UID -payment.sid=???ID -common.error.login.account=??????? -global.refresh=?? -system.log.isopen=?????? -admin.common.down=?? -Article.title=?? -Article.author=?? -Article.content=?? -Article.seoTitle=???? -Article.seoKeywords=????? -Article.seoDescription=???? -Article.isPublication=???? -Article.isTop=???? -Article.hits=??? -Article.pageNumber=?? -Article.articleCategory=???? -Article.tags=?? -Article.path=???? -Article.text=???? -Article.pageContents=???? -Article.totalPages=??? - -ArticleCategory.name=?? -ArticleCategory.seoTitle=???? -ArticleCategory.seoKeywords=????? -ArticleCategory.seoDescription=???? -path.home=?? -ArticleCategory.treePath=??? -ArticleCategory.grade=?? -ArticleCategory.parent=???? -ArticleCategory.children=???? -ArticleCategory.articles=?? -ArticleCategory.treePaths=??? -ArticleCategory.path=???? \ No newline at end of file +payment.sid=服务器ID +common.error.login.account=账号或密码错误 +global.refresh=刷新 +system.log.isopen=是否开启日志 +path.home=首页 diff --git a/src/main/webapp/WEB-INF/template/admin/top.ftl b/src/main/webapp/WEB-INF/template/admin/top.ftl index d8339bb..0a1e81a 100644 --- a/src/main/webapp/WEB-INF/template/admin/top.ftl +++ b/src/main/webapp/WEB-INF/template/admin/top.ftl @@ -99,14 +99,20 @@ $(function(){ - <#assign max = 13> + <#assign max = 15>