Refactor Plex OAuth code

This commit is contained in:
JonnyWong16 2018-07-05 09:06:03 -07:00
parent 8514cf1975
commit c0b960bccf
5 changed files with 181 additions and 237 deletions

View file

@ -291,6 +291,7 @@ ${next.modalIncludes()}
<script src="${http_root}js/bootstrap.min.js"></script> <script src="${http_root}js/bootstrap.min.js"></script>
<script src="${http_root}js/bootstrap-hover-dropdown.min.js"></script> <script src="${http_root}js/bootstrap-hover-dropdown.min.js"></script>
<script src="${http_root}js/pnotify.custom.min.js"></script> <script src="${http_root}js/pnotify.custom.min.js"></script>
<script src="${http_root}js/platform.min.js"></script>
<script src="${http_root}js/script.js${cache_param}"></script> <script src="${http_root}js/script.js${cache_param}"></script>
<script src="${http_root}js/jquery.qrcode.min.js"></script> <script src="${http_root}js/jquery.qrcode.min.js"></script>
<script src="${http_root}js/jquery.tripleclick.min.js"></script> <script src="${http_root}js/jquery.tripleclick.min.js"></script>

View file

@ -490,3 +490,144 @@ function PopupCenter(url, title, w, h) {
return newWindow; return newWindow;
} }
if (!localStorage.getItem('Tautulli_ClientId')) {
localStorage.setItem('Tautulli_ClientId', uuidv4());
}
function uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
)
}
var x_plex_headers = {
'Accept': 'application/json',
'X-Plex-Product': '',
'X-Plex-Version': '',
'X-Plex-Client-Identifier': localStorage.getItem('Tautulli_ClientId'),
'X-Plex-Platform': platform.name,
'X-Plex-Platform-Version': platform.version,
'X-Plex-Device': platform.os.toString(),
'X-Plex-Device-Name': platform.name
};
var plex_oauth_window = null;
const plex_oauth_loader = '<style>' +
'.login-loader-container {' +
'font-family: \'Open Sans\', Arial, sans-serif;' +
'position: absolute;' +
'top: 0;' +
'right: 0;' +
'bottom: 0;' +
'left: 0;' +
'}' +
'.login-loader-message {' +
'color: #282A2D;' +
'text-align: center;' +
'position: absolute;' +
'left: 50%;' +
'top: 25%;' +
'transform: translate(-50%, -50%);' +
'}' +
'.login-loader {' +
'border: 5px solid #ccc;' +
'-webkit-animation: spin 1s linear infinite;' +
'animation: spin 1s linear infinite;' +
'border-top: 5px solid #282A2D;' +
'border-radius: 50%;' +
'width: 50px;' +
'height: 50px;' +
'position: relative;' +
'left: calc(50% - 25px);' +
'}' +
'</style>' +
'<div class"login-loader-container">' +
'<div class="login-loader-message">' +
'<div class="login-loader"></div>' +
'<br>' +
'Redirecting to Plex Login...' +
'</div>' +
'</div>';
function closePlexOAuthWindow() {
if (plex_oauth_window) {
plex_oauth_window.close();
}
}
getPlexOAuthPin = function () {
var deferred = $.Deferred();
$.ajax({
url: 'https://plex.tv/api/v2/pins?strong=true',
type: 'POST',
headers: x_plex_headers,
success: function(data) {
plex_oauth_window.location = 'https://app.plex.tv/auth/#!?clientID=' + x_plex_headers['X-Plex-Client-Identifier'] + '&code=' + data.code;
deferred.resolve({pin: data.id, code: data.code});
},
error: function() {
closePlexOAuthWindow();
deferred.reject();
}
});
return deferred;
};
var polling = null;
function PlexOAuth(success, error, pre) {
if (typeof pre === "function") {
pre()
}
clearTimeout(polling);
closePlexOAuthWindow();
plex_oauth_window = PopupCenter('', 'Plex-OAuth', 600, 700);
$(plex_oauth_window.document.body).html(plex_oauth_loader);
getPlexOAuthPin().then(function (data) {
const pin = data.pin;
const code = data.code;
var keep_polling = true;
(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;
closePlexOAuthWindow();
if (typeof success === "function") {
success(data.authToken)
}
}
},
error: function () {
keep_polling = false;
closePlexOAuthWindow();
if (typeof error === "function") {
error()
}
},
complete: function () {
if (keep_polling){
poll();
} else {
clearTimeout(polling);
}
},
timeout: 1000
});
}, 1000);
})();
}, function () {
closePlexOAuthWindow();
if (typeof error === "function") {
error()
}
});
}

