${a['total_plays']}
plays
diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py
index 7401b3e8..f94fa111 100644
--- a/plexpy/datafactory.py
+++ b/plexpy/datafactory.py
@@ -13,10 +13,10 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see
.
-from plexpy import logger, datatables, common, database, helpers
-
import datetime
+from plexpy import logger, datatables, common, database, helpers, session
+
class DataFactory(object):
"""
@@ -29,6 +29,23 @@ class DataFactory(object):
def get_datatables_history(self, kwargs=None, custom_where=None, grouping=0, watched_percent=85):
data_tables = datatables.DataTables()
+ if session.get_session_user_id():
+ session_user_id = str(session.get_session_user_id())
+ added = False
+
+ for c_where in custom_where:
+ if 'user_id' in c_where[0]:
+ # This currently only works if c_where[1] is not a list or tuple
+ if str(c_where[1]) == session_user_id:
+ added = True
+ break
+ else:
+ c_where[1] = (c_where[1], session_user_id)
+ added = True
+
+ if not added:
+ custom_where = [['session_history.user_id', session.get_session_user_id()]]
+
group_by = ['session_history.reference_id'] if grouping else ['session_history.id']
columns = ['session_history.reference_id',
@@ -148,7 +165,7 @@ class DataFactory(object):
dict = {'recordsFiltered': query['filteredCount'],
'recordsTotal': query['totalCount'],
- 'data': helpers.filter_session_info(rows, 'user_id'),
+ 'data': rows,
'draw': query['draw'],
'filter_duration': helpers.human_duration(filter_duration, sig='dhm'),
'total_duration': helpers.human_duration(total_duration, sig='dhm')
@@ -162,6 +179,13 @@ class DataFactory(object):
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
sort_type = 'total_plays' if stats_type == 0 else 'total_duration'
+ library_cond = ''
+ if session.get_session_libraries():
+ library_cond = 'AND ('
+ for section_id in session.get_session_libraries():
+ library_cond += 'session_history_metadata.section_id = %s OR ' % section_id
+ library_cond = library_cond.rstrip(' OR ') + ')'
+
home_stats = []
for stat in stats_cards:
@@ -177,11 +201,11 @@ class DataFactory(object):
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
' WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
' >= datetime("now", "-%s days", "localtime") ' \
- ' AND session_history.media_type = "episode" ' \
+ ' AND session_history.media_type = "episode" %s ' \
' GROUP BY %s) AS t ' \
'GROUP BY t.grandparent_title ' \
'ORDER BY %s DESC ' \
- 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
+ 'LIMIT %s ' % (time_range, library_cond, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_tv: %s." % e)
@@ -207,7 +231,7 @@ class DataFactory(object):
home_stats.append({'stat_id': stat,
'stat_type': sort_type,
- 'rows': helpers.filter_session_info(top_tv, 'section_id')})
+ 'rows': session.mask_session_info(top_tv, mask_metadata=True)})
elif stat == 'popular_tv':
popular_tv = []
@@ -222,11 +246,11 @@ class DataFactory(object):
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
' WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
' >= datetime("now", "-%s days", "localtime") ' \
- ' AND session_history.media_type = "episode" ' \
+ ' AND session_history.media_type = "episode" %s ' \
' GROUP BY %s) AS t ' \
'GROUP BY t.grandparent_title ' \
'ORDER BY users_watched DESC, %s DESC ' \
- 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
+ 'LIMIT %s ' % (time_range, library_cond, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_tv: %s." % e)
@@ -250,7 +274,7 @@ class DataFactory(object):
popular_tv.append(row)
home_stats.append({'stat_id': stat,
- 'rows': helpers.filter_session_info(popular_tv, 'section_id')})
+ 'rows': session.mask_session_info(popular_tv, mask_metadata=True)})
elif stat == 'top_movies':
top_movies = []
@@ -264,11 +288,11 @@ class DataFactory(object):
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
' WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
' >= datetime("now", "-%s days", "localtime") ' \
- ' AND session_history.media_type = "movie" ' \
+ ' AND session_history.media_type = "movie" %s ' \
' GROUP BY %s) AS t ' \
'GROUP BY t.full_title ' \
'ORDER BY %s DESC ' \
- 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
+ 'LIMIT %s ' % (time_range, library_cond, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_movies: %s." % e)
@@ -291,9 +315,10 @@ class DataFactory(object):
'row_id': item['id']
}
top_movies.append(row)
+
home_stats.append({'stat_id': stat,
'stat_type': sort_type,
- 'rows': helpers.filter_session_info(top_movies, 'section_id')})
+ 'rows': session.mask_session_info(top_movies, mask_metadata=True)})
elif stat == 'popular_movies':
popular_movies = []
@@ -308,11 +333,11 @@ class DataFactory(object):
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
' WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
' >= datetime("now", "-%s days", "localtime") ' \
- ' AND session_history.media_type = "movie" ' \
+ ' AND session_history.media_type = "movie" %s ' \
' GROUP BY %s) AS t ' \
'GROUP BY t.full_title ' \
'ORDER BY users_watched DESC, %s DESC ' \
- 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
+ 'LIMIT %s ' % (time_range, library_cond, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_movies: %s." % e)
@@ -336,7 +361,7 @@ class DataFactory(object):
popular_movies.append(row)
home_stats.append({'stat_id': stat,
- 'rows': helpers.filter_session_info(popular_movies, 'section_id')})
+ 'rows': session.mask_session_info(popular_movies, mask_metadata=True)})
elif stat == 'top_music':
top_music = []
@@ -350,11 +375,11 @@ class DataFactory(object):
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
' WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
' >= datetime("now", "-%s days", "localtime") ' \
- ' AND session_history.media_type = "track" ' \
+ ' AND session_history.media_type = "track" %s ' \
' GROUP BY %s) AS t ' \
'GROUP BY t.grandparent_title ' \
'ORDER BY %s DESC ' \
- 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
+ 'LIMIT %s ' % (time_range, library_cond, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_music: %s." % e)
@@ -380,7 +405,7 @@ class DataFactory(object):
home_stats.append({'stat_id': stat,
'stat_type': sort_type,
- 'rows': helpers.filter_session_info(top_music, 'section_id')})
+ 'rows': session.mask_session_info(top_music, mask_metadata=True)})
elif stat == 'popular_music':
popular_music = []
@@ -395,11 +420,11 @@ class DataFactory(object):
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
' WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
' >= datetime("now", "-%s days", "localtime") ' \
- ' AND session_history.media_type = "track" ' \
+ ' AND session_history.media_type = "track" %s ' \
' GROUP BY %s) AS t ' \
'GROUP BY t.grandparent_title ' \
'ORDER BY users_watched DESC, %s DESC ' \
- 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
+ 'LIMIT %s ' % (time_range, library_cond, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_music: %s." % e)
@@ -423,7 +448,7 @@ class DataFactory(object):
popular_music.append(row)
home_stats.append({'stat_id': stat,
- 'rows': helpers.filter_session_info(popular_music, 'section_id')})
+ 'rows': session.mask_session_info(popular_music, mask_metadata=True)})
elif stat == 'top_users':
top_users = []
@@ -476,7 +501,7 @@ class DataFactory(object):
home_stats.append({'stat_id': stat,
'stat_type': sort_type,
- 'rows': helpers.mask_session_info(top_users)})
+ 'rows': session.mask_session_info(top_users, mask_metadata=True)})
elif stat == 'top_platforms':
top_platform = []
@@ -522,13 +547,13 @@ class DataFactory(object):
home_stats.append({'stat_id': stat,
'stat_type': sort_type,
- 'rows': top_platform})
+ 'rows': session.mask_session_info(top_platform, mask_metadata=True)})
elif stat == 'last_watched':
last_watched = []
try:
query = 'SELECT t.id, t.full_title, t.rating_key, t.thumb, t.grandparent_thumb, ' \
- 't.user, t.user_id, t.custom_avatar_url as user_thumb, t.player, ' \
+ 't.user, t.user_id, t.custom_avatar_url as user_thumb, t.player, t.section_id, ' \
'(CASE WHEN t.friendly_name IS NULL THEN t.username ELSE t.friendly_name END) ' \
' AS friendly_name, ' \
'MAX(t.started) AS last_watch, ' \
@@ -541,12 +566,12 @@ class DataFactory(object):
' WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
' >= datetime("now", "-%s days", "localtime") ' \
' AND (session_history.media_type = "movie" ' \
- ' OR session_history_metadata.media_type = "episode") ' \
+ ' OR session_history_metadata.media_type = "episode") %s ' \
' GROUP BY %s) AS t ' \
'WHERE percent_complete >= %s ' \
'GROUP BY t.id ' \
'ORDER BY last_watch DESC ' \
- 'LIMIT %s' % (time_range, group_by, notify_watched_percent, stats_count)
+ 'LIMIT %s' % (time_range, library_cond, group_by, notify_watched_percent, stats_count)
result = monitor_db.select(query)
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: last_watched: %s." % e)
@@ -567,13 +592,14 @@ class DataFactory(object):
'rating_key': item['rating_key'],
'thumb': thumb,
'grandparent_thumb': item['grandparent_thumb'],
+ 'section_id': item['section_id'],
'last_watch': item['last_watch'],
'player': item['player']
}
last_watched.append(row)
home_stats.append({'stat_id': stat,
- 'rows': helpers.filter_session_info(last_watched, 'user_id')})
+ 'rows': session.mask_session_info(last_watched, mask_metadata=True)})
elif stat == 'most_concurrent':
@@ -692,19 +718,24 @@ class DataFactory(object):
}
library_stats.append(library)
- return helpers.filter_session_info(library_stats, 'section_id')
+ return session.filter_session_info(library_stats, 'section_id')
def get_stream_details(self, row_id=None):
monitor_db = database.MonitorDatabase()
+ user_cond = ''
+ if session.get_session_user_id():
+ user_cond = 'AND session_history.user_id = %s ' % session.get_session_user_id()
+
if row_id:
query = 'SELECT container, bitrate, video_resolution, width, height, aspect_ratio, video_framerate, ' \
'video_codec, audio_codec, audio_channels, video_decision, transcode_video_codec, transcode_height, ' \
- 'transcode_width, audio_decision, transcode_audio_codec, transcode_audio_channels, media_type, ' \
- 'title, grandparent_title ' \
- 'from session_history_media_info ' \
- 'join session_history_metadata on session_history_media_info.id = session_history_metadata.id ' \
- 'where session_history_media_info.id = ?'
+ 'transcode_width, audio_decision, transcode_audio_codec, transcode_audio_channels, ' \
+ 'session_history_metadata.media_type, title, grandparent_title ' \
+ 'FROM session_history_media_info ' \
+ 'JOIN session_history ON session_history_media_info.id = session_history.id ' \
+ 'JOIN session_history_metadata ON session_history_media_info.id = session_history_metadata.id ' \
+ 'WHERE session_history_media_info.id = ? %s' % user_cond
result = monitor_db.select(query, args=[row_id])
else:
return None
diff --git a/plexpy/datatables.py b/plexpy/datatables.py
index 6c0a9b98..88275b3c 100644
--- a/plexpy/datatables.py
+++ b/plexpy/datatables.py
@@ -89,16 +89,15 @@ class DataTables(object):
# Build custom where parameters
if custom_where:
for w in custom_where:
- c_where += w[0] + ' = ? AND '
-
- # The order of our args changes if we are grouping
- #if grouping:
- # args.insert(0, w[1])
- #else:
- # args.append(w[1])
-
- # My testing shows that order of args doesn't change
- args.append(w[1])
+ if isinstance(w[1], (list, tuple)) and len(w[1]):
+ c_where += '('
+ for w_ in w[1]:
+ c_where += w[0] + ' = ? OR '
+ args.append(w_)
+ c_where = c_where.rstrip(' OR ') + ') AND '
+ else:
+ c_where += w[0] + ' = ? AND '
+ args.append(w[1])
if c_where:
c_where = 'WHERE ' + c_where.rstrip(' AND ')
diff --git a/plexpy/helpers.py b/plexpy/helpers.py
index 334beed3..c028284e 100644
--- a/plexpy/helpers.py
+++ b/plexpy/helpers.py
@@ -563,104 +563,4 @@ def uploadToImgur(imgPath, imgTitle=''):
except (urllib2.HTTPError, urllib2.URLError) as e:
logger.warn(u"PlexPy Helpers :: Unable to upload image to Imgur: %s" % e)
- return img_url
-
-
-def allow_session_user(user_id):
- """
- Returns True or False if the user_id is allowed for the user session
- """
- import cherrypy
- from plexpy.webauth import SESSION_KEY
-
- if cherrypy.config.get('tools.auth.on'):
- _session = cherrypy.session.get(SESSION_KEY)
- if str(user_id) != _session['user_id']:
- return False
-
- return True
-
-def allow_session_library(section_id):
- """
- Returns True or False if the section_id is allowed for the user session
- """
- import cherrypy
- from plexpy.webauth import SESSION_KEY
-
- if cherrypy.config.get('tools.auth.on'):
- _session = cherrypy.session.get(SESSION_KEY)
- if str(section_id) not in _session['user_libraries']:
- return False
-
- return True
-
-def filter_session_info(list_of_dicts, filter_key=None):
- """
- Filters a list of dictionary items to only return the info for the current logged in user
- """
- import cherrypy
- from plexpy.webauth import SESSION_KEY
-
- if cherrypy.config.get('tools.auth.on'):
- _session = cherrypy.session.get(SESSION_KEY)
-
- if filter_key == 'user_id' and _session['user_id']:
- session_user_id = str(_session['user_id'])
- return [d for d in list_of_dicts if str(d.get('user_id','')) == session_user_id]
-
- elif filter_key == 'section_id' and _session['user_libraries']:
- session_library_ids = _session['user_libraries']
- return [d for d in list_of_dicts if str(d.get('section_id','')) in session_library_ids]
-
- return list_of_dicts
-
-def mask_session_info(list_of_dicts, mask_metadata=False):
- """
- Masks user info in a list of dictionary items to only display info for the current logged in user
- """
- import cherrypy
- from plexpy.webauth import SESSION_KEY
-
- if cherrypy.config.get('tools.auth.on'):
- _session = cherrypy.session.get(SESSION_KEY)
-
- keys_to_mask = {'user_id': '',
- 'user': '',
- 'friendly_name': 'Plex User',
- 'user_thumb': common.DEFAULT_USER_THUMB,
- 'ip_address': 'N/A',
- 'machine_id': ''
- }
-
- metadata_to_mask = {'media_index': '',
- 'parent_media_index': '',
- 'art': common.DEFAULT_ART,
- 'parent_thumb': common.DEFAULT_POSTER_THUMB,
- 'grandparent_thumb': common.DEFAULT_POSTER_THUMB,
- 'thumb': common.DEFAULT_POSTER_THUMB,
- 'bif_thumb': '',
- 'grandparent_title': '',
- 'parent_title': '',
- 'title': '',
- 'rating_key': '',
- 'parent_rating_key': '',
- 'grandparent_rating_key': '',
- 'year': ''
- }
-
- if _session['user_id']:
- session_user_id = str(_session['user_id'])
- session_library_ids = _session['user_libraries']
-
- for d in list_of_dicts:
- if not (str(d.get('user_id')) == session_user_id or d.get('user') == _session['user']):
- for k, v in keys_to_mask.iteritems():
- if k in d: d[k] = keys_to_mask[k]
-
- if mask_metadata and str(d.get('section_id','')) not in session_library_ids:
- for k, v in metadata_to_mask.iteritems():
- if k in d: d[k] = metadata_to_mask[k]
-
- return list_of_dicts
-
- return list_of_dicts
\ No newline at end of file
+ return img_url
\ No newline at end of file
diff --git a/plexpy/libraries.py b/plexpy/libraries.py
index 88997e31..a3d952c6 100644
--- a/plexpy/libraries.py
+++ b/plexpy/libraries.py
@@ -13,8 +13,8 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see
.
-from plexpy import logger, datatables, common, database, helpers
import plexpy
+from plexpy import logger, datatables, common, database, helpers, session
def update_section_ids():
from plexpy import pmsconnect, activity_pinger
@@ -119,9 +119,18 @@ class Libraries(object):
pass
def get_datatables_list(self, kwargs=None):
+ default_return = {'recordsFiltered': 0,
+ 'recordsTotal': 0,
+ 'draw': 0,
+ 'data': 'null',
+ 'error': 'Unable to execute database query.'}
+
data_tables = datatables.DataTables()
- custom_where = ['library_sections.deleted_section', 0]
+ custom_where = [['library_sections.deleted_section', 0]]
+
+ if session.get_session_libraries():
+ custom_where.append(['library_sections.section_id', session.get_session_libraries()])
columns = ['library_sections.section_id',
'library_sections.section_name',
@@ -155,7 +164,7 @@ class Libraries(object):
try:
query = data_tables.ssp_query(table_name='library_sections',
columns=columns,
- custom_where=[custom_where],
+ custom_where=custom_where,
group_by=['library_sections.server_id', 'library_sections.section_id'],
join_types=['LEFT OUTER JOIN',
'LEFT OUTER JOIN',
@@ -169,11 +178,7 @@ class Libraries(object):
kwargs=kwargs)
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_list: %s." % e)
- return {'recordsFiltered': 0,
- 'recordsTotal': 0,
- 'draw': 0,
- 'data': 'null',
- 'error': 'Unable to execute database query.'}
+ return default_return
result = query['result']
@@ -222,7 +227,7 @@ class Libraries(object):
dict = {'recordsFiltered': query['filteredCount'],
'recordsTotal': query['totalCount'],
- 'data': helpers.filter_session_info(rows, 'section_id'),
+ 'data': rows,
'draw': query['draw']
}
@@ -235,9 +240,12 @@ class Libraries(object):
default_return = {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
- 'data': None,
+ 'data': 'null',
'error': 'Unable to execute database query.'}
+ if not session.allow_session_library(section_id):
+ return default_return
+
if section_id and not str(section_id).isdigit():
logger.warn(u"PlexPy Libraries :: Datatable media info called by invalid section_id provided.")
return default_return
@@ -443,6 +451,9 @@ class Libraries(object):
from plexpy import pmsconnect
import json, os
+ if not session.allow_session_library(section_id):
+ return False
+
if section_id and not str(section_id).isdigit():
logger.warn(u"PlexPy Libraries :: Datatable media info file size called by invalid section_id provided.")
return False
@@ -619,6 +630,9 @@ class Libraries(object):
return default_return
def get_watch_time_stats(self, section_id=None):
+ if not session.allow_session_library(section_id):
+ return []
+
monitor_db = database.MonitorDatabase()
time_queries = [1, 7, 30, 0]
@@ -671,6 +685,9 @@ class Libraries(object):
return library_watch_time_stats
def get_user_stats(self, section_id=None):
+ if not session.allow_session_library(section_id):
+ return []
+
monitor_db = database.MonitorDatabase()
user_stats = []
@@ -678,7 +695,7 @@ class Libraries(object):
try:
if str(section_id).isdigit():
query = 'SELECT (CASE WHEN users.friendly_name IS NULL THEN users.username ' \
- 'ELSE users.friendly_name END) AS user, users.user_id, users.thumb, COUNT(user) AS user_count ' \
+ 'ELSE users.friendly_name END) AS friendly_name, users.user_id, users.thumb, COUNT(user) AS user_count ' \
'FROM session_history ' \
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
'JOIN users ON users.user_id = session_history.user_id ' \
@@ -693,16 +710,19 @@ class Libraries(object):
result = []
for item in result:
- row = {'user': item['user'],
+ row = {'friendly_name': item['friendly_name'],
'user_id': item['user_id'],
- 'thumb': item['thumb'],
+ 'user_thumb': item['thumb'],
'total_plays': item['user_count']
}
user_stats.append(row)
- return helpers.filter_session_info(user_stats, 'user_id')
+ return session.mask_session_info(user_stats)
def get_recently_watched(self, section_id=None, limit='10'):
+ if not session.allow_session_library(section_id):
+ return []
+
monitor_db = database.MonitorDatabase()
recently_watched = []
diff --git a/plexpy/plextv.py b/plexpy/plextv.py
index 13864a97..5e89001d 100644
--- a/plexpy/plextv.py
+++ b/plexpy/plextv.py
@@ -16,14 +16,13 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see
.
-from plexpy import logger, helpers, http_handler, database, users
-import xmltodict
-import json
-from xml.dom import minidom
-import requests
-
import base64
+import json
+import xmltodict
+from xml.dom import minidom
+
import plexpy
+from plexpy import logger, helpers, http_handler, database, users, session
def refresh_users():
@@ -401,7 +400,7 @@ class PlexTV(object):
synced_items.append(sync_details)
- return helpers.filter_session_info(synced_items, 'user_id')
+ return session.filter_session_info(synced_items, 'user_id')
def get_server_urls(self, include_https=True):
diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py
index 35d0255f..a8949b40 100644
--- a/plexpy/pmsconnect.py
+++ b/plexpy/pmsconnect.py
@@ -13,11 +13,11 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see
.
-from plexpy import logger, helpers, users, http_handler, common, database
+import urllib2
from urlparse import urlparse
import plexpy
-import urllib2
+from plexpy import logger, helpers, users, http_handler, common, database, session
def get_server_friendly_name():
@@ -462,7 +462,7 @@ class PmsConnect(object):
'grandparent_title': helpers.get_xml_attr(item, 'grandparentTitle'),
'media_index': helpers.get_xml_attr(item, 'index'),
'parent_media_index': helpers.get_xml_attr(item, 'parentIndex'),
- 'section_id': helpers.get_xml_attr(item, 'librarySectionID'),
+ 'section_id': section_id if section_id else helpers.get_xml_attr(item, 'librarySectionID'),
'library_name': helpers.get_xml_attr(item, 'librarySectionTitle'),
'year': helpers.get_xml_attr(item, 'year'),
'thumb': helpers.get_xml_attr(item, 'thumb'),
@@ -484,7 +484,7 @@ class PmsConnect(object):
'grandparent_title': helpers.get_xml_attr(item, 'grandparentTitle'),
'media_index': helpers.get_xml_attr(item, 'index'),
'parent_media_index': helpers.get_xml_attr(item, 'parentIndex'),
- 'section_id': helpers.get_xml_attr(item, 'librarySectionID'),
+ 'section_id': section_id if section_id else helpers.get_xml_attr(item, 'librarySectionID'),
'library_name': helpers.get_xml_attr(item, 'librarySectionTitle'),
'year': helpers.get_xml_attr(item, 'year'),
'thumb': helpers.get_xml_attr(item, 'thumb'),
@@ -493,9 +493,10 @@ class PmsConnect(object):
'added_at': helpers.get_xml_attr(item, 'addedAt')
}
recents_list.append(recent_items)
-
- output = {'recently_added': helpers.filter_session_info(
+
+ output = {'recently_added': session.filter_session_info(
sorted(recents_list, key=lambda k: k['added_at'], reverse=True), 'section_id')}
+
return output
def get_metadata_details(self, rating_key='', get_media_info=False):
@@ -975,7 +976,7 @@ class PmsConnect(object):
session_list.append(session_output)
output = {'stream_count': helpers.get_xml_attr(xml_head[0], 'size'),
- 'sessions': helpers.mask_session_info(session_list, True)
+ 'sessions': session.mask_session_info(session_list, True)
}
return output
diff --git a/plexpy/session.py b/plexpy/session.py
new file mode 100644
index 00000000..1b49fbe4
--- /dev/null
+++ b/plexpy/session.py
@@ -0,0 +1,150 @@
+# This file is part of PlexPy.
+#
+# PlexPy is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# PlexPy is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with PlexPy. If not, see
.
+
+import cherrypy
+
+from plexpy import common
+
+
+def get_session_info():
+ """
+ Returns the session info for the user session
+ """
+ from plexpy.webauth import SESSION_KEY
+
+ if cherrypy.config.get('tools.auth.on'):
+ _session = cherrypy.session.get(SESSION_KEY)
+ if _session:
+ return _session
+
+ return {'user_id': None,
+ 'user': None,
+ 'user_group': 'admin',
+ 'user_libraries': None,
+ 'expiry': None}
+
+def get_session_user():
+ """
+ Returns the user_id for the current logged in session
+ """
+ _session = get_session_info()
+ return _session['user']
+
+def get_session_user_id():
+ """
+ Returns the user_id for the current logged in session
+ """
+ _session = get_session_info()
+ return str(_session['user_id']) if _session['user_id'] else None
+
+def get_session_libraries():
+ """
+ Returns a tuple of section_id for the current logged in session
+ """
+ _session = get_session_info()
+ return _session['user_libraries']
+
+def allow_session_user(user_id):
+ """
+ Returns True or False if the user_id is allowed for the current logged in session
+ """
+ session_user_id = get_session_user_id()
+ if session_user_id and str(user_id) != session_user_id:
+ return False
+ return True
+
+def allow_session_library(section_id):
+ """
+ Returns True or False if the section_id is allowed for the current logged in session
+ """
+ session_library_ids = get_session_libraries()
+ if session_library_ids and str(section_id) not in session_library_ids:
+ return False
+ return True
+
+def filter_session_info(list_of_dicts, filter_key=None):
+ """
+ Filters a list of dictionary items to only return the info for the current logged in session
+ """
+ session_user_id = get_session_user_id()
+ session_library_ids = get_session_libraries()
+
+ list_of_dicts = friendly_name_to_username(list_of_dicts)
+
+ if filter_key == 'user_id' and session_user_id:
+ return [d for d in list_of_dicts if str(d.get('user_id','')) == session_user_id]
+
+ elif filter_key == 'section_id' and session_library_ids:
+ return [d for d in list_of_dicts if str(d.get('section_id','')) in session_library_ids]
+
+ return list_of_dicts
+
+def mask_session_info(list_of_dicts, mask_metadata=False):
+ """
+ Masks user info in a list of dictionary items to only display info for the current logged in session
+ """
+ session_user = get_session_user()
+ session_user_id = get_session_user_id()
+ session_library_ids = get_session_libraries()
+
+ keys_to_mask = {'user_id': '',
+ 'user': 'Plex User',
+ 'friendly_name': 'Plex User',
+ 'user_thumb': common.DEFAULT_USER_THUMB,
+ 'ip_address': 'N/A',
+ 'machine_id': '',
+ 'player': 'Player'
+ }
+
+ metadata_to_mask = {'media_index': '',
+ 'parent_media_index': '',
+ 'art': common.DEFAULT_ART,
+ 'parent_thumb': common.DEFAULT_POSTER_THUMB,
+ 'grandparent_thumb': common.DEFAULT_POSTER_THUMB,
+ 'thumb': common.DEFAULT_POSTER_THUMB,
+ 'bif_thumb': '',
+ 'grandparent_title': '',
+ 'parent_title': '',
+ 'title': '',
+ 'rating_key': '',
+ 'parent_rating_key': '',
+ 'grandparent_rating_key': '',
+ 'year': ''
+ }
+
+ list_of_dicts = friendly_name_to_username(list_of_dicts)
+
+ for d in list_of_dicts:
+ if session_user_id and not (str(d.get('user_id')) == session_user_id or d.get('user') == session_user):
+ for k, v in keys_to_mask.iteritems():
+ if k in d: d[k] = keys_to_mask[k]
+
+ if mask_metadata and session_library_ids and str(d.get('section_id','')) not in session_library_ids:
+ for k, v in metadata_to_mask.iteritems():
+ if k in d: d[k] = metadata_to_mask[k]
+
+ return list_of_dicts
+
+def friendly_name_to_username(list_of_dicts):
+ """
+ Reverts the friendly name back to the username of the current logged in session
+ """
+ session_user = get_session_user()
+
+ for d in list_of_dicts:
+ if 'friendly_name' in d and d['friendly_name'] != session_user:
+ d['friendly_name'] = session_user
+
+ return list_of_dicts
\ No newline at end of file
diff --git a/plexpy/users.py b/plexpy/users.py
index 9ef40ecb..47aa814b 100644
--- a/plexpy/users.py
+++ b/plexpy/users.py
@@ -13,7 +13,8 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see
.
-from plexpy import logger, datatables, common, database, helpers
+import plexpy
+from plexpy import logger, datatables, common, database, helpers, session
def user_login(username=None, password=None):
from plexpy import plextv
@@ -85,9 +86,18 @@ class Users(object):
pass
def get_datatables_list(self, kwargs=None):
+ default_return = {'recordsFiltered': 0,
+ 'recordsTotal': 0,
+ 'draw': 0,
+ 'data': 'null',
+ 'error': 'Unable to execute database query.'}
+
data_tables = datatables.DataTables()
- custom_where = ['users.deleted_user', 0]
+ custom_where = [['users.deleted_user', 0]]
+
+ if session.get_session_user_id():
+ custom_where.append(['users.user_id', session.get_session_user_id()])
columns = ['users.user_id',
'(CASE WHEN users.friendly_name IS NULL OR TRIM(users.friendly_name) = "" \
@@ -121,7 +131,7 @@ class Users(object):
try:
query = data_tables.ssp_query(table_name='users',
columns=columns,
- custom_where=[custom_where],
+ custom_where=custom_where,
group_by=['users.user_id'],
join_types=['LEFT OUTER JOIN',
'LEFT OUTER JOIN',
@@ -135,11 +145,7 @@ class Users(object):
kwargs=kwargs)
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_list: %s." % e)
- return {'recordsFiltered': 0,
- 'recordsTotal': 0,
- 'draw': 0,
- 'data': 'null',
- 'error': 'Unable to execute database query.'}
+ return default_return
users = query['result']
@@ -190,13 +196,22 @@ class Users(object):
dict = {'recordsFiltered': query['filteredCount'],
'recordsTotal': query['totalCount'],
- 'data': helpers.filter_session_info(rows, 'user_id'),
+ 'data': session.friendly_name_to_username(rows),
'draw': query['draw']
}
return dict
def get_datatables_unique_ips(self, user_id=None, kwargs=None):
+ default_return = {'recordsFiltered': 0,
+ 'recordsTotal': 0,
+ 'draw': 0,
+ 'data': 'null',
+ 'error': 'Unable to execute database query.'}
+
+ if not session.allow_session_user(user_id):
+ return default_return
+
data_tables = datatables.DataTables()
custom_where = ['users.user_id', user_id]
@@ -241,11 +256,7 @@ class Users(object):
kwargs=kwargs)
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_unique_ips: %s." % e)
- return {'recordsFiltered': 0,
- 'recordsTotal': 0,
- 'draw': 0,
- 'data': 'null',
- 'error': 'Unable to execute database query.'}
+ return default_return
results = query['result']
@@ -284,7 +295,7 @@ class Users(object):
dict = {'recordsFiltered': query['filteredCount'],
'recordsTotal': query['totalCount'],
- 'data': helpers.filter_session_info(rows, 'user_id'),
+ 'data': session.friendly_name_to_username(rows),
'draw': query['draw']
}
@@ -356,7 +367,9 @@ class Users(object):
user_details = {}
if result:
for item in result:
- if item['friendly_name']:
+ if session.get_session_user():
+ friendly_name = session.get_session_user()
+ elif item['friendly_name']:
friendly_name = item['friendly_name']
else:
friendly_name = item['username']
@@ -407,6 +420,9 @@ class Users(object):
return default_return
def get_watch_time_stats(self, user_id=None):
+ if not session.allow_session_user(user_id):
+ return []
+
monitor_db = database.MonitorDatabase()
time_queries = [1, 7, 30, 0]
@@ -457,6 +473,9 @@ class Users(object):
return user_watch_time_stats
def get_player_stats(self, user_id=None):
+ if not session.allow_session_user(user_id):
+ return []
+
monitor_db = database.MonitorDatabase()
player_stats = []
@@ -491,6 +510,9 @@ class Users(object):
return player_stats
def get_recently_watched(self, user_id=None, limit='10'):
+ if not session.allow_session_user(user_id):
+ return []
+
monitor_db = database.MonitorDatabase()
recently_watched = []
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index 0d1f6449..3fa0d243 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -13,32 +13,24 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see
.
-from plexpy import logger, notifiers, plextv, pmsconnect, common, log_reader, \
- datafactory, graphs, users, libraries, database, web_socket
-from plexpy.helpers import checked, addtoapi, get_ip, create_https_certificates
-from plexpy.webauth import AuthController, requireAuth, member_of, name_is, SESSION_KEY
-
-from mako.lookup import TemplateLookup
-from mako import exceptions
-from hashing_passwords import make_hash
-
-import plexpy
-import threading
import cherrypy
import hashlib
-import random
import json
import os
-from api2 import API2
+import random
+import threading
-try:
- # pylint:disable=E0611
- # ignore this error because we are catching the ImportError
- from collections import OrderedDict
- # pylint:enable=E0611
-except ImportError:
- # Python 2.6.x fallback, from libs
- from ordereddict import OrderedDict
+from hashing_passwords import make_hash
+from mako.lookup import TemplateLookup
+from mako import exceptions
+
+import plexpy
+from plexpy import logger, notifiers, plextv, pmsconnect, common, log_reader, \
+ datafactory, graphs, users, libraries, database, web_socket
+from plexpy.api2 import API2
+from plexpy.helpers import checked, addtoapi, get_ip, create_https_certificates
+from plexpy.session import get_session_info, allow_session_user, allow_session_library
+from plexpy.webauth import AuthController, requireAuth, member_of, name_is, SESSION_KEY
def serve_template(templatename, **kwargs):
@@ -49,13 +41,7 @@ def serve_template(templatename, **kwargs):
server_name = plexpy.CONFIG.PMS_NAME
- _session = {'user_id': None,
- 'user': None,
- 'user_group': 'admin',
- 'expiry': None}
-
- if cherrypy.config.get('tools.auth.on'):
- _session = cherrypy.session.get(SESSION_KEY)
+ _session = get_session_info()
try:
template = _hplookup.get_template(templatename)
@@ -351,6 +337,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def library(self, section_id=None):
+ if not allow_session_library(section_id):
+ raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
+
config = {
"get_file_sizes": plexpy.CONFIG.GET_FILE_SIZES,
"get_file_sizes_hold": plexpy.CONFIG.GET_FILE_SIZES_HOLD
@@ -409,6 +398,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_library_watch_time_stats(self, section_id=None, **kwargs):
+ if not allow_session_library(section_id):
+ return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats")
+
if section_id:
library_data = libraries.Libraries()
result = library_data.get_watch_time_stats(section_id=section_id)
@@ -424,6 +416,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_library_user_stats(self, section_id=None, **kwargs):
+ if not allow_session_library(section_id):
+ return serve_template(templatename="library_user_stats.html", data=None, title="Player Stats")
+
if section_id:
library_data = libraries.Libraries()
result = library_data.get_user_stats(section_id=section_id)
@@ -439,6 +434,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_library_recently_watched(self, section_id=None, limit='10', **kwargs):
+ if not allow_session_library(section_id):
+ return serve_template(templatename="user_recently_watched.html", data=None, title="Recently Watched")
+
if section_id:
library_data = libraries.Libraries()
result = library_data.get_recently_watched(section_id=section_id, limit=limit)
@@ -454,6 +452,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_library_recently_added(self, section_id=None, limit='10', **kwargs):
+ if not allow_session_library(section_id):
+ return serve_template(templatename="library_recently_added.html", data=None, title="Recently Added")
+
if section_id:
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_recently_added_details(section_id=section_id, count=limit)
@@ -649,6 +650,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def user(self, user_id=None):
+ if not allow_session_user(user_id):
+ raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
+
user_data = users.Users()
if user_id:
try:
@@ -702,6 +706,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_user_watch_time_stats(self, user=None, user_id=None, **kwargs):
+ if not allow_session_user(user_id):
+ return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats")
+
if user_id or user:
user_data = users.Users()
result = user_data.get_watch_time_stats(user_id=user_id)
@@ -717,6 +724,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_user_player_stats(self, user=None, user_id=None, **kwargs):
+ if not allow_session_user(user_id):
+ return serve_template(templatename="user_player_stats.html", data=None, title="Player Stats")
+
if user_id or user:
user_data = users.Users()
result = user_data.get_player_stats(user_id=user_id)
@@ -732,6 +742,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_user_recently_watched(self, user=None, user_id=None, limit='10', **kwargs):
+ if not allow_session_user(user_id):
+ return serve_template(templatename="user_recently_watched.html", data=None, title="Recently Watched")
+
if user_id or user:
user_data = users.Users()
result = user_data.get_recently_watched(user_id=user_id, limit=limit)
@@ -1239,10 +1252,10 @@ class WebInterface(object):
def log_js_errors(self, page, message, file, line):
""" Logs javascript errors from the web interface. """
logger.error(u"WebUI :: /%s : %s. (%s:%s)" % (page.rpartition('/')[-1],
- message,
- file.rpartition('/')[-1].partition('?')[0],
- line))
- return True
+ message,
+ file.rpartition('/')[-1].partition('?')[0],
+ line))
+ return "js error logged."
@cherrypy.expose
@requireAuth(member_of("admin"))