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
1 change: 1 addition & 0 deletions applications/home/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
]
50 changes: 47 additions & 3 deletions applications/home/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json

from applications.users.forms import RegisterForm
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
Expand All @@ -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):
"""
Expand Down Expand Up @@ -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!"
Expand Down Expand Up @@ -218,7 +224,6 @@ def reset_password_page(request):
def login(request):
"""
Handles login (POST) request.

:param request: HTTP Request
"""
if 'POST' == request.method:
Expand Down Expand Up @@ -290,4 +295,43 @@ def images(request, query):
:param request: HTTP GET Request

"""
return redirect('/static' + request.path)
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.


28 changes: 23 additions & 5 deletions applications/users/controllers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import bcrypt
import base64

from django.conf import settings
from django.core.mail import send_mail
Expand Down Expand Up @@ -26,11 +27,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
Expand All @@ -40,11 +45,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)


Expand Down Expand Up @@ -129,11 +135,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.
Expand All @@ -142,11 +149,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_%[email protected]" % 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):
Expand Down Expand Up @@ -312,3 +320,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

20 changes: 18 additions & 2 deletions applications/users/dal.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,27 @@
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.

:param db_session: Database session.
: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

Expand Down Expand Up @@ -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()
2 changes: 2 additions & 0 deletions applications/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ 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"

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")
Expand Down
28 changes: 28 additions & 0 deletions docs/Programmers_Guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,34 @@ The GraphSpace REST API is served over HTTP. In case you are

<iframe src="http://35.163.136.54/static/api.html" style="height: 100vh;width: 100%;"></iframe>

## 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

Expand Down
10 changes: 10 additions & 0 deletions static/js/account_page.js
Original file line number Diff line number Diff line change
@@ -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();

},
}
8 changes: 4 additions & 4 deletions templates/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
<title>GraphSpace</title>

<!-- Bootstrap core CSS -->
<link href="{% static 'graphs/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'graphs/css/base.css' %}" rel="stylesheet">
<link href="{% static 'components/bootstrap/dist/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'css/graphspace.css' %}" rel="stylesheet">

<!-- Custom styles for this base template -->
<link href="{% static 'graphs/css/base.css' %}" rel="stylesheet">
<link href="{% static 'css/graphspace.css' %}" rel="stylesheet">
</head>

<body>
Expand All @@ -30,7 +30,7 @@ <h1 style='text-align: center;'>Sorry, but the page you are looking for is not f
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="{% static 'graphs/js/bootstrap.min.js' %}"></script>
<script src="{% static 'components/bootstrap/dist/css/bootstrap.min.css' %}"></script>

</body>
</html>
Expand Down
8 changes: 4 additions & 4 deletions templates/500.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
<title>GraphSpace</title>

<!-- Bootstrap core CSS -->
<link href="{% static 'graphs/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'graphs/css/base.css' %}" rel="stylesheet">
<link href="{% static 'components/bootstrap/dist/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'css/graphspace.css' %}" rel="stylesheet">

<!-- Custom styles for this base template -->
<link href="{% static 'graphs/css/base.css' %}" rel="stylesheet">
<link href="{% static 'css/graphspace.css' %}" rel="stylesheet">
</head>

<body>
Expand All @@ -36,7 +36,7 @@ <h1 style='text-align: center;'>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="{% static 'graphs/js/bootstrap.min.js' %}"></script>
<script src="{% static 'components/bootstrap/dist/css/bootstrap.min.css' %}"></script>

</body>
</html>
Expand Down
13 changes: 13 additions & 0 deletions templates/account/auth_token.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="container-fluid margin-top-4" style="height: auto">
<div class="panel panel-default" style="max-width: 700px; margin: 0 auto;">
<div class="panel-heading">Authentication</div>
<div class="panel-body">
<form class="form-horizontal" role="form">
<div class="form-group">
<p>Type: Basic Auth</p>
<p>Value: {{ auth_token }}</p>
</div>
</form>
</div>
</div>
</div>
16 changes: 16 additions & 0 deletions templates/account/email.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div class="container-fluid margin-top-4" style="height: auto">
<div class="panel panel-default" style="max-width: 700px; margin: 0 auto;">
<div class="panel-heading">Email Address</div>
<div class="panel-body">
<form class="form-horizontal" role="form">
<div class="form-group">
<p>
{% if uid != None %}
{{ uid }}
{% endif %}
</p>
</div>
</form>
</div>
</div>
</div>
Loading