From 6a70ef515b7c48a88a05bf982f7c37f5407597e7 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 16 Jun 2017 13:23:12 +0200 Subject: [PATCH] openvidu-mvc-node README updated --- openvidu-js-node/README.md | 8 +- openvidu-js-node/server.js | 2 +- openvidu-mvc-java/README.md | 2 +- .../src/main/resources/templates/session.html | 4 +- openvidu-mvc-node/README.md | 404 ++++++++++++++++++ openvidu-mvc-node/server.js | 81 ++-- openvidu-mvc-node/views/dashboard.ejs | 11 +- openvidu-mvc-node/views/index.ejs | 2 +- openvidu-mvc-node/views/leave-session.ejs | 18 - openvidu-mvc-node/views/session.ejs | 4 +- 10 files changed, 463 insertions(+), 73 deletions(-) delete mode 100644 openvidu-mvc-node/views/leave-session.ejs diff --git a/openvidu-js-node/README.md b/openvidu-js-node/README.md index a45e8ab3..922382c4 100644 --- a/openvidu-js-node/README.md +++ b/openvidu-js-node/README.md @@ -32,12 +32,12 @@ OpenVidu is composed by the modules displayed on the image above. sudo apt-get install npm ``` -3. To run the sample application, execute the following commands in the project. They will install the NPM dependencies and will execute `server.js` server passing two arguments: "localhost" as the URL where _openvidu-server_ will be listening and "MY_SECRET" as the secret share with it: +3. To run the sample application, execute the following commands in the project. They will install the NPM dependencies and will execute `server.js` server passing two arguments: "localhost:8443" as the URL where _openvidu-server_ will be listening and "MY_SECRET" as the secret share with it: ```bash cd openvidu-js-node npm install - node server.js localhost MY_SECRET + node server.js localhost:8443 MY_SECRET ``` 4. _openvidu-server_ and _Kurento Media Server_ must be up and running in your development machine. The easiest way is running this Docker container which wraps both of them (you will need [Docker CE](https://store.docker.com/search?type=edition&offering=community)): @@ -50,7 +50,7 @@ OpenVidu is composed by the modules displayed on the image above. ## Understanding the code -This is a very basic web application with a pretty simple vanilla JS/HTML/CSS frontend and a straightforward Node backend with [express](http://expressjs.com/es/). OpenVidu assumes you can identify your users so you can tell which users can connect to which video-calls, and what role (and therefore what permissions) each one of them will have in the calls. You can do this as you prefer. Here our backend will manage the users and their sessions with the easy-to-use and non-intrusive [_express-session_](https://github.com/expressjs/session) API. +This is a very basic web application with a pretty simple vanilla JS/HTML/CSS frontend and a straightforward Node backend with [_express_](http://expressjs.com/es/). OpenVidu assumes you can identify your users so you can tell which users can connect to which video-calls, and what role (and therefore what permissions) each one of them will have in the calls. You can do this as you prefer. Here our backend will manage the users and their sessions with the easy-to-use and non-intrusive [_express-session_](https://github.com/expressjs/session) API. - **Backend**: node server - `server.js` : single file which handles all operations of server. @@ -105,7 +105,7 @@ Let's describe the code following this scenario: a user logs in to the app and c } ``` - `server.js` at `/api-login/login` checks the params are correct and if so sets an active session for the newly logged user (adding a _loggedUser_ attribute with its username in the _req.session_ object): + `server.js` at `/api-login/login` checks the params are correct and if so sets an active session for the newly logged user (adding a _loggedUser_ property with its username in the _req.session_ object): ```javascript app.post('/api-login/login', function (req, res) { diff --git a/openvidu-js-node/server.js b/openvidu-js-node/server.js index f651d353..d5b7af84 100644 --- a/openvidu-js-node/server.js +++ b/openvidu-js-node/server.js @@ -42,7 +42,7 @@ var options = { cert: fs.readFileSync('openviducert.pem') }; https.createServer(options, app).listen(5000); -console.log("App listening on port https://[]:5000"); +console.log("App listening on port https://localhost:5000"); // Mock database var users = [{ diff --git a/openvidu-mvc-java/README.md b/openvidu-mvc-java/README.md index 2841cbdc..db1861d3 100644 --- a/openvidu-mvc-java/README.md +++ b/openvidu-mvc-java/README.md @@ -339,7 +339,7 @@ Let's describe the code following this scenario: a user logs in to the app and c } } ``` - The code executed in `session.html` _< scrpipt >_ tag would also be the same. After the `Session.publish()` method has been succesful, both users will be seeing each other's video, as well as the username and the nickname below it. + The code executed in `session.html` _< script >_ tag would also be the same. After the `Session.publish()` method has been succesful, both users will be seeing each other's video, as well as the username and the nickname below it. 4. **Users leave the video-call** diff --git a/openvidu-mvc-java/src/main/resources/templates/session.html b/openvidu-mvc-java/src/main/resources/templates/session.html index 99cb3f22..32a26815 100644 --- a/openvidu-mvc-java/src/main/resources/templates/session.html +++ b/openvidu-mvc-java/src/main/resources/templates/session.html @@ -34,7 +34,7 @@ console.warn('Request of SESSIONID and TOKEN gone WELL (SESSIONID:' + sessionId + ", TOKEN:" + token + ")"); - // 1) Get an OpenVidu object an initialize a Session + // 1) Get an OpenVidu object and initialize a Session var OV = new OpenVidu(); var session = OV.initSession(sessionId); @@ -87,7 +87,7 @@ function appendUserData(videoElement, connection) { var clientDataJSON = JSON.parse(connection.data.split('%/%')[0]); var serverDataJSON = JSON.parse(connection.data.split('%/%')[1]); - $('

