Skip to content

Commit 2ffe0ac

Browse files
committed
init
0 parents  commit 2ffe0ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+2267
-0
lines changed

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/mails/
2+
!*/mails/
3+
venv/
4+
env/
5+
*.sqlite3
6+
.idea
7+
__pycache__/
8+
9+
/files/*
10+
!files/.keep

app/__init__.py

Whitespace-only changes.

app/asgi.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
ASGI config for myhackupc2 project.
3+
4+
It exposes the ASGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.asgi import get_asgi_application
13+
14+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
15+
16+
application = get_asgi_application()

app/emails.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import os
2+
from pathlib import Path
3+
4+
from django.conf import settings
5+
from django.core.mail import send_mail
6+
from django.template.loader import render_to_string
7+
from django.utils.html import strip_tags
8+
9+
10+
# Class that creates the mails and subjects from the template/mails folder
11+
# In debug mode the mail is stored in mails/[name] folder otherwise it sends the email to [list_mails]
12+
# Author Arnau Casas Saez
13+
class Email:
14+
15+
def __init__(self, name, context, list_mails) -> None:
16+
super().__init__()
17+
self.name = name
18+
self.list_mails = list_mails
19+
self.context = context
20+
self.__get_subject__()
21+
self.__get_content__()
22+
23+
# Private method that renders and save the subject of the mail
24+
def __get_subject__(self):
25+
file_template = 'mails/%s.txt' % self.name
26+
self.subject = render_to_string(template_name=file_template, context=self.context)
27+
28+
# Private method that renders and save the HTML content of the mail
29+
def __get_content__(self):
30+
file_template = 'mails/%s.html' % self.name
31+
self.html_message = render_to_string(template_name=file_template, context=self.context)
32+
self.plain_message = strip_tags(self.html_message)
33+
34+
# Public method that sends the mail to [list_mails] if not debug else saves the file at mails folder
35+
def send(self):
36+
email_from = getattr(settings, 'HACKATHON_NAME', '') + ' Team <' + \
37+
getattr(settings, 'HACKATHON_CONTACT_EMAIL') + '>'
38+
39+
if settings.DEBUG:
40+
base_dir = getattr(settings, 'BASE_DIR', '')
41+
42+
mails_folder = os.path.join(base_dir, 'mails')
43+
Path(mails_folder).mkdir(parents=True, exist_ok=True)
44+
path_mail_test = os.path.join(mails_folder, self.name)
45+
Path(path_mail_test).mkdir(parents=True, exist_ok=True)
46+
separator = '_'
47+
final_path = os.path.join(path_mail_test, separator.join(self.list_mails) + '.html')
48+
with open(final_path, "w", encoding='utf-8') as text_file:
49+
text_file.write(self.html_message)
50+
else:
51+
send_mail(subject=self.subject,
52+
message=self.plain_message,
53+
from_email=email_from,
54+
recipient_list=self.list_mails,
55+
html_message=self.html_message)

app/hackathon_variables.py

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
HACKATHON_NAME = 'HackUPC'
2+
HACKATHON_DESCRIPTION = 'Join us for BarcelonaTech\'s hackathon. 36h. 29th April - 1st May.'
3+
HACKATHON_ORG = 'Hackers@UPC'
4+
HACKATHON_CONTACT_EMAIL = ''
5+
HACKATHON_SOCIALS = [('fa-facebook', 'fa-facebook')]
6+
REGEX_HACKATHON_ORGANIZER_EMAIL = '^.*@hackupc\.com$'
7+
HACKATHON_ORGANIZER_EMAILS = []
8+
APP_NAME = 'MyHackUPC'
9+
APP_EMAIL = ''

app/mixins.py

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import copy
2+
3+
from django.forms import model_to_dict
4+
5+
6+
class TabsViewMixin:
7+
def get_current_tabs(self):
8+
return []
9+
10+
def get_back_url(self):
11+
return None
12+
13+
def get_context_data(self, **kwargs):
14+
c = super(TabsViewMixin, self).get_context_data(**kwargs)
15+
c.update({'tabs': self.get_current_tabs(), 'back': self.get_back_url()})
16+
return c
17+
18+
19+
class OverwriteOnlyModelFormMixin(object):
20+
'''
21+
Delete POST keys that were not actually found in the POST dict
22+
to prevent accidental overwriting of fields due to missing POST data.
23+
Based on:
24+
https://yuji.wordpress.com/2013/03/12/django-prevent-modelform-from-updating-values-if-user-did-not-submit-them/
25+
'''
26+
27+
def clean(self):
28+
cleaned_data = super(OverwriteOnlyModelFormMixin, self).clean()
29+
c_cl_data = cleaned_data.copy()
30+
for field in c_cl_data.keys():
31+
if self.prefix is not None:
32+
post_key = '-'.join((self.prefix, field))
33+
else:
34+
post_key = field
35+
36+
if post_key not in list(self.data.keys()) + list(self.files.keys()):
37+
# value was not posted, thus it should not overwrite any data.
38+
del cleaned_data[field]
39+
40+
# only overwrite keys that were actually submitted via POST.
41+
model_data = model_to_dict(self.instance)
42+
model_data.update(cleaned_data)
43+
return model_data
44+
45+
46+
class BootstrapFormMixin:
47+
48+
# example: {'TITLE': {'fields': [{'name': 'FIELD_NAME', 'space': GRID_NUMBER},], 'description': 'DESCRIPTION'},}
49+
# UPPER LETTERS MUST BE CHANGED
50+
bootstrap_field_info = {}
51+
read_only = []
52+
53+
def get_bootstrap_field_info(self):
54+
return copy.deepcopy(self.bootstrap_field_info)
55+
56+
def set_read_only(self):
57+
for field in self.fields.values():
58+
field.disabled = True
59+
60+
@property
61+
def is_read_only(self):
62+
for field in self.fields.values():
63+
if not field.disabled:
64+
return False
65+
return True
66+
67+
def get_fields(self):
68+
result = self.get_bootstrap_field_info()
69+
for list_fields in result.values():
70+
sum = 0
71+
for field in list_fields.get('fields'):
72+
if sum + field.get('space') > 12:
73+
sum = field.get('space')
74+
field['new_row'] = True
75+
else:
76+
sum += field.get('space')
77+
field['new_row'] = False
78+
name = field.get('name')
79+
field.update({'field': self.fields.get(name).get_bound_field(self, name)})
80+
return result

app/patterns.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class SingletonMeta(type):
2+
"""
3+
The Singleton class can be implemented in different ways in Python. Some
4+
possible methods include: base class, decorator, metaclass. We will use the
5+
metaclass because it is best suited for this purpose.
6+
"""
7+
8+
_instances = {}
9+
10+
def __call__(cls, *args, **kwargs):
11+
"""
12+
Possible changes to the value of the `__init__` argument do not affect
13+
the returned instance.
14+
"""
15+
if cls not in cls._instances:
16+
instance = super().__call__(*args, **kwargs)
17+
cls._instances[cls] = instance
18+
return cls._instances[cls]

app/settings.py

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
"""
2+
Django settings for myhackupc2 project.
3+
4+
Generated by 'django-admin startproject' using Django 4.0.4.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.0/topics/settings/
8+
9+
For the full list of settings and their values, see
10+
https://docs.djangoproject.com/en/4.0/ref/settings/
11+
"""
12+
import os
13+
from pathlib import Path
14+
15+
from django.contrib.messages import constants as message_constants
16+
17+
from .hackathon_variables import *
18+
19+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
20+
BASE_DIR = Path(__file__).resolve().parent.parent
21+
22+
23+
# Quick-start development settings - unsuitable for production
24+
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
25+
26+
# SECURITY WARNING: keep the secret key used in production secret!
27+
SECRET_KEY = os.environ.get('SECRET_KEY', 'django-insecure-*9+h@8wtz_f0i#0i@*8(dt#y1ktpb^1*)ddwr)su8$doq6ny1w')
28+
29+
# SECURITY WARNING: don't run with debug turned on in production!
30+
DEBUG = os.environ.get('DEBUG', 'true').lower() != 'false'
31+
32+
ALLOWED_HOSTS = []
33+
HOST = os.environ.get('HOST')
34+
35+
if DEBUG:
36+
ALLOWED_HOSTS.extend(['localhost', '127.0.0.1'])
37+
elif HOST is not None:
38+
ALLOWED_HOSTS.append(HOST)
39+
40+
41+
# Application definition
42+
43+
INSTALLED_APPS = [
44+
'django.contrib.admin',
45+
'django.contrib.auth',
46+
'django.contrib.contenttypes',
47+
'django.contrib.sessions',
48+
'django.contrib.messages',
49+
'django.contrib.staticfiles',
50+
'django_jwt',
51+
'django_jwt.server',
52+
'django_bootstrap5',
53+
'corsheaders',
54+
'user',
55+
]
56+
57+
MIDDLEWARE = [
58+
'django.middleware.security.SecurityMiddleware',
59+
'django.contrib.sessions.middleware.SessionMiddleware',
60+
'corsheaders.middleware.CorsMiddleware',
61+
'django.middleware.common.CommonMiddleware',
62+
'django.middleware.csrf.CsrfViewMiddleware',
63+
'django.contrib.auth.middleware.AuthenticationMiddleware',
64+
'django.contrib.messages.middleware.MessageMiddleware',
65+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
66+
]
67+
68+
ROOT_URLCONF = 'app.urls'
69+
70+
TEMPLATES = [
71+
{
72+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
73+
'DIRS': [BASE_DIR / 'app' / 'templates']
74+
,
75+
'APP_DIRS': True,
76+
'OPTIONS': {
77+
'context_processors': [
78+
'django.template.context_processors.debug',
79+
'django.template.context_processors.request',
80+
'django.contrib.auth.context_processors.auth',
81+
'django.contrib.messages.context_processors.messages',
82+
'app.template.app_variables',
83+
],
84+
'libraries': {
85+
'util': 'app.templatetags.util',
86+
},
87+
},
88+
},
89+
]
90+
91+
WSGI_APPLICATION = 'app.wsgi.application'
92+
93+
94+
# Database
95+
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
96+
97+
DATABASES = {
98+
'default': {
99+
'ENGINE': 'django.db.backends.sqlite3',
100+
'NAME': BASE_DIR / 'db.sqlite3',
101+
}
102+
}
103+
104+
105+
# Password validation
106+
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
107+
108+
AUTH_PASSWORD_VALIDATORS = [
109+
{
110+
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
111+
},
112+
{
113+
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
114+
},
115+
{
116+
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
117+
},
118+
{
119+
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
120+
},
121+
]
122+
123+
124+
# Internationalization
125+
# https://docs.djangoproject.com/en/4.0/topics/i18n/
126+
127+
LANGUAGE_CODE = 'en-us'
128+
129+
TIME_ZONE = 'UTC'
130+
131+
USE_I18N = True
132+
133+
USE_TZ = True
134+
135+
136+
# Static files (CSS, JavaScript, Images)
137+
# https://docs.djangoproject.com/en/4.0/howto/static-files/
138+
139+
STATIC_URL = 'static/'
140+
STATIC_ROOT = BASE_DIR / 'staticfiles'
141+
STATICFILES_DIRS = [
142+
BASE_DIR / 'app' / 'static',
143+
]
144+
145+
# Default primary key field type
146+
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
147+
148+
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
149+
150+
# App theme: dark, light, both
151+
THEME = 'both'
152+
153+
# UserModel default
154+
AUTH_USER_MODEL = 'user.User'
155+
156+
# JWT settings
157+
JWT_CLIENT = {
158+
'OPENID2_URL': os.environ.get('OPENID_CLIENT_ID', 'http://localhost:8000/openid'), # Required
159+
'CLIENT_ID': os.environ.get('OPENID_CLIENT_ID', 'client_id'), # Required
160+
'TYPE': 'fake' if DEBUG else 'local', # Required
161+
'RESPONSE_TYPE': 'id_token', # Required
162+
'RENAME_ATTRIBUTES': {'sub': 'email'}, # Optional
163+
164+
}
165+
JWT_SERVER = {
166+
'JWK_EXPIRATION_TIME': 3600, # Optional
167+
'JWT_EXPIRATION_TIME': 14400 # Optional
168+
}
169+
170+
# Toast styles
171+
MESSAGE_TAGS = {
172+
message_constants.DEBUG: 'info text-dark',
173+
message_constants.INFO: 'info text-dark',
174+
message_constants.SUCCESS: 'success',
175+
message_constants.WARNING: 'warning text-dark',
176+
message_constants.ERROR: 'danger',
177+
}
178+
179+
# Google recaptcha
180+
GOOGLE_RECAPTCHA_SECRET_KEY = os.environ.get('GOOGLE_RECAPTCHA_SECRET_KEY', '')
181+
GOOGLE_RECAPTCHA_SITE_KEY = os.environ.get('GOOGLE_RECAPTCHA_SITE_KEY', '')
182+
183+
# Login tries
184+
LOGIN_TRIES = 1000 if DEBUG else 4

0 commit comments

Comments
 (0)