diff --git a/__pycache__/__init__.cpython-37.pyc b/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..d7658de Binary files /dev/null and b/__pycache__/__init__.cpython-37.pyc differ diff --git a/__pycache__/admin.cpython-37.pyc b/__pycache__/admin.cpython-37.pyc new file mode 100644 index 0000000..e5ec84b Binary files /dev/null and b/__pycache__/admin.cpython-37.pyc differ diff --git a/__pycache__/apps.cpython-37.pyc b/__pycache__/apps.cpython-37.pyc new file mode 100644 index 0000000..974e55d Binary files /dev/null and b/__pycache__/apps.cpython-37.pyc differ diff --git a/__pycache__/forms.cpython-37.pyc b/__pycache__/forms.cpython-37.pyc new file mode 100644 index 0000000..9e2b9f3 Binary files /dev/null and b/__pycache__/forms.cpython-37.pyc differ diff --git a/__pycache__/models.cpython-37.pyc b/__pycache__/models.cpython-37.pyc new file mode 100644 index 0000000..9aaec89 Binary files /dev/null and b/__pycache__/models.cpython-37.pyc differ diff --git a/__pycache__/urls.cpython-37.pyc b/__pycache__/urls.cpython-37.pyc new file mode 100644 index 0000000..d4a7de0 Binary files /dev/null and b/__pycache__/urls.cpython-37.pyc differ diff --git a/__pycache__/views.cpython-37.pyc b/__pycache__/views.cpython-37.pyc new file mode 100644 index 0000000..efb46f4 Binary files /dev/null and b/__pycache__/views.cpython-37.pyc differ diff --git a/admin.py b/admin.py new file mode 100644 index 0000000..7587366 --- /dev/null +++ b/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import File + +admin.site.register(File) + +# Register your models here. diff --git a/apps.py b/apps.py new file mode 100644 index 0000000..c86f272 --- /dev/null +++ b/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class FilesConfig(AppConfig): + name = 'files' diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000..3c5e97c Binary files /dev/null and b/db.sqlite3 differ diff --git a/dbportal/__pycache__/__init__.cpython-37.pyc b/dbportal/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..a241397 Binary files /dev/null and b/dbportal/__pycache__/__init__.cpython-37.pyc differ diff --git a/dbportal/__pycache__/settings.cpython-37.pyc b/dbportal/__pycache__/settings.cpython-37.pyc new file mode 100644 index 0000000..4693522 Binary files /dev/null and b/dbportal/__pycache__/settings.cpython-37.pyc differ diff --git a/dbportal/__pycache__/urls.cpython-37.pyc b/dbportal/__pycache__/urls.cpython-37.pyc new file mode 100644 index 0000000..9d5d759 Binary files /dev/null and b/dbportal/__pycache__/urls.cpython-37.pyc differ diff --git a/dbportal/__pycache__/wsgi.cpython-37.pyc b/dbportal/__pycache__/wsgi.cpython-37.pyc new file mode 100644 index 0000000..8c3c387 Binary files /dev/null and b/dbportal/__pycache__/wsgi.cpython-37.pyc differ diff --git a/dbportal/db.sqlite3 b/dbportal/db.sqlite3 new file mode 100644 index 0000000..6558641 Binary files /dev/null and b/dbportal/db.sqlite3 differ diff --git a/dbportal/dbportal/__pycache__/__init__.cpython-37.pyc b/dbportal/dbportal/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..a241397 Binary files /dev/null and b/dbportal/dbportal/__pycache__/__init__.cpython-37.pyc differ diff --git a/dbportal/dbportal/__pycache__/settings.cpython-37.pyc b/dbportal/dbportal/__pycache__/settings.cpython-37.pyc new file mode 100644 index 0000000..ebb62f8 Binary files /dev/null and b/dbportal/dbportal/__pycache__/settings.cpython-37.pyc differ diff --git a/dbportal/dbportal/__pycache__/urls.cpython-37.pyc b/dbportal/dbportal/__pycache__/urls.cpython-37.pyc new file mode 100644 index 0000000..26fa7e4 Binary files /dev/null and b/dbportal/dbportal/__pycache__/urls.cpython-37.pyc differ diff --git a/dbportal/dbportal/__pycache__/wsgi.cpython-37.pyc b/dbportal/dbportal/__pycache__/wsgi.cpython-37.pyc new file mode 100644 index 0000000..8c3c387 Binary files /dev/null and b/dbportal/dbportal/__pycache__/wsgi.cpython-37.pyc differ diff --git a/dbportal/dbportal/settings.py b/dbportal/dbportal/settings.py new file mode 100644 index 0000000..a3ae240 --- /dev/null +++ b/dbportal/dbportal/settings.py @@ -0,0 +1,142 @@ +""" +Django settings for dbportal project. + +Generated by 'django-admin startproject' using Django 2.2.4. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.2/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'nmud+4cu4s^x$ir_nr#l9%w@32=s9=6x+(&5t_ago0)%r*k5_4' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'users.apps.UsersConfig', + 'files.apps.FilesConfig', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + 'crispy_forms', +] + +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 = 'dbportal.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 = 'dbportal.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/2.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +#Email information + +SITE_ID = 1 + +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_PORT = 587 +EMAIL_HOST_USER = '############' +EMAIL_HOST_PASSWORD = '############' +EMAIL_USE_TLS = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.2/howto/static-files/ + +STATIC_URL = '/static/' + +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = '/media/' + +CRISPY_TEMPLATE_PACK = 'bootstrap4' + +LOGIN_REDIRECT_URL = 'home' +LOGIN_URL = 'login' diff --git a/dbportal/dbportal/urls.py b/dbportal/dbportal/urls.py new file mode 100644 index 0000000..92b2552 --- /dev/null +++ b/dbportal/dbportal/urls.py @@ -0,0 +1,23 @@ +"""dbportal URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('files.urls')), + path('users/', include('users.urls')), +] diff --git a/dbportal/dbportal/wsgi.py b/dbportal/dbportal/wsgi.py new file mode 100644 index 0000000..472843a --- /dev/null +++ b/dbportal/dbportal/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for dbportal project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dbportal.settings') + +application = get_wsgi_application() diff --git a/dbportal/files/admin.py b/dbportal/files/admin.py new file mode 100644 index 0000000..7587366 --- /dev/null +++ b/dbportal/files/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import File + +admin.site.register(File) + +# Register your models here. diff --git a/dbportal/files/apps.py b/dbportal/files/apps.py new file mode 100644 index 0000000..c86f272 --- /dev/null +++ b/dbportal/files/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class FilesConfig(AppConfig): + name = 'files' diff --git a/dbportal/files/forms.py b/dbportal/files/forms.py new file mode 100644 index 0000000..8402e92 --- /dev/null +++ b/dbportal/files/forms.py @@ -0,0 +1,36 @@ + from django import forms +from django.contrib.auth.models import User +from django.contrib.auth.forms import UserCreationForm +from .models import File +from users.models import Profile +from allauth.socialaccount.forms import SignupForm +from allauth.account.forms import LoginForm +from django.core import validators + +class FileUploadForm(forms.ModelForm): + botcatcher = forms.FileField(required = False, widget = forms.HiddenInput, + validators = [validators.MaxLengthValidator(0)]) + + class Meta: + model = File + fields = ['name', 'doc'] + +class SearchUIDForm(forms.ModelForm): + botcatcher = forms.CharField(required = False, widget = forms.HiddenInput, + validators = [validators.MaxLengthValidator(0)]) + + class Meta: + model = Profile + fields = ['uid'] + +class MailContentForm(forms.ModelForm): + subject = forms.CharField(max_length = 20) + content = forms.TextField(max_length = 264) + + fields = ['subject', 'content'] + +class AddDberForm(forms.ModelForm): + + class Meta: + model = Profile + fields = ['uid', 'name', 'dob', 'gender', 'city', 'state'] diff --git a/dbportal/files/models.py b/dbportal/files/models.py new file mode 100644 index 0000000..61f246b --- /dev/null +++ b/dbportal/files/models.py @@ -0,0 +1,21 @@ +from django.db import models +from django.contrib.auth.models import User +from PIL import Image +from django.dispatch import receiver +from django.db.models.signals import post_save +from django.utils import timezone +from django.urls import reverse +from users.models import Profile + +class File(models.Model): + + staff = models.ForeignKey(Profile, on_delete = models.CASCADE) + fname = models.CharField(max_length=20) + doc = models.FileField(upload_to='files/', blank=True) + up_date = models.DateField(default = timezone.now) + + def __str__(self): + return f'{self.fname}' + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) diff --git a/dbportal/files/tests.py b/dbportal/files/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/dbportal/files/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/dbportal/files/urls.py b/dbportal/files/urls.py new file mode 100644 index 0000000..6d529a3 --- /dev/null +++ b/dbportal/files/urls.py @@ -0,0 +1,16 @@ +from django.contrib import admin +from django.urls import path +from .views import upload_file, search_dber, update_dber, delete_dber, add_dber, send_mail, send_mass_mails, home +from django.contrib.auth import views as auth_views + +urlpatterns = [ + + path('/', home, name='home'), + path('upload_file/', upload_file, name='upload_file'), + path('search_dber/', search_dber, name='search_dber'), + path('update_dber//', update_dber, name='update_dber'), + path('delete_dber//', delete_dber, name='delete_dber'), + path('add_dber/', add_dber, name='add_dber'), + path('send_mail//', send_mail, name='send_mail'), + path('send_mass_mails/', send_mass_mails, name='send_mass_mails'), +] diff --git a/dbportal/files/views.py b/dbportal/files/views.py new file mode 100644 index 0000000..da5cf4c --- /dev/null +++ b/dbportal/files/views.py @@ -0,0 +1,290 @@ +from django.shortcuts import render +from django.contrib.auth.decorators import login_required +from django.contrib import messages +import requests +from django.shortcuts import render, get_object_or_404, redirect +from django.contrib.auth.decorators import login_required +from .forms import FileUploadForm, SearchUIDForm, MailContentForm, AddDberForm +import xlrd, xlsxwriter +import openpyxl + + +def home(request): + return render(request, 'templates/home.html') + +@login_required +def upload_file(request): + if request.method == 'POST': + form = FileUploadForm(request.POST, request.FILES) + if form.is_valid(): + file = form.save(commit=False) + file.save() + + #file = request.FILES['filename'].temporary_file_path + document = file.doc + wb = xlrd.open_workbook(document.path) + sheet = wb.sheet_by_index(0) + sheet.cell_value(0, 0) + + rows = sheet.nrows + cols = sheet.ncols + + for i in range(2,rows): + dber_uid = sheet.cell_value(i, 0) + dber_name = sheet.cell_value(i, 1) + dber_dob = sheet.cell_value(i, 2) + dber_gender = sheet.cell_value(i, 3) + dber_city = sheet.cell_value(i, 4) + dber_state = sheet.cell_value(i, 5) + + new_dber = Profile.objects.get_or_create(uid = dber_uid) + new_dber.name = dber_name + new_dber.dob = dber_dob + new_dber.gender = dber_gender + new_dber.city = dber_city + new_dber.state = dber_state + new_dber.city_circle = file.staff.city_circle + + new_dber.save() + + return redirect('home') + else: + form = FileUploadForm() + + return render(request, 'templates/upload_file.html', { + 'form': form + }) + +def search_dber(request): + + file = get_object_or_404(File, staff = request.user.profile) + + if request.method == 'POST': + form = SearchUIDForm(request.POST) + if form.is_valid(): + form.save() + search_uid = form.cleaned_data['uid'] + + #file = request.FILES['filename'].temporary_file_path + document = file.doc + wb = xlrd.open_workbook(document.path) + sheet = wb.sheet_by_index(0) + + rows = sheet.nrows + cols = sheet.ncols + + flag = 0 + + for i in range(2,rows): + + if search_uid == sheet.cell_value(i, 0): + flag = 1 + dber = get_object_or_404(Profile, uid = search_uid) + return render(request, "templates/search_results.html", {'dber':dber}) + + if flag == 0: + return render(request, "templates/failed_search.html") + else: + form = SearchUIDForm() + + return render(request, 'templates/search_dber.html', { + 'form': form + }) + +@login_required +def update_dber(request, pk): + + dber = get_object_or_404(Profile, pk = pk) + if request.method == 'POST': + p_form = DberUpdateForm(request.POST, + instance=dber) + + if p_form.is_valid(): + dber.save() + p_form.save() + + # File updation begins + + file = get_object_or_404(File, staff = request.user.profile) + document = file.doc + wb = openpyxl.load_workbook(document.path) + sheet = wb.get_sheet(0) + + rows = sheet.max_row + + flag = 0 + for i in range(3,rows+1): + + cell_name = f'A{i}' + if dber.uid == sheet[cell_name].value: + flag = 1 + + list = [dber.uid, dber.name, dber.dob, dber.gender, dber.city, dber.state] + for j in range(2, 7): + cell = sheet.cell(row = i, column = j) + cell.value = list[j-1] + + break + + if flag == 0: + return render(request, "templates/failed_search.html") + + wb.save(document.path) + file.save() + #File Updation Ends + + return redirect('home') + + else: + p_form = DberUpdateForm(instance=dber) + + + context = { + 'p_form' : p_form + } + return render(request, 'templates/update_dber.html', context) + +@login_required +def delete_dber(request, pk): + + dber = get_object_or_404(Profile, pk = pk) + + # File updation begins + file = get_object_or_404(File, staff = request.user.profile) + document = file.doc + wb = openpyxl.load_workbook(document.path) + sheet = wb.get_sheet(0) + + rows = sheet.max_row + + flag = 0 + for i in range(3,rows+1): + cell_name = f'A{i}' + if dber.uid == sheet[cell_name].value: + flag = 1 + sheet.delete_rows(i, 1) + break + + Profile.objects.remove(dber) + + wb.save(document.path) + file.save() + #File Updation Ends + + return redirect('home') + +@login_required +def add_dber(request): + + if request.method == 'POST': + form = AddDberForm(request.POST) + + if form.is_valid(): + form.save() + dber_uid = form.cleaned_data['uid'] + + #new dber created in database + new_dber = Profile.objects.get_or_create(uid = dber_uid) + new_dber.name = form.cleaned_data['name'] + new_dber.dob = form.cleaned_data['dob'] + new_dber.gender = form.cleaned_data['gender'] + new_dber.city = form.cleaned_data['city'] + new_dber.state = form.cleaned_data['state'] + new_dber.city_circle = request.user.profile.city_circle + + new_dber.save() + + # File updation begins + file = get_object_or_404(File, staff = request.user.profile) + document = file.doc + wb = openpyxl.load_workbook(document.path) + sheet = wb.get_sheet(0) + + rows = sheet.max_row + cols = sheet.max_column + + sheet.insert_rows(3) #new dber insterted at top of sheet + + list = [new_dber.uid, new_dber.name, new_dber.dob, new_dber.gender, new_dber.city, new_dber.state] + for j in range(1, 7): + cell = sheet.cell(row = 3, column = j) + cell.value = list[j-1] + + + wb.save(document.path) + file.save() + #File Updation Ends + + else: + form = AddDberForm() + + return render(request, 'templates/add_dber.html', {'form':form}) + +@login_required +def send_mail(request, pk): + + dber = get_object_or_404(Profile, pk = pk) + if request.method == 'POST': + form = MailContentForm(request.POST) + + if form.is_valid(): + + form.save() + subject = form.cleaned_data['subject'] + content = form.cleaned_data['content'] + + mail = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT) + mail.ehlo() + mail.starttls() + mail.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD) + + message = f'**** SUBJECT : {subject} **** \n{content}\n\nRegards,\n{request.user.profile.name}' + + email = dber.user.email + try: + mail.sendmail(settings.EMAIL_HOST_USER, email, message) + except: + pass + + mail.close() + + else: + form = MailContentForm() + + return render(request, 'templates/mail_content.html', {'form':form}) + +@login_required +def send_mass_mails(request): + + if request.method == 'POST': + form = MailContentForm(request.POST) + + if form.is_valid(): + + form.save() + subject = form.cleaned_data['subject'] + content = form.cleaned_data['content'] + + mail = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT) + mail.ehlo() + mail.starttls() + mail.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD) + + message = f'**** SUBJECT : {subject} **** \n{content}\n\nRegards,\n{request.user.profile.name}' + + users = User.objects.all(profile) + for user in users: + if (user.profile.city_circle == request.user.profile.city_circle)&&(user.profile.qualifier == 0): + + email = user.email + try: + mail.sendmail(settings.EMAIL_HOST_USER, email, message) + except: + pass + + mail.close() + + else: + form = MailContentForm() + + return render(request, 'templates/mail_content.html', {'form':form}) diff --git a/dbportal/manage.py b/dbportal/manage.py new file mode 100644 index 0000000..bba21b4 --- /dev/null +++ b/dbportal/manage.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dbportal.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/dbportal/settings.py b/dbportal/settings.py new file mode 100644 index 0000000..190f29c --- /dev/null +++ b/dbportal/settings.py @@ -0,0 +1,195 @@ +""" +Django settings for dbportal project. + +Generated by 'django-admin startproject' using Django 2.2.4. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.2/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'nmud+4cu4s^x$ir_nr#l9%w@32=s9=6x+(&5t_ago0)%r*k5_4' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'users.apps.UsersConfig', + 'files.apps.FilesConfig', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django.contrib.sites', + + 'allauth', + 'allauth.account', + 'allauth.socialaccount', + 'allauth.socialaccount.providers.google', + + 'crispy_forms', +] + +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 = 'dbportal.urls' + +ACCOUNT_FORMS = { + 'login': 'allauth.account.forms.LoginForm', + 'signup': 'allauth.account.forms.SignupForm', + 'add_email': 'allauth.account.forms.AddEmailForm', + 'change_password': 'allauth.account.forms.ChangePasswordForm', + 'set_password': 'allauth.account.forms.SetPasswordForm', + 'reset_password': 'allauth.account.forms.ResetPasswordForm', + 'reset_password_from_key': 'allauth.account.forms.ResetPasswordKeyForm', + 'disconnect': 'allauth.socialaccount.forms.DisconnectForm', +} + +SOCIAL_AUTH_PIPELINE = ( + 'social_core.pipeline.social_auth.social_details', + 'social_core.pipeline.social_auth.social_uid', + 'social_core.pipeline.social_auth.auth_allowed', + 'social_core.pipeline.social_auth.social_user', + 'social_core.pipeline.user.get_username', + 'ProfilesConfig.custom_social_auth_pipeline.create_user', + 'social_core.pipeline.social_auth.associate_user', + 'social_core.pipeline.social_auth.load_extra_data', + 'social_core.pipeline.user.user_details', +) + +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 = 'dbportal.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/2.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +SOCIALACCOUNT_PROVIDERS = { + 'google': { + 'SCOPE': ['profile', 'https://www.googleapis.com/auth/userinfo.profile','https://www.googleapis.com/auth/plus.login'], + 'PROFILE_FIELDS': [ + 'id', + 'first-name', + 'last-name', + 'email-address', + 'picture-url', + 'public-profile-url', + ], + 'AUTH_PARAMS': { + 'access_type' : 'online', + #'hd' : 'pilani.bits-pilani.ac.in', + } + } +} + +#Email information + +SITE_ID = 1 + +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_PORT = 587 +EMAIL_HOST_USER = '############' +EMAIL_HOST_PASSWORD = '############' +EMAIL_USE_TLS = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.2/howto/static-files/ + +STATIC_URL = '/static/' +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, "static"), +] + +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = '/media/' + +#TEMPLATES_ROOT = os.path.join(BASE_DIR, 'templates') +#TEMPLATES_URL = '/templates/' + +CRISPY_TEMPLATE_PACK = 'bootstrap4' + +LOGIN_REDIRECT_URL = 'home' +LOGIN_URL = 'login' diff --git a/dbportal/urls.py b/dbportal/urls.py new file mode 100644 index 0000000..92b2552 --- /dev/null +++ b/dbportal/urls.py @@ -0,0 +1,23 @@ +"""dbportal URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('files.urls')), + path('users/', include('users.urls')), +] diff --git a/dbportal/users/admin.py b/dbportal/users/admin.py new file mode 100644 index 0000000..e0406cb --- /dev/null +++ b/dbportal/users/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin +from .models import Profile + +admin.site.register(Profile) + + +# Register your models here. diff --git a/dbportal/users/apps.py b/dbportal/users/apps.py new file mode 100644 index 0000000..4ce1fab --- /dev/null +++ b/dbportal/users/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class UsersConfig(AppConfig): + name = 'users' diff --git a/dbportal/users/forms.py b/dbportal/users/forms.py new file mode 100644 index 0000000..7e3efa5 --- /dev/null +++ b/dbportal/users/forms.py @@ -0,0 +1,39 @@ +from django import forms +from django.contrib.auth.models import User +from django.contrib.auth.forms import UserCreationForm +from .models import Profile +from allauth.socialaccount.forms import SignupForm +from allauth.account.forms import LoginForm +from django.core import validators + +class RegForm(UserCreationForm): + email = forms.EmailField() + botcatcher = forms.CharField(required = False, widget = forms.HiddenInput, + validators = [validators.MaxLengthValidator(0)]) + + class Meta: + model = User + fields = ['username', 'email', 'password1', 'password2', 'botcatcher'] + + +class StaffUpdateForm(forms.ModelForm): + botcatcher = forms.CharField(required = False, widget = forms.HiddenInput, + validators = [validators.MaxLengthValidator(0)]) + + class Meta: + model = Profile + fields = ['uid', 'name', 'dob', 'gender', 'state', 'city', 'botcatcher'] + +class DberUpdateForm(forms.ModelForm): + botcatcher = forms.CharField(required = False, widget = forms.HiddenInput, + validators = [validators.MaxLengthValidator(0)]) + + class Meta: + model = Profile + fields = ['name', 'dob', 'gender', 'state', 'city', 'botcatcher'] + +class EmailChangeForm(forms.ModelForm): + + class Meta: + model = User + fields = ['email'] diff --git a/dbportal/users/models.py b/dbportal/users/models.py new file mode 100644 index 0000000..1e2d1b0 --- /dev/null +++ b/dbportal/users/models.py @@ -0,0 +1,33 @@ +from django.db import models +from django.contrib.auth.models import User +from PIL import Image +from django.dispatch import receiver +from django.db.models.signals import post_save +from django.utils import timezone +from django.urls import reverse + +sex_choices = [('MALE', 'Male'), ('FEMALE', 'Female'), ('OTHERS', 'Rather Not Say'),] + +class Profile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + uid = models.CharField(max_length=12) + name = models.CharField(max_length = 20) + dob = models.DateField(default = timezone.now) + gender = models.CharField(max_length = 6, choices = sex_choices, default = 1) + city = models.CharField(max_length = 20) + state = models.CharField(max_length = 20) + + city_circle = models.IntegerField(default=0) + qualifier = models.IntegerField(default = 0) # 1 - Staff 0 - DBer + + def profile_create_url(self): + return reverse('create_profile', kwargs={'pk': self.pk}) + + def __str__(self): + return f'{self.user.username} Profile' + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + + if self.qualifier == 0: + self.city_circle = ord(upper(self.city[0])) - 64 diff --git a/dbportal/users/tests.py b/dbportal/users/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/dbportal/users/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/dbportal/users/urls.py b/dbportal/users/urls.py new file mode 100644 index 0000000..009f0c9 --- /dev/null +++ b/dbportal/users/urls.py @@ -0,0 +1,13 @@ +from django.contrib import admin +from django.urls import path +from .views import register, update_staff, change_email, change_password +from django.contrib.auth import views as auth_views + +urlpatterns = [ + path('register/', register, name='register'), + path('update_staff/', update_staff, name='update_staff'), + path('login/', auth_views.LoginView.as_view(template_name='templates/login.html'), name='login'), + path('logout/', auth_views.LogoutView.as_view(template_name='templates/logout.html'), name='logout'), + path('change_email/', change_email, name='change_email'), + path('change_password/', change_password, name='change_password'), +] diff --git a/dbportal/users/views.py b/dbportal/users/views.py new file mode 100644 index 0000000..c0e2390 --- /dev/null +++ b/dbportal/users/views.py @@ -0,0 +1,85 @@ +from django.shortcuts import render +from django.contrib.auth.decorators import login_required +from django.contrib import messages +import requests +from django.shortcuts import render, get_object_or_404, redirect +from django.contrib.auth.decorators import login_required +from .forms import RegForm, StaffUpdateForm, DberUpdateForm, EmailChangeForm +from django.contrib.auth import update_session_auth_hash +from django.contrib.auth.forms import PasswordChangeForm + +def register(request): + if request.method == 'POST': + form = RegForm(request.POST) + if form.is_valid(): + form.save() + username = form.cleaned_data.get('username') + pwd = form.cleaned_data.get('password1') + messages.success(request, f'Account created successfully for {username}') + + Profile.objects.get_or_create(user = request.user) + + user = authenticate(username = username, password = pwd) + login(request, user) + + return redirect('home') + else : + form = RegForm() + + return render(request, 'templates/register.html', {'form' : form}) + +@login_required +def update_staff(request): + + if request.method == 'POST': + p_form = StaffUpdateForm(request.POST, + instance=request.user.profile) + + if p_form.is_valid(): + request.user.profile.save() + p_form.save() + + else: + p_form = StaffUpdateForm(instance=request.user.profile) + + context = { + 'p_form' : p_form + } + return render(request, 'templates/update_staff.html', context) + + +def change_password(request): + if request.method == 'POST': + form = PasswordChangeForm(request.user, request.POST) + if form.is_valid(): + user = form.save() + update_session_auth_hash(request, user) + return redirect('home') + + else: + form = PasswordChangeForm(request.user) + return render(request, 'templates/change_password.html', { + 'form': form + }) + +@login_required +def change_email(request): + + user = request.user + if request.method == 'POST': + form = EmailChangeForm(request.POST) + if form.is_valid(): + form.save() + + user.email = form.cleaned_data['email'] + user.save() + + return redirect('change_email') + + else: + form = EmailChangeForm() + + return render(request, 'templates/change_email.html', { + 'form': form + }) +# Create your views here. diff --git a/dbportal/wsgi.py b/dbportal/wsgi.py new file mode 100644 index 0000000..472843a --- /dev/null +++ b/dbportal/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for dbportal project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dbportal.settings') + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..bba21b4 --- /dev/null +++ b/manage.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dbportal.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/migrations/0001_initial.py b/migrations/0001_initial.py new file mode 100644 index 0000000..d9e0f2c --- /dev/null +++ b/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# Generated by Django 2.2.4 on 2019-12-30 06:54 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('users', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='File', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('fname', models.CharField(max_length=20)), + ('doc', models.FileField(blank=True, upload_to='files_dir/')), + ('up_date', models.DateField(default=django.utils.timezone.now)), + ('staff', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Profile')), + ], + ), + ] diff --git a/migrations/__pycache__/0001_initial.cpython-37.pyc b/migrations/__pycache__/0001_initial.cpython-37.pyc new file mode 100644 index 0000000..5cf8ac0 Binary files /dev/null and b/migrations/__pycache__/0001_initial.cpython-37.pyc differ diff --git a/migrations/__pycache__/__init__.cpython-37.pyc b/migrations/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..8174320 Binary files /dev/null and b/migrations/__pycache__/__init__.cpython-37.pyc differ diff --git a/models.py b/models.py new file mode 100644 index 0000000..9012fa8 --- /dev/null +++ b/models.py @@ -0,0 +1,21 @@ +from django.db import models +from django.contrib.auth.models import User +from PIL import Image +from django.dispatch import receiver +from django.db.models.signals import post_save +from django.utils import timezone +from django.urls import reverse +from users.models import Profile + +class File(models.Model): + + staff = models.ForeignKey(Profile, on_delete = models.CASCADE) + fname = models.CharField(max_length=20) + doc = models.FileField(upload_to='files_dir/', blank=True) + up_date = models.DateField(default = timezone.now) + + def __str__(self): + return f'{self.fname}' + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) diff --git a/templates/files/add_dber.html b/templates/files/add_dber.html new file mode 100644 index 0000000..cddad23 --- /dev/null +++ b/templates/files/add_dber.html @@ -0,0 +1,39 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} + +
+
+
+
+

