Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get("DEBUG") == "True"


ALLOWED_HOSTS = (
[
os.environ.get("DOMAIN", "*"),
Expand All @@ -49,8 +50,13 @@
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.sites",
# third party apps
"django_celery_beat",
"allauth",
"allauth.account",
"allauth.socialaccount",
"allauth.socialaccount.providers.github",
# custom apps
"tracker",
]
Expand All @@ -63,6 +69,7 @@
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"allauth.account.middleware.AccountMiddleware",
]

ROOT_URLCONF = "core.urls"
Expand Down Expand Up @@ -162,3 +169,35 @@
# Custom app settings

DEFAULT_SCHEDULE_INTERVAL = 3600

# Django-Allauth settings
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
)

LOGIN_REDIRECT_URL = "/admin/"
ACCOUNT_LOGOUT_REDIRECT_URL = "/admin/"

SITE_ID = int(os.environ.get("SITE_ID", 1))

SOCIAL_AUTH_GITHUB_KEY = os.environ.get("GITHUB_CLIENT_ID")
SOCIAL_AUTH_GITHUB_SECRET = os.environ.get("GITHUB_CLIENT_SECRET")

SOCIALACCOUNT_PROVIDERS = {
"github": {
"SCOPE": ["read:user", "user:email"],
}
}


SOCIALACCOUNT_ADAPTER = "tracker.adapter.CustomSocialAccountAdapter"
SOCIALACCOUNT_LOGIN_ON_GET = True
SOCIALACCOUNT_STORE_TOKENS = True
SOCIALACCOUNT_QUERY_EMAIL = True

