Revision 1ae97c83
b/docs/source/devguide.rst | ||
---|---|---|
12 | 12 |
|
13 | 13 |
* Shibboleth |
14 | 14 |
|
15 |
It provides also an administrative interface for managing user accounts.
|
|
15 |
It provides also a command line tool for managing user accounts.
|
|
16 | 16 |
|
17 | 17 |
It is build over django and extends its authentication mechanism. |
18 | 18 |
|
... | ... | |
102 | 102 |
* send feedback for grnet services via: ``/im/send_feedback`` |
103 | 103 |
* logout (and delete cookie) via: ``/im/logout`` |
104 | 104 |
|
105 |
User entries can also be modified/added via the administrative interface available at ``/im/admin``.
|
|
105 |
User entries can also be modified/added via the ``snf-manage activateuser`` command.
|
|
106 | 106 |
|
107 | 107 |
A superuser account can be created the first time you run the ``manage.py syncdb`` django command and then loading the extra user data from the ``admin_user`` fixture. At a later date, the ``manage.py createsuperuser`` command line utility can be used (as long as the extra user data for Astakos is added with a fixture or by hand). |
108 | 108 |
|
... | ... | |
126 | 126 |
The Astakos API |
127 | 127 |
--------------- |
128 | 128 |
|
129 |
All API requests require a token. An application that wishes to connect to Astakos, but does not have a token, should redirect the user to ``/login``. (see :ref:`authentication-label`) |
|
130 |
|
|
131 | 129 |
.. _authenticate-api-label: |
132 | 130 |
|
133 | 131 |
Authenticate |
134 | 132 |
^^^^^^^^^^^^ |
135 | 133 |
|
134 |
Authenticate API requests require a token. An application that wishes to connect to Astakos, but does not have a token, should redirect the user to ``/login``. (see :ref:`authentication-label`) |
|
135 |
|
|
136 | 136 |
==================== ========= ================== |
137 |
Uri Method Description
|
|
137 |
Uri Method Description |
|
138 | 138 |
==================== ========= ================== |
139 | 139 |
``/im/authenticate`` GET Authenticate user using token |
140 | 140 |
==================== ========= ================== |
... | ... | |
179 | 179 |
401 (Unauthorized) Missing token or inactive user |
180 | 180 |
500 (Internal Server Error) The request cannot be completed because of an internal error |
181 | 181 |
=========================== ===================== |
182 |
|
|
183 |
Get Services |
|
184 |
^^^^^^^^^^^^ |
|
185 |
|
|
186 |
Returns a json formatted list containing information about the supported cloud services. |
|
187 |
|
|
188 |
==================== ========= ================== |
|
189 |
Uri Method Description |
|
190 |
==================== ========= ================== |
|
191 |
``/im/get_services`` GET Get cloud services |
|
192 |
==================== ========= ================== |
|
193 |
|
|
194 |
Example reply: |
|
195 |
|
|
196 |
:: |
|
197 |
|
|
198 |
[{"url": "/", "icon": "home-icon.png", "name": "grnet cloud", "id": "cloud"}, |
|
199 |
{"url": "/okeanos.html", "name": "~okeanos", "id": "okeanos"}, |
|
200 |
{"url": "/ui/", "name": "pithos+", "id": "pithos"}] |
|
201 |
|
|
202 |
Get Menu |
|
203 |
^^^^^^^^ |
|
204 |
|
|
205 |
Returns a json formatted list containing the cloud bar links. |
|
206 |
|
|
207 |
==================== ========= ================== |
|
208 |
Uri Method Description |
|
209 |
==================== ========= ================== |
|
210 |
``/im/get_menu`` GET Get cloud bar menu |
|
211 |
==================== ========= ================== |
|
212 |
|
|
213 |
Example reply if request user is not authenticated: |
|
214 |
|
|
215 |
:: |
|
216 |
|
|
217 |
[{"url": "/im/login?next=", "name": "login..."}] |
|
218 |
|
|
219 |
Example reply if request user is authenticated: |
|
220 |
|
|
221 |
[{"url": "/im/profile", "name": "spapagian@grnet.gr"}, |
|
222 |
{"url": "/im/profile", "name": "view your profile..."}, |
|
223 |
{"url": "/im/password", "name": "change your password..."}, |
|
224 |
{"url": "/im/feedback", "name": "feedback..."}, |
|
225 |
{"url": "/im/logout", "name": "logout..."}] |
|
226 |
|
|
227 |
|
|
228 |
|
|
229 |
|
b/snf-astakos-app/astakos/im/api.py | ||
---|---|---|
33 | 33 |
|
34 | 34 |
from traceback import format_exc |
35 | 35 |
from time import time, mktime |
36 |
from urllib import quote |
|
37 |
from urlparse import urlparse |
|
38 |
|
|
36 | 39 |
from django.conf import settings |
37 | 40 |
from django.http import HttpResponse |
38 | 41 |
from django.utils import simplejson as json |
42 |
from django.core.urlresolvers import reverse |
|
39 | 43 |
|
40 | 44 |
from astakos.im.faults import BadRequest, Unauthorized, InternalServerError |
41 | 45 |
from astakos.im.models import AstakosUser |
46 |
from astakos.im.settings import CLOUD_SERVICES, INVITATIONS_ENABLED |
|
42 | 47 |
|
43 | 48 |
def render_fault(request, fault): |
44 | 49 |
if isinstance(fault, InternalServerError) and settings.DEBUG: |
... | ... | |
91 | 96 |
except BaseException, e: |
92 | 97 |
fault = InternalServerError('Unexpected error') |
93 | 98 |
return render_fault(request, fault) |
99 |
|
|
100 |
def get_services(request): |
|
101 |
if request.method != 'GET': |
|
102 |
raise BadRequest('Method not allowed.') |
|
103 |
data = json.dumps(CLOUD_SERVICES) |
|
104 |
return HttpResponse(content=data, mimetype="application/json") |
|
105 |
|
|
106 |
def get_menu(request): |
|
107 |
if request.method != 'GET': |
|
108 |
raise BadRequest('Method not allowed.') |
|
109 |
location = request.GET.get('location', '') |
|
110 |
index_url = reverse('astakos.im.views.index') |
|
111 |
if urlparse(location).query.rfind('next=') == -1: |
|
112 |
index_url = '%s?next=%s' % (index_url, quote(location)) |
|
113 |
l = [{ 'url': index_url, 'name': "login..."}] |
|
114 |
if request.user.is_authenticated(): |
|
115 |
l = [] |
|
116 |
l.append({ 'url': reverse('astakos.im.views.edit_profile'), 'name': request.user.email}) |
|
117 |
l.append({ 'url': reverse('astakos.im.views.edit_profile'), 'name': "view your profile..." }) |
|
118 |
if request.user.password: |
|
119 |
l.append({ 'url': reverse('password_change'), 'name': "change your password..." }) |
|
120 |
if INVITATIONS_ENABLED: |
|
121 |
l.append({ 'url': reverse('astakos.im.views.invite'), 'name': "invite some friends..." }) |
|
122 |
l.append({ 'url': reverse('astakos.im.views.send_feedback'), 'name': "feedback..." }) |
|
123 |
l.append({ 'url': reverse('astakos.im.views.logout'), 'name': "logout..."}) |
|
124 |
data = json.dumps(tuple(l)) |
|
125 |
return HttpResponse(content=data, mimetype="application/json") |
b/snf-astakos-app/astakos/im/settings.py | ||
---|---|---|
47 | 47 |
|
48 | 48 |
# Set service name |
49 | 49 |
SITENAME = getattr(settings, 'ASTAKOS_SITENAME', 'GRNET Cloud') |
50 |
|
|
51 |
# Set cloud services appear in the horizontal bar |
|
52 |
CLOUD_SERVICES = getattr(settings, 'ASTAKOS_CLOUD_SERVICES', ( |
|
53 |
{ 'url':'/', 'name':'grnet cloud', 'id':'cloud', 'icon':'home-icon.png' }, |
|
54 |
{ 'url':'/okeanos.html', 'name':'~okeanos', 'id':'okeanos' }, |
|
55 |
{ 'url':'/ui/', 'name':'pithos+', 'id':'pithos' })) |
b/snf-astakos-app/astakos/im/static/im/cloudbar/cloudbar.js | ||
---|---|---|
5 | 5 |
*/ |
6 | 6 |
|
7 | 7 |
var PROFILE_URL = "https://accounts.cloud.grnet.gr"; |
8 |
var SERVICES_LINKS = window.CLOUDBAR_SERVICES_LINKS || { |
|
9 |
'cloud': { url:'/', name:'grnet cloud', id:'cloud', icon:'home-icon.png' }, |
|
10 |
'okeanos': { url:'/okeanos.html', name:'~okeanos', id:'okeanos' }, |
|
11 |
'pithos': { url:'/ui/', name:'pithos+', id:'pithos' } |
|
12 |
}; |
|
13 |
|
|
14 |
var PROFILE_LINKS = window.CLOUDBAR_PROFILE_LINKS || { |
|
15 |
'login': { url: '/im/login?next=' + window.location.toString(), auth:false, name: "login...", visible:false }, |
|
16 |
'profile': { url: '/im/profile', auth:true, name: "view your profile..." }, |
|
17 |
'password': { url: '/im/password', auth:true, name: "change your password..." }, |
|
18 |
'invitations': { url: '/im/invite', auth:true, name: "invite some friends..." }, |
|
19 |
'feedback': { url: '/im/feedback', auth:true, name: "feedback..." }, |
|
20 |
'logout': { url: '/im/logout', auth:true, name: "logout..." } |
|
21 |
}; |
|
22 |
|
|
23 | 8 |
|
24 | 9 |
// cookie plugin https://raw.github.com/carhartl/jquery-cookie/master/jquery.cookie.js |
25 | 10 |
// * Copyright (c) 2010 Klaus Hartl, @carhartl |
... | ... | |
51 | 36 |
var services = $('<div class="services"></div>'); |
52 | 37 |
var profile = $('<div class="profile"></div>'); |
53 | 38 |
|
54 |
|
|
55 | 39 |
// create services links and set the active class to the current service |
56 |
$.each(SERVICES_LINKS, function(i, el){ |
|
57 |
var slink = $("<a>"); |
|
58 |
if (el.icon) { |
|
59 |
slink.append($('<img src="'+cssloc+el.icon+'"/>')); |
|
60 |
} else { |
|
61 |
slink.text(el.name); |
|
62 |
} |
|
63 |
slink.attr('href', el.url); |
|
64 |
slink.attr('title', el.name); |
|
65 |
services.append(slink); |
|
66 |
if (el.id == ACTIVE_MENU) { |
|
67 |
slink.addClass("active"); |
|
68 |
} |
|
69 |
}); |
|
70 |
|
|
71 |
var USERNAME, LOGGED_IN; |
|
72 |
var authcookie = cookie(COOKIE_NAME); |
|
73 |
var anonymous = {'user': 'Login...', 'logged_in': false}; |
|
74 |
|
|
75 |
if (authcookie && authcookie.indexOf("|") > -1) { |
|
76 |
USER_DATA.logged_in = true; |
|
77 |
USER_DATA.user = authcookie.split("|")[0]; |
|
78 |
} else { |
|
79 |
USER_DATA = anonymous; |
|
80 |
} |
|
81 |
|
|
82 |
USERNAME = USER_DATA.user; |
|
83 |
LOGGED_IN = USER_DATA.logged_in; |
|
84 |
|
|
85 |
// clear username |
|
86 |
USERNAME = USERNAME.replace(/\\'/g,''); |
|
87 |
USERNAME = USERNAME.replace(/\"/g,''); |
|
88 |
|
|
89 |
var user = $('<div class="user"></div>'); |
|
90 |
var username = $('<a href="#"></a>'); |
|
91 |
username.text(USERNAME); |
|
40 |
$.getJSON('/im/get_services/', function(data) { |
|
41 |
$.each(data, function(i, el){ |
|
42 |
var slink = $("<a>"); |
|
43 |
if (el.icon) { |
|
44 |
slink.append($('<img src="'+cssloc+el.icon+'"/>')); |
|
45 |
} else { |
|
46 |
slink.text(el.name); |
|
47 |
} |
|
48 |
slink.attr('href', el.url); |
|
49 |
slink.attr('title', el.name); |
|
50 |
services.append(slink); |
|
51 |
if (el.id == ACTIVE_MENU) { |
|
52 |
slink.addClass("active"); |
|
53 |
} |
|
54 |
}); |
|
55 |
}); |
|
92 | 56 |
|
93 | 57 |
// create profile links |
58 |
var user = $('<div class="user"></div>'); |
|
59 |
var username = $('<a href="#"></a>'); |
|
94 | 60 |
var usermenu = $("<ul>"); |
95 |
$.each(PROFILE_LINKS, function(i,el) { |
|
96 |
if (!LOGGED_IN && el.auth) { return } |
|
97 |
if (LOGGED_IN && !el.auth) { return } |
|
98 |
var li = $("<li />"); |
|
99 |
var link = $("<a />"); |
|
100 |
link.text(el.name); |
|
101 |
link.attr({href:el.url}); |
|
102 |
li.append(link); |
|
103 |
if (el.visible == false) { |
|
104 |
li.hide(); |
|
105 |
} |
|
106 |
usermenu.append(li); |
|
61 |
$.getJSON('/im/get_menu/?location='.concat(window.location.toString()), function(data) { |
|
62 |
$.each(data, function(i,el) { |
|
63 |
if (i == 0){ |
|
64 |
username.text(el.name); |
|
65 |
username.attr('href', el.url); |
|
66 |
}else{ |
|
67 |
var link = $("<a />"); |
|
68 |
link.text(el.name); |
|
69 |
link.attr({href:el.url}); |
|
70 |
var li = $("<li />"); |
|
71 |
li.append(link); |
|
72 |
usermenu.append(li); |
|
73 |
} |
|
74 |
}); |
|
107 | 75 |
}); |
108 |
|
|
76 |
|
|
109 | 77 |
//profile.filter(".user a").attr("href", |
110 | 78 |
//profile.find("li a").get(0).attr("href")) |
111 | 79 |
|
112 |
|
|
113 |
|
|
114 | 80 |
user.append(username); |
115 | 81 |
user.append(usermenu); |
116 | 82 |
profile.append(user); |
b/snf-astakos-app/astakos/im/urls.py | ||
---|---|---|
62 | 62 |
url(r'^local/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$', |
63 | 63 |
'password_reset_confirm'), |
64 | 64 |
url(r'^local/password/reset/complete/$', 'password_reset_complete'), |
65 |
url(r'^password/?$', 'password_change', {'post_change_redirect':'profile'}) |
|
65 |
url(r'^password/?$', 'password_change', {'post_change_redirect':'profile'}, name='password_change')
|
|
66 | 66 |
) |
67 | 67 |
|
68 | 68 |
if INVITATIONS_ENABLED: |
... | ... | |
82 | 82 |
) |
83 | 83 |
|
84 | 84 |
urlpatterns += patterns('astakos.im.api', |
85 |
url(r'^authenticate/?$', 'authenticate') |
|
85 |
url(r'^authenticate/?$', 'authenticate'), |
|
86 |
url(r'^get_services/?$', 'get_services'), |
|
87 |
url(r'^get_menu/?$', 'get_menu'), |
|
86 | 88 |
) |
Also available in: Unified diff