diff --git a/.gitignore b/.gitignore index 5f9bb7d6d4966cde2b06f26d5f668b449a925dcb..af110197bcd3394c9ec1965cd540b46e16c0d8ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,8 @@ -.idea/ .DS_Store *.sqlite3 __pycache__ # dependencies -*/node_modules -/.pnp -.pnp.js # testing /coverage @@ -22,12 +18,14 @@ __pycache__ .env.production.local .env -npm-debug.log* yarn-debug.log* yarn-error.log* *.eslintcache */media/account/images/ -solar/django_static +the_social_network/django_static pypi/*/ + +the_social_network/dist +the_social_network/the_social_network.egg-info \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..e9a3fad77e07d3fe00ed0541cf51896ab67ad3db --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,54 @@ +image: docker + +services: + - docker:dind + +stages: + - build + - test + - deploy + +before_script: + - docker version + - apk add --no-cache docker-compose + - docker-compose version + - docker login -u gitlab-ci-token -p $REGISTRY_TOKEN $REGISTRY + +after_script: + - docker-compose -f docker-compose.ci.yml down + - docker-compose -f docker-compose.ci.yml ps + + +build: + stage: build + script: + - echo "Building ..." + - docker-compose -f docker-compose.ci.yml build + - docker-compose -f docker-compose.ci.yml push + +test: + stage: test + needs: + - build + script: + - echo "Testing ..." + - docker-compose -f docker-compose.ci.yml pull + - docker-compose -f docker-compose.ci.yml run web sh -c "poetry run python manage.py makemigrations && poetry run python manage.py migrate && poetry run python manage.py test core -v 2" + +deploy: + only: + - main + stage: deploy + needs: + - test + script: + - echo "Deploying ..." + - cd ./the_social_network + - mv ./the_social_network ./not_needed + - mv ./core ./the_social_network + - apk add py-pip + - pip install poetry + - poetry --version + - poetry config pypi-token.pypi $PYPI_TOKEN + - poetry build + - poetry publish diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 8e60571b6ab19789cf8ddfbda397be30e2485890..0000000000000000000000000000000000000000 --- a/Pipfile +++ /dev/null @@ -1,16 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -django = "*" -django-cors-headers = "*" -djangorestframework = "*" -pillow = "*" -uwsgi = "*" - -[dev-packages] - -[requires] -python_version = "3.9" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 9d8d6a14c906b3b26240170a8390306e493429f0..0000000000000000000000000000000000000000 --- a/Pipfile.lock +++ /dev/null @@ -1,122 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "f1ffc1e60d515d604136eec07eea7e16c697c4e5529414b3b41eb9a672871223" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.9" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "asgiref": { - "hashes": [ - "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9", - "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214" - ], - "markers": "python_version >= '3.6'", - "version": "==3.4.1" - }, - "django": { - "hashes": [ - "sha256:51284300f1522ffcdb07ccbdf676a307c6678659e1284f0618e5a774127a6a08", - "sha256:e22c9266da3eec7827737cde57694d7db801fedac938d252bf27377cec06ed1b" - ], - "index": "pypi", - "version": "==3.2.9" - }, - "django-cors-headers": { - "hashes": [ - "sha256:cba6e99659abb0e47cc4aaabb8fcde03f193e6bb3b92ba47c5185ec4cedc5d9e", - "sha256:cd6f4360f5246569c149dc1c40c907c191f1ec45551e10d2a2e2e68512652f78" - ], - "index": "pypi", - "version": "==3.10.0" - }, - "djangorestframework": { - "hashes": [ - "sha256:6d1d59f623a5ad0509fe0d6bfe93cbdfe17b8116ebc8eda86d45f6e16e819aaf", - "sha256:f747949a8ddac876e879190df194b925c177cdeb725a099db1460872f7c0a7f2" - ], - "index": "pypi", - "version": "==3.12.4" - }, - "pillow": { - "hashes": [ - "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76", - "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585", - "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b", - "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8", - "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55", - "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc", - "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645", - "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff", - "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc", - "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b", - "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6", - "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20", - "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e", - "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a", - "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779", - "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02", - "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39", - "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f", - "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a", - "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409", - "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c", - "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488", - "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b", - "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d", - "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09", - "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b", - "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153", - "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9", - "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad", - "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df", - "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df", - "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed", - "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed", - "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698", - "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29", - "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649", - "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49", - "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b", - "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2", - "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a", - "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78" - ], - "index": "pypi", - "version": "==8.4.0" - }, - "pytz": { - "hashes": [ - "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c", - "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326" - ], - "version": "==2021.3" - }, - "sqlparse": { - "hashes": [ - "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae", - "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d" - ], - "markers": "python_version >= '3.5'", - "version": "==0.4.2" - }, - "uwsgi": { - "hashes": [ - "sha256:88ab9867d8973d8ae84719cf233b7dafc54326fcaec89683c3f9f77c002cdff9" - ], - "index": "pypi", - "version": "==2.0.20" - } - }, - "develop": {} -} diff --git a/README.md b/README.md index bce1a47864659f837d009c27a232c9287f06a036..6c32fcb53bc5008b9c9880465b4b7097d18959d0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,69 @@ # The Social Network -TBA \ No newline at end of file +`the_social_network/` is the backend of the most thinkable fronted for social networks, which was developed with [Django](https://www.djangoproject.com/) and [Django Rest Framework](https://www.django-rest-framework.org/) + +This subproject is the basis for any possible type of social networks. + +The `core/` subfolder is the core of this project an is managed to working as a starting point for any further works on basic social networks. + +Use the [Postman-Documentation](https://documenter.getpostman.com/view/13331140/TzRNFVaC) and run it locally for a detailed overview about the API. +Make sure the database is seeded with corresponding data. + +## Requirements + +Before using this project one must create the corresponding virtual environment if there is none. +Otherwise the virtual environment can be joined with the same command: + + $ pipenv shell + +If the dependencies listed in `Pipfile` are not installed in the virtual environment they can be installed by using: + + $ pipenv install + +If the database is not existent then the following command can be used to make all existing migrations: + + $ pipenv run python manage.py migrate + +Afterwards this project should be ready to use. + +## Environment + +Before one can start this project a environment file must be defined regarding the mode in which this project should operate in. +Therefore the variables inside `.env` can be changed accordingly. + +| Variable | Development | Production | Use | +|:--------------------:|:-----------:|:-------------------:|:----------------------------------------------------------------------:| +| CORS_ORIGIN_ALLOW_ALL| True | False | Turn on/off cross-origin resource sharing | +| DEBUG | True | False | For turn on/off the debug mode and the corresponding debug logging | +| DJANGO_ALLOWED_HOSTS | * | tsn.marc-feger.de | List of strings representing the host/domain names this site can serve | +| SECRET_KEY | ------ | ------ | For cryptographic signing. Should be a unique, unpredictable value. | + +### Development + +For the development mode of this project one must specify an `.env` file like specified in the table above. +Any code changes will we validated and added after the automated refresh of the running service. + +To start this project the following command can be used: + + $ pipenv run python manage.py runserver + +### Database + +If any new database model has been added to the project one must add the migrations with: + + $ pipenv run python manage.py makemigrations + +To make those migrations visible and to add them permanently to the database one must use: + + $ pipenv run python manage.py migrate + +### Testing + +Each application in this project contains test to validate the working code of this project. +To test everything one can use: + + $ pipenv run python manage.py test + +To test specific applications one can use: + + $ pipenv run python manage.py test <e.g. accounts or contents ...> diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..0f0ff87877d3eab802235337eae733cffdf7a2b8 --- /dev/null +++ b/docker-compose.ci.yml @@ -0,0 +1,7 @@ +version: "3" +services: + web: + build: ./the_social_network + image: ${REGISTRY}/feger/the-social-network/web:latest + volumes: + - ./the_social_network:/code \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..a186eadccf58680390287d22147a8ecae29974f1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3' + +services: + the_social_network: + container_name: the_social_network + build: ./the_social_network + restart: always + command: sh -c "poetry run python manage.py collectstatic --noinput && poetry run python manage.py runserver 0.0.0.0:9000" + volumes: + - ./the_social_network:/code + networks: + - webnet + ports: + - "9000:9000" + +networks: + webnet: diff --git a/the_social_network/Dockerfile b/the_social_network/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..682978732915d43d2506b6fcefd5abb9f43b17ea --- /dev/null +++ b/the_social_network/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9-alpine +ENV PYTHONUNBUFFERED 1 +RUN apk update && \ + apk add --virtual build-deps curl gcc python3-dev musl-dev openssl-dev libffi-dev build-base linux-headers && \ + apk add jpeg-dev zlib-dev libjpeg pcre-dev +WORKDIR /code +COPY pyproject.toml ./ +RUN pip install poetry +RUN poetry install +COPY . ./ +RUN apk del build-deps diff --git a/the_social_network/LICENSE b/the_social_network/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..244da3cd363fc1f62ff56c37957a694d606f8c9d --- /dev/null +++ b/the_social_network/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2021, Marc Feger +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the <organization>. +4. Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/the_social_network/README.md b/the_social_network/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b00af60727745120c455dc9c870ae2b4eee146b8 --- /dev/null +++ b/the_social_network/README.md @@ -0,0 +1,7 @@ +# The Social Network + +The package "The Social Network" is a django base backend core element for any possible social network you can think of. + +It contains the following models + +Django.Authentication.User diff --git a/the_social_network/pyproject.toml b/the_social_network/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..749d6438aae38614d05f7bad2dc9d5e6c60841c0 --- /dev/null +++ b/the_social_network/pyproject.toml @@ -0,0 +1,25 @@ +[tool.poetry] +name = "the-social-network" +version = "0.0.1" +description = "Basic social network core." +authors = ["Marc Feger <marc.feger@hhu.de>"] +license = "BSD-4" +readme = "README.md" +exclude = ["not_needed"] +homepage = "https://gitlab.cs.uni-duesseldorf.de/feger/the-social-network" + + +[tool.poetry.dependencies] +python = "^3.9" +Django = "^3.2.9" +djangorestframework = "^3.12.4" +Pillow = "^8.4.0" +django-cors-headers = "^3.10.0" +django-dotenv = "^1.4.2" +uWSGI = "^2.0.20" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/the_social_network/the_social_network/settings.py b/the_social_network/the_social_network/settings.py index f19f1ca7142d95bd8b298c2155864d72f63a29f7..84842f0bb7c73cd4aeb6610905a55b97d69e4be3 100644 --- a/the_social_network/the_social_network/settings.py +++ b/the_social_network/the_social_network/settings.py @@ -1,14 +1,15 @@ """ Django settings for the_social_network project. -Generated by 'django-admin startproject' using Django 3.2.9. +Generated by 'django-admin startproject' using Django 3.1.2. For more information on this file, see -https://docs.djangoproject.com/en/3.2/topics/settings/ +https://docs.djangoproject.com/en/3.1/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/3.2/ref/settings/ +https://docs.djangoproject.com/en/3.1/ref/settings/ """ +import logging import os from pathlib import Path @@ -16,18 +17,20 @@ from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'django-insecure-hpjug(8bb2&mx*lv-$h!a6ried17*-34or7ngwee*1x#f6kak^' +SECRET_KEY = os.environ.get("SECRET_KEY", "MySecretSecret") # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = os.environ.get("DEBUG", True) -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "*").split(",") -# Application definition +CORS_ORIGIN_ALLOW_ALL = bool(os.environ.get("CORS_ORIGIN_ALLOW_ALL", True)) +# CORS_ORIGIN_WHITELIST = os.environ.get("CORS_ORIGIN_WHITELIST", "*").split(",") +# Application definition INSTALLED_APPS = [ 'django.contrib.admin', @@ -74,7 +77,7 @@ TEMPLATES = [ WSGI_APPLICATION = 'the_social_network.wsgi.application' # Database -# https://docs.djangoproject.com/en/3.2/ref/settings/#databases +# https://docs.djangoproject.com/en/3.1/ref/settings/#databases DATABASES = { 'default': { @@ -84,7 +87,7 @@ DATABASES = { } # Password validation -# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -102,7 +105,7 @@ AUTH_PASSWORD_VALIDATORS = [ ] # Internationalization -# https://docs.djangoproject.com/en/3.2/topics/i18n/ +# https://docs.djangoproject.com/en/3.1/topics/i18n/ LANGUAGE_CODE = 'en-us' @@ -115,7 +118,7 @@ USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/3.2/howto/static-files/ +# https://docs.djangoproject.com/en/3.1/howto/static-files/ STATIC_URL = '/django_static/' STATIC_ROOT = os.path.join(BASE_DIR, "django_static/") @@ -130,8 +133,3 @@ REST_FRAMEWORK = { # Folder to store media data MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') - -# Default primary key field type -# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field - -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/the_social_network/the_social_network/urls.py b/the_social_network/the_social_network/urls.py index 1acc893cfeb1de6fb679a7bedcf40ccf3f608500..a6b7db4cba1dde09a7fe801101c1db6d0e537187 100644 --- a/the_social_network/the_social_network/urls.py +++ b/the_social_network/the_social_network/urls.py @@ -20,9 +20,9 @@ from django.contrib import admin from django.urls import path, include urlpatterns = [ - path('admin/', admin.site.urls), - url(r'^authentication/', include('core.urls.authenticationUrls')), - url(r'^accounts/', include('core.urls.accountUrls')), - url(r'^search/', include('core.urls.searchUrls')), - url(r'^contents/', include('core.urls.contentUrls')), - ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + path('admin/', admin.site.urls), + url(r'^authentication/', include('core.urls.authenticationUrls')), + url(r'^accounts/', include('core.urls.accountUrls')), + url(r'^search/', include('core.urls.searchUrls')), + url(r'^contents/', include('core.urls.contentUrls')), +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)