commit a8613846d0f0995f319f64d8f53cbbc5bac51394 Author: Invinceaman Date: Tue Jun 9 11:03:30 2020 -0400 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7167be7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.py[cod] +__pycache__/ + +secret.py +venv +.venv +db.sqlite3 +media diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..e4891d7 --- /dev/null +++ b/Pipfile @@ -0,0 +1,12 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +django = "*" +social-auth-app-django = "*" +pillow = "~=6.0" +whitenoise = "*" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..92de662 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,252 @@ +{ + "_meta": { + "hash": { + "sha256": "10c3d136466a23ce8f5df046909d4028d5b329539ae047b95bb0af54506fa480" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "asgiref": { + "hashes": [ + "sha256:8036f90603c54e93521e5777b2b9a39ba1bad05773fcf2d208f0299d1df58ce5", + "sha256:9ca8b952a0a9afa61d30aa6d3d9b570bb3fd6bafcf7ec9e6bed43b936133db1c" + ], + "version": "==3.2.7" + }, + "certifi": { + "hashes": [ + "sha256:5ad7e9a056d25ffa5082862e36f119f7f7cec6457fa07ee2f8c339814b80c9b1", + "sha256:9cd41137dc19af6a5e03b630eefe7d1f458d964d406342dd3edf625839b944cc" + ], + "version": "==2020.4.5.2" + }, + "cffi": { + "hashes": [ + "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff", + "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b", + "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac", + "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0", + "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384", + "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26", + "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6", + "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b", + "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e", + "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd", + "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2", + "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66", + "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc", + "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8", + "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55", + "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4", + "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5", + "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d", + "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78", + "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa", + "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793", + "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f", + "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a", + "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f", + "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30", + "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f", + "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3", + "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c" + ], + "version": "==1.14.0" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "cryptography": { + "hashes": [ + "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6", + "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b", + "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5", + "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf", + "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e", + "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b", + "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae", + "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b", + "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0", + "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b", + "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d", + "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229", + "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3", + "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365", + "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55", + "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270", + "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e", + "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785", + "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0" + ], + "version": "==2.9.2" + }, + "defusedxml": { + "hashes": [ + "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93", + "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5" + ], + "markers": "python_version >= '3.0'", + "version": "==0.6.0" + }, + "django": { + "hashes": [ + "sha256:5052b34b34b3425233c682e0e11d658fd6efd587d11335a0203d827224ada8f2", + "sha256:e1630333248c9b3d4e38f02093a26f1e07b271ca896d73097457996e0fae12e8" + ], + "index": "pypi", + "version": "==3.0.7" + }, + "idna": { + "hashes": [ + "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", + "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" + ], + "version": "==2.9" + }, + "oauthlib": { + "hashes": [ + "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", + "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" + ], + "version": "==3.1.0" + }, + "pillow": { + "hashes": [ + "sha256:00e0bbe9923adc5cc38a8da7d87d4ce16cde53b8d3bba8886cb928e84522d963", + "sha256:03457e439d073770d88afdd90318382084732a5b98b0eb6f49454746dbaae701", + "sha256:0d5c99f80068f13231ac206bd9b2e80ea357f5cf9ae0fa97fab21e32d5b61065", + "sha256:1a3bc8e1db5af40a81535a62a591fafdb30a8a1b319798ea8052aa65ef8f06d2", + "sha256:2b4a94be53dff02af90760c10a2e3634c3c7703410f38c98154d5ce71fe63d20", + "sha256:3ba7d8f1d962780f86aa747fef0baf3211b80cb13310fff0c375da879c0656d4", + "sha256:3e81485cec47c24f5fb27acb485a4fc97376b2b332ed633867dc68ac3077998c", + "sha256:43ef1cff7ee57f9c8c8e6fa02a62eae9fa23a7e34418c7ce88c0e3fe09d1fb38", + "sha256:4adc3302df4faf77c63ab3a83e1a3e34b94a6a992084f4aa1cb236d1deaf4b39", + "sha256:535e8e0e02c9f1fc2e307256149d6ee8ad3aa9a6e24144b7b6e6fb6126cb0e99", + "sha256:5ccfcb0a34ad9b77ad247c231edb781763198f405a5c8dc1b642449af821fb7f", + "sha256:5dcbbaa3a24d091a64560d3c439a8962866a79a033d40eb1a75f1b3413bfc2bc", + "sha256:6e2a7e74d1a626b817ecb7a28c433b471a395c010b2a1f511f976e9ea4363e64", + "sha256:82859575005408af81b3e9171ae326ff56a69af5439d3fc20e8cb76cd51c8246", + "sha256:834dd023b7f987d6b700ad93dc818098d7eb046bd445e9992b3093c6f9d7a95f", + "sha256:87ef0eca169f7f0bc050b22f05c7e174a65c36d584428431e802c0165c5856ea", + "sha256:900de1fdc93764be13f6b39dc0dd0207d9ff441d87ad7c6e97e49b81987dc0f3", + "sha256:92b83b380f9181cacc994f4c983d95a9c8b00b50bf786c66d235716b526a3332", + "sha256:aa1b0297e352007ec781a33f026afbb062a9a9895bb103c8f49af434b1666880", + "sha256:aa4792ab056f51b49e7d59ce5733155e10a918baf8ce50f64405db23d5627fa2", + "sha256:b72c39585f1837d946bd1a829a4820ccf86e361f28cbf60f5d646f06318b61e2", + "sha256:bb7861e4618a0c06c40a2e509c1bea207eea5fd4320d486e314e00745a402ca5", + "sha256:bc149dab804291a18e1186536519e5e122a2ac1316cb80f506e855a500b1cdd4", + "sha256:c424d35a5259be559b64490d0fd9e03fba81f1ce8e5b66e0a59de97547351d80", + "sha256:cbd5647097dc55e501f459dbac7f1d0402225636deeb9e0a98a8d2df649fc19d", + "sha256:ccf16fe444cc43800eeacd4f4769971200982200a71b1368f49410d0eb769543", + "sha256:d3a98444a00b4643b22b0685dbf9e0ddcaf4ebfd4ea23f84f228adf5a0765bb2", + "sha256:d6b4dc325170bee04ca8292bbd556c6f5398d52c6149ca881e67daf62215426f", + "sha256:db9ff0c251ed066d367f53b64827cc9e18ccea001b986d08c265e53625dab950", + "sha256:e3a797a079ce289e59dbd7eac9ca3bf682d52687f718686857281475b7ca8e6a" + ], + "index": "pypi", + "version": "==6.2.2" + }, + "pycparser": { + "hashes": [ + "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", + "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + ], + "version": "==2.20" + }, + "pyjwt": { + "hashes": [ + "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e", + "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96" + ], + "version": "==1.7.1" + }, + "python3-openid": { + "hashes": [ + "sha256:0086da6b6ef3161cfe50fb1ee5cceaf2cda1700019fda03c2c5c440ca6abe4fa", + "sha256:628d365d687e12da12d02c6691170f4451db28d6d68d050007e4a40065868502" + ], + "markers": "python_version >= '3.0'", + "version": "==3.1.0" + }, + "pytz": { + "hashes": [ + "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed", + "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048" + ], + "version": "==2020.1" + }, + "requests": { + "hashes": [ + "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", + "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" + ], + "version": "==2.23.0" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a" + ], + "version": "==1.3.0" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "version": "==1.15.0" + }, + "social-auth-app-django": { + "hashes": [ + "sha256:02b561e175d4a93896e4436b591586b61e647bd8eeef14c99a26344eb3b48d0e", + "sha256:09575f5c7dd91465df3a898c58e7c4ae1e78f31edba36b8b7be47ab0aeef2789", + "sha256:47d1720115a9eaad78a67e99987d556abaa01222b9c2b9538182bbdbb10304ba" + ], + "index": "pypi", + "version": "==3.4.0" + }, + "social-auth-core": { + "hashes": [ + "sha256:21c0639c56befd33ec162c2210d583bb1de8e1136d53b21bafb96afaf2f86c91", + "sha256:2f6ce1af8ec2b2cc37b86d647f7d4e4292f091ee556941db34b1e0e2dee77fc0", + "sha256:4a3cdf69c449b235cdabd54a1be7ba3722611297e69fded52e3584b1a990af25" + ], + "version": "==3.3.3" + }, + "sqlparse": { + "hashes": [ + "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e", + "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548" + ], + "version": "==0.3.1" + }, + "urllib3": { + "hashes": [ + "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", + "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" + ], + "version": "==1.25.9" + }, + "whitenoise": { + "hashes": [ + "sha256:60154b976a13901414a25b0273a841145f77eb34a141f9ae032a0ace3e4d5b27", + "sha256:6dd26bfda3af29177d8ab7333a0c7b7642eb615ce83764f4d15a9aecda3201c4" + ], + "index": "pypi", + "version": "==5.1.0" + } + }, + "develop": {} +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..b970379 --- /dev/null +++ b/manage.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'studyguidebank.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/studyguidebank/Pipfile b/studyguidebank/Pipfile new file mode 100644 index 0000000..b723d01 --- /dev/null +++ b/studyguidebank/Pipfile @@ -0,0 +1,11 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] + +[requires] +python_version = "3.7" diff --git a/studyguidebank/__init__.py b/studyguidebank/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/auth/__init__.py b/studyguidebank/apps/auth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/auth/admin.py b/studyguidebank/apps/auth/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/studyguidebank/apps/auth/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/studyguidebank/apps/auth/apps.py b/studyguidebank/apps/auth/apps.py new file mode 100644 index 0000000..7d2794f --- /dev/null +++ b/studyguidebank/apps/auth/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class AuthConfig(AppConfig): + name = 'studyguidebank.apps.auth' + label = 'authentication' + diff --git a/studyguidebank/apps/auth/migrations/__init__.py b/studyguidebank/apps/auth/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/auth/models.py b/studyguidebank/apps/auth/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/studyguidebank/apps/auth/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/studyguidebank/apps/auth/oauth.py b/studyguidebank/apps/auth/oauth.py new file mode 100644 index 0000000..eafd17b --- /dev/null +++ b/studyguidebank/apps/auth/oauth.py @@ -0,0 +1,40 @@ +from social_core.backends.oauth import BaseOAuth2 +from social_core.pipeline.user import get_username as social_get_username + + +def get_username(strategy, details, user = None, *args, **kwargs): + result = social_get_username(strategy, details, user = user, *args, **kwargs) + return result + + +class IonOauth2(BaseOAuth2): + name = 'ion' + AUTHORIZATION_URL = 'https://ion.tjhsst.edu/oauth/authorize' + ACCESS_TOKEN_URL = 'https://ion.tjhsst.edu/oauth/token' + ACCESS_TOKEN_METHOD = 'POST' + EXTRA_DATA = [ + ('refresh_token', 'refresh_token', True), + ('expires_in', 'expires') + ] + + def get_scope(self): + return ["read"] + + def get_user_details(self, response): + profile = self.get_json( + 'https://ion.tjhsst.edu/api/profile', + params = {'access_token': response['access_token']}, + ) + # fields used to populate/update User model + return { + 'id': profile['id'], + 'username': profile['ion_username'], + 'first_name': profile['first_name'], + 'last_name': profile['last_name'], + 'full_name': profile['full_name'], + 'email': profile['tj_email'], + } + + def get_user_id(self, details, response): + return details["id"] + diff --git a/studyguidebank/apps/auth/tests.py b/studyguidebank/apps/auth/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/studyguidebank/apps/auth/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/studyguidebank/apps/auth/urls.py b/studyguidebank/apps/auth/urls.py new file mode 100644 index 0000000..af37471 --- /dev/null +++ b/studyguidebank/apps/auth/urls.py @@ -0,0 +1,11 @@ +from django.urls import path + +from . import views + +app_name = "auth" + +urlpatterns = [ + path("login", views.login, name = "login"), + path("logout", views.logout, name = "logout"), +] + diff --git a/studyguidebank/apps/auth/views.py b/studyguidebank/apps/auth/views.py new file mode 100644 index 0000000..def013a --- /dev/null +++ b/studyguidebank/apps/auth/views.py @@ -0,0 +1,10 @@ +from django.shortcuts import render +from django.contrib.auth.views import LogoutView + +# Create your views here. + +def login(request): + return render(request, "auth/login.html") + +logout = LogoutView.as_view() + diff --git a/studyguidebank/apps/context_processors.py b/studyguidebank/apps/context_processors.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/courses/__init__.py b/studyguidebank/apps/courses/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/courses/admin.py b/studyguidebank/apps/courses/admin.py new file mode 100644 index 0000000..efc4b51 --- /dev/null +++ b/studyguidebank/apps/courses/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin +from .models import Subject, Course, Unit +# Register your models here. + +admin.site.register(Subject) +admin.site.register(Course) +admin.site.register(Unit) diff --git a/studyguidebank/apps/courses/apps.py b/studyguidebank/apps/courses/apps.py new file mode 100644 index 0000000..a32e945 --- /dev/null +++ b/studyguidebank/apps/courses/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CoursesConfig(AppConfig): + name = 'courses' diff --git a/studyguidebank/apps/courses/migrations/__init__.py b/studyguidebank/apps/courses/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/courses/models.py b/studyguidebank/apps/courses/models.py new file mode 100644 index 0000000..1d00f98 --- /dev/null +++ b/studyguidebank/apps/courses/models.py @@ -0,0 +1,34 @@ +from django.db import models +from django.core.validators import RegexValidator, FileExtensionValidator + +# Create your models here. +class Subject(models.Model): + id = models.AutoField(primary_key = True) + name = models.CharField(max_length=100, unique = True) + url = models.CharField(max_length=20, unique = True, validators=[RegexValidator(regex="^[a-zA-Z0-9_\-]+$", message="Only alphanumeric, dashes, and underscores allowed")]) + + courses = models.ManyToManyField("Course", related_name="subject") + + def __str__(self): + return self.name + +class Course(models.Model): + id = models.AutoField(primary_key = True) + name = models.CharField(max_length=100, unique = True) + + units = models.ManyToManyField("Unit", related_name="course") + + def __str__(self): + return self.name + +class Unit(models.Model): + id = models.AutoField(primary_key = True) + name = models.CharField(max_length=100) + + pdf_file = models.FileField(upload_to='guides/', validators=[FileExtensionValidator(allowed_extensions=['pdf'])]) + + def __str__(self): + return self.name + + + diff --git a/studyguidebank/apps/courses/tests.py b/studyguidebank/apps/courses/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/studyguidebank/apps/courses/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/studyguidebank/apps/courses/urls.py b/studyguidebank/apps/courses/urls.py new file mode 100644 index 0000000..5dd63e1 --- /dev/null +++ b/studyguidebank/apps/courses/urls.py @@ -0,0 +1,9 @@ +from django.urls import path + +from . import views + +app_name = "courses" + +urlpatterns = [ + +] \ No newline at end of file diff --git a/studyguidebank/apps/courses/views.py b/studyguidebank/apps/courses/views.py new file mode 100644 index 0000000..3dba6ef --- /dev/null +++ b/studyguidebank/apps/courses/views.py @@ -0,0 +1,8 @@ +import random + +from django import http +from django.shortcuts import render, redirect, reverse, get_object_or_404 + +from .models import Subject, Course, Unit +# Create your views here. + diff --git a/studyguidebank/apps/home/__init__.py b/studyguidebank/apps/home/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/home/admin.py b/studyguidebank/apps/home/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/studyguidebank/apps/home/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/studyguidebank/apps/home/apps.py b/studyguidebank/apps/home/apps.py new file mode 100644 index 0000000..90dc713 --- /dev/null +++ b/studyguidebank/apps/home/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class HomeConfig(AppConfig): + name = 'home' diff --git a/studyguidebank/apps/home/migrations/__init__.py b/studyguidebank/apps/home/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/home/models.py b/studyguidebank/apps/home/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/studyguidebank/apps/home/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/studyguidebank/apps/home/tests.py b/studyguidebank/apps/home/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/studyguidebank/apps/home/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/studyguidebank/apps/home/urls.py b/studyguidebank/apps/home/urls.py new file mode 100644 index 0000000..1aaab90 --- /dev/null +++ b/studyguidebank/apps/home/urls.py @@ -0,0 +1,9 @@ +from django.urls import path +from . import views + +app_name = "home" + +urlpatterns = [ + path("", views.index_view, name = "index"), +] + diff --git a/studyguidebank/apps/home/views.py b/studyguidebank/apps/home/views.py new file mode 100644 index 0000000..7f0e0df --- /dev/null +++ b/studyguidebank/apps/home/views.py @@ -0,0 +1,10 @@ +from django.shortcuts import render, redirect +from django.http import HttpResponse + +# Create your views here. + +def index_view(request): + #return render(request, "home/index.html") + return HttpResponse("hello world") + + diff --git a/studyguidebank/apps/users/__init__.py b/studyguidebank/apps/users/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/apps/users/admin.py b/studyguidebank/apps/users/admin.py new file mode 100644 index 0000000..f9c7057 --- /dev/null +++ b/studyguidebank/apps/users/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from .models import User + +# Register your models here. + +admin.site.register(User, UserAdmin) diff --git a/studyguidebank/apps/users/apps.py b/studyguidebank/apps/users/apps.py new file mode 100644 index 0000000..4ce1fab --- /dev/null +++ b/studyguidebank/apps/users/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class UsersConfig(AppConfig): + name = 'users' diff --git a/studyguidebank/apps/users/models.py b/studyguidebank/apps/users/models.py new file mode 100644 index 0000000..f3fc791 --- /dev/null +++ b/studyguidebank/apps/users/models.py @@ -0,0 +1,48 @@ +from django.contrib.auth.models import AbstractUser +from django.db import models + +from social_django.utils import load_strategy + +import requests +import logging + +logger = logging.getLogger(__name__) + +# Create your models here. +class User(AbstractUser): + id = models.AutoField(primary_key = True) + full_name = models.CharField(max_length = 105) + + @property + def short_name(self): + return self.username + def __str__(self): + return self.full_name + def empty_fields(self): + list = [] + for field in User._meta.fields: + list.append((field.value_from_object(self),field)) + return list + def api_request(self, url, params={}, refresh=True): + s = self.get_social_auth() + params.update({"format": "json"}) + params.update({"access_token": s.access_token}) + r = requests.get( + "https://ion.tjhsst.edu/api/{}".format(url), + params = params, + ) + if r.status_code == 401: + if refresh: + try: + self.get_social_auth().refresh_token(load_strategy()) + except BaseException as e: + logger.exception(str(e)) + return self.api_request(url, params, False) + else: + logger.error( + "Ion API Request Failure: {} {}".format(r.status_code, + r.json())) + return r.json() + + def get_social_auth(self): + return self.social_auth.get(provider = "ion") diff --git a/studyguidebank/apps/users/tests.py b/studyguidebank/apps/users/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/studyguidebank/apps/users/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/studyguidebank/apps/users/urls.py b/studyguidebank/apps/users/urls.py new file mode 100644 index 0000000..f62712b --- /dev/null +++ b/studyguidebank/apps/users/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from . import views + +app_name = "users" + +urlpatterns = [ + +] + diff --git a/studyguidebank/apps/users/views.py b/studyguidebank/apps/users/views.py new file mode 100644 index 0000000..494a254 --- /dev/null +++ b/studyguidebank/apps/users/views.py @@ -0,0 +1,6 @@ +from django.shortcuts import render, redirect +from django import http +from .models import User +from django.forms import formset_factory +# Create your views here. + diff --git a/studyguidebank/settings/__init__.py b/studyguidebank/settings/__init__.py new file mode 100644 index 0000000..0bd520f --- /dev/null +++ b/studyguidebank/settings/__init__.py @@ -0,0 +1,182 @@ +""" +Django settings for studyguidebank project. + +Generated by 'django-admin startproject' using Django 2.2.1. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.2/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +PROJECT_ROOT = os.path.join(BASE_DIR, "studyguidebank") + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = ';IFmR4#o&[HCO+kLgfalA!F@s}q{I{e$fq/,1Q*f2`5YY=DW\\i' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'studyguides.tjhsst.edu', '*'] + +SOCIAL_AUTH_ION_KEY = "" + +SOCIAL_AUTH_ION_SECRET = "" + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'social_django', + 'studyguidebank.apps.courses', + 'studyguidebank.apps.home', + 'studyguidebank.apps.users', + 'studyguidebank.apps.auth.apps.AuthConfig', + + +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'whitenoise.middleware.WhiteNoiseMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'studyguidebank.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(BASE_DIR, "studyguidebank/templates") + #os.path.join(BASE_DIR, "templates/techmun") + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + 'social_django.context_processors.backends', + 'social_django.context_processors.login_redirect', + ], + }, + }, +] + +WSGI_APPLICATION = 'studyguidebank.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +AUTHENTICATION_BACKENDS = ( + 'studyguidebank.apps.auth.oauth.IonOauth2', + 'django.contrib.auth.backends.ModelBackend', +) + +SOCIAL_AUTH_USER_FIELDS = ['username', 'full_name', 'first_name', 'last_name', 'email', 'id'] + +SOCIAL_AUTH_URL_NAMESPACE = 'social' + +SOCIAL_AUTH_PIPELINE = ( + 'social_core.pipeline.social_auth.social_details', + 'social_core.pipeline.social_auth.social_uid', + 'social_core.pipeline.social_auth.auth_allowed', + 'social_core.pipeline.social_auth.social_user', + 'studyguidebank.apps.auth.oauth.get_username', + 'social_core.pipeline.social_auth.associate_by_email', + 'social_core.pipeline.user.create_user', + 'social_core.pipeline.social_auth.associate_user', + 'social_core.pipeline.social_auth.load_extra_data', +) + +AUTH_USER_MODEL = "users.User" + +SOCIAL_AUTH_ALWAYS_ASSOCIATE = True + +# Internationalization +# https://docs.djangoproject.com/en/2.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'America/New_York' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +LOGIN_URL = "auth:login" +LOGIN_REDIRECT_URL = "users:index" +LOGOUT_REDIRECT_URL = "home:index" + +SOCIAL_AUTH_LOGIN_ERROR_URL = '/' +SOCIAL_AUTH_RAISE_EXCEPTIONS = False + +# ION_REDIRECT_URI = 'http://localhost:8000/complete/ion' +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.2/howto/static-files/ + +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'studyguidebank/serve') + +STATICFILES_DIRS = ( + os.path.join(BASE_DIR, 'studyguidebank/static'), +) + +MEDIA_ROOT = os.path.join(BASE_DIR, 'studyguidebank/media') + +MEDIA_URL = "/media/" + +USE_X_FORWARDED_HOST = True + +STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' +from .secret import * diff --git a/studyguidebank/templates/base.html b/studyguidebank/templates/base.html new file mode 100644 index 0000000..e69de29 diff --git a/studyguidebank/urls.py b/studyguidebank/urls.py new file mode 100644 index 0000000..cfdcab8 --- /dev/null +++ b/studyguidebank/urls.py @@ -0,0 +1,32 @@ +"""studyguidebank URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include +from django.conf import settings +from django.conf.urls.static import static + +urlpatterns = [ + path('admin/', admin.site.urls), + + path('courses/', include('studyguidebank.apps.courses.urls', namespace = 'courses')), + path('auth/', include('studyguidebank.apps.auth.urls', namespace = 'auth')), + path('', include('studyguidebank.apps.home.urls', namespace='home')), + path('', include('social_django.urls', namespace = 'social')), + +] +if settings.DEBUG: + urlpatterns.extend(static("static/", document_root=settings.STATIC_ROOT)) + urlpatterns.extend(static("media/", document_root = settings.MEDIA_ROOT)) diff --git a/studyguidebank/wsgi.py b/studyguidebank/wsgi.py new file mode 100644 index 0000000..3855893 --- /dev/null +++ b/studyguidebank/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for studyguidebank project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'studyguidebank.settings') + +application = get_wsgi_application()