From a54e238aeac1a5747fc9e2b47efdca21c95c826e Mon Sep 17 00:00:00 2001 From: JingVT <33851894+JingVT@users.noreply.github.com> Date: Tue, 14 Aug 2018 10:10:59 -0400 Subject: [PATCH 1/8] Update PULL_REQUEST_TEMPLATE.md --- PULL_REQUEST_TEMPLATE.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 9de17e17..e30346ba 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,19 +1,19 @@ ## Purpose -_Describe the problem or feature in addition to a link to the issues._ - -Example: -Fixes # . +Built announcements and users email lists to post important announcements and allow users to communicate with each other. ## Approach -_How does this change address the problem?_ +Invoke GNU Mailman3 REST API. #### Open Questions and Pre-Merge TODOs -- [ ] Use github checklists. When solved, check the box and explain the answer. +- [ ] Merge [validates email address by sending a confirmation email to users](https://github.com/Murali-group/GraphSpace/pull/368) +- [ ] [Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix) +- [ ] Create the email lists of GraphSpace and add them to settings file +- [ ] Update the database. ## Learning -_Describe the research stage_ +[Mailman 3 suite documents](http://docs.mailman3.org/en/latest/) +[Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix) -_Links to blog posts, patterns, libraries or addons used to solve this problem_ #### Blog Posts - [How to Pull Request](https://github.com/flexyford/pull-request) Github Repo with Learning focused Pull Request Template. From 56ba549b2a0ffab554e9baf8054c6f115d4bc26c Mon Sep 17 00:00:00 2001 From: JingVT <33851894+JingVT@users.noreply.github.com> Date: Tue, 14 Aug 2018 10:16:22 -0400 Subject: [PATCH 2/8] Update PULL_REQUEST_TEMPLATE.md --- PULL_REQUEST_TEMPLATE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index e30346ba..2a8ac35d 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -12,6 +12,7 @@ Invoke GNU Mailman3 REST API. ## Learning [Mailman 3 suite documents](http://docs.mailman3.org/en/latest/) + [Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix) From 73cb7985665e944a5705a29a8c3bfa3c2871dd56 Mon Sep 17 00:00:00 2001 From: JingVT <33851894+JingVT@users.noreply.github.com> Date: Tue, 14 Aug 2018 10:18:51 -0400 Subject: [PATCH 3/8] Update PULL_REQUEST_TEMPLATE.md --- PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 2a8ac35d..c0312c02 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -6,7 +6,7 @@ Invoke GNU Mailman3 REST API. #### Open Questions and Pre-Merge TODOs - [ ] Merge [validates email address by sending a confirmation email to users](https://github.com/Murali-group/GraphSpace/pull/368) -- [ ] [Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix) +- [ ] [Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Running-GraphSpace-Locally) - [ ] Create the email lists of GraphSpace and add them to settings file - [ ] Update the database. From 4855a7e40e19d20cd21329f912cada34e77debf9 Mon Sep 17 00:00:00 2001 From: JingVT <33851894+JingVT@users.noreply.github.com> Date: Tue, 14 Aug 2018 10:20:15 -0400 Subject: [PATCH 4/8] Update PULL_REQUEST_TEMPLATE.md --- PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index c0312c02..2160943c 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -6,14 +6,14 @@ Invoke GNU Mailman3 REST API. #### Open Questions and Pre-Merge TODOs - [ ] Merge [validates email address by sending a confirmation email to users](https://github.com/Murali-group/GraphSpace/pull/368) -- [ ] [Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Running-GraphSpace-Locally) +- [ ] [Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix)) - [ ] Create the email lists of GraphSpace and add them to settings file - [ ] Update the database. ## Learning [Mailman 3 suite documents](http://docs.mailman3.org/en/latest/) -[Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix) +[Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix)) #### Blog Posts From 71b5aea52da9d77cba7246209713c3de4d8f37b3 Mon Sep 17 00:00:00 2001 From: JingVT <33851894+JingVT@users.noreply.github.com> Date: Tue, 14 Aug 2018 10:32:58 -0400 Subject: [PATCH 5/8] Update PULL_REQUEST_TEMPLATE.md --- PULL_REQUEST_TEMPLATE.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 2160943c..9de17e17 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,20 +1,19 @@ ## Purpose -Built announcements and users email lists to post important announcements and allow users to communicate with each other. +_Describe the problem or feature in addition to a link to the issues._ + +Example: +Fixes # . ## Approach -Invoke GNU Mailman3 REST API. +_How does this change address the problem?_ #### Open Questions and Pre-Merge TODOs -- [ ] Merge [validates email address by sending a confirmation email to users](https://github.com/Murali-group/GraphSpace/pull/368) -- [ ] [Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix)) -- [ ] Create the email lists of GraphSpace and add them to settings file -- [ ] Update the database. +- [ ] Use github checklists. When solved, check the box and explain the answer. ## Learning -[Mailman 3 suite documents](http://docs.mailman3.org/en/latest/) - -[Install and Configure Mailman3 Suite for GraphSpace](https://github.com/Murali-group/GraphSpace/wiki/Install-and-Configure-Mailman3-Suite-for-GraphSpace-(Ubuntu-16.04,-PostgreSQL,-Apache2,-Postfix)) +_Describe the research stage_ +_Links to blog posts, patterns, libraries or addons used to solve this problem_ #### Blog Posts - [How to Pull Request](https://github.com/flexyford/pull-request) Github Repo with Learning focused Pull Request Template. From e82d264ec7d08d1a006b06855411f86a6c1b0fcc Mon Sep 17 00:00:00 2001 From: jing Date: Sat, 1 Dec 2018 03:16:43 -0500 Subject: [PATCH 6/8] auth_token --- applications/home/urls.py | 1 + applications/home/views.py | 50 +++++++++++++++++++++++++++++-- applications/users/controllers.py | 31 +++++++++++++++---- applications/users/dal.py | 20 +++++++++++-- applications/users/models.py | 1 + docs/Programmers_Guide.md | 28 +++++++++++++++++ static/js/account_page.js | 10 +++++++ templates/404.html | 8 ++--- templates/500.html | 8 ++--- templates/account/auth_token.html | 13 ++++++++ templates/account/email.html | 16 ++++++++++ templates/account/index.html | 48 +++++++++++++++++++++++++++++ templates/partials/header.html | 5 +++- 13 files changed, 220 insertions(+), 19 deletions(-) create mode 100644 static/js/account_page.js create mode 100644 templates/account/auth_token.html create mode 100644 templates/account/email.html create mode 100644 templates/account/index.html diff --git a/applications/home/urls.py b/applications/home/urls.py index 2cabddce..7eb62b80 100644 --- a/applications/home/urls.py +++ b/applications/home/urls.py @@ -14,4 +14,5 @@ url(r'^about_us/$', views.about_us_page, name='about_us'), url(r'^forgot_password/$', views.forgot_password_page, name='forgot_password'), url(r'^reset_password/$', views.reset_password_page, name='reset_password'), + url(r'^account/$', views.account_page, name='account'), ] diff --git a/applications/home/views.py b/applications/home/views.py index d9ddf1a0..3359d23a 100644 --- a/applications/home/views.py +++ b/applications/home/views.py @@ -1,4 +1,5 @@ import json + from applications.users.forms import RegisterForm from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render, redirect @@ -7,6 +8,11 @@ from graphspace.utils import * from graphspace.exceptions import * +# import the logging library +import logging + +# Get an instance of a logger +logger = logging.getLogger(__name__) def home_page(request): """ @@ -157,7 +163,7 @@ def forgot_password_page(request): return render(request, 'forgot_password/index.html', context) # Handle GET request to forgot password page. elif 'POST' == request.method: password_reset_code = users.add_user_to_password_reset(request, email=request.POST.get('forgot_email', None)) - + logger.error(password_reset_code) if password_reset_code is not None: users.send_password_reset_email(request, password_reset_code) context["success_message"] = "Email has been sent!" @@ -218,7 +224,6 @@ def reset_password_page(request): def login(request): """ Handles login (POST) request. - :param request: HTTP Request """ if 'POST' == request.method: @@ -290,4 +295,43 @@ def images(request, query): :param request: HTTP GET Request """ - return redirect('/static' + request.path) \ No newline at end of file + return redirect('/static' + request.path) + + +def account_page(request): + """ + Wrapper view function for the following pages: + / + account/index.html + + Parameters + ---------- + request : HTTP Request + + Returns + ------- + response : HTML Page Response + Rendered account home page in HTML. + + Raises + ------ + MethodNotAllowed: If a user tries to send requests other than GET i.e., POST, PUT or UPDATE. + + Notes + ------ + + """ + context = RequestContext(request) # Checkout base.py file to see what context processors are being applied here. + + if 'GET' == request.method: + auth_token = users.get_auth_token(request, request.session['uid']) + logger.error(auth_token) + if auth_token is None: + context['error_message'] = "Please try logging in again." + else: + context['auth_token'] = auth_token + return render(request, 'account/index.html', context) # Handle GET request to auth_token page. + else: + raise MethodNotAllowed(request) # Handle other type of request methods like POST, PUT, UPDATE. + + diff --git a/applications/users/controllers.py b/applications/users/controllers.py index be2fe623..f8865a27 100644 --- a/applications/users/controllers.py +++ b/applications/users/controllers.py @@ -1,4 +1,5 @@ import bcrypt +import base64 from django.conf import settings from django.core.mail import send_mail @@ -19,6 +20,9 @@ def authenticate_user(request, username=None, password=None): # check the username/password and return a User user = db.get_user(request.db_session, username) + logger.error(user) + logger.error(username) + logger.error(password) if user: hashed_pw = user.password @@ -26,11 +30,15 @@ def authenticate_user(request, username=None, password=None): #check password. if the password matches, return a #User object with associated information if bcrypt.hashpw(password, hashed_pw) == hashed_pw: + #Check auth_token in database. If it is None, create and save new auth_token to database. + if user.auth_token == None: + user = update_user(request, user.id, email=user.email, password=password) return { 'id': user.id, 'user_id': user.email, 'password': user.password, - 'admin': user.is_admin + 'admin': user.is_admin, + 'auth_token': user.auth_token } else: return None @@ -40,11 +48,12 @@ def update_user(request, user_id, email=None, password=None, is_admin=None): user = {} if email is not None: user['email'] = email + user['auth_token'] = 'Basic %s' % base64.b64encode('{0}:{1}'.format(email, password)) if password is not None: user['password'] = bcrypt.hashpw(password, bcrypt.gensalt()) + user['auth_token'] = 'Basic %s' % base64.b64encode('{0}:{1}'.format(email, password)) if is_admin is not None: user['is_admin'] = is_admin - return db.update_user(request.db_session, id=user_id, updated_user=user) @@ -129,11 +138,12 @@ def search_users(request, email=None, limit=20, offset=0, order='desc', sort='na def register(request, username=None, password=None): if db.get_user(request.db_session, username): raise BadRequest(request, error_code=ErrorCodes.Validation.UserAlreadyExists, args=username) + auth_token = 'Basic %s' % base64.b64encode('{0}:{1}'.format(username, password)) - return add_user(request, email=username, password=password) + return add_user(request, email=username, password=password, auth_token=auth_token) -def add_user(request, email=None, password="graphspace_public_user", is_admin=0): +def add_user(request, email=None, password="graphspace_public_user", auth_token=None, is_admin=0): """ Add a new user. If email and password is not passed, it will create a user with default values. By default a user has no admin access. @@ -142,11 +152,12 @@ def add_user(request, email=None, password="graphspace_public_user", is_admin=0) :param email: User ID of the user. Default value is dynamically generated user id. :param password: Password of the user. Default value is "public". :param admin: 1 if user has admin access else 0. Default value is 0. + :param auth_token: Auth_token if the user. Default value is None. :return: User """ email = "public_user_%s@graphspace.com" % generate_uid(size=10) if email is None else email - return db.add_user(request.db_session, email=email, password=bcrypt.hashpw(password, bcrypt.gensalt()), is_admin=is_admin) + return db.add_user(request.db_session, email=email, password=bcrypt.hashpw(password, bcrypt.gensalt()), auth_token=auth_token, is_admin=is_admin) def is_member_of_group(request, username, group_id): @@ -312,3 +323,13 @@ def send_password_reset_email(request, password_reset_code): email_from = "GraphSpace Admin" return send_mail(mail_title, message, email_from, [password_reset_code.email], fail_silently=False) + +def get_auth_token(request, email): + # check the username and return a User + user = db.get_user(request.db_session, email) + + if user: + return user.auth_token + else: + return None + diff --git a/applications/users/dal.py b/applications/users/dal.py index 66b19861..f62e565b 100644 --- a/applications/users/dal.py +++ b/applications/users/dal.py @@ -7,12 +7,16 @@ from graphspace.wrappers import with_session from models import * +import logging + +# Get an instance of a logger +logger = logging.getLogger(__name__) # TODO: Add documentation about exception raised. @with_session -def add_user(db_session, email, password, is_admin): +def add_user(db_session, email, password, auth_token, is_admin): """ Add a new user. @@ -20,9 +24,10 @@ def add_user(db_session, email, password, is_admin): :param email: User ID of the user. :param password: Password of the user. :param admin: 1 if user has admin access else 0. + :param auth_token: Auth_token of the user. :return: User """ - user = User(email=email, password=password, is_admin = is_admin) + user = User(email=email, password=password, auth_token=auth_token, is_admin=is_admin) db_session.add(user) return user @@ -322,3 +327,14 @@ def find_groups(db_session, owner_email, member_email, name, description, graph_ query = query.limit(limit).offset(offset) return total, query.all() + +@with_session +def get_auth_token(db_session, email): + """ + Get the auth_token with given email. + + :param db_session: Database session. + :param email: email of the user. + :return: User's auth_token if email exists else None. + """ + return db_session.query().filter(User.email == email).one_or_none() diff --git a/applications/users/models.py b/applications/users/models.py index 053fc6f1..b3392715 100644 --- a/applications/users/models.py +++ b/applications/users/models.py @@ -23,6 +23,7 @@ class User(IDMixin, TimeStampMixin, Base): email = Column(String, nullable=False, unique=True, index=True) password = Column(String, nullable=False) is_admin = Column(Integer, nullable=False, default=0) + auth_token = Column(String, nullable=True) password_reset_codes = relationship("PasswordResetCode", back_populates="user", cascade="all, delete-orphan") owned_groups = relationship("Group", back_populates="owner", cascade="all, delete-orphan") diff --git a/docs/Programmers_Guide.md b/docs/Programmers_Guide.md index f2434b9d..8b7443e4 100644 --- a/docs/Programmers_Guide.md +++ b/docs/Programmers_Guide.md @@ -34,6 +34,34 @@ The GraphSpace REST API is served over HTTP. In case you are +## API Authentication Token +### Obtain Authentication Token +To get your API authentication token, log into your GraphSpace account and navigate to your account page. Once you are there click on the **Authentication Token** tab on the top. Then you can see your authentication token value. + +![Get Auth Token](_static/gifs/gs-screenshot-get-auth-token.gif) + +### Use Authentication Token to Access GraphSpace API +cURL is the most used command line tool for making API calls. Here we use cURL command as an example. + +**GET** +``` +curl -X GET \ + '**YOUR GRAPHSPACE API URL**' \ + -H 'accept: application/json' \ + -H 'authorization: Basic **YOUR API AUTH TOKEN**' \ + -H 'content-type: application/json' \ +``` +**POST** +``` +curl -X POST \ + **YOUR GRAPHSPACE API URL** \ + -H 'accept: application/json' \ + -H 'authorization: Basic **YOUR API AUTH TOKEN**' \ + -H 'content-type: application/json' \ + -d '**YOUR JSON DATA**' +``` + + ## graphspace-python diff --git a/static/js/account_page.js b/static/js/account_page.js new file mode 100644 index 00000000..b3eac968 --- /dev/null +++ b/static/js/account_page.js @@ -0,0 +1,10 @@ +var accountPage = { + init: function () { + /** + * This function is called to setup the account page. + * It will initialize all the event listeners. + */ + utils.initializeTabs(); + + }, +} diff --git a/templates/404.html b/templates/404.html index a564e7bf..e127f589 100644 --- a/templates/404.html +++ b/templates/404.html @@ -16,11 +16,11 @@ GraphSpace - - + + - + @@ -30,7 +30,7 @@

