diff --git a/.gitignore b/.gitignore index 02f08e4..cecf253 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,6 @@ venv.bak/ # vscode configs .vscode + +# secrets +projectsplatform/secrets.py diff --git a/projectsplatform/secrets.example.py b/projectsplatform/secrets.example.py new file mode 100644 index 0000000..191bc73 --- /dev/null +++ b/projectsplatform/secrets.example.py @@ -0,0 +1,30 @@ +# SECURITY WARNING: don't run with debug turned on in production! +SECRET_KEY = '' + +# Database +# https://docs.djangoproject.com/en/2.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': '', + 'USER': '', + 'PASSWORD': '', + 'HOST': 'localhost', + 'PORT': '5432', + } +} + + +# Provider specific settings +SITE_ID = 2 +SOCIALACCOUNT_PROVIDERS = { + 'github': { + # todo: do not commit this to github + 'APP': { + 'client_id': '', + 'secret': '', + 'key': '' + } + } +} diff --git a/projectsplatform/settings.py b/projectsplatform/settings.py index f120751..29dbf16 100644 --- a/projectsplatform/settings.py +++ b/projectsplatform/settings.py @@ -11,6 +11,7 @@ """ import os +from .secrets import * # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -20,8 +21,6 @@ # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ -# SECURITY WARNING: don't run with debug turned on in production! -SECRET_KEY = 'dulwepf_b#@eh19w)==v+pxvw$u$2gbxpwoevmzg)h-pl1mded' DEBUG = True ALLOWED_HOSTS = [] @@ -36,8 +35,23 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'corsheaders', + 'django.contrib.sites', + 'scprojects.apps.ScprojectsConfig', + 'allauth', + 'allauth.account', + 'allauth.socialaccount', + 'allauth.socialaccount.providers.github', + ] +CORS_ALLOW_CREDENTIALS = True + +CORS_ORIGIN_WHITELIST = [ + "http://localhost:3000", +] +SESSION_COOKIE_SAMESITE = None +CRSF_COOKIE_SAMESITE = None MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -46,6 +60,8 @@ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'corsheaders.middleware.CorsMiddleware', + 'django.middleware.common.CommonMiddleware', ] ROOT_URLCONF = 'projectsplatform.urls' @@ -61,6 +77,8 @@ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + # `allauth` needs this from django + 'django.template.context_processors.request', ], }, }, @@ -69,21 +87,6 @@ WSGI_APPLICATION = 'projectsplatform.wsgi.application' -# Database -# https://docs.djangoproject.com/en/2.2/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'scprojects', - 'USER': 'scadmin', - 'PASSWORD': '', - 'HOST': 'localhost', - 'PORT': '5432', - } -} - - # Password validation # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators @@ -121,3 +124,14 @@ # https://docs.djangoproject.com/en/2.2/howto/static-files/ STATIC_URL = '/static/' + +AUTHENTICATION_BACKENDS = ( + # Needed to login by username in Django admin, regardless of `allauth` + 'django.contrib.auth.backends.ModelBackend', + + # `allauth` specific authentication methods, such as login by e-mail + 'allauth.account.auth_backends.AuthenticationBackend', +) + +ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = None +LOGIN_REDIRECT_URL = FRONTEND_DOMAIN_NAME diff --git a/projectsplatform/urls.py b/projectsplatform/urls.py index 339d73a..4f01a4f 100644 --- a/projectsplatform/urls.py +++ b/projectsplatform/urls.py @@ -14,8 +14,12 @@ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path +from django.urls import include, path, re_path +from scprojects import views urlpatterns = [ + path('projects/', include('scprojects.urls')), path('admin/', admin.site.urls), + path('', views.index, name='index'), + re_path(r'^accounts/', include('allauth.urls')), ] diff --git a/scprojects/__init__.py b/scprojects/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scprojects/admin.py b/scprojects/admin.py new file mode 100644 index 0000000..1905f65 --- /dev/null +++ b/scprojects/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +from .models import Project, UserProfile + +admin.site.register(Project) +admin.site.register(UserProfile) +# Register your models here. diff --git a/scprojects/apps.py b/scprojects/apps.py new file mode 100644 index 0000000..7db5ff9 --- /dev/null +++ b/scprojects/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig + + +class ScprojectsConfig(AppConfig): + name = 'scprojects' + + def ready(self): + import scprojects.signals diff --git a/scprojects/migrations/0001_initial.py b/scprojects/migrations/0001_initial.py new file mode 100644 index 0000000..5660479 --- /dev/null +++ b/scprojects/migrations/0001_initial.py @@ -0,0 +1,41 @@ +# Generated by Django 2.2.6 on 2019-12-28 20:25 + +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='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=255)), + ], + ), + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('github_url', models.URLField(blank=True, max_length=255)), + ('description', models.TextField()), + ('looking_for', models.TextField()), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('contributors', models.ManyToManyField(to=settings.AUTH_USER_MODEL)), + ('lead', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='leads', to=settings.AUTH_USER_MODEL)), + ('tech_stack', models.ManyToManyField(to='scprojects.Tag')), + ], + ), + ] diff --git a/scprojects/migrations/0002_auto_20200113_1700.py b/scprojects/migrations/0002_auto_20200113_1700.py new file mode 100644 index 0000000..2e06ea0 --- /dev/null +++ b/scprojects/migrations/0002_auto_20200113_1700.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.6 on 2020-01-13 17:00 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='project', + name='tech_stack', + ), + migrations.DeleteModel( + name='Tag', + ), + ] diff --git a/scprojects/migrations/0003_userprofile.py b/scprojects/migrations/0003_userprofile.py new file mode 100644 index 0000000..e43fe97 --- /dev/null +++ b/scprojects/migrations/0003_userprofile.py @@ -0,0 +1,32 @@ +# Generated by Django 2.2.6 on 2020-01-20 22:27 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('scprojects', '0002_auto_20200113_1700'), + ] + + operations = [ + migrations.CreateModel( + name='UserProfile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('department', models.CharField(max_length=100)), + ('experience_lvl', models.PositiveSmallIntegerField()), + ('position', models.CharField(max_length=255)), + ('is_active', models.BooleanField()), + ('github_username', models.CharField(max_length=255)), + ('github_id', models.PositiveIntegerField()), + ('github_url', models.URLField(blank=True, max_length=255)), + ('avatar_url', models.URLField(blank=True, max_length=255)), + ('gravatar_url', models.URLField(blank=True, max_length=255)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/scprojects/migrations/0004_auto_20200123_0453.py b/scprojects/migrations/0004_auto_20200123_0453.py new file mode 100644 index 0000000..08816b9 --- /dev/null +++ b/scprojects/migrations/0004_auto_20200123_0453.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.6 on 2020-01-23 04:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0003_userprofile'), + ] + + operations = [ + migrations.AlterField( + model_name='userprofile', + name='avatar_url', + field=models.URLField(max_length=255), + ), + migrations.AlterField( + model_name='userprofile', + name='github_url', + field=models.URLField(max_length=255), + ), + migrations.AlterField( + model_name='userprofile', + name='gravatar_url', + field=models.URLField(max_length=255), + ), + ] diff --git a/scprojects/migrations/0005_remove_userprofile_department.py b/scprojects/migrations/0005_remove_userprofile_department.py new file mode 100644 index 0000000..65f1d20 --- /dev/null +++ b/scprojects/migrations/0005_remove_userprofile_department.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.6 on 2020-01-23 06:58 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0004_auto_20200123_0453'), + ] + + operations = [ + migrations.RemoveField( + model_name='userprofile', + name='department', + ), + ] diff --git a/scprojects/migrations/0006_auto_20200123_0707.py b/scprojects/migrations/0006_auto_20200123_0707.py new file mode 100644 index 0000000..dc381e7 --- /dev/null +++ b/scprojects/migrations/0006_auto_20200123_0707.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:07 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0005_remove_userprofile_department'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='lead', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='leads', to='scprojects.UserProfile'), + ), + ] diff --git a/scprojects/migrations/0007_auto_20200123_0708.py b/scprojects/migrations/0007_auto_20200123_0708.py new file mode 100644 index 0000000..0023c08 --- /dev/null +++ b/scprojects/migrations/0007_auto_20200123_0708.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:08 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0006_auto_20200123_0707'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='lead', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='leads', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/scprojects/migrations/0008_auto_20200123_0715.py b/scprojects/migrations/0008_auto_20200123_0715.py new file mode 100644 index 0000000..a3581cf --- /dev/null +++ b/scprojects/migrations/0008_auto_20200123_0715.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:15 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0007_auto_20200123_0708'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='lead', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='leads', to='scprojects.UserProfile'), + ), + ] diff --git a/scprojects/migrations/0009_remove_project_contributors.py b/scprojects/migrations/0009_remove_project_contributors.py new file mode 100644 index 0000000..aabb094 --- /dev/null +++ b/scprojects/migrations/0009_remove_project_contributors.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:22 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0008_auto_20200123_0715'), + ] + + operations = [ + migrations.RemoveField( + model_name='project', + name='contributors', + ), + ] diff --git a/scprojects/migrations/0010_remove_project_lead.py b/scprojects/migrations/0010_remove_project_lead.py new file mode 100644 index 0000000..70ab63a --- /dev/null +++ b/scprojects/migrations/0010_remove_project_lead.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:26 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0009_remove_project_contributors'), + ] + + operations = [ + migrations.RemoveField( + model_name='project', + name='lead', + ), + ] diff --git a/scprojects/migrations/0011_project_lead.py b/scprojects/migrations/0011_project_lead.py new file mode 100644 index 0000000..5f05988 --- /dev/null +++ b/scprojects/migrations/0011_project_lead.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:28 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0010_remove_project_lead'), + ] + + operations = [ + migrations.AddField( + model_name='project', + name='lead', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='leads', to='scprojects.UserProfile'), + ), + ] diff --git a/scprojects/migrations/0012_remove_project_lead.py b/scprojects/migrations/0012_remove_project_lead.py new file mode 100644 index 0000000..af5ce7f --- /dev/null +++ b/scprojects/migrations/0012_remove_project_lead.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:29 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0011_project_lead'), + ] + + operations = [ + migrations.RemoveField( + model_name='project', + name='lead', + ), + ] diff --git a/scprojects/migrations/0013_project_lead.py b/scprojects/migrations/0013_project_lead.py new file mode 100644 index 0000000..efa7187 --- /dev/null +++ b/scprojects/migrations/0013_project_lead.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:36 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0012_remove_project_lead'), + ] + + operations = [ + migrations.AddField( + model_name='project', + name='lead', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='leads', to='scprojects.UserProfile'), + ), + ] diff --git a/scprojects/migrations/0014_remove_project_lead.py b/scprojects/migrations/0014_remove_project_lead.py new file mode 100644 index 0000000..8a6342b --- /dev/null +++ b/scprojects/migrations/0014_remove_project_lead.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0013_project_lead'), + ] + + operations = [ + migrations.RemoveField( + model_name='project', + name='lead', + ), + ] diff --git a/scprojects/migrations/0015_project_lead.py b/scprojects/migrations/0015_project_lead.py new file mode 100644 index 0000000..e01999d --- /dev/null +++ b/scprojects/migrations/0015_project_lead.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.6 on 2020-01-23 07:37 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('scprojects', '0014_remove_project_lead'), + ] + + operations = [ + migrations.AddField( + model_name='project', + name='lead', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='leads', to='scprojects.UserProfile'), + ), + ] diff --git a/scprojects/migrations/0016_auto_20200123_1721.py b/scprojects/migrations/0016_auto_20200123_1721.py new file mode 100644 index 0000000..860a3d1 --- /dev/null +++ b/scprojects/migrations/0016_auto_20200123_1721.py @@ -0,0 +1,55 @@ +# Generated by Django 2.2.6 on 2020-01-23 17:21 + +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('scprojects', '0015_project_lead'), + ] + + operations = [ + migrations.AddField( + model_name='project', + name='contributors', + field=models.ManyToManyField(to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='userprofile', + name='avatar_url', + field=models.URLField(blank=True, max_length=255), + ), + migrations.AlterField( + model_name='userprofile', + name='experience_lvl', + field=models.PositiveSmallIntegerField(blank=True), + ), + migrations.AlterField( + model_name='userprofile', + name='github_id', + field=models.PositiveIntegerField(blank=True), + ), + migrations.AlterField( + model_name='userprofile', + name='github_url', + field=models.URLField(blank=True, max_length=255), + ), + migrations.AlterField( + model_name='userprofile', + name='github_username', + field=models.CharField(blank=True, max_length=255), + ), + migrations.AlterField( + model_name='userprofile', + name='gravatar_url', + field=models.URLField(blank=True, max_length=255), + ), + migrations.AlterField( + model_name='userprofile', + name='position', + field=models.CharField(blank=True, max_length=255), + ), + ] diff --git a/scprojects/migrations/__init__.py b/scprojects/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scprojects/models.py b/scprojects/models.py new file mode 100644 index 0000000..b0487a9 --- /dev/null +++ b/scprojects/models.py @@ -0,0 +1,58 @@ +from django.db import models +from django.contrib.auth.models import User +# from .models import UserProfile +# Create your models here. + + +class UserProfile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + experience_lvl = models.PositiveSmallIntegerField(blank=True) + position = models.CharField(max_length=255, blank=True) + is_active = models.BooleanField() + github_username = models.CharField(max_length=255, blank=True) + github_id = models.PositiveIntegerField(blank=True) + github_url = models.URLField(max_length=255, blank=True) + avatar_url = models.URLField(max_length=255, blank=True) + gravatar_url = models.URLField(max_length=255, blank=True) + + +class Project(models.Model): + name = models.CharField(max_length=255) + github_url = models.URLField(max_length=255, blank=True) + description = models.TextField() + looking_for = models.TextField() + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + lead = models.ForeignKey( + UserProfile, on_delete=models.SET_NULL, null=True, related_name="leads") + + contributors = models.ManyToManyField(User) + + def __str__(self): + return self.name + + def getInitials(self, user): + return user.first_name[0] + user.last_name[0] + + def dict_format(self): + contributers_list = [ + self.getInitials(user) for user in self.contributors.all()] + print("contributors", contributers_list) + # get lead info bundle + + lead_obj = {} + lead_obj["name"] = self.lead.user.first_name + \ + ' ' + self.lead.user.last_name + lead_obj["position"] = self.lead.position + lead_obj["experience"] = self.lead.experience_lvl + return { + "id": self.id, + "name": self.name, + "github_url": self.github_url, + "lead": lead_obj, + "description": self.description, + "looking_for": self.looking_for, + "created": self.created, + "updated": self.updated, + "contributors": contributers_list, + } diff --git a/scprojects/signals.py b/scprojects/signals.py new file mode 100644 index 0000000..68eec27 --- /dev/null +++ b/scprojects/signals.py @@ -0,0 +1,36 @@ +from django.db.models.signals import pre_save +from django.dispatch import receiver +from allauth.socialaccount.models import SocialAccount +from allauth.account.signals import user_logged_in +from django.core.signals import request_finished +from .models import UserProfile + +# request_finished.connect( +# "http://127.0.0.1:8000/accounts/github/login/callback") +# ljsadkjdljs + + +@receiver(user_logged_in) +def retrieve_social_data(request, user, **kwargs): + print("hello xxx") + data = SocialAccount.objects.filter( + user=user, provider='github')[0].extra_data + print(data) + + try: + newUser = UserProfile.objects.get(user=user) + print("User Profile", newUser) + except UserProfile.DoesNotExist: + print("Does not exists, creating new") + newUser = UserProfile( + user=user, + experience_lvl=0, + position=data["company"], + is_active=True, + github_username=data["login"], + github_id=data["id"], + github_url=data["html_url"], + avatar_url=data["avatar_url"], + gravatar_url=data["gravatar_id"] + ) + newUser.save() diff --git a/scprojects/tests.py b/scprojects/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/scprojects/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/scprojects/urls.py b/scprojects/urls.py new file mode 100644 index 0000000..dc5b25b --- /dev/null +++ b/scprojects/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.index, name='index'), + path('all/', views.projects, name='projects'), + path('logout/', views.logout, name='logout'), +] diff --git a/scprojects/views.py b/scprojects/views.py new file mode 100644 index 0000000..609f94e --- /dev/null +++ b/scprojects/views.py @@ -0,0 +1,30 @@ +from django.shortcuts import render +from django.http import HttpResponse +from .models import Project +from django.contrib.auth.models import User +from django.contrib.auth import logout as django_logout +from django.http import JsonResponse + + +def index(request): + return HttpResponse("Hello, world. You're at the polls index.") + + +def projects(request): + projects = Project.objects.all() + response = {} + response["user"] = { + "name": request.user.username, + "is_authenticated": request.user.is_authenticated, + } + response["projects"] = [] + for project in list(projects): + json_obj = project.dict_format() + response["projects"].append(json_obj) + + return JsonResponse(response) + + +def logout(request): + django_logout(request) + return JsonResponse({"status": "logout success"})