import packages
import repository
import settings
+import sessions
import sources
import updates
import uploads
self.mirrors = mirrors.Mirrors(self)
self.packages = packages.Packages(self)
self.repos = repository.Repositories(self)
+ self.sessions = sessions.Sessions(self)
self.sources = sources.Sources(self)
self.updates = updates.Updates(self)
self.uploads = uploads.Uploads(self)
managers.append(DeleteManager)
+
+class SessionsManager(Manager):
+ """
+ Cleans up sessions that are not valid anymore.
+ Keeps the database smaller.
+ """
+
+ @property
+ def timeout(self):
+ return 3600
+
+ def do(self):
+ self.pakfire.sessions.cleanup()
+
+
+managers.append(SessionsManager)
return session
+ def get_all(self):
+ query = "SELECT session_id FROM sessions WHERE valid_until >= NOW() \
+ ORDER BY valid_until DESC"
+
+ sessions = []
+ for s in self.db.query(query):
+ s = Session(self.pakfire, s.session_id)
+ sessions.append(s)
+
+ return sessions
+
+ def cleanup(self):
+ # Delete all sessions that are not valid any more.
+ self.db.execute("DELETE FROM sessions WHERE valid_until < NOW()")
+
class Session(base.Object):
def __init__(self, pakfire, session_id):
self._user = None
self._impersonated_user = None
- # Update the valid time of the session.
- #self.update()
-
@staticmethod
def has_session(pakfire, session_id):
if self.db.get("SELECT session_id FROM sessions WHERE session_id = %s \
return False
- def refresh(self):
- self.db.execute("UPDATE sessions SET valid_until = DATE_ADD(NOW(), INTERVAL 3 DAY) \
- WHERE session_id = %s", self.id)
+ def refresh(self, address=None):
+ self.db.execute("UPDATE sessions \
+ SET valid_until = DATE_ADD(NOW(), INTERVAL 3 DAY), from_address = %s \
+ WHERE session_id = %s", address, self.id)
def destroy(self):
self.db.execute("DELETE FROM sessions WHERE session_id = %s", self.id)
- @staticmethod
- def cleanup(pakfire):
- # Remove all sessions that are no more valid.
- pakfire.db.execute("DELETE FROM sessions WHERE valid_until < NOW()")
-
@property
def user(self):
if self._user is None:
self._user = users.User(self.pakfire, self.data.user_id)
+ self._user.session = self
return self._user
+ @property
+ def creation_time(self):
+ return self.data.creation_time
+
+ @property
+ def valid_until(self):
+ return self.data.valid_until
+
+ @property
+ def from_address(self):
+ return self.data.from_address
+
@property
def impersonated_user(self):
if not self.data.impersonated_user_id:
if self._impersonated_user is None:
self._impersonated_user = \
users.User(self.pakfire, self.data.impersonated_user_id)
+ self._impersonated_user.session = self
return self._impersonated_user
base.Object.__init__(self, pakfire)
self.id = id
+ # A valid session of the user.
+ self.session = None
+
# Cache.
self._data = None
self._emails = None
self._perms = None
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__, self.realname)
+
+ def __hash__(self):
+ return hash(self.id)
+
def __cmp__(self, other):
if other is None:
return 1
{% if current_user %}
<li>
<a href="/users">
- <i class="icon-user"></i>
+ <i class="icon-group"></i>
{{ _("Users") }}
</a>
</li>
<li class="nav-header">
{{ _("Administration") }}
</li>
+ <li>
+ <a href="/sessions">
+ <i class="icon-user"></i>
+ {{ _("Sessions") }}
+ </a>
+ </li>
<li>
<a href="/uploads">
<i class="icon-upload"></i>
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Sessions") }}{% end block %}
+
+{% block body %}
+ <ul class="breadcrumb">
+ <li>
+ <a href="/">{{ _("Home") }}</a>
+ <span class="divider">/</span>
+ </li>
+ <li class="active">
+ <a href="/sessions">{{ _("Sessions") }}</a>
+ </li>
+ </ul>
+
+ <div class="page-header">
+ <h2>{{ _("Sessions") }}</h2>
+ </div>
+
+ <table class="table table-striped table-hover">
+ <tbody>
+ {% for user, user_sessions in sessions %}
+ <tr>
+ <td>
+ <div class="ac">
+ <img class="img-polaroid" src="{{ user.gravatar_icon(96) }}" alt="{{ user.realname }}">
+ <br><br>
+ <a href="/user/{{ user.name }}">{{ user.realname }}</a>
+ </div>
+ </td>
+ <td>
+ <table class="table table-striped table-hover">
+ <thead>
+ <tr>
+ <th>{{ _("Started") }}</th>
+ <th>{{ _("Valid until") }}</th>
+ <th>{{ _("Last seen at") }}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for s in user_sessions %}
+ <tr>
+ <td>
+ {{ format_date(s.creation_time) }}
+ </td>
+ <td>
+ {{ format_date(s.valid_until) }}
+ </td>
+ <td>
+ {{ s.from_address or _("N/A") }}
+ </td>
+ </tr>
+ {% end %}
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ {% end %}
+ </tbody>
+ </table>
+{% end block %}
# Log
(r"/log", LogHandler),
+ # Sessions
+ (r"/sessions", SessionsHandler),
+
] + static_handlers + [
# Everything else is catched by the 404 handler.
self.render("log.html", log=self.pakfire.log)
+class SessionsHandler(BaseHandler):
+ def prepare(self):
+ # This is only accessible for administrators.
+ if not self.current_user.is_admin():
+ raise tornado.web.HTTPError(403)
+
+ @tornado.web.authenticated
+ def get(self):
+ sessions = self.pakfire.sessions.get_all()
+
+ # Sort the sessions by user.
+ users = {}
+
+ for s in sessions:
+ try:
+ users[s.user].append(s)
+ except KeyError:
+ users[s.user] = [s]
+
+ sessions = sorted(users.items())
+
+ self.render("sessions/index.html", sessions=sessions)
+
+
class RepositoryDetailHandler(BaseHandler):
def get(self, distro, repo):
distro = self.pakfire.distros.get_by_name(distro)
session = backend.sessions.Session.create(self.pakfire, user)
# Set a cookie and update the current user.
- self.set_cookie("session_id", session.id)
+ self.set_cookie("session_id", session.id, expires=session.valid_until)
self._current_user = user
# If there is "next" given, we redirect the user accordingly.
session = backend.sessions.Session.create(self.pakfire, user)
# Set a cookie and update the current user.
- self.set_cookie("session_id", session.id)
+ self.set_cookie("session_id", session.id, expires=session.valid_until)
self._current_user = user
self.render("register-activation-success.html", user=user)
import backend
import backend.misc
-import backend.sessions
class BaseHandler(tornado.web.RequestHandler):
@property
if not session_id:
return
- try:
- self.session = backend.sessions.Session(self.pakfire, session_id)
- except:
+ # Get the session from the database.
+ session = self.pakfire.sessions.get(session_id)
+
+ # Return nothing, if no session was found.
+ if not session:
return
# Update the session lifetime.
- # XXX refresh cookie, too
- self.session.refresh()
+ session.refresh(self.request.remote_ip)
+ self.set_cookie("session_id", session.id, expires=session.valid_until)
# If the session impersonated a user, we return that one.
- if self.session.impersonated_user:
- return self.session.impersonated_user
+ if session.impersonated_user:
+ return session.impersonated_user
# By default, we return the user of this session.
- return self.session.user
+ return session.user
def get_user_locale(self):
DEFAULT_LOCALE = tornado.locale.get("en_US")
@property
def render_args(self):
+ session = None
+ if self.current_user:
+ session = self.current_user.session
+
ret = {
"bugtracker" : self.pakfire.bugzilla,
"hostname" : self.request.host,
"format_filemode" : backend.misc.format_filemode,
"lang" : self.locale.code[:2],
"pakfire_version" : pakfire.__version__,
+ "session" : session,
"year" : time.strftime("%Y"),
}
- # Add session.
- ret["session"] = getattr(self, "session", None)
-
return ret
def render(self, *args, **kwargs):
action = self.get_argument("action", "start")
if action == "stop":
- self.session.stop_impersonation()
+ if self.current_user.session:
+ self.current_user.session.stop_impersonation()
self.redirect("/")
return
if not user:
raise tornado.web.HTTPError(404, "User does not exist: %s" % username)
- self.session.start_impersonation(user)
+ if self.current_user.session:
+ self.current_user.session.start_impersonation(user)
# Redirect to start page.
self.redirect("/")