Add DBER

+

+ Add a New Record to the Database +

+
+
+
+
+ +
+
+
+ +
+ {% csrf_token %} +
+ Profile Info +
+ {{ form }} +
+
+
+ +
+
+
+
+
+ + +{% endblock content %} diff --git a/templates/files/base.html b/templates/files/base.html new file mode 100644 index 0000000..f780e67 --- /dev/null +++ b/templates/files/base.html @@ -0,0 +1,184 @@ +{% load static %} + + + + + DBPortal - The Database Management System + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + {%block content%} + + + {%endblock content%} + + +
+
+
+ BITS Pilani + Vidya Vihar, Pilani, Rajasthan 333031 +
+ +
+
+ + +
+
+
+
+
+ +
+
+ +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/templates/files/failed_search.html b/templates/files/failed_search.html new file mode 100644 index 0000000..7b0ed0b --- /dev/null +++ b/templates/files/failed_search.html @@ -0,0 +1,32 @@ +{%extends "files/base.html"%} +{% block content %} +
+
+
+
+

Sorry, No Search Results !

+

+ Your search returned no results. Please check the UID once again or make a new search. +

+
+
+
+
+ + +
+
+
+ +
+

Make a new Search

+ + + Search Students + + +
+
+
+
+{%endblock content%} diff --git a/templates/files/home.html b/templates/files/home.html new file mode 100644 index 0000000..a3fc897 --- /dev/null +++ b/templates/files/home.html @@ -0,0 +1,44 @@ +{% extends "files/base.html" %} +{% block content %} + +
+
+
+
+

