diff --git a/openvidu-call/openvidu-call-back-java/.gitignore b/openvidu-call/openvidu-call-back-java/.gitignore new file mode 100644 index 00000000..950fc085 --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/.gitignore @@ -0,0 +1,24 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +target/ diff --git a/openvidu-call/openvidu-call-back-java/README.md b/openvidu-call/openvidu-call-back-java/README.md new file mode 100644 index 00000000..073cee1e --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/README.md @@ -0,0 +1,25 @@ +# openvidu-basic-java + +This is a minimal OpenVidu server application sample built for Java with Spring Boot. Visit [Application server](https://docs.openvidu.io/en/stable/application-server/) documentation for further context. + +It internally uses [openvidu-java-client SDK](https://docs.openvidu.io/en/stable/reference-docs/openvidu-java-client/). + +## Prerequisites + +- [Java (>=11)](https://www.java.com/en/download/manual.jsp) +- [Maven](https://maven.apache.org) + +## Run + +Download repository + +``` +git clone git@github.com:OpenVidu/openvidu-tutorials.git +cd openvidu-tutorials/openvidu-basic-java +``` + +Run the application + +``` +mvn spring-boot:run +``` \ No newline at end of file diff --git a/openvidu-call/openvidu-call-back-java/pom.xml b/openvidu-call/openvidu-call-back-java/pom.xml new file mode 100644 index 00000000..e7218964 --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/pom.xml @@ -0,0 +1,56 @@ + + 4.0.0 + + io.openvidu + openvidu-call-back-java + 2.22.0 + jar + + openvidu-call-back-java + https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-call/openvidu-call-back-java + + + org.springframework.boot + spring-boot-starter-parent + 2.7.0 + + + + UTF-8 + 11 + 11 + 11 + io.openvidu.basic.java.App + + + + + + org.springframework.boot + spring-boot-starter-web + + + io.openvidu + openvidu-java-client + 2.22.0 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/App.java b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/App.java new file mode 100644 index 00000000..8ad23261 --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/App.java @@ -0,0 +1,13 @@ +package io.openvidu.call.java; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class App { + + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } + +} diff --git a/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/AdminController.java b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/AdminController.java new file mode 100644 index 00000000..621fa47e --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/AdminController.java @@ -0,0 +1,95 @@ +package io.openvidu.call.java.controllers; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.openvidu.call.java.services.OpenViduService; +import io.openvidu.java.client.OpenViduHttpException; +import io.openvidu.java.client.OpenViduJavaClientException; +import io.openvidu.java.client.Recording; + +@CrossOrigin(origins = "*") +@RestController +@RequestMapping("admin") +public class AdminController { + + @Value("${ADMIN_SECRET}") + private String ADMIN_SECRET; + + @Autowired + private OpenViduService openviduService; + + @PostMapping("/login") + public ResponseEntity> login(@RequestBody(required = false) Map params, + @CookieValue(name = OpenViduService.RECORDING_TOKEN_NAME, defaultValue = "") String recordingToken, HttpServletResponse res) { + + Map response = new HashMap(); + + String password = params.get("password"); + String sessionToken = this.openviduService.getSessionIdFromCookie(recordingToken); + boolean isAdminTokenValid = this.openviduService.adminTokens.contains(sessionToken); + + boolean isAuthValid = password.equals(ADMIN_SECRET) || isAdminTokenValid; + if (isAuthValid) { + try { + if (sessionToken.isEmpty() || !openviduService.adminTokens.contains(sessionToken)) { + // Save session token + String token = UUID.randomUUID().toString(); + + Cookie cookie = new Cookie(OpenViduService.ADMIN_TOKEN_NAME, token); + cookie.setPath("/"); + res.addCookie(cookie); + + cookie = new Cookie("session", token); + cookie.setPath("/"); + res.addCookie(cookie); + + openviduService.adminTokens.add(token); + } + List recordings = openviduService.listAllRecordings(); + System.out.println("Login succeeded"); + System.out.println(recordings.size() + " Recordings found"); + response.put("recordings", recordings); + + return new ResponseEntity<>(response, HttpStatus.OK); + } catch (OpenViduJavaClientException | OpenViduHttpException error) { + + error.printStackTrace(); + System.err.println(error.getMessage() + "Unexpected error getting recordings"); + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + System.err.println("Permissions denied"); + return new ResponseEntity<>(null, HttpStatus.FORBIDDEN); + } + + } + + @PostMapping("/logout") + public ResponseEntity logout(@RequestBody(required = false) Map params, + @CookieValue(name = "session", defaultValue = "") String sessionToken, + HttpServletResponse res) { + this.openviduService.adminTokens.remove(sessionToken); + Cookie cookie = new Cookie("session", null); + res.addCookie(cookie); + return new ResponseEntity<>(null, HttpStatus.OK); + + } + +} diff --git a/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/RecordingController.java b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/RecordingController.java new file mode 100644 index 00000000..d3433c17 --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/RecordingController.java @@ -0,0 +1,227 @@ +package io.openvidu.call.java.controllers; + +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.openvidu.call.java.services.OpenViduService; +import io.openvidu.call.java.services.ProxyService; +import io.openvidu.java.client.OpenViduHttpException; +import io.openvidu.java.client.OpenViduJavaClientException; +import io.openvidu.java.client.Recording; + +@CrossOrigin(origins = "*") +@RestController +@RequestMapping("/recordings") +public class RecordingController { + + @Value("${RECORDING}") + private String RECORDING; + + @Autowired + private OpenViduService openviduService; + + @Autowired + private ProxyService proxyService; + + @GetMapping("") + public ResponseEntity> getRecordings( + @CookieValue(name = OpenViduService.RECORDING_TOKEN_NAME, defaultValue = "") String recordingToken) { + try { + List recordings = new ArrayList(); + boolean IS_RECORDING_ENABLED = RECORDING.toUpperCase().equals("ENABLED"); + String sessionId = openviduService.getSessionIdFromCookie(recordingToken); + boolean isAdminDashboard = openviduService.adminTokens.contains(sessionId); + + if ((!sessionId.isEmpty() && IS_RECORDING_ENABLED + && openviduService.isValidToken(sessionId, recordingToken)) || isAdminDashboard) { + if (isAdminDashboard) { + recordings = this.openviduService.listAllRecordings(); + } else { + long date = openviduService.getDateFromCookie(recordingToken); + recordings = openviduService.listRecordingsBySessionIdAndDate(sessionId, date); + } + return new ResponseEntity<>(recordings, HttpStatus.OK); + } else { + String message = IS_RECORDING_ENABLED ? "Permissions denied to drive recording" + : "Recording is disabled"; + System.err.println(message); + return new ResponseEntity<>(null, HttpStatus.FORBIDDEN); + + } + } catch (OpenViduJavaClientException | OpenViduHttpException error) { + error.printStackTrace(); + int code = Integer.parseInt(error.getMessage()); + String message = "Unexpected error getting all recordings"; + if (code == 404) { + message = "No recording exist for the session"; + } + System.err.println(message); + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + + } + + @PostMapping("/start") + public ResponseEntity startRecording(@RequestBody(required = false) Map params, + @CookieValue(name = OpenViduService.RECORDING_TOKEN_NAME, defaultValue = "") String recordingToken) { + + try { + String sessionId = params.get("sessionId"); + if (openviduService.isValidToken(sessionId, recordingToken)) { + Recording startingRecording = openviduService.startRecording(sessionId); + openviduService.recordingMap.get(sessionId).setRecordingId(startingRecording.getId()); + System.out.println("Starting recording in " + sessionId); + return new ResponseEntity<>(startingRecording, HttpStatus.OK); + + } else { + + System.out.println("Permissions denied for starting recording in session " + sessionId); + return new ResponseEntity<>(null, HttpStatus.FORBIDDEN); + } + } catch (OpenViduJavaClientException | OpenViduHttpException error) { + error.printStackTrace(); + int code = Integer.parseInt(error.getMessage()); + String message = "Unexpected error starting recording"; + if (code == 409) { + message = "The session is already being recorded."; + } else if (code == 501) { + message = "OpenVidu Server recording module is disabled"; + } else if (code == 406) { + message = "The session has no connected participants"; + } + System.err.println(message); + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + + } + + } + + @PostMapping("/stop") + public ResponseEntity> stopRecording(@RequestBody(required = false) Map params, + @CookieValue(name = OpenViduService.RECORDING_TOKEN_NAME, defaultValue = "") String recordingToken) { + try { + String sessionId = params.get("sessionId"); + if (openviduService.isValidToken(sessionId, recordingToken)) { + String recordingId = openviduService.recordingMap.get(sessionId).getRecordingId(); + + if (!recordingId.isEmpty()) { + System.out.println("Stopping recording in " + sessionId); + openviduService.stopRecording(recordingId); + long date = openviduService.getDateFromCookie(recordingToken); + List recordingList = openviduService.listRecordingsBySessionIdAndDate(sessionId, date); + openviduService.recordingMap.get(sessionId).setRecordingId(""); + return new ResponseEntity<>(recordingList, HttpStatus.OK); + } else { + System.err.println("Session was not being recorded"); + return new ResponseEntity<>(null, HttpStatus.NOT_FOUND); + } + } else { + System.err.println("Permissions denied to drive recording"); + return new ResponseEntity<>(null, HttpStatus.FORBIDDEN); + } + } catch (OpenViduJavaClientException | OpenViduHttpException error) { + error.printStackTrace(); + int code = Integer.parseInt(error.getMessage()); + String message = "Unexpected error stopping recording"; + if (code == 501) { + message = "OpenVidu Server recording module is disabled"; + } else if (code == 406) { + message = "Recording has STARTING status. Wait until STARTED status before stopping the recording"; + } + System.err.println(message); + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @DeleteMapping("/delete/{recordingId}") + public ResponseEntity> deleteRecording(@PathVariable String recordingId, + @CookieValue(name = OpenViduService.RECORDING_TOKEN_NAME, defaultValue = "") String recordingToken, + @CookieValue(name = "session", defaultValue = "") String sessionToken) { + try { + List recordings = new ArrayList(); + String sessionId = openviduService.getSessionIdFromCookie(recordingToken); + boolean isAdminDashboard = openviduService.adminTokens.contains(sessionToken); + + if ((!sessionId.isEmpty() && openviduService.isValidToken(sessionId, recordingToken)) || isAdminDashboard) { + if (recordingId.isEmpty()) { + System.err.println("Missing recording id parameter."); + return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); + } + + System.out.println("Deleting recording " + recordingId); + openviduService.deleteRecording(recordingId); + if (isAdminDashboard && !sessionToken.isEmpty()) { + recordings = openviduService.listAllRecordings(); + } else { + long date = openviduService.getDateFromCookie(recordingToken); + recordings = openviduService.listRecordingsBySessionIdAndDate(sessionId, date); + } + return new ResponseEntity<>(recordings, HttpStatus.OK); + + } else { + System.err.println("Permissions denied to drive recording"); + return new ResponseEntity<>(recordings, HttpStatus.FORBIDDEN); + } + } catch (OpenViduJavaClientException | OpenViduHttpException error) { + error.printStackTrace(); + int code = Integer.parseInt(error.getMessage()); + String message = "Unexpected error deleting the recording"; + if (code == 409) { + message = "The recording has STARTED status. Stop it before deletion."; + } else if (code == 501) { + message = "OpenVidu Server recording module is disabled"; + } else if (code == 409) { + message = "No recording exists for the session"; + } + System.err.println(message); + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @GetMapping("/{recordingId}/{extension}") + public ResponseEntity getRecording(@PathVariable String recordingId, @PathVariable String extension, + @CookieValue(name = OpenViduService.RECORDING_TOKEN_NAME, defaultValue = "") String recordingToken, + @CookieValue(name = "session", defaultValue = "") String sessionToken, HttpServletRequest req, HttpServletResponse res) { + + boolean isAdminDashboard = openviduService.adminTokens.contains(sessionToken); + String sessionId = this.openviduService.getSessionIdFromCookie(recordingToken); + if ((!sessionId.isEmpty() && openviduService.isValidToken(sessionId, recordingToken)) || isAdminDashboard) { + if (recordingId.isEmpty()) { + System.err.println("Missing recording id parameter."); + return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); + } else { + try { + return proxyService.processProxyRequest(req, res); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + System.err.println("Permissions denied to drive recording"); + return new ResponseEntity<>(null, HttpStatus.FORBIDDEN); + } + + } + + +} diff --git a/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/SessionController.java b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/SessionController.java new file mode 100644 index 00000000..daa9e8fc --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/controllers/SessionController.java @@ -0,0 +1,126 @@ +package io.openvidu.call.java.controllers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import io.openvidu.call.java.models.RecordingData; +import io.openvidu.call.java.services.OpenViduService; +import io.openvidu.java.client.Connection; +import io.openvidu.java.client.OpenViduHttpException; +import io.openvidu.java.client.OpenViduJavaClientException; +import io.openvidu.java.client.OpenViduRole; +import io.openvidu.java.client.Recording; +import io.openvidu.java.client.Session; + +@CrossOrigin(origins = "*") +@RestController +public class SessionController { + + + @Value("${RECORDING}") + private String RECORDING; + + + @Autowired + private OpenViduService openviduService; + + + @PostMapping("/sessions") + public ResponseEntity> createConnection(@RequestBody(required = false) Map params, + @CookieValue(name = OpenViduService.RECORDING_TOKEN_NAME, defaultValue = "") String recordingTokenCookie, + HttpServletResponse res) { + + Map response = new HashMap(); + try { + long date = -1; + String nickname = ""; + + String sessionId = params.get("sessionId").toString(); + if(params.containsKey("nickname")) { + nickname = params.get("nickname").toString(); + } + + Session sessionCreated = this.openviduService.createSession(sessionId); + boolean IS_RECORDING_ENABLED = RECORDING.toUpperCase().equals("ENABLED"); + + boolean hasValidToken = this.openviduService.isValidToken(sessionId, recordingTokenCookie); + boolean isSessionCreator = hasValidToken || sessionCreated.getActiveConnections().size() == 0; + + OpenViduRole role = isSessionCreator && IS_RECORDING_ENABLED ? OpenViduRole.MODERATOR : OpenViduRole.PUBLISHER; + + response.put("recordingEnabled", IS_RECORDING_ENABLED); + response.put("recordings", new ArrayList()); + + + Connection cameraConnection = this.openviduService.createConnection(sessionCreated, nickname, role); + Connection screenConnection = this.openviduService.createConnection(sessionCreated, nickname, role); + + response.put("cameraToken", cameraConnection.getToken()); + response.put("screenToken", screenConnection.getToken()); + + if (IS_RECORDING_ENABLED && isSessionCreator && !hasValidToken) { + /** + * ! *********** WARN *********** ! + * + * To identify who is able to manage session recording, the code sends a cookie with a token to the session creator. + * The relation between cookies and sessions are stored in backend memory. + * + * This authentication & authorization system is pretty basic and it is not for production. + * We highly recommend IMPLEMENT YOUR OWN USER MANAGEMENT with persistence for a properly and secure recording feature. + * + * ! *********** WARN *********** ! + **/ + + String uuid = UUID.randomUUID().toString(); + date = System.currentTimeMillis(); + String recordingToken = cameraConnection.getToken() + "&" + OpenViduService.RECORDING_TOKEN_NAME + "=" + uuid + "&createdAt=" +date; + + Cookie cookie = new Cookie(OpenViduService.RECORDING_TOKEN_NAME, recordingToken); + res.addCookie(cookie); + + RecordingData recData = new RecordingData(recordingToken, ""); + this.openviduService.recordingMap.put(sessionId, recData); + } + + if(IS_RECORDING_ENABLED){ + if(date == -1) { + date = openviduService.getDateFromCookie(recordingTokenCookie); + } + List recordings = openviduService.listRecordingsBySessionIdAndDate(sessionId, date); + response.put("recordings", recordings); + } + + return new ResponseEntity<>(response, HttpStatus.OK); + + + } catch (OpenViduJavaClientException | OpenViduHttpException e) { + + if(Integer.parseInt(e.getMessage()) == 501) { + System.err.println("OpenVidu Server recording module is disabled"); + response.put("recordingEnabled", false); + return new ResponseEntity<>(response, HttpStatus.OK); + } else { + e.printStackTrace(); + System.out.println(e.getMessage()); + return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + } + } + +} diff --git a/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/models/RecordingData.java b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/models/RecordingData.java new file mode 100644 index 00000000..d5e2c697 --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/models/RecordingData.java @@ -0,0 +1,25 @@ +package io.openvidu.call.java.models; + +public class RecordingData { + + String token; + String recordingId; + public RecordingData(String token, String recordingId) { + super(); + this.token = token; + this.recordingId = recordingId; + } + public String getToken() { + return token; + } + public void setToken(String token) { + this.token = token; + } + public String getRecordingId() { + return recordingId; + } + public void setRecordingId(String recordingId) { + this.recordingId = recordingId; + } + +} diff --git a/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/services/OpenViduService.java b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/services/OpenViduService.java new file mode 100644 index 00000000..e018d5b3 --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/services/OpenViduService.java @@ -0,0 +1,171 @@ +package io.openvidu.call.java.services; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.PostConstruct; + +import org.apache.commons.codec.binary.Base64; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; + +import io.openvidu.call.java.models.RecordingData; +import io.openvidu.java.client.Connection; +import io.openvidu.java.client.ConnectionProperties; +import io.openvidu.java.client.OpenVidu; +import io.openvidu.java.client.OpenViduHttpException; +import io.openvidu.java.client.OpenViduJavaClientException; +import io.openvidu.java.client.OpenViduRole; +import io.openvidu.java.client.Recording; +import io.openvidu.java.client.Session; +import io.openvidu.java.client.SessionProperties; + +@Service +public class OpenViduService { + + public static final String RECORDING_TOKEN_NAME = "ovCallRecordingToken"; + public static final String ADMIN_TOKEN_NAME = "ovCallAdminToken"; + public Map recordingMap = new HashMap(); + public List adminTokens = new ArrayList(); + + @Value("${OPENVIDU_URL}") + public String OPENVIDU_URL; + + @Value("${OPENVIDU_SECRET}") + private String OPENVIDU_SECRET; + + private OpenVidu openvidu; + + @PostConstruct + public void init() { + this.openvidu = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); + } + + public String getBasicAuth() { + String stringToEncode = "OPENVIDUAPP:" + OPENVIDU_SECRET; + byte[] encodedString = Base64.encodeBase64(stringToEncode.getBytes()); + return "Basic " + new String(encodedString); + } + + public long getDateFromCookie(String recordingToken) { + + if (!recordingToken.isEmpty()) { + MultiValueMap cookieTokenParams = UriComponentsBuilder.fromUriString(recordingToken).build() + .getQueryParams(); + String date = cookieTokenParams.get("createdAt").get(0); + return Long.parseLong(date); + } else { + return System.currentTimeMillis(); + } + } + + public String getSessionIdFromCookie(String cookie) { + try { + + if (!cookie.isEmpty()) { + MultiValueMap cookieTokenParams = UriComponentsBuilder.fromUriString(cookie) + .build().getQueryParams(); + return cookieTokenParams.get("sessionId").get(0); + } + + } catch (Exception error) { + System.out.println("Recording cookie not found"); + System.err.println(error); + } + return ""; + + } + + public boolean isValidToken(String sessionId, String recordingToken) { + try { + + if (!recordingToken.isEmpty()) { + MultiValueMap storedTokenParams = null; + + if(this.recordingMap.containsKey(sessionId)) { + storedTokenParams = UriComponentsBuilder + .fromUriString(this.recordingMap.get(sessionId).getToken()).build().getQueryParams(); + } + + MultiValueMap cookieTokenParams = UriComponentsBuilder + .fromUriString(recordingToken).build().getQueryParams(); + + if (!cookieTokenParams.isEmpty() && storedTokenParams != null) { + String cookieSessionId = cookieTokenParams.get("sessionId").get(0); + String cookieToken = cookieTokenParams.get(RECORDING_TOKEN_NAME).get(0); + String cookieDate = cookieTokenParams.get("createdAt").get(0); + + String storedToken = storedTokenParams.get(RECORDING_TOKEN_NAME).get(0); + String storedDate = storedTokenParams.get("createdAt").get(0); + + return sessionId.equals(cookieSessionId) && cookieToken.equals(storedToken) && cookieDate.equals(storedDate); + } + } + + return false; + } catch (Exception e) { + return false; + } + } + + public Session createSession(String sessionId) throws OpenViduJavaClientException, OpenViduHttpException { + Map params = new HashMap(); + params.put("customSessionId", sessionId); + SessionProperties properties = SessionProperties.fromJson(params).build(); + Session session = openvidu.createSession(properties); + session.fetch(); + return session; + } + + public Connection createConnection(Session session, String nickname, OpenViduRole role) + throws OpenViduJavaClientException, OpenViduHttpException { + Map params = new HashMap(); + Map connectionData = new HashMap(); + + if (!nickname.isEmpty()) { + connectionData.put("openviduCustomConnectionId", nickname); + } + params.put("role", role.name()); + params.put("data", connectionData.toString()); + ConnectionProperties properties = ConnectionProperties.fromJson(params).build(); + return session.createConnection(properties); + + } + + public Recording startRecording(String sessionId) throws OpenViduJavaClientException, OpenViduHttpException { + return this.openvidu.startRecording(sessionId); + } + + public Recording stopRecording(String recordingId) throws OpenViduJavaClientException, OpenViduHttpException { + return this.openvidu.stopRecording(recordingId); + } + + public void deleteRecording(String recordingId) throws OpenViduJavaClientException, OpenViduHttpException { + this.openvidu.deleteRecording(recordingId); + } + + public Recording getRecording(String recordingId) throws OpenViduJavaClientException, OpenViduHttpException { + return this.openvidu.getRecording(recordingId); + } + + public List listAllRecordings() throws OpenViduJavaClientException, OpenViduHttpException { + return this.openvidu.listRecordings(); + } + + public List listRecordingsBySessionIdAndDate(String sessionId, long date) + throws OpenViduJavaClientException, OpenViduHttpException { + List recordings = this.listAllRecordings(); + List recordingsAux = new ArrayList(); + for (Recording recording : recordings) { + if (recording.getSessionId().equals(sessionId) && date <= recording.getCreatedAt()) { + recordingsAux.add(recording); + } + } + return recordingsAux; + } + +} diff --git a/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/services/ProxyService.java b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/services/ProxyService.java new file mode 100644 index 00000000..28183a2b --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/main/java/io/openvidu/call/java/services/ProxyService.java @@ -0,0 +1,67 @@ +package io.openvidu.call.java.services; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +@Service +public class ProxyService { + + @Value("${OPENVIDU_URL}") + public String OPENVIDU_URL; + + @Autowired + private OpenViduService openviduService; + + public ResponseEntity processProxyRequest(HttpServletRequest request, HttpServletResponse response) + throws URISyntaxException { + + String requestUrl = request.getRequestURI(); + + URI uri = UriComponentsBuilder.fromUriString(OPENVIDU_URL).path(requestUrl).query(request.getQueryString()).build(true).toUri(); + + HttpHeaders headers = new HttpHeaders(); + Enumeration headerNames = request.getHeaderNames(); + + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + headers.set(headerName, request.getHeader(headerName)); + } + + headers.add("Authorization", this.openviduService.getBasicAuth()); + + headers.remove(HttpHeaders.ACCEPT_ENCODING); + + HttpEntity httpEntity = new HttpEntity<>(null, headers); + ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()); + RestTemplate restTemplate = new RestTemplate(factory); + try { + + return restTemplate.exchange(uri, HttpMethod.GET, httpEntity, byte[].class); + + } catch (HttpStatusCodeException e) { + System.err.println(e.getMessage()); + System.err.println(e.getRawStatusCode()); + return ResponseEntity.status(e.getRawStatusCode()).headers(e.getResponseHeaders()) + .body(e.getResponseBodyAsString()); + } + + } +} diff --git a/openvidu-call/openvidu-call-back-java/src/main/resources/application.properties b/openvidu-call/openvidu-call-back-java/src/main/resources/application.properties new file mode 100644 index 00000000..af4c8394 --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/main/resources/application.properties @@ -0,0 +1,8 @@ +server.port: 5000 +server.ssl.enabled: false + +OPENVIDU_URL: https://demos.openvidu.io +OPENVIDU_SECRET: MY_SECRET + +RECORDING: ENABLED +ADMIN_SECRET: MY_SECRET diff --git a/openvidu-call/openvidu-call-back-java/src/test/java/io/openvidu/basic/java/AppTests.java b/openvidu-call/openvidu-call-back-java/src/test/java/io/openvidu/basic/java/AppTests.java new file mode 100644 index 00000000..b341cf0e --- /dev/null +++ b/openvidu-call/openvidu-call-back-java/src/test/java/io/openvidu/basic/java/AppTests.java @@ -0,0 +1,13 @@ +package io.openvidu.basic.java; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AppTests { + + @Test + void contextLoads() { + } + +}