From f633ce604ab3a2b0a88d75ed052505a75fed5a5b Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 2 Mar 2018 13:19:17 -0500 Subject: [PATCH] http-service: add session service --- .../service/session/SessionController.java | 95 ++++++++++++++ .../http/service/session/SessionEntry.java | 39 ++++++ .../http/service/session/SessionService.java | 118 ++++++++++++++++++ .../runelite/http/service/session/session.sql | 46 +++++++ 4 files changed, 298 insertions(+) create mode 100644 http-service/src/main/java/net/runelite/http/service/session/SessionController.java create mode 100644 http-service/src/main/java/net/runelite/http/service/session/SessionEntry.java create mode 100644 http-service/src/main/java/net/runelite/http/service/session/SessionService.java create mode 100644 http-service/src/main/resources/net/runelite/http/service/session/session.sql diff --git a/http-service/src/main/java/net/runelite/http/service/session/SessionController.java b/http-service/src/main/java/net/runelite/http/service/session/SessionController.java new file mode 100644 index 0000000000..8b653f2c65 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/session/SessionController.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.session; + +import java.time.Instant; +import java.util.UUID; +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/session") +public class SessionController +{ + private final SessionService sessionService; + + @Autowired + public SessionController(SessionService sessionService) + { + this.sessionService = sessionService; + } + + @RequestMapping + public UUID get(HttpServletRequest request) + { + UUID uuid = UUID.randomUUID(); + String addr = request.getRemoteAddr(); + Instant now = Instant.now(); + SessionEntry sessionEntry = new SessionEntry(); + sessionEntry.setUuid(uuid); + sessionEntry.setIp(addr); + sessionEntry.setStart(now); + sessionEntry.setLast(now); + sessionService.createSession(sessionEntry); + return uuid; + } + + @RequestMapping("/ping") + public ResponseEntity ping(@RequestParam("session") UUID uuid) + { + SessionEntry sessionEntry = sessionService.findSessionByUUID(uuid); + if (sessionEntry == null) + { + return ResponseEntity.notFound().build(); + } + + sessionService.updateLast(uuid); + return ResponseEntity.ok().build(); + } + + @DeleteMapping + public ResponseEntity delete(@RequestParam("session") UUID uuid, HttpServletRequest request) + { + SessionEntry sessionEntry = sessionService.findSessionByUUID(uuid); + if (sessionEntry == null) + { + return ResponseEntity.notFound().build(); + } + + sessionService.deleteSession(sessionEntry); + return ResponseEntity.ok().build(); + } + + @RequestMapping("/count") + public int count() + { + return sessionService.getCount(); + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/session/SessionEntry.java b/http-service/src/main/java/net/runelite/http/service/session/SessionEntry.java new file mode 100644 index 0000000000..28e67d72af --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/session/SessionEntry.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.session; + +import java.time.Instant; +import java.util.UUID; +import lombok.Data; + +@Data +public class SessionEntry +{ + private int id; + private UUID uuid; + private String ip; + private Instant start; + private Instant last; +} diff --git a/http-service/src/main/java/net/runelite/http/service/session/SessionService.java b/http-service/src/main/java/net/runelite/http/service/session/SessionService.java new file mode 100644 index 0000000000..4c056135c8 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/session/SessionService.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.session; + +import java.time.Instant; +import java.util.UUID; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.sql2o.Connection; +import org.sql2o.Sql2o; + +@Service +public class SessionService +{ + private final Sql2o sql2o; + + @Autowired + public SessionService( + @Qualifier("Runelite SQL2O") Sql2o sql2o + ) + { + this.sql2o = sql2o; + } + + public void createSession(SessionEntry session) + { + try (Connection con = sql2o.open()) + { + con.createQuery("insert into session (uuid, ip, start, last) " + + "values (:uuid, :ip, :start, :last)") + .addParameter("uuid", session.getUuid().toString()) + .addParameter("ip", session.getIp()) + .addParameter("start", session.getStart()) + .addParameter("last", session.getLast()) + .executeUpdate(); + } + } + + public SessionEntry findSessionByUUID(UUID id) + { + try (Connection con = sql2o.open()) + { + return con.createQuery("select uuid, ip, start, last from session where uuid = :uuid") + .addParameter("uuid", id.toString()) + .executeAndFetchFirst(SessionEntry.class); + } + } + + public void deleteSession(SessionEntry session) + { + try (Connection con = sql2o.open()) + { + con.createQuery("delete from session where uuid = :uuid") + .addParameter("uuid", session.getUuid().toString()) + .executeUpdate(); + } + } + + public void updateLast(UUID session) + { + try (Connection con = sql2o.open()) + { + Instant last = Instant.now(); + con.createQuery("update session set last = :last where uuid = :uuid") + .addParameter("last", last) + .addParameter("uuid", session.toString()) + .executeUpdate(); + } + } + + private void deleteExpired() + { + try (Connection con = sql2o.open()) + { + con.createQuery("delete from session where last + interval 2 minute < current_timestamp()") + .executeUpdate(); + } + } + + public int getCount() + { + try (Connection con = sql2o.open()) + { + return con.createQuery("select count(*) from session") + .executeScalar(Integer.class); + } + } + + @Scheduled(fixedDelay = 60000) + public void expire() + { + deleteExpired(); + } +} diff --git a/http-service/src/main/resources/net/runelite/http/service/session/session.sql b/http-service/src/main/resources/net/runelite/http/service/session/session.sql new file mode 100644 index 0000000000..880bb17b13 --- /dev/null +++ b/http-service/src/main/resources/net/runelite/http/service/session/session.sql @@ -0,0 +1,46 @@ +-- MySQL dump 10.16 Distrib 10.2.9-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: runelite +-- ------------------------------------------------------ +-- Server version 10.2.9-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `session` +-- + +DROP TABLE IF EXISTS `session`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `session` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `uuid` varchar(36) NOT NULL, + `ip` varchar(39) NOT NULL, + `start` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `last` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`), + UNIQUE KEY `uuid` (`uuid`), + KEY `last` (`last`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2018-03-02 13:23:39