DBPortal

+

+ The Database Management System +

+
+
+
+
+ +
+
+
+ +
+
+
+
+

Home

+

+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem + Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown + printer took a galley of type and scrambled it to make a type specimen book. It has survived + not only five centuries, but also the leap into electronic typesetting, remaining essentially + unchanged. It was popularised in the 1960s with the release of Letraset sheets containing + Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker + including versions of Lorem Ipsum. +

+
+
+
+
+ +
+
+
+ +{% endblock content %} diff --git a/templates/files/mail_content.html b/templates/files/mail_content.html new file mode 100644 index 0000000..07d7a18 --- /dev/null +++ b/templates/files/mail_content.html @@ -0,0 +1,36 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} +
+
+
+
+

Send Mail

+

Send Mail to the Concerned User

+
+
+
+
+ + +
+
+
+
+ {% csrf_token %} +
+ Write Mail + {{ form|crispy }} +
+
+ +
+
+
+ +
+
+ + + +{%endblock content%} diff --git a/templates/files/search_city_staff.html b/templates/files/search_city_staff.html new file mode 100644 index 0000000..11f757b --- /dev/null +++ b/templates/files/search_city_staff.html @@ -0,0 +1,36 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} +
+
+
+
+

Search City Staff

+

Search for City Staff in the Database

