|
17 | 17 | </p> |
18 | 18 |
|
19 | 19 |
|
| 20 | +> ### OpenLRW is the next evolution of OpenLRS. OpenLRW is a standards-focused learning records warehouse with support for event capture with xAPI and IMS Caliper. |
20 | 21 |
|
21 | | -> OpenLRW is the next evolution of OpenLRS. OpenLRW is a standards-focused learning records warehouse with support for event capture with xAPI and IMS Caliper. |
| 22 | +## Documentation |
| 23 | +The documentation is available in different languages on this [link](https://github.com/Apereo-Learning-Analytics-Initiative/OpenLRW/blob/master/docs/index.md). |
22 | 24 |
|
23 | | - |
24 | | -# Table of Contents |
25 | | -* [I. Requirements](#i-requirements) |
26 | | -* [II. Installation](#ii-installation) |
27 | | - * [A. Clone the project](#a-clone-the-project) |
28 | | - * [B. Using Maven for development purposes](#b-using-maven-for-development-purposes) |
29 | | - * [C. Using a more production-like setup](#c-using-a-more-production-like-setup) |
30 | | -* [III. Tips](#iii-tips) |
31 | | - * [A. Find OpenLRW API Key and Secret](#a-find-openlrw-api-key-and-secret) |
32 | | - * [B. Log in](#b-log-in) |
33 | | - * [C. Count events](#c-count-events) |
34 | | - * [D. Remove all events (testing only)](#d-remove-all-events-testing-only) |
35 | | - * [E. Caliper routes](#e-caliper-routes) |
36 | | -* [IV. Possible Issues](#iv-possible-issues) |
37 | | -* [V. Resources](#v-resources) |
38 | | -* [VI. License](#vi-license) |
39 | | -* [VII. Contact](#vii-contact) |
40 | | - |
41 | | -## I. Requirements |
42 | | -- [Git](https://git-scm.com/) |
43 | | -- [Java Development Kit 8](https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html) |
44 | | -- [Maven 3](https://maven.apache.org/download.cgi) |
45 | | -- [MongoDB 2.6+](https://docs.mongodb.com/manual/installation/) |
46 | | - |
47 | | - |
48 | | - |
49 | | -## II. Installation |
50 | | -### A. Clone the project |
51 | | -` $ git clone https://github.com/Apereo-Learning-Analytics-Initiative/OpenLRW.git ` |
52 | | - |
53 | | -### B. Using Maven for development purposes |
54 | | -` $ mvn clean package spring-boot:run ` |
55 | | - |
56 | | - |
57 | | -This will start the application on port 9966. You can check to see if the application is running by accessing the info endpoint at http://localhost:9966/info |
58 | | - |
59 | | -These instructions also assume that you are running MongoDB on the same machine as the LRW application (i.e., MongoDB is accessible at localhost:27017). If you need to configure the application to connect to a different MongoDB address see the [Spring-Boot & MongoDB configuration](http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html) properties. |
60 | | - |
61 | | -### C. Using Docker for development |
62 | | - |
63 | | -In the future this could be used for production but currently it's just set up for development |
64 | | - |
65 | | -This is built with regular `docker-compose build` then `docker-compose up -d`. `docker-compose down` will bring this down. The redis data is stored in a local folder ./redis-data. Delete this folder to delete the data. |
66 | | - |
67 | | -An container running Mongo and this application will be started |
68 | | - |
69 | | -#### Get your API |
70 | | - |
71 | | -The API can be retrieved similarly to above |
72 | | - |
73 | | -`docker run -it --link openlrw_mongo --net openlrw_net --rm mongo mongo --host mongo test -u root -p example --eval "db.mongoOrg.find().pretty()" | grep \"api` |
74 | | - |
75 | | -### D. Using a more production-like setup |
76 | | -#### 1. Directory Structure |
77 | | -Create the following directory structure. |
78 | | - |
79 | | -``` |
80 | | -/opt/ |
81 | | -└── openlrw/ |
82 | | - ├── conf/ |
83 | | - ├── lib/ |
84 | | - ├── logs/ |
85 | | - ├── run/ |
86 | | - ├── src/ |
87 | | - ├── build.sh |
88 | | - └── run.sh |
89 | | -``` |
90 | | - |
91 | | -#### 2. Add a user to run the application |
92 | | - |
93 | | -Create a user to run the application and make them owner of /opt/openlrw/* directories. |
94 | | -```bash |
95 | | -$ useradd -c "Boot User" boot |
96 | | -$ chown -R boot:boot /opt/openlrw |
97 | | -``` |
98 | | - |
99 | | -#### 3. Checkout the source code |
100 | | -This is a one time operation. Note you'll need to update the git command below with your git username. |
101 | | - |
102 | | -```bash |
103 | | -$ cd /opt/openlrw/src |
104 | | -$ git clone https://github.com/Apereo-Learning-Analytics-Initiative/OpenLRW |
105 | | -``` |
106 | | - |
107 | | -#### 4. Build Script (build.sh) |
108 | | -From the `/opt/openlrw/` directory execute the build script to create the LRW executable. |
109 | | - |
110 | | -```bash |
111 | | -#!/bin/sh |
112 | | -cd `dirname $0` |
113 | | -cd src/OpenLRW |
114 | | -git pull |
115 | | -mvn -DskipTests=true clean install |
116 | | -cp target/matthews-1.jar ../../lib/openlrw.jar |
117 | | -``` |
118 | | - |
119 | | -#### 5. Run Script (run.sh) |
120 | | -From the `/opt/openlrw/` directory execute the run script to start the application. Note you will need to update the script below with the appropriate MongoDB path. The application listens on port 9966. |
121 | | - |
122 | | -```bash |
123 | | -#!/bin/sh |
124 | | -cd `dirname $0` |
125 | | -APP_HOME="$PWD" |
126 | | -PID_FILE=$APP_HOME/run/openlrw.pid |
127 | | -JAR_PATH=$APP_HOME/lib/openlrw.jar |
128 | | - |
129 | | -cd $APP_HOME |
130 | | - |
131 | | -case "$1" in |
132 | | -"start") |
133 | | - if [ -f $PID_FILE ]; then |
134 | | - exit 1 |
135 | | - fi |
136 | | - java \ |
137 | | - -Dlogging.path=/opt/openlrw/logs/ \ |
138 | | - -Dspring.data.mongodb.uri=<!-- mongodb uri --> \ |
139 | | - -jar $JAR_PATH & |
140 | | - echo $! > $PID_FILE |
141 | | - ;; |
142 | | -"stop") |
143 | | - if [ ! -f $PID_FILE ]; then |
144 | | - exit 1 |
145 | | - fi |
146 | | - kill `cat $PID_FILE` |
147 | | - rm -f $PID_FILE |
148 | | - ;; |
149 | | -*) |
150 | | - echo "Usage: $0 start|stop" |
151 | | - ;; |
152 | | -esac |
153 | | -exit 0 |
154 | | -``` |
155 | | - |
156 | | -#### 6. Automated Start (e.g. AWS Auto-scale) |
157 | | - |
158 | | -```bash |
159 | | -#!/bin/bash |
160 | | -yum update -y |
161 | | -bash |
162 | | -cd /opt/openlrw |
163 | | -rm /opt/openlrw/run/*.pid |
164 | | -rm /opt/openlrw/*.log |
165 | | -rm /opt/openlrw/logs/*.log |
166 | | -su boot -c "sh build.sh" |
167 | | -su boot -c "sh run.sh start" |
168 | | -``` |
169 | | - |
170 | | -## III. Tips |
171 | | -### A. Find OpenLRW API Key and Secret |
172 | | -The OpenLRW admin user interface is under development so you'll have to find your API key and secret by directly accessing your MongoDB instance. Follow the commands below to find your key and secret. The commands assume that you are able to access MongoDB via the command line and that you are using the default database name (if not, you would have changed this manually in openlrw). |
173 | | - |
174 | | -```javascript |
175 | | -> mongo |
176 | | -> use test |
177 | | -> db.mongoOrg.find().pretty() |
178 | | - |
179 | | -{ |
180 | | - "_id" : ObjectId("objid"), |
181 | | - "_class" : "unicon.matthews.oneroster.service.repository.MongoOrg", |
182 | | - "apiKey" : "abcdef", |
183 | | - "apiSecret" : "123456", |
184 | | - "tenantId" : "583ce4076f03bb1f88bee0ea", |
185 | | - "org" : { |
186 | | - "sourcedId" : "1f03f835-d992-4301-8e5c-5ad55e6489f5", |
187 | | - "status" : "active", |
188 | | - "metadata" : { |
189 | | - "https://matthews/tenant" : "583ce4076f03bb1f88bee0ea" |
190 | | - }, |
191 | | - "dateLastModified" : ISODate("2016-11-29T02:12:23.757Z"), |
192 | | - "name" : "DEFAULT_ORG", |
193 | | - "type" : "other" |
194 | | - } |
195 | | -} |
196 | | -``` |
197 | | - |
198 | | -Find the values apiKey and apiSecret, those are the values you'll need to use to create a session with openlrw. In the example above the key is abcdef and the secret is 123456 |
199 | | - |
200 | | -### B. Log in |
201 | | -> Curl |
202 | | -
|
203 | | -```bash |
204 | | -curl -X POST -H "X-Requested-With: XMLHttpRequest" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ |
205 | | - "username": "USERNAME", |
206 | | - "password": "PASSWORD"}' "http://localhost:9966/api/auth/login" |
207 | | -``` |
208 | | - |
209 | | -<br> |
210 | | - |
211 | | -> Python |
212 | | -
|
213 | | -```python |
214 | | -import requests |
215 | | -import json |
216 | | - |
217 | | -response = requests.post("http://localhost:9966/api/auth/login", |
218 | | - headers={'X-Requested-With': 'XMLHttpRequest'}, |
219 | | - json={"username": USERNAME, "password": PASSWORD}) |
220 | | -response = response.json() |
221 | | -token = response['token'] |
222 | | -``` |
223 | | - |
224 | | -<br> |
225 | | - |
226 | | -### C. Count events |
227 | | - |
228 | | -```javascript |
229 | | -> mongo |
230 | | -> use test |
231 | | -> db.mongoEvent.count() |
232 | | -17813 |
233 | | -``` |
234 | | - |
235 | | -<br> |
236 | | - |
237 | | -### D. Remove all events (testing only) |
238 | | - |
239 | | -```javascript |
240 | | -> mongo |
241 | | -> use test |
242 | | -> db.mongoEvent.count() |
243 | | -17813 |
244 | | -> db.mongoEvent.remove({}) |
245 | | -WriteResult({ "nRemoved" : 17813 }) |
246 | | -> db.mongoEvent.count() |
247 | | -0 |
248 | | -``` |
249 | | - |
250 | | -<br> |
251 | | - |
252 | | -### E. Caliper routes |
253 | | -> OpenLRW provides two endpoints that support receipt of event data in IMS Caliper format. |
254 | | -
|
255 | | -#### `/key/caliper` |
256 | | -This endpoint expects only to have your OpenLRW API key passed in the Authorization header. Here is an example: |
257 | | - |
258 | | -```javascript |
259 | | -POST /key/caliper HTTP/1.1 |
260 | | -Host: localhost:9966 |
261 | | -Content-Type: application/json |
262 | | -X-Requested-With: XMLHttpRequest |
263 | | -Authorization: YOUR-API-KEY |
264 | | -Cache-Control: no-cache |
265 | | - |
266 | | -{ "sensor": "https://example.edu/sensor/001", "sendTime": "2015-09-15T11:05:01.000Z", "data": [ { "@context": "http://purl.imsglobal.org/ctx/caliper/v1/Context", "@type": "http://purl.imsglobal.org/caliper/v1/Event", "actor": { "@id": "https://example.edu/user/554433", "@type": "http://purl.imsglobal.org/caliper/v1/lis/Person" }, "action": "http://purl.imsglobal.org/vocab/caliper/v1/action#Viewed", "eventTime": "2015-09-15T10:15:00.000Z", "object": { "@id": "https://example.com/viewer/book/34843#epubcfi(/4/3)", "@type": "http://www.idpf.org/epub/vocab/structure/#volume" } } ] } |
267 | | -``` |
268 | | - |
269 | | -#### `/api/caliper` |
270 | | -This endpoint expects you to pass a valid bearer token in the Authorization header. To get a bearer token, first use the login endpoint with your api key and secret as follows: |
271 | | - |
272 | | -```javascript |
273 | | -POST /api/auth/login HTTP/1.1 |
274 | | -Host: localhost:9966 |
275 | | -Content-Type: application/json |
276 | | -X-Requested-With: XMLHttpRequest |
277 | | -Cache-Control: no-cache |
278 | | - |
279 | | -{ "username":"YOUR-API-KEY", "password":"YOUR-API-SECRET" } |
280 | | -``` |
281 | | - |
282 | | -Once you have the token, you can use it as follows: |
283 | | - |
284 | | -```javascript |
285 | | -POST /api/caliper HTTP/1.1 |
286 | | -Host: localhost:9966 |
287 | | -Content-Type: application/json |
288 | | -X-Requested-With: XMLHttpRequest |
289 | | -Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI4NmMxMGY5Zi02MDUxLTQxNTEtYTNiYS01ODIwMmZhYWQ4ZjIiLCJzY29wZXMiOlsiUk9MRV9PUkdfQURNSU4iXSwidGVuYW50IjoiNTk2ZTM5N2RhOWY1NjQzYjFmNWFkMDA1IiwiaXNzIjoiaHR0cDovL2V4YW1wbGUuY29tIiwiaWF0IjoxNTAyMjE5MTY3LCJleHAiOjE1MDIyMzM1Njd9.6QvRpoNFe83ulOTIU3UJrAIbZLHCMx7izUwdtirrv5_-cWG5XYxVhi8b5uB5c3pYWBKld1w6y0vx7JPidECBMg |
290 | | -Cache-Control: no-cache |
291 | | - |
292 | | -{ "sensor": "https://example.edu/sensor/001", "sendTime": "2015-09-15T11:05:01.000Z", "data": [ { "@context": "http://purl.imsglobal.org/ctx/caliper/v1/Context", "@type": "http://purl.imsglobal.org/caliper/v1/Event", "actor": { "@id": "https://example.edu/user/554433", "@type": "http://purl.imsglobal.org/caliper/v1/lis/Person" }, "action": "http://purl.imsglobal.org/vocab/caliper/v1/action#Viewed", "eventTime": "2015-09-15T10:15:00.000Z", "object": { "@id": "https://example.com/viewer/book/34843#epubcfi(/4/3)", "@type": "http://www.idpf.org/epub/vocab/structure/#volume" } } ] } |
293 | | - |
294 | | -``` |
295 | | - |
296 | | -<br> |
297 | | - |
298 | | -## IV. Possible Issues |
299 | | - |
300 | | -You might experience very long startup times on some cloud hosted servers. This might be because of a shortage |
301 | | -of entropy as a result of no keyboard, or mouse: |
302 | | - |
303 | | -http://www.issihosts.com/haveged/ |
304 | | - |
305 | | -To rectify, install the above software (Ubuntu instructions): |
306 | | - |
307 | | -```bash |
308 | | -apt-get install haveged |
309 | | -update-rc.d haveged defaults |
310 | | -apt-get install rng-tools |
311 | | -cat /dev/random | rngtest -c 1000 |
312 | | -``` |
313 | | - |
314 | | -If you are having troubles with certain caliper or xapi payloads, you can turn on http request loggging with the following: |
315 | | - |
316 | | -``` |
317 | | -logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter: DEBUG |
318 | | -``` |
319 | | - |
320 | | -## V. Resources |
321 | | -- [Caliper Analytics](https://www.imsglobal.org/activity/caliper) |
322 | | -- [OneRoster](https://www.imsglobal.org/activity/onerosterlis) |
323 | | -- [xAPI](https://experienceapi.com/) |
324 | | -- [Swagger](http://imshackathonlrw.cloudlrs.com/swagger-ui.html#/) |
325 | | - |
326 | | -## VI. License |
| 25 | +## License |
327 | 26 | OpenLRW is made available under the terms of the [Educational Community License, Version 2.0 (ECL-2.0)](https://opensource.org/licenses/ECL-2.0). |
328 | 27 |
|
329 | | -## VII. Contact |
| 28 | +## Contact |
330 | 29 | Send questions or comments to the mailing list: openlrs-user@apereo.org |
331 | 30 |
|
0 commit comments