ACCOUNT_EMAIL_VERIFICATION = "optional"
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_AUTHENTICATION_METHOD = "email"
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
1 change: 1 addition & 0 deletions core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("tracker.urls")),
path("accounts/", include("allauth.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ celery = "^5.4.0"
django-celery-beat = "^2.7.0"
redis = "^5.2.0"
faker = "^33.1.0"
django-allauth = "^65.3.1"


[build-system]
Expand Down
21 changes: 21 additions & 0 deletions tracker/adapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
from django.contrib.auth import get_user_model


User = get_user_model()


class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
def pre_social_login(self, request, sociallogin):
"""
Processes a login attempt before registration.
If a user with such an email exists, associates it with the social account.
"""
if not sociallogin.is_existing:
email = sociallogin.account.extra_data.get("email")
if email:
try:
user = User.objects.get(email=email)
sociallogin.connect(request, user)
except User.DoesNotExist:
pass
153 changes: 102 additions & 51 deletions tracker/templates/signup.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% load static %}
{% load socialaccount %}
<!DOCTYPE html>
<html lang="en">
<head>
Expand All @@ -12,46 +13,103 @@
<link rel="stylesheet" href="{% static 'admin/css/login.css' %}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static 'admin/css/responsive.css' %}">
</head>
<body class=" login">
{% if messages %}
<ul class="errorlist">
{% for message in messages %}
<li class="{{ message.tags }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<script>
document.addEventListener('DOMContentLoaded', function () {
const roleSelect = document.querySelector('#id_role');
const githubText = document.querySelector('#github-text');
const submitButton = document.querySelector('.submit-row input[type="submit"]');
const signupForm = document.querySelector('#signup-form');
const loginTechLead = document.querySelector('#tech-lead-login');
const githubSection = document.querySelector('#github-section');
const formSection = document.querySelector('#form-section');
const techLeadLoginLink = document.querySelector('#tech-lead-login-link');

function updateRoleText() {
const role = roleSelect.value;
if (role === 'contributor') {
// Show GitHub login only for Contributor
githubSection.style.display = 'block';
formSection.style.display = 'none';
signupForm.style.display = 'none';
techLeadLoginLink.style.display = 'none'; // Hide Tech Lead login
submitButton.value = 'Sign Up as Contributor';
} else if (role === 'tech-lead') {
// Show Tech Lead login/sign up form
githubSection.style.display = 'none';
formSection.style.display = 'block';
signupForm.style.display = 'block';
techLeadLoginLink.style.display = 'block'; // Show Tech Lead login link
submitButton.value = 'Sign Up as Tech Lead';
}
}

// Initialize text and section visibility based on the default value
updateRoleText();

<div id="container">
<header id="header">
<div id="branding">
<div id="site-name">
<a href="/">Sign Up</a>
</div>
// Update text and section visibility on role change
roleSelect.addEventListener('change', updateRoleText);
});

</script>
</head>
<body class="login">
{% if messages %}
<ul class="errorlist">
{% for message in messages %}
<li class="{{ message.tags }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}

<div id="container">
<header id="header">
<div id="branding">
<div id="site-name">
<a href="/">Sign Up</a>
</div>
<button class="theme-toggle">
<span class="visually-hidden theme-label-when-auto">Toggle theme (current theme: auto)</span>
<span class="visually-hidden theme-label-when-light">Toggle theme (current theme: light)</span>
<span class="visually-hidden theme-label-when-dark">Toggle theme (current theme: dark)</span>
<svg aria-hidden="true" class="theme-icon-when-auto">
<use xlink:href="#icon-auto" />
</svg>
<svg aria-hidden="true" class="theme-icon-when-dark">
<use xlink:href="#icon-moon" />
</svg>
<svg aria-hidden="true" class="theme-icon-when-light">
<use xlink:href="#icon-sun" />
</svg>
<span class="visually-hidden theme-label-when-auto">Toggle theme (current theme: auto)</span>
<span class="visually-hidden theme-label-when-light">Toggle theme (current theme: light)</span>
<span class="visually-hidden theme-label-when-dark">Toggle theme (current theme: dark)</span>
<svg aria-hidden="true" class="theme-icon-when-auto">
<use xlink:href="#icon-auto"/>
</svg>
<svg aria-hidden="true" class="theme-icon-when-dark">
<use xlink:href="#icon-moon"/>
</svg>
<svg aria-hidden="true" class="theme-icon-when-light">
<use xlink:href="#icon-sun"/>
</svg>
</button>
</div>
</header>
</div>
</header>

<div id="main" class="main">
<main id="content-start" class="content" tabindex="-1">
<div id="content" class="colM">
<div id="content-main">
<!-- Role Selection -->
<div class="form-row">
<label for="id_role" class="required">Role:</label>
<select id="id_role" name="role">
<option value="contributor">Contributor</option>
<option value="tech-lead">Tech Lead</option>
</select>
</div>

<div id="main" class="main">
<main id="content-start" class="content" tabindex="-1">
<div id="content" class="colM">
<div id="content-main">
<form method="post" id="login-form">
<!-- GitHub Login Section for Contributor -->
<div id="github-section" style="display: none; text-align: center;">
<p>Sign in with GitHub:</p>
<a href="{% provider_login_url 'github' %}" style="display: inline-block;">
<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
alt="Sign in with GitHub"
style="width: 40px; height: 40px; vertical-align: middle;">
</a>
</div>

<!-- Tech Lead Sign Up / Login Form -->
<div id="form-section" style="display: none;">
<form method="post" id="signup-form">
{% csrf_token %}
<div class="form-row">
<label for="id_username" class="required">Email:</label>
Expand All @@ -65,29 +123,22 @@
<label for="id_confirm_password" class="required">Confirm password:</label>
<input type="password" name="confirm_password" required id="id_password">
</div>
<div class="form-row">
<label for="role" class="required">Role:</label>
{{ form.role }}
</div>
<div class="submit-row">
<input type="submit" value="Sign up">
</div>
<div class="submit-row">
<a href="/admin/">Log in</a>
<input type="submit" value="Sign Up as Tech Lead">
</div>
</form>

<!-- Login Link for Tech Lead -->
<div id="tech-lead-login-link" style="display: none;">
<p>Already a Tech Lead? <a href="/admin/">Log in as Tech Lead</a></p>
</div>
</div>
<br class="clear">
</div>
</main>
</div>
<br class="clear">
</div>
</main>
</div>
<footer id="footer"></footer>
</div>

<svg xmlns="http://www.w3.org/2000/svg" class="base-svgs">
<symbol viewBox="0 0 24 24" width="1rem" height="1rem" id="icon-auto"><path d="M0 0h24v24H0z" fill="currentColor"/><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2V4a8 8 0 1 0 0 16z"/></symbol>
<symbol viewBox="0 0 24 24" width="1rem" height="1rem" id="icon-moon"><path d="M0 0h24v24H0z" fill="currentColor"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol>
<symbol viewBox="0 0 24 24" width="1rem" height="1rem" id="icon-sun"><path d="M0 0h24v24H0z" fill="currentColor"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol>
</svg>
</body>
</html>
Loading