+
+
+
+
+ + +
+
+
+
+ {% csrf_token %} +
+ Search Staff + {{ form }} +
+
+ +
+
+
+ +
+
+ + + +{%endblock content%} diff --git a/templates/files/search_dber.html b/templates/files/search_dber.html new file mode 100644 index 0000000..364a3eb --- /dev/null +++ b/templates/files/search_dber.html @@ -0,0 +1,36 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} +
+
+
+
+

Search Users

+

Search for Users in the Database

+
+
+
+
+ + +
+
+
+
+ {% csrf_token %} +
+ Search Users + {{ form }} +
+
+ +
+
+
+ +
+
+ + + +{%endblock content%} diff --git a/templates/files/search_results.html b/templates/files/search_results.html new file mode 100644 index 0000000..a9d53b2 --- /dev/null +++ b/templates/files/search_results.html @@ -0,0 +1,100 @@ +{%extends "files/base.html"%} +{% load crispy_forms_tags %} +{% block content %} +
+
+
+
+

Search Results

+

+ Your search returned the following results. +

+
+
+
+
+ + +
+
+
+ {% if dber %} + +
+ + + + + + {% if user.profile.qualifier == 1%} + + + + + {% elif user != dber.user %} + + + + {% endif %} + +
+

{{ dber.name }}

