10693.3.1
by Jonathan Lange
Split the events classes into their own module. |
1 |
# Copyright 2010 Canonical Ltd. This software is licensed under the
|
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
|
3 |
||
4 |
"""Events generated by the SSH server."""
|
|
5 |
||
6 |
__metaclass__ = type |
|
7 |
__all__ = [ |
|
8 |
'AuthenticationFailed', |
|
10693.5.10
by Jonathan Lange
Move the BazaarSSH events back to codehosting. |
9 |
'AvatarEvent', |
10693.3.1
by Jonathan Lange
Split the events classes into their own module. |
10 |
'ILoggingEvent', |
11 |
'LoggingEvent', |
|
12 |
'ServerStarting', |
|
13 |
'ServerStopped', |
|
14 |
'SFTPClosed', |
|
15 |
'SFTPStarted', |
|
16 |
'UserConnected', |
|
17 |
'UserDisconnected', |
|
18 |
'UserLoggedIn', |
|
19 |
'UserLoggedOut', |
|
20 |
]
|
|
21 |
||
22 |
import logging |
|
23 |
||
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
24 |
from zope.interface import ( |
25 |
Attribute, |
|
26 |
implements, |
|
27 |
Interface, |
|
28 |
)
|
|
10693.3.1
by Jonathan Lange
Split the events classes into their own module. |
29 |
|
30 |
||
31 |
class ILoggingEvent(Interface): |
|
32 |
"""An event is a logging event if it has a message and a severity level.
|
|
33 |
||
10693.5.11
by Jonathan Lange
Clean up some references to codehosting. |
34 |
Events that provide this interface will be logged in the SSH server access
|
10693.3.1
by Jonathan Lange
Split the events classes into their own module. |
35 |
log.
|
36 |
"""
|
|
37 |
||
38 |
level = Attribute("The level to log the event at.") |
|
39 |
message = Attribute("The message to log.") |
|
40 |
||
41 |
||
42 |
class LoggingEvent: |
|
43 |
"""An event that can be logged to a Python logger.
|
|
44 |
||
45 |
:ivar level: The level to log itself as. This should be defined as a
|
|
46 |
class variable in subclasses.
|
|
47 |
:ivar template: The format string of the message to log. This should be
|
|
48 |
defined as a class variable in subclasses.
|
|
49 |
"""
|
|
50 |
||
51 |
implements(ILoggingEvent) |
|
52 |
||
53 |
def __init__(self, level=None, template=None, **data): |
|
54 |
"""Construct a logging event.
|
|
55 |
||
56 |
:param level: The level to log the event as. If specified, overrides
|
|
57 |
the 'level' class variable.
|
|
58 |
:param template: The format string of the message to log. If
|
|
59 |
specified, overrides the 'template' class variable.
|
|
60 |
:param **data: Information to be logged. Entries will be substituted
|
|
61 |
into the template and stored as attributes.
|
|
62 |
"""
|
|
63 |
if level is not None: |
|
64 |
self._level = level |
|
65 |
if template is not None: |
|
66 |
self.template = template |
|
67 |
self._data = data |
|
68 |
||
69 |
@property
|
|
70 |
def level(self): |
|
71 |
"""See `ILoggingEvent`."""
|
|
72 |
return self._level |
|
73 |
||
74 |
@property
|
|
75 |
def message(self): |
|
76 |
"""See `ILoggingEvent`."""
|
|
77 |
return self.template % self._data |
|
78 |
||
79 |
||
80 |
class ServerStarting(LoggingEvent): |
|
81 |
||
82 |
level = logging.INFO |
|
83 |
template = '---- Server started ----' |
|
84 |
||
85 |
||
86 |
class ServerStopped(LoggingEvent): |
|
87 |
||
88 |
level = logging.INFO |
|
89 |
template = '---- Server stopped ----' |
|
90 |
||
91 |
||
92 |
class UserConnected(LoggingEvent): |
|
93 |
||
94 |
level = logging.INFO |
|
95 |
template = '[%(session_id)s] %(address)s connected.' |
|
96 |
||
97 |
def __init__(self, transport, address): |
|
98 |
LoggingEvent.__init__( |
|
99 |
self, session_id=id(transport), address=address) |
|
100 |
||
101 |
||
102 |
class AuthenticationFailed(LoggingEvent): |
|
103 |
||
104 |
level = logging.INFO |
|
105 |
template = '[%(session_id)s] failed to authenticate.' |
|
106 |
||
107 |
def __init__(self, transport): |
|
108 |
LoggingEvent.__init__(self, session_id=id(transport)) |
|
109 |
||
110 |
||
111 |
class UserDisconnected(LoggingEvent): |
|
112 |
||
113 |
level = logging.INFO |
|
114 |
template = '[%(session_id)s] disconnected.' |
|
115 |
||
116 |
def __init__(self, transport): |
|
117 |
LoggingEvent.__init__(self, session_id=id(transport)) |
|
118 |
||
119 |
||
120 |
class AvatarEvent(LoggingEvent): |
|
121 |
"""Base avatar event."""
|
|
122 |
||
123 |
level = logging.INFO |
|
124 |
||
125 |
def __init__(self, avatar): |
|
126 |
self.avatar = avatar |
|
127 |
LoggingEvent.__init__( |
|
128 |
self, session_id=id(avatar.transport), username=avatar.username) |
|
129 |
||
130 |
||
131 |
class UserLoggedIn(AvatarEvent): |
|
132 |
||
133 |
template = '[%(session_id)s] %(username)s logged in.' |
|
134 |
||
135 |
||
136 |
class UserLoggedOut(AvatarEvent): |
|
137 |
||
138 |
template = '[%(session_id)s] %(username)s disconnected.' |
|
139 |
||
140 |
||
141 |
class SFTPStarted(AvatarEvent): |
|
142 |
||
143 |
template = '[%(session_id)s] %(username)s started SFTP session.' |
|
144 |
||
145 |
||
146 |
class SFTPClosed(AvatarEvent): |
|
147 |
||
148 |
template = '[%(session_id)s] %(username)s closed SFTP session.' |