summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunil Shetye2024-05-22 17:07:30 +0530
committerSunil Shetye2024-05-22 17:55:56 +0530
commit65e926c01d2f2e5418ea6530d16f436468dcf293 (patch)
treeffd6f99d7052c40c95bb2f3581db7293e38ca746
parent9adc9f7a6e104fdd8bcfc2e91891bec39ede9be1 (diff)
downloadCommon-Interface-Project-65e926c01d2f2e5418ea6530d16f436468dcf293.tar.gz
Common-Interface-Project-65e926c01d2f2e5418ea6530d16f436468dcf293.tar.bz2
Common-Interface-Project-65e926c01d2f2e5418ea6530d16f436468dcf293.zip
add authAPI
-rw-r--r--blocks/authAPI/__init__.py0
-rw-r--r--blocks/authAPI/admin.py6
-rw-r--r--blocks/authAPI/apps.py5
-rw-r--r--blocks/authAPI/models.py7
-rw-r--r--blocks/authAPI/serializers.py45
-rw-r--r--blocks/authAPI/templates/activate_user.html109
-rw-r--r--blocks/authAPI/templates/css/normalize.css438
-rw-r--r--blocks/authAPI/templates/css/skeleton.css418
-rw-r--r--blocks/authAPI/templates/google_callback.html20
-rw-r--r--blocks/authAPI/tests.py1
-rw-r--r--blocks/authAPI/token.py10
-rw-r--r--blocks/authAPI/urls.py10
-rw-r--r--blocks/authAPI/views.py97
-rw-r--r--blocks/blocks/settings.py3
-rw-r--r--blocks/blocks/urls.py3
-rw-r--r--blocks/requirements.txt17
16 files changed, 1189 insertions, 0 deletions
diff --git a/blocks/authAPI/__init__.py b/blocks/authAPI/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/blocks/authAPI/__init__.py
diff --git a/blocks/authAPI/admin.py b/blocks/authAPI/admin.py
new file mode 100644
index 00000000..3757febe
--- /dev/null
+++ b/blocks/authAPI/admin.py
@@ -0,0 +1,6 @@
+from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin
+from .models import User
+
+
+admin.site.register(User, UserAdmin)
diff --git a/blocks/authAPI/apps.py b/blocks/authAPI/apps.py
new file mode 100644
index 00000000..ad78e078
--- /dev/null
+++ b/blocks/authAPI/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class AuthapiConfig(AppConfig):
+ name = 'authAPI'
diff --git a/blocks/authAPI/models.py b/blocks/authAPI/models.py
new file mode 100644
index 00000000..7d79b7c7
--- /dev/null
+++ b/blocks/authAPI/models.py
@@ -0,0 +1,7 @@
+from django.db import models
+from django.contrib.auth.models import AbstractUser
+
+
+class User(AbstractUser):
+ id = models.AutoField(primary_key=True)
+ email = models.EmailField(unique=True)
diff --git a/blocks/authAPI/serializers.py b/blocks/authAPI/serializers.py
new file mode 100644
index 00000000..92286aec
--- /dev/null
+++ b/blocks/authAPI/serializers.py
@@ -0,0 +1,45 @@
+from django.contrib.auth import authenticate, get_user_model
+from rest_framework import serializers
+
+from djoser.conf import settings
+
+User = get_user_model()
+
+
+class TokenCreateSerializer(serializers.Serializer):
+ password = serializers.CharField(required=False,
+ style={"input_type": "password"})
+
+ default_error_messages = {
+ "invalid_credentials": "Incorrect username or password",
+ "inactive_account": """Your account is not activated.
+ Please click on the activation link
+ sent by email.""",
+ }
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.user = None
+ self.fields[settings.LOGIN_FIELD] = serializers.CharField()
+
+ def validate(self, attrs):
+ password = attrs.get("password")
+ params = {settings.LOGIN_FIELD: attrs.get(settings.LOGIN_FIELD)}
+ self.user = authenticate(
+ request=self.context.get("request"), **params, password=password
+ )
+ if not self.user:
+ self.user = User.objects.filter(**params).first()
+ if self.user and not self.user.is_active:
+ self.fail("inactive_account")
+
+ if self.user and not self.user.check_password(password):
+ self.fail("invalid_credentials")
+
+ if self.user and self.user.is_active:
+ return attrs
+
+ if self.user and (not self.user.is_active):
+ self.fail("inactive_account")
+
+ self.fail("invalid_credentials")
diff --git a/blocks/authAPI/templates/activate_user.html b/blocks/authAPI/templates/activate_user.html
new file mode 100644
index 00000000..23973370
--- /dev/null
+++ b/blocks/authAPI/templates/activate_user.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+
+ <!-- Basic Page Needs
+ –––––––––––––––––––––––––––––––––––––––––––––––––– -->
+ <meta charset="utf-8">
+ <title>Activate Account</title>
+ <meta name="description" content="">
+
+ <!-- Mobile Specific Metas
+ –––––––––––––––––––––––––––––––––––––––––––––––––– -->
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <!-- FONT
+ –––––––––––––––––––––––––––––––––––––––––––––––––– -->
+ <link href="//fonts.googleapis.com/css?family=Raleway:400,300,600" rel="stylesheet" type="text/css">
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
+
+ <!-- CSS
+ –––––––––––––––––––––––––––––––––––––––––––––––––– -->
+ <link rel="stylesheet" href="/css/normalize.css">
+ <link rel="stylesheet" href="/css/skeleton.css">
+ <style>
+ html,
+ body {
+ min-height: 100%;
+ }
+
+ .button {
+ border-color: #33C3F0;
+ }
+
+ .footer {
+ position: absolute;
+ bottom: 0;
+ min-width: 100%;
+ padding: 10px;
+ text-align: center;
+ }
+
+ #clickhere {
+ cursor: pointer;
+ }
+ </style>
+
+ <!-- Script
+ –––––––––––––––––––––––––––––––––––––––––––––––––– -->
+
+
+ <script>
+ function sendData() {
+ $.ajax({
+ url: "{{ activation_url }}",
+ data: { uid: '{{ uid }}', token: '{{ token }}' },
+ type: "POST",
+ dataType: "json",
+ //on success
+ success: function (data) {
+ window.location.replace('{{ redirect_url }}');
+ },
+ //on error
+ error: function (err) {
+ // ToDo: Error message popup
+ console.log(err)
+ $('#error-text').text(err.statusText)
+
+ }
+ });
+ }
+
+ </script>
+
+ <!-- Favicon
+ –––––––––––––––––––––––––––––––––––––––––––––––––– -->
+ <!-- <link rel="icon" type="image/png" href="images/favicon.png"> -->
+
+</head>
+
+<body>
+
+
+ <!-- Primary Page Layout
+ –––––––––––––––––––––––––––––––––––––––––––––––––– -->
+ <div class="container">
+ <div class="row">
+
+ <div style="padding-top: 30%; align-content: center;">
+ <h1 style="text-align: center;">To Activate Your Account
+ <a id="clickhere" onClick="sendData();"><strong><u>Click Here</u><strong></a></h1>
+ </div>
+ <div style="padding-top: 30%; align-content: center;">
+ <h1 style="text-align: center; color: #e25555;" id="error-text"> </h1>
+ </div>
+ </div>
+ </div>
+ <div class="container footer">
+ <footer class="twelve columns">
+ Made with <span style="color: #e25555;">&hearts;</span> by <a
+ href="https://github.com/frg-fossee">frg-fossee</a>
+ </footer>
+ </div> <!-- end footer div.container -->
+ </div>
+ <!-- End Document
+ –––––––––––––––––––––––––––––––––––––––––––––––––– -->
+</body>
+
+</html>
diff --git a/blocks/authAPI/templates/css/normalize.css b/blocks/authAPI/templates/css/normalize.css
new file mode 100644
index 00000000..a0a96625
--- /dev/null
+++ b/blocks/authAPI/templates/css/normalize.css
@@ -0,0 +1,438 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
+
+.footer-wrapper {
+position: relative;
+margin-top: 0;
+background-color: #e5e5e5;
+border-top: 1px solid #fff;
+bottom: -10px;
+height: 40px;
+width: 100%;}
+
+.footer-wrapper footer { margin: 0 auto; }
diff --git a/blocks/authAPI/templates/css/skeleton.css b/blocks/authAPI/templates/css/skeleton.css
new file mode 100644
index 00000000..f28bf6c5
--- /dev/null
+++ b/blocks/authAPI/templates/css/skeleton.css
@@ -0,0 +1,418 @@
+/*
+* Skeleton V2.0.4
+* Copyright 2014, Dave Gamache
+* www.getskeleton.com
+* Free to use under the MIT license.
+* http://www.opensource.org/licenses/mit-license.php
+* 12/29/2014
+*/
+
+
+/* Table of contents
+––––––––––––––––––––––––––––––––––––––––––––––––––
+- Grid
+- Base Styles
+- Typography
+- Links
+- Buttons
+- Forms
+- Lists
+- Code
+- Tables
+- Spacing
+- Utilities
+- Clearing
+- Media Queries
+*/
+
+
+/* Grid
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+.container {
+ position: relative;
+ width: 100%;
+ max-width: 960px;
+ margin: 0 auto;
+ padding: 0 20px;
+ box-sizing: border-box; }
+.column,
+.columns {
+ width: 100%;
+ float: left;
+ box-sizing: border-box; }
+
+/* For devices larger than 400px */
+@media (min-width: 400px) {
+ .container {
+ width: 85%;
+ padding: 0; }
+}
+
+/* For devices larger than 550px */
+@media (min-width: 550px) {
+ .container {
+ width: 80%; }
+ .column,
+ .columns {
+ margin-left: 4%; }
+ .column:first-child,
+ .columns:first-child {
+ margin-left: 0; }
+
+ .one.column,
+ .one.columns { width: 4.66666666667%; }
+ .two.columns { width: 13.3333333333%; }
+ .three.columns { width: 22%; }
+ .four.columns { width: 30.6666666667%; }
+ .five.columns { width: 39.3333333333%; }
+ .six.columns { width: 48%; }
+ .seven.columns { width: 56.6666666667%; }
+ .eight.columns { width: 65.3333333333%; }
+ .nine.columns { width: 74.0%; }
+ .ten.columns { width: 82.6666666667%; }
+ .eleven.columns { width: 91.3333333333%; }
+ .twelve.columns { width: 100%; margin-left: 0; }
+
+ .one-third.column { width: 30.6666666667%; }
+ .two-thirds.column { width: 65.3333333333%; }
+
+ .one-half.column { width: 48%; }
+
+ /* Offsets */
+ .offset-by-one.column,
+ .offset-by-one.columns { margin-left: 8.66666666667%; }
+ .offset-by-two.column,
+ .offset-by-two.columns { margin-left: 17.3333333333%; }
+ .offset-by-three.column,
+ .offset-by-three.columns { margin-left: 26%; }
+ .offset-by-four.column,
+ .offset-by-four.columns { margin-left: 34.6666666667%; }
+ .offset-by-five.column,
+ .offset-by-five.columns { margin-left: 43.3333333333%; }
+ .offset-by-six.column,
+ .offset-by-six.columns { margin-left: 52%; }
+ .offset-by-seven.column,
+ .offset-by-seven.columns { margin-left: 60.6666666667%; }
+ .offset-by-eight.column,
+ .offset-by-eight.columns { margin-left: 69.3333333333%; }
+ .offset-by-nine.column,
+ .offset-by-nine.columns { margin-left: 78.0%; }
+ .offset-by-ten.column,
+ .offset-by-ten.columns { margin-left: 86.6666666667%; }
+ .offset-by-eleven.column,
+ .offset-by-eleven.columns { margin-left: 95.3333333333%; }
+
+ .offset-by-one-third.column,
+ .offset-by-one-third.columns { margin-left: 34.6666666667%; }
+ .offset-by-two-thirds.column,
+ .offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
+
+ .offset-by-one-half.column,
+ .offset-by-one-half.columns { margin-left: 52%; }
+
+}
+
+
+/* Base Styles
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+/* NOTE
+html is set to 62.5% so that all the REM measurements throughout Skeleton
+are based on 10px sizing. So basically 1.5rem = 15px :) */
+html {
+ font-size: 62.5%; }
+body {
+ font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
+ line-height: 1.6;
+ font-weight: 400;
+ font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #222; }
+
+
+/* Typography
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 0;
+ margin-bottom: 2rem;
+ font-weight: 300; }
+h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;}
+h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
+h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; }
+h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }
+h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; }
+h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
+
+/* Larger than phablet */
+@media (min-width: 550px) {
+ h1 { font-size: 5.0rem; }
+ h2 { font-size: 4.2rem; }
+ h3 { font-size: 3.6rem; }
+ h4 { font-size: 3.0rem; }
+ h5 { font-size: 2.4rem; }
+ h6 { font-size: 1.5rem; }
+}
+
+p {
+ margin-top: 0; }
+
+
+/* Links
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+a {
+ color: #1EAEDB; }
+a:hover {
+ color: #0FA0CE; }
+
+
+/* Buttons
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+.button,
+button,
+input[type="submit"],
+input[type="reset"],
+input[type="button"] {
+ display: inline-block;
+ height: 38px;
+ padding: 0 30px;
+ color: #555;
+ text-align: center;
+ font-size: 11px;
+ font-weight: 600;
+ line-height: 38px;
+ letter-spacing: .1rem;
+ text-transform: uppercase;
+ text-decoration: none;
+ white-space: nowrap;
+ background-color: transparent;
+ border-radius: 4px;
+ border: 1px solid #bbb;
+ cursor: pointer;
+ box-sizing: border-box; }
+.button:hover,
+button:hover,
+input[type="submit"]:hover,
+input[type="reset"]:hover,
+input[type="button"]:hover,
+.button:focus,
+button:focus,
+input[type="submit"]:focus,
+input[type="reset"]:focus,
+input[type="button"]:focus {
+ color: #333;
+ border-color: #888;
+ outline: 0; }
+.button.button-primary,
+button.button-primary,
+input[type="submit"].button-primary,
+input[type="reset"].button-primary,
+input[type="button"].button-primary {
+ color: #FFF;
+ background-color: #33C3F0;
+ border-color: #33C3F0; }
+.button.button-primary:hover,
+button.button-primary:hover,
+input[type="submit"].button-primary:hover,
+input[type="reset"].button-primary:hover,
+input[type="button"].button-primary:hover,
+.button.button-primary:focus,
+button.button-primary:focus,
+input[type="submit"].button-primary:focus,
+input[type="reset"].button-primary:focus,
+input[type="button"].button-primary:focus {
+ color: #FFF;
+ background-color: #1EAEDB;
+ border-color: #1EAEDB; }
+
+
+/* Forms
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+input[type="email"],
+input[type="number"],
+input[type="search"],
+input[type="text"],
+input[type="tel"],
+input[type="url"],
+input[type="password"],
+textarea,
+select {
+ height: 38px;
+ padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
+ background-color: #fff;
+ border: 1px solid #D1D1D1;
+ border-radius: 4px;
+ box-shadow: none;
+ box-sizing: border-box; }
+/* Removes awkward default styles on some inputs for iOS */
+input[type="email"],
+input[type="number"],
+input[type="search"],
+input[type="text"],
+input[type="tel"],
+input[type="url"],
+input[type="password"],
+textarea {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none; }
+textarea {
+ min-height: 65px;
+ padding-top: 6px;
+ padding-bottom: 6px; }
+input[type="email"]:focus,
+input[type="number"]:focus,
+input[type="search"]:focus,
+input[type="text"]:focus,
+input[type="tel"]:focus,
+input[type="url"]:focus,
+input[type="password"]:focus,
+textarea:focus,
+select:focus {
+ border: 1px solid #33C3F0;
+ outline: 0; }
+label,
+legend {
+ display: block;
+ margin-bottom: .5rem;
+ font-weight: 600; }
+fieldset {
+ padding: 0;
+ border-width: 0; }
+input[type="checkbox"],
+input[type="radio"] {
+ display: inline; }
+label > .label-body {
+ display: inline-block;
+ margin-left: .5rem;
+ font-weight: normal; }
+
+
+/* Lists
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+ul {
+ list-style: circle inside; }
+ol {
+ list-style: decimal inside; }
+ol, ul {
+ padding-left: 0;
+ margin-top: 0; }
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+ margin: 1.5rem 0 1.5rem 3rem;
+ font-size: 90%; }
+li {
+ margin-bottom: 1rem; }
+
+
+/* Code
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+code {
+ padding: .2rem .5rem;
+ margin: 0 .2rem;
+ font-size: 90%;
+ white-space: nowrap;
+ background: #F1F1F1;
+ border: 1px solid #E1E1E1;
+ border-radius: 4px; }
+pre > code {
+ display: block;
+ padding: 1rem 1.5rem;
+ white-space: pre; }
+
+
+/* Tables
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+th,
+td {
+ padding: 12px 15px;
+ text-align: left;
+ border-bottom: 1px solid #E1E1E1; }
+th:first-child,
+td:first-child {
+ padding-left: 0; }
+th:last-child,
+td:last-child {
+ padding-right: 0; }
+
+
+/* Spacing
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+button,
+.button {
+ margin-bottom: 1rem; }
+input,
+textarea,
+select,
+fieldset {
+ margin-bottom: 1.5rem; }
+pre,
+blockquote,
+dl,
+figure,
+table,
+p,
+ul,
+ol,
+form {
+ margin-bottom: 2.5rem; }
+
+
+/* Utilities
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+.u-full-width {
+ width: 100%;
+ box-sizing: border-box; }
+.u-max-full-width {
+ max-width: 100%;
+ box-sizing: border-box; }
+.u-pull-right {
+ float: right; }
+.u-pull-left {
+ float: left; }
+
+
+/* Misc
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+hr {
+ margin-top: 3rem;
+ margin-bottom: 3.5rem;
+ border-width: 0;
+ border-top: 1px solid #E1E1E1; }
+
+
+/* Clearing
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+
+/* Self Clearing Goodness */
+.container:after,
+.row:after,
+.u-cf {
+ content: "";
+ display: table;
+ clear: both; }
+
+
+/* Media Queries
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+/*
+Note: The best way to structure the use of media queries is to create the queries
+near the relevant code. For example, if you wanted to change the styles for buttons
+on small devices, paste the mobile query code up in the buttons section and style it
+there.
+*/
+
+
+/* Larger than mobile */
+@media (min-width: 400px) {}
+
+/* Larger than phablet (also point when grid becomes active) */
+@media (min-width: 550px) {}
+
+/* Larger than tablet */
+@media (min-width: 750px) {}
+
+/* Larger than desktop */
+@media (min-width: 1000px) {}
+
+/* Larger than Desktop HD */
+@media (min-width: 1200px) {}
diff --git a/blocks/authAPI/templates/google_callback.html b/blocks/authAPI/templates/google_callback.html
new file mode 100644
index 00000000..51641258
--- /dev/null
+++ b/blocks/authAPI/templates/google_callback.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Redirecting to the destination...</title>
+ <script>
+ window.localStorage.setItem('xcos_token', '{{ token }}');
+ var redirect_to = window.localStorage.getItem('ard_redurl');
+ if (redirect_to) {
+ window.localStorage.removeItem('ard_redurl');
+ window.open(redirect_to, '_self')
+ } else {
+ window.open('{{url}}', '_self')
+ }
+ </script>
+</head>
+<body></body>
+</html> \ No newline at end of file
diff --git a/blocks/authAPI/tests.py b/blocks/authAPI/tests.py
new file mode 100644
index 00000000..a39b155a
--- /dev/null
+++ b/blocks/authAPI/tests.py
@@ -0,0 +1 @@
+# Create your tests here.
diff --git a/blocks/authAPI/token.py b/blocks/authAPI/token.py
new file mode 100644
index 00000000..24ea745d
--- /dev/null
+++ b/blocks/authAPI/token.py
@@ -0,0 +1,10 @@
+class TokenStrategy:
+ @classmethod
+ def obtain(cls, user):
+ from rest_framework.authtoken.models import Token
+ from django.utils.six import text_type
+
+ token = Token.objects.create(user=...)
+ return {
+ "token": text_type(token.key),
+ }
diff --git a/blocks/authAPI/urls.py b/blocks/authAPI/urls.py
new file mode 100644
index 00000000..e38fb710
--- /dev/null
+++ b/blocks/authAPI/urls.py
@@ -0,0 +1,10 @@
+from django.conf.urls import url
+from authAPI import views as authAPI_views
+
+
+urlpatterns = [
+ url(r'^google-callback', authAPI_views.GoogleOAuth2),
+ url(r'^users/activate/(?P<uid>[\w-]+)/(?P<token>[\w-]+)/$',
+ authAPI_views.activate_user),
+ url(r'user/token/', authAPI_views.CustomTokenCreateView.as_view())
+]
diff --git a/blocks/authAPI/views.py b/blocks/authAPI/views.py
new file mode 100644
index 00000000..7468cb36
--- /dev/null
+++ b/blocks/authAPI/views.py
@@ -0,0 +1,97 @@
+from rest_framework import generics, status, permissions
+from rest_framework.response import Response
+from django.conf import settings
+from requests_oauthlib import OAuth2Session
+from django.contrib.auth import get_user_model
+from djoser.conf import settings as djoser_settings
+from random import randint
+from django.shortcuts import render
+from django.http import HttpResponseNotFound
+from djoser import utils
+from djoser.serializers import TokenSerializer
+from authAPI.serializers import TokenCreateSerializer
+
+Token = djoser_settings.TOKEN_MODEL
+
+
+def activate_user(request, uid, token):
+ """
+ Used to activate accounts,
+ sends POST request to /api/auth/users/activation/ route
+ internally to activate account.
+ Link to this route is sent via email to user for verification
+ """
+
+ protocol = 'https://' if request.is_secure() else 'http://'
+ web_url = protocol + request.get_host() + '/api/auth/users/activation/' # noqa URL comes from Djoser library
+ return render(request, 'activate_user.html',
+ {'uid': uid,
+ 'token': token,
+ 'activation_url': web_url,
+ 'redirect_url': settings.POST_ACTIVATE_REDIRECT_URL
+ })
+
+
+def GoogleOAuth2(request):
+ state = request.GET.get('state', None)
+ code = request.GET.get('code', None)
+
+ if not (state is None) or not (code is None):
+ client_id = settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY
+ client_secret = settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET
+
+ google = OAuth2Session(
+ client_id,
+ redirect_uri=settings.GOOGLE_OAUTH_REDIRECT_URI,
+ state=state
+ )
+ google.fetch_token(
+ 'https://accounts.google.com/o/oauth2/token',
+ client_secret=client_secret,
+ code=code
+ )
+
+ user_info = google.get(
+ 'https://www.googleapis.com/oauth2/v1/userinfo').json()
+
+ if user_info['email']:
+ user, created = get_user_model().objects.get_or_create(
+ email=user_info['email'])
+ if created:
+ # If User was created
+ # Set name to firstname_lastname1209
+ username = user_info['name'].strip().replace(
+ ' ', '_') + str(randint(0, 9999))
+ user.username = username
+ user.save()
+ token, created = Token.objects.get_or_create(user=user)
+
+ protocol = 'https://' if request.is_secure() else 'http://'
+ web_url = protocol + request.get_host() + '/eda/#/login'
+
+ return render(request, 'google_callback.html',
+ {
+ "token": token,
+ "url": web_url
+ })
+ return HttpResponseNotFound("<h1>Page Not Found</h1>")
+
+
+class CustomTokenCreateView(utils.ActionViewMixin, generics.GenericAPIView):
+ """
+ Use this endpoint to obtain user authentication token.
+ """
+
+ serializer_class = TokenCreateSerializer
+ permission_classes = [permissions.AllowAny]
+
+ def _action(self, serializer):
+ token = utils.login_user(self.request, serializer.user)
+ token_serializer_class = TokenSerializer
+ data = {
+ 'auth_token': token_serializer_class(token).data["auth_token"],
+ 'user_id': serializer.user.id
+ }
+ return Response(
+ data=data, status=status.HTTP_200_OK
+ )
diff --git a/blocks/blocks/settings.py b/blocks/blocks/settings.py
index e71104a6..151db70a 100644
--- a/blocks/blocks/settings.py
+++ b/blocks/blocks/settings.py
@@ -52,6 +52,7 @@ INSTALLED_APPS = [
'django_filters',
'corsheaders',
'rest_framework',
+ 'authAPI',
'simulationAPI',
]
@@ -86,6 +87,8 @@ TEMPLATES = [
WSGI_APPLICATION = 'blocks.wsgi.application'
+AUTH_USER_MODEL = 'authAPI.User'
+
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
diff --git a/blocks/blocks/urls.py b/blocks/blocks/urls.py
index 3b3df835..59997e3e 100644
--- a/blocks/blocks/urls.py
+++ b/blocks/blocks/urls.py
@@ -19,6 +19,9 @@ from django.urls import path, include
urlpatterns = [
path('api/admin/', admin.site.urls),
+ # Auth API Routes
+ path('api/auth/', include('authAPI.urls')),
+
# Simulation API Routes
path('api/simulation/', include('simulationAPI.urls')),
diff --git a/blocks/requirements.txt b/blocks/requirements.txt
index f159393a..93d5a10e 100644
--- a/blocks/requirements.txt
+++ b/blocks/requirements.txt
@@ -3,27 +3,44 @@ asgiref==3.6.0
async-timeout==4.0.2
billiard==4.2.0
celery==5.3.6
+certifi==2024.2.2
+cffi==1.16.0
+charset-normalizer==3.3.2
click==8.1.3
click-didyoumean==0.3.0
click-plugins==1.1.1
click-repl==0.2.0
+cryptography==42.0.7
defusedxml==0.7.1
Django==3.2.25
django-cors-headers==3.13.0
django-filter==22.1
+django-templated-mail==1.1.1
djangorestframework==3.14.0
+djangorestframework-simplejwt==5.3.1
+djoser==2.2.2
flake8==6.0.0
+idna==3.7
kombu==5.3.5
mccabe==0.7.0
+oauthlib==3.2.2
prompt-toolkit==3.0.36
pycodestyle==2.10.0
+pycparser==2.22
pyflakes==3.0.1
+PyJWT==2.8.0
python-dateutil==2.8.2
+python3-openid==3.2.0
pytz==2022.7.1
PyYAML==6.0.1
redis==4.5.4
+requests==2.32.2
+requests-oauthlib==2.0.0
six==1.16.0
+social-auth-app-django==5.4.1
+social-auth-core==4.5.4
sqlparse==0.5.0
tzdata==2024.1
+urllib3==2.2.1
vine==5.1.0
wcwidth==0.2.6