diff --git a/oshc/authentication/__init__.py b/oshc/authentication/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/oshc/authentication/admin.py b/oshc/authentication/admin.py
new file mode 100644
index 0000000..e69de29
diff --git a/oshc/authentication/apps.py b/oshc/authentication/apps.py
new file mode 100644
index 0000000..9635c9d
--- /dev/null
+++ b/oshc/authentication/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class AuthenticationConfig(AppConfig):
+ name = 'authentication'
diff --git a/oshc/authentication/migrations/__init__.py b/oshc/authentication/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/oshc/authentication/models.py b/oshc/authentication/models.py
new file mode 100644
index 0000000..e69de29
diff --git a/oshc/authentication/regbackend.py b/oshc/authentication/regbackend.py
new file mode 100644
index 0000000..31b2e6d
--- /dev/null
+++ b/oshc/authentication/regbackend.py
@@ -0,0 +1,24 @@
+from django.contrib.auth import get_user_model
+
+
+class EmailLoginBackend(object):
+ '''
+ This class checks that the user can be authenticated via our backend and if it fails than normal authentication backend is used.
+ '''
+
+ def authenticate(self, username=None, password=None):
+ user_cls = get_user_model()
+ try:
+ user = user_cls.objects.get(email=username)
+ if user.check_password(password):
+ return user
+ except user_cls.DoesNotExist:
+ return None
+ return None
+
+ def get_user(self, user_id):
+ user_cls = get_user_model()
+ try:
+ return user_cls.objects.get(pk=user_id)
+ except user_cls.DoesNotExist:
+ return None
diff --git a/oshc/authentication/tests.py b/oshc/authentication/tests.py
new file mode 100644
index 0000000..e69de29
diff --git a/oshc/authentication/urls.py b/oshc/authentication/urls.py
new file mode 100644
index 0000000..0a5b1aa
--- /dev/null
+++ b/oshc/authentication/urls.py
@@ -0,0 +1,8 @@
+from django.conf.urls import url, include
+from . import views
+
+urlpatterns = [
+ url(r'^accounts/', include('allauth.urls')),
+ url(r'^accounts/login/profile/', views.profile, name="profile"),
+ url(r'^ajax/validate_username/$', views.validate_username, name='validate_username'),
+]
diff --git a/oshc/authentication/views.py b/oshc/authentication/views.py
new file mode 100644
index 0000000..d5be2d2
--- /dev/null
+++ b/oshc/authentication/views.py
@@ -0,0 +1,15 @@
+from django.shortcuts import render
+from django.contrib.auth.models import User
+from django.http import JsonResponse
+
+
+def profile(request):
+ return render(request, "profile.html")
+
+
+def validate_username(request):
+ username = request.GET.get('username', None)
+ data = {
+ 'is_present': User.objects.filter(username__iexact=username).exists()
+ }
+ return JsonResponse(data)
\ No newline at end of file
diff --git a/oshc/main/static/main/css/app.css b/oshc/main/static/main/css/app.css
index 289c069..764d6bd 100644
--- a/oshc/main/static/main/css/app.css
+++ b/oshc/main/static/main/css/app.css
@@ -354,11 +354,11 @@ footer .container {
border-top-right-radius: 0;
}
-.forgot-password {
+.form-registration .forgot-password {
margin-top: 10px;
}
-.new-account {
+.form-registration .new-account {
display: block;
margin-top: 10px;
}
@@ -379,26 +379,3 @@ footer .container {
.form-registration button:focus {
background: #0275d8;
}
-
-/*css for strength meter*/
-
-.strength-wrapper {
- margin-top: -33px;
-}
-
-.strength-wrapper .strength {
- float:left;
- width:72px;
- height:3px;
- margin-right: 3px;
-}
-
-#passwordStrengthString {
- font-size: 0.8em;
- margin-left: -299px;
- font-weight: bold;
-}
-
-.zone {
- display:none;
-}
diff --git a/oshc/main/static/main/images/user.png b/oshc/main/static/main/images/user.png
new file mode 100644
index 0000000..b27b17a
Binary files /dev/null and b/oshc/main/static/main/images/user.png differ
diff --git a/oshc/main/static/main/js/pwstrength.js b/oshc/main/static/main/js/pwstrength.js
new file mode 100644
index 0000000..998b3c6
--- /dev/null
+++ b/oshc/main/static/main/js/pwstrength.js
@@ -0,0 +1,863 @@
+/*!
+* jQuery Password Strength plugin for Twitter Bootstrap
+* Version: 2.1.3
+*
+* Copyright (c) 2008-2013 Tane Piper
+* Copyright (c) 2013 Alejandro Blanco
+* Dual licensed under the MIT and GPL licenses.
+*/
+
+(function (jQuery) {
+// Source: src/i18n.js
+
+
+
+
+var i18n = {};
+
+(function (i18n, i18next) {
+ 'use strict';
+
+ i18n.fallback = {
+ "wordMinLength": "Your password is too short",
+ "wordMaxLength": "Your password is too long",
+ "wordInvalidChar": "Your password contains an invalid character",
+ "wordNotEmail": "Do not use your email as your password",
+ "wordSimilarToUsername": "Your password cannot contain your username",
+ "wordTwoCharacterClasses": "Use different character classes",
+ "wordRepetitions": "Too many repetitions",
+ "wordSequences": "Your password contains sequences",
+ "errorList": "Errors:",
+ "veryWeak": "Very Weak",
+ "weak": "Weak",
+ "normal": "Normal",
+ "medium": "Medium",
+ "strong": "Strong",
+ "veryStrong": "Very Strong"
+ };
+
+ i18n.t = function (key) {
+ var result = '';
+
+ // Try to use i18next.com
+ if (i18next) {
+ result = i18next.t(key);
+ } else {
+ // Fallback to english
+ result = i18n.fallback[key];
+ }
+
+ return result === key ? '' : result;
+ };
+}(i18n, window.i18next));
+
+// Source: src/rules.js
+
+
+
+
+var rulesEngine = {};
+
+try {
+ if (!jQuery && module && module.exports) {
+ var jQuery = require("jquery"),
+ jsdom = require("jsdom").jsdom;
+ jQuery = jQuery(jsdom().defaultView);
+ }
+} catch (ignore) {}
+
+(function ($, rulesEngine) {
+ "use strict";
+ var validation = {};
+
+ rulesEngine.forbiddenSequences = [
+ "0123456789", "abcdefghijklmnopqrstuvwxyz", "qwertyuiop", "asdfghjkl",
+ "zxcvbnm", "!@#$%^&*()_+"
+ ];
+
+ validation.wordNotEmail = function (options, word, score) {
+ if (word.match(/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i)) {
+ return score;
+ }
+ return 0;
+ };
+
+ validation.wordMinLength = function (options, word, score) {
+ var wordlen = word.length,
+ lenScore = Math.pow(wordlen, options.rules.raisePower);
+ if (wordlen < options.common.minChar) {
+ lenScore = (lenScore + score);
+ }
+ return lenScore;
+ };
+
+ validation.wordMaxLength = function (options, word, score) {
+ var wordlen = word.length,
+ lenScore = Math.pow(wordlen, options.rules.raisePower);
+ if (wordlen > options.common.maxChar) {
+ return score;
+ }
+ return lenScore;
+ };
+
+ validation.wordInvalidChar = function (options, word, score) {
+ if (word.match(/[\s,',"]/)) {
+ return score;
+ }
+ return 0;
+ };
+
+ validation.wordMinLengthStaticScore = function (options, word, score) {
+ return word.length < options.common.minChar ? 0 : score;
+ };
+
+ validation.wordMaxLengthStaticScore = function (options, word, score) {
+ return word.length > options.common.maxChar ? 0 : score;
+ };
+
+
+ validation.wordSimilarToUsername = function (options, word, score) {
+ var username = $(options.common.usernameField).val();
+ if (username && word.toLowerCase().match(username.replace(/[\-\[\]\/\{\}\(\)\*\+\=\?\:\.\\\^\$\|\!\,]/g, "\\$&").toLowerCase())) {
+ return score;
+ }
+ return 0;
+ };
+
+ validation.wordTwoCharacterClasses = function (options, word, score) {
+ if (word.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) ||
+ (word.match(/([a-zA-Z])/) && word.match(/([0-9])/)) ||
+ (word.match(/(.[!,@,#,$,%,\^,&,*,?,_,~])/) && word.match(/[a-zA-Z0-9_]/))) {
+ return score;
+ }
+ return 0;
+ };
+
+ validation.wordRepetitions = function (options, word, score) {
+ if (word.match(/(.)\1\1/)) { return score; }
+ return 0;
+ };
+
+ validation.wordSequences = function (options, word, score) {
+ var found = false,
+ j;
+ if (word.length > 2) {
+ $.each(rulesEngine.forbiddenSequences, function (idx, seq) {
+ if (found) { return; }
+ var sequences = [seq, seq.split('').reverse().join('')];
+ $.each(sequences, function (idx, sequence) {
+ for (j = 0; j < (word.length - 2); j += 1) { // iterate the word trough a sliding window of size 3:
+ if (sequence.indexOf(word.toLowerCase().substring(j, j + 3)) > -1) {
+ found = true;
+ }
+ }
+ });
+ });
+ if (found) { return score; }
+ }
+ return 0;
+ };
+
+ validation.wordLowercase = function (options, word, score) {
+ return word.match(/[a-z]/) && score;
+ };
+
+ validation.wordUppercase = function (options, word, score) {
+ return word.match(/[A-Z]/) && score;
+ };
+
+ validation.wordOneNumber = function (options, word, score) {
+ return word.match(/\d+/) && score;
+ };
+
+ validation.wordThreeNumbers = function (options, word, score) {
+ return word.match(/(.*[0-9].*[0-9].*[0-9])/) && score;
+ };
+
+ validation.wordOneSpecialChar = function (options, word, score) {
+ return word.match(/[!,@,#,$,%,\^,&,*,?,_,~]/) && score;
+ };
+
+ validation.wordTwoSpecialChar = function (options, word, score) {
+ return word.match(/(.*[!,@,#,$,%,\^,&,*,?,_,~].*[!,@,#,$,%,\^,&,*,?,_,~])/) && score;
+ };
+
+ validation.wordUpperLowerCombo = function (options, word, score) {
+ return word.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) && score;
+ };
+
+ validation.wordLetterNumberCombo = function (options, word, score) {
+ return word.match(/([a-zA-Z])/) && word.match(/([0-9])/) && score;
+ };
+
+ validation.wordLetterNumberCharCombo = function (options, word, score) {
+ return word.match(/([a-zA-Z0-9].*[!,@,#,$,%,\^,&,*,?,_,~])|([!,@,#,$,%,\^,&,*,?,_,~].*[a-zA-Z0-9])/) && score;
+ };
+
+ rulesEngine.validation = validation;
+
+ rulesEngine.executeRules = function (options, word) {
+ var totalScore = 0;
+
+ $.each(options.rules.activated, function (rule, active) {
+ if (active) {
+ var score = options.rules.scores[rule],
+ funct = rulesEngine.validation[rule],
+ result,
+ errorMessage;
+
+ if (!$.isFunction(funct)) {
+ funct = options.rules.extra[rule];
+ }
+
+ if ($.isFunction(funct)) {
+ result = funct(options, word, score);
+ if (result) {
+ totalScore += result;
+ }
+ if (result < 0 || (!$.isNumeric(result) && !result)) {
+ errorMessage = options.ui.spanError(options, rule);
+ if (errorMessage.length > 0) {
+ options.instances.errors.push(errorMessage);
+ }
+ }
+ }
+ }
+ });
+
+ return totalScore;
+ };
+}(jQuery, rulesEngine));
+
+try {
+ if (module && module.exports) {
+ module.exports = rulesEngine;
+ }
+} catch (ignore) {}
+
+// Source: src/options.js
+
+
+
+
+var defaultOptions = {};
+
+defaultOptions.common = {};
+defaultOptions.common.minChar = 6;
+defaultOptions.common.maxChar = 20;
+defaultOptions.common.usernameField = "#username";
+defaultOptions.common.userInputs = [
+ // Selectors for input fields with user input
+];
+defaultOptions.common.onLoad = undefined;
+defaultOptions.common.onKeyUp = undefined;
+defaultOptions.common.onScore = undefined;
+defaultOptions.common.zxcvbn = false;
+defaultOptions.common.zxcvbnTerms = [
+ // List of disrecommended words
+];
+defaultOptions.common.events = ["keyup", "change", "paste"];
+defaultOptions.common.debug = false;
+
+defaultOptions.rules = {};
+defaultOptions.rules.extra = {};
+defaultOptions.rules.scores = {
+ wordNotEmail: -100,
+ wordMinLength: -50,
+ wordMaxLength: -50,
+ wordInvalidChar: -100,
+ wordSimilarToUsername: -100,
+ wordSequences: -20,
+ wordTwoCharacterClasses: 2,
+ wordRepetitions: -25,
+ wordLowercase: 1,
+ wordUppercase: 3,
+ wordOneNumber: 3,
+ wordThreeNumbers: 5,
+ wordOneSpecialChar: 3,
+ wordTwoSpecialChar: 5,
+ wordUpperLowerCombo: 2,
+ wordLetterNumberCombo: 2,
+ wordLetterNumberCharCombo: 2
+};
+defaultOptions.rules.activated = {
+ wordNotEmail: true,
+ wordMinLength: true,
+ wordMaxLength: false,
+ wordInvalidChar: false,
+ wordSimilarToUsername: true,
+ wordSequences: true,
+ wordTwoCharacterClasses: false,
+ wordRepetitions: false,
+ wordLowercase: true,
+ wordUppercase: true,
+ wordOneNumber: true,
+ wordThreeNumbers: true,
+ wordOneSpecialChar: true,
+ wordTwoSpecialChar: true,
+ wordUpperLowerCombo: true,
+ wordLetterNumberCombo: true,
+ wordLetterNumberCharCombo: true
+};
+defaultOptions.rules.raisePower = 1.4;
+
+defaultOptions.ui = {};
+defaultOptions.ui.bootstrap2 = false;
+defaultOptions.ui.bootstrap4 = false;
+defaultOptions.ui.colorClasses = [
+ "danger", "danger", "danger", "warning", "warning", "success"
+];
+defaultOptions.ui.showProgressBar = true;
+defaultOptions.ui.progressBarEmptyPercentage = 1;
+defaultOptions.ui.progressBarMinPercentage = 1;
+defaultOptions.ui.progressExtraCssClasses = '';
+defaultOptions.ui.progressBarExtraCssClasses = '';
+defaultOptions.ui.showPopover = false;
+defaultOptions.ui.popoverPlacement = "bottom";
+defaultOptions.ui.showStatus = false;
+defaultOptions.ui.spanError = function (options, key) {
+ "use strict";
+ var text = options.i18n.t(key);
+ if (!text) { return ''; }
+ return '' + text + '';
+};
+defaultOptions.ui.popoverError = function (options) {
+ "use strict";
+ var errors = options.instances.errors,
+ errorsTitle = options.i18n.t("errorList"),
+ message = "
" + errorsTitle + "
";
+
+ jQuery.each(errors, function (idx, err) {
+ message += "- " + err + "
";
+ });
+ message += "
";
+ return message;
+};
+defaultOptions.ui.showVerdicts = true;
+defaultOptions.ui.showVerdictsInsideProgressBar = false;
+defaultOptions.ui.useVerdictCssClass = false;
+defaultOptions.ui.showErrors = false;
+defaultOptions.ui.showScore = false;
+defaultOptions.ui.container = undefined;
+defaultOptions.ui.viewports = {
+ progress: undefined,
+ verdict: undefined,
+ errors: undefined,
+ score: undefined
+};
+defaultOptions.ui.scores = [0, 14, 26, 38, 50];
+
+defaultOptions.i18n = {};
+defaultOptions.i18n.t = i18n.t;
+
+// Source: src/ui.js
+
+
+
+
+var ui = {};
+
+(function ($, ui) {
+ "use strict";
+
+ var statusClasses = ["error", "warning", "success"],
+ verdictKeys = [
+ "veryWeak", "weak", "normal", "medium", "strong", "veryStrong"
+ ];
+
+ ui.getContainer = function (options, $el) {
+ var $container;
+
+ $container = $(options.ui.container);
+ if (!($container && $container.length === 1)) {
+ $container = $el.parent();
+ }
+ return $container;
+ };
+
+ ui.findElement = function ($container, viewport, cssSelector) {
+ if (viewport) {
+ return $container.find(viewport).find(cssSelector);
+ }
+ return $container.find(cssSelector);
+ };
+
+ ui.getUIElements = function (options, $el) {
+ var $container, result;
+
+ if (options.instances.viewports) {
+ return options.instances.viewports;
+ }
+
+ $container = ui.getContainer(options, $el);
+
+ result = {};
+ result.$progressbar = ui.findElement($container, options.ui.viewports.progress, "div.progress");
+ if (options.ui.showVerdictsInsideProgressBar) {
+ result.$verdict = result.$progressbar.find("span.password-verdict");
+ }
+
+ if (!options.ui.showPopover) {
+ if (!options.ui.showVerdictsInsideProgressBar) {
+ result.$verdict = ui.findElement($container, options.ui.viewports.verdict, "span.password-verdict");
+ }
+ result.$errors = ui.findElement($container, options.ui.viewports.errors, "ul.error-list");
+ }
+ result.$score = ui.findElement($container, options.ui.viewports.score,
+ "span.password-score");
+
+ options.instances.viewports = result;
+ return result;
+ };
+
+ ui.initProgressBar = function (options, $el) {
+ var $container = ui.getContainer(options, $el),
+ progressbar = "
@@ -85,6 +92,7 @@
+ {% block javascript %}{% endblock %}