Nickname: ' + clientDataJSON.clientData + + $('

Nickname: ' + clientDataJSON.clientData + '
Username: ' + serverDataJSON.serverData + '

' ).insertAfter(videoElement); } diff --git a/openvidu-mvc-node/README.md b/openvidu-mvc-node/README.md index 5f3c1a40..bd1b027a 100644 --- a/openvidu-mvc-node/README.md +++ b/openvidu-mvc-node/README.md @@ -1 +1,405 @@ # openvidu-mvc-node + + +A secure OpenVidu sample app with a Node backend and a traditional MVC frontend. With regard to the use of OpenVidu, it is identical to _openvidu-js-node_. This tutorial is intended for developers who feel more comfortable with MVC web architectures for their frontends. [Embedded JavaScript](http://www.embeddedjs.com/) is the template engine of choice for this tutorial. + +## Understanding this example + +

+ +

+ + +OpenVidu is composed by the modules displayed on the image above. + +- **openvidu-browser**: JavaScript library for the browser. It allows you to manage your video-calls straight away from your clients +- **openvidu-node-client**: NPM package to easily get the necessary params (sessionId's and tokens) from openvidu-server. Quick alternative to REST API +- **openvidu-server**: Java application that controls Kurento Media Server +- **Kurento Media Server**: server that handles low level operations of media flow transmissions + +> You will only have to make use of **openvidu-browser** and **openvidu-node-client** to get this sample app working + +## Executing this example + +1. Clone the repo: + + ```bash + git clone https://github.com/OpenVidu/openvidu-tutorials.git + ``` + +2. You will need _node_ and _NPM_ to execute the app. You can install them with: + + ```bash + sudo apt-get install nodejs + sudo apt-get install npm + ``` + +3. To run the sample application, execute the following commands in the project. They will install the NPM dependencies and will execute `server.js` server passing two arguments: "localhost:8443" as the URL where _openvidu-server_ will be listening and "MY_SECRET" as the secret share with it: + + ```bash + cd openvidu-mvc-node + npm install + node server.js localhost:8443 MY_SECRET + ``` + +4. _openvidu-server_ and _Kurento Media Server_ must be up and running in your development machine. The easiest way is running this Docker container which wraps both of them (you will need [Docker CE](https://store.docker.com/search?type=edition&offering=community)): + + ```bash + docker run -p 8443:8443 --rm -e KMS_STUN_IP=193.147.51.12 -e KMS_STUN_PORT=3478 -e openvidu.secret=MY_SECRET openvidu/openvidu-server-kms + ``` + +5. Go to [`https://localhost:5000`](https://localhost:5000) to test the app once the server is running. The first time you use the docker container, an alert message will suggest you accept the self-signed certificate of _openvidu-server_ when you first try to join a video-call. To test two users in the same computer, use a standard window and an incognito window. + +## Understanding the code + +This is a very basic web application with a pretty simple vanilla JS/HTML/CSS frontend and a straightforward Node backend built with [_express_](http://expressjs.com/es/) that serves HTML files with a MVC approach, building the templates with the help of [Embedded JavaScript](http://www.embeddedjs.com/). + +OpenVidu assumes you can identify your users so you can tell which users can connect to which video-calls, and what role (and therefore what permissions) each one of them will have in the calls. You can do this as you prefer. Here our backend will manage the users and their sessions with the easy-to-use and non-intrusive [_express-session_](https://github.com/expressjs/session) API. + +- **Backend**: node server + - `server.js` : single file which handles all operations of server. It returns HTML templates as response to HTTP requests. + +- **Frontend templates**: Pure JS/HTML/CSS files served by the backend, with `.ejs` extension to support Embedded JavaScript (`/views` folder) + - `index.ejs` : template with the login form + - `dashboard.ejs` : template with the form to join a video-call + - `session.ejs` : template of the video-call itself + +- **Frontend static files** (`/public` folder) + - `OpenVidu.js` : openvidu-browser library. You don't have to manipulate this file + - `style.css` : some CSS classes to style the templates + + +Let's describe the code following this scenario: a user logs in to the app and connects to the video-call "TUTORIAL", where he publishes his webcam. A second user will connect to the same video-call just after that and publish its own webcam. Both of them will leave the call after a while. + +1. **User logs in** + + At path `/` a login form will be displayed: + +

+ +

+ + The form will execute a POST operation to path `/dashboard` whenever "Log in" button is clicked, passing the username and the password: + + ```html +
+

+ +

+

+ +

+

+ +

+
+ ``` + + `server.js` at `/dashboard` first checks if the user is already logged (maybe he has just refreshed `/dashboard` page), and if so it just redirects to the dashboard itself. If the user is actually logging in, the method checks that the params are correct and if so sets a new _express-session_ for the newly logged user (adding a _loggedUser_ property with its username in the _req.session_ object). Finally it returns `dashboard.ejs` template: + + ```javascript + app.post('/dashboard', dashboardController); + app.get('/dashboard', dashboardController); + + function dashboardController(req, res) { + + // Check if the user is already logged in + if (isLogged(req.session)) { + // User is already logged. Immediately return dashboard + user = req.session.loggedUser; + res.render('dashboard.ejs', { + user: user + }); + } else { + // User wasn't logged and wants to + + // Retrieve params from POST body + var user = req.body.user; + var pass = req.body.pass; + + if (login(user, pass)) { // Correct user-pass + // Validate session and return OK + // Value stored in req.session allows us to identify the user in future requests + req.session.loggedUser = user; + res.render('dashboard.ejs', { + user: user + }); + } else { // Wrong user-pass + // Invalidate session and return index template + req.session.destroy(); + res.redirect('/'); + } + } + } + ``` + +2. **User connects to "TUTORIAL" video-call** + + `dashboard.html` template will display a form asking for the video-call to connect and the nickname the user wants to have in it. So our 'publisher1' user would write TUTORIAL in "Session" field: + +

+ +

+ + The form will execute a POST operation to path `/session` whenever "Join!" button is clicked, passing the nickname and the session name: + + ```html +
+

+ +

+

+ +

+

+ +

+
+ ``` + + When `server.js` receives a request at `/session` path is when things get interesting. + First of all there are some important attributes in this class we must mention: + + ```javascript + // Environment variable: URL where our OpenVidu server is listening + var OPENVIDU_URL = process.argv[2]; + // Environment variable: secret shared with our OpenVidu server + var OPENVIDU_SECRET = process.argv[3]; + + // OpenVidu object to ask openvidu-server for sessionId and token + var OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); + + // Collection to pair session names and OpenVidu Session objects + var mapSessionNameSession = {}; + // Collection to pair sessionId's (identifiers of Session objects) and tokens + var mapSessionIdTokens = {}; + ``` + + Rest controller method receives both params sent by the client (whatever nickname the user has chosen and "TUTORIAL" as the sessionName). First it prepares a param we will need a little further on: `tokenOptions`. + + ```javascript + app.post('/session', (req, res) => { + // Check the user is logged ... + + // The nickname sent by the client + var clientData = req.body.data; + // The video-call to connect ("TUTORIAL") + var sessionName = req.body.sessionname; + + // Role associated to this user + var role = users.find(u => (u.user === req.session.loggedUser)).role; + + // Optional data to be passed to other users when this user connects to the video-call + // In this case, a JSON with the value we stored in the req.session object on login + var serverData = '{"serverData": "' + req.session.loggedUser + '"}'; + + // Build tokenOptions object with the serverData and the role + var tokenOptions = new TokenOptions.Builder() + .data(serverData) + .role(role) + .build(); + ``` + + Just after that an _if-else_ statement comes into play: does the session "TUTORIAL" already exitsts? + ```javascript + if (mapSessionNameSession[sessionName]) { ... + ``` + In this case it doesn't because 'publisher1' is the first user connecting to it. So we focus on the _else_ branch: + + ```javascript + else { // New session: return a new sessionId and a new token + // Create a new OpenVidu Session + var mySession = OV.createSession(); + + // Get the sessionId asynchronously + mySession.getSessionId(function (sessionId) { + + // Store the new Session in the collection of Sessions + mapSessionNameSession[sessionName] = mySession; + // Store a new empty array in the collection of tokens + mapSessionIdTokens[sessionId] = []; + + // Generate a new token asynchronously with the recently created tokenOptions + mySession.generateToken(tokenOptions, function (token) { + + // Store the new token in the collection of tokens + mapSessionIdTokens[sessionId].push(token); + + // Return session template with all the needed attributes + res.render('session.ejs', { + sessionId: sessionId, + token: token, + nickName: clientData, + userName: req.session.loggedUser, + sessionName: sessionName + }); + }); + }); + } + ``` + We are almost there! Now in `session.html` JavaScript code (preceded by a tag ` diff --git a/openvidu-mvc-node/views/index.ejs b/openvidu-mvc-node/views/index.ejs index d4a05022..a13b1746 100644 --- a/openvidu-mvc-node/views/index.ejs +++ b/openvidu-mvc-node/views/index.ejs @@ -12,7 +12,7 @@

- +

diff --git a/openvidu-mvc-node/views/leave-session.ejs b/openvidu-mvc-node/views/leave-session.ejs deleted file mode 100644 index b33fea66..00000000 --- a/openvidu-mvc-node/views/leave-session.ejs +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - OpenVidu Demo Node MVC Secure - - -Leaving session... - - - - - - - \ No newline at end of file diff --git a/openvidu-mvc-node/views/session.ejs b/openvidu-mvc-node/views/session.ejs index df58bdb8..0a93da32 100644 --- a/openvidu-mvc-node/views/session.ejs +++ b/openvidu-mvc-node/views/session.ejs @@ -35,8 +35,8 @@ sessionId + ", TOKEN:" + token + ")"); // 1) Get an OpenVidu object and initialize a Session - var OV = new OpenVidu("wss://" + location.hostname + ":8443/"); - var session = OV.initSession("apikey", sessionId); + var OV = new OpenVidu(); + var session = OV.initSession(sessionId); // 2) Specify the actions when events take place session.on('streamCreated', function (event) {