+

{{ dber.uid }}

+

DOB : {{ dber.dob }}

+

Sex : {{ dber.gender }}

+

City: {{ dber.city }}, {{ dber.state }}

+
+
+

+ + Update + +     + + Delete + +     + + Mail + +     +

+
+

+ + Mail + +     + {% if user.profile %} + + {% elif dber.user %} + + {% else %} + + Link Account + + {% endif %} +

+
+
+
+ + {% else %} +

Sorry, No Users Related to Your Search were Found

+ {% endif %} + +
+ + {% if user.profile %} + + {% else %} +
+

Didn't Find Your Profile ?

+ Report the issue to your city's staff in-charge. + +
+ {% endif %} +
+
+ +{%endblock content%} diff --git a/templates/files/update_dber.html b/templates/files/update_dber.html new file mode 100644 index 0000000..4f3d8c2 --- /dev/null +++ b/templates/files/update_dber.html @@ -0,0 +1,39 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} + +
+
+
+
+

Update DBER

+

+ Update the User Profile of the Dber +

+
+
+
+
+ +
+
+
+ +
+ {% csrf_token %} +
+ Profile Info +
+ {{ p_form|crispy }} +
+
+
+ +
+
+
+
+
+ + +{% endblock content %} diff --git a/templates/files/upload_file.html b/templates/files/upload_file.html new file mode 100644 index 0000000..7505aab --- /dev/null +++ b/templates/files/upload_file.html @@ -0,0 +1,36 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} +
+
+
+
+

Upload Files

+

Upload Fiels to Populate the Database

