fixed package typo, closes #435
[oweals/karmaworld.git] / README.md
1 # KarmaWorld
2 __Description__: A django application for sharing and uploading class notes.
3
4 __Copyright__: FinalsClub, a 501c3 non-profit organization
5
6 __License__: GPLv3 except where otherwise noted
7
8 __Contact__: info@karmanotes.org
9
10 v3.0 of the karmanotes.org website from the FinalsClub Foundation
11
12 # Purpose
13
14 KarmaWorld is an online database of college lecture notes.  KarmaWorld
15 empowers college students to participate in the free exchange of knowledge.
16
17 # Naming
18
19 The repository and the project are called KarmaWorld. One implementation
20 of KarmaWorld, which is run by FinalsClub Foundation, is called
21 [KarmaNotes](https://www.karmanotes.org/).
22
23 # Pre-Installation
24
25 ## Code
26
27 Before doing anything, you'll need the code. Grab it from github.
28
29 Clone the project from the central repo using your github account:
30
31     git clone git@github.com:FinalsClub/karmaworld.git
32
33 If you aren't using a system setup for github, then grab the project with
34 this command instead:
35
36     git clone https://github.com/FinalsClub/karmaworld.git
37
38 Generally speaking, this will create a subdirectory called `karmaworld` under
39 the directory where the `git` command was run. This git repository directory
40 will be referred to herein as `{project_root}`.
41
42 There might be some confusion as the git repository's directory will likely be
43 called `karmaworld` (this is `{project_root}`), but there is also a `karmaworld`
44 directory underneath that (`{project_root}/karmaworld`) alongside files like
45 `fabfile.py` (`{project_root}/fabfile.py`) and `README.md`
46 (`{project_root}/README.md`).
47
48 ## External Software Dependencies
49
50 ### pdf2htmlEX
51
52 KarmaWorld uses [pdf2htmlEX](https://github.com/coolwanglu/pdf2htmlEX) as
53 a dependency. pdf2htmlEX is used to convert uploaded PDF notes into HTML.
54
55 An [outdated version of pdf2htmlEX](https://github.com/FinalsClub/pdf2htmlEX)
56 is available which includes the
57 [patch](https://github.com/FinalsClub/pdf2htmlEX/commit/3c19f6abd8d59d1b58cf254b7160b332b3f5b517)
58 required for pdf2htmlEX to correctly work with KarmaWorld.
59
60 Newer versions can be used by applying the patch by hand. It's a fairly
61 simple two-line modification that can be done after installing
62 pdf2htmlEX.
63
64 ### SSL Certificate
65
66 If you wish to host your system publicly, you'll almost certainly want
67 an SSL certificate signed by a proper authority.
68
69 You may need to set the `SSL_REDIRECT` environment variable to `true` to
70 make KarmaWorld redirect insecure connections to secure ones.
71
72 Follow [Heroku's SSL setup](https://devcenter.heroku.com/articles/ssl-endpoint)
73 to get SSL running on your server with Heroku.
74
75 ## External Service Dependencies
76
77 Notice: This software makes use of external third party services which require
78 accounts to access the service APIs. Without these third parties available,
79 this software may require considerable overhaul. These services have
80 API keys, credentials, and other information that you must provide to KarmaWorld
81 as environment variables. The best way to persist these environment variables is
82 by using a `.env` file. Copy `.env.example` to `.env` and populate the fields as
83 required.
84
85 A number of services are required even if running the KarmaWorld web service
86 locally, some of the services are recommended, and some are completely optional
87 even if running the web service on Heroku.
88
89 Many of these services have free tiers and can be used without charge for
90 development testing purposes.
91
92 * Required Services
93   * [Google Drive](#google-drive)
94   * [Filepicker](#filepicker)
95   * [PostgreSQL](#postgresql)
96   * [Celery](#celery-queue)
97 * Optional but recommended
98   * [IndexDen](#indexden): enables searching through courses, notes, etc
99   * [Heroku](#heroku): the production environment used by karmanotes.org
100     * it might not be possible to run KarmaWorld on Heroku using a free
101       webapp.
102   * [Amazon S3](#s3-for-static-files): for static file hosting
103 * Entirely optional (though used in the production environment)
104   * [Twitter](#twitter): share updates about new uploads
105   * [Amazon Mechanical Turk](#amazon-mechanical-turk): generate quizzes, flashcards, etc
106   * [Amazon CloudFront](#amazon-cloudfront-cdn)
107   * [Amazon S3](#s3-for-filepicker): store files uploaded to Filepicker
108     * Filepicker does not support S3 storage in its free tier
109
110 ### Heroku
111 This project has chosen to use [Heroku](www.heroku.com) to host the Django and
112 celery software. While not a hard requirement, the more up-to-date parts of this
113 documentation will operate assuming Heroku is in use.
114
115 See README.heroku for more information.
116
117 #### pdf2htmlEX on Heroku
118 If using Heroku, the default
119 [KarmaNotes Heroku buildpack](https://github.com/FinalsClub/heroku-buildpack-karmanotes)
120 will [include](https://github.com/FinalsClub/heroku-buildpack-karmanotes/blob/master/bin/steps/pdf2htmlex)
121 the [required version of pdf2htmlEX](#pdf2htmlex).
122
123 ### Celery Queue
124 Celery uses the Apache Message Queueing Protocol for passing messages to its workers.
125
126 For production, we recommend using Heroku's CloudAMQP add-on, getting your own CloudAMQP account, or
127 running a queueing system on your own. The `CLOUDAMQP_URL` environment variable must be set correctly
128 for KarmaWorld to be able to use Celery. The `CELERY_QUEUE_NAME` environment variable
129 must be set to the name of the queue you wish to use. Settings this to something unique
130 allows multiple instances of KarmaWorld (or some other software) to share the same queueing server.
131
132 For development on localhost, `RabbitMQ` is the default for `djcelery` and is well supported. Ensure
133 `RabbitMQ` is installed for local development.
134
135 ### PostgreSQL
136
137 PostgreSQL is not necessarily required; other RDBMS could probably be fit into
138 place. However, the code was largely written assuming PostgreSQL will be used.
139 Change to another system with the caveat that it might take some work.
140
141 There are many cloud providers which provide PostgreSQL databases. Heroku has
142 an add-on for providing a PostgreSQL database. Ensure something like this
143 is made available and installed to the app.
144
145 For local development, ensure a PostgreSQL is running on localhost or is
146 otherwise accessible.
147
148 ### Amazon S3
149 The instructions for creating an [S3](http://aws.amazon.com/s3/) bucket may be
150 [found on Amazon.](http://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html)
151
152 Two, separate buckets may be used in production: one for static file hosting
153 and one as a communication bus with Filepicker.
154
155 #### S3 for Filepicker
156
157 This software uses S3 to store files which are sent to or received 
158 from Filepicker. Filepicker will need to know the S3 bucket name, access key,
159 and secret key.
160
161 Filepicker users can only make use of an S3 bucket with a paid account. For
162 development purposes, no Filepicker S3 bucket is needed. Skip all references to
163 the Filepicker S3 bucket in the development case.
164
165 The software will not need to know the S3 credentials for the Filepicker
166 bucket, because the software will upload files to the Filepicker S3 bucket
167 through Filepicker's API and it will link to or download files from the
168 Filepicker S3 bucket through Filepicker's URLs. This will be covered in the
169 [Filepicker section](#filepicker).
170
171 #### S3 for static files
172
173 This software uses S3 for hosting static files. The software will need to
174 update static files on the S3 bucket. As such, the software will need the
175 S3 bucket name, access key, and secret key via the environment variables. This
176 is described in subsections below.
177
178 To support static hosting, `DEFAULT_FILE_STORAGE` should be set to
179 `'storages.backends.s3boto.S3BotoStorage'`, unless there is a compelling reason
180 to change it.
181
182 There are three ways to setup access to the S3 buckets depending upon speed
183 and security. The more secure, the slower it will be to setup.
184
185 #### insecure S3 access
186 For quick and dirty insecure S3 access, create a single group and a single user
187 with full access to all buckets. Full access to all buckets is insecure!
188
189 Create an 
190 [Amazon IAM group](http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_CreatingAndListingGroups.html)
191 with full access to the S3 bucket. Select the "Amazon S3 Full Accesss" Policy
192 Template.
193
194 Create an
195 [Amazon IAM user](http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_SettingUpUser.html).
196 Copy the credentials into the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
197 environment variables. Be sure to write down the access information, as it
198 will only be shown once.
199
200 #### secure S3 access
201 For secure S3 access, two users will be needed. One with access to the
202 Filepicker bucket and one with access to the static hosting bucket.
203
204 Note: this might need to be modified to prevent creation and deletion of
205 buckets?
206
207 Create an 
208 [Amazon IAM group](http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_CreatingAndListingGroups.html)
209 with full access to the S3 bucket. The quick way is to select the
210 "Amazon S3 Full Accesss" Policy Template and replace `"Resource": "*"` with 
211 `"Resource": "arn:aws:s3:::<static_bucket_name>"`.
212
213 Create an
214 [Amazon IAM user](http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_SettingUpUser.html).
215 Copy the credentials into the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
216 environment variables. Be sure to write down the access information, as it
217 will only be shown once.
218
219 Ensure the created user is a member of the group with access to the S3
220 static files bucket.
221
222 Repeat the process again, creating a group for the Filepicker bucket and
223 creating a user with access to that group. These credentials will be passed
224 on to Filepicker.
225
226 #### somewhat secure S3 access
227 Create two groups as described in the `secure S3 access` section above.
228
229 Create a single user, save the credentials as described in the
230 `insecure S3 access` section above, and pass the credentials on to Filepicker.
231
232 Add the single user to both groups.
233
234 This is less secure because if your web server or Filepicker get compromised
235 (so there are two points for potential failure), the single compromised
236 user has full access to both buckets.
237
238 ### Amazon Cloudfront CDN
239 [Cloudfront CDN](http://aws.amazon.com/cloudfront/) assists static file hosting.
240
241 Follow
242 [Amazon's instructions](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.html)
243 to host static files out of the appropriate S3 bucket. Note that Django's static
244 file upload process has been modified to mark static files as publicly
245 assessible.
246
247 In the settings for the Cloudfront Distribution, copy the "Domain Name" from
248 General settings and set `CLOUDFRONT_DOMAIN` to it. For example, `abcdefghij.cloudfront.net`.
249
250 ### Amazon Mechanical Turk
251 Mechanical turk is employed to generate human feedback from uploaded notes.
252 This service is helpful for generating flash cards and quizzes.
253
254 This service is optional and it might cause unexpected charges when
255 deployed.  If the required environment variable is not found,
256 then no errors will occur and no mechanical turk tasks will be created, avoiding any unexpected
257 costs.
258
259 The `MTURK_HOST` environment variable is almost certainly
260 `"mechanicalturk.amazonaws.com"`.
261
262 The code will create and publish HITs on your behalf.
263
264 ### Google Drive
265 This software uses [Google Drive](https://developers.google.com/drive/) to
266 convert documents to and from various file formats.
267
268 A Google Drive service account with access to the Google Drive is required.
269 This may be done with a Google Apps account with administrative privileges, or ask
270 your business sysadmin.
271
272 Follow [Google's instructions](https://developers.google.com/drive/delegation)
273 to create a Google Drive service account.
274
275 Convert the p12 file into a Base64 encoded string for the
276 `GOOGLE_SERVICE_KEY_BASE64` environment variable. There are many ways to do
277 this. If Python is available, the
278 [binascii library](https://docs.python.org/2/library/binascii.html#binascii.b2a_base64)
279 makes this very easy:
280
281         import binascii
282         with open('file.p12', 'r') as f:
283             print binascii.b2a_base64(f.read)
284
285 Copy the contents of `client_secret_*.apps.googleusercontent.com.json` into the
286 `GOOGLE_CLIENT_SECRETS` environment variable.
287
288 ### Filepicker
289 This software uses [Filepicker.io](https://www.inkfilepicker.com/) for uploading
290 files. This requires an account with Filepicker.
291
292 Filepicker can use an additional third party file hosting site where it may
293 send uploaded files. This project, in production, uses Amazon S3 as the third
294 party. See the Amazon S3 section above for more information.  
295
296 Create a new App with Web SDK and provide the Heroku App URL for the
297 Application's URL. You'll be given an API Key for the App. Paste this into the
298 `FILEPICKER_API_KEY` environment variable.
299
300 Find the 'App Security' button on the left hand side of the web site. Make sure
301 'Use Security' is enabled. Generate a new secret key. Paste this key into the
302 `FILEPICKER_SECRET` environment variable.
303
304 If you have an upgraded plan, you can configure Filepicker to have access to
305 your Filepicker S3 bucket. Click 'Amazon S3' on the left hand side menu and
306 supply the credentials for the user with access to the Filepicker S3 bucket.
307
308 ### IndexDen
309 KarmaWorld uses IndexDen to create a searchable index of all the notes in the
310 system. Create an free IndexDen account at
311 [their homepage](http://indexden.com/). You will be given a private URL that
312 accesses your IndexDen account. This URL is visible on your dashboard (you
313 might need to scroll down).
314
315 Set the `INDEXDEN_PRIVATE_URL` environment variable to your private URL.
316
317 Set the `INDEXDEN_INDEX` environment variable to the name of the index you want
318 to use for KarmaWorld. The index will be created automatically when KarmaNotes
319 is run if it doesn't already exist. It may be created through the GUI if
320 desired.
321
322 ### Twitter
323
324 Twitter is used to post updates about new courses. Access to the Twitter API
325 will be required for this task.
326
327 If this Twitter feature is desired, the consumer key and secret as well as the
328 access token key and secret are needed by the software.
329
330 If the required environment variables are not found, then no errors will occur
331 and no tweets will be posted.
332
333 To set this up,
334 [create a new Twitter application](https://dev.twitter.com/apps/new).
335 Use your Heroku App URL for the website field. Leave the Callback field blank.
336
337 Make sure this application has read/write access. Generate an access token. Go
338 to your OAuth settings, and grab the "Consumer key", "Consumer secret",
339 "Access token", and "Access token secret". Paste these, respectively, into the
340 environment variables `TWITTER_CONSUMER_KEY`, `TWITTER_CONSUMER_SECRET`,
341 `TWITTER_ACCESS_TOKEN_KEY`, `TWITTER_ACCESS_TOKEN_SECRET`.
342
343 # Local
344
345 ## Configuring foreman
346
347 KarmaNotes runs on Heroku as a webapp and thus makes use of a Procfie. While
348 not strictly necessary, KarmaWorld can use the same basic Procfile which is
349 convenient and consistent.
350
351 To use the Procfile locally, we recommend using `foreman`. To install `foreman`
352 and other Heroku tools, install the
353 [Heroku toolbelt](https://toolbelt.heroku.com/).
354
355 Ensure environment variables are available to `foreman` by copying
356 `.env.example` to `.env` and update those variables as appropriate for your
357 local system.
358
359 ## pdf2htmlEX
360
361 This project uses [pdf2htmlEX](https://github.com/coolwanglu/pdf2htmlEX) as
362 a dependency. pdf2htmlEX is used to convert uploaded PDF notes into HTML. It
363 needs to be installed on the same system that KarmaWorld is running on.
364
365 ### using their source
366
367 See their instructions at
368 [https://github.com/coolwanglu/pdf2htmlEX/wiki/Building](https://github.com/coolwanglu/pdf2htmlEX/wiki/Building).
369
370 Make sure to [patch](https://github.com/FinalsClub/pdf2htmlEX/commit/3c19f6abd8d59d1b58cf254b7160b332b3f5b517)
371 the source code to expose two variables.
372
373 ### using our fork
374
375 You can use FinalsClub's [outdated version of pdf2htmlEX](https://github.com/FinalsClub/pdf2htmlEX).
376 See their installation instructions above, but don't worry about patching.
377
378 ### using their PPA
379
380 You can use [their upstream PPA](https://launchpad.net/~coolwanglu/+archive/ubuntu/pdf2htmlex).
381
382         apt-add-repository ppa:coolwanglu/pdf2htmlex
383         apt-get update
384         apt-get install pdf2htmlex
385
386 Then patch the javascript on your system by running this code in the shell.
387
388         cat >> `dpkg -L pdf2htmlex | grep pdf2htmlEX.js` <<PDF2HTMLEXHACK
389         Viewer.prototype['rescale'] = Viewer.prototype.rescale;
390         Viewer.prototype['scroll_to'] = Viewer.prototype.scroll_to;
391         PDF2HTMLEXHACK
392
393 ## Install
394
395   1. `virtualenv venv`
396   1. `source venv/bin/activate`
397   1. `pip install -r requirements.txt`
398     * on Debian systems, some packages are required for pip to succeed:
399     * `apt-get install python-dev libpython-dev python-psycopg2 libmemcached-dev libffi-dev libssl-dev postgresql-server-dev-X.Y`
400   1. `pip install -r requirements-dev.txt`
401   1. `foreman run python manage.py syncdb --migrate --noinput`
402   1. `foreman run python manage.py createsuperuser`
403   1. `foreman run python manage.py fetch_usde_csv ./schools.csv`
404   1. `foreman run python manage.py import_usde_csv ./schools.csv`
405   1. `foreman run python manage.py sanitize_usde_schools`
406
407 * `fetch_usde_csv` downloads school records and stores them to `./schools.csv`. This file name
408      and location is arbitrary. As long as the same file is passed into `import_usde_csv` for
409      reading, everything should be fine.
410
411 * `fetching_usde_csv` requires `7zip` to be installed for processing compressed
412      archives. On Debian-based systems, this entails `apt-get install p7zip-full`
413
414 ## Run
415
416 Make sure you are inside your virtual environment (`source venv/bin/activate`).
417
418 If the code has changed or this is the first run, make sure any modified static
419 files get compressed with `foreman run python manage.py compress`. Static files
420 then need to be uploaded correctly with `foreman run python manage.py
421 collectstatic`.
422
423 Run `foreman start`.  `foreman` will load the `.env` file and manage running all
424 processes in a way that is similar to that of Heroku. This allows better
425 consistency with local, staging, and production deployments.
426
427 To run web-only, but no celery or beat, run `foreman start web` to specify
428 strictly the web worker.
429
430 Press ctrl-C to kill foreman. Foreman will run Django's runserver command.
431 If you wish to have more control over how this is done, you can do
432 `foreman run python manage.py runserver <options>`. For running any other
433 `manage.py` commands, you should also precede them with `foreman run` like just shown.
434 This simply ensures that the environment variables from `.env` are present.
435
436 # Heroku Install
437
438 KarmaNotes runs on Heroku as a webapp. This section addresses what was done
439 for KarmaNotes so that other implementations of KarmaWorld can be run on
440 Heroku.
441
442 Before anything else, download the [Heroku toolbelt](https://toolbelt.heroku.com/).
443
444 To run KarmaWorld on Heroku, do `heroku create` and `git push heroku master` as typical
445 for a Heroku application. Set your the variable `BUILDPACK_URL` to
446 `https://github.com/FinalsClub/heroku-buildpack-karmanotes` to use a buildpack
447 designed to support KarmaNotes.
448
449 You will need to import the US Department of Education's list of accredited schools.
450    1. Fetch USDE schools with
451       `heroku run python manage.py fetch_usde_csv ./schools.csv`
452    1. Upload the schools into the database with
453       `heroku run python /manage.py import_usde_csv ./schools.csv`
454    1. Clean up redundant information with
455       `heroku run python /manage.py sanitize_usde_schools`
456
457
458 # Django Database management
459
460 ## South
461
462 We have setup Django to use
463 [south](http://south.aeracode.org/wiki/QuickStartGuide) for migrations. When
464 changing models, it is important to run
465 `foreman run python manage.py schemamigration` which will create a migration
466  to reflect the model changes into the database. These changes can be pulled
467 into the database with `foreman run python manage.py migrate`.
468
469 Sometimes the database already has a migration performed on it, but that
470 information wasn't told to south. There are subtleties to the process which
471 require looking at the south docs. As a tip, start by looking at the `--fake`
472 flag.
473
474 # Assets from Third Parties
475
476 A number of assets have been added to the repository which come from external
477 sources. It would be difficult to keep a complete list in this README and keep
478 it up to date. Software which originally came from outside parties can
479 generally be found in `karmaworld/assets`.
480
481 Additionally, all third party Python projects (downloaded and installed with
482 pip) are listed in these files:
483
484 * `requirements.txt`
485 * `requirements-dev.txt`
486
487 # Thanks
488
489 * KarmaNotes.org is a project of the FinalsClub Foundation with generous funding from the William and Flora Hewlett Foundation
490
491 * Also thanks to [rdegges](https://github.com/rdegges/django-skel) for the django-skel template