mirror of
				https://github.com/ZSCNetSupportDept/WechatTicketSystem.git
				synced 2025-11-01 02:46:19 +08:00 
			
		
		
		
	| @@ -31,21 +31,21 @@ import java.io.PrintWriter; | ||||
| @WebServlet(name = "Index", urlPatterns = "/index", loadOnStartup = 1) | ||||
| public class Index extends HttpServlet { | ||||
|  | ||||
| 	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
| 		doGet(request, response); | ||||
| 	} | ||||
|     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
|         doGet(request, response); | ||||
|     } | ||||
|  | ||||
| 	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
| 		request.setCharacterEncoding("utf-8"); | ||||
| 		response.addHeader("Content-type", "text/plain;charset=utf-8"); | ||||
| 		response.setCharacterEncoding("utf-8"); | ||||
| 		PrintWriter out = response.getWriter(); | ||||
| 		out.println("Wechat Ticket System (WTS) 0.1 Copyright 2015-2016 Sola & LiuYue all rights reserved. | Commercial license for ZSC Network Support Department (ZSCNSD)."); | ||||
| 		out.println("For any problem, Please contact loli@sola.love."); | ||||
| 		if (response.getStatus() == HttpServletResponse.SC_NOT_FOUND) { | ||||
| 			out.println("\nError 404: Page not found."); | ||||
| 		} | ||||
| 		out.close(); | ||||
| 	} | ||||
|     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
|         request.setCharacterEncoding("utf-8"); | ||||
|         response.addHeader("Content-type", "text/plain;charset=utf-8"); | ||||
|         response.setCharacterEncoding("utf-8"); | ||||
|         PrintWriter out = response.getWriter(); | ||||
|         out.println("Wechat Ticket System (WTS) 0.1 Copyright 2015-2016 Sola & LiuYue all rights reserved. | Commercial license for ZSC Network Support Department (ZSCNSD)."); | ||||
|         out.println("For any problem, Please contact loli@sola.love."); | ||||
|         if (response.getStatus() == HttpServletResponse.SC_NOT_FOUND) { | ||||
|             out.println("\nError 404: Page not found."); | ||||
|         } | ||||
|         out.close(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,35 +31,35 @@ import java.util.Date; | ||||
|  */ | ||||
| public abstract class API { | ||||
|  | ||||
| 	public String url = null; //url | ||||
| 	public int access = Access.GOD_MODE; //operator's permission | ||||
| 	public Command authorize = null; //session check | ||||
|     public String url = null; //url | ||||
|     public int access = Access.GOD_MODE; //operator's permission | ||||
|     public Command authorize = null; //session check | ||||
|  | ||||
| 	protected abstract Object process(HttpServletRequest req, WxSession session) throws Exception; | ||||
|     protected abstract Object process(HttpServletRequest req, WxSession session) throws Exception; | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return getClass().getSimpleName() + "{" + | ||||
| 				"url='" + url + '\'' + | ||||
| 				", access=" + Access.inverseMap.get(access) + | ||||
| 				", authorize=" + authorize + | ||||
| 				'}'; | ||||
| 	} | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return getClass().getSimpleName() + "{" + | ||||
|                 "url='" + url + '\'' + | ||||
|                 ", access=" + Access.inverseMap.get(access) + | ||||
|                 ", authorize=" + authorize + | ||||
|                 '}'; | ||||
|     } | ||||
|  | ||||
| 	public static String getParameterWithDefault(String obj, String def) { | ||||
| 		return obj == null ? def : obj; | ||||
| 	} | ||||
|     public static String getParameterWithDefault(String obj, String def) { | ||||
|         return obj == null ? def : obj; | ||||
|     } | ||||
|  | ||||
| 	public static Date getParameterAsDate(String obj, Date def) { | ||||
| 		return obj == null ? def : new Date(Long.valueOf(obj)); | ||||
| 	} | ||||
|     public static Date getParameterAsDate(String obj, Date def) { | ||||
|         return obj == null ? def : new Date(Long.valueOf(obj)); | ||||
|     } | ||||
|  | ||||
| 	public static Date getToday() { | ||||
| 		return DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH); | ||||
| 	} | ||||
|     public static Date getToday() { | ||||
|         return DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH); | ||||
|     } | ||||
|  | ||||
| 	public static Date getDay(Date date) { | ||||
| 		return DateUtils.truncate(date, Calendar.DAY_OF_MONTH); | ||||
| 	} | ||||
|     public static Date getDay(Date date) { | ||||
|         return DateUtils.truncate(date, Calendar.DAY_OF_MONTH); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -46,107 +46,107 @@ import java.util.Set; | ||||
| @WebServlet(name = "APIRouter", urlPatterns = "/api/*", loadOnStartup = 11) | ||||
| public class APIRouter extends HttpServlet { | ||||
|  | ||||
| 	protected static Gson gson = SQLCore.gson; | ||||
| 	private Map<String, API> nodes = new HashMap<>(); | ||||
|     protected static Gson gson = SQLCore.gson; | ||||
|     private Map<String, API> nodes = new HashMap<>(); | ||||
|  | ||||
| 	@Override | ||||
| 	public void init() throws ServletException { | ||||
| 		super.init(); | ||||
| 		try { | ||||
| 			Reflections reflections = new Reflections(getClass().getPackage().getName()); | ||||
| 			Set<Class<? extends API>> set = reflections.getSubTypesOf(API.class); | ||||
| 			for (Class<? extends API> clz : set) { | ||||
| 				try { | ||||
| 					System.out.println("Loading API: " + clz.getName()); | ||||
| 					API obj = clz.newInstance(); | ||||
| 					System.out.println("Registered API: " + obj); | ||||
| 					nodes.put(obj.url, obj); | ||||
| 				} catch (InstantiationException | IllegalAccessException e) { | ||||
| 					e.printStackTrace(); | ||||
| 				} | ||||
| 			} | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 		System.out.println("Total " + nodes.size() + " API(s) loaded."); | ||||
| 	} | ||||
|     @Override | ||||
|     public void init() throws ServletException { | ||||
|         super.init(); | ||||
|         try { | ||||
|             Reflections reflections = new Reflections(getClass().getPackage().getName()); | ||||
|             Set<Class<? extends API>> set = reflections.getSubTypesOf(API.class); | ||||
|             for (Class<? extends API> clz : set) { | ||||
|                 try { | ||||
|                     System.out.println("Loading API: " + clz.getName()); | ||||
|                     API obj = clz.newInstance(); | ||||
|                     System.out.println("Registered API: " + obj); | ||||
|                     nodes.put(obj.url, obj); | ||||
|                 } catch (InstantiationException | IllegalAccessException e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         System.out.println("Total " + nodes.size() + " API(s) loaded."); | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
| 		req.setCharacterEncoding("utf-8"); | ||||
| 		resp.setCharacterEncoding("utf-8"); | ||||
| 		resp.addHeader("Content-type", "application/json;charset=utf-8"); | ||||
| 		resp.addHeader("Access-Control-Allow-Origin", "*"); | ||||
| 		Object obj = null; | ||||
| 		try { | ||||
| 			API api = nodes.get(req.getPathInfo()); | ||||
| 			if (api == null) { | ||||
| 				resp.sendError(HttpServletResponse.SC_FORBIDDEN); | ||||
| 				return; | ||||
| 			} | ||||
| 			WxSession session = getSession(req); | ||||
| 			if (session == null) { | ||||
| 				obj = Error.UNAUTHORIZED; | ||||
| 				return; | ||||
| 			} | ||||
| 			if (api.authorize != null) { | ||||
| 				if (session.getAttribute(Attribute.AUTHORIZED) != api.authorize) { | ||||
| 					obj = Error.UNAUTHORIZED; | ||||
| 					return; | ||||
| 				} | ||||
| 				if (api.access == Access.USER) { | ||||
| 					User u = session.getAttribute(Attribute.USER); | ||||
| 					if (u == null) { | ||||
| 						obj = Error.UNAUTHORIZED; | ||||
| 						return; | ||||
| 					} | ||||
| 				} | ||||
| 				if (api.access < Access.USER) { | ||||
| 					Operator op = session.getAttribute(Attribute.OPERATOR); | ||||
| 					if (op == null) { | ||||
| 						obj = Error.UNAUTHORIZED; | ||||
| 						return; | ||||
| 					} | ||||
| 					if (op.getAccess() > api.access) { | ||||
| 						obj = Error.PERMISSION_DENIED; | ||||
| 						return; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			obj = api.process(req, session); | ||||
| 		} catch (ParseException | NumberFormatException e) { | ||||
| 			obj = Error.ILLEGAL_PARAMETER; | ||||
| 		} catch (HibernateException e) { | ||||
| 			e.printStackTrace(); | ||||
| 			obj = Error.DATABASE_ERROR; | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 			obj = Error.INTERNAL_ERROR; | ||||
| 		} finally { | ||||
| 			if (!resp.isCommitted()) { | ||||
| 				try (PrintWriter out = resp.getWriter()) { | ||||
| 					out.println(gson.toJson(obj)); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
|         req.setCharacterEncoding("utf-8"); | ||||
|         resp.setCharacterEncoding("utf-8"); | ||||
|         resp.addHeader("Content-type", "application/json;charset=utf-8"); | ||||
|         resp.addHeader("Access-Control-Allow-Origin", "*"); | ||||
|         Object obj = null; | ||||
|         try { | ||||
|             API api = nodes.get(req.getPathInfo()); | ||||
|             if (api == null) { | ||||
|                 resp.sendError(HttpServletResponse.SC_FORBIDDEN); | ||||
|                 return; | ||||
|             } | ||||
|             WxSession session = getSession(req); | ||||
|             if (session == null) { | ||||
|                 obj = Error.UNAUTHORIZED; | ||||
|                 return; | ||||
|             } | ||||
|             if (api.authorize != null) { | ||||
|                 if (session.getAttribute(Attribute.AUTHORIZED) != api.authorize) { | ||||
|                     obj = Error.UNAUTHORIZED; | ||||
|                     return; | ||||
|                 } | ||||
|                 if (api.access == Access.USER) { | ||||
|                     User u = session.getAttribute(Attribute.USER); | ||||
|                     if (u == null) { | ||||
|                         obj = Error.UNAUTHORIZED; | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|                 if (api.access < Access.USER) { | ||||
|                     Operator op = session.getAttribute(Attribute.OPERATOR); | ||||
|                     if (op == null) { | ||||
|                         obj = Error.UNAUTHORIZED; | ||||
|                         return; | ||||
|                     } | ||||
|                     if (op.getAccess() > api.access) { | ||||
|                         obj = Error.PERMISSION_DENIED; | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             obj = api.process(req, session); | ||||
|         } catch (ParseException | NumberFormatException e) { | ||||
|             obj = Error.ILLEGAL_PARAMETER; | ||||
|         } catch (HibernateException e) { | ||||
|             e.printStackTrace(); | ||||
|             obj = Error.DATABASE_ERROR; | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|             obj = Error.INTERNAL_ERROR; | ||||
|         } finally { | ||||
|             if (!resp.isCommitted()) { | ||||
|                 try (PrintWriter out = resp.getWriter()) { | ||||
|                     out.println(gson.toJson(obj)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
| 		doGet(req, resp); | ||||
| 	} | ||||
|     @Override | ||||
|     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
|         doGet(req, resp); | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
| 		resp.addHeader("Access-Control-Allow-Method", "POST, GET, OPTIONS"); | ||||
| 		resp.addHeader("Access-Control-Allow-Origin", "*"); | ||||
| 		resp.setStatus(HttpServletResponse.SC_NO_CONTENT); | ||||
| 	} | ||||
|     @Override | ||||
|     protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
|         resp.addHeader("Access-Control-Allow-Method", "POST, GET, OPTIONS"); | ||||
|         resp.addHeader("Access-Control-Allow-Origin", "*"); | ||||
|         resp.setStatus(HttpServletResponse.SC_NO_CONTENT); | ||||
|     } | ||||
|  | ||||
| 	private static WxSession getSession(HttpServletRequest req) { | ||||
| 		String t = req.getParameter("token"); | ||||
| 		if (t == null || t.isEmpty()) return null; | ||||
| 		return WechatSession.get(t); | ||||
| 	} | ||||
|     private static WxSession getSession(HttpServletRequest req) { | ||||
|         String t = req.getParameter("token"); | ||||
|         if (t == null || t.isEmpty()) return null; | ||||
|         return WechatSession.get(t); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -30,26 +30,26 @@ import java.util.Map; | ||||
|  */ | ||||
| public class CheckSession extends API { | ||||
|  | ||||
| 	public CheckSession() { | ||||
| 		url = "/checksession"; | ||||
| 		access = Access.GUEST; | ||||
| 		authorize = null; | ||||
| 	} | ||||
|     public CheckSession() { | ||||
|         url = "/checksession"; | ||||
|         access = Access.GUEST; | ||||
|         authorize = null; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		String more = req.getParameter("more"); | ||||
| 		Map<String, Object> result = new HashMap<>(); | ||||
| 		result.put(Attribute.AUTHORIZED, session.getAttribute(Attribute.AUTHORIZED)); | ||||
| 		if (more != null) { | ||||
| 			switch (more) { | ||||
| 				case "1": | ||||
| 					result.put(Attribute.USER, session.getAttribute(Attribute.USER)); | ||||
| 					result.put(Attribute.OPERATOR, session.getAttribute(Attribute.OPERATOR)); | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
| 		return result; | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         String more = req.getParameter("more"); | ||||
|         Map<String, Object> result = new HashMap<>(); | ||||
|         result.put(Attribute.AUTHORIZED, session.getAttribute(Attribute.AUTHORIZED)); | ||||
|         if (more != null) { | ||||
|             switch (more) { | ||||
|                 case "1": | ||||
|                     result.put(Attribute.USER, session.getAttribute(Attribute.USER)); | ||||
|                     result.put(Attribute.OPERATOR, session.getAttribute(Attribute.OPERATOR)); | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -24,36 +24,36 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class Error { | ||||
|  | ||||
| 	public static final Error ALREADY_SUBMITTED = new Error(1); | ||||
| 	public static final Object OK = new Object(); | ||||
| 	public static final Error PARAMETER_REQUIRED = new Error(-1); | ||||
| 	public static final Error ILLEGAL_PARAMETER = new Error(-2); | ||||
| //	public static final Error REQUEST_FAILED = new Error(-3); REMOVED | ||||
| 	public static final Error LENGTH_LIMIT_EXCEEDED = new Error(-4); | ||||
| 	public static final Error INVALID_PARAMETER = new Error(-5); | ||||
| 	public static final Error USER_NOT_FOUND = new Error(-11); | ||||
| 	public static final Error TICKET_NOT_FOUND = new Error(-12); | ||||
| 	public static final Error OPERATOR_NOT_FOUND = new Error(-13); | ||||
| 	public static final Error UNAUTHORIZED = new Error(-20); | ||||
| 	public static final Error WRONG_PASSWORD = new Error(-22); | ||||
| 	public static final Error PERMISSION_DENIED = new Error(-24); | ||||
| 	public static final Error INTERNAL_ERROR = new Error(-90); | ||||
| 	public static final Error DATABASE_ERROR = new Error(-91); | ||||
|     public static final Error ALREADY_SUBMITTED = new Error(1); | ||||
|     public static final Object OK = new Object(); | ||||
|     public static final Error PARAMETER_REQUIRED = new Error(-1); | ||||
|     public static final Error ILLEGAL_PARAMETER = new Error(-2); | ||||
|     //	public static final Error REQUEST_FAILED = new Error(-3); REMOVED | ||||
|     public static final Error LENGTH_LIMIT_EXCEEDED = new Error(-4); | ||||
|     public static final Error INVALID_PARAMETER = new Error(-5); | ||||
|     public static final Error USER_NOT_FOUND = new Error(-11); | ||||
|     public static final Error TICKET_NOT_FOUND = new Error(-12); | ||||
|     public static final Error OPERATOR_NOT_FOUND = new Error(-13); | ||||
|     public static final Error UNAUTHORIZED = new Error(-20); | ||||
|     public static final Error WRONG_PASSWORD = new Error(-22); | ||||
|     public static final Error PERMISSION_DENIED = new Error(-24); | ||||
|     public static final Error INTERNAL_ERROR = new Error(-90); | ||||
|     public static final Error DATABASE_ERROR = new Error(-91); | ||||
|  | ||||
| 	public int errCode; | ||||
| 	public String errMsg; | ||||
|     public int errCode; | ||||
|     public String errMsg; | ||||
|  | ||||
| 	private Error(int code) { | ||||
| 		this(code, lang("ERR_" + code)); | ||||
| 	} | ||||
|     private Error(int code) { | ||||
|         this(code, lang("ERR_" + code)); | ||||
|     } | ||||
|  | ||||
| 	public Error(int errCode, String errMsg) { | ||||
| 		this.errCode = errCode; | ||||
| 		this.errMsg = errMsg; | ||||
| 	} | ||||
|     public Error(int errCode, String errMsg) { | ||||
|         this.errCode = errCode; | ||||
|         this.errMsg = errMsg; | ||||
|     } | ||||
|  | ||||
| 	public Error withMsg(String msg) { | ||||
| 		return new Error(errCode, msg); | ||||
| 	} | ||||
|     public Error withMsg(String msg) { | ||||
|         return new Error(errCode, msg); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -46,59 +46,59 @@ import java.io.PrintWriter; | ||||
| @WebServlet(name = "Login", urlPatterns = "/api/admin/login", loadOnStartup = 12) | ||||
| public class Login extends HttpServlet { | ||||
|  | ||||
| 	private Gson gson = SQLCore.gson; | ||||
|     private Gson gson = SQLCore.gson; | ||||
|  | ||||
| 	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
| 		doGet(request, response); | ||||
| 	} | ||||
|     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
|         doGet(request, response); | ||||
|     } | ||||
|  | ||||
| 	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
| 		request.setCharacterEncoding("utf-8"); | ||||
| 		response.setCharacterEncoding("utf-8"); | ||||
| 		response.addHeader("Content-type", "application/json;charset=utf-8"); | ||||
| 		response.addHeader("Access-Control-Allow-Origin", "*"); | ||||
| 		PrintWriter out = response.getWriter(); | ||||
| 		out.println(gson.toJson(login(request))); | ||||
| 		out.close(); | ||||
| 	} | ||||
|     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
|         request.setCharacterEncoding("utf-8"); | ||||
|         response.setCharacterEncoding("utf-8"); | ||||
|         response.addHeader("Content-type", "application/json;charset=utf-8"); | ||||
|         response.addHeader("Access-Control-Allow-Origin", "*"); | ||||
|         PrintWriter out = response.getWriter(); | ||||
|         out.println(gson.toJson(login(request))); | ||||
|         out.close(); | ||||
|     } | ||||
|  | ||||
| 	private Object login(HttpServletRequest request) { | ||||
| 		try { | ||||
| 			int oid = Integer.parseInt(request.getParameter("id")); | ||||
| 			String password = request.getParameter("pass"); | ||||
| 			boolean bypass = request.getParameter("bypass") != null; | ||||
| 			Operator op = TableOperator.get(oid); | ||||
| 			if (op == null) | ||||
| 				return Error.OPERATOR_NOT_FOUND; | ||||
| 			else if (op.getAccess() >= Access.NO_LOGIN) | ||||
| 				return Error.PERMISSION_DENIED; | ||||
|     private Object login(HttpServletRequest request) { | ||||
|         try { | ||||
|             int oid = Integer.parseInt(request.getParameter("id")); | ||||
|             String password = request.getParameter("pass"); | ||||
|             boolean bypass = request.getParameter("bypass") != null; | ||||
|             Operator op = TableOperator.get(oid); | ||||
|             if (op == null) | ||||
|                 return Error.OPERATOR_NOT_FOUND; | ||||
|             else if (op.getAccess() >= Access.NO_LOGIN) | ||||
|                 return Error.PERMISSION_DENIED; | ||||
|  | ||||
| 			if (!Crypto.check(bypass ? password : RSAUtil.decrypt(password), op.getPassword())) { | ||||
| 				return Error.WRONG_PASSWORD; | ||||
| 			} | ||||
|             if (!Crypto.check(bypass ? password : RSAUtil.decrypt(password), op.getPassword())) { | ||||
|                 return Error.WRONG_PASSWORD; | ||||
|             } | ||||
|  | ||||
| 			WxSession session = WechatSession.create(); | ||||
| 			if (bypass) { | ||||
| 				session.setAttribute(Attribute.AUTHORIZED, Command.fromId(Integer.parseInt(request.getParameter("bypass")))); | ||||
| 			} else { | ||||
| 				session.setAttribute(Attribute.AUTHORIZED, Command.LOGIN); | ||||
| 			} | ||||
|             WxSession session = WechatSession.create(); | ||||
|             if (bypass) { | ||||
|                 session.setAttribute(Attribute.AUTHORIZED, Command.fromId(Integer.parseInt(request.getParameter("bypass")))); | ||||
|             } else { | ||||
|                 session.setAttribute(Attribute.AUTHORIZED, Command.LOGIN); | ||||
|             } | ||||
|  | ||||
| 			session.setAttribute(Attribute.WECHAT, op.getWechat()); | ||||
| 			session.setAttribute(Attribute.OPERATOR, op); | ||||
|             session.setAttribute(Attribute.WECHAT, op.getWechat()); | ||||
|             session.setAttribute(Attribute.OPERATOR, op); | ||||
|  | ||||
| 			if (request.getParameter("bypassuser") != null) { | ||||
| 				User u = TableUser.getById(Long.parseLong(request.getParameter("bypassuser"))); | ||||
| 				session.setAttribute(Attribute.USER, u); | ||||
| 				session.setAttribute(Attribute.WECHAT, u.getWechatId()); | ||||
| 			} | ||||
| 			if (request.getParameter("bypasswechat") != null) { | ||||
| 				session.setAttribute(Attribute.WECHAT, request.getParameter("bypasswechat")); | ||||
| 			} | ||||
| 			return session.getId(); | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 			return Error.INTERNAL_ERROR; | ||||
| 		} | ||||
| 	} | ||||
|             if (request.getParameter("bypassuser") != null) { | ||||
|                 User u = TableUser.getById(Long.parseLong(request.getParameter("bypassuser"))); | ||||
|                 session.setAttribute(Attribute.USER, u); | ||||
|                 session.setAttribute(Attribute.WECHAT, u.getWechatId()); | ||||
|             } | ||||
|             if (request.getParameter("bypasswechat") != null) { | ||||
|                 session.setAttribute(Attribute.WECHAT, request.getParameter("bypasswechat")); | ||||
|             } | ||||
|             return session.getId(); | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|             return Error.INTERNAL_ERROR; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -32,36 +32,36 @@ import javax.servlet.http.HttpServletRequest; | ||||
|  */ | ||||
| public class GetUser extends API { | ||||
|  | ||||
| 	public GetUser() { | ||||
| 		url = "/admin/getuser"; | ||||
| 		access = Access.LEADER; | ||||
| 		authorize = Command.LOGIN; | ||||
| 	} | ||||
|     public GetUser() { | ||||
|         url = "/admin/getuser"; | ||||
|         access = Access.LEADER; | ||||
|         authorize = Command.LOGIN; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		String id = req.getParameter("id"); | ||||
| 		String name = req.getParameter("name"); | ||||
| 		if ((id == null || id.isEmpty()) && (name == null || name.isEmpty())) { | ||||
| 			return Error.PARAMETER_REQUIRED; | ||||
| 		} | ||||
| 		if (id != null) { | ||||
| 			try { | ||||
| 				User u = TableUser.getById(Long.parseLong(id)); | ||||
| 				if (u == null) | ||||
| 					return Error.USER_NOT_FOUND; | ||||
| 				else | ||||
| 					return u; | ||||
| 			} catch (NumberFormatException e) { | ||||
| 				return Error.ILLEGAL_PARAMETER; | ||||
| 			} | ||||
| 		} else { | ||||
| 			User u = TableUser.getByName(name); | ||||
| 			if (u == null) | ||||
| 				return Error.USER_NOT_FOUND; | ||||
| 			else | ||||
| 				return u; | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         String id = req.getParameter("id"); | ||||
|         String name = req.getParameter("name"); | ||||
|         if ((id == null || id.isEmpty()) && (name == null || name.isEmpty())) { | ||||
|             return Error.PARAMETER_REQUIRED; | ||||
|         } | ||||
|         if (id != null) { | ||||
|             try { | ||||
|                 User u = TableUser.getById(Long.parseLong(id)); | ||||
|                 if (u == null) | ||||
|                     return Error.USER_NOT_FOUND; | ||||
|                 else | ||||
|                     return u; | ||||
|             } catch (NumberFormatException e) { | ||||
|                 return Error.ILLEGAL_PARAMETER; | ||||
|             } | ||||
|         } else { | ||||
|             User u = TableUser.getByName(name); | ||||
|             if (u == null) | ||||
|                 return Error.USER_NOT_FOUND; | ||||
|             else | ||||
|                 return u; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,23 +31,23 @@ import java.util.Set; | ||||
|  */ | ||||
| public class DashBoard extends API { | ||||
|  | ||||
| 	public DashBoard() { | ||||
| 		url = "/root/dashboard"; | ||||
| 		access = Access.ROOT; | ||||
| 		authorize = Command.LOGIN; | ||||
| 	} | ||||
|     public DashBoard() { | ||||
|         url = "/root/dashboard"; | ||||
|         access = Access.ROOT; | ||||
|         authorize = Command.LOGIN; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		StringBuilder sb = new StringBuilder(); | ||||
| 		for (love.sola.netsupport.session.WxSession ws : WechatSession.list()) { | ||||
| 			sb.append("=====").append(ws.getId()).append("=====\n"); | ||||
| 			Set<String> e = ws.getAttributeNames(); | ||||
| 			for (String key : e) { | ||||
| 				sb.append(key).append(": ").append(ws.getAttribute(key).toString()).append("\n"); | ||||
| 			} | ||||
| 		} | ||||
| 		return sb.toString(); | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         StringBuilder sb = new StringBuilder(); | ||||
|         for (love.sola.netsupport.session.WxSession ws : WechatSession.list()) { | ||||
|             sb.append("=====").append(ws.getId()).append("=====\n"); | ||||
|             Set<String> e = ws.getAttributeNames(); | ||||
|             for (String key : e) { | ||||
|                 sb.append(key).append(": ").append(ws.getAttribute(key).toString()).append("\n"); | ||||
|             } | ||||
|         } | ||||
|         return sb.toString(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,16 +31,16 @@ import javax.servlet.http.HttpServletRequest; | ||||
|  */ | ||||
| public class FlushCache extends API { | ||||
|  | ||||
| 	public FlushCache() { | ||||
| 		url = "/root/flushcache"; | ||||
| 		access = Access.ROOT; | ||||
| 		authorize = Command.LOGIN; | ||||
| 	} | ||||
|     public FlushCache() { | ||||
|         url = "/root/flushcache"; | ||||
|         access = Access.ROOT; | ||||
|         authorize = Command.LOGIN; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		TableUser.flushCache(); | ||||
| 		return Error.OK; | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         TableUser.flushCache(); | ||||
|         return Error.OK; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -34,30 +34,30 @@ import javax.servlet.http.HttpServletRequest; | ||||
|  */ | ||||
| public class SetPassword extends API { | ||||
|  | ||||
| 	public SetPassword() { | ||||
| 		url = "/root/setpass"; | ||||
| 		access = Access.ROOT; | ||||
| 		authorize = Command.LOGIN; | ||||
| 	} | ||||
|     public SetPassword() { | ||||
|         url = "/root/setpass"; | ||||
|         access = Access.ROOT; | ||||
|         authorize = Command.LOGIN; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		String id = req.getParameter("id"); | ||||
| 		String pass = req.getParameter("pass"); | ||||
| 		if (pass == null || pass.length() < 8) { | ||||
| 			return Error.INVALID_PARAMETER; | ||||
| 		} | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			s.beginTransaction(); | ||||
| 			Operator op = s.get(Operator.class, Integer.parseInt(id)); | ||||
| 			if (op == null) { | ||||
| 				return Error.OPERATOR_NOT_FOUND; | ||||
| 			} | ||||
| 			op.setPassword(Crypto.hash(pass)); | ||||
| 			s.update(op); | ||||
| 			s.getTransaction().commit(); | ||||
| 			return Error.OK; | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         String id = req.getParameter("id"); | ||||
|         String pass = req.getParameter("pass"); | ||||
|         if (pass == null || pass.length() < 8) { | ||||
|             return Error.INVALID_PARAMETER; | ||||
|         } | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             s.beginTransaction(); | ||||
|             Operator op = s.get(Operator.class, Integer.parseInt(id)); | ||||
|             if (op == null) { | ||||
|                 return Error.OPERATOR_NOT_FOUND; | ||||
|             } | ||||
|             op.setPassword(Crypto.hash(pass)); | ||||
|             s.update(op); | ||||
|             s.getTransaction().commit(); | ||||
|             return Error.OK; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -38,35 +38,35 @@ import java.util.Date; | ||||
|  */ | ||||
| public class TicketLog extends API { | ||||
|  | ||||
| 	public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); | ||||
|     public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); | ||||
|  | ||||
| 	public TicketLog() { | ||||
| 		url = "/admin/ticketlog"; | ||||
| 		access = Access.MEMBER; | ||||
| 		authorize = Command.LOGIN; | ||||
| 	} | ||||
|     public TicketLog() { | ||||
|         url = "/admin/ticketlog"; | ||||
|         access = Access.MEMBER; | ||||
|         authorize = Command.LOGIN; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		int first; | ||||
| 		int limit; | ||||
| 		Date start; | ||||
| 		Date end; | ||||
| 		first = req.getParameter("first") == null ? 0 : Integer.parseInt(req.getParameter("first")); | ||||
| 		limit = req.getParameter("limit") == null ? 20 : Integer.parseInt(req.getParameter("limit")); | ||||
| 		start = req.getParameter("start") == null ? getToday() : dateFormat.parse(req.getParameter("start")); | ||||
| 		end = req.getParameter("end") == null ? getToday() : dateFormat.parse(req.getParameter("end")); | ||||
| 		end = DateUtils.addDays(end, 1); | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			AuditReader reader = TableTicket.getAuditReader(s); | ||||
| 			return reader.createQuery() | ||||
| 					.forRevisionsOfEntity(Ticket.class, false, true) | ||||
| 					.addOrder(AuditEntity.revisionNumber().desc()) | ||||
| 					.add(AuditEntity.revisionProperty("timestamp").between(start.getTime(), end.getTime())) | ||||
| 					.setFirstResult(first) | ||||
| 					.setMaxResults(limit) | ||||
| 					.getResultList(); | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         int first; | ||||
|         int limit; | ||||
|         Date start; | ||||
|         Date end; | ||||
|         first = req.getParameter("first") == null ? 0 : Integer.parseInt(req.getParameter("first")); | ||||
|         limit = req.getParameter("limit") == null ? 20 : Integer.parseInt(req.getParameter("limit")); | ||||
|         start = req.getParameter("start") == null ? getToday() : dateFormat.parse(req.getParameter("start")); | ||||
|         end = req.getParameter("end") == null ? getToday() : dateFormat.parse(req.getParameter("end")); | ||||
|         end = DateUtils.addDays(end, 1); | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             AuditReader reader = TableTicket.getAuditReader(s); | ||||
|             return reader.createQuery() | ||||
|                     .forRevisionsOfEntity(Ticket.class, false, true) | ||||
|                     .addOrder(AuditEntity.revisionNumber().desc()) | ||||
|                     .add(AuditEntity.revisionProperty("timestamp").between(start.getTime(), end.getTime())) | ||||
|                     .setFirstResult(first) | ||||
|                     .setMaxResults(limit) | ||||
|                     .getResultList(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -32,22 +32,22 @@ import javax.servlet.http.HttpServletRequest; | ||||
|  */ | ||||
| public class TicketLookup extends API { | ||||
|  | ||||
| 	public TicketLookup() { | ||||
| 		url = "/admin/ticketlookup"; | ||||
| 		access = Access.MEMBER; | ||||
| 		authorize = Command.LOGIN; | ||||
| 	} | ||||
|     public TicketLookup() { | ||||
|         url = "/admin/ticketlookup"; | ||||
|         access = Access.MEMBER; | ||||
|         authorize = Command.LOGIN; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		Operator op = session.getAttribute(Attribute.OPERATOR); | ||||
| 		int block; | ||||
| 		if (req.getParameter("block") != null) { | ||||
| 			block = Integer.parseInt(req.getParameter("block")); | ||||
| 		} else { | ||||
| 			block = op.getBlock(); | ||||
| 		} | ||||
| 		return TableTicket.unsolvedByBlock(block); | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         Operator op = session.getAttribute(Attribute.OPERATOR); | ||||
|         int block; | ||||
|         if (req.getParameter("block") != null) { | ||||
|             block = Integer.parseInt(req.getParameter("block")); | ||||
|         } else { | ||||
|             block = op.getBlock(); | ||||
|         } | ||||
|         return TableTicket.unsolvedByBlock(block); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,19 +31,19 @@ import javax.servlet.http.HttpServletRequest; | ||||
|  */ | ||||
| public class TicketTrack extends API { | ||||
|  | ||||
| 	public TicketTrack() { | ||||
| 		url = "/admin/tickettrack"; | ||||
| 		access = Access.MEMBER; | ||||
| 		authorize = Command.LOGIN; | ||||
| 	} | ||||
|     public TicketTrack() { | ||||
|         url = "/admin/tickettrack"; | ||||
|         access = Access.MEMBER; | ||||
|         authorize = Command.LOGIN; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		String tid = req.getParameter("id"); | ||||
| 		if (tid == null) { | ||||
| 			return Error.PARAMETER_REQUIRED; | ||||
| 		} | ||||
| 		return TableTicket.track(Integer.parseInt(tid)); | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         String tid = req.getParameter("id"); | ||||
|         if (tid == null) { | ||||
|             return Error.PARAMETER_REQUIRED; | ||||
|         } | ||||
|         return TableTicket.track(Integer.parseInt(tid)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -37,32 +37,32 @@ import java.util.Date; | ||||
|  */ | ||||
| public class TicketUpdate extends API { | ||||
|  | ||||
| 	public TicketUpdate() { | ||||
| 		url = "/admin/ticketupdate"; | ||||
| 		access = Access.MEMBER; | ||||
| 		authorize = Command.LOGIN; | ||||
| 	} | ||||
|     public TicketUpdate() { | ||||
|         url = "/admin/ticketupdate"; | ||||
|         access = Access.MEMBER; | ||||
|         authorize = Command.LOGIN; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		String ticket = req.getParameter("ticket"); | ||||
| 		String remark = req.getParameter("remark"); | ||||
| 		String status = req.getParameter("status"); | ||||
| 		if (Checker.hasNull(ticket, remark, status)) return Error.PARAMETER_REQUIRED; | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			Operator op = session.getAttribute(Attribute.OPERATOR); | ||||
| 			Ticket t = s.get(Ticket.class, Integer.parseInt(ticket)); | ||||
| 			if (t == null) { | ||||
| 				return Error.TICKET_NOT_FOUND; | ||||
| 			} | ||||
| 			t.setOperator(op); | ||||
| 			t.setRemark(remark); | ||||
| 			t.setStatus(Integer.parseInt(status)); | ||||
| 			t.setUpdateTime(new Date()); | ||||
| 			s.beginTransaction(); | ||||
| 			s.update(t); | ||||
| 			s.getTransaction().commit(); | ||||
| 			return t; | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         String ticket = req.getParameter("ticket"); | ||||
|         String remark = req.getParameter("remark"); | ||||
|         String status = req.getParameter("status"); | ||||
|         if (Checker.hasNull(ticket, remark, status)) return Error.PARAMETER_REQUIRED; | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             Operator op = session.getAttribute(Attribute.OPERATOR); | ||||
|             Ticket t = s.get(Ticket.class, Integer.parseInt(ticket)); | ||||
|             if (t == null) { | ||||
|                 return Error.TICKET_NOT_FOUND; | ||||
|             } | ||||
|             t.setOperator(op); | ||||
|             t.setRemark(remark); | ||||
|             t.setStatus(Integer.parseInt(status)); | ||||
|             t.setUpdateTime(new Date()); | ||||
|             s.beginTransaction(); | ||||
|             s.update(t); | ||||
|             s.getTransaction().commit(); | ||||
|             return t; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -37,39 +37,39 @@ import static love.sola.netsupport.util.Checker.*; | ||||
|  */ | ||||
| public class ProfileModify extends API { | ||||
|  | ||||
| 	public ProfileModify() { | ||||
| 		url = "/profilemodify"; | ||||
| 		access = Access.USER; | ||||
| 		authorize = Command.PROFILE; | ||||
| 	} | ||||
|     public ProfileModify() { | ||||
|         url = "/profilemodify"; | ||||
|         access = Access.USER; | ||||
|         authorize = Command.PROFILE; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		User u = session.getAttribute(Attribute.USER); | ||||
| 		ISP isp = checkISP(req.getParameter("isp")); | ||||
| 		String netAccount = checkNetAccount(req.getParameter("username"), isp); | ||||
| 		int block = checkBlock(req.getParameter("block")); | ||||
| 		int room = checkRoom(req.getParameter("room"), block); | ||||
| 		long phone = checkPhoneNumber(req.getParameter("phone")); | ||||
| 		if (room == -1) | ||||
| 			return Error.INVALID_PARAMETER.withMsg("Invalid_Room"); | ||||
| 		if (phone == -1) | ||||
| 			return Error.INVALID_PARAMETER.withMsg("Invalid_Phone_Number"); | ||||
| 		if (netAccount == null) | ||||
| 			return Error.INVALID_PARAMETER.withMsg("Invalid_Account"); | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         User u = session.getAttribute(Attribute.USER); | ||||
|         ISP isp = checkISP(req.getParameter("isp")); | ||||
|         String netAccount = checkNetAccount(req.getParameter("username"), isp); | ||||
|         int block = checkBlock(req.getParameter("block")); | ||||
|         int room = checkRoom(req.getParameter("room"), block); | ||||
|         long phone = checkPhoneNumber(req.getParameter("phone")); | ||||
|         if (room == -1) | ||||
|             return Error.INVALID_PARAMETER.withMsg("Invalid_Room"); | ||||
|         if (phone == -1) | ||||
|             return Error.INVALID_PARAMETER.withMsg("Invalid_Phone_Number"); | ||||
|         if (netAccount == null) | ||||
|             return Error.INVALID_PARAMETER.withMsg("Invalid_Account"); | ||||
|  | ||||
| 		u.setIsp(isp); | ||||
| 		u.setNetAccount(netAccount); | ||||
| 		u.setBlock(block); | ||||
| 		u.setRoom(room); | ||||
| 		u.setPhone(phone); | ||||
| 		try { | ||||
| 			TableUser.update(u); | ||||
| 		} catch (ConstraintViolationException e) { | ||||
| 			String dupKey = e.getConstraintName(); | ||||
| 			return Error.INVALID_PARAMETER.withMsg("Duplicated_" + dupKey.toUpperCase()); | ||||
| 		} | ||||
| 		session.invalidate(); | ||||
| 		return Error.OK; | ||||
| 	} | ||||
|         u.setIsp(isp); | ||||
|         u.setNetAccount(netAccount); | ||||
|         u.setBlock(block); | ||||
|         u.setRoom(room); | ||||
|         u.setPhone(phone); | ||||
|         try { | ||||
|             TableUser.update(u); | ||||
|         } catch (ConstraintViolationException e) { | ||||
|             String dupKey = e.getConstraintName(); | ||||
|             return Error.INVALID_PARAMETER.withMsg("Duplicated_" + dupKey.toUpperCase()); | ||||
|         } | ||||
|         session.invalidate(); | ||||
|         return Error.OK; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -37,56 +37,56 @@ import static love.sola.netsupport.util.Checker.*; | ||||
|  */ | ||||
| public class Register extends API { | ||||
|  | ||||
| 	public Register() { | ||||
| 		url = "/register"; | ||||
| 		access = Access.GUEST; | ||||
| 		authorize = Command.REGISTER; | ||||
| 	} | ||||
|     public Register() { | ||||
|         url = "/register"; | ||||
|         access = Access.GUEST; | ||||
|         authorize = Command.REGISTER; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		String wechat = session.getAttribute(Attribute.WECHAT); | ||||
| 		if (wechat == null) { | ||||
| 			return Error.UNAUTHORIZED; | ||||
| 		} | ||||
| 		ISP isp = checkISP(req.getParameter("isp")); | ||||
| 		int block = checkBlock(req.getParameter("block")); | ||||
| 		return register( | ||||
| 				checkStudentId(req.getParameter("sid")), | ||||
| 				req.getParameter("name"), | ||||
| 				isp, | ||||
| 				checkNetAccount(req.getParameter("username"), isp), | ||||
| 				block, | ||||
| 				checkRoom(req.getParameter("room"), block), | ||||
| 				checkPhoneNumber(req.getParameter("phone")), | ||||
| 				wechat); | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         String wechat = session.getAttribute(Attribute.WECHAT); | ||||
|         if (wechat == null) { | ||||
|             return Error.UNAUTHORIZED; | ||||
|         } | ||||
|         ISP isp = checkISP(req.getParameter("isp")); | ||||
|         int block = checkBlock(req.getParameter("block")); | ||||
|         return register( | ||||
|                 checkStudentId(req.getParameter("sid")), | ||||
|                 req.getParameter("name"), | ||||
|                 isp, | ||||
|                 checkNetAccount(req.getParameter("username"), isp), | ||||
|                 block, | ||||
|                 checkRoom(req.getParameter("room"), block), | ||||
|                 checkPhoneNumber(req.getParameter("phone")), | ||||
|                 wechat); | ||||
|     } | ||||
|  | ||||
| 	private Object register(long sid, String name, ISP isp, String netAccount, int block, int room, long phone, String wechat) { | ||||
| 		if (sid == -1) return Error.INVALID_PARAMETER.withMsg("Invalid_Student_Id"); | ||||
| 		if (name == null) return Error.INVALID_PARAMETER.withMsg("Invalid_Name"); | ||||
| 		if (isp == null) return Error.INVALID_PARAMETER.withMsg("Invalid_ISP"); | ||||
| 		if (netAccount == null) return Error.INVALID_PARAMETER.withMsg("Invalid_Account"); | ||||
| 		if (block == -1) return Error.INVALID_PARAMETER.withMsg("Invalid_Block"); | ||||
| 		if (room == -1) return Error.INVALID_PARAMETER.withMsg("Invalid_Room"); | ||||
| 		if (phone == -1) return Error.INVALID_PARAMETER.withMsg("Invalid_Phone_Number"); | ||||
| 		User user = TableUser.getById(sid); | ||||
| 		if (user == null) return Error.INVALID_PARAMETER.withMsg("Invalid_Student_Id"); | ||||
| 		if (!user.getName().equals(name)) return Error.INVALID_PARAMETER.withMsg("Invalid_Name"); | ||||
| 		if (user.getWechatId() != null) return Error.INVALID_PARAMETER.withMsg("User_Already_Registered"); | ||||
| 		user.setIsp(isp); | ||||
| 		user.setNetAccount(netAccount); | ||||
| 		user.setBlock(block); | ||||
| 		user.setRoom(room); | ||||
| 		user.setPhone(phone); | ||||
| 		user.setWechatId(wechat); | ||||
| 		try { | ||||
| 			TableUser.update(user); | ||||
| 		} catch (ConstraintViolationException e) { | ||||
| 			String dupKey = e.getConstraintName(); | ||||
| 			return Error.INVALID_PARAMETER.withMsg("Duplicated_" + dupKey.toUpperCase()); // PHONE ACCOUNT WECHAT | ||||
| 		} | ||||
| 		return Error.OK; | ||||
| 	} | ||||
|     private Object register(long sid, String name, ISP isp, String netAccount, int block, int room, long phone, String wechat) { | ||||
|         if (sid == -1) return Error.INVALID_PARAMETER.withMsg("Invalid_Student_Id"); | ||||
|         if (name == null) return Error.INVALID_PARAMETER.withMsg("Invalid_Name"); | ||||
|         if (isp == null) return Error.INVALID_PARAMETER.withMsg("Invalid_ISP"); | ||||
|         if (netAccount == null) return Error.INVALID_PARAMETER.withMsg("Invalid_Account"); | ||||
|         if (block == -1) return Error.INVALID_PARAMETER.withMsg("Invalid_Block"); | ||||
|         if (room == -1) return Error.INVALID_PARAMETER.withMsg("Invalid_Room"); | ||||
|         if (phone == -1) return Error.INVALID_PARAMETER.withMsg("Invalid_Phone_Number"); | ||||
|         User user = TableUser.getById(sid); | ||||
|         if (user == null) return Error.INVALID_PARAMETER.withMsg("Invalid_Student_Id"); | ||||
|         if (!user.getName().equals(name)) return Error.INVALID_PARAMETER.withMsg("Invalid_Name"); | ||||
|         if (user.getWechatId() != null) return Error.INVALID_PARAMETER.withMsg("User_Already_Registered"); | ||||
|         user.setIsp(isp); | ||||
|         user.setNetAccount(netAccount); | ||||
|         user.setBlock(block); | ||||
|         user.setRoom(room); | ||||
|         user.setPhone(phone); | ||||
|         user.setWechatId(wechat); | ||||
|         try { | ||||
|             TableUser.update(user); | ||||
|         } catch (ConstraintViolationException e) { | ||||
|             String dupKey = e.getConstraintName(); | ||||
|             return Error.INVALID_PARAMETER.withMsg("Duplicated_" + dupKey.toUpperCase()); // PHONE ACCOUNT WECHAT | ||||
|         } | ||||
|         return Error.OK; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -37,33 +37,33 @@ import javax.servlet.http.HttpServletRequest; | ||||
|  */ | ||||
| public class TicketQuery extends API { | ||||
|  | ||||
| 	public TicketQuery() { | ||||
| 		url = "/ticketquery"; | ||||
| 		access = Access.USER; | ||||
| 		authorize = Command.QUERY; | ||||
| 	} | ||||
|     public TicketQuery() { | ||||
|         url = "/ticketquery"; | ||||
|         access = Access.USER; | ||||
|         authorize = Command.QUERY; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			User u = session.getAttribute(Attribute.USER); | ||||
| 			Criteria c = s.createCriteria(Ticket.class); | ||||
| 			int first = req.getParameter("offset") == null ? 0 : Integer.parseInt(req.getParameter("offset")); | ||||
| 			int limit = req.getParameter("limit") == null ? 5 : Integer.parseInt(req.getParameter("limit")); | ||||
| 			c.setFirstResult(first); | ||||
| 			c.setMaxResults(limit); | ||||
| 			c.addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)); | ||||
| 			c.add(Restrictions.eq(Ticket.PROPERTY_USER, u)); | ||||
| 			if (req.getParameter("status") != null) { | ||||
| 				c.add(Restrictions.eq(Ticket.PROPERTY_STATUS, Integer.parseInt(req.getParameter("status")))); | ||||
| 			} else if (req.getParameter("statusl") != null && req.getParameter("statush") != null) { | ||||
| 				c.add(Restrictions.between(Ticket.PROPERTY_STATUS, | ||||
| 						Integer.parseInt(req.getParameter("statusl")), | ||||
| 						Integer.parseInt(req.getParameter("statush")) | ||||
| 				)); | ||||
| 			} | ||||
| 			return c.list(); | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             User u = session.getAttribute(Attribute.USER); | ||||
|             Criteria c = s.createCriteria(Ticket.class); | ||||
|             int first = req.getParameter("offset") == null ? 0 : Integer.parseInt(req.getParameter("offset")); | ||||
|             int limit = req.getParameter("limit") == null ? 5 : Integer.parseInt(req.getParameter("limit")); | ||||
|             c.setFirstResult(first); | ||||
|             c.setMaxResults(limit); | ||||
|             c.addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)); | ||||
|             c.add(Restrictions.eq(Ticket.PROPERTY_USER, u)); | ||||
|             if (req.getParameter("status") != null) { | ||||
|                 c.add(Restrictions.eq(Ticket.PROPERTY_STATUS, Integer.parseInt(req.getParameter("status")))); | ||||
|             } else if (req.getParameter("statusl") != null && req.getParameter("statush") != null) { | ||||
|                 c.add(Restrictions.between(Ticket.PROPERTY_STATUS, | ||||
|                         Integer.parseInt(req.getParameter("statusl")), | ||||
|                         Integer.parseInt(req.getParameter("statush")) | ||||
|                 )); | ||||
|             } | ||||
|             return c.list(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -37,37 +37,37 @@ import javax.servlet.http.HttpServletRequest; | ||||
|  */ | ||||
| public class TicketSubmit extends API { | ||||
|  | ||||
| 	public TicketSubmit() { | ||||
| 		url = "/ticketsubmit"; | ||||
| 		access = Access.USER; | ||||
| 		authorize = Command.SUBMIT; | ||||
| 	} | ||||
|     public TicketSubmit() { | ||||
|         url = "/ticketsubmit"; | ||||
|         access = Access.USER; | ||||
|         authorize = Command.SUBMIT; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
| 		String desc = req.getParameter("desc"); | ||||
| 		if (desc == null || desc.isEmpty()) { | ||||
| 			return Error.PARAMETER_REQUIRED; | ||||
| 		} | ||||
| 		if (desc.length() > Settings.MAX_DESC_LENGTH) { | ||||
| 			return Error.LENGTH_LIMIT_EXCEEDED; | ||||
| 		} | ||||
|     @Override | ||||
|     protected Object process(HttpServletRequest req, WxSession session) throws Exception { | ||||
|         String desc = req.getParameter("desc"); | ||||
|         if (desc == null || desc.isEmpty()) { | ||||
|             return Error.PARAMETER_REQUIRED; | ||||
|         } | ||||
|         if (desc.length() > Settings.MAX_DESC_LENGTH) { | ||||
|             return Error.LENGTH_LIMIT_EXCEEDED; | ||||
|         } | ||||
|  | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			User u = session.getAttribute(Attribute.USER); | ||||
| 			if (TableTicket.hasOpen(u)) { | ||||
| 				session.invalidate(); | ||||
| 				return Error.ALREADY_SUBMITTED; | ||||
| 			} | ||||
| 			Ticket t = new Ticket(); | ||||
| 			t.setUser(u); | ||||
| 			t.setDescription(desc); | ||||
| 			t.setStatus(0); | ||||
| 			s.beginTransaction(); | ||||
| 			s.save(t); | ||||
| 			s.getTransaction().commit(); | ||||
| 			session.invalidate(); | ||||
| 			return Error.OK; | ||||
| 		} | ||||
| 	} | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             User u = session.getAttribute(Attribute.USER); | ||||
|             if (TableTicket.hasOpen(u)) { | ||||
|                 session.invalidate(); | ||||
|                 return Error.ALREADY_SUBMITTED; | ||||
|             } | ||||
|             Ticket t = new Ticket(); | ||||
|             t.setUser(u); | ||||
|             t.setDescription(desc); | ||||
|             t.setStatus(0); | ||||
|             s.beginTransaction(); | ||||
|             s.save(t); | ||||
|             s.getTransaction().commit(); | ||||
|             session.invalidate(); | ||||
|             return Error.OK; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -40,45 +40,45 @@ import java.util.Map; | ||||
| @WebServlet(name = "OAuth2", urlPatterns = "/oauth2/callback", loadOnStartup = 21, asyncSupported = true) | ||||
| public class OAuth2 extends HttpServlet { | ||||
|  | ||||
| 	private static Map<String, OAuth2Handler> oAuth2HandlerMap = new HashMap<>(); | ||||
|     private static Map<String, OAuth2Handler> oAuth2HandlerMap = new HashMap<>(); | ||||
|  | ||||
| 	/** | ||||
| 	 * for {@link love.sola.netsupport.wechat.WxMpServlet#registerCommands} | ||||
| 	 * | ||||
| 	 * @param state   the state key from open platform callback. | ||||
| 	 * @param handler handler | ||||
| 	 */ | ||||
| 	public static void registerOAuth2Handler(String state, OAuth2Handler handler) { | ||||
| 		oAuth2HandlerMap.put(state, handler); | ||||
| 	} | ||||
|     /** | ||||
|      * for {@link love.sola.netsupport.wechat.WxMpServlet#registerCommands} | ||||
|      * | ||||
|      * @param state   the state key from open platform callback. | ||||
|      * @param handler handler | ||||
|      */ | ||||
|     public static void registerOAuth2Handler(String state, OAuth2Handler handler) { | ||||
|         oAuth2HandlerMap.put(state, handler); | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
| 		AsyncContext actx = req.startAsync(); | ||||
| 		String code = req.getParameter("code"); | ||||
| 		String state = req.getParameter("state"); | ||||
| 		if (Checker.hasNull(code, state)) { | ||||
| 			resp.sendError(HttpServletResponse.SC_FORBIDDEN); | ||||
| 			return; | ||||
| 		} | ||||
| 		OAuth2Handler handler = oAuth2HandlerMap.get(state); | ||||
| 		if (handler == null) { | ||||
| 			resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); | ||||
| 			return; | ||||
| 		} | ||||
| 		actx.start(() -> { | ||||
| 			try { | ||||
| 				WxMpService wxMpService = WxMpServlet.instance.wxMpService; | ||||
| 				WxMpOAuth2AccessToken token = wxMpService.oauth2getAccessToken(code); | ||||
| 				String wechat = token.getOpenId(); | ||||
| 				WxSession session = WechatSession.create(); | ||||
| 				handler.onOAuth2(actx, (HttpServletResponse) actx.getResponse(), wechat, session); | ||||
| 				actx.complete(); | ||||
| 			} catch (Exception e) { | ||||
| 				e.printStackTrace(); | ||||
| 			} | ||||
| 		}); | ||||
|     @Override | ||||
|     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
|         AsyncContext actx = req.startAsync(); | ||||
|         String code = req.getParameter("code"); | ||||
|         String state = req.getParameter("state"); | ||||
|         if (Checker.hasNull(code, state)) { | ||||
|             resp.sendError(HttpServletResponse.SC_FORBIDDEN); | ||||
|             return; | ||||
|         } | ||||
|         OAuth2Handler handler = oAuth2HandlerMap.get(state); | ||||
|         if (handler == null) { | ||||
|             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); | ||||
|             return; | ||||
|         } | ||||
|         actx.start(() -> { | ||||
|             try { | ||||
|                 WxMpService wxMpService = WxMpServlet.instance.wxMpService; | ||||
|                 WxMpOAuth2AccessToken token = wxMpService.oauth2getAccessToken(code); | ||||
|                 String wechat = token.getOpenId(); | ||||
|                 WxSession session = WechatSession.create(); | ||||
|                 handler.onOAuth2(actx, (HttpServletResponse) actx.getResponse(), wechat, session); | ||||
|                 actx.complete(); | ||||
|             } catch (Exception e) { | ||||
|                 e.printStackTrace(); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
| 	} | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -27,6 +27,6 @@ import javax.servlet.http.HttpServletResponse; | ||||
|  */ | ||||
| public interface OAuth2Handler { | ||||
|  | ||||
| 	void onOAuth2(AsyncContext actx, HttpServletResponse resp, String user, WxSession session); | ||||
|     void onOAuth2(AsyncContext actx, HttpServletResponse resp, String user, WxSession session); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -29,31 +29,31 @@ import java.util.regex.Pattern; | ||||
|  */ | ||||
| public class Cortana { | ||||
|  | ||||
| 	public static List<Compiled> entries; | ||||
|     public static List<Compiled> entries; | ||||
|  | ||||
| 	public static void load() { | ||||
| 		InputStream in = Lang.class.getClassLoader().getResourceAsStream("cortana.yml"); | ||||
| 		RawConfig root = new Yaml().loadAs(in, RawConfig.class); | ||||
| 	} | ||||
|     public static void load() { | ||||
|         InputStream in = Lang.class.getClassLoader().getResourceAsStream("cortana.yml"); | ||||
|         RawConfig root = new Yaml().loadAs(in, RawConfig.class); | ||||
|     } | ||||
|  | ||||
| 	static class Compiled { | ||||
| 		Pattern[] patterns; | ||||
| 		String[] replies; | ||||
| 	} | ||||
|     static class Compiled { | ||||
|         Pattern[] patterns; | ||||
|         String[] replies; | ||||
|     } | ||||
|  | ||||
| 	public static class Rule { | ||||
| 		String[] regexp; | ||||
| 		String[] replies; | ||||
|     public static class Rule { | ||||
|         String[] regexp; | ||||
|         String[] replies; | ||||
|  | ||||
| 		public Rule() { | ||||
| 		} | ||||
| 	} | ||||
|         public Rule() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static class RawConfig { | ||||
| 		Map<String, Rule> rules; | ||||
|     public static class RawConfig { | ||||
|         Map<String, Rule> rules; | ||||
|  | ||||
| 		public RawConfig() { | ||||
| 		} | ||||
| 	} | ||||
|         public RawConfig() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -29,29 +29,29 @@ import java.util.Map; | ||||
|  */ | ||||
| public class Lang { | ||||
|  | ||||
| 	public static Map<String, String> messages; | ||||
| 	public static Map<String, MessageFormat> format_cache = new HashMap<>(32); | ||||
|     public static Map<String, String> messages; | ||||
|     public static Map<String, MessageFormat> format_cache = new HashMap<>(32); | ||||
|  | ||||
| 	static { | ||||
| 		InputStream in = Lang.class.getClassLoader().getResourceAsStream("lang.yml"); | ||||
| 		//noinspection unchecked | ||||
| 		messages = new Yaml().loadAs(in, Map.class); | ||||
| 	} | ||||
|     static { | ||||
|         InputStream in = Lang.class.getClassLoader().getResourceAsStream("lang.yml"); | ||||
|         //noinspection unchecked | ||||
|         messages = new Yaml().loadAs(in, Map.class); | ||||
|     } | ||||
|  | ||||
| 	public static String lang(String key) { | ||||
| 		String value = messages.get(key); | ||||
| 		return value == null ? "!!" + key + "!!" : value; | ||||
| 	} | ||||
|     public static String lang(String key) { | ||||
|         String value = messages.get(key); | ||||
|         return value == null ? "!!" + key + "!!" : value; | ||||
|     } | ||||
|  | ||||
| 	public static String format(String key, Object... args) { | ||||
| 		MessageFormat cache = format_cache.get(key); | ||||
| 		if (cache != null) { | ||||
| 			return cache.format(args); | ||||
| 		} else { | ||||
| 			cache = new MessageFormat(lang(key)); | ||||
| 			format_cache.put(key, cache); | ||||
| 			return cache.format(args); | ||||
| 		} | ||||
| 	} | ||||
|     public static String format(String key, Object... args) { | ||||
|         MessageFormat cache = format_cache.get(key); | ||||
|         if (cache != null) { | ||||
|             return cache.format(args); | ||||
|         } else { | ||||
|             cache = new MessageFormat(lang(key)); | ||||
|             format_cache.put(key, cache); | ||||
|             return cache.format(args); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,7 +31,7 @@ public class Settings { | ||||
|     static { | ||||
|         I = TableConfig.getSettings(); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     public String Wechat_AppId; | ||||
|     public String Wechat_Secret; | ||||
|     public String Wechat_Token; | ||||
|   | ||||
| @@ -28,40 +28,40 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class Access { | ||||
|  | ||||
| 	public static final int GOD_MODE = -1; | ||||
| 	public static final int ROOT = 0; | ||||
| 	public static final int MANAGER = 1; | ||||
| 	public static final int CO_MANAGER = 2; | ||||
| 	public static final int LEADER = 3; | ||||
| 	public static final int CO_LEADER = 4; | ||||
| 	public static final int ELITE = 5; | ||||
| 	public static final int ELDER = 6; | ||||
| 	public static final int MEMBER = 7; | ||||
| 	public static final int PRE_MEMBER = 8; | ||||
| 	public static final int NO_LOGIN = 9; | ||||
| 	public static final int USER = 10; | ||||
| 	public static final int GUEST = 11; | ||||
|     public static final int GOD_MODE = -1; | ||||
|     public static final int ROOT = 0; | ||||
|     public static final int MANAGER = 1; | ||||
|     public static final int CO_MANAGER = 2; | ||||
|     public static final int LEADER = 3; | ||||
|     public static final int CO_LEADER = 4; | ||||
|     public static final int ELITE = 5; | ||||
|     public static final int ELDER = 6; | ||||
|     public static final int MEMBER = 7; | ||||
|     public static final int PRE_MEMBER = 8; | ||||
|     public static final int NO_LOGIN = 9; | ||||
|     public static final int USER = 10; | ||||
|     public static final int GUEST = 11; | ||||
|  | ||||
| 	public static final Map<Integer, String> inverseMap = new HashMap<>(); | ||||
|     public static final Map<Integer, String> inverseMap = new HashMap<>(); | ||||
|  | ||||
| 	static { | ||||
| 		System.out.println("Loading Access..."); | ||||
| 		for (Field field : Access.class.getDeclaredFields()) { | ||||
| 			if (field.getType().isAssignableFrom(Integer.TYPE)) { | ||||
| 				try { | ||||
| 					inverseMap.put((Integer) field.get(null), field.getName()); | ||||
| 				} catch (IllegalAccessException e) { | ||||
| 					e.printStackTrace(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     static { | ||||
|         System.out.println("Loading Access..."); | ||||
|         for (Field field : Access.class.getDeclaredFields()) { | ||||
|             if (field.getType().isAssignableFrom(Integer.TYPE)) { | ||||
|                 try { | ||||
|                     inverseMap.put((Integer) field.get(null), field.getName()); | ||||
|                 } catch (IllegalAccessException e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static String getLocalized(int access) { | ||||
| 		if (inverseMap.containsKey(access)) { | ||||
| 			return lang("ACCESS_" + inverseMap.get(access)); | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
|     public static String getLocalized(int access) { | ||||
|         if (inverseMap.containsKey(access)) { | ||||
|             return lang("ACCESS_" + inverseMap.get(access)); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -22,9 +22,9 @@ package love.sola.netsupport.enums; | ||||
|  */ | ||||
| public class Attribute { | ||||
|  | ||||
| 	public static final String AUTHORIZED = "authorized"; | ||||
| 	public static final String WECHAT = "wechat"; | ||||
| 	public static final String OPERATOR = "operator"; | ||||
| 	public static final String USER = "user"; | ||||
|     public static final String AUTHORIZED = "authorized"; | ||||
|     public static final String WECHAT = "wechat"; | ||||
|     public static final String OPERATOR = "operator"; | ||||
|     public static final String USER = "user"; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -26,61 +26,61 @@ import java.util.Map; | ||||
|  */ | ||||
| public class Block { | ||||
|  | ||||
| 	public static final int QT_18 = 10; | ||||
| 	public static final int QT_19 = 11; | ||||
| 	public static final int QT_16 = 12; | ||||
| 	public static final int QT_17 = 13; | ||||
| 	public static final int BM_7 = 20; | ||||
| 	public static final int BM_8 = 21; | ||||
| 	public static final int BM_9 = 22; | ||||
| 	public static final int BM_10 = 23; | ||||
| 	public static final int BM_11 = 24; | ||||
| 	public static final int DM_12 = 30; | ||||
| 	public static final int DM_13 = 31; | ||||
| 	public static final int DM_14 = 32; | ||||
| 	public static final int DM_15 = 33; | ||||
| 	public static final int DM_20 = 34; | ||||
| 	public static final int DM_21 = 35; | ||||
| 	public static final int XH_A = 40; | ||||
| 	public static final int XH_B = 41; | ||||
| 	public static final int XH_C = 42; | ||||
| 	public static final int XH_D = 43; | ||||
| 	public static final int FX_1 = 50; | ||||
| 	public static final int FX_2 = 51; | ||||
| 	public static final int FX_3 = 52; | ||||
| 	public static final int FX_4 = 53; | ||||
| 	public static final int FX_5 = 54; | ||||
| 	public static final int FX_6 = 55; | ||||
| 	public static final int BS_1 = 60; | ||||
| 	public static final int BS_2 = 61; | ||||
| 	public static final int BS_3 = 62; | ||||
| 	public static final int BS_4 = 63; | ||||
| 	public static final int BS_5 = 64; | ||||
| 	public static final int BS_6 = 65; | ||||
| 	public static final int BS_7 = 66; | ||||
| 	public static final int BS_8 = 67; | ||||
| 	public static final int BS_9 = 68; | ||||
| 	public static final int ZH = 80; | ||||
|     public static final int QT_18 = 10; | ||||
|     public static final int QT_19 = 11; | ||||
|     public static final int QT_16 = 12; | ||||
|     public static final int QT_17 = 13; | ||||
|     public static final int BM_7 = 20; | ||||
|     public static final int BM_8 = 21; | ||||
|     public static final int BM_9 = 22; | ||||
|     public static final int BM_10 = 23; | ||||
|     public static final int BM_11 = 24; | ||||
|     public static final int DM_12 = 30; | ||||
|     public static final int DM_13 = 31; | ||||
|     public static final int DM_14 = 32; | ||||
|     public static final int DM_15 = 33; | ||||
|     public static final int DM_20 = 34; | ||||
|     public static final int DM_21 = 35; | ||||
|     public static final int XH_A = 40; | ||||
|     public static final int XH_B = 41; | ||||
|     public static final int XH_C = 42; | ||||
|     public static final int XH_D = 43; | ||||
|     public static final int FX_1 = 50; | ||||
|     public static final int FX_2 = 51; | ||||
|     public static final int FX_3 = 52; | ||||
|     public static final int FX_4 = 53; | ||||
|     public static final int FX_5 = 54; | ||||
|     public static final int FX_6 = 55; | ||||
|     public static final int BS_1 = 60; | ||||
|     public static final int BS_2 = 61; | ||||
|     public static final int BS_3 = 62; | ||||
|     public static final int BS_4 = 63; | ||||
|     public static final int BS_5 = 64; | ||||
|     public static final int BS_6 = 65; | ||||
|     public static final int BS_7 = 66; | ||||
|     public static final int BS_8 = 67; | ||||
|     public static final int BS_9 = 68; | ||||
|     public static final int ZH = 80; | ||||
|  | ||||
| 	public static final Map<Integer, String> inverseMap = new HashMap<>(); | ||||
|     public static final Map<Integer, String> inverseMap = new HashMap<>(); | ||||
|  | ||||
| 	static { | ||||
| 		System.out.println("Loading Blocks..."); | ||||
| 		for (Field field : Block.class.getDeclaredFields()) { | ||||
| 			if (field.getType().isAssignableFrom(Integer.TYPE)) { | ||||
| 				try { | ||||
| 					inverseMap.put((Integer) field.get(null), field.getName()); | ||||
| 				} catch (IllegalAccessException e) { | ||||
| 					e.printStackTrace(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     static { | ||||
|         System.out.println("Loading Blocks..."); | ||||
|         for (Field field : Block.class.getDeclaredFields()) { | ||||
|             if (field.getType().isAssignableFrom(Integer.TYPE)) { | ||||
|                 try { | ||||
|                     inverseMap.put((Integer) field.get(null), field.getName()); | ||||
|                 } catch (IllegalAccessException e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private static final int[][] AVAILABLE = new int[100][0]; | ||||
|     private static final int[][] AVAILABLE = new int[100][0]; | ||||
|  | ||||
| 	static { | ||||
| 		// @formatter:off | ||||
|     static { | ||||
|         // @formatter:off | ||||
| 		// -------------------------------------------- // | ||||
| 		// THANKS DATA PROVIDED BY Lai Juncheng | ||||
| 		// -------------------------------------------- // | ||||
| @@ -120,14 +120,14 @@ public class Block { | ||||
| 		AVAILABLE[BS_9]     = new int[]{103, 203, 302}; | ||||
| 		AVAILABLE[ZH]       = new int[]{199, 299, 399, 499, 599, 699, 799, 899, 999, 1099, 1199, 1299, 1399}; | ||||
| 		// @formatter:on | ||||
| 	} | ||||
|     } | ||||
|  | ||||
| 	public static boolean checkRoom(int block, int room) { | ||||
| 		int floor = room / 100; | ||||
| 		if (floor == 0 || room % 100 == 0) return false; | ||||
| 		if (block < 0 || block >= AVAILABLE.length) return false; | ||||
| 		if (AVAILABLE[block].length < floor) return false; | ||||
| 		return room <= AVAILABLE[block][floor - 1]; | ||||
| 	} | ||||
|     public static boolean checkRoom(int block, int room) { | ||||
|         int floor = room / 100; | ||||
|         if (floor == 0 || room % 100 == 0) return false; | ||||
|         if (block < 0 || block >= AVAILABLE.length) return false; | ||||
|         if (AVAILABLE[block].length < floor) return false; | ||||
|         return room <= AVAILABLE[block][floor - 1]; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -27,49 +27,49 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public enum ISP { | ||||
|  | ||||
| 	TELECOM(1, "^1[3|4|5|7|8][0-9]{9}$"), | ||||
| 	UNICOM(2, "ZSZJLAN[0-9]{10}@16900\\.gd"), | ||||
| 	CHINAMOBILE(3, "^1[3|4|5|7|8][0-9]{9}@139\\.gd$"), | ||||
| 	OTHER(4, ".*"),; | ||||
|     TELECOM(1, "^1[3|4|5|7|8][0-9]{9}$"), | ||||
|     UNICOM(2, "ZSZJLAN[0-9]{10}@16900\\.gd"), | ||||
|     CHINAMOBILE(3, "^1[3|4|5|7|8][0-9]{9}@139\\.gd$"), | ||||
|     OTHER(4, ".*"),; | ||||
|  | ||||
| 	private static final Map<String, ISP> NAME_MAP = new HashMap<>(); | ||||
| 	private static final Map<Integer, ISP> ID_MAP = new HashMap<>(); | ||||
|     private static final Map<String, ISP> NAME_MAP = new HashMap<>(); | ||||
|     private static final Map<Integer, ISP> ID_MAP = new HashMap<>(); | ||||
|  | ||||
| 	static { | ||||
| 		for (ISP type : values()) { | ||||
| 			if (type.name != null) { | ||||
| 				NAME_MAP.put(type.name.toLowerCase(), type); | ||||
| 			} | ||||
| 			if (type.id > 0) { | ||||
| 				ID_MAP.put(type.id, type); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     static { | ||||
|         for (ISP type : values()) { | ||||
|             if (type.name != null) { | ||||
|                 NAME_MAP.put(type.name.toLowerCase(), type); | ||||
|             } | ||||
|             if (type.id > 0) { | ||||
|                 ID_MAP.put(type.id, type); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public final int id; | ||||
| 	public final String name; | ||||
| 	public final String accountRegex; | ||||
|     public final int id; | ||||
|     public final String name; | ||||
|     public final String accountRegex; | ||||
|  | ||||
| 	ISP(int id, String accountRegex) { | ||||
| 		this.id = id; | ||||
| 		this.name = lang("ISP_" + name()); | ||||
| 		this.accountRegex = accountRegex; | ||||
| 	} | ||||
|     ISP(int id, String accountRegex) { | ||||
|         this.id = id; | ||||
|         this.name = lang("ISP_" + name()); | ||||
|         this.accountRegex = accountRegex; | ||||
|     } | ||||
|  | ||||
| 	public static ISP fromName(String name) { | ||||
| 		if (name == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		return NAME_MAP.get(name.toLowerCase()); | ||||
| 	} | ||||
|     public static ISP fromName(String name) { | ||||
|         if (name == null) { | ||||
|             return null; | ||||
|         } | ||||
|         return NAME_MAP.get(name.toLowerCase()); | ||||
|     } | ||||
|  | ||||
| 	public static ISP fromId(int id) { | ||||
| 		return ID_MAP.get(id); | ||||
| 	} | ||||
|     public static ISP fromId(int id) { | ||||
|         return ID_MAP.get(id); | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return name; | ||||
| 	} | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return name; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -26,20 +26,20 @@ import javax.persistence.Converter; | ||||
| @Converter | ||||
| public class ISPConverter implements AttributeConverter<ISP, Integer> { | ||||
|  | ||||
| 	@Override | ||||
| 	public Integer convertToDatabaseColumn(ISP attribute) { | ||||
| 		if (attribute == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		return attribute.id; | ||||
| 	} | ||||
|     @Override | ||||
|     public Integer convertToDatabaseColumn(ISP attribute) { | ||||
|         if (attribute == null) { | ||||
|             return null; | ||||
|         } | ||||
|         return attribute.id; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	public ISP convertToEntityAttribute(Integer dbData) { | ||||
| 		if (dbData == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		return ISP.fromId(dbData); | ||||
| 	} | ||||
|     @Override | ||||
|     public ISP convertToEntityAttribute(Integer dbData) { | ||||
|         if (dbData == null) { | ||||
|             return null; | ||||
|         } | ||||
|         return ISP.fromId(dbData); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -28,33 +28,33 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class Status { | ||||
|  | ||||
| 	public static final int UNCHECKED = 0; | ||||
| 	public static final int ARRANGED = 1; | ||||
| 	public static final int PUTOFF = 2; | ||||
| 	public static final int REPORTED = 4; | ||||
| 	public static final int ISP_HANDLED = 7; | ||||
| 	public static final int SOLVED = 9; | ||||
|     public static final int UNCHECKED = 0; | ||||
|     public static final int ARRANGED = 1; | ||||
|     public static final int PUTOFF = 2; | ||||
|     public static final int REPORTED = 4; | ||||
|     public static final int ISP_HANDLED = 7; | ||||
|     public static final int SOLVED = 9; | ||||
|  | ||||
| 	public static final Map<Integer, String> inverseMap = new HashMap<>(); | ||||
|     public static final Map<Integer, String> inverseMap = new HashMap<>(); | ||||
|  | ||||
| 	static { | ||||
| 		System.out.println("Loading Status..."); | ||||
| 		for (Field field : Status.class.getDeclaredFields()) { | ||||
| 			if (field.getType().isAssignableFrom(Integer.TYPE)) { | ||||
| 				try { | ||||
| 					inverseMap.put((Integer) field.get(null), field.getName()); | ||||
| 				} catch (IllegalAccessException e) { | ||||
| 					e.printStackTrace(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     static { | ||||
|         System.out.println("Loading Status..."); | ||||
|         for (Field field : Status.class.getDeclaredFields()) { | ||||
|             if (field.getType().isAssignableFrom(Integer.TYPE)) { | ||||
|                 try { | ||||
|                     inverseMap.put((Integer) field.get(null), field.getName()); | ||||
|                 } catch (IllegalAccessException e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static String getLocalized(int status) { | ||||
| 		if (inverseMap.containsKey(status)) { | ||||
| 			return lang("STATUS_" + inverseMap.get(status)); | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
|     public static String getLocalized(int status) { | ||||
|         if (inverseMap.containsKey(status)) { | ||||
|             return lang("STATUS_" + inverseMap.get(status)); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,105 +31,105 @@ import javax.persistence.Table; | ||||
| @Table(name = "operators") | ||||
| public class Operator { | ||||
|  | ||||
| 	public static final String PROPERTY_WECHAT = "wechat"; | ||||
|     public static final String PROPERTY_WECHAT = "wechat"; | ||||
|  | ||||
| 	//System Accounts | ||||
| 	public static Operator USER_SELF; | ||||
| 	public static Operator ADMIN; | ||||
|     //System Accounts | ||||
|     public static Operator USER_SELF; | ||||
|     public static Operator ADMIN; | ||||
|  | ||||
| 	@Id | ||||
| 	@Column(name = "id", nullable = false, insertable = false, updatable = false) | ||||
| 	private Integer id; | ||||
| 	@Column(name = "name", nullable = false, insertable = false, updatable = false) | ||||
| 	private String name; | ||||
| 	@Column(name = "access", nullable = false, insertable = false, updatable = false) | ||||
| 	private Integer access; | ||||
| 	@Column(name = "wechat", insertable = false, updatable = false) | ||||
| 	@Expose(serialize = false) | ||||
| 	private String wechat; | ||||
| 	private Integer block; | ||||
| 	private Integer week; | ||||
| 	@Expose(serialize = false) | ||||
| 	private String password; | ||||
|     @Id | ||||
|     @Column(name = "id", nullable = false, insertable = false, updatable = false) | ||||
|     private Integer id; | ||||
|     @Column(name = "name", nullable = false, insertable = false, updatable = false) | ||||
|     private String name; | ||||
|     @Column(name = "access", nullable = false, insertable = false, updatable = false) | ||||
|     private Integer access; | ||||
|     @Column(name = "wechat", insertable = false, updatable = false) | ||||
|     @Expose(serialize = false) | ||||
|     private String wechat; | ||||
|     private Integer block; | ||||
|     private Integer week; | ||||
|     @Expose(serialize = false) | ||||
|     private String password; | ||||
|  | ||||
| 	public Operator(Integer id, String name, Integer access, String wechat, Integer block, Integer week, String password) { | ||||
| 		this.id = id; | ||||
| 		this.name = name; | ||||
| 		this.access = access; | ||||
| 		this.wechat = wechat; | ||||
| 		this.block = block; | ||||
| 		this.week = week; | ||||
| 		this.password = password; | ||||
| 	} | ||||
|     public Operator(Integer id, String name, Integer access, String wechat, Integer block, Integer week, String password) { | ||||
|         this.id = id; | ||||
|         this.name = name; | ||||
|         this.access = access; | ||||
|         this.wechat = wechat; | ||||
|         this.block = block; | ||||
|         this.week = week; | ||||
|         this.password = password; | ||||
|     } | ||||
|  | ||||
| 	public Operator() { | ||||
| 	} | ||||
|     public Operator() { | ||||
|     } | ||||
|  | ||||
| 	public Integer getId() { | ||||
| 		return id; | ||||
| 	} | ||||
|     public Integer getId() { | ||||
|         return id; | ||||
|     } | ||||
|  | ||||
| 	public void setId(Integer id) { | ||||
| 		this.id = id; | ||||
| 	} | ||||
|     public void setId(Integer id) { | ||||
|         this.id = id; | ||||
|     } | ||||
|  | ||||
| 	public String getName() { | ||||
| 		return name; | ||||
| 	} | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
|  | ||||
| 	public void setName(String name) { | ||||
| 		this.name = name; | ||||
| 	} | ||||
|     public void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
|  | ||||
| 	public Integer getAccess() { | ||||
| 		return access; | ||||
| 	} | ||||
|     public Integer getAccess() { | ||||
|         return access; | ||||
|     } | ||||
|  | ||||
| 	public void setAccess(Integer access) { | ||||
| 		this.access = access; | ||||
| 	} | ||||
|     public void setAccess(Integer access) { | ||||
|         this.access = access; | ||||
|     } | ||||
|  | ||||
| 	public String getWechat() { | ||||
| 		return wechat; | ||||
| 	} | ||||
|     public String getWechat() { | ||||
|         return wechat; | ||||
|     } | ||||
|  | ||||
| 	public void setWechat(String wechat) { | ||||
| 		this.wechat = wechat; | ||||
| 	} | ||||
|     public void setWechat(String wechat) { | ||||
|         this.wechat = wechat; | ||||
|     } | ||||
|  | ||||
| 	public Integer getBlock() { | ||||
| 		return block; | ||||
| 	} | ||||
|     public Integer getBlock() { | ||||
|         return block; | ||||
|     } | ||||
|  | ||||
| 	public void setBlock(Integer block) { | ||||
| 		this.block = block; | ||||
| 	} | ||||
|     public void setBlock(Integer block) { | ||||
|         this.block = block; | ||||
|     } | ||||
|  | ||||
| 	public Integer getWeek() { | ||||
| 		return week; | ||||
| 	} | ||||
|     public Integer getWeek() { | ||||
|         return week; | ||||
|     } | ||||
|  | ||||
| 	public void setWeek(Integer week) { | ||||
| 		this.week = week; | ||||
| 	} | ||||
|     public void setWeek(Integer week) { | ||||
|         this.week = week; | ||||
|     } | ||||
|  | ||||
| 	public String getPassword() { | ||||
| 		return password; | ||||
| 	} | ||||
|     public String getPassword() { | ||||
|         return password; | ||||
|     } | ||||
|  | ||||
| 	public void setPassword(String password) { | ||||
| 		this.password = password; | ||||
| 	} | ||||
|     public void setPassword(String password) { | ||||
|         this.password = password; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return "Operator{" + | ||||
| 				"id=" + id + | ||||
| 				", name='" + name + '\'' + | ||||
| 				", access=" + access + | ||||
| 				", wechat='" + wechat + '\'' + | ||||
| 				", block=" + block + | ||||
| 				", week=" + week + | ||||
| 				'}'; | ||||
| 	} | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "Operator{" + | ||||
|                 "id=" + id + | ||||
|                 ", name='" + name + '\'' + | ||||
|                 ", access=" + access + | ||||
|                 ", wechat='" + wechat + '\'' + | ||||
|                 ", block=" + block + | ||||
|                 ", week=" + week + | ||||
|                 '}'; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -47,56 +47,56 @@ import java.util.concurrent.TimeUnit; | ||||
|  */ | ||||
| public class MapSessionRepository { | ||||
|  | ||||
| 	private final LoadingCache<String, MapSession> sessions; | ||||
|     private final LoadingCache<String, MapSession> sessions; | ||||
|  | ||||
| 	public MapSessionRepository() { | ||||
| 		this(CacheBuilder.newBuilder() | ||||
| 				.concurrencyLevel(4) | ||||
| 				.maximumSize(65535) | ||||
| 				.expireAfterAccess(Settings.I.User_Session_Max_Inactive, TimeUnit.SECONDS) | ||||
| 				.build(new CacheLoader<String, MapSession>() { | ||||
| 					       @Override | ||||
| 					       public MapSession load(@Nonnull String key) throws Exception { | ||||
| 						       return new MapSession(key); | ||||
| 					       } | ||||
| 				       } | ||||
| 				) | ||||
| 		); | ||||
| 	} | ||||
|     public MapSessionRepository() { | ||||
|         this(CacheBuilder.newBuilder() | ||||
|                 .concurrencyLevel(4) | ||||
|                 .maximumSize(65535) | ||||
|                 .expireAfterAccess(Settings.I.User_Session_Max_Inactive, TimeUnit.SECONDS) | ||||
|                 .build(new CacheLoader<String, MapSession>() { | ||||
|                            @Override | ||||
|                            public MapSession load(@Nonnull String key) throws Exception { | ||||
|                                return new MapSession(key); | ||||
|                            } | ||||
|                        } | ||||
|                 ) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| 	public MapSessionRepository(LoadingCache<String, MapSession> sessions) { | ||||
| 		Validate.notNull(sessions); | ||||
| 		this.sessions = sessions; | ||||
| 	} | ||||
|     public MapSessionRepository(LoadingCache<String, MapSession> sessions) { | ||||
|         Validate.notNull(sessions); | ||||
|         this.sessions = sessions; | ||||
|     } | ||||
|  | ||||
| 	public void save(MapSession session) { | ||||
| 		sessions.put(session.getId(), session); | ||||
| 	} | ||||
|     public void save(MapSession session) { | ||||
|         sessions.put(session.getId(), session); | ||||
|     } | ||||
|  | ||||
| 	public MapSession getSession(String id) { | ||||
| 		MapSession saved = sessions.getIfPresent(id); | ||||
| 		if (saved == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		if (saved.isInvalidated()) { | ||||
| 			delete(saved.getId()); | ||||
| 			return null; | ||||
| 		} | ||||
| 		return saved; | ||||
| 	} | ||||
|     public MapSession getSession(String id) { | ||||
|         MapSession saved = sessions.getIfPresent(id); | ||||
|         if (saved == null) { | ||||
|             return null; | ||||
|         } | ||||
|         if (saved.isInvalidated()) { | ||||
|             delete(saved.getId()); | ||||
|             return null; | ||||
|         } | ||||
|         return saved; | ||||
|     } | ||||
|  | ||||
| 	public void delete(String id) { | ||||
| 		sessions.invalidate(id); | ||||
| 	} | ||||
|     public void delete(String id) { | ||||
|         sessions.invalidate(id); | ||||
|     } | ||||
|  | ||||
| 	public MapSession createSession() { | ||||
| 		MapSession session = new MapSession(); | ||||
| 		save(session); | ||||
| 		return session; | ||||
| 	} | ||||
|     public MapSession createSession() { | ||||
|         MapSession session = new MapSession(); | ||||
|         save(session); | ||||
|         return session; | ||||
|     } | ||||
|  | ||||
| 	public Map<String, MapSession> asMap() { | ||||
| 		return sessions.asMap(); | ||||
| 	} | ||||
|     public Map<String, MapSession> asMap() { | ||||
|         return sessions.asMap(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -25,22 +25,22 @@ import java.util.Collection; | ||||
|  */ | ||||
| public class WechatSession { | ||||
|  | ||||
| 	private static MapSessionRepository repository; | ||||
|     private static MapSessionRepository repository; | ||||
|  | ||||
| 	static { | ||||
| 		repository = new MapSessionRepository(); | ||||
| 	} | ||||
|     static { | ||||
|         repository = new MapSessionRepository(); | ||||
|     } | ||||
|  | ||||
| 	public static WxSession get(String id) { | ||||
| 		return repository.getSession(id); | ||||
| 	} | ||||
|     public static WxSession get(String id) { | ||||
|         return repository.getSession(id); | ||||
|     } | ||||
|  | ||||
| 	public static WxSession create() { | ||||
| 		return repository.createSession(); | ||||
| 	} | ||||
|     public static WxSession create() { | ||||
|         return repository.createSession(); | ||||
|     } | ||||
|  | ||||
| 	public static Collection<? extends WxSession> list() { | ||||
| 		return repository.asMap().values(); | ||||
| 	} | ||||
|     public static Collection<? extends WxSession> list() { | ||||
|         return repository.asMap().values(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -24,16 +24,16 @@ import java.util.Set; | ||||
|  */ | ||||
| public interface WxSession { | ||||
|  | ||||
| 	String getId(); | ||||
|     String getId(); | ||||
|  | ||||
| 	<T> T getAttribute(String name); | ||||
|     <T> T getAttribute(String name); | ||||
|  | ||||
| 	Set<String> getAttributeNames(); | ||||
|     Set<String> getAttributeNames(); | ||||
|  | ||||
| 	void setAttribute(String name, Object value); | ||||
|     void setAttribute(String name, Object value); | ||||
|  | ||||
| 	void removeAttribute(String name); | ||||
|     void removeAttribute(String name); | ||||
|  | ||||
| 	void invalidate(); | ||||
|     void invalidate(); | ||||
|  | ||||
| } | ||||
| @@ -46,111 +46,111 @@ import java.util.Date; | ||||
|  */ | ||||
| public class SQLCore { | ||||
|  | ||||
| 	public static InitialContext ic; | ||||
| 	public static DataSource ds; | ||||
| 	public static SessionFactory sf; | ||||
| 	public static ServiceRegistry sr; | ||||
| 	public static Gson gson = new GsonBuilder() | ||||
| 			.addSerializationExclusionStrategy(new ExclusionStrategy() { | ||||
| 				@Override | ||||
| 				public boolean shouldSkipField(FieldAttributes fieldAttributes) { | ||||
| 					final Expose expose = fieldAttributes.getAnnotation(Expose.class); | ||||
| 					return expose != null && !expose.serialize(); | ||||
| 				} | ||||
|     public static InitialContext ic; | ||||
|     public static DataSource ds; | ||||
|     public static SessionFactory sf; | ||||
|     public static ServiceRegistry sr; | ||||
|     public static Gson gson = new GsonBuilder() | ||||
|             .addSerializationExclusionStrategy(new ExclusionStrategy() { | ||||
|                 @Override | ||||
|                 public boolean shouldSkipField(FieldAttributes fieldAttributes) { | ||||
|                     final Expose expose = fieldAttributes.getAnnotation(Expose.class); | ||||
|                     return expose != null && !expose.serialize(); | ||||
|                 } | ||||
|  | ||||
| 				@Override | ||||
| 				public boolean shouldSkipClass(Class<?> aClass) { | ||||
| 					return false; | ||||
| 				} | ||||
| 			}) | ||||
| 			.addDeserializationExclusionStrategy(new ExclusionStrategy() { | ||||
| 				@Override | ||||
| 				public boolean shouldSkipField(FieldAttributes fieldAttributes) { | ||||
| 					final Expose expose = fieldAttributes.getAnnotation(Expose.class); | ||||
| 					return expose != null && !expose.deserialize(); | ||||
| 				} | ||||
|                 @Override | ||||
|                 public boolean shouldSkipClass(Class<?> aClass) { | ||||
|                     return false; | ||||
|                 } | ||||
|             }) | ||||
|             .addDeserializationExclusionStrategy(new ExclusionStrategy() { | ||||
|                 @Override | ||||
|                 public boolean shouldSkipField(FieldAttributes fieldAttributes) { | ||||
|                     final Expose expose = fieldAttributes.getAnnotation(Expose.class); | ||||
|                     return expose != null && !expose.deserialize(); | ||||
|                 } | ||||
|  | ||||
| 				@Override | ||||
| 				public boolean shouldSkipClass(Class<?> aClass) { | ||||
| 					return false; | ||||
| 				} | ||||
| 			}) | ||||
| 			.registerTypeAdapter(Date.class, (JsonDeserializer<Date>) (json, typeOfT, context) -> new Date(json.getAsJsonPrimitive().getAsLong())) | ||||
| 			.registerTypeAdapter(Date.class, (JsonSerializer<Date>) (src, typeOfSrc, context) -> new JsonPrimitive(src.getTime())) | ||||
| 			.registerTypeAdapter(ISP.class, (JsonDeserializer<ISP>) (json, typeOfT, context) -> ISP.fromId(json.getAsJsonPrimitive().getAsInt())) | ||||
| 			.registerTypeAdapter(ISP.class, (JsonSerializer<ISP>) (src, typeOfSrc, context) -> new JsonPrimitive(src.id)) | ||||
| 			.registerTypeAdapter(Command.class, (JsonDeserializer<Command>) (json, typeOfT, context) -> Command.fromId(json.getAsJsonPrimitive().getAsInt())) | ||||
| 			.registerTypeAdapter(Command.class, (JsonSerializer<Command>) (src, typeOfSrc, context) -> new JsonPrimitive(src.id)) | ||||
| 			.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY) | ||||
| 			.create(); | ||||
|                 @Override | ||||
|                 public boolean shouldSkipClass(Class<?> aClass) { | ||||
|                     return false; | ||||
|                 } | ||||
|             }) | ||||
|             .registerTypeAdapter(Date.class, (JsonDeserializer<Date>) (json, typeOfT, context) -> new Date(json.getAsJsonPrimitive().getAsLong())) | ||||
|             .registerTypeAdapter(Date.class, (JsonSerializer<Date>) (src, typeOfSrc, context) -> new JsonPrimitive(src.getTime())) | ||||
|             .registerTypeAdapter(ISP.class, (JsonDeserializer<ISP>) (json, typeOfT, context) -> ISP.fromId(json.getAsJsonPrimitive().getAsInt())) | ||||
|             .registerTypeAdapter(ISP.class, (JsonSerializer<ISP>) (src, typeOfSrc, context) -> new JsonPrimitive(src.id)) | ||||
|             .registerTypeAdapter(Command.class, (JsonDeserializer<Command>) (json, typeOfT, context) -> Command.fromId(json.getAsJsonPrimitive().getAsInt())) | ||||
|             .registerTypeAdapter(Command.class, (JsonSerializer<Command>) (src, typeOfSrc, context) -> new JsonPrimitive(src.id)) | ||||
|             .registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY) | ||||
|             .create(); | ||||
|  | ||||
| 	static { | ||||
| 		try { | ||||
| 			ic = new InitialContext(); | ||||
| 			ds = (DataSource) ic.lookup("java:comp/env/jdbc/netsupport"); | ||||
| 			ds.setLoginTimeout(3); | ||||
|     static { | ||||
|         try { | ||||
|             ic = new InitialContext(); | ||||
|             ds = (DataSource) ic.lookup("java:comp/env/jdbc/netsupport"); | ||||
|             ds.setLoginTimeout(3); | ||||
|  | ||||
| 			sr = new StandardServiceRegistryBuilder().configure().build(); | ||||
| 			sf = new MetadataSources(sr).buildMetadata().buildSessionFactory(); | ||||
|             sr = new StandardServiceRegistryBuilder().configure().build(); | ||||
|             sf = new MetadataSources(sr).buildMetadata().buildSessionFactory(); | ||||
|  | ||||
| 			TableUser.init(); | ||||
| 			TableOperator.init(); | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
|             TableUser.init(); | ||||
|             TableOperator.init(); | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static void destroy() { | ||||
| 		try { | ||||
| 			SQLCore.sf.close(); | ||||
| 			((ComboPooledDataSource) SQLCore.ds).close(); | ||||
| 			SQLCore.ic.close(); | ||||
| 		} catch (NamingException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
|     public static void destroy() { | ||||
|         try { | ||||
|             SQLCore.sf.close(); | ||||
|             ((ComboPooledDataSource) SQLCore.ds).close(); | ||||
|             SQLCore.ic.close(); | ||||
|         } catch (NamingException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static AuditReader getAuditReader(Session session) { | ||||
| 		return AuditReaderFactory.get(session); | ||||
| 	} | ||||
|     public static AuditReader getAuditReader(Session session) { | ||||
|         return AuditReaderFactory.get(session); | ||||
|     } | ||||
|  | ||||
| 	public static class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> { | ||||
|     public static class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> { | ||||
|  | ||||
| 		public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { | ||||
| 			@Override | ||||
| 			@SuppressWarnings("unchecked") | ||||
| 			public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { | ||||
| 				return (HibernateProxy.class.isAssignableFrom(type.getRawType()) ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson) : null); | ||||
| 			} | ||||
| 		}; | ||||
| 		private final Gson context; | ||||
|         public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { | ||||
|             @Override | ||||
|             @SuppressWarnings("unchecked") | ||||
|             public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { | ||||
|                 return (HibernateProxy.class.isAssignableFrom(type.getRawType()) ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson) : null); | ||||
|             } | ||||
|         }; | ||||
|         private final Gson context; | ||||
|  | ||||
| 		private HibernateProxyTypeAdapter(Gson context) { | ||||
| 			this.context = context; | ||||
| 		} | ||||
|         private HibernateProxyTypeAdapter(Gson context) { | ||||
|             this.context = context; | ||||
|         } | ||||
|  | ||||
| 		@Override | ||||
| 		public HibernateProxy read(JsonReader in) throws IOException { | ||||
| 			throw new UnsupportedOperationException("Not supported"); | ||||
| 		} | ||||
|         @Override | ||||
|         public HibernateProxy read(JsonReader in) throws IOException { | ||||
|             throw new UnsupportedOperationException("Not supported"); | ||||
|         } | ||||
|  | ||||
| 		@SuppressWarnings({"rawtypes", "unchecked"}) | ||||
| 		@Override | ||||
| 		public void write(JsonWriter out, HibernateProxy value) throws IOException { | ||||
| 			if (value == null) { | ||||
| 				out.nullValue(); | ||||
| 				return; | ||||
| 			} | ||||
| 			// Retrieve the original (not proxy) class | ||||
| 			Class<?> baseType = Hibernate.getClass(value); | ||||
| 			// Get the TypeAdapter of the original class, to delegate the serialization | ||||
| 			TypeAdapter delegate = context.getAdapter(TypeToken.get(baseType)); | ||||
| 			// Get a filled instance of the original class | ||||
| 			Object unproxiedValue = ((HibernateProxy) value).getHibernateLazyInitializer() | ||||
| 					.getImplementation(); | ||||
| 			// Serialize the value | ||||
| 			delegate.write(out, unproxiedValue); | ||||
| 		} | ||||
| 	} | ||||
|         @SuppressWarnings({"rawtypes", "unchecked"}) | ||||
|         @Override | ||||
|         public void write(JsonWriter out, HibernateProxy value) throws IOException { | ||||
|             if (value == null) { | ||||
|                 out.nullValue(); | ||||
|                 return; | ||||
|             } | ||||
|             // Retrieve the original (not proxy) class | ||||
|             Class<?> baseType = Hibernate.getClass(value); | ||||
|             // Get the TypeAdapter of the original class, to delegate the serialization | ||||
|             TypeAdapter delegate = context.getAdapter(TypeToken.get(baseType)); | ||||
|             // Get a filled instance of the original class | ||||
|             Object unproxiedValue = ((HibernateProxy) value).getHibernateLazyInitializer() | ||||
|                     .getImplementation(); | ||||
|             // Serialize the value | ||||
|             delegate.write(out, unproxiedValue); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -26,29 +26,29 @@ import java.sql.*; | ||||
|  */ | ||||
| public class TableConfig extends SQLCore { | ||||
|  | ||||
| 	public static final String KEY_SYS = "sys"; | ||||
|     public static final String KEY_SYS = "sys"; | ||||
|  | ||||
| 	public static Settings getSettings() { | ||||
| 		try (Connection conn = ds.getConnection()) { | ||||
| 			Statement st = conn.createStatement(); | ||||
| 			ResultSet rs = st.executeQuery("SELECT * FROM settings WHERE type='" + KEY_SYS + "'"); | ||||
| 			if (rs.next()) { | ||||
| 				return gson.fromJson(rs.getString("data"), Settings.class); | ||||
| 			} | ||||
| 		} catch (SQLException e) { | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
|     public static Settings getSettings() { | ||||
|         try (Connection conn = ds.getConnection()) { | ||||
|             Statement st = conn.createStatement(); | ||||
|             ResultSet rs = st.executeQuery("SELECT * FROM settings WHERE type='" + KEY_SYS + "'"); | ||||
|             if (rs.next()) { | ||||
|                 return gson.fromJson(rs.getString("data"), Settings.class); | ||||
|             } | ||||
|         } catch (SQLException e) { | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| 	public static int saveSettings(Settings obj) { | ||||
| 		try (Connection conn = ds.getConnection()) { | ||||
| 			PreparedStatement ps = conn.prepareStatement("UPDATE settings SET data=? WHERE type=?"); | ||||
| 			ps.setString(1, gson.toJson(obj)); | ||||
| 			ps.setString(2, KEY_SYS); | ||||
| 			return ps.executeUpdate(); | ||||
| 		} catch (SQLException e) { | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
|     public static int saveSettings(Settings obj) { | ||||
|         try (Connection conn = ds.getConnection()) { | ||||
|             PreparedStatement ps = conn.prepareStatement("UPDATE settings SET data=? WHERE type=?"); | ||||
|             ps.setString(1, gson.toJson(obj)); | ||||
|             ps.setString(2, KEY_SYS); | ||||
|             return ps.executeUpdate(); | ||||
|         } catch (SQLException e) { | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -27,35 +27,35 @@ import org.hibernate.criterion.Restrictions; | ||||
|  */ | ||||
| public class TableOperator extends SQLCore { | ||||
|  | ||||
| 	public static boolean has(String wechat) { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			return (long) s.createCriteria(Operator.class) | ||||
| 					.add(Restrictions.eq(Operator.PROPERTY_WECHAT, wechat)) | ||||
| 					.setProjection(Projections.rowCount()) | ||||
| 					.uniqueResult() > 0; | ||||
| 		} | ||||
| 	} | ||||
|     public static boolean has(String wechat) { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             return (long) s.createCriteria(Operator.class) | ||||
|                     .add(Restrictions.eq(Operator.PROPERTY_WECHAT, wechat)) | ||||
|                     .setProjection(Projections.rowCount()) | ||||
|                     .uniqueResult() > 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| 	public static Operator get(String wechat) { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			return (Operator) s.createCriteria(Operator.class) | ||||
| 					.add(Restrictions.eq(Operator.PROPERTY_WECHAT, wechat)) | ||||
| 					.uniqueResult(); | ||||
| 		} | ||||
| 	} | ||||
|     public static Operator get(String wechat) { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             return (Operator) s.createCriteria(Operator.class) | ||||
|                     .add(Restrictions.eq(Operator.PROPERTY_WECHAT, wechat)) | ||||
|                     .uniqueResult(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static Operator get(int id) { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			return s.get(Operator.class, id); | ||||
| 		} | ||||
| 	} | ||||
|     public static Operator get(int id) { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             return s.get(Operator.class, id); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	protected static void init() { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			Operator.USER_SELF = s.get(Operator.class, -1); | ||||
| 			Operator.ADMIN = s.get(Operator.class, 0); | ||||
| 		} | ||||
| 	} | ||||
|     protected static void init() { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             Operator.USER_SELF = s.get(Operator.class, -1); | ||||
|             Operator.ADMIN = s.get(Operator.class, 0); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -34,83 +34,83 @@ import java.util.List; | ||||
|  */ | ||||
| public class TableTicket extends SQLCore { | ||||
|  | ||||
| 	public static final String COLUMN_ID = "id"; | ||||
| 	public static final String COLUMN_SID = "sid"; | ||||
| 	public static final String COLUMN_DESC = "description"; | ||||
| 	public static final String COLUMN_SUBMIT_TIME = "submittime"; | ||||
| 	public static final String COLUMN_REMARK = "remark"; | ||||
| 	public static final String COLUMN_UPDATE_TIME = "updatetime"; | ||||
| 	public static final String COLUMN_OPSID = "opsid"; | ||||
| 	public static final String COLUMN_STATUS = "status"; | ||||
|     public static final String COLUMN_ID = "id"; | ||||
|     public static final String COLUMN_SID = "sid"; | ||||
|     public static final String COLUMN_DESC = "description"; | ||||
|     public static final String COLUMN_SUBMIT_TIME = "submittime"; | ||||
|     public static final String COLUMN_REMARK = "remark"; | ||||
|     public static final String COLUMN_UPDATE_TIME = "updatetime"; | ||||
|     public static final String COLUMN_OPSID = "opsid"; | ||||
|     public static final String COLUMN_STATUS = "status"; | ||||
|  | ||||
|  | ||||
| 	public static Ticket latestOpen(User u) { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			return (Ticket) s.createCriteria(Ticket.class) | ||||
| 					.addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)) | ||||
| 					.add(Restrictions.eq(Ticket.PROPERTY_USER, u)) | ||||
| 					.add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED)) | ||||
| 					.setMaxResults(1) | ||||
| 					.uniqueResult(); | ||||
| 		} | ||||
| 	} | ||||
|     public static Ticket latestOpen(User u) { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             return (Ticket) s.createCriteria(Ticket.class) | ||||
|                     .addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)) | ||||
|                     .add(Restrictions.eq(Ticket.PROPERTY_USER, u)) | ||||
|                     .add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED)) | ||||
|                     .setMaxResults(1) | ||||
|                     .uniqueResult(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static Ticket latest(User u) { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			return (Ticket) s.createCriteria(Ticket.class) | ||||
| 					.addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)) | ||||
| 					.add(Restrictions.eq(Ticket.PROPERTY_USER, u)) | ||||
| 					.setMaxResults(1) | ||||
| 					.uniqueResult(); | ||||
| 		} | ||||
| 	} | ||||
|     public static Ticket latest(User u) { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             return (Ticket) s.createCriteria(Ticket.class) | ||||
|                     .addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)) | ||||
|                     .add(Restrictions.eq(Ticket.PROPERTY_USER, u)) | ||||
|                     .setMaxResults(1) | ||||
|                     .uniqueResult(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static boolean hasOpen(User u) { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			return (long) s.createCriteria(Ticket.class) | ||||
| 					.add(Restrictions.eq(Ticket.PROPERTY_USER, u)) | ||||
| 					.add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED)) | ||||
| 					.setProjection(Projections.rowCount()) | ||||
| 					.uniqueResult() > 0; | ||||
| 		} | ||||
| 	} | ||||
|     public static boolean hasOpen(User u) { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             return (long) s.createCriteria(Ticket.class) | ||||
|                     .add(Restrictions.eq(Ticket.PROPERTY_USER, u)) | ||||
|                     .add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED)) | ||||
|                     .setProjection(Projections.rowCount()) | ||||
|                     .uniqueResult() > 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	public static List<Ticket> unsolvedByBlock(int b) { | ||||
| 		if (b == 0) return unsolved(); | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			return s.createCriteria(Ticket.class) | ||||
| 					.addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)) | ||||
| 					.add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED)) | ||||
| 					.createCriteria(Ticket.PROPERTY_USER) | ||||
| 					.add(Restrictions.between(User.PROPERTY_BLOCK, b * 10, (b + 1) * 10 - 1)) | ||||
| 					.list(); | ||||
| 		} | ||||
| 	} | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static List<Ticket> unsolvedByBlock(int b) { | ||||
|         if (b == 0) return unsolved(); | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             return s.createCriteria(Ticket.class) | ||||
|                     .addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)) | ||||
|                     .add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED)) | ||||
|                     .createCriteria(Ticket.PROPERTY_USER) | ||||
|                     .add(Restrictions.between(User.PROPERTY_BLOCK, b * 10, (b + 1) * 10 - 1)) | ||||
|                     .list(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	public static List<Ticket> unsolved() { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			return s.createCriteria(Ticket.class) | ||||
| 					.createAlias(Ticket.PROPERTY_USER, "u") | ||||
| 					.addOrder(Order.asc("u." + User.PROPERTY_BLOCK)) | ||||
| 					.addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)) | ||||
| 					.add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED)) | ||||
| 					.list(); | ||||
| 		} | ||||
| 	} | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static List<Ticket> unsolved() { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             return s.createCriteria(Ticket.class) | ||||
|                     .createAlias(Ticket.PROPERTY_USER, "u") | ||||
|                     .addOrder(Order.asc("u." + User.PROPERTY_BLOCK)) | ||||
|                     .addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME)) | ||||
|                     .add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED)) | ||||
|                     .list(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	public static List<Object[]> track(int tid) { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			AuditReader reader = getAuditReader(s); | ||||
| 			return reader.createQuery() | ||||
| 					.forRevisionsOfEntity(Ticket.class, false, true) | ||||
| 					.addOrder(AuditEntity.revisionNumber().desc()) | ||||
| 					.add(AuditEntity.id().eq(tid)) | ||||
| 					.getResultList() | ||||
| 					; | ||||
| 		} | ||||
| 	} | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static List<Object[]> track(int tid) { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             AuditReader reader = getAuditReader(s); | ||||
|             return reader.createQuery() | ||||
|                     .forRevisionsOfEntity(Ticket.class, false, true) | ||||
|                     .addOrder(AuditEntity.revisionNumber().desc()) | ||||
|                     .add(AuditEntity.id().eq(tid)) | ||||
|                     .getResultList() | ||||
|                     ; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -34,79 +34,79 @@ import java.util.concurrent.TimeUnit; | ||||
| @SuppressWarnings("Duplicates") | ||||
| public class TableUser extends SQLCore { | ||||
|  | ||||
| 	public static final String COLUMN_ID = "id"; | ||||
| 	public static final String COLUMN_NAME = "name"; | ||||
| 	public static final String COLUMN_ISP = "isp"; | ||||
| 	public static final String COLUMN_NET_ACCOUNT = "netaccount"; | ||||
| 	public static final String COLUMN_WECHAT = "wechat"; | ||||
| 	public static final String COLUMN_BLOCK = "block"; | ||||
| 	public static final String COLUMN_ROOM = "room"; | ||||
| 	public static final String COLUMN_PHONE = "phone"; | ||||
|     public static final String COLUMN_ID = "id"; | ||||
|     public static final String COLUMN_NAME = "name"; | ||||
|     public static final String COLUMN_ISP = "isp"; | ||||
|     public static final String COLUMN_NET_ACCOUNT = "netaccount"; | ||||
|     public static final String COLUMN_WECHAT = "wechat"; | ||||
|     public static final String COLUMN_BLOCK = "block"; | ||||
|     public static final String COLUMN_ROOM = "room"; | ||||
|     public static final String COLUMN_PHONE = "phone"; | ||||
|  | ||||
| 	public static User getById(long id) { | ||||
| 		try (Session s = sf.openSession()) { | ||||
| 			return s.get(User.class, id); | ||||
| 		} | ||||
| 	} | ||||
|     public static User getById(long id) { | ||||
|         try (Session s = sf.openSession()) { | ||||
|             return s.get(User.class, id); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static User getByName(String name) { | ||||
| 		try (Session s = sf.openSession()) { | ||||
| 			return (User) s.createCriteria(User.class).add(Restrictions.eq(User.PROPERTY_NAME, name)).uniqueResult(); | ||||
| 		} | ||||
| 	} | ||||
|     public static User getByName(String name) { | ||||
|         try (Session s = sf.openSession()) { | ||||
|             return (User) s.createCriteria(User.class).add(Restrictions.eq(User.PROPERTY_NAME, name)).uniqueResult(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static User getByWechat(String wechat) { | ||||
| 		try { | ||||
| 			User u = cache.get(wechat); | ||||
| 			return u == NULL_USER ? null : u; | ||||
| 		} catch (ExecutionException e) { | ||||
| 			e.printStackTrace(); | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
|     public static User getByWechat(String wechat) { | ||||
|         try { | ||||
|             User u = cache.get(wechat); | ||||
|             return u == NULL_USER ? null : u; | ||||
|         } catch (ExecutionException e) { | ||||
|             e.printStackTrace(); | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static int update(User user) { | ||||
| 		try (Session s = sf.openSession()) { | ||||
| 			s.beginTransaction(); | ||||
| 			s.update(user); | ||||
| 			s.getTransaction().commit(); | ||||
| 			cache.put(user.getWechatId(), user); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
|     public static int update(User user) { | ||||
|         try (Session s = sf.openSession()) { | ||||
|             s.beginTransaction(); | ||||
|             s.update(user); | ||||
|             s.getTransaction().commit(); | ||||
|             cache.put(user.getWechatId(), user); | ||||
|             return 1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	protected static void init() { | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			User.OFFICIAL_CHINA_UNICOM_XH = s.get(User.class, 100104L); | ||||
| 			User.OFFICIAL_CHINA_MOBILE_XH = s.get(User.class, 100864L); | ||||
| 			User.OFFICIAL_CHINA_MOBILE_FX = s.get(User.class, 100865L); | ||||
| 		} | ||||
| 	} | ||||
|     protected static void init() { | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             User.OFFICIAL_CHINA_UNICOM_XH = s.get(User.class, 100104L); | ||||
|             User.OFFICIAL_CHINA_MOBILE_XH = s.get(User.class, 100864L); | ||||
|             User.OFFICIAL_CHINA_MOBILE_FX = s.get(User.class, 100865L); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private static LoadingCache<String, User> cache = CacheBuilder.newBuilder() | ||||
| 			.concurrencyLevel(4) | ||||
| 			.maximumSize(4096) | ||||
| 			.expireAfterAccess(Settings.I.User_Wechat_Cache_Expire_Time, TimeUnit.SECONDS) | ||||
| 			.build(new ValueLoader()); | ||||
|     private static LoadingCache<String, User> cache = CacheBuilder.newBuilder() | ||||
|             .concurrencyLevel(4) | ||||
|             .maximumSize(4096) | ||||
|             .expireAfterAccess(Settings.I.User_Wechat_Cache_Expire_Time, TimeUnit.SECONDS) | ||||
|             .build(new ValueLoader()); | ||||
|  | ||||
| 	private static class ValueLoader extends CacheLoader<String, User> { | ||||
| 		@Override | ||||
| 		public User load(String key) throws Exception { | ||||
| 			User u = TableUser.getByWechat0(key); | ||||
| 			return u == null ? NULL_USER : u; | ||||
| 		} | ||||
| 	} | ||||
|     private static class ValueLoader extends CacheLoader<String, User> { | ||||
|         @Override | ||||
|         public User load(String key) throws Exception { | ||||
|             User u = TableUser.getByWechat0(key); | ||||
|             return u == null ? NULL_USER : u; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private static final User NULL_USER = new User(); | ||||
|     private static final User NULL_USER = new User(); | ||||
|  | ||||
| 	public static void flushCache() { | ||||
| 		cache.invalidateAll(); | ||||
| 	} | ||||
|     public static void flushCache() { | ||||
|         cache.invalidateAll(); | ||||
|     } | ||||
|  | ||||
| 	private static User getByWechat0(String wechat) { | ||||
| 		try (Session s = sf.openSession()) { | ||||
| 			return (User) s.createCriteria(User.class).add(Restrictions.eq(User.PROPERTY_WECHAT, wechat)).uniqueResult(); | ||||
| 		} | ||||
| 	} | ||||
|     private static User getByWechat0(String wechat) { | ||||
|         try (Session s = sf.openSession()) { | ||||
|             return (User) s.createCriteria(User.class).add(Restrictions.eq(User.PROPERTY_WECHAT, wechat)).uniqueResult(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -25,76 +25,76 @@ import love.sola.netsupport.enums.ISP; | ||||
|  */ | ||||
| public class Checker { | ||||
|  | ||||
| 	public static final String STUDENT_ID_REGEX = "^(2014|2015|2016|2017)[0-9]{9}$"; | ||||
| 	public static final String PHONE_NUMBER_REGEX = "^1[34578][0-9]{9}$"; | ||||
|     public static final String STUDENT_ID_REGEX = "^(2014|2015|2016|2017)[0-9]{9}$"; | ||||
|     public static final String PHONE_NUMBER_REGEX = "^1[34578][0-9]{9}$"; | ||||
|  | ||||
| 	public static boolean hasNull(Object... v) { | ||||
| 		for (Object o : v) if (o == null) return true; | ||||
| 		return false; | ||||
| 	} | ||||
|     public static boolean hasNull(Object... v) { | ||||
|         for (Object o : v) if (o == null) return true; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| 	public static long checkStudentId(String studentId) { | ||||
| 		if (studentId == null) return -1; | ||||
| 		if (studentId.matches(STUDENT_ID_REGEX)) { | ||||
| 			try { | ||||
| 				return Long.parseLong(studentId); | ||||
| 			} catch (NumberFormatException ignored) { | ||||
| 			} | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
|     public static long checkStudentId(String studentId) { | ||||
|         if (studentId == null) return -1; | ||||
|         if (studentId.matches(STUDENT_ID_REGEX)) { | ||||
|             try { | ||||
|                 return Long.parseLong(studentId); | ||||
|             } catch (NumberFormatException ignored) { | ||||
|             } | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
| 	public static long checkPhoneNumber(String phone) { | ||||
| 		if (phone == null) return -1; | ||||
| 		if (!phone.matches(PHONE_NUMBER_REGEX)) return -1; | ||||
| 		try { | ||||
| 			return Long.parseLong(phone); | ||||
| 		} catch (NumberFormatException ignored) { | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
|     public static long checkPhoneNumber(String phone) { | ||||
|         if (phone == null) return -1; | ||||
|         if (!phone.matches(PHONE_NUMBER_REGEX)) return -1; | ||||
|         try { | ||||
|             return Long.parseLong(phone); | ||||
|         } catch (NumberFormatException ignored) { | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
| 	public static ISP checkISP(String isp) { | ||||
| 		if (isp == null) return null; | ||||
| 		try { | ||||
| 			return ISP.fromId(Integer.parseInt(isp)); | ||||
| 		} catch (NumberFormatException ignored) { | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
|     public static ISP checkISP(String isp) { | ||||
|         if (isp == null) return null; | ||||
|         try { | ||||
|             return ISP.fromId(Integer.parseInt(isp)); | ||||
|         } catch (NumberFormatException ignored) { | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| 	public static String checkNetAccount(String account, ISP isp) { | ||||
| 		if (isp == null) return null; | ||||
| 		if (account == null) return null; | ||||
| 		if (!account.matches(isp.accountRegex)) return null; | ||||
| 		return account; | ||||
| 	} | ||||
|     public static String checkNetAccount(String account, ISP isp) { | ||||
|         if (isp == null) return null; | ||||
|         if (account == null) return null; | ||||
|         if (!account.matches(isp.accountRegex)) return null; | ||||
|         return account; | ||||
|     } | ||||
|  | ||||
| 	public static int checkBlock(String block) { | ||||
| 		if (block == null) return -1; | ||||
| 		try { | ||||
| 			int b = Integer.parseInt(block); | ||||
| 			if (Block.inverseMap.containsKey(b)) | ||||
| 				return b; | ||||
| 			else | ||||
| 				return -1; | ||||
| 		} catch (NumberFormatException ignored) { | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
|     public static int checkBlock(String block) { | ||||
|         if (block == null) return -1; | ||||
|         try { | ||||
|             int b = Integer.parseInt(block); | ||||
|             if (Block.inverseMap.containsKey(b)) | ||||
|                 return b; | ||||
|             else | ||||
|                 return -1; | ||||
|         } catch (NumberFormatException ignored) { | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
| 	public static int checkRoom(String room, int block) { | ||||
| 		if (block == -1) return -1; | ||||
| 		if (room == null) return -1; | ||||
| 		try { | ||||
| 			Integer i = Integer.parseInt(room); | ||||
| 			if (Block.checkRoom(block, i)) | ||||
| 				return i; | ||||
| 			else | ||||
| 				return -1; | ||||
| 		} catch (NumberFormatException ignored) { | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
|     public static int checkRoom(String room, int block) { | ||||
|         if (block == -1) return -1; | ||||
|         if (room == null) return -1; | ||||
|         try { | ||||
|             Integer i = Integer.parseInt(room); | ||||
|             if (Block.checkRoom(block, i)) | ||||
|                 return i; | ||||
|             else | ||||
|                 return -1; | ||||
|         } catch (NumberFormatException ignored) { | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -24,12 +24,12 @@ import org.mindrot.jbcrypt.BCrypt; | ||||
|  */ | ||||
| public class Crypto { | ||||
|  | ||||
| 	public static String hash(String pw) { | ||||
| 		return BCrypt.hashpw(pw, BCrypt.gensalt()); | ||||
| 	} | ||||
|     public static String hash(String pw) { | ||||
|         return BCrypt.hashpw(pw, BCrypt.gensalt()); | ||||
|     } | ||||
|  | ||||
| 	public static boolean check(String plain, String hash) { | ||||
| 		return BCrypt.checkpw(plain, hash); | ||||
| 	} | ||||
|     public static boolean check(String plain, String hash) { | ||||
|         return BCrypt.checkpw(plain, hash); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -29,20 +29,20 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class ParseUtil { | ||||
|  | ||||
| 	public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm EEE"); | ||||
|     public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm EEE"); | ||||
|  | ||||
| 	public static String parseTicket(Ticket t) { | ||||
| 		StringBuilder sb = new StringBuilder() | ||||
| 				.append(lang("Ticket_Info_Id")).append(t.getId()).append("\n") | ||||
| 				.append(lang("Ticket_Info_Desc")).append(t.getDescription()).append("\n") | ||||
| 				.append(lang("Ticket_Info_Submit_Time")).append(dateFormat.format(t.getSubmitTime())).append("\n"); | ||||
| 		if (t.getOperator() != null) | ||||
| 			sb.append(lang("Ticket_Info_Operator")).append(t.getOperator().getId()).append("\n"); | ||||
| 		if (t.getRemark() != null) sb.append(lang("Ticket_Info_Remark")).append(t.getRemark()).append("\n"); | ||||
| 		if (t.getUpdateTime() != null) | ||||
| 			sb.append(lang("Ticket_Info_Update_Time")).append(dateFormat.format(t.getUpdateTime())).append("\n"); | ||||
| 		sb.append(lang("Ticket_Info_Status")).append(Status.getLocalized(t.getStatus())); | ||||
| 		return sb.toString(); | ||||
| 	} | ||||
|     public static String parseTicket(Ticket t) { | ||||
|         StringBuilder sb = new StringBuilder() | ||||
|                 .append(lang("Ticket_Info_Id")).append(t.getId()).append("\n") | ||||
|                 .append(lang("Ticket_Info_Desc")).append(t.getDescription()).append("\n") | ||||
|                 .append(lang("Ticket_Info_Submit_Time")).append(dateFormat.format(t.getSubmitTime())).append("\n"); | ||||
|         if (t.getOperator() != null) | ||||
|             sb.append(lang("Ticket_Info_Operator")).append(t.getOperator().getId()).append("\n"); | ||||
|         if (t.getRemark() != null) sb.append(lang("Ticket_Info_Remark")).append(t.getRemark()).append("\n"); | ||||
|         if (t.getUpdateTime() != null) | ||||
|             sb.append(lang("Ticket_Info_Update_Time")).append(dateFormat.format(t.getUpdateTime())).append("\n"); | ||||
|         sb.append(lang("Ticket_Info_Status")).append(Status.getLocalized(t.getStatus())); | ||||
|         return sb.toString(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,51 +31,51 @@ import java.security.KeyPairGenerator; | ||||
| public class RSAUtil { | ||||
|  | ||||
|  | ||||
| 	public static Key publicKey; | ||||
| 	public static Key privateKey; | ||||
| 	public static String publicKey_s; | ||||
| 	public static String privateKey_s; | ||||
|     public static Key publicKey; | ||||
|     public static Key privateKey; | ||||
|     public static String publicKey_s; | ||||
|     public static String privateKey_s; | ||||
|  | ||||
| 	static { | ||||
| 		genKeyPair(); | ||||
| 	} | ||||
|     static { | ||||
|         genKeyPair(); | ||||
|     } | ||||
|  | ||||
| 	public static void genKeyPair() { | ||||
| 		try { | ||||
| 			KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); | ||||
| 			kpg.initialize(1024); | ||||
| 			KeyPair kp = kpg.genKeyPair(); | ||||
| 			publicKey = kp.getPublic(); | ||||
| 			privateKey = kp.getPrivate(); | ||||
| 			publicKey_s = Base64.encodeBase64String(publicKey.getEncoded()); | ||||
| 			privateKey_s = Base64.encodeBase64String(privateKey.getEncoded()); | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
|     public static void genKeyPair() { | ||||
|         try { | ||||
|             KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); | ||||
|             kpg.initialize(1024); | ||||
|             KeyPair kp = kpg.genKeyPair(); | ||||
|             publicKey = kp.getPublic(); | ||||
|             privateKey = kp.getPrivate(); | ||||
|             publicKey_s = Base64.encodeBase64String(publicKey.getEncoded()); | ||||
|             privateKey_s = Base64.encodeBase64String(privateKey.getEncoded()); | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static String encrypt(String value) { | ||||
| 		try { | ||||
| 			Cipher cipher = Cipher.getInstance("RSA"); | ||||
| 			cipher.init(Cipher.ENCRYPT_MODE, publicKey); | ||||
| 			byte[] encrypted = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8)); | ||||
| 			return Base64.encodeBase64String(encrypted); | ||||
| 		} catch (Exception ex) { | ||||
| 			ex.printStackTrace(); | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
|     public static String encrypt(String value) { | ||||
|         try { | ||||
|             Cipher cipher = Cipher.getInstance("RSA"); | ||||
|             cipher.init(Cipher.ENCRYPT_MODE, publicKey); | ||||
|             byte[] encrypted = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8)); | ||||
|             return Base64.encodeBase64String(encrypted); | ||||
|         } catch (Exception ex) { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| 	public static String decrypt(String encrypted) { | ||||
| 		try { | ||||
| 			Cipher cipher = Cipher.getInstance("RSA"); | ||||
| 			cipher.init(Cipher.DECRYPT_MODE, privateKey); | ||||
| 			byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted)); | ||||
| 			return new String(original, StandardCharsets.UTF_8); | ||||
| 		} catch (Exception ex) { | ||||
| 			ex.printStackTrace(); | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
|     public static String decrypt(String encrypted) { | ||||
|         try { | ||||
|             Cipher cipher = Cipher.getInstance("RSA"); | ||||
|             cipher.init(Cipher.DECRYPT_MODE, privateKey); | ||||
|             byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted)); | ||||
|             return new String(original, StandardCharsets.UTF_8); | ||||
|         } catch (Exception ex) { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -29,105 +29,105 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class Redirect { | ||||
|  | ||||
| 	private static final String REDIRECT_PAGE = lang("Result_Page"); | ||||
|     private static final String REDIRECT_PAGE = lang("Result_Page"); | ||||
|  | ||||
| 	private static final int SUCCESS = 1; | ||||
| 	private static final int ERROR = 0; | ||||
| 	private static final int WARNING = -1; | ||||
| 	private static final int NON_WECHAT = 88; | ||||
|     private static final int SUCCESS = 1; | ||||
|     private static final int ERROR = 0; | ||||
|     private static final int WARNING = -1; | ||||
|     private static final int NON_WECHAT = 88; | ||||
|  | ||||
| 	public static RedirectBuilder success() { | ||||
| 		return new RedirectBuilder(SUCCESS); | ||||
| 	} | ||||
|     public static RedirectBuilder success() { | ||||
|         return new RedirectBuilder(SUCCESS); | ||||
|     } | ||||
|  | ||||
| 	public static RedirectBuilder error() { | ||||
| 		return new RedirectBuilder(ERROR); | ||||
| 	} | ||||
|     public static RedirectBuilder error() { | ||||
|         return new RedirectBuilder(ERROR); | ||||
|     } | ||||
|  | ||||
| 	public static class RedirectBuilder { | ||||
|     public static class RedirectBuilder { | ||||
|  | ||||
| 		private StringBuilder sb; | ||||
|         private StringBuilder sb; | ||||
|  | ||||
| 		RedirectBuilder(int type) { | ||||
| 			sb = new StringBuilder(REDIRECT_PAGE).append("?"); | ||||
| 			type(type); | ||||
| 		} | ||||
|         RedirectBuilder(int type) { | ||||
|             sb = new StringBuilder(REDIRECT_PAGE).append("?"); | ||||
|             type(type); | ||||
|         } | ||||
|  | ||||
| 		private RedirectBuilder type(int type) { | ||||
| 			sb.append("type=").append(type).append("&"); | ||||
| 			return this; | ||||
| 		} | ||||
|         private RedirectBuilder type(int type) { | ||||
|             sb.append("type=").append(type).append("&"); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| 		public RedirectBuilder msg(String msg) { | ||||
| 			sb.append("msg=").append(escape(msg)).append("&"); | ||||
| 			return this; | ||||
| 		} | ||||
|         public RedirectBuilder msg(String msg) { | ||||
|             sb.append("msg=").append(escape(msg)).append("&"); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| 		public RedirectBuilder title(String title) { | ||||
| 			sb.append("title=").append(escape(title)).append("&"); | ||||
| 			return this; | ||||
| 		} | ||||
|         public RedirectBuilder title(String title) { | ||||
|             sb.append("title=").append(escape(title)).append("&"); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| 		public RedirectBuilder noButton() { | ||||
| 			sb.append("btn=").append("hide").append("&"); | ||||
| 			return this; | ||||
| 		} | ||||
|         public RedirectBuilder noButton() { | ||||
|             sb.append("btn=").append("hide").append("&"); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| 		public RedirectBuilder button(String text) { | ||||
| 			sb.append("btn=").append(escape(text)).append("&"); | ||||
| 			return this; | ||||
| 		} | ||||
|         public RedirectBuilder button(String text) { | ||||
|             sb.append("btn=").append(escape(text)).append("&"); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| 		public RedirectBuilder icon(WeUIIcon icon) { | ||||
| 			sb.append("icon=").append(icon.toString()).append("&"); | ||||
| 			return this; | ||||
| 		} | ||||
|         public RedirectBuilder icon(WeUIIcon icon) { | ||||
|             sb.append("icon=").append(icon.toString()).append("&"); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| 		public RedirectBuilder to(String url) { | ||||
| 			sb.append("redirect=").append(escape(url)).append("&"); | ||||
| 			return this; | ||||
| 		} | ||||
|         public RedirectBuilder to(String url) { | ||||
|             sb.append("redirect=").append(escape(url)).append("&"); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| 		public void go(HttpServletResponse resp) throws IOException { | ||||
| 			resp.sendRedirect(sb.toString()); | ||||
| 		} | ||||
|         public void go(HttpServletResponse resp) throws IOException { | ||||
|             resp.sendRedirect(sb.toString()); | ||||
|         } | ||||
|  | ||||
| 		public String toString() { | ||||
| 			return sb.toString(); | ||||
| 		} | ||||
|         public String toString() { | ||||
|             return sb.toString(); | ||||
|         } | ||||
|  | ||||
| 		private static String escape(String str) { | ||||
| 			return UrlEscapers.urlFragmentEscaper().escape(str); | ||||
| 		} | ||||
|         private static String escape(String str) { | ||||
|             return UrlEscapers.urlFragmentEscaper().escape(str); | ||||
|         } | ||||
|  | ||||
| 	} | ||||
|     } | ||||
|  | ||||
| 	public enum WeUIIcon { | ||||
| 		SUCCESS("weui_icon_success"), | ||||
| 		SUCCESS_CIRCLE("weui_icon_success_circle"), | ||||
| 		SUCCESS_NO_CIRCLE("weui_icon_success_no_circle"), | ||||
| 		SUCCESS_SAFE("weui_icon_safe_success"), | ||||
| 		INFO("weui_icon_info"), | ||||
| 		INFO_CIRCLE("weui_icon_info_circle"), | ||||
| 		WAITING("weui_icon_waiting"), | ||||
| 		WAITING_CIRCLE("weui_icon_waiting_circle"), | ||||
| 		CIRCLE("weui_icon_circle"), | ||||
| 		WARN("weui_icon_warn"), | ||||
| 		WARN_SAFE("weui_icon_safe_warn"), | ||||
| 		DOWNLOAD("weui_icon_download"), | ||||
| 		CANCEL("weui_icon_cancel"),; | ||||
|     public enum WeUIIcon { | ||||
|         SUCCESS("weui_icon_success"), | ||||
|         SUCCESS_CIRCLE("weui_icon_success_circle"), | ||||
|         SUCCESS_NO_CIRCLE("weui_icon_success_no_circle"), | ||||
|         SUCCESS_SAFE("weui_icon_safe_success"), | ||||
|         INFO("weui_icon_info"), | ||||
|         INFO_CIRCLE("weui_icon_info_circle"), | ||||
|         WAITING("weui_icon_waiting"), | ||||
|         WAITING_CIRCLE("weui_icon_waiting_circle"), | ||||
|         CIRCLE("weui_icon_circle"), | ||||
|         WARN("weui_icon_warn"), | ||||
|         WARN_SAFE("weui_icon_safe_warn"), | ||||
|         DOWNLOAD("weui_icon_download"), | ||||
|         CANCEL("weui_icon_cancel"),; | ||||
|  | ||||
| 		private String value; | ||||
|         private String value; | ||||
|  | ||||
| 		WeUIIcon(String value) { | ||||
| 			this.value = value; | ||||
| 		} | ||||
|         WeUIIcon(String value) { | ||||
|             this.value = value; | ||||
|         } | ||||
|  | ||||
| 		@Override | ||||
| 		public String toString() { | ||||
| 			return value; | ||||
| 		} | ||||
|         @Override | ||||
|         public String toString() { | ||||
|             return value; | ||||
|         } | ||||
|  | ||||
| 	} | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -33,43 +33,43 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public enum Command { | ||||
|  | ||||
| 	REGISTER(0, RegisterHandler.class), | ||||
| 	QUERY(1, QueryHandler.class), | ||||
| 	SUBMIT(2, SubmitHandler.class), | ||||
| 	CANCEL(3, CancelHandler.class), | ||||
| 	PROFILE(4, ProfileHandler.class), | ||||
| 	LOGIN(10, LoginHandler.class), | ||||
| 	OPERATOR_INFO(11, OperatorInfoHandler.class), | ||||
| 	SIGN(12, SignHandler.class), //FIXME | ||||
| 	; | ||||
|     REGISTER(0, RegisterHandler.class), | ||||
|     QUERY(1, QueryHandler.class), | ||||
|     SUBMIT(2, SubmitHandler.class), | ||||
|     CANCEL(3, CancelHandler.class), | ||||
|     PROFILE(4, ProfileHandler.class), | ||||
|     LOGIN(10, LoginHandler.class), | ||||
|     OPERATOR_INFO(11, OperatorInfoHandler.class), | ||||
|     SIGN(12, SignHandler.class), //FIXME | ||||
|     ; | ||||
|  | ||||
| 	private static final Map<Integer, Command> ID_MAP = new HashMap<>(); | ||||
|     private static final Map<Integer, Command> ID_MAP = new HashMap<>(); | ||||
|  | ||||
| 	static { | ||||
| 		for (Command type : values()) { | ||||
| 			if (type.id >= 0) { | ||||
| 				ID_MAP.put(type.id, type); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     static { | ||||
|         for (Command type : values()) { | ||||
|             if (type.id >= 0) { | ||||
|                 ID_MAP.put(type.id, type); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public final String regex; | ||||
| 	public final Class<? extends WxMpMessageHandler> handler; | ||||
| 	public final int id; | ||||
|     public final String regex; | ||||
|     public final Class<? extends WxMpMessageHandler> handler; | ||||
|     public final int id; | ||||
|  | ||||
| 	Command(int id, Class<? extends WxMpMessageHandler> handler) { | ||||
| 		this.id = id; | ||||
| 		this.regex = lang("REGEX_" + name()); | ||||
| 		this.handler = handler; | ||||
| 	} | ||||
|     Command(int id, Class<? extends WxMpMessageHandler> handler) { | ||||
|         this.id = id; | ||||
|         this.regex = lang("REGEX_" + name()); | ||||
|         this.handler = handler; | ||||
|     } | ||||
|  | ||||
| 	public static Command fromId(int id) { | ||||
| 		return ID_MAP.get(id); | ||||
| 	} | ||||
|     public static Command fromId(int id) { | ||||
|         return ID_MAP.get(id); | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return name(); | ||||
| 	} | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return name(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -46,94 +46,94 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
| @WebServlet(name = "WxMpServlet", urlPatterns = "/wechat", loadOnStartup = 99) | ||||
| public class WxMpServlet extends HttpServlet { | ||||
|  | ||||
| 	public static WxMpServlet instance; | ||||
| 	protected WxMpInMemoryConfigStorage config; | ||||
| 	public WxMpService wxMpService; | ||||
| 	protected WxMpMessageRouter wxMpMessageRouter; | ||||
| 	protected CheckSpamMatcher checkSpamMatcher; | ||||
|     public static WxMpServlet instance; | ||||
|     protected WxMpInMemoryConfigStorage config; | ||||
|     public WxMpService wxMpService; | ||||
|     protected WxMpMessageRouter wxMpMessageRouter; | ||||
|     protected CheckSpamMatcher checkSpamMatcher; | ||||
|  | ||||
| 	public WxMpServlet() { | ||||
| 		instance = this; | ||||
| 	} | ||||
|     public WxMpServlet() { | ||||
|         instance = this; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	public void init() throws ServletException { | ||||
| 		super.init(); | ||||
|     @Override | ||||
|     public void init() throws ServletException { | ||||
|         super.init(); | ||||
|  | ||||
| 		config = new WxMpInMemoryConfigStorage(); | ||||
| 		config.setAppId(Settings.I.Wechat_AppId); | ||||
| 		config.setSecret(Settings.I.Wechat_Secret); | ||||
| 		config.setToken(Settings.I.Wechat_Token); | ||||
| 		config.setAesKey(Settings.I.Wechat_AesKey); | ||||
|         config = new WxMpInMemoryConfigStorage(); | ||||
|         config.setAppId(Settings.I.Wechat_AppId); | ||||
|         config.setSecret(Settings.I.Wechat_Secret); | ||||
|         config.setToken(Settings.I.Wechat_Token); | ||||
|         config.setAesKey(Settings.I.Wechat_AesKey); | ||||
|  | ||||
| 		wxMpService = new WxMpServiceImpl(); | ||||
| 		wxMpService.setWxMpConfigStorage(config); | ||||
|         wxMpService = new WxMpServiceImpl(); | ||||
|         wxMpService.setWxMpConfigStorage(config); | ||||
|  | ||||
| 		checkSpamMatcher = new CheckSpamMatcher(); | ||||
| 		wxMpMessageRouter = new WxMpMessageRouter(wxMpService); | ||||
| 		wxMpMessageRouter.rule() | ||||
| 				.async(false) | ||||
| 				.msgType(WxConsts.XML_MSG_EVENT) | ||||
| 				.event(WxConsts.EVT_SUBSCRIBE) | ||||
| 				.handler(new SubscribeHandler()) | ||||
| 				.end(); | ||||
| 		wxMpMessageRouter.rule() | ||||
| 				.async(false) | ||||
| 				.matcher(new CheckSpamMatcher()) | ||||
| 				.handler((wxMessage, context, wxMpService1, sessionManager) | ||||
| 						-> WxMpXmlOutMessage.TEXT() | ||||
| 						.fromUser(wxMessage.getToUserName()) | ||||
| 						.toUser(wxMessage.getFromUserName()) | ||||
| 						.content(lang("Message_Spam")).build()) | ||||
| 				.end(); | ||||
| 		wxMpMessageRouter.rule() | ||||
| 				.async(false) | ||||
| 				.matcher(new RegisterMatcher()) | ||||
| 				.handler(new RegisterHandler()) | ||||
| 				.end(); | ||||
| 		try { | ||||
| 			registerCommands(wxMpMessageRouter); | ||||
| 		} catch (IllegalAccessException | InstantiationException e) { | ||||
| 			throw new ServletException(e); | ||||
| 		} | ||||
| 	} | ||||
|         checkSpamMatcher = new CheckSpamMatcher(); | ||||
|         wxMpMessageRouter = new WxMpMessageRouter(wxMpService); | ||||
|         wxMpMessageRouter.rule() | ||||
|                 .async(false) | ||||
|                 .msgType(WxConsts.XML_MSG_EVENT) | ||||
|                 .event(WxConsts.EVT_SUBSCRIBE) | ||||
|                 .handler(new SubscribeHandler()) | ||||
|                 .end(); | ||||
|         wxMpMessageRouter.rule() | ||||
|                 .async(false) | ||||
|                 .matcher(new CheckSpamMatcher()) | ||||
|                 .handler((wxMessage, context, wxMpService1, sessionManager) | ||||
|                         -> WxMpXmlOutMessage.TEXT() | ||||
|                         .fromUser(wxMessage.getToUserName()) | ||||
|                         .toUser(wxMessage.getFromUserName()) | ||||
|                         .content(lang("Message_Spam")).build()) | ||||
|                 .end(); | ||||
|         wxMpMessageRouter.rule() | ||||
|                 .async(false) | ||||
|                 .matcher(new RegisterMatcher()) | ||||
|                 .handler(new RegisterHandler()) | ||||
|                 .end(); | ||||
|         try { | ||||
|             registerCommands(wxMpMessageRouter); | ||||
|         } catch (IllegalAccessException | InstantiationException e) { | ||||
|             throw new ServletException(e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	public static void registerCommands(WxMpMessageRouter router) throws IllegalAccessException, InstantiationException { | ||||
| 		for (Command c : Command.values()) { | ||||
| 			WxMpMessageHandler handler = c.handler.newInstance(); | ||||
| 			router.rule().async(false).msgType(WxConsts.XML_MSG_TEXT).rContent(c.regex).handler(handler).end(); | ||||
| 			router.rule().async(false).msgType(WxConsts.XML_MSG_EVENT).event(WxConsts.EVT_CLICK).eventKey(c.name()).handler(handler).end(); | ||||
| 			if (handler instanceof OAuth2Handler) { | ||||
| 				OAuth2.registerOAuth2Handler(c.name(), (OAuth2Handler) handler); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     public static void registerCommands(WxMpMessageRouter router) throws IllegalAccessException, InstantiationException { | ||||
|         for (Command c : Command.values()) { | ||||
|             WxMpMessageHandler handler = c.handler.newInstance(); | ||||
|             router.rule().async(false).msgType(WxConsts.XML_MSG_TEXT).rContent(c.regex).handler(handler).end(); | ||||
|             router.rule().async(false).msgType(WxConsts.XML_MSG_EVENT).event(WxConsts.EVT_CLICK).eventKey(c.name()).handler(handler).end(); | ||||
|             if (handler instanceof OAuth2Handler) { | ||||
|                 OAuth2.registerOAuth2Handler(c.name(), (OAuth2Handler) handler); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected void doPost(HttpServletRequest request, HttpServletResponse response) | ||||
| 			throws ServletException, IOException { | ||||
|     @Override | ||||
|     protected void doPost(HttpServletRequest request, HttpServletResponse response) | ||||
|             throws ServletException, IOException { | ||||
|  | ||||
| 		response.setContentType("text/html;charset=utf-8"); | ||||
| 		response.setStatus(HttpServletResponse.SC_OK); | ||||
|         response.setContentType("text/html;charset=utf-8"); | ||||
|         response.setStatus(HttpServletResponse.SC_OK); | ||||
|  | ||||
| 		String signature = request.getParameter("signature"); | ||||
| 		String nonce = request.getParameter("nonce"); | ||||
| 		String timestamp = request.getParameter("timestamp"); | ||||
|         String signature = request.getParameter("signature"); | ||||
|         String nonce = request.getParameter("nonce"); | ||||
|         String timestamp = request.getParameter("timestamp"); | ||||
|  | ||||
| 		if (!wxMpService.checkSignature(timestamp, nonce, signature)) { | ||||
| 			// Signature fail | ||||
| 			response.getWriter().println(lang("Access_Denied")); | ||||
| 			return; | ||||
| 		} | ||||
|         if (!wxMpService.checkSignature(timestamp, nonce, signature)) { | ||||
|             // Signature fail | ||||
|             response.getWriter().println(lang("Access_Denied")); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| 		String echostr = request.getParameter("echostr"); | ||||
| 		if (StringUtils.isNotBlank(echostr)) { | ||||
| 			// validate request | ||||
| 			response.getWriter().println(echostr); | ||||
| 			return; | ||||
| 		} | ||||
|         String echostr = request.getParameter("echostr"); | ||||
|         if (StringUtils.isNotBlank(echostr)) { | ||||
|             // validate request | ||||
|             response.getWriter().println(echostr); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| 		String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ? "raw" : request.getParameter("encrypt_type"); | ||||
|         String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ? "raw" : request.getParameter("encrypt_type"); | ||||
|  | ||||
| //		if ("raw".equals(encryptType)) { | ||||
| //			WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream()); | ||||
| @@ -149,32 +149,32 @@ public class WxMpServlet extends HttpServlet { | ||||
| //			return; | ||||
| //		} | ||||
|  | ||||
| 		if ("aes".equals(encryptType)) { | ||||
| 			String msgSignature = request.getParameter("msg_signature"); | ||||
| 			WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), config, timestamp, nonce, msgSignature); | ||||
| 			WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage); | ||||
| 			if (outMessage == null) { | ||||
| 				outMessage = WxMpXmlOutMessage.TEXT() | ||||
| 						.fromUser(inMessage.getToUserName()) | ||||
| 						.toUser(inMessage.getFromUserName()) | ||||
| 						.content(lang("Invalid_Operation")) | ||||
| 						.build(); | ||||
| 			} | ||||
| 			response.getWriter().write(outMessage.toEncryptedXml(config)); | ||||
| 			return; | ||||
| 		} | ||||
|         if ("aes".equals(encryptType)) { | ||||
|             String msgSignature = request.getParameter("msg_signature"); | ||||
|             WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), config, timestamp, nonce, msgSignature); | ||||
|             WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage); | ||||
|             if (outMessage == null) { | ||||
|                 outMessage = WxMpXmlOutMessage.TEXT() | ||||
|                         .fromUser(inMessage.getToUserName()) | ||||
|                         .toUser(inMessage.getFromUserName()) | ||||
|                         .content(lang("Invalid_Operation")) | ||||
|                         .build(); | ||||
|             } | ||||
|             response.getWriter().write(outMessage.toEncryptedXml(config)); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| 		response.getWriter().println(lang("Unknown_Encrypt_Type")); | ||||
| 		return; | ||||
| 	} | ||||
|         response.getWriter().println(lang("Unknown_Encrypt_Type")); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
| 		doPost(req, resp); | ||||
| 	} | ||||
|     @Override | ||||
|     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
|         doPost(req, resp); | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	public void destroy() { | ||||
| 		SQLCore.destroy(); | ||||
| 	} | ||||
|     @Override | ||||
|     public void destroy() { | ||||
|         SQLCore.destroy(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -31,10 +31,10 @@ import java.util.Map; | ||||
|  */ | ||||
| public class AutoReplyHandler implements WxMpMessageHandler { | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		//TODO auto reply | ||||
| 		return null; | ||||
| 	} | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         //TODO auto reply | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -45,33 +45,33 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class CancelHandler implements WxMpMessageHandler { | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		User u = TableUser.getByWechat(wxMessage.getFromUserName()); | ||||
| 		Ticket t = TableTicket.latestOpen(u); | ||||
| 		if (t == null) { | ||||
| 			return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) | ||||
| 					.content(lang("No_Open_Ticket_Available")).build(); | ||||
| 		} | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			t.setOperator(Operator.USER_SELF); | ||||
| 			t.setUpdateTime(new Date()); | ||||
| 			t.setRemark(lang("User_Cancel_Remark")); | ||||
| 			t.setStatus(Status.SOLVED); | ||||
| 			s.beginTransaction(); | ||||
| 			s.update(t); | ||||
| 			s.getTransaction().commit(); | ||||
| 			NewsBuilder out = WxMpXmlOutMessage.NEWS().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
| 			WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item(); | ||||
| 			item.setTitle(lang("Cancel_Title")); | ||||
| 			item.setDescription(ParseUtil.parseTicket(t)); | ||||
| 			out.addArticle(item); | ||||
| 			return out.build(); | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 			return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) | ||||
| 					.content(lang("Cancel_Failed")).build(); | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         User u = TableUser.getByWechat(wxMessage.getFromUserName()); | ||||
|         Ticket t = TableTicket.latestOpen(u); | ||||
|         if (t == null) { | ||||
|             return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) | ||||
|                     .content(lang("No_Open_Ticket_Available")).build(); | ||||
|         } | ||||
|         try (Session s = SQLCore.sf.openSession()) { | ||||
|             t.setOperator(Operator.USER_SELF); | ||||
|             t.setUpdateTime(new Date()); | ||||
|             t.setRemark(lang("User_Cancel_Remark")); | ||||
|             t.setStatus(Status.SOLVED); | ||||
|             s.beginTransaction(); | ||||
|             s.update(t); | ||||
|             s.getTransaction().commit(); | ||||
|             NewsBuilder out = WxMpXmlOutMessage.NEWS().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
|             WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item(); | ||||
|             item.setTitle(lang("Cancel_Title")); | ||||
|             item.setDescription(ParseUtil.parseTicket(t)); | ||||
|             out.addArticle(item); | ||||
|             return out.build(); | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|             return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) | ||||
|                     .content(lang("Cancel_Failed")).build(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -45,37 +45,37 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class ProfileHandler implements WxMpMessageHandler, OAuth2Handler { | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		User u = TableUser.getByWechat(wxMessage.getFromUserName()); | ||||
| 		WxSession session = WechatSession.create(); | ||||
| 		session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE); | ||||
| 		session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName()); | ||||
| 		session.setAttribute(Attribute.USER, u); | ||||
| 		TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
| 		out.content(format("Profile_Modify", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone()))); | ||||
| 		return out.build(); | ||||
| 	} | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         User u = TableUser.getByWechat(wxMessage.getFromUserName()); | ||||
|         WxSession session = WechatSession.create(); | ||||
|         session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE); | ||||
|         session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName()); | ||||
|         session.setAttribute(Attribute.USER, u); | ||||
|         TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
|         out.content(format("Profile_Modify", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone()))); | ||||
|         return out.build(); | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	public void onOAuth2(AsyncContext actx, HttpServletResponse resp, String user, WxSession session) { | ||||
| 		try { | ||||
| 			User u = TableUser.getByWechat(user); | ||||
| 			if (u == null) { | ||||
| 				session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER); | ||||
| 				session.setAttribute(Attribute.WECHAT, user); | ||||
| 				Redirect.error().icon(Redirect.WeUIIcon.INFO).noButton() | ||||
| 						.title(lang("Need_Register_Title")).msg(lang("Need_Register")) | ||||
| 						.to(format("User_Register_Link", session.getId())).go(resp); | ||||
| 				return; | ||||
| 			} | ||||
| 			session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE); | ||||
| 			session.setAttribute(Attribute.WECHAT, user); | ||||
| 			session.setAttribute(Attribute.USER, u); | ||||
| 			resp.sendRedirect(format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())); | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     public void onOAuth2(AsyncContext actx, HttpServletResponse resp, String user, WxSession session) { | ||||
|         try { | ||||
|             User u = TableUser.getByWechat(user); | ||||
|             if (u == null) { | ||||
|                 session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER); | ||||
|                 session.setAttribute(Attribute.WECHAT, user); | ||||
|                 Redirect.error().icon(Redirect.WeUIIcon.INFO).noButton() | ||||
|                         .title(lang("Need_Register_Title")).msg(lang("Need_Register")) | ||||
|                         .to(format("User_Register_Link", session.getId())).go(resp); | ||||
|                 return; | ||||
|             } | ||||
|             session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE); | ||||
|             session.setAttribute(Attribute.WECHAT, user); | ||||
|             session.setAttribute(Attribute.USER, u); | ||||
|             resp.sendRedirect(format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())); | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -46,26 +46,26 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
| public class QueryHandler implements WxMpMessageHandler { | ||||
|  | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		User u = TableUser.getByWechat(wxMessage.getFromUserName()); | ||||
| 		Ticket t = TableTicket.latest(u); | ||||
| 		if (t == null) { | ||||
| 			return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) | ||||
| 					.content(lang("No_Ticket_Available")).build(); | ||||
| 		} | ||||
| 		WxSession session = WechatSession.create(); | ||||
| 		session.setAttribute(Attribute.AUTHORIZED, Command.QUERY); | ||||
| 		session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName()); | ||||
| 		session.setAttribute(Attribute.USER, u); | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         User u = TableUser.getByWechat(wxMessage.getFromUserName()); | ||||
|         Ticket t = TableTicket.latest(u); | ||||
|         if (t == null) { | ||||
|             return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) | ||||
|                     .content(lang("No_Ticket_Available")).build(); | ||||
|         } | ||||
|         WxSession session = WechatSession.create(); | ||||
|         session.setAttribute(Attribute.AUTHORIZED, Command.QUERY); | ||||
|         session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName()); | ||||
|         session.setAttribute(Attribute.USER, u); | ||||
|  | ||||
| 		NewsBuilder out = WxMpXmlOutMessage.NEWS().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
| 		WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item(); | ||||
| 		item.setTitle(lang("Query_Title")); | ||||
| 		item.setDescription(ParseUtil.parseTicket(t) + "\n" + lang("More_Details")); | ||||
| 		item.setUrl(format("User_Query_Link", session.getId())); | ||||
| 		out.addArticle(item); | ||||
| 		return out.build(); | ||||
| 	} | ||||
|         NewsBuilder out = WxMpXmlOutMessage.NEWS().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
|         WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item(); | ||||
|         item.setTitle(lang("Query_Title")); | ||||
|         item.setDescription(ParseUtil.parseTicket(t) + "\n" + lang("More_Details")); | ||||
|         item.setUrl(format("User_Query_Link", session.getId())); | ||||
|         out.addArticle(item); | ||||
|         return out.build(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -40,24 +40,24 @@ import static love.sola.netsupport.config.Lang.format; | ||||
|  */ | ||||
| public class RegisterHandler implements WxMpMessageHandler { | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) | ||||
| 			throws WxErrorException { | ||||
| 		TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
| 		String fromUser = wxMessage.getFromUserName(); | ||||
| 		User u = TableUser.getByWechat(fromUser); | ||||
| 		WxSession session = WechatSession.create(); | ||||
| 		if (u != null) { | ||||
| 			session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE); | ||||
| 			session.setAttribute(Attribute.WECHAT, fromUser); | ||||
| 			session.setAttribute(Attribute.USER, u); | ||||
| 			out.content(format("Already_Registered", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone()))); | ||||
| 		} else { | ||||
| 			session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER); | ||||
| 			session.setAttribute(Attribute.WECHAT, fromUser); | ||||
| 			out.content(format("User_Register", format("User_Register_Link", session.getId()))); | ||||
| 		} | ||||
| 		return out.build(); | ||||
| 	} | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) | ||||
|             throws WxErrorException { | ||||
|         TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
|         String fromUser = wxMessage.getFromUserName(); | ||||
|         User u = TableUser.getByWechat(fromUser); | ||||
|         WxSession session = WechatSession.create(); | ||||
|         if (u != null) { | ||||
|             session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE); | ||||
|             session.setAttribute(Attribute.WECHAT, fromUser); | ||||
|             session.setAttribute(Attribute.USER, u); | ||||
|             out.content(format("Already_Registered", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone()))); | ||||
|         } else { | ||||
|             session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER); | ||||
|             session.setAttribute(Attribute.WECHAT, fromUser); | ||||
|             out.content(format("User_Register", format("User_Register_Link", session.getId()))); | ||||
|         } | ||||
|         return out.build(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -43,25 +43,25 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class SubmitHandler implements WxMpMessageHandler { | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		User u = TableUser.getByWechat(wxMessage.getFromUserName()); | ||||
| 		if (TableTicket.hasOpen(u)) { | ||||
| 			return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) | ||||
| 					.content(lang("Already_Opening_Ticket")).build(); | ||||
| 		} | ||||
| 		WxSession session = WechatSession.create(); | ||||
| 		session.setAttribute(Attribute.AUTHORIZED, Command.SUBMIT); | ||||
| 		session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName()); | ||||
| 		session.setAttribute(Attribute.USER, u); | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         User u = TableUser.getByWechat(wxMessage.getFromUserName()); | ||||
|         if (TableTicket.hasOpen(u)) { | ||||
|             return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()) | ||||
|                     .content(lang("Already_Opening_Ticket")).build(); | ||||
|         } | ||||
|         WxSession session = WechatSession.create(); | ||||
|         session.setAttribute(Attribute.AUTHORIZED, Command.SUBMIT); | ||||
|         session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName()); | ||||
|         session.setAttribute(Attribute.USER, u); | ||||
|  | ||||
| 		NewsBuilder out = WxMpXmlOutMessage.NEWS().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
| 		WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item(); | ||||
| 		item.setTitle(lang("Submit_Title")); | ||||
| 		item.setDescription(lang("Submit_Desc")); | ||||
| 		item.setUrl(format("User_Submit_Link", session.getId(), u.getName(), u.getIsp().id, u.getRoom(), u.getBlock(), u.getPhone())); | ||||
| 		out.addArticle(item); | ||||
| 		return out.build(); | ||||
| 	} | ||||
|         NewsBuilder out = WxMpXmlOutMessage.NEWS().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
|         WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item(); | ||||
|         item.setTitle(lang("Submit_Title")); | ||||
|         item.setDescription(lang("Submit_Desc")); | ||||
|         item.setUrl(format("User_Submit_Link", session.getId(), u.getName(), u.getIsp().id, u.getRoom(), u.getBlock(), u.getPhone())); | ||||
|         out.addArticle(item); | ||||
|         return out.build(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -42,28 +42,28 @@ import static love.sola.netsupport.config.Lang.format; | ||||
|  */ | ||||
| public class SubscribeHandler implements WxMpMessageHandler { | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
| 		String fromUser = wxMessage.getFromUserName(); | ||||
| 		User u = TableUser.getByWechat(fromUser); | ||||
| 		WxSession session = WechatSession.create(); | ||||
| 		if (u != null) { | ||||
| 			session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE); | ||||
| 			session.setAttribute(Attribute.WECHAT, fromUser); | ||||
| 			session.setAttribute(Attribute.USER, u); | ||||
| 			out.content(format("Event_Subscribe", format("Already_Registered", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())))); | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
|         String fromUser = wxMessage.getFromUserName(); | ||||
|         User u = TableUser.getByWechat(fromUser); | ||||
|         WxSession session = WechatSession.create(); | ||||
|         if (u != null) { | ||||
|             session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE); | ||||
|             session.setAttribute(Attribute.WECHAT, fromUser); | ||||
|             session.setAttribute(Attribute.USER, u); | ||||
|             out.content(format("Event_Subscribe", format("Already_Registered", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())))); | ||||
|  | ||||
| 			Operator op = TableOperator.get(fromUser); | ||||
| 			if (op != null) { | ||||
| 				wxMpService.userUpdateGroup(fromUser, 100L); | ||||
| 			} | ||||
| 		} else { | ||||
| 			session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER); | ||||
| 			session.setAttribute(Attribute.WECHAT, fromUser); | ||||
| 			out.content(format("Event_Subscribe", format("User_Register", format("User_Register_Link", session.getId())))); | ||||
| 		} | ||||
| 		return out.build(); | ||||
| 	} | ||||
|             Operator op = TableOperator.get(fromUser); | ||||
|             if (op != null) { | ||||
|                 wxMpService.userUpdateGroup(fromUser, 100L); | ||||
|             } | ||||
|         } else { | ||||
|             session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER); | ||||
|             session.setAttribute(Attribute.WECHAT, fromUser); | ||||
|             out.content(format("Event_Subscribe", format("User_Register", format("User_Register_Link", session.getId())))); | ||||
|         } | ||||
|         return out.build(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -46,51 +46,51 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class LoginHandler implements WxMpMessageHandler, OAuth2Handler { | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
| 		try { | ||||
| 			Operator operator = TableOperator.get(wxMessage.getFromUserName()); | ||||
| 			if (operator == null) | ||||
| 				out.content(lang("Not_Operator")); | ||||
| 			else if (operator.getAccess() >= Access.NO_LOGIN) { | ||||
| 				out.content(lang("No_Login")); | ||||
| 			} else { | ||||
| 				WxSession session = WechatSession.create(); | ||||
| 				session.setAttribute(Attribute.AUTHORIZED, Command.LOGIN); | ||||
| 				session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName()); | ||||
| 				session.setAttribute(Attribute.OPERATOR, operator); | ||||
| 				out.content(format("Home_Page_Msg", format("Operator_Home_Page", session.getId()))); | ||||
| 			} | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 			out.content(lang("Login_Error")); | ||||
| 		} | ||||
| 		return out.build(); | ||||
| 	} | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
|         try { | ||||
|             Operator operator = TableOperator.get(wxMessage.getFromUserName()); | ||||
|             if (operator == null) | ||||
|                 out.content(lang("Not_Operator")); | ||||
|             else if (operator.getAccess() >= Access.NO_LOGIN) { | ||||
|                 out.content(lang("No_Login")); | ||||
|             } else { | ||||
|                 WxSession session = WechatSession.create(); | ||||
|                 session.setAttribute(Attribute.AUTHORIZED, Command.LOGIN); | ||||
|                 session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName()); | ||||
|                 session.setAttribute(Attribute.OPERATOR, operator); | ||||
|                 out.content(format("Home_Page_Msg", format("Operator_Home_Page", session.getId()))); | ||||
|             } | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|             out.content(lang("Login_Error")); | ||||
|         } | ||||
|         return out.build(); | ||||
|     } | ||||
|  | ||||
|  | ||||
| 	@Override | ||||
| 	public void onOAuth2(AsyncContext actx, HttpServletResponse resp, String user, WxSession session) { | ||||
| 		try { | ||||
| 			Operator operator = TableOperator.get(user); | ||||
| 			if (operator == null) { | ||||
| 				Redirect.error().icon(Redirect.WeUIIcon.WARN_SAFE).noButton() | ||||
| 						.title(lang("Not_Operator")).msg(lang("Not_Operator_OAuth2")).go(resp); | ||||
| 				return; | ||||
| 			} | ||||
| 			if (operator.getAccess() >= Access.NO_LOGIN) { | ||||
| 				Redirect.error().icon(Redirect.WeUIIcon.WAITING).noButton() | ||||
| 						.title(lang("Left_Operator_Title")).msg(lang("Left_Operator")).go(resp); | ||||
| 				return; | ||||
| 			} | ||||
| 			session.setAttribute(Attribute.AUTHORIZED, Command.LOGIN); | ||||
| 			session.setAttribute(Attribute.WECHAT, user); | ||||
| 			session.setAttribute(Attribute.OPERATOR, operator); | ||||
| 			resp.sendRedirect(format("Operator_Home_Page", session.getId())); | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     public void onOAuth2(AsyncContext actx, HttpServletResponse resp, String user, WxSession session) { | ||||
|         try { | ||||
|             Operator operator = TableOperator.get(user); | ||||
|             if (operator == null) { | ||||
|                 Redirect.error().icon(Redirect.WeUIIcon.WARN_SAFE).noButton() | ||||
|                         .title(lang("Not_Operator")).msg(lang("Not_Operator_OAuth2")).go(resp); | ||||
|                 return; | ||||
|             } | ||||
|             if (operator.getAccess() >= Access.NO_LOGIN) { | ||||
|                 Redirect.error().icon(Redirect.WeUIIcon.WAITING).noButton() | ||||
|                         .title(lang("Left_Operator_Title")).msg(lang("Left_Operator")).go(resp); | ||||
|                 return; | ||||
|             } | ||||
|             session.setAttribute(Attribute.AUTHORIZED, Command.LOGIN); | ||||
|             session.setAttribute(Attribute.WECHAT, user); | ||||
|             session.setAttribute(Attribute.OPERATOR, operator); | ||||
|             resp.sendRedirect(format("Operator_Home_Page", session.getId())); | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -37,23 +37,23 @@ import static love.sola.netsupport.config.Lang.lang; | ||||
|  */ | ||||
| public class OperatorInfoHandler implements WxMpMessageHandler { | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
| 		try { | ||||
| 			Operator op = TableOperator.get(wxMessage.getFromUserName()); | ||||
| 			if (op == null) { | ||||
| 				out.content(lang("Not_Operator")); | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName()); | ||||
|         try { | ||||
|             Operator op = TableOperator.get(wxMessage.getFromUserName()); | ||||
|             if (op == null) { | ||||
|                 out.content(lang("Not_Operator")); | ||||
| //			} else if (op.getAccess() >= Access.NO_LOGIN) { | ||||
| //				out.content(lang("No_Login")); | ||||
| 			} else { | ||||
| 				out.content(format("Operator_Info", op.getId(), op.getName(), op.getAccess(), op.getBlock(), op.getWeek())); | ||||
| 			} | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 			out.content(lang("Login_Error")); | ||||
| 		} | ||||
| 		return out.build(); | ||||
| 	} | ||||
|             } else { | ||||
|                 out.content(format("Operator_Info", op.getId(), op.getName(), op.getAccess(), op.getBlock(), op.getWeek())); | ||||
|             } | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|             out.content(lang("Login_Error")); | ||||
|         } | ||||
|         return out.build(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -35,72 +35,72 @@ import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| /** | ||||
|  * @deprecated limited time only | ||||
|  * @author Sola {@literal <dev@sola.love>} | ||||
|  * @deprecated limited time only | ||||
|  */ | ||||
| @Deprecated | ||||
| public class SignHandler implements WxMpMessageHandler { | ||||
|  | ||||
| 	public static Pattern pat = Pattern.compile("^(?i)Auth (\\d{4})"); | ||||
| 	public static final int INVALID_ID = -1; | ||||
| 	public static final int SIGNED_ID = -2; | ||||
|     public static Pattern pat = Pattern.compile("^(?i)Auth (\\d{4})"); | ||||
|     public static final int INVALID_ID = -1; | ||||
|     public static final int SIGNED_ID = -2; | ||||
|  | ||||
| 	@Override | ||||
| 	public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
| 		String msg = wxMessage.getContent(); | ||||
| 		TextBuilder out = WxMpXmlOutMessage.TEXT().toUser(wxMessage.getFromUserName()).fromUser(wxMessage.getToUserName()); | ||||
| 		Matcher mat = pat.matcher(msg); | ||||
|     @Override | ||||
|     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | ||||
|         String msg = wxMessage.getContent(); | ||||
|         TextBuilder out = WxMpXmlOutMessage.TEXT().toUser(wxMessage.getFromUserName()).fromUser(wxMessage.getToUserName()); | ||||
|         Matcher mat = pat.matcher(msg); | ||||
|  | ||||
| 		root: | ||||
| 		if (mat.find()) { | ||||
| 			int id = Integer.parseInt(mat.group(1)); | ||||
| 			try (Connection conn = SQLCore.ds.getConnection()) { | ||||
| 				switch (checkID(conn, id)) { | ||||
| 					case INVALID_ID: | ||||
| 						out.content("无效ID。"); | ||||
| 						break root; | ||||
| 					case SIGNED_ID: | ||||
| 						out.content("该ID已登记过。"); | ||||
| 						break root; | ||||
| 				} | ||||
| 				if (checkDuplicated(conn, wxMessage.getFromUserName())) { | ||||
| 					out.content("你的微信已经登记过。"); | ||||
| 					break root; | ||||
| 				} | ||||
| 				PreparedStatement ps = conn.prepareStatement("UPDATE auth SET wechat=? WHERE id=?"); | ||||
| 				ps.setString(1, wxMessage.getFromUserName()); | ||||
| 				ps.setInt(2, id); | ||||
| 				if (ps.executeUpdate() == 1) { | ||||
| 					out.content("登记成功。"); | ||||
| 				} else { | ||||
| 					out.content("登记失败,请联系管理员。"); | ||||
| 				} | ||||
| 			} catch (SQLException e) { | ||||
| 				e.printStackTrace(); | ||||
| 				out.content("系统异常,请联系管理员。"); | ||||
| 			} | ||||
| 		} else { | ||||
| 			out.content("无效ID。"); | ||||
| 		} | ||||
| 		return out.build(); | ||||
| 	} | ||||
|         root: | ||||
|         if (mat.find()) { | ||||
|             int id = Integer.parseInt(mat.group(1)); | ||||
|             try (Connection conn = SQLCore.ds.getConnection()) { | ||||
|                 switch (checkID(conn, id)) { | ||||
|                     case INVALID_ID: | ||||
|                         out.content("无效ID。"); | ||||
|                         break root; | ||||
|                     case SIGNED_ID: | ||||
|                         out.content("该ID已登记过。"); | ||||
|                         break root; | ||||
|                 } | ||||
|                 if (checkDuplicated(conn, wxMessage.getFromUserName())) { | ||||
|                     out.content("你的微信已经登记过。"); | ||||
|                     break root; | ||||
|                 } | ||||
|                 PreparedStatement ps = conn.prepareStatement("UPDATE auth SET wechat=? WHERE id=?"); | ||||
|                 ps.setString(1, wxMessage.getFromUserName()); | ||||
|                 ps.setInt(2, id); | ||||
|                 if (ps.executeUpdate() == 1) { | ||||
|                     out.content("登记成功。"); | ||||
|                 } else { | ||||
|                     out.content("登记失败,请联系管理员。"); | ||||
|                 } | ||||
|             } catch (SQLException e) { | ||||
|                 e.printStackTrace(); | ||||
|                 out.content("系统异常,请联系管理员。"); | ||||
|             } | ||||
|         } else { | ||||
|             out.content("无效ID。"); | ||||
|         } | ||||
|         return out.build(); | ||||
|     } | ||||
|  | ||||
| 	private static int checkID(Connection conn, int id) throws SQLException { | ||||
| 		PreparedStatement ps = conn.prepareStatement("SELECT wechat FROM auth WHERE id=?"); | ||||
| 		ps.setInt(1, id); | ||||
| 		ResultSet rs = ps.executeQuery(); | ||||
| 		if (rs.next()) { | ||||
| 			return rs.getString("wechat") != null ? SIGNED_ID : 0; | ||||
| 		} else { | ||||
| 			return INVALID_ID; | ||||
| 		} | ||||
| 	} | ||||
|     private static int checkID(Connection conn, int id) throws SQLException { | ||||
|         PreparedStatement ps = conn.prepareStatement("SELECT wechat FROM auth WHERE id=?"); | ||||
|         ps.setInt(1, id); | ||||
|         ResultSet rs = ps.executeQuery(); | ||||
|         if (rs.next()) { | ||||
|             return rs.getString("wechat") != null ? SIGNED_ID : 0; | ||||
|         } else { | ||||
|             return INVALID_ID; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private static boolean checkDuplicated(Connection conn, String wechat) throws SQLException { | ||||
| 		PreparedStatement ps = conn.prepareStatement("SELECT wechat FROM auth WHERE wechat=?"); | ||||
| 		ps.setString(1, wechat); | ||||
| 		ResultSet rs = ps.executeQuery(); | ||||
| 		return rs.next(); | ||||
| 	} | ||||
|     private static boolean checkDuplicated(Connection conn, String wechat) throws SQLException { | ||||
|         PreparedStatement ps = conn.prepareStatement("SELECT wechat FROM auth WHERE wechat=?"); | ||||
|         ps.setString(1, wechat); | ||||
|         ResultSet rs = ps.executeQuery(); | ||||
|         return rs.next(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,27 +31,27 @@ import java.util.concurrent.TimeUnit; | ||||
|  */ | ||||
| public class CheckSpamMatcher implements WxMpMessageMatcher { | ||||
|  | ||||
| 	private class ValueLoader extends CacheLoader<String, Long> { | ||||
| 		@Override | ||||
| 		public Long load(String key) throws Exception { | ||||
| 			return System.currentTimeMillis() + Settings.I.Check_Spam_Interval; | ||||
| 		} | ||||
| 	} | ||||
|     private class ValueLoader extends CacheLoader<String, Long> { | ||||
|         @Override | ||||
|         public Long load(String key) throws Exception { | ||||
|             return System.currentTimeMillis() + Settings.I.Check_Spam_Interval; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private LoadingCache<String, Long> cache = CacheBuilder.newBuilder() | ||||
| 			.concurrencyLevel(4) | ||||
| 			.maximumSize(4096) | ||||
| 			.expireAfterWrite(Settings.I.Check_Spam_Cache_Expire_Time, TimeUnit.SECONDS) | ||||
| 			.build(new ValueLoader()); | ||||
|     private LoadingCache<String, Long> cache = CacheBuilder.newBuilder() | ||||
|             .concurrencyLevel(4) | ||||
|             .maximumSize(4096) | ||||
|             .expireAfterWrite(Settings.I.Check_Spam_Cache_Expire_Time, TimeUnit.SECONDS) | ||||
|             .build(new ValueLoader()); | ||||
|  | ||||
| 	@Override | ||||
| 	public boolean match(WxMpXmlMessage wxMessage) { | ||||
| 		Long l = cache.getIfPresent(wxMessage.getFromUserName()); | ||||
| 		if (l != null && l > System.currentTimeMillis()) { | ||||
| 			return true; | ||||
| 		} | ||||
| 		cache.refresh(wxMessage.getFromUserName()); | ||||
| 		return false; | ||||
| 	} | ||||
|     @Override | ||||
|     public boolean match(WxMpXmlMessage wxMessage) { | ||||
|         Long l = cache.getIfPresent(wxMessage.getFromUserName()); | ||||
|         if (l != null && l > System.currentTimeMillis()) { | ||||
|             return true; | ||||
|         } | ||||
|         cache.refresh(wxMessage.getFromUserName()); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -29,22 +29,22 @@ import java.util.concurrent.ConcurrentHashMap; | ||||
|  */ | ||||
| public class CommandMatcher implements WxMpMessageMatcher { | ||||
|  | ||||
| 	public static Map<String, Command> inCmdUsers = new ConcurrentHashMap<>(); | ||||
|     public static Map<String, Command> inCmdUsers = new ConcurrentHashMap<>(); | ||||
|  | ||||
| 	Command command; | ||||
|     Command command; | ||||
|  | ||||
| 	public CommandMatcher(Command command) { | ||||
| 		this.command = command; | ||||
| 	} | ||||
|     public CommandMatcher(Command command) { | ||||
|         this.command = command; | ||||
|     } | ||||
|  | ||||
| 	@Override | ||||
| 	public boolean match(WxMpXmlMessage message) { | ||||
| 		String fromUser = message.getFromUserName(); | ||||
| 		if (inCmdUsers.containsKey(fromUser)) { | ||||
| 			return command == inCmdUsers.get(fromUser); | ||||
| 		} else { | ||||
| 			return message.getContent().matches(command.regex); | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     public boolean match(WxMpXmlMessage message) { | ||||
|         String fromUser = message.getFromUserName(); | ||||
|         if (inCmdUsers.containsKey(fromUser)) { | ||||
|             return command == inCmdUsers.get(fromUser); | ||||
|         } else { | ||||
|             return message.getContent().matches(command.regex); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -26,9 +26,9 @@ import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | ||||
|  */ | ||||
| public class RegisterMatcher implements WxMpMessageMatcher { | ||||
|  | ||||
| 	@Override | ||||
| 	public boolean match(WxMpXmlMessage message) { | ||||
| 		return TableUser.getByWechat(message.getFromUserName()) == null; | ||||
| 	} | ||||
|     @Override | ||||
|     public boolean match(WxMpXmlMessage message) { | ||||
|         return TableUser.getByWechat(message.getFromUserName()) == null; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Sola
					Sola