View file

@ -116,90 +116,17 @@
<script> <script>
var login_accordion = new Accordion($('#login-methods'), false, false); var login_accordion = new Accordion($('#login-methods'), false, false);
if (!localStorage.getItem('Tautulli_ClientId')) { function OAuthSuccessCallback(authToken) {
localStorage.setItem('Tautulli_ClientId', uuidv4()); signIn(true, authToken);
}
function OAuthErrorCallback() {
$('#sign-in-alert').text('Error communicating with Plex.tv.').show();
} }
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': localStorage.getItem('Tautulli_ClientId'),
'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() { $('#sign-in-plex').click(function() {
clearTimeout(polling); x_plex_headers['X-Plex-Product'] = '${plexpy.common.PRODUCT}';
x_plex_headers['X-Plex-Version'] = '${plexpy.common.RELEASE}';
getPlexOAuthPin().then(function (data) { PlexOAuth(OAuthSuccessCallback, OAuthErrorCallback);
const pin = data.pin;
const code = data.code;
var keep_polling = true;
var plex_oauth_window = PopupCenter(
'https://app.plex.tv/auth/#!?clientID=' + x_plex_headers['X-Plex-Client-Identifier'] + '&code=' + code,
'Plex-OAuth', 600, 700);
(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;
if (plex_oauth_window) {
plex_oauth_window.close();
}
signIn(true, data.authToken);
}
},
error: function () {
keep_polling = false;
$('#sign-in-alert').text('Error communicating with Plex.tv.').show();
},
complete: function () {
if (keep_polling){
poll();
} else {
clearTimeout(polling);
}
},
timeout: 1000
});
}, 1000);
})();
}, function () {
$('#sign-in-alert').text('Error communicating with Plex.tv.').show();
});
}); });
$('#login-form').submit(function(event) { $('#login-form').submit(function(event) {

View file

@ -2255,86 +2255,23 @@ $(document).ready(function() {
window.open(pms_web_url, '_blank'); window.open(pms_web_url, '_blank');
}); });
const x_plex_headers = { function OAuthPreFunction() {
'Accept': 'application/json',
'X-Plex-Product': '${plexpy.common.PRODUCT}',
'X-Plex-Version': '${plexpy.common.RELEASE}',
'X-Plex-Client-Identifier': '${plexpy.generate_uuid()}',
'X-Plex-Platform': '${plexpy.common.PLATFORM}',
'X-Plex-Platform-Version': '${plexpy.common.PLATFORM_RELEASE}',
'X-Plex-Device': '${plexpy.common.PLATFORM} ${plexpy.common.PLATFORM_RELEASE}',
'X-Plex-Device-Name': '${plexpy.common.PLATFORM_DEVICE_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() {
$("#token_verify").html('<i class="fa fa-refresh fa-spin"></i>').fadeIn('fast'); $("#token_verify").html('<i class="fa fa-refresh fa-spin"></i>').fadeIn('fast');
clearTimeout(polling);
getPlexOAuthPin().then(function (data) {
const pin = data.pin;
const code = data.code;
var keep_polling = true;
var plex_oauth_window = PopupCenter(
'https://app.plex.tv/auth/#!?clientID=' + x_plex_headers['X-Plex-Client-Identifier'] + '&code=' + code,
'Plex-OAuth', 600, 700);
(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){
var authToken = data.authToken;
keep_polling = false;
if (plex_oauth_window) {
plex_oauth_window.close();
} }
function OAuthSuccessCallback(authToken) {
$("#pms_token").val(authToken); $("#pms_token").val(authToken);
$("#pms_uuid").val(x_plex_headers['X-Plex-Client-Identifier']); $("#pms_uuid").val(x_plex_headers['X-Plex-Client-Identifier']);
$("#token_verify").html('<i class="fa fa-check"></i>').fadeIn('fast'); $("#token_verify").html('<i class="fa fa-check"></i>').fadeIn('fast');
getServerOptions(authToken) getServerOptions(authToken);
} }
}, function OAuthErrorCallback() {
error: function () {
keep_polling = false;
$("#token_verify").html('<i class="fa fa-close"></i>').fadeIn('fast'); $("#token_verify").html('<i class="fa fa-close"></i>').fadeIn('fast');
},
complete: function () {
if (keep_polling){
poll();
} else {
clearTimeout(polling);
} }
},
timeout: 1000 $('#sign-in-plex').click(function() {
}); x_plex_headers['X-Plex-Product'] = '${plexpy.common.PRODUCT}';
}, 1000); x_plex_headers['X-Plex-Version'] = '${plexpy.common.RELEASE}';
})(); PlexOAuth(OAuthSuccessCallback, OAuthErrorCallback, OAuthPreFunction);
}, function () {
$("#token_verify").html('<i class="fa fa-close"></i>').fadeIn('fast');
});
}); });
// Load database import modal // Load database import modal