Sorry, but the page you are looking for is not f - + diff --git a/templates/500.html b/templates/500.html index a0868144..b648f5e9 100644 --- a/templates/500.html +++ b/templates/500.html @@ -16,11 +16,11 @@ GraphSpace - - + + - + @@ -36,7 +36,7 @@

- + diff --git a/templates/account/auth_token.html b/templates/account/auth_token.html new file mode 100644 index 00000000..361f3582 --- /dev/null +++ b/templates/account/auth_token.html @@ -0,0 +1,13 @@ +
+
+
Authentication
+
+
+
+

Type: Basic Auth

+

Value: {{ auth_token }}

+
+
+
+
+
diff --git a/templates/account/email.html b/templates/account/email.html new file mode 100644 index 00000000..266f2682 --- /dev/null +++ b/templates/account/email.html @@ -0,0 +1,16 @@ +
+
+
Email Address
+
+
+
+

+ {% if uid != None %} + {{ uid }} + {% endif %} +

+
+
+
+
+
diff --git a/templates/account/index.html b/templates/account/index.html new file mode 100644 index 00000000..c2fa89bc --- /dev/null +++ b/templates/account/index.html @@ -0,0 +1,48 @@ + + +{% extends 'base.html' %} +{% block content %} + {% load staticfiles %} + +
+ + +
+ +
+ {% include 'account/email.html' %} +
+ +
+ {% include 'account/auth_token.html' %} +
+ + +
+ +
+ + + + + + + + + + +{% endblock %} \ No newline at end of file diff --git a/templates/partials/header.html b/templates/partials/header.html index 13055281..72875bf0 100644 --- a/templates/partials/header.html +++ b/templates/partials/header.html @@ -35,7 +35,10 @@ From bd441c94868b5b2f5c2db515c4018366deab1de1 Mon Sep 17 00:00:00 2001 From: JingVT <33851894+JingVT@users.noreply.github.com> Date: Sat, 1 Dec 2018 03:21:28 -0500 Subject: [PATCH 7/8] Update controllers.py --- applications/users/controllers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/applications/users/controllers.py b/applications/users/controllers.py index f8865a27..2baa4eea 100644 --- a/applications/users/controllers.py +++ b/applications/users/controllers.py @@ -20,9 +20,6 @@ def authenticate_user(request, username=None, password=None): # check the username/password and return a User user = db.get_user(request.db_session, username) - logger.error(user) - logger.error(username) - logger.error(password) if user: hashed_pw = user.password From 24abe104a4089807932d7f312965833784ac35a4 Mon Sep 17 00:00:00 2001 From: JingVT <33851894+JingVT@users.noreply.github.com> Date: Sat, 1 Dec 2018 03:49:42 -0500 Subject: [PATCH 8/8] Update models.py --- applications/users/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/applications/users/models.py b/applications/users/models.py index b3392715..1cb66545 100644 --- a/applications/users/models.py +++ b/applications/users/models.py @@ -17,6 +17,7 @@ class User(IDMixin, TimeStampMixin, Base): :param email: Email ID of the user. :param password: Password of the user. :param admin: 1 if the user has admin access else 0. + :param auth_token: Auth_token of the user. """ __tablename__ = "user"