Building permission-checker for system functions
This commit is contained in:
@ -1 +1 @@
|
||||
3.17.1
|
||||
3.17.3
|
||||
@ -473,6 +473,7 @@ class IrisCore(object):
|
||||
else:
|
||||
return response
|
||||
|
||||
|
||||
def get_version(self, *args, **kwargs):
|
||||
callback = kwargs.get('callback', False)
|
||||
url = 'https://pypi.python.org/pypi/Mopidy-Iris/json'
|
||||
@ -504,11 +505,28 @@ class IrisCore(object):
|
||||
else:
|
||||
return response
|
||||
|
||||
|
||||
def upgrade(self, *args, **kwargs):
|
||||
logger.info("Upgrading")
|
||||
|
||||
callback = kwargs.get('callback', False)
|
||||
|
||||
try:
|
||||
self.check_system_access()
|
||||
except Exception, e:
|
||||
logger.error(e)
|
||||
|
||||
error = {
|
||||
'message': "Permission denied",
|
||||
'description': str(e)
|
||||
}
|
||||
|
||||
if (callback):
|
||||
callback(False, error)
|
||||
return
|
||||
else:
|
||||
return error
|
||||
|
||||
self.broadcast(data={
|
||||
'method': "upgrading",
|
||||
'params': {}
|
||||
@ -516,24 +534,6 @@ class IrisCore(object):
|
||||
|
||||
# Run the system task
|
||||
path = os.path.dirname(__file__)
|
||||
|
||||
# Make sure we can run as sudo without password
|
||||
# TODO: Test cross-platform??
|
||||
permission_check = str(subprocess.call(["sudo -n "+path+"/system.sh"], shell=True)).lower()
|
||||
if "password is required" in permission_check:
|
||||
|
||||
logger.error("Upgrade failed: Permission denied. Password-less access to "+path+"/system.sh was refused. Check your /etc/sudoers file.")
|
||||
|
||||
error = {
|
||||
'message': "Permission denied",
|
||||
'description': "Password-less access to "+path+"/system.sh was refused. Check your /etc/sudoers file."
|
||||
}
|
||||
|
||||
if (callback):
|
||||
callback(False, error)
|
||||
return
|
||||
else:
|
||||
return error
|
||||
|
||||
# Attempt the upgrade
|
||||
upgrade_process = subprocess.Popen("sudo "+path+"/system.sh upgrade", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
@ -578,9 +578,25 @@ class IrisCore(object):
|
||||
|
||||
def restart(self, *args, **kwargs):
|
||||
logger.info("Restarting")
|
||||
|
||||
callback = kwargs.get('callback', False)
|
||||
|
||||
try:
|
||||
self.check_system_access()
|
||||
except Exception, e:
|
||||
logger.error(e)
|
||||
|
||||
error = {
|
||||
'message': "Permission denied",
|
||||
'description': str(e)
|
||||
}
|
||||
|
||||
if (callback):
|
||||
callback(False, error)
|
||||
return
|
||||
else:
|
||||
return error
|
||||
|
||||
|
||||
self.broadcast(data={
|
||||
'method': "restarting",
|
||||
'params': {}
|
||||
@ -588,22 +604,6 @@ class IrisCore(object):
|
||||
|
||||
path = os.path.dirname(__file__)
|
||||
|
||||
# Make sure we can run as sudo without password
|
||||
# TODO: Test cross-platform??
|
||||
permission_check = str(subprocess.call(["sudo -n "+path+"/system.sh"], shell=True)).lower()
|
||||
if "password is required" in permission_check:
|
||||
error = {
|
||||
'message': "Permission denied",
|
||||
'data': {
|
||||
'description': "Password-less access to "+path+"/system.sh was refused. Check your /etc/sudoers file."
|
||||
}
|
||||
}
|
||||
if (callback):
|
||||
callback(False, error)
|
||||
return
|
||||
else:
|
||||
return error
|
||||
|
||||
subprocess.Popen(["sudo "+path+"/system.sh restart 0"], shell=True)
|
||||
|
||||
response = {
|
||||
@ -1019,16 +1019,55 @@ class IrisCore(object):
|
||||
|
||||
|
||||
##
|
||||
# Simple test method
|
||||
# Check if we have access to the system script (system.sh)
|
||||
#
|
||||
# @return boolean or exception
|
||||
##
|
||||
def check_system_access(self, *args, **kwargs):
|
||||
callback = kwargs.get('callback', None)
|
||||
|
||||
# Run the system task
|
||||
path = os.path.dirname(__file__)
|
||||
|
||||
# Attempt the upgrade
|
||||
process = subprocess.Popen("sudo -n "+path+"/system.sh", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
result, error = process.communicate()
|
||||
exitCode = process.wait()
|
||||
|
||||
if exitCode > 0:
|
||||
raise Exception("Password-less access to "+path+"/system.sh was refused. Check your /etc/sudoers file.")
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
##
|
||||
# Simple test method. Not for use in production for any purposes.
|
||||
##
|
||||
def test(self, *args, **kwargs):
|
||||
callback = kwargs.get('callback', None)
|
||||
data = kwargs.get('data', {})
|
||||
|
||||
if data and 'force_error' in data:
|
||||
callback(False, {'message': "Could not sleep, forced error"})
|
||||
try:
|
||||
self.check_system_access()
|
||||
except Exception, e:
|
||||
logger.error(e)
|
||||
|
||||
error = {
|
||||
'message': "Permission denied",
|
||||
'description': str(e)
|
||||
}
|
||||
|
||||
if (callback):
|
||||
callback(False, error)
|
||||
return
|
||||
else:
|
||||
return error
|
||||
|
||||
response = {
|
||||
'message': "Permission granted"
|
||||
}
|
||||
|
||||
if (callback):
|
||||
callback(response)
|
||||
return
|
||||
else:
|
||||
time.sleep(1)
|
||||
callback({'message': "Slept for one second"}, False)
|
||||
return
|
||||
return response
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -73,7 +73,7 @@
|
||||
|
||||
// Release details
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1524301303";
|
||||
var build = "1524428502";
|
||||
var version = "3.17.1";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
@ -24,21 +24,31 @@ const PusherMiddleware = (function(){
|
||||
console.log('Pusher log (incoming)', message);
|
||||
}
|
||||
|
||||
// Pull our ID. JSON-RPC nests the ID under the error object,
|
||||
// so make sure we handle that.
|
||||
// TODO: Use this as our measure of a successful response vs error
|
||||
var id = null;
|
||||
if (message.id){
|
||||
id = message.id;
|
||||
} else if (message.error && message.error.id){
|
||||
id = message.error.id;
|
||||
}
|
||||
|
||||
// Response with request_id
|
||||
if (message.id !== undefined && message.id){
|
||||
if (id){
|
||||
|
||||
// Response matches a pending request
|
||||
if (deferredRequests[message.id] !== undefined){
|
||||
if (deferredRequests[id] !== undefined){
|
||||
|
||||
store.dispatch(uiActions.stopLoading(message.id));
|
||||
store.dispatch(uiActions.stopLoading(id));
|
||||
|
||||
// Response is an error
|
||||
if (message.error !== undefined){
|
||||
deferredRequests[message.id].reject(message.error);
|
||||
deferredRequests[id].reject(message.error);
|
||||
|
||||
// Successful response
|
||||
} else {
|
||||
deferredRequests[message.id].resolve(message.result);
|
||||
deferredRequests[id].resolve(message.result);
|
||||
}
|
||||
|
||||
// Hmm, the response doesn't appear to be for us?
|
||||
@ -54,10 +64,10 @@ const PusherMiddleware = (function(){
|
||||
|
||||
// Broadcast of an error
|
||||
if (message.error !== undefined){
|
||||
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Pusher: '+message.error.message,
|
||||
message
|
||||
message,
|
||||
(message.error.data !== undefined && message.error.data.description !== undefined ? message.error.data.description : null)
|
||||
));
|
||||
|
||||
} else {
|
||||
@ -110,10 +120,6 @@ const PusherMiddleware = (function(){
|
||||
const request = (store, method, params = null) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
if (store.getState().ui.log_pusher){
|
||||
console.log('Pusher log (outgoing)', {method: method, params: params});
|
||||
}
|
||||
|
||||
var id = helpers.generateGuid();
|
||||
var message = {
|
||||
jsonrpc: '2.0',
|
||||
@ -123,11 +129,16 @@ const PusherMiddleware = (function(){
|
||||
if (params){
|
||||
message.params = params;
|
||||
}
|
||||
|
||||
if (store.getState().ui.log_pusher){
|
||||
console.log('Pusher log (outgoing)', message);
|
||||
}
|
||||
|
||||
socket.send(JSON.stringify(message));
|
||||
|
||||
store.dispatch(uiActions.startLoading(id, 'pusher_'+method));
|
||||
|
||||
// Start our 15 second timeout
|
||||
// Start our 30 second timeout
|
||||
var timeout = setTimeout(
|
||||
function(){
|
||||
store.dispatch(uiActions.stopLoading(id));
|
||||
@ -499,7 +510,7 @@ const PusherMiddleware = (function(){
|
||||
store.dispatch(mopidyActions.upgrading());
|
||||
},
|
||||
error => {
|
||||
store.dispatch(uiActions.createNotification({content: error.message, type: 'bad'}));
|
||||
store.dispatch(uiActions.createNotification({content: error.message, description: (error.description ? error.description : null), type: 'bad'}));
|
||||
}
|
||||
);
|
||||
break;
|
||||
@ -517,21 +528,25 @@ const PusherMiddleware = (function(){
|
||||
|
||||
// Set default country/locale (unless we've already been configured)
|
||||
var spotify = store.getState().spotify;
|
||||
var spotify_updated = false;
|
||||
var spotify_updates = {};
|
||||
|
||||
if (!spotify.country && action.config.country){
|
||||
spotify_updates.country = action.config.country;
|
||||
spotify_updated = true;
|
||||
}
|
||||
|
||||
if (!spotify.locale && action.config.locale){
|
||||
spotify_updates.locale = action.config.locale;
|
||||
spotify_updated = true;
|
||||
}
|
||||
|
||||
if (action.config.spotify_authorization_url){
|
||||
spotify_updates.authorization_url = action.config.authorization_url;
|
||||
spotify_updated = true;
|
||||
}
|
||||
|
||||
if (spotify_updates !== {}){
|
||||
if (spotify_updated){
|
||||
store.dispatch(spotifyActions.set(spotify_updates));
|
||||
}
|
||||
|
||||
|
||||
@ -153,7 +153,7 @@ class Settings extends React.Component {
|
||||
} else if (this.props.pusher.version.upgrade_available){
|
||||
var upgrade_button = <button className="alternative" onClick={e => this.props.pusherActions.upgrade()}>Upgrade to { this.props.pusher.version.latest }</button>;
|
||||
} else {
|
||||
var upgrade_button = <button className="alternative" onClick={e => this.props.pusherActions.upgrade()}>Already up-to-date</button>;
|
||||
var upgrade_button = null;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -271,7 +271,7 @@ class Settings extends React.Component {
|
||||
<div className="name">Version</div>
|
||||
<div className="input">
|
||||
<span className="text">
|
||||
{this.props.pusher.version.current} installed {this.props.pusher.version.upgrade_available ? <span className="flag blue">Upgrade available</span> : null}
|
||||
{this.props.pusher.version.current} installed {this.props.pusher.version.upgrade_available ? <span className="flag blue">Upgrade available</span> : <span className="flag grey">Up-to-date</span>}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user