+
+
+
+
+ + +
+
+
+
+ {% csrf_token %} +
+ Upload File + {{ form|crispy }} +
+
+ +
+
+
+ +
+
+ + + +{%endblock content%} diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..f221019 --- /dev/null +++ b/urls.py @@ -0,0 +1,19 @@ +from django.contrib import admin +from django.urls import path +from .views import upload_file, search_dber, search_uid_normal, update_dber, search_city_staff, delete_dber, add_dber, send_mail, send_mass_mails, home, link_account +from django.contrib.auth import views as auth_views + +urlpatterns = [ + + path('', home, name='home'), + path('upload_file/', upload_file, name='upload_file'), + path('search_dber/', search_dber, name='search_dber'), + path('search_uid/', search_uid_normal, name='search_uid_normal'), + path('search_city_staff/', search_city_staff, name='search_city_staff'), + path('link_account//', link_account, name='link_account'), + path('update_dber//', update_dber, name='update_dber'), + path('delete_dber//', delete_dber, name='delete_dber'), + path('add_dber/', add_dber, name='add_dber'), + path('send_mail//', send_mail, name='send_mail'), + path('send_mass_mails/', send_mass_mails, name='send_mass_mails'), +] diff --git a/users/__pycache__/__init__.cpython-37.pyc b/users/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..76fa8d2 Binary files /dev/null and b/users/__pycache__/__init__.cpython-37.pyc differ diff --git a/users/__pycache__/admin.cpython-37.pyc b/users/__pycache__/admin.cpython-37.pyc new file mode 100644 index 0000000..f57fab6 Binary files /dev/null and b/users/__pycache__/admin.cpython-37.pyc differ diff --git a/users/__pycache__/apps.cpython-37.pyc b/users/__pycache__/apps.cpython-37.pyc new file mode 100644 index 0000000..e878f2c Binary files /dev/null and b/users/__pycache__/apps.cpython-37.pyc differ diff --git a/users/__pycache__/forms.cpython-37.pyc b/users/__pycache__/forms.cpython-37.pyc new file mode 100644 index 0000000..fd188ac Binary files /dev/null and b/users/__pycache__/forms.cpython-37.pyc differ diff --git a/users/__pycache__/models.cpython-37.pyc b/users/__pycache__/models.cpython-37.pyc new file mode 100644 index 0000000..bd11345 Binary files /dev/null and b/users/__pycache__/models.cpython-37.pyc differ diff --git a/users/__pycache__/urls.cpython-37.pyc b/users/__pycache__/urls.cpython-37.pyc new file mode 100644 index 0000000..1bdf1e4 Binary files /dev/null and b/users/__pycache__/urls.cpython-37.pyc differ diff --git a/users/__pycache__/views.cpython-37.pyc b/users/__pycache__/views.cpython-37.pyc new file mode 100644 index 0000000..55fb7ee Binary files /dev/null and b/users/__pycache__/views.cpython-37.pyc differ diff --git a/users/admin.py b/users/admin.py new file mode 100644 index 0000000..e0406cb --- /dev/null +++ b/users/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin +from .models import Profile + +admin.site.register(Profile) + + +# Register your models here. diff --git a/users/apps.py b/users/apps.py new file mode 100644 index 0000000..4ce1fab --- /dev/null +++ b/users/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class UsersConfig(AppConfig): + name = 'users' diff --git a/users/forms.py b/users/forms.py new file mode 100644 index 0000000..7e3efa5 --- /dev/null +++ b/users/forms.py @@ -0,0 +1,39 @@ +from django import forms +from django.contrib.auth.models import User +from django.contrib.auth.forms import UserCreationForm +from .models import Profile +from allauth.socialaccount.forms import SignupForm +from allauth.account.forms import LoginForm +from django.core import validators + +class RegForm(UserCreationForm): + email = forms.EmailField() + botcatcher = forms.CharField(required = False, widget = forms.HiddenInput, + validators = [validators.MaxLengthValidator(0)]) + + class Meta: + model = User + fields = ['username', 'email', 'password1', 'password2', 'botcatcher'] + + +class StaffUpdateForm(forms.ModelForm): + botcatcher = forms.CharField(required = False, widget = forms.HiddenInput, + validators = [validators.MaxLengthValidator(0)]) + + class Meta: + model = Profile + fields = ['uid', 'name', 'dob', 'gender', 'state', 'city', 'botcatcher'] + +class DberUpdateForm(forms.ModelForm): + botcatcher = forms.CharField(required = False, widget = forms.HiddenInput, + validators = [validators.MaxLengthValidator(0)]) + + class Meta: + model = Profile + fields = ['name', 'dob', 'gender', 'state', 'city', 'botcatcher'] + +class EmailChangeForm(forms.ModelForm): + + class Meta: + model = User + fields = ['email'] diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py new file mode 100644 index 0000000..9a0b3e4 --- /dev/null +++ b/users/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# Generated by Django 2.2.4 on 2019-12-30 06:54 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Profile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uid', models.CharField(max_length=12)), + ('name', models.CharField(max_length=20)), + ('dob', models.DateField(default=django.utils.timezone.now)), + ('gender', models.CharField(choices=[('MALE', 'Male'), ('FEMALE', 'Female'), ('OTHERS', 'Rather Not Say')], default=1, max_length=6)), + ('city', models.CharField(max_length=20)), + ('state', models.CharField(max_length=20)), + ('city_circle', models.IntegerField(default=0)), + ('qualifier', models.IntegerField(default=0)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/users/migrations/__pycache__/0001_initial.cpython-37.pyc b/users/migrations/__pycache__/0001_initial.cpython-37.pyc new file mode 100644 index 0000000..2b50d71 Binary files /dev/null and b/users/migrations/__pycache__/0001_initial.cpython-37.pyc differ diff --git a/users/migrations/__pycache__/__init__.cpython-37.pyc b/users/migrations/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..0090db3 Binary files /dev/null and b/users/migrations/__pycache__/__init__.cpython-37.pyc differ diff --git a/users/models.py b/users/models.py new file mode 100644 index 0000000..1e2d1b0 --- /dev/null +++ b/users/models.py @@ -0,0 +1,33 @@ +from django.db import models +from django.contrib.auth.models import User +from PIL import Image +from django.dispatch import receiver +from django.db.models.signals import post_save +from django.utils import timezone +from django.urls import reverse + +sex_choices = [('MALE', 'Male'), ('FEMALE', 'Female'), ('OTHERS', 'Rather Not Say'),] + +class Profile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + uid = models.CharField(max_length=12) + name = models.CharField(max_length = 20) + dob = models.DateField(default = timezone.now) + gender = models.CharField(max_length = 6, choices = sex_choices, default = 1) + city = models.CharField(max_length = 20) + state = models.CharField(max_length = 20) + + city_circle = models.IntegerField(default=0) + qualifier = models.IntegerField(default = 0) # 1 - Staff 0 - DBer + + def profile_create_url(self): + return reverse('create_profile', kwargs={'pk': self.pk}) + + def __str__(self): + return f'{self.user.username} Profile' + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + + if self.qualifier == 0: + self.city_circle = ord(upper(self.city[0])) - 64 diff --git a/users/templates/users/change_email.html b/users/templates/users/change_email.html new file mode 100644 index 0000000..cea4777 --- /dev/null +++ b/users/templates/users/change_email.html @@ -0,0 +1,36 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} +
+
+
+
+

Reset Email

+

Change Your Email Account Linked to DBPortal

+
+
+
+
+ + +
+
+
+
+ {% csrf_token %} +
+ Change Email + {{ form|crispy }} +
+
+ +
+
+
+ +
+
+ + + +{%endblock content%} diff --git a/users/templates/users/change_password.html b/users/templates/users/change_password.html new file mode 100644 index 0000000..df383e5 --- /dev/null +++ b/users/templates/users/change_password.html @@ -0,0 +1,36 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} +
+
+
+
+

Reset Password

+

Change Your Account Password Linked to DBPortal

