diff --git a/data/interfaces/default/js/tables/login_logs.js b/data/interfaces/default/js/tables/login_logs.js
index 325ad973..d2cf605b 100644
--- a/data/interfaces/default/js/tables/login_logs.js
+++ b/data/interfaces/default/js/tables/login_logs.js
@@ -77,9 +77,24 @@ login_log_table_options = {
{
"targets": [6],
"data": "browser",
- "width": "20%",
+ "width": "18%",
"className": "no-wrap"
- }
+ },
+ {
+ "targets": [7],
+ "data": "success",
+ "createdCell": function (td, cellData, rowData, row, col) {
+ if (cellData == 1) {
+ $(td).html('');
+ } else {
+ $(td).html('');
+ }
+ },
+ "searchable": false,
+ "orderable": false,
+ "className": "no-wrap",
+ "width": "2%"
+ },
],
"drawCallback": function (settings) {
// Jump to top of page
diff --git a/data/interfaces/default/logs.html b/data/interfaces/default/logs.html
index f82dfd59..b041b4a9 100644
--- a/data/interfaces/default/logs.html
+++ b/data/interfaces/default/logs.html
@@ -145,13 +145,14 @@
- Timestamp |
- User |
- User Group |
- IP Address |
- Host |
- Operating System |
- Browser |
+ Timestamp |
+ User |
+ User Group |
+ IP Address |
+ Host |
+ Operating System |
+ Browser |
+ |
diff --git a/plexpy/__init__.py b/plexpy/__init__.py
index a72e3923..e04b3dd5 100644
--- a/plexpy/__init__.py
+++ b/plexpy/__init__.py
@@ -496,7 +496,8 @@ def dbcheck():
# user_login table :: This table keeps record of the PlexPy guest logins
c_db.execute(
'CREATE TABLE IF NOT EXISTS user_login (id INTEGER PRIMARY KEY AUTOINCREMENT, '
- 'timestamp INTEGER, user_id INTEGER, user TEXT, user_group TEXT, ip_address TEXT, host TEXT, user_agent TEXT)'
+ 'timestamp INTEGER, user_id INTEGER, user TEXT, user_group TEXT, '
+ 'ip_address TEXT, host TEXT, user_agent TEXT, success INTEGER DEFAULT 1)'
)
# notifiers table :: This table keeps record of the notification agent settings
@@ -1124,6 +1125,15 @@ def dbcheck():
'DROP INDEX IF EXISTS idx_themoviedb_lookup_imdb_id'
)
+ # Upgrade user_login table from earlier versions
+ try:
+ c_db.execute('SELECT success FROM user_login')
+ except sqlite3.OperationalError:
+ logger.debug(u"Altering database. Updating database table user_login.")
+ c_db.execute(
+ 'ALTER TABLE user_login ADD COLUMN success INTEGER DEFAULT 1'
+ )
+
# Add "Local" user to database as default unauthenticated user.
result = c_db.execute('SELECT id FROM users WHERE username = "Local"')
if not result.fetchone():
diff --git a/plexpy/users.py b/plexpy/users.py
index 5a034f4a..4ba68f9f 100644
--- a/plexpy/users.py
+++ b/plexpy/users.py
@@ -678,7 +678,7 @@ class Users(object):
return filters_list
- def set_user_login(self, user_id=None, user=None, user_group=None, ip_address=None, host=None, user_agent=None):
+ def set_user_login(self, user_id=None, user=None, user_group=None, ip_address=None, host=None, user_agent=None, success=0):
if user_id is None or str(user_id).isdigit():
monitor_db = database.MonitorDatabase()
@@ -690,7 +690,8 @@ class Users(object):
'user_group': user_group,
'ip_address': ip_address,
'host': host,
- 'user_agent': user_agent}
+ 'user_agent': user_agent,
+ 'success': success}
try:
monitor_db.upsert(table_name='user_login', key_dict=keys, value_dict=values)
@@ -714,13 +715,14 @@ class Users(object):
else:
custom_where = [['user_login.user_id', user_id]] if user_id else []
- columns = ['user_login.user_id',
+ columns = ['user_login.timestamp',
+ 'user_login.user_id',
'user_login.user',
'user_login.user_group',
'user_login.ip_address',
'user_login.host',
'user_login.user_agent',
- 'user_login.timestamp',
+ 'user_login.success',
'(CASE WHEN users.friendly_name IS NULL OR TRIM(users.friendly_name) = "" \
THEN users.username ELSE users.friendly_name END) AS friendly_name'
]
@@ -744,14 +746,15 @@ class Users(object):
for item in results:
(os, browser) = httpagentparser.simple_detect(item['user_agent'])
- row = {'user_id': item['user_id'],
+ row = {'timestamp': item['timestamp'],
+ 'user_id': item['user_id'],
'user_group': item['user_group'],
'ip_address': item['ip_address'],
'host': item['host'],
'user_agent': item['user_agent'],
'os': os,
'browser': browser,
- 'timestamp': item['timestamp'],
+ 'success': item['success'],
'friendly_name': item['friendly_name'] or item['user']
}
diff --git a/plexpy/webauth.py b/plexpy/webauth.py
index 805bec7c..170141d8 100644
--- a/plexpy/webauth.py
+++ b/plexpy/webauth.py
@@ -190,7 +190,8 @@ class AuthController(object):
user_group=user_group,
ip_address=ip_address,
host=host,
- user_agent=user_agent)
+ user_agent=user_agent,
+ success=1)
logger.debug(u"PlexPy WebAuth :: %s user '%s' logged into PlexPy." % (user_group.capitalize(), username))
@@ -198,6 +199,20 @@ class AuthController(object):
"""Called on logout"""
logger.debug(u"PlexPy WebAuth :: %s User '%s' logged out of PlexPy." % (user_group.capitalize(), username))
+ def on_login_failed(self, username):
+ """Called on failed login"""
+
+ # Save login attempt to the database
+ ip_address = cherrypy.request.headers.get('X-Forwarded-For', cherrypy.request.headers.get('Remote-Addr'))
+ host = cherrypy.request.headers.get('Origin')
+ user_agent = cherrypy.request.headers.get('User-Agent')
+
+ Users().set_user_login(user=username,
+ ip_address=ip_address,
+ host=host,
+ user_agent=user_agent,
+ success=0)
+
def get_loginform(self, username="", msg=""):
from plexpy.webserve import serve_template
return serve_template(templatename="login.html", title="Login", username=escape(username, True), msg=msg)
@@ -240,9 +255,11 @@ class AuthController(object):
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
elif admin_login == '1':
+ self.on_login_failed(username)
logger.debug(u"PlexPy WebAuth :: Invalid admin login attempt from '%s'." % username)
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
else:
+ self.on_login_failed(username)
logger.debug(u"PlexPy WebAuth :: Invalid login attempt from '%s'." % username)
return self.get_loginform(username, u"Incorrect username/email or password.")