mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-08 06:00:51 -07:00
Use client headers for OAuth
This commit is contained in:
parent
434cb89ba8
commit
3fd0708d21
5 changed files with 89 additions and 86 deletions
7
data/interfaces/default/js/platform.min.js
vendored
Normal file
7
data/interfaces/default/js/platform.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -93,7 +93,85 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="${http_root}js/jquery-2.1.4.min.js"></script>
|
<script src="${http_root}js/jquery-2.1.4.min.js"></script>
|
||||||
|
<script src="${http_root}js/platform.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
function uuidv4() {
|
||||||
|
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
|
||||||
|
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const x_plex_headers = {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'X-Plex-Product': '${plexpy.common.PRODUCT}',
|
||||||
|
'X-Plex-Version': '${plexpy.common.RELEASE}',
|
||||||
|
'X-Plex-Client-Identifier': uuidv4(),
|
||||||
|
'X-Plex-Platform': platform.name,
|
||||||
|
'X-Plex-Platform-Version': platform.version,
|
||||||
|
'X-Plex-Device': platform.os.toString(),
|
||||||
|
'X-Plex-Device-Name': platform.name
|
||||||
|
};
|
||||||
|
|
||||||
|
getPlexOAuthPin = function () {
|
||||||
|
var deferred = $.Deferred();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'https://plex.tv/api/v2/pins?strong=true',
|
||||||
|
type: 'POST',
|
||||||
|
headers: x_plex_headers,
|
||||||
|
success: function(data) {
|
||||||
|
deferred.resolve({pin: data.id, code: data.code});
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
deferred.reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
};
|
||||||
|
|
||||||
|
var polling = null;
|
||||||
|
$('#sign-in-plex').click(function() {
|
||||||
|
clearTimeout(polling);
|
||||||
|
|
||||||
|
getPlexOAuthPin().then(function (data) {
|
||||||
|
const pin = data.pin;
|
||||||
|
const code = data.code;
|
||||||
|
var keep_polling = true;
|
||||||
|
|
||||||
|
window.open('https://app.plex.tv/auth/#!?clientID=' + x_plex_headers['X-Plex-Client-Identifier'] + '&code=' + code);
|
||||||
|
|
||||||
|
(function poll() {
|
||||||
|
polling = setTimeout(function () {
|
||||||
|
$.ajax({
|
||||||
|
url: 'https://plex.tv/api/v2/pins/' + pin,
|
||||||
|
type: 'GET',
|
||||||
|
headers: x_plex_headers,
|
||||||
|
success: function (data) {
|
||||||
|
if (data.authToken){
|
||||||
|
keep_polling = false;
|
||||||
|
signIn(true, data.authToken);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
keep_polling = false;
|
||||||
|
$('#sign-in-plex-alert').text('Error communicating with Plex.tv.').show();
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
if (keep_polling){
|
||||||
|
poll();
|
||||||
|
} else {
|
||||||
|
clearTimeout(polling);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
timeout: 1000
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
})();
|
||||||
|
}, function () {
|
||||||
|
$('#sign-in-plex-alert').text('Error communicating with Plex.tv.').show();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$('#login-form').submit(function(event) {
|
$('#login-form').submit(function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
signIn(false);
|
signIn(false);
|
||||||
|
@ -144,89 +222,6 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlexOAuthURL = function () {
|
|
||||||
var deferred = $.Deferred();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: 'https://plex.tv/api/v2/pins?strong=true',
|
|
||||||
type: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-Plex-Product': 'Tautulli',
|
|
||||||
'X-Plex-Version': '${plexpy.common.RELEASE}',
|
|
||||||
'X-Plex-Client-Identifier': '${plexpy.CONFIG.PMS_UUID}',
|
|
||||||
'X-Plex-Platform': '${plexpy.common.PLATFORM}',
|
|
||||||
'X-Plex-Platform-Version': '${plexpy.common.PLATFORM_RELEASE}',
|
|
||||||
'X-Plex-Device': 'Web',
|
|
||||||
'X-Plex-Device-Name': '${plexpy.common.PLATFORM_DEVICE_NAME}'
|
|
||||||
},
|
|
||||||
success: function(data) {
|
|
||||||
const pin = data.id;
|
|
||||||
const code = data.code;
|
|
||||||
const url = 'https://app.plex.tv/auth/#!?clientID=' + '${plexpy.CONFIG.PMS_UUID}' + '&code=' + code;
|
|
||||||
data = {pin: pin, url: url };
|
|
||||||
deferred.resolve(data);
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
deferred.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return deferred;
|
|
||||||
};
|
|
||||||
|
|
||||||
var polling = null;
|
|
||||||
$('#sign-in-plex').click(function() {
|
|
||||||
clearTimeout(polling);
|
|
||||||
|
|
||||||
getPlexOAuthURL().then(function (data) {
|
|
||||||
const url = data.url;
|
|
||||||
const pin = data.pin;
|
|
||||||
var keep_polling = true;
|
|
||||||
|
|
||||||
window.open(url);
|
|
||||||
|
|
||||||
(function poll() {
|
|
||||||
polling = setTimeout(function () {
|
|
||||||
$.ajax({
|
|
||||||
url: 'https://plex.tv/api/v2/pins/' + pin,
|
|
||||||
type: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-Plex-Product': 'Tautulli',
|
|
||||||
'X-Plex-Version': '${plexpy.common.RELEASE}',
|
|
||||||
'X-Plex-Client-Identifier': '${plexpy.CONFIG.PMS_UUID}',
|
|
||||||
'X-Plex-Platform': '${plexpy.common.PLATFORM}',
|
|
||||||
'X-Plex-Platform-Version': '${plexpy.common.PLATFORM_RELEASE}',
|
|
||||||
'X-Plex-Device': 'Web',
|
|
||||||
'X-Plex-Device-Name': '${plexpy.common.PLATFORM_DEVICE_NAME}'
|
|
||||||
},
|
|
||||||
success: function (data) {
|
|
||||||
if (data.authToken){
|
|
||||||
keep_polling = false;
|
|
||||||
signIn(true, data.authToken);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
keep_polling = false;
|
|
||||||
$('#sign-in-plex-alert').text('Error communicating with Plex.tv.').show();
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
if (keep_polling){
|
|
||||||
poll();
|
|
||||||
} else {
|
|
||||||
clearTimeout(polling);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
timeout: 1000
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
})();
|
|
||||||
}, function () {
|
|
||||||
$('#sign-in-plex-alert').text('Error communicating with Plex.tv.').show();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1863,7 +1863,7 @@ def generate_uuid():
|
||||||
def initialize_tracker():
|
def initialize_tracker():
|
||||||
data = {
|
data = {
|
||||||
'dataSource': 'server',
|
'dataSource': 'server',
|
||||||
'appName': 'Tautulli',
|
'appName': common.PRODUCT,
|
||||||
'appVersion': common.RELEASE,
|
'appVersion': common.RELEASE,
|
||||||
'appId': plexpy.INSTALL_TYPE,
|
'appId': plexpy.INSTALL_TYPE,
|
||||||
'appInstallerId': plexpy.CONFIG.GIT_BRANCH,
|
'appInstallerId': plexpy.CONFIG.GIT_BRANCH,
|
||||||
|
|
|
@ -19,6 +19,7 @@ from collections import OrderedDict
|
||||||
import version
|
import version
|
||||||
|
|
||||||
# Identify Our Application
|
# Identify Our Application
|
||||||
|
PRODUCT = 'Tautulli'
|
||||||
PLATFORM = platform.system()
|
PLATFORM = platform.system()
|
||||||
PLATFORM_RELEASE = platform.release()
|
PLATFORM_RELEASE = platform.release()
|
||||||
PLATFORM_VERSION = platform.version()
|
PLATFORM_VERSION = platform.version()
|
||||||
|
@ -27,7 +28,7 @@ PLATFORM_DEVICE_NAME = platform.node()
|
||||||
BRANCH = version.PLEXPY_BRANCH
|
BRANCH = version.PLEXPY_BRANCH
|
||||||
RELEASE = version.PLEXPY_RELEASE_VERSION
|
RELEASE = version.PLEXPY_RELEASE_VERSION
|
||||||
|
|
||||||
USER_AGENT = 'Tautulli/{} ({} {})'.format(RELEASE, PLATFORM, PLATFORM_RELEASE)
|
USER_AGENT = '{}/{} ({} {})'.format(PRODUCT, RELEASE, PLATFORM, PLATFORM_RELEASE)
|
||||||
|
|
||||||
DEFAULT_USER_THUMB = "interfaces/default/images/gravatar-default-80x80.png"
|
DEFAULT_USER_THUMB = "interfaces/default/images/gravatar-default-80x80.png"
|
||||||
DEFAULT_POSTER_THUMB = "interfaces/default/images/poster.png"
|
DEFAULT_POSTER_THUMB = "interfaces/default/images/poster.png"
|
||||||
|
|
|
@ -39,7 +39,7 @@ class HTTPHandler(object):
|
||||||
else:
|
else:
|
||||||
self.urls = urls
|
self.urls = urls
|
||||||
|
|
||||||
self.headers = {'X-Plex-Product': 'Tautulli',
|
self.headers = {'X-Plex-Product': plexpy.common.PRODUCT,
|
||||||
'X-Plex-Version': plexpy.common.RELEASE,
|
'X-Plex-Version': plexpy.common.RELEASE,
|
||||||
'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID,
|
'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID,
|
||||||
'X-Plex-Platform': plexpy.common.PLATFORM,
|
'X-Plex-Platform': plexpy.common.PLATFORM,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue