diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..cedc68dea4664a15d54e338f245710f4c545f98d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# Use the official Python image +FROM python:3.9-slimcd + +# Set the working directory +WORKDIR /code + +# Install system dependencies required for mysqlclient +RUN apt-get update && apt-get install -y \ + gcc \ + libmariadb-dev \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# Copy and install dependencies +COPY requirements.txt /code/ +RUN pip install --upgrade pip && pip install -r requirements.txt + +# Copy the project files +COPY . /code/ + +# Command to run the application +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..aee73115063575b38e6c35eae746ea9f80981029 --- /dev/null +++ b/Pipfile @@ -0,0 +1,16 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +django = ">=4.0" +mysqlclient = "*" +djangorestframework = "*" +pymysql = "*" +cryptography = "*" + +[dev-packages] + +[requires] +python_version = "3.13" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000000000000000000000000000000000000..5ac1f0fc67255d64a907b4fb1e750145f4f83e9a --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,210 @@ +{ + "_meta": { + "hash": { + "sha256": "2945d5ab87cd0426818793fb4ba82a8e6f0ecac5546e04c1fbb52e092c8cea36" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.13" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "asgiref": { + "hashes": [ + "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", + "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590" + ], + "markers": "python_version >= '3.8'", + "version": "==3.8.1" + }, + "cffi": { + "hashes": [ + "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", + "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", + "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1", + "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", + "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", + "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", + "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", + "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", + "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", + "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", + "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc", + "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", + "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", + "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", + "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", + "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", + "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", + "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", + "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", + "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b", + "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", + "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", + "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c", + "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", + "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", + "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", + "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", + "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", + "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", + "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", + "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", + "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", + "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", + "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", + "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", + "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", + "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", + "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", + "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", + "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", + "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", + "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", + "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", + "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964", + "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", + "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", + "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", + "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", + "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", + "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", + "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", + "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", + "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", + "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", + "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", + "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", + "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", + "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9", + "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", + "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", + "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", + "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", + "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", + "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", + "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", + "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", + "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b" + ], + "markers": "python_version >= '3.8'", + "version": "==1.17.1" + }, + "cryptography": { + "hashes": [ + "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390", + "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41", + "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688", + "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5", + "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1", + "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d", + "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7", + "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843", + "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5", + "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c", + "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a", + "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79", + "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6", + "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181", + "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4", + "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5", + "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562", + "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639", + "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922", + "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3", + "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d", + "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471", + "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd", + "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa", + "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb", + "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699", + "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb", + "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa", + "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0", + "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23", + "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9", + "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615", + "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea", + "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7", + "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308" + ], + "index": "pypi", + "markers": "python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1'", + "version": "==44.0.2" + }, + "django": { + "hashes": [ + "sha256:1323617cb624add820cb9611cdcc788312d250824f92ca6048fda8625514af2b", + "sha256:30de4ee43a98e5d3da36a9002f287ff400b43ca51791920bfb35f6917bfe041c" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==5.1.7" + }, + "djangorestframework": { + "hashes": [ + "sha256:bea7e9f6b96a8584c5224bfb2e4348dfb3f8b5e34edbecb98da258e892089361", + "sha256:f022ff46613584de994c0c6a4aebbace5fd700555fbe9d33b865ebf173eba6c9" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==3.16.0" + }, + "mysqlclient": { + "hashes": [ + "sha256:199dab53a224357dd0cb4d78ca0e54018f9cee9bf9ec68d72db50e0a23569076", + "sha256:201a6faa301011dd07bca6b651fe5aaa546d7c9a5426835a06c3172e1056a3c5", + "sha256:24ae22b59416d5fcce7e99c9d37548350b4565baac82f95e149cac6ce4163845", + "sha256:2e3c11f7625029d7276ca506f8960a7fd3c5a0a0122c9e7404e6a8fe961b3d22", + "sha256:4b4c0200890837fc64014cc938ef2273252ab544c1b12a6c1d674c23943f3f2e", + "sha256:92af368ed9c9144737af569c86d3b6c74a012a6f6b792eb868384787b52bb585", + "sha256:977e35244fe6ef44124e9a1c2d1554728a7b76695598e4b92b37dc2130503069", + "sha256:a22d99d26baf4af68ebef430e3131bb5a9b722b79a9fcfac6d9bbf8a88800687" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2.2.7" + }, + "pycparser": { + "hashes": [ + "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" + ], + "markers": "python_version >= '3.8'", + "version": "==2.22" + }, + "pymysql": { + "hashes": [ + "sha256:4de15da4c61dc132f4fb9ab763063e693d521a80fd0e87943b9a453dd4c19d6c", + "sha256:e127611aaf2b417403c60bf4dc570124aeb4a57f5f37b8e95ae399a42f904cd0" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==1.1.1" + }, + "sqlparse": { + "hashes": [ + "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", + "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca" + ], + "markers": "python_version >= '3.8'", + "version": "==0.5.3" + }, + "tzdata": { + "hashes": [ + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" + ], + "markers": "python_version >= '2'", + "version": "==2025.2" + } + }, + "develop": {} +} diff --git a/README.md b/README.md index a4a019c63d08f68fbacced9f1d9b156f523c1d30..fef23e329fd0ad41f4e961ba1ddfa3c83c641016 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Uni Hub - DSD Project +# GROUP_PROJECT_UWE @@ -11,18 +11,18 @@ Already a pro? Just edit this README.md and make it your own. Want to make it ea ## Add your files - [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command: +- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: ``` cd existing_repo -git remote add origin https://gitlab.uwe.ac.uk/y2-youssef/uni-hub-dsd-project.git +git remote add origin https://gitlab.uwe.ac.uk/m2-sefari/group_project_uwe.git git branch -M main git push -uf origin main ``` ## Integrate with your tools -- [ ] [Set up project integrations](https://gitlab.uwe.ac.uk/y2-youssef/uni-hub-dsd-project/-/settings/integrations) +- [ ] [Set up project integrations](https://gitlab.uwe.ac.uk/m2-sefari/group_project_uwe/-/settings/integrations) ## Collaborate with your team @@ -30,7 +30,7 @@ git push -uf origin main - [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) - [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) - [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/) +- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) ## Test and Deploy diff --git a/accounts/__init__.py b/accounts/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/accounts/__pycache__/__init__.cpython-313.pyc b/accounts/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..63ab691557bfd2616aeb18a6be3cf1feab5f7234 Binary files /dev/null and b/accounts/__pycache__/__init__.cpython-313.pyc differ diff --git a/accounts/__pycache__/__init__.cpython-39.pyc b/accounts/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0bc38790f85d990d9ad61ddc79c2ee330f977ba1 Binary files /dev/null and b/accounts/__pycache__/__init__.cpython-39.pyc differ diff --git a/accounts/__pycache__/admin.cpython-313.pyc b/accounts/__pycache__/admin.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81ef455e5599562790f2d46bee1fa32b66089b14 Binary files /dev/null and b/accounts/__pycache__/admin.cpython-313.pyc differ diff --git a/accounts/__pycache__/admin.cpython-39.pyc b/accounts/__pycache__/admin.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f588d68e1308cf3485b01f620556527c1fc08e69 Binary files /dev/null and b/accounts/__pycache__/admin.cpython-39.pyc differ diff --git a/accounts/__pycache__/apps.cpython-313.pyc b/accounts/__pycache__/apps.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c738dfa96d77fa16bb801c08988f041f288b900d Binary files /dev/null and b/accounts/__pycache__/apps.cpython-313.pyc differ diff --git a/accounts/__pycache__/apps.cpython-39.pyc b/accounts/__pycache__/apps.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1fed5bf79691aeedf50c4e89bdb54f0097d347e Binary files /dev/null and b/accounts/__pycache__/apps.cpython-39.pyc differ diff --git a/accounts/__pycache__/auth_forms.cpython-39.pyc b/accounts/__pycache__/auth_forms.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bab1fa326ecd5cb46eb917ffeaf73d9c11a7edb7 Binary files /dev/null and b/accounts/__pycache__/auth_forms.cpython-39.pyc differ diff --git a/accounts/__pycache__/forms.cpython-313.pyc b/accounts/__pycache__/forms.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24d3ee5ecbd76875656389e502afb456b82b9170 Binary files /dev/null and b/accounts/__pycache__/forms.cpython-313.pyc differ diff --git a/accounts/__pycache__/forms.cpython-39.pyc b/accounts/__pycache__/forms.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8842586f3b933eb434500ad686c325b13c977a36 Binary files /dev/null and b/accounts/__pycache__/forms.cpython-39.pyc differ diff --git a/accounts/__pycache__/models.cpython-313.pyc b/accounts/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba8f239623aa2c93a88e0d9e92951fd5d256a5e9 Binary files /dev/null and b/accounts/__pycache__/models.cpython-313.pyc differ diff --git a/accounts/__pycache__/models.cpython-39.pyc b/accounts/__pycache__/models.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06b64117f518bc5c816e0a6d6b766ae4ae82c94d Binary files /dev/null and b/accounts/__pycache__/models.cpython-39.pyc differ diff --git a/accounts/__pycache__/urls.cpython-313.pyc b/accounts/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4dc712c771852614779519229b64f286d80a267 Binary files /dev/null and b/accounts/__pycache__/urls.cpython-313.pyc differ diff --git a/accounts/__pycache__/urls.cpython-39.pyc b/accounts/__pycache__/urls.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a26d0697866c0255bed01d4e1c00de3c3e9f0057 Binary files /dev/null and b/accounts/__pycache__/urls.cpython-39.pyc differ diff --git a/accounts/__pycache__/views.cpython-313.pyc b/accounts/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..490bec89c11f8102d00fdb854915497507a1cd68 Binary files /dev/null and b/accounts/__pycache__/views.cpython-313.pyc differ diff --git a/accounts/__pycache__/views.cpython-39.pyc b/accounts/__pycache__/views.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da3d75a994d4308aaad2c1e9133b117843171491 Binary files /dev/null and b/accounts/__pycache__/views.cpython-39.pyc differ diff --git a/accounts/admin.py b/accounts/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/accounts/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/accounts/apps.py b/accounts/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..3e3c76595bcab116bb99a1722e542e07cdd23c71 --- /dev/null +++ b/accounts/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AccountsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'accounts' diff --git a/accounts/decorators.py b/accounts/decorators.py new file mode 100644 index 0000000000000000000000000000000000000000..1b3043957d14e724beb2519671e40e3f61d0d7cc --- /dev/null +++ b/accounts/decorators.py @@ -0,0 +1,11 @@ +from django.core.exceptions import PermissionDenied + +def role_required(allowed_roles): + """ Restrict access to views based on user roles. """ + def decorator(view_func): + def wrapper(request, *args, **kwargs): + if not request.user.is_authenticated or request.user.role not in allowed_roles: + raise PermissionDenied # 403 Forbidden + return view_func(request, *args, **kwargs) + return wrapper + return decorator diff --git a/accounts/forms.py b/accounts/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..637109d3e108babae52a3fcddde5bc8c80fb014b --- /dev/null +++ b/accounts/forms.py @@ -0,0 +1,18 @@ +# accounts/forms.py +from django import forms +from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth.models import User +from django.contrib.auth import get_user_model + +User = get_user_model() + +class SignUpForm(UserCreationForm): + class Meta: + model = User + fields = ["username", "email", "password1", "password2"] + + + +# forms.py + + diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..34b418a68f21690bec35f9a0af54ed05aa8a767f --- /dev/null +++ b/accounts/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# Generated by Django 4.2.19 on 2025-03-06 22:56 + +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('role', models.CharField(choices=[('student', 'Student'), ('community_leader', 'Community Leader'), ('admin', 'Admin')], default='student', max_length=20)), + ('groups', models.ManyToManyField(blank=True, related_name='custom_user_groups', to='auth.group')), + ('user_permissions', models.ManyToManyField(blank=True, related_name='custom_user_permissions', to='auth.permission')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + ] diff --git a/accounts/migrations/__init__.py b/accounts/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/accounts/migrations/__pycache__/0001_initial.cpython-39.pyc b/accounts/migrations/__pycache__/0001_initial.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..41c6efb56fee2663616aff7ded2853aac90f243d Binary files /dev/null and b/accounts/migrations/__pycache__/0001_initial.cpython-39.pyc differ diff --git a/accounts/migrations/__pycache__/__init__.cpython-39.pyc b/accounts/migrations/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef155c26c26564f4d41fbb44fd05016f668ac3cf Binary files /dev/null and b/accounts/migrations/__pycache__/__init__.cpython-39.pyc differ diff --git a/accounts/models.py b/accounts/models.py new file mode 100644 index 0000000000000000000000000000000000000000..78c42db8500c0c074a16c13ea034354b55656dab --- /dev/null +++ b/accounts/models.py @@ -0,0 +1,31 @@ +from django.contrib.auth.models import AbstractUser +from django.db import models + +class User(AbstractUser): + STUDENT = 'student' + COMMUNITY_LEADER = 'community_leader' + ADMIN = 'admin' + + ROLE_CHOICES = [ + (STUDENT, 'Student'), + (COMMUNITY_LEADER, 'Community Leader'), + (ADMIN, 'Admin'), + ] + + role = models.CharField(max_length=20, choices=ROLE_CHOICES, default=STUDENT) + + # Fix for SystemCheckError: Add `related_name` to prevent clashes with auth.User + groups = models.ManyToManyField( + "auth.Group", + related_name="custom_user_groups", + blank=True + ) + user_permissions = models.ManyToManyField( + "auth.Permission", + related_name="custom_user_permissions", + blank=True + ) + + + +# Create your models here. diff --git a/accounts/templates/accounts/login.html b/accounts/templates/accounts/login.html new file mode 100644 index 0000000000000000000000000000000000000000..96f3d182847ec172f2a6abfecbad34734ea16f4a --- /dev/null +++ b/accounts/templates/accounts/login.html @@ -0,0 +1,16 @@ +<!-- templates/accounts/signup.html --> +<!DOCTYPE html> +<html> +<head> + <title>Login</title> +</head> +<body> + <h2>Login</h2> + <form method="post"> + {% csrf_token %} + {{ form.as_p }} + <button type="submit">Login</button> + </form> + <p>Don't have an account? <a href="{% url 'signup' %}">Register here</a>.</p> +</body> +</html> diff --git a/accounts/templates/accounts/signup.html b/accounts/templates/accounts/signup.html new file mode 100644 index 0000000000000000000000000000000000000000..d0f7a9c4592e6dc0caad09cf73ea7faf47b873a8 --- /dev/null +++ b/accounts/templates/accounts/signup.html @@ -0,0 +1,16 @@ +<!-- templates/accounts/login.html --> +<!DOCTYPE html> +<html> +<head> + <title>Sign Up</title> +</head> +<body> + <h2>Sign Up</h2> + <form method="post"> + {% csrf_token %} + {{ form.as_p }} + <button type="submit">Sign Up</button> + </form> + <p>Already have an account?<a href="{% url 'login' %}">Login here</a>.</p> +</body> +</html> diff --git a/accounts/tests.py b/accounts/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/accounts/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/accounts/urls.py b/accounts/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..301858ab4f0d34be91e8e2a081478bd46317acf6 --- /dev/null +++ b/accounts/urls.py @@ -0,0 +1,10 @@ +# accounts/urls.py +from django.urls import path +from .views import signup_view, login_view +from django.contrib.auth.views import LogoutView + +urlpatterns = [ + path("signup/", signup_view, name="signup"), + path("login/", login_view, name="login"), + path("logout/", LogoutView.as_view(next_page="login"), name="logout"), +] diff --git a/accounts/views.py b/accounts/views.py new file mode 100644 index 0000000000000000000000000000000000000000..3680ccd568b644643fb3b3b54ac970f6121db187 --- /dev/null +++ b/accounts/views.py @@ -0,0 +1,32 @@ +from django.shortcuts import render +# accounts/views.py +from django.shortcuts import render, redirect +from django.contrib.auth import login, authenticate +from django.contrib.auth.forms import AuthenticationForm + +from .forms import SignUpForm + +def signup_view(request): + if request.method == "POST": + form = SignUpForm(request.POST) + if form.is_valid(): + user = form.save() + login(request, user) # Automatically log in the user after signup + return redirect("home") # Redirect to homepage after signup + else: + form = SignUpForm() + return render(request, "accounts/signup.html", {"form": form}) + +def login_view(request): + if request.method == "POST": + form = AuthenticationForm(request, data=request.POST) + if form.is_valid(): + user = form.get_user() + login(request, user) + return redirect("home") # Redirect to homepage after login + else: + form = AuthenticationForm() + return render(request, "accounts/login.html", {"form": form}) + + +# Create your views here. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..294c75f41fc03bb5aea78f6f0124b55780d62571 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ + +services: + web: + build: . + command: python manage.py runserver 0.0.0.0:8000 + volumes: + - .:/code + ports: + - "8000:8000" + depends_on: + - db + + db: + image: mysql:8.0 + restart: always + environment: + MYSQL_DATABASE: unihub_db + MYSQL_USER: unihub_user + MYSQL_PASSWORD: Thescotts111 + MYSQL_ROOT_PASSWORD: Constantine.25 + ports: + - "3307:3306" + volumes: + - db_data:/var/lib/mysql + +volumes: + db_data: diff --git a/events/__init__.py b/events/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/events/__pycache__/__init__.cpython-313.pyc b/events/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81fd327f1a1854dd82d2e08cec1ea1d8efa9c99b Binary files /dev/null and b/events/__pycache__/__init__.cpython-313.pyc differ diff --git a/events/__pycache__/__init__.cpython-39.pyc b/events/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07c93c299966525bb0dc622df306925289af718a Binary files /dev/null and b/events/__pycache__/__init__.cpython-39.pyc differ diff --git a/events/__pycache__/admin.cpython-313.pyc b/events/__pycache__/admin.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85bc0c386dbe0456b22170ca5b7fa2e5481a1ed3 Binary files /dev/null and b/events/__pycache__/admin.cpython-313.pyc differ diff --git a/events/__pycache__/admin.cpython-39.pyc b/events/__pycache__/admin.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c49eeed3100ad2cdafa4c41ca39dbccdb6af90a Binary files /dev/null and b/events/__pycache__/admin.cpython-39.pyc differ diff --git a/events/__pycache__/apps.cpython-313.pyc b/events/__pycache__/apps.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f869b4099b269e211c70696a8cff4d216864919 Binary files /dev/null and b/events/__pycache__/apps.cpython-313.pyc differ diff --git a/events/__pycache__/apps.cpython-39.pyc b/events/__pycache__/apps.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37181a8abb832d49b5a6c91ac678d152b2f0b3f3 Binary files /dev/null and b/events/__pycache__/apps.cpython-39.pyc differ diff --git a/events/__pycache__/forms.cpython-313.pyc b/events/__pycache__/forms.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edcd646bdc553765cd6c930a26c2cc72dc1d859b Binary files /dev/null and b/events/__pycache__/forms.cpython-313.pyc differ diff --git a/events/__pycache__/forms.cpython-39.pyc b/events/__pycache__/forms.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9aabdf07b080c83280a5d08b175275127a7f4139 Binary files /dev/null and b/events/__pycache__/forms.cpython-39.pyc differ diff --git a/events/__pycache__/models.cpython-313.pyc b/events/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bf1f0ac9993b8700854969bde01d7e201101eed Binary files /dev/null and b/events/__pycache__/models.cpython-313.pyc differ diff --git a/events/__pycache__/models.cpython-39.pyc b/events/__pycache__/models.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd7106e098e800bd3a6e197810a8db1f7ca78aba Binary files /dev/null and b/events/__pycache__/models.cpython-39.pyc differ diff --git a/events/__pycache__/urls.cpython-313.pyc b/events/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e92f1c16f9a755e6408ae0499c87a268fe41634 Binary files /dev/null and b/events/__pycache__/urls.cpython-313.pyc differ diff --git a/events/__pycache__/urls.cpython-39.pyc b/events/__pycache__/urls.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee5c8912770e457abb17b6d4f2f1e379b14f02e8 Binary files /dev/null and b/events/__pycache__/urls.cpython-39.pyc differ diff --git a/events/__pycache__/views.cpython-313.pyc b/events/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0637b9595f1cf1bfd3006bdac8d8f2c183d68728 Binary files /dev/null and b/events/__pycache__/views.cpython-313.pyc differ diff --git a/events/__pycache__/views.cpython-39.pyc b/events/__pycache__/views.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3d48a69ccce03e41d2399db0a1989976706d79e Binary files /dev/null and b/events/__pycache__/views.cpython-39.pyc differ diff --git a/events/admin.py b/events/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/events/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/events/apps.py b/events/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..20f48f26beb374dce75650546404b1c5a26bb006 --- /dev/null +++ b/events/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class EventsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'events' diff --git a/events/forms.py b/events/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..d8efb620627471913da11d7cf581d8881638c2f4 --- /dev/null +++ b/events/forms.py @@ -0,0 +1,7 @@ +from django import forms +from .models import Event + +class EventForm(forms.ModelForm): + class Meta: + model = Event + fields = ["title", "description", "date", "time", "location"] diff --git a/events/migrations/0001_initial.py b/events/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..d3ece7df837c0f5cbbbdd2468666e34756c286b1 --- /dev/null +++ b/events/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# Generated by Django 4.2.20 on 2025-03-11 22:38 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255)), + ('description', models.TextField()), + ('date', models.DateField()), + ('time', models.TimeField()), + ('location', models.CharField(max_length=255)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('organizer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organized_events', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/events/migrations/__init__.py b/events/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/events/migrations/__pycache__/0001_initial.cpython-39.pyc b/events/migrations/__pycache__/0001_initial.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ff70ed178a0d1e18a7bf8a70edba9b2845be094 Binary files /dev/null and b/events/migrations/__pycache__/0001_initial.cpython-39.pyc differ diff --git a/events/migrations/__pycache__/__init__.cpython-39.pyc b/events/migrations/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37c89e2a65040891a4a594bcbedc537cf624664d Binary files /dev/null and b/events/migrations/__pycache__/__init__.cpython-39.pyc differ diff --git a/events/models.py b/events/models.py new file mode 100644 index 0000000000000000000000000000000000000000..5913ad1f9e8eaabc96cd60df3b7f326b75718d9b --- /dev/null +++ b/events/models.py @@ -0,0 +1,18 @@ +from django.db import models +from django.conf import settings + +class Event(models.Model): + title = models.CharField(max_length=255) + description = models.TextField() + date = models.DateField() + time = models.TimeField() + location = models.CharField(max_length=255) + organizer = models.ForeignKey( + settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="organized_events" + ) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.title + +# Create your models here. diff --git a/events/templates/events/event_detail.html b/events/templates/events/event_detail.html new file mode 100644 index 0000000000000000000000000000000000000000..d11f455f476c6d7aefba22f46959f059464e81fc --- /dev/null +++ b/events/templates/events/event_detail.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block content %} +<h2>{{ event.title }}</h2> +<p><strong>Date:</strong> {{ event.date }} at {{ event.time }}</p> +<p><strong>Location:</strong> {{ event.location }}</p> +<p>{{ event.description }}</p> +{% endblock %} diff --git a/events/templates/events/event_form.html b/events/templates/events/event_form.html new file mode 100644 index 0000000000000000000000000000000000000000..cc7b8c92c4e1357b8f75c76d3cdb6cbe10bab867 --- /dev/null +++ b/events/templates/events/event_form.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} +{% block content %} +<h2>Create an Event</h2> +<form method="POST"> + {% csrf_token %} + {{ form.as_p }} + <button type="submit">Save Event</button> +</form> +{% endblock %} diff --git a/events/templates/events/event_list.html b/events/templates/events/event_list.html new file mode 100644 index 0000000000000000000000000000000000000000..509e014b0bf365c47a69b6a8db83236508dd3699 --- /dev/null +++ b/events/templates/events/event_list.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} + <h2>Upcoming Events</h2> + <ul> + {% for event in events %} + <li><a href="{% url 'event_detail' event.id %}">{{ event.title }}</a> - {{ event.date }}</li> + {% empty %} + <li>No events available.</li> + {% endfor %} + </ul> + + {% if user.is_authenticated and user.role == "community_leader" %} + <a href="{% url 'create_event' %}">Create Event</a> + {% endif %} +{% endblock %} diff --git a/events/templates/home.html b/events/templates/home.html new file mode 100644 index 0000000000000000000000000000000000000000..8e6f219d95494fd1c3769c8ffcd05768d33c633a --- /dev/null +++ b/events/templates/home.html @@ -0,0 +1,2 @@ +<h1>Welcome to Uni Hub</h1> +<p>Go to <a href="/events/">Events</a></p> diff --git a/events/tests.py b/events/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/events/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/events/urls.py b/events/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..7377619cf33ab7785872f2610819dd1cd19dedad --- /dev/null +++ b/events/urls.py @@ -0,0 +1,11 @@ +from django.urls import path +from .views import event_list, event_detail, create_event + + +urlpatterns = [ + path("", event_list, name="event_list"), # Show all events + path("<int:event_id>/", event_detail, name="event_detail"), # View event details + path("create/", create_event, name="create_event"), # Create an event +] + + diff --git a/events/views.py b/events/views.py new file mode 100644 index 0000000000000000000000000000000000000000..eacb72c94b6ceec0a62f61f9a56710e0270b33e6 --- /dev/null +++ b/events/views.py @@ -0,0 +1,32 @@ +from django.shortcuts import render, get_object_or_404, redirect +from django.contrib.auth.decorators import login_required +from .models import Event +from .forms import EventForm + +# ✅ View All Events (Homepage) +def event_list(request): + events = Event.objects.all().order_by('date') + return render(request, "events/event_list.html", {"events": events}) + +# ✅ View a Single Event +def event_detail(request, event_id): + event = get_object_or_404(Event, id=event_id) + return render(request, "events/event_detail.html", {"event": event}) + +# ✅ Create an Event (Only for Community Leaders) +@login_required +def create_event(request): + if request.user.role != "community_leader": # Restrict access + return redirect("event_list") # Redirect unauthorized users + + if request.method == "POST": + form = EventForm(request.POST) + if form.is_valid(): + event = form.save(commit=False) + event.organizer = request.user # Set the event creator + event.save() + return redirect("event_list") + else: + form = EventForm() + + return render(request, "events/event_form.html", {"form": form}) diff --git a/manage.py b/manage.py new file mode 100644 index 0000000000000000000000000000000000000000..497afbc36b6be7facc3b6a6420b630390b413385 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unihub_project.settings') + + try: + from django.core.management import execute_from_command_line + except ImportError: + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable?" + ) + raise + + execute_from_command_line(sys.argv) + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fabc354a21ad8c3f7aab29d4488cc238e67e6d58 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +Django>=4.0 +mysqlclient +djangorestframework +pymysql +cryptography diff --git a/unihub_project/__init__.py b/unihub_project/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/unihub_project/__pycache__/__init__.cpython-313.pyc b/unihub_project/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77b1621ecfe7f0844cf92f21e92efc123645fae2 Binary files /dev/null and b/unihub_project/__pycache__/__init__.cpython-313.pyc differ diff --git a/unihub_project/__pycache__/__init__.cpython-39.pyc b/unihub_project/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c893463e52528bb5219b3f6587d4cf85c5371ff Binary files /dev/null and b/unihub_project/__pycache__/__init__.cpython-39.pyc differ diff --git a/unihub_project/__pycache__/settings.cpython-313.pyc b/unihub_project/__pycache__/settings.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb8c527d375feb8531c6c77abea1dd56c24c28fa Binary files /dev/null and b/unihub_project/__pycache__/settings.cpython-313.pyc differ diff --git a/unihub_project/__pycache__/settings.cpython-39.pyc b/unihub_project/__pycache__/settings.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92d747bfaf1605954944f125db7e4cd20b58e124 Binary files /dev/null and b/unihub_project/__pycache__/settings.cpython-39.pyc differ diff --git a/unihub_project/__pycache__/urls.cpython-313.pyc b/unihub_project/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c725bca990714f571f369a13026b258e0f8067c8 Binary files /dev/null and b/unihub_project/__pycache__/urls.cpython-313.pyc differ diff --git a/unihub_project/__pycache__/urls.cpython-39.pyc b/unihub_project/__pycache__/urls.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..476840f2406d3b785ac9d1d402638f6149707e40 Binary files /dev/null and b/unihub_project/__pycache__/urls.cpython-39.pyc differ diff --git a/unihub_project/__pycache__/views.cpython-313.pyc b/unihub_project/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e59009d6588ca854fc5532d6fc070549160e1d1 Binary files /dev/null and b/unihub_project/__pycache__/views.cpython-313.pyc differ diff --git a/unihub_project/__pycache__/views.cpython-39.pyc b/unihub_project/__pycache__/views.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91529644c8eda20741bd3dd07afca03ab6032b4c Binary files /dev/null and b/unihub_project/__pycache__/views.cpython-39.pyc differ diff --git a/unihub_project/__pycache__/wsgi.cpython-39.pyc b/unihub_project/__pycache__/wsgi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..56c909a3d223001ddc5f74ef328b5ad153c132e7 Binary files /dev/null and b/unihub_project/__pycache__/wsgi.cpython-39.pyc differ diff --git a/unihub_project/asgi.py b/unihub_project/asgi.py new file mode 100644 index 0000000000000000000000000000000000000000..02da32152d7e269360664e23e7502f96983aa229 --- /dev/null +++ b/unihub_project/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for unihub_project project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unihub_project.settings') + +application = get_asgi_application() diff --git a/unihub_project/settings.py b/unihub_project/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..745d403881a0fbfc196ffda3cee25f6035400160 --- /dev/null +++ b/unihub_project/settings.py @@ -0,0 +1,137 @@ +""" +Django settings for unihub_project project. + +Generated by 'django-admin startproject' using Django 5.1.6. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +from pathlib import Path +import pymysql +pymysql.install_as_MySQLdb() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-9os%w6o3zjgxf-7^=51h4vtl)j)7e4yp--puf!v8_zmh7!#@nc' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'accounts', + 'events', +] + +AUTH_USER_MODEL = 'accounts.User' + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + '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 = 'unihub_project.urls' + + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + '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', + ], + }, + }, +] + +WSGI_APPLICATION = 'unihub_project.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +# unihub_project/settings.py + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'unihub_db', + 'USER': 'unihub_user', + 'PASSWORD': 'Thescotts111', + 'HOST': 'db', # Refer to the service name in docker-compose.yml + 'PORT': '3306', + } +} + + + +# Password validation +# https://docs.djangoproject.com/en/5.1/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', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/unihub_project/urls.py b/unihub_project/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..0feeb72922d0a6cf108adb0f9c5b356caa59a71f --- /dev/null +++ b/unihub_project/urls.py @@ -0,0 +1,26 @@ +""" +URL configuration for unihub_project project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.1/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 .views import home_view # Import the homepage view + +urlpatterns = [ + path("admin/", admin.site.urls), + path("accounts/", include("accounts.urls")), # Include accounts URLs + path("events/", include("events.urls")), # Include events URLs + path("", home_view, name="home"), # Homepage +] diff --git a/unihub_project/views.py b/unihub_project/views.py new file mode 100644 index 0000000000000000000000000000000000000000..ab86773e39581e9ed649212d223d75ae4ab3d1e2 --- /dev/null +++ b/unihub_project/views.py @@ -0,0 +1,4 @@ +from django.shortcuts import render + +def home_view(request): + return render(request, "home.html") # This will look for templates/home.html diff --git a/unihub_project/wsgi.py b/unihub_project/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..d8a08ab5372c0839f9dfc22c87c6474b106651b6 --- /dev/null +++ b/unihub_project/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for unihub_project 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/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unihub_project.settings') + +application = get_wsgi_application()