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