Commit 37102897 authored by Kostas Papadimitriou's avatar Kostas Papadimitriou
Browse files

Merge branch 'feature-api-access-view' into develop

parents 78ab8e07 da6bc3f1
......@@ -35,5 +35,5 @@ from django.conf.urls.defaults import patterns, url
urlpatterns = patterns(
'astakos.api.tokens',
url(r'^v2.0/tokens/?$', 'authenticate'),
url(r'^v2.0/tokens/?$', 'authenticate', name='tokens_authenticate'),
)
......@@ -436,18 +436,16 @@ class ProfileForm(forms.ModelForm):
"""
email = forms.EmailField(label='E-mail address', help_text='E-mail address')
renew = forms.BooleanField(label='Renew token', required=False)
uuid = forms.CharField(label='User id', required=False)
class Meta:
model = AstakosUser
fields = ('email', 'first_name', 'last_name', 'auth_token',
'auth_token_expires', 'uuid')
fields = ('email', 'first_name', 'last_name')
def __init__(self, *args, **kwargs):
self.session_key = kwargs.pop('session_key', None)
super(ProfileForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
ro_fields = ('email', 'auth_token', 'auth_token_expires', 'uuid')
ro_fields = ('email',)
if instance and instance.id:
for field in ro_fields:
self.fields[field].widget.attrs['readonly'] = True
......@@ -455,15 +453,6 @@ class ProfileForm(forms.ModelForm):
def clean_email(self):
return self.instance.email
def clean_auth_token(self):
return self.instance.auth_token
def clean_auth_token_expires(self):
return self.instance.auth_token_expires
def clean_uuid(self):
return self.instance.uuid
def save(self, commit=True):
user = super(ProfileForm, self).save(commit=False)
user.is_verified = True
......@@ -1024,14 +1013,11 @@ class ExtendedProfileForm(ProfileForm):
'new_email_address',
'first_name',
'last_name',
'auth_token',
'auth_token_expires',
'old_password',
'new_password1',
'new_password2',
'change_email',
'change_password',
'uuid'
]
super(ExtendedProfileForm, self).__init__(*args, **kwargs)
......
......@@ -180,3 +180,7 @@ RESOURCES_META = getattr(settings, 'ASTAKOS_RESOURCES_META', {})
# Do not require email verification for new users
SKIP_EMAIL_VERIFICATION = getattr(settings,
'ASTAKOS_SKIP_EMAIL_VERIFICATION', False)
# Kamaki download url. Displayed in api access view
API_CLIENT_URL = getattr(settings, 'ASTAKOS_API_CLIENT_URL',
'https://pypi.python.org/pypi/kamaki')
......@@ -113,3 +113,76 @@ span.action-desc { display: block; color: #fff;}
/* heading extra */
h2 .header-actions { float: right; font-size: 0.8em;}
.api-access-view div.detail .title {
float: left;
font-size: 0.8em;
}
.api-access-view div.detail input {
border: none;
text-decoration: none;
width: 80%;
font-family: monospace;
position: absolute;
left: 20%;
cursor: pointer;
}
.api-access-view div.detail {
display: block;
position: relative;
margin: 2em 0;
font-size: 1.3em;
padding-bottom: 0.2em;
}
.api-access-view div.detail.small {
padding-bottom: 0.9em;
}
.api-access-view div.detail .expires {
font-size: 9px;
font-family: 'Open Sans', sans-serif;
position: absolute;
left: 20%;
top: 25px;
color:#b3b3b3;
}
.api-access-view p.sub {
font-size: 0.7em;
color:#b3b3b3;
padding-top:6px;
}
.api-access-view .api-clients h3 {
font-size: 1.2em;
}
.subsection {
margin-bottom: 4em;
}
.token-view .actions {
position: absolute;
right:0;
font-size:13px;
max-width: 230px;
overflow: hidden
}
.renew-token .confirm {
color:#3582AC;
margin:0 15px;
}
.renew-token .close {
color:#F24E53;
}
.renew-token .sub,
.renew-token .confirm,
.renew-token .close {
visibility: hidden;
}
\ No newline at end of file
......@@ -21,3 +21,6 @@ dl.alt-style { width:auto; }
#token-confirm { position:relative; top:8px; left:auto; }
form.submit-inline .form-row.submit { position:static; margin-top:20px; }
.token-view .actions { left:0; position: relative; top:50px;}
.api-access-view div.detail .expires { }
\ No newline at end of file
......@@ -87,6 +87,11 @@ if (navigator.userAgent.match(/iPhone/i)) {
$(document).ready(function() {
/* api access */
$(".token-view .detail").click(function() {
$(this).find("input").select();
});
setContainerMinHeight('.container .wrapper');
//tableFixedCols('my-projects', 25);
......@@ -403,9 +408,27 @@ $('#members-table tr .check input').click(function(e){
/* end of project members page js */
$('.renew-token a.confirm').click(function(e){
e.preventDefault();
e.stopPropagation();
renewToken();
});
$('.renew-token a.do').click(function(e){
e.preventDefault();
e.stopPropagation();
var els = [$(".renew-token .sub"),$('.renew-token .confirm'), $('.renew-token .close')];
_.each(els, function (el) { el.css({'visibility':'visible'});})
})
$('.renew-token a.close').click(function(e){
e.preventDefault();
e.stopPropagation();
var els = [$(".renew-token .sub"),$('.renew-token .confirm'), $('.renew-token .close')];
_.each(els, function (el) { el.css({'visibility':'hidden'});})
})
});
$(window).resize(function() {
......
{% extends "im/account_base.html" %}
{% extends "im/api_access_base.html" %}
{% load filters %}
{% block page.body %}
<h2>API ACCESS</h2>
<p>Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, quia dolor sit amet, consectetur, adipisci[ng] velit, sed quia non numquam [do] eius modi tempora inci[di]dunt, ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla pariatur?</p>
{% endblock %}
{% extends "im/account_base.html" %}
{% load filters %}
{% block headjs %}
{{ block.super }}
<script>
var CHANGE_TOKEN_URL = '{% url update_token %}';
</script>
{% endblock %}
{% block page.body %}
<form>{% csrf_token %}</form>
<div class="api-access-view">
<div class="subsection">
{% block page.body.title %}
<h2>API ACCESS</h2>
{% endblock %}
{% block page.body.description %}
<div class="two-cols dotted clearfix">
<div class="rt">
<p>
If
you want to learn more about the specification of the REST API itself,
please take a look at the <a href="https://www.synnefo.org/docs"
alt="Synnefo documentation">Synnefo documentation</a>.
</p>
</div>
<div class="lt">
<p>{{ BRANDING_SERVICE_NAME }} provides a complete REST API that allows you to access and
control your virtual resources programmatically. This means you can execute
all the actions you do from the {{ BRANDING_SERVICE_NAME }} Web UI by using a command
line client or importing the corresponding library inside your own code.</p>
</div>
</div>
{% endblock %}
</div>
<div class="subsection dotted">
{% block page.body.token %}
<h2>API details</h2>
<p>
To use {{ BRANDING_SERVICE_NAME }} via its REST API the only things you will need is your
Authentication Token and the Identity Service's public URL, which you can
find right below.<br /><br />
</p>
<div class="token-view">
<div class="detail small clearfix">
<span class="title">Authentication url</span>
<input type="text" value="{{ token_url }}" disabled />
</div>
<div class="detail clearfix">
<div class="facts">
<span class="title">API Token</span>
<input type="text" value="{{ request.user.auth_token }}" disabled />
<span class="expires">
<span class="date">
expires in {{ request.user.auth_token_expires|timeuntil }}
({{ request.user.auth_token_expires|date }})
</span>
</span>
</div>
<div class="actions">
<div class="renew-token">
<a href="#" class="do">renew token</a>
<a href="#" class="confirm">confirm</a>
<a href="#" class="close">x</a>
<p class="sub">Make sure to set the new token in any clientyou may be using each
time you renew your token.</p>
</div>
</div>
<span class="extra-img" id="token-span">&nbsp;</span>
</div>
</div>
{% endblock %}
</div>
<div class="two-cols dotted clearfix">
<div class="rt">
{% block page.body.api_advanced %}
<h2>API Advanced Usage</h2>
<p>
Apart from using the kamaki command line client, you can also import the
kamaki library inside your code and use it directly. More details on how
to do that on the corresponding kamaki
<a href="{{ client_url }}">kamaki </a>page.</p>
<p>You can also implement the REST API calls by yourself, without
using the official kamaki library if you feel confident with your
programming skills. To do so, you first need to get a good grasp of the
API itself; for more information take a look at the corresponding page
inside the
<a href="https://synnefo.org/docs/">Synnefo documentation</a>.
</p>
{% endblock %}
</div>
<div class="lt">
{% block page.body.clients %}
<h2>Kamaki</h2>
<p><a href="{{ client_url }}" alt="kamaki">Kamaki</a> is the official
{{ BRANDING_SERVICE_NAME }} command line client. You can use it to control your virtual
resources from the command line or use it inside your scripts.</p>
<p>Kamaki allows you to execute all the operations you do from the Web UI. You can use kamaki to<br><br>
- register images,<br>- spawn clusters of customized VMs,<br>- connect them to
Private Virtual Networks,<br>- have them executing computations dynamically and
many other neat things.</p>
<p> Kamaki is available for most Linux distributions,
Windows and Mac OS X. To use it you will need to set it up using your
Authentication Token and the Identity Service's public URL, found above. To
learn more about kamaki and how to install, configure and use, take a look
at its <a href="http://www.synnefo.org/docs/kamaki/latest/index.html">corresponding page</a>
</p>
<p class="download">You can download kamaki
from the <a href="{{ client_url }}">project homepage</a></p>
</div>
{% endblock %}
</div>
</div>
{% endblock %}
......@@ -47,7 +47,7 @@ urlpatterns = patterns(
url(r'^landing/?$', 'landing', {}, name='landing'),
url(r'^profile/update_token?$', 'update_token', {}, name='update_token'),
url(r'^profile/?$','edit_profile', {}, name='edit_profile'),
url(r'^api_access/?$', 'api_access', {}, name='api_access'),
url(r'^api_access/?$','api_access', {}, name='api_access'),
url(r'^feedback/?$', 'feedback', {}, name='feedback'),
url(r'^signup/?$', 'signup', {'on_success': 'index', 'extra_context': {'login_form': LoginForm()}}, name='signup'),
url(r'^logout/?$', 'logout', {'template': 'im/login.html', 'extra_context': {'login_form': LoginForm()}}, name='logout'),
......
......@@ -51,6 +51,8 @@ from django.core.exceptions import PermissionDenied
from django.views.decorators.http import require_http_methods
from django.utils import simplejson as json
from synnefo.lib import join_urls
import astakos.im.messages as astakos_messages
from astakos.im import activation_backends
......@@ -126,7 +128,7 @@ def update_token(request):
user.renew_token()
user.save()
messages.success(request, astakos_messages.TOKEN_UPDATED)
return HttpResponseRedirect(reverse('edit_profile'))
return HttpResponseRedirect(reverse('api_access'))
@require_http_methods(["GET", "POST"])
......@@ -202,6 +204,31 @@ def invite(request, template_name='im/invitations.html', extra_context=None):
context_instance=context)
@require_http_methods(["GET", "POST"])
@required_auth_methods_assigned()
@login_required
@cookie_fix
@signed_terms_required
def api_access(request, template_name='im/api_access.html',
extra_context=None):
"""
API access view.
"""
context = {}
token_url = join_urls(settings.BASE_URL, settings.BASE_PATH,
reverse('tokens_authenticate'))
context['services'] = Component.catalog()
context['token_url'] = token_url
context['client_url'] = settings.API_CLIENT_URL
if extra_context:
context.update(extra_context)
context_instance = get_context(request, context)
return render_response(template_name,
context_instance=context_instance)
@require_http_methods(["GET", "POST"])
@required_auth_methods_assigned(allow_access=True)
@login_required
......@@ -811,11 +838,6 @@ def landing(request):
context_instance=get_context(request), **context)
def api_access(request):
return render_response(
'im/api_access.html',
context_instance=get_context(request))
@cookie_fix
def get_menu(request, with_extra_links=False, with_signout=True):
user = request.user
......@@ -843,6 +865,9 @@ def get_menu(request, with_extra_links=False, with_signout=True):
append(item(url=request.build_absolute_uri(reverse('invite')),
name="Invitations"))
append(item(url=request.build_absolute_uri(reverse('api_access')),
name="API access"))
append(item(url=request.build_absolute_uri(reverse('resource_usage')),
name="Usage"))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment