Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
itminedu
synnefo
Commits
903d075f
Commit
903d075f
authored
Feb 28, 2012
by
Sofia Papagiannaki
Browse files
Merge branch 'master', remote-tracking branch 'origin' into aquarium
parents
963fde65
d01e7b22
Changes
147
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
903d075f
...
...
@@ -2,3 +2,4 @@ docs/build
*.db
*.pyc
.DS_Store
snf-astakos-app/astakos/version.py
README
deleted
100644 → 0
View file @
963fde65
README
======
Astakos is an identity management service, built by GRNET using Django (https://www.djangoproject.com/).
Learn more about Astakos at: http://code.grnet.gr/projects/astakos
Consult LICENSE for licensing information.
Documentation
-------------
All docs are in the docs/source directory. The .rst files are perfectly readable in source form.
To build the documentation you need to have Sphinx (http://sphinx.pocoo.org/) installed.
On a typical debian-based Linux system run:
apt-get install python-django python-django-south python-setuptools python-sphinx python-httplib2
Then run:
python setup.py build_sphinx
The documentation will be built in the docs/build/html directory.
Also run:
python setup.py build_sphinx -b text
Then find the plain text version of the docs in docs/build/text.
Running the server
------------------
Make sure you have all required packages installed:
apt-get install python-django python-django-south python-setuptools python-sphinx python-httplib2
Then run:
python manage.py syncdb
python manage.py migrate im
python manage.py loaddata admin_user
python manage.py runserver
Go to:
http://127.0.0.1:8000/im/admin?user=admin&token=0000
This server is useful during development, but should not be used for deployment.
To deploy Astakos using Apache, take a look at the Administrator Guide in docs.
README.upgrade
deleted
100644 → 0
View file @
963fde65
UPGRADE
=======
\ No newline at end of file
astakos/im/admin/templates/admin.html
deleted
100644 → 0
View file @
963fde65
{% extends "admin_base.html" %}
{% block body %}
<ul
class=
"unstyled"
>
<li><strong>
{{ stats.users }}
</strong>
User{{ stats.users|pluralize }} (
<strong>
{{ stats.pending }}
</strong>
pending)
</li>
<li><strong>
{{ stats.invitations }}
</strong>
Invitation{{ stats.invitations|pluralize }} sent (
<strong>
{{ stats.invitations_consumed }}
</strong>
consumed)
</li>
</ul>
{% endblock body %}
astakos/im/admin/templates/admin_base.html
deleted
100644 → 0
View file @
963fde65
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
/>
<title>
{{ title|default:"Astakos Login" }}
</title>
<link
rel=
"stylesheet"
href=
"{{ IM_MEDIA_URL }}css/bootstrap.css"
>
<script
src=
"{{ IM_MEDIA_URL }}js/jquery.js"
></script>
<script
src=
"{{ IM_MEDIA_URL }}js/jquery.tablesorter.js"
></script>
<script
src=
"{{ IM_MEDIA_URL }}js/main.js"
></script>
{% block head %}{% endblock %}
</head>
<body>
<div
class=
"container"
>
<div
style=
"padding: 5px 0px 0px 0px"
>
<img
src=
"{{ IM_MEDIA_URL }}images/banner.png"
width=
"900"
height=
"200"
>
</div>
{% block title %}{% endblock %}
{% if messages %}
<ul
class=
"messages"
>
{% for message in messages %}
<li
{%
if
message.tags
%}
class=
"alert-message.{{ message.tags }}"
{%
endif
%}
>
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
{% block tabs %}
<ul
class=
"tabs"
>
<li
{%
ifequal
tab
"
admin
"
%}
class=
"active"
{%
endifequal
%}
>
<a
href=
"{% url astakos.im.admin.views.admin %}"
>
Home
</a>
</li>
<li
{%
ifequal
tab
"
users
"
%}
class=
"active"
{%
endifequal
%}
>
<a
href=
"{% url astakos.im.admin.views.users_list %}"
>
Users
</a>
</li>
<li
{%
ifequal
tab
"
pending
"
%}
class=
"active"
{%
endifequal
%}
>
<a
href=
"{% url astakos.im.admin.views.pending_users %}"
>
Pending Users
</a>
</li>
<li
{%
ifequal
tab
"
invitations
"
%}
class=
"active"
{%
endifequal
%}
>
<a
href=
"{% url astakos.im.admin.views.invitations_list %}"
>
Invitations
</a>
</li>
<li
{%
ifequal
tab
"
logout
"
%}
class=
"active"
{%
endifequal
%}
>
<a
href=
"{% url astakos.im.views.logout %}"
>
Logout
</a>
</li>
</ul>
{% endblock %}
{% block body %}{% endblock %}
</div>
</body>
</html>
astakos/im/admin/templates/invitations_list.html
deleted
100644 → 0
View file @
963fde65
{% extends "admin_base.html" %}
{% load formatters %}
{% block body %}
<div
class=
"row"
>
<div
class=
"offset10 span3"
>
<form
method=
"get"
>
<div
class=
"input"
>
<input
class=
"span3"
name=
"filter"
type=
"search"
placeholder=
"search"
value=
"{{ filter }}"
>
</div>
</form>
</div>
</div>
<table
class=
"zebra-striped id-sorted"
>
<thead>
<tr>
<th>
ID
</th>
<th>
Email
</th>
<th>
Real Name
</th>
<th>
Code
</th>
<th>
Inviter email
</th>
<th>
Inviter Real Name
</th>
<th>
Is consumed
</th>
<th>
Created
</th>
<th>
Consumed
</th>
</tr>
</thead>
<tbody>
{% for inv in invitations %}
<tr>
<td>
{{ inv.id }}
</td>
<td>
{{ inv.username }}
</td>
<td>
{{ inv.realname }}
</td>
<td>
{{ inv.code }}
</td>
<td>
{{ inv.inviter.email }}
</td>
<td>
{{ inv.inviter.realname }}
</td>
<td>
{{ inv.is_consumed }}
</td>
<td>
{{ inv.created }}
</td>
<td>
{{ inv.consumed }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if pages|length > 1 %}
<div
class=
"pagination"
>
<ul>
{% if prev %}
<li
class=
"prev"
><a
href=
"?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}"
>
←
Previous
</a></li>
{% else %}
<li
class=
"prev disabled"
><a
href=
"#"
>
←
Previous
</a></li>
{% endif %}
{% for p in pages %}
<li
{%
if
page =
=
p
%}
class=
"active"
{%
endif
%}
><a
href=
"?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}"
>
{{ p }}
</a></li>
{% endfor %}
{% if next %}
<li
class=
"next"
><a
href=
"?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}"
>
→
Next
</a></li>
{% else %}
<li
class=
"next disabled"
><a
href=
"#"
>
→
Next
</a></li>
{% endif %}
</ul>
</div>
{% endif %}
<a
class=
"btn success"
href=
"{% url astakos.im.admin.views.invitations_export %}"
>
Export
</a>
<br
/><br
/>
{% endblock body %}
astakos/im/admin/templates/pending_users.html
deleted
100644 → 0
View file @
963fde65
{% extends "admin_base.html" %}
{% load formatters %}
{% block body %}
<div
class=
"row"
>
<div
class=
"offset10 span3"
>
<form
method=
"get"
>
<div
class=
"input"
>
<input
class=
"span3"
name=
"filter"
type=
"search"
placeholder=
"search"
value=
"{{ filter }}"
>
</div>
</form>
</div>
</div>
<table
class=
"zebra-striped id-sorted"
>
<thead>
<tr>
<th>
ID
</th>
<th>
Email
</th>
<th>
Real Name
</th>
<th>
Affiliation
</th>
<th>
Email
</th>
<th>
Inviter
</th>
<th>
Action
</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>
{{ user.id }}
</td>
<td>
{{ user.email }}
</td>
<td>
{{ user.realname }}
</td>
<td>
{{ user.affiliation }}
</td>
<td>
{{ user.email }}
</td>
<td>
{{ user.inviter.realname }}
</td>
<td>
<form
action=
"{% url astakos.im.admin.views.users_activate user.id %}"
method=
"post"
>
{% csrf_token %}
<input
type=
"hidden"
name=
"page"
value=
"{{ page }}"
>
<button
type=
"submit"
class=
"btn primary"
>
Activate
</button>
</form>
</tr>
{% endfor %}
</tbody>
</table>
{% if pages|length > 1 %}
<div
class=
"pagination"
>
<ul>
{% if prev %}
<li
class=
"prev"
><a
href=
"?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}"
>
←
Previous
</a></li>
{% else %}
<li
class=
"prev disabled"
><a
href=
"#"
>
←
Previous
</a></li>
{% endif %}
{% for p in pages %}
<li
{%
if
page =
=
p
%}
class=
"active"
{%
endif
%}
><a
href=
"?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}"
>
{{ p }}
</a></li>
{% endfor %}
{% if next %}
<li
class=
"next"
><a
href=
"?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}"
>
→
Next
</a></li>
{% else %}
<li
class=
"next disabled"
><a
href=
"#"
>
→
Next
</a></li>
{% endif %}
</ul>
</div>
{% endif %}
<br
/><br
/>
{% endblock body %}
astakos/im/admin/templates/users_create.html
deleted
100644 → 0
View file @
963fde65
{% extends "admin_base.html" %}
{% block body %}
<form
action=
"{% url astakos.im.admin.views.users_create %}"
method=
"post"
>
{% csrf_token %}
{{ form.as_p }}
<div
class=
"actions"
>
<button
type=
"submit"
class=
"btn primary"
>
Create
</button>
<button
type=
"reset"
class=
"btn"
>
Reset
</button>
</div>
</form>
{% endblock body %}
astakos/im/admin/templates/users_info.html
deleted
100644 → 0
View file @
963fde65
{% extends "admin_base.html" %}
{% load formatters %}
{% block body %}
<form
action=
"{% url astakos.im.admin.views.users_modify user.id %}"
method=
"post"
>
{% csrf_token %}
{{ form.as_p }}
<div
class=
"actions"
>
<button
type=
"submit"
class=
"btn primary"
>
Save Changes
</button>
<button
type=
"reset"
class=
"btn"
>
Reset
</button>
<a
class=
"btn danger needs-confirm"
href=
"{% url astakos.im.admin.views.users_delete user.id %}"
>
Delete User
</a>
</div>
<div
class=
"alert-message block-message error"
>
<p><strong>
WARNING:
</strong>
Are you sure you want to delete this user?
</p>
<div
class=
"alert-actions"
>
<a
class=
"btn danger"
href=
"{% url astakos.im.admin.views.users_delete user.id %}"
>
Delete
</a>
<a
class=
"btn alert-close"
>
Cancel
</a>
</div>
</div>
</form>
{% endblock body %}
astakos/im/admin/templates/users_list.html
deleted
100644 → 0
View file @
963fde65
{% extends "admin_base.html" %}
{% load formatters %}
{% block body %}
<div
class=
"row"
>
<div
class=
"offset10 span3"
>
<form
method=
"get"
>
<div
class=
"input"
>
<input
class=
"span3"
name=
"filter"
type=
"search"
placeholder=
"search"
value=
"{{ filter }}"
>
</div>
</form>
</div>
</div>
<table
class=
"zebra-striped id-sorted"
>
<thead>
<tr>
<th>
ID
</th>
<th>
Email
</th>
<th>
Real Name
</th>
<th>
Admin
</th>
<th>
Affiliation
</th>
<th>
Is active?
</th>
<th>
Quota
</th>
<th>
Updated
</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td><a
href=
"{% url astakos.im.admin.views.users_info user.id %}"
>
{{ user.id }}
</a></td>
<td><a
href=
"{% url astakos.im.admin.views.users_info user.id %}"
>
{{ user.email }}
</a></td>
<td>
{{ user.realname }}
</td>
<td>
{{ user.is_superuser }}
</td>
<td>
{{ user.affiliation }}
</td>
<td>
{{ user.is_active }}
</td>
<td>
{{ user.quota|GiB }} GiB
</td>
<td>
{{ user.updated }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if pages|length > 1 %}
<div
class=
"pagination"
>
<ul>
{% if prev %}
<li
class=
"prev"
><a
href=
"?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}"
>
←
Previous
</a></li>
{% else %}
<li
class=
"prev disabled"
><a
href=
"#"
>
←
Previous
</a></li>
{% endif %}
{% for p in pages %}
<li
{%
if
page =
=
p
%}
class=
"active"
{%
endif
%}
><a
href=
"?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}"
>
{{ p }}
</a></li>
{% endfor %}
{% if next %}
<li
class=
"next"
><a
href=
"?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}"
>
→
Next
</a></li>
{% else %}
<li
class=
"next disabled"
><a
href=
"#"
>
→
Next
</a></li>
{% endif %}
</ul>
</div>
{% endif %}
<a
class=
"btn success"
href=
"{% url astakos.im.admin.views.users_create %}"
>
Create a user
</a>
<a
class=
"btn success"
href=
"{% url astakos.im.admin.views.users_export %}"
>
Export
</a>
<br
/><br
/>
{% endblock body %}
astakos/im/admin/views.py
deleted
100644 → 0
View file @
963fde65
# Copyright 2011 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
import
logging
import
socket
import
csv
from
functools
import
wraps
from
math
import
ceil
from
smtplib
import
SMTPException
from
django.conf
import
settings
from
django.core.mail
import
send_mail
from
django.http
import
HttpResponse
,
HttpResponseRedirect
from
django.shortcuts
import
redirect
from
django.template.loader
import
render_to_string
from
django.utils.http
import
urlencode
from
django.utils.translation
import
ugettext
as
_
from
django.core.urlresolvers
import
reverse
from
django.contrib
import
messages
from
django.db
import
transaction
from
astakos.im.models
import
AstakosUser
,
Invitation
from
astakos.im.util
import
get_context
,
get_current_site
from
astakos.im.forms
import
*
from
astakos.im.views
import
render_response
,
index
from
astakos.im.admin.forms
import
AdminProfileForm
from
astakos.im.admin.forms
import
AdminUserCreationForm
def
requires_admin
(
func
):
"""
Decorator checkes whether the request.user is a superuser and if not
redirects to login page.
"""
@
wraps
(
func
)
def
wrapper
(
request
,
*
args
):
if
not
settings
.
BYPASS_ADMIN_AUTH
:
if
request
.
user
.
is_anonymous
():
next
=
urlencode
({
'next'
:
request
.
build_absolute_uri
()})
login_uri
=
reverse
(
index
)
+
'?'
+
next
return
HttpResponseRedirect
(
login_uri
)
if
not
request
.
user
.
is_superuser
:
return
HttpResponse
(
'Forbidden'
,
status
=
403
)
return
func
(
request
,
*
args
)
return
wrapper
@
requires_admin
def
admin
(
request
,
template_name
=
'admin.html'
,
extra_context
=
{}):
"""
Renders the admin page
If the ``request.user`` is not a superuser redirects to login page.
**Arguments**
``template_name``
A custom template to use. This is optional; if not specified,
this will default to ``admin.html``.
``extra_context``
An dictionary of variables to add to the template context.
**Template:**
admin.html or ``template_name`` keyword argument.
**Template Context:**
The template context is extended by:
* tab: the name of the active tab
* stats: dictionary containing the number of all and prending users
"""
stats
=
{}
stats
[
'users'
]
=
AstakosUser
.
objects
.
count
()
stats
[
'pending'
]
=
AstakosUser
.
objects
.
filter
(
is_active
=
False
).
count
()
invitations
=
Invitation
.
objects
.
all
()
stats
[
'invitations'
]
=
invitations
.
count
()
stats
[
'invitations_consumed'
]
=
invitations
.
filter
(
is_consumed
=
True
).
count
()
kwargs
=
{
'tab'
:
'home'
,
'stats'
:
stats
}
context
=
get_context
(
request
,
extra_context
,
**
kwargs
)
return
render_response
(
template_name
,
context_instance
=
context
)
@
requires_admin
def
users_list
(
request
,
template_name
=
'users_list.html'
,
extra_context
=
{}):
"""
Displays the list of all users.
If the ``request.user`` is not a superuser redirects to login page.
**Arguments**
``template_name``
A custom template to use. This is optional; if not specified,
this will default to ``users_list.html``.
``extra_context``
An dictionary of variables to add to the template context.
**Template:**
users_list.html or ``template_name`` keyword argument.
**Template Context:**
The template context is extended by:
* users: list of users fitting in current page
* filter: search key
* pages: the number of pages
* prev: the previous page
* next: the current page
**Settings:**
* ADMIN_PAGE_LIMIT: Show these many users per page in admin interface
"""
users
=
AstakosUser
.
objects
.
order_by
(
'id'
)
filter
=
request
.
GET
.
get
(
'filter'
,
''
)
if
filter
:
if
filter
.
startswith
(
'-'
):
users
=
users
.
exclude
(
username__icontains
=
filter
[
1
:])
else
:
users
=
users
.
filter
(
username__icontains
=
filter
)
try
:
page
=
int
(
request
.
GET
.
get
(
'page'
,
1
))
except
ValueError
:
page
=
1
offset
=
max
(
0
,
page
-
1
)
*
settings
.
ADMIN_PAGE_LIMIT
limit
=
offset
+
settings
.
ADMIN_PAGE_LIMIT
npages
=
int
(
ceil
(
1.0
*
users
.
count
()
/
settings
.
ADMIN_PAGE_LIMIT
))
prev
=
page
-
1
if
page
>
1
else
None
next
=
page
+
1
if
page
<
npages
else
None
kwargs
=
{
'users'
:
users
[
offset
:
limit
],
'filter'
:
filter
,
'pages'
:
range
(
1
,
npages
+
1
),
'prev'
:
prev
,
'next'
:
next
}
context
=
get_context
(
request
,
extra_context
,
**
kwargs
)
return
render_response
(
template_name
,
context_instance
=
context
)
@
requires_admin
def
users_info
(
request
,
user_id
,
template_name
=
'users_info.html'
,
extra_context
=
{}):
"""
Displays the specific user profile.
If the ``request.user`` is not a superuser redirects to login page.
**Arguments**
``template_name``
A custom template to use. This is optional; if not specified,
this will default to ``users_info.html``.
``extra_context``
An dictionary of variables to add to the template context.
**Template:**
users_info.html or ``template_name`` keyword argument.
**Template Context:**
The template context is extended by:
* user: the user instance identified by ``user_id`` keyword argument
"""
if
not
extra_context
:
extra_context
=
{}
user
=
AstakosUser
.
objects
.
get
(
id
=
user_id
)
return
render_response
(
template_name
,
form
=
AdminProfileForm
(
instance
=
user
),
user
=
user
,
context_instance
=
get_context
(
request
,
extra_context
))
@
requires_admin
def
users_modify
(
request
,
user_id
,
template_name
=
'users_info.html'
,
extra_context
=
{}):
"""
Update the specific user information. Upon success redirects to ``user_info`` view.
If the ``request.user`` is not a superuser redirects to login page.
"""
user
=
AstakosUser
.
objects
.
get
(
id
=
user_id
)
form
=
AdminProfileForm
(
request
.
POST
,
instance
=
user
)
if
form
.
is_valid
():
form
.
save
()
return
users_info
(
request
,
user
.
id
,
template_name
,
extra_context
)
return
render_response
(
template_name
,
form
=
form
,
context_instance
=
get_context
(
request
,
extra_context
))
@
requires_admin
def
users_delete
(
request
,
user_id
):
"""
Deletes the specified user
If the ``request.user`` is not a superuser redirects to login page.
"""
user
=
AstakosUser
.
objects
.
get
(
id
=
user_id
)
user
.
delete
()
return
redirect
(
users_list
)
@
requires_admin
def
pending_users
(
request
,
template_name
=
'pending_users.html'
,
extra_context
=
{}):
"""
Displays the list of the pending users.