+
+
+
+
+ + +
+
+
+
+ {% csrf_token %} +
+ Change Password + {{ form|crispy }} +
+
+ +
+
+
+ +
+
+ + + +{%endblock content%} diff --git a/users/templates/users/login.html b/users/templates/users/login.html new file mode 100644 index 0000000..d8c2637 --- /dev/null +++ b/users/templates/users/login.html @@ -0,0 +1,42 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} +
+
+
+
+

User Login

+

Login to Your DBPortal Account

+
+
+
+
+ + +
+
+
+
+ {% csrf_token %} +
+ Log In + {{ form|crispy }} +
+
+ +
+
+
+
+ + Don't have an account ? + Sign Up + + +
+
+
+ + + +{%endblock content%} diff --git a/users/templates/users/logout.html b/users/templates/users/logout.html new file mode 100644 index 0000000..cfdd360 --- /dev/null +++ b/users/templates/users/logout.html @@ -0,0 +1,38 @@ +{% extends "files/base.html" %} +{% block content %} + +
+
+
+
+

Logged Out

+

+ You Have been successfully logged out +

+
+
+
+
+ +
+
+
+ +
+
+
+
+

You have been successfully logged out

+ + Log In Again + +
+
+
+
+ +
+
+
+ +{% endblock content %} diff --git a/users/templates/users/register.html b/users/templates/users/register.html new file mode 100644 index 0000000..6c34a17 --- /dev/null +++ b/users/templates/users/register.html @@ -0,0 +1,45 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} + + +
+
+
+
+

Register

+

+ Register a New User +

+
+
+
+
+ +
+
+
+
+
+ {% csrf_token %} +
+ Join Today + {{ form|crispy }} +
+
+ +
+
+
+ + Already have an Account? Sign In +    Register an organization? + Register + +
+
+
+
+
+ +{% endblock content %} diff --git a/users/templates/users/update_staff.html b/users/templates/users/update_staff.html new file mode 100644 index 0000000..e6b8af7 --- /dev/null +++ b/users/templates/users/update_staff.html @@ -0,0 +1,40 @@ +{% extends "files/base.html" %} +{% load crispy_forms_tags %} +{% block content %} + +
+
+
+
+

User Profile

+

+ Update the User Profile of the Staff +

