package dev.peerat.backend; import static dev.peerat.framework.RequestType.OPTIONS; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import dev.peerat.backend.bonus.extract.RouteExtracter; import dev.peerat.backend.model.Completion; import dev.peerat.backend.model.Group; import dev.peerat.backend.model.PeerAtUser; import dev.peerat.backend.repository.DatabaseRepository; import dev.peerat.backend.routes.BadgeDetails; import dev.peerat.backend.routes.ChapterElement; import dev.peerat.backend.routes.ChapterList; import dev.peerat.backend.routes.DynamicLeaderboard; import dev.peerat.backend.routes.Leaderboard; import dev.peerat.backend.routes.PlayerDetails; import dev.peerat.backend.routes.PuzzleElement; import dev.peerat.backend.routes.PuzzleResponse; import dev.peerat.backend.routes.Result; import dev.peerat.backend.routes.Swagger; import dev.peerat.backend.routes.admins.DynamicLogs; import dev.peerat.backend.routes.admins.ExceptionLogs; import dev.peerat.backend.routes.admins.WebHookLeaderboard; import dev.peerat.backend.routes.admins.chapter.AddChapter; import dev.peerat.backend.routes.admins.chapter.DeleteChapter; import dev.peerat.backend.routes.admins.chapter.EditChapter; import dev.peerat.backend.routes.admins.chapter.GetChapter; import dev.peerat.backend.routes.admins.puzzle.AddPuzzle; import dev.peerat.backend.routes.admins.puzzle.DeletePuzzle; import dev.peerat.backend.routes.admins.puzzle.EditPuzzle; import dev.peerat.backend.routes.admins.puzzle.GetPuzzle; import dev.peerat.backend.routes.admins.puzzle.GetPuzzles; import dev.peerat.backend.routes.admins.tag.AddTag; import dev.peerat.backend.routes.admins.tag.DeleteTag; import dev.peerat.backend.routes.admins.tag.EditTag; import dev.peerat.backend.routes.admins.tag.GetTags; import dev.peerat.backend.routes.groups.GroupCreate; import dev.peerat.backend.routes.groups.GroupJoin; import dev.peerat.backend.routes.groups.GroupList; import dev.peerat.backend.routes.groups.GroupQuit; import dev.peerat.backend.routes.users.ChangePassword; import dev.peerat.backend.routes.users.ForgotPassword; import dev.peerat.backend.routes.users.Login; import dev.peerat.backend.routes.users.MailConfirmation; import dev.peerat.backend.routes.users.ProfileSettings; import dev.peerat.backend.routes.users.Register; import dev.peerat.backend.utils.Mail; import dev.peerat.framework.Context; import dev.peerat.framework.HttpReader; import dev.peerat.framework.HttpWriter; import dev.peerat.framework.Locker; import dev.peerat.framework.Locker.Key; import dev.peerat.framework.RequestType; import dev.peerat.framework.Response; import dev.peerat.framework.Route; import dev.peerat.framework.RouteInterceptor; import dev.peerat.framework.Router; import dev.peerat.framework.utils.json.JsonMap; import dev.peerat.framework.utils.json.JsonParser; public class Main{ private static Router ACCESS_ROUTER; public static void main(String[] args) throws Exception{ Configuration config = new Configuration("config.txt") .addDefaultValue("users_files", "/tmp/users_files"); config.load(); Class.forName("com.mysql.cj.jdbc.Driver"); DatabaseRepository repo = new DatabaseRepository(config); Router router = new Router() .activeReOrdering(). addDefaultHeaders(RequestType.GET, "Access-Control-Allow-Origin: *"). addDefaultHeaders(RequestType.POST, "Access-Control-Allow-Origin: *"). addDefaultHeaders(RequestType.OPTIONS, "Access-Control-Allow-Origin: *", "Access-Control-Allow-Methods: *", "Access-Control-Allow-Headers: *"); ACCESS_ROUTER = router; if(config.getJwtKey() != null){ JsonParser parser = new JsonParser(); JsonMap json = parser.parse(config.getJwtKey()); Map params = new HashMap<>(); for(Entry entry : json.entries()) params.put(entry.getKey(), entry.getValue()); router.configureJwt( (builder) -> builder.setExpectedIssuer(config.getTokenIssuer()), (claims) -> { claims.setIssuer(config.getTokenIssuer()); claims.setExpirationTimeMinutesInTheFuture(config.getTokenExpiration()); }, (claims) -> new PeerAtUser(claims), params); }else{ router.configureJwt( (builder) -> builder.setExpectedIssuer(config.getTokenIssuer()), (claims) -> { claims.setIssuer(config.getTokenIssuer()); claims.setExpirationTimeMinutesInTheFuture(config.getTokenExpiration()); }, (claims) -> new PeerAtUser(claims)); JsonMap json = new JsonMap(); for(Entry entry : router.exportJwtKey().entrySet()){ json.set(entry.getKey(), entry.getValue()); } config.setJwtKey(json.toString()); config.save(); } router.setDefault((matcher, context, reader, writer) -> { context.response(404); writer.write("404 not Found.\n"); }); router.register(new Response(){ @Route(path = "^(.*)$", type = OPTIONS) public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { context.response(200); } }); initRoutes(router, repo, config); router.addInterceptor(new RouteInterceptor(){ @Override public boolean intercept(Matcher matcher, Context context, HttpReader reader, HttpWriter writer, Method method){ if(method.getDeclaringClass().getPackage().getName().contains(".admins")){ try { Group group = repo.getPlayerGroup(context.getUser().getId(), 1); if(!group.getName().equalsIgnoreCase("Quarter-Master - Battles PAC x CEI")){ context.response(401); return false; } }catch(Exception ex){ ex.printStackTrace(); try{ context.response(401); }catch(Exception e){} return false; } } return true; } }); new Thread(new Runnable(){ public void run(){ Key key = new Key(); Locker locker = router.getLogger(); locker.init(key); try { while(true){ locker.lock(key); Context instance = locker.getValue(key); if(instance == null) continue; System.out.println("["+((instance.isLogged()) ? repo.getPlayer(instance.getUser().getId()).getPseudo() : "?")+"] "+instance.getType()+" "+instance.getPath()+" -> "+instance.getResponseCode()); } }catch(Exception e){ e.printStackTrace(); } locker.remove(key); } }).start(); if(config.useSsl()) router.configureSSL(config.getSslKeystore(), config.getSslKeystorePasswd()); router.listen(config.getTcpPort(), config.useSsl()); } private static void initRoutes(Router router, DatabaseRepository repo, Configuration config) throws Exception{ Map playersWaiting = new HashMap<>(); Mail mail = config.getMail(); Locker groupLock = new Locker<>(); Locker leaderboard = new Locker<>(); if(config.isProduction()) router. register(new Register(repo, playersWaiting, mail)). register(new MailConfirmation(repo, router, config.getUsersFiles(), config.getGitToken(), playersWaiting, mail)); router. register(new Login(repo, router)). register(new ProfileSettings(repo)). register(new ChangePassword(repo)). register(new ForgotPassword(router, repo, mail)). register(new DynamicLogs(router.getLogger(), repo)). register(new ExceptionLogs(router.getExceptionLogger())). register(new AddChapter(repo)). register(new DeleteChapter(repo)). register(new EditChapter(repo)). register(new GetChapter(repo)). register(new AddPuzzle(repo)). register(new DeletePuzzle(repo)). register(new EditPuzzle(repo)). register(new GetPuzzle(repo)). register(new GetPuzzles(repo)). register(new AddTag(repo)). register(new DeleteTag(repo)). register(new EditTag(repo)). register(new GetTags(repo)). register(new WebHookLeaderboard(leaderboard)). register(new ChapterElement(repo)). register(new ChapterList(repo)). register(new PuzzleElement(repo)). register(new Result(repo)). register(new Leaderboard(repo)). register(new PlayerDetails(repo)). register(new BadgeDetails(repo)). register(new DynamicLeaderboard(repo, leaderboard)). register(new PuzzleResponse(repo, config.getUsersFiles(), leaderboard)). register(new GroupCreate(repo, groupLock, config.getGroupJoinMinutes())). register(new GroupList(repo)). register(new GroupJoin(repo, config.getGroupJoinMinutes(), config.getGroupQuitMinutes(), leaderboard)). register(new GroupQuit(repo, config.getGroupJoinMinutes(), leaderboard)) .register(new Swagger(new RouteExtracter(router),config.getTokenIssuer())); // Bot bot = new Bot(config, repo, groupLock); // bot.start(); } }