View file

@ -212,6 +212,7 @@
<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/bootstrap.min.js"></script> <script src="${http_root}js/bootstrap.min.js"></script>
<script src="${http_root}js/selectize.min.js"></script> <script src="${http_root}js/selectize.min.js"></script>
<script src="${http_root}js/platform.min.js"></script>
<script src="${http_root}js/script.js${cache_param}"></script> <script src="${http_root}js/script.js${cache_param}"></script>
<script src="${http_root}js/bootstrap-wizard.min.js"></script> <script src="${http_root}js/bootstrap-wizard.min.js"></script>
<script> <script>
@ -467,87 +468,24 @@ $(document).ready(function() {
$("#pms-verify-status").html(""); $("#pms-verify-status").html("");
}); });
const x_plex_headers = { function OAuthPreFunction() {
'Accept': 'application/json',
'X-Plex-Product': '${plexpy.common.PRODUCT}',
'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': '${plexpy.common.PLATFORM} ${plexpy.common.PLATFORM_RELEASE}',
'X-Plex-Device-Name': '${plexpy.common.PLATFORM_DEVICE_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() {
$("#pms_token").val(''); $("#pms_token").val('');
$("#pms-token-status").html('<i class="fa fa-refresh fa-spin"></i>&nbsp; Waiting for authentication...').fadeIn('fast'); $("#pms-token-status").html('<i class="fa fa-refresh fa-spin"></i>&nbsp; Waiting for authentication...').fadeIn('fast');
clearTimeout(polling);
getPlexOAuthPin().then(function (data) {
const pin = data.pin;
const code = data.code;
var keep_polling = true;
var plex_oauth_window = PopupCenter(
'https://app.plex.tv/auth/#!?clientID=' + x_plex_headers['X-Plex-Client-Identifier'] + '&code=' + code,
'Plex-OAuth', 600, 700);
(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){
var authToken = data.authToken;
keep_polling = false;
if (plex_oauth_window) {
plex_oauth_window.close();
} }
function OAuthSuccessCallback(authToken) {
$("#pms_token").val(authToken); $("#pms_token").val(authToken);
$("#pms-token-status").html('<i class="fa fa-check"></i>&nbsp; Authentication successful.').fadeIn('fast'); $("#pms-token-status").html('<i class="fa fa-check"></i>&nbsp; Authentication successful.').fadeIn('fast');
authenticated = true; authenticated = true;
getServerOptions(authToken) getServerOptions(authToken);
} }
}, function OAuthErrorCallback() {
error: function () {
keep_polling = false;
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i>&nbsp; Error communicating with Plex.tv.').fadeIn('fast'); $("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i>&nbsp; Error communicating with Plex.tv.').fadeIn('fast');
},
complete: function () {
if (keep_polling){
poll();
} else {
clearTimeout(polling);
} }
},
timeout: 1000 $('#sign-in-plex').click(function() {
}); x_plex_headers['X-Plex-Product'] = '${plexpy.common.PRODUCT}';
}, 1000); x_plex_headers['X-Plex-Version'] = '${plexpy.common.RELEASE}';
})(); PlexOAuth(OAuthSuccessCallback, OAuthErrorCallback, OAuthPreFunction);
}, function () {
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i>&nbsp; Error communicating with Plex.tv.').fadeIn('fast');
});
}); });
}); });
</script> </script>