+
+
+
+
+ +
+
+
+ +
+ {% csrf_token %} +
+ Profile Info +
+ + {{ p_form|crispy }} +
+
+
+ +
+
+
+
+
+ + +{% endblock content %} diff --git a/users/tests.py b/users/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/users/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/users/urls.py b/users/urls.py new file mode 100644 index 0000000..09e8b1a --- /dev/null +++ b/users/urls.py @@ -0,0 +1,13 @@ +from django.contrib import admin +from django.urls import path +from .views import register, update_staff, change_email, change_password +from django.contrib.auth import views as auth_views + +urlpatterns = [ + path('register/', register, name='register'), + path('update_staff/', update_staff, name='update_staff'), + path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'), + path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'), + path('change_email/', change_email, name='change_email'), + path('change_password/', change_password, name='change_password'), +] diff --git a/users/views.py b/users/views.py new file mode 100644 index 0000000..bbf4792 --- /dev/null +++ b/users/views.py @@ -0,0 +1,85 @@ +from django.shortcuts import render +from django.contrib.auth.decorators import login_required +from django.contrib import messages +import requests +from django.shortcuts import render, get_object_or_404, redirect +from django.contrib.auth.decorators import login_required +from .forms import RegForm, StaffUpdateForm, DberUpdateForm, EmailChangeForm +from django.contrib.auth import update_session_auth_hash +from django.contrib.auth.forms import PasswordChangeForm + +def register(request): + if request.method == 'POST': + form = RegForm(request.POST) + if form.is_valid(): + form.save() + username = form.cleaned_data.get('username') + pwd = form.cleaned_data.get('password1') + messages.success(request, f'Account created successfully for {username}') + + Profile.objects.get_or_create(user = request.user) + + user = authenticate(username = username, password = pwd) + login(request, user) + + return redirect('home') + else : + form = RegForm() + + return render(request, 'users/register.html', {'form' : form}) + +@login_required +def update_staff(request): + + if request.method == 'POST': + p_form = StaffUpdateForm(request.POST, + instance=request.user.profile) + + if p_form.is_valid(): + request.user.profile.save() + p_form.save() + + else: + p_form = StaffUpdateForm(instance=request.user.profile) + + context = { + 'p_form' : p_form + } + return render(request, 'users/update_staff.html', context) + + +def change_password(request): + if request.method == 'POST': + form = PasswordChangeForm(request.user, request.POST) + if form.is_valid(): + user = form.save() + update_session_auth_hash(request, user) + return redirect('home') + + else: + form = PasswordChangeForm(request.user) + return render(request, 'users/change_password.html', { + 'form': form + }) + +@login_required +def change_email(request): + + user = request.user + if request.method == 'POST': + form = EmailChangeForm(request.POST) + if form.is_valid(): + form.save() + + user.email = form.cleaned_data['email'] + user.save() + + return redirect('change_email') + + else: + form = EmailChangeForm() + + return render(request, 'users/change_email.html', { + 'form': form + }) +# Create your views here. diff --git a/views.py b/views.py new file mode 100644 index 0000000..db87188 --- /dev/null +++ b/views.py @@ -0,0 +1,370 @@ +from django.shortcuts import render +from django.contrib.auth.decorators import login_required +from django.contrib import messages +import requests +from django.shortcuts import render, get_object_or_404, redirect, HttpResponseRedirect +from django.contrib.auth.decorators import login_required +from .forms import FileUploadForm, SearchUIDForm, MailContentForm, AddDberForm, SearchCityStaffForm +import xlrd, xlsxwriter +import openpyxl +from django.conf import settings +from .models import File +from users.models import Profile + + +def home(request): + return render(request, 'files/home.html') + +@login_required +def upload_file(request): + + if File.objects.filter(staff = request.user.profile).exists(): + return HttpResponse("You have already uploaded your file, Update the previous file.") + if request.method == 'POST': + form = FileUploadForm(request.POST, request.FILES) + if form.is_valid(): + file = form.save(commit=False) + file.save() + + #file = request.FILES['filename'].temporary_file_path + document = file.doc + wb = xlrd.open_workbook(document.path) + sheet = wb.sheet_by_index(0) + sheet.cell_value(0, 0) + + rows = sheet.nrows + cols = sheet.ncols + + for i in range(2,rows): + dber_uid = sheet.cell_value(i, 0) + dber_name = sheet.cell_value(i, 1) + dber_dob = sheet.cell_value(i, 2) + dber_gender = sheet.cell_value(i, 3) + dber_city = sheet.cell_value(i, 4) + dber_state = sheet.cell_value(i, 5) + + new_dber = Profile.objects.get_or_create(uid = dber_uid) + new_dber.name = dber_name + new_dber.dob = dber_dob + new_dber.gender = dber_gender + new_dber.city = dber_city + new_dber.state = dber_state + new_dber.city_circle = file.staff.city_circle + + new_dber.save() + + return redirect('home') + else: + form = FileUploadForm() + + return render(request, 'files/upload_file.html', { + 'form': form + }) + +def search_dber(request): + + if request.method == 'POST': + form = SearchUIDForm(request.POST) + if form.is_valid(): + search_uid = form.cleaned_data['uid'] + + file = get_object_or_404(File, staff = request.user.profile) + document = file.doc + wb = xlrd.open_workbook(document.path) + sheet = wb.sheet_by_index(0) + + rows = sheet.nrows + cols = sheet.ncols + + flag = 0 + + for i in range(2,rows): + + if search_uid == sheet.cell_value(i, 0): + flag = 1 + dber = get_object_or_404(Profile, uid = search_uid) + return render(request, "files/search_results.html", {'dber':dber}) + + if flag == 0: + return render(request, "files/failed_search.html") + else: + form = SearchUIDForm() + + return render(request, 'files/search_dber.html', { + 'form': form + }) + +def search_uid_normal(request): + + if request.method == 'POST': + form = SearchUIDForm(request.POST) + if form.is_valid(): + search_uid = form.cleaned_data['uid'] + + dber = get_object_or_404(Profile, uid = search_uid) + return render(request, "files/search_results.html", {'dber':dber}) + + else: + form = SearchUIDForm() + + return render(request, 'files/search_dber.html', { + 'form': form + }) + +@login_required +def update_dber(request, pk): + + dber = get_object_or_404(Profile, pk = pk) + if request.method == 'POST': + p_form = DberUpdateForm(request.POST, + instance=dber) + + if p_form.is_valid(): + dber.save() + p_form.save() + + # File updation begins + + file = get_object_or_404(File, staff = request.user.profile) + document = file.doc + wb = openpyxl.load_workbook(document.path) + sheet = wb.get_sheet(0) + + rows = sheet.max_row + + flag = 0 + for i in range(3,rows+1): + + cell_name = f'A{i}' + if dber.uid == sheet[cell_name].value: + flag = 1 + + list = [dber.uid, dber.name, dber.dob, dber.gender, dber.city, dber.state] + for j in range(2, 7): + cell = sheet.cell(row = i, column = j) + cell.value = list[j-1] + + break + + if flag == 0: + return render(request, "files/failed_search.html") + + wb.save(document.path) + file.save() + #File Updation Ends + + return redirect('home') + + else: + p_form = DberUpdateForm(instance=dber) + + + context = { + 'p_form' : p_form + } + return render(request, 'files/update_dber.html', context) + +@login_required +def delete_dber(request, pk): + + dber = get_object_or_404(Profile, pk = pk) + + # File updation begins + file = get_object_or_404(File, staff = request.user.profile) + document = file.doc + wb = openpyxl.load_workbook(document.path) + sheet = wb.get_sheet(0) + + rows = sheet.max_row + + flag = 0 + for i in range(3,rows+1): + cell_name = f'A{i}' + if dber.uid == sheet[cell_name].value: + flag = 1 + sheet.delete_rows(i, 1) + break + + Profile.objects.remove(dber) + + wb.save(document.path) + file.save() + #File Updation Ends + + return redirect('home') + +@login_required +def add_dber(request): + + if request.method == 'POST': + form = AddDberForm(request.POST) + + if form.is_valid(): + form.save() + dber_uid = form.cleaned_data['uid'] + + #new dber created in database + new_dber = Profile.objects.get_or_create(uid = dber_uid) + new_dber.name = form.cleaned_data['name'] + new_dber.dob = form.cleaned_data['dob'] + new_dber.gender = form.cleaned_data['gender'] + new_dber.city = form.cleaned_data['city'] + new_dber.state = form.cleaned_data['state'] + new_dber.city_circle = request.user.profile.city_circle + + new_dber.save() + + # File updation begins + file = get_object_or_404(File, staff = request.user.profile) + document = file.doc + wb = openpyxl.load_workbook(document.path) + sheet = wb.get_sheet(0) + + rows = sheet.max_row + cols = sheet.max_column + + sheet.insert_rows(3) #new dber insterted at top of sheet + + list = [new_dber.uid, new_dber.name, new_dber.dob, new_dber.gender, new_dber.city, new_dber.state] + for j in range(1, 7): + cell = sheet.cell(row = 3, column = j) + cell.value = list[j-1] + + + wb.save(document.path) + file.save() + #File Updation Ends + + return redirect('home') + + else: + form = AddDberForm() + + return render(request, 'files/add_dber.html', {'form':form}) + +@login_required +def send_mail(request, pk): + + dber = get_object_or_404(Profile, pk = pk) + if request.method == 'POST': + form = MailContentForm(request.POST) + + if form.is_valid(): + + subject = form.cleaned_data['subject'] + content = form.cleaned_data['content'] + + mail = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT) + mail.ehlo() + mail.starttls() + mail.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD) + + message = f'**** SUBJECT : {subject} **** \n{content}\n\nRegards,\n{request.user.profile.name}' + + email = dber.user.email + try: + mail.sendmail(settings.EMAIL_HOST_USER, email, message) + except: + pass + + mail.close() + + else: + form = MailContentForm() + + return render(request, 'files/mail_content.html', {'form':form}) + +@login_required +def send_mass_mails(request): + + if request.method == 'POST': + form = MailContentForm(request.POST) + + if form.is_valid(): + + subject = form.cleaned_data['subject'] + content = form.cleaned_data['content'] + + mail = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT) + mail.ehlo() + mail.starttls() + mail.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD) + + message = f'**** SUBJECT : {subject} **** \n{content}\n\nRegards,\n{request.user.profile.name}' + + users = User.objects.all(profile) + for user in users: + if (user.profile.city_circle == request.user.profile.city_circle) and (user.profile.qualifier == 0): + + email = user.email + try: + mail.sendmail(settings.EMAIL_HOST_USER, email, message) + except: + pass + + mail.close() + + else: + form = MailContentForm() + + return render(request, 'files/mail_content.html', {'form':form}) + +@login_required +def send_city_staff_mail(request): + + if request.method == 'POST': + form = SearchCityStaffForm(request.POST) + + if form.is_valid(): + + city = form.cleaned_data['city'] + + flag = 0 + staff_pool = Profile.objects.exclude(qualifier=0) + + for staff_user in staff_pool: + if staff_user.city == city: + flag = 1 + return redirect('send_mail', staff_user.id) + break + + if flag == 0: + return render(request, 'templates/failed_search.html') + + else: + + + form = SearchCityStaffForm() + + return render(request, 'files/search_results.html', {'form':form}) + +@login_required +def link_account(request, pk): + profile = get_object_or_404(Profile, pk = pk) + user = request.user + + profile.user = user + profile.save() + user.save() + + return redirect('home') + +@login_required +def search_city_staff(request): + + if request.method == "POST": + form = SearchCityStaffForm(request.POST) + + if form.is_valid(): + search_city = form.cleaned_data['city'] + + if Profile.objects.filter(qualifier = 1, city = search_city).exists(): + staff = Profile.objects.get(qualifier = 1, city = search_city) + return redirect('send_mail', staff.id) + else: + return redirect('search_city_staff') + + else: + form = SearchCityStaffForm() + + return render(request, 'files/search_city_staff.html', {'form':form})