mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-11 16:44:05 +02:00
Major restructuring to how ACLs will work. Disable dialog box again, for
now.
This commit is contained in:
@@ -43,9 +43,10 @@ ACLRegistry::ACLRegistry( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
s_instance = this;
|
||||
qRegisterMetaType< ACLRegistry::ACL >("ACLRegistry::ACL");
|
||||
qRegisterMetaType< ACLRegistry::ACL >( "ACLRegistry::ACL" );
|
||||
qRegisterMetaType< ACLRegistry::User >( "ACLRegistry::User" );
|
||||
|
||||
m_cache = TomahawkSettings::instance()->aclEntries();
|
||||
load();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,174 +56,77 @@ ACLRegistry::~ACLRegistry()
|
||||
|
||||
|
||||
void
|
||||
ACLRegistry::isAuthorizedPeer( const QString& dbid, ACLRegistry::ACL globalType, const QString &username )
|
||||
ACLRegistry::isAuthorizedUser( const QString& dbid, const QString &username, ACLRegistry::ACL globalType )
|
||||
{
|
||||
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
||||
{
|
||||
emit aclResult( dbid, globalType );
|
||||
emit aclResult( dbid, username, globalType );
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Current cache keys =" << m_cache.keys();
|
||||
if( m_cache.contains( dbid ) )
|
||||
bool found = false;
|
||||
QMutableListIterator< ACLRegistry::User > i( m_cache );
|
||||
while ( i.hasNext() )
|
||||
{
|
||||
QVariantHash peerHash = m_cache[ dbid ].toHash();
|
||||
if( peerHash.contains( "global" ) )
|
||||
ACLRegistry::User user = i.next();
|
||||
foreach ( QString knowndbid, user.knownDbids )
|
||||
{
|
||||
registerAlias( dbid, username );
|
||||
emit aclResult( dbid, ACLRegistry::ACL( peerHash[ "global" ].toInt() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( globalType == ACLRegistry::NotFound )
|
||||
if ( dbid == knowndbid )
|
||||
{
|
||||
emit aclResult( dbid, globalType );
|
||||
return;
|
||||
if ( !user.knownAccountIds.contains( username ) )
|
||||
user.knownAccountIds.append( username );
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
peerHash[ "global" ] = int( globalType );
|
||||
m_cache[ dbid ] = peerHash;
|
||||
save();
|
||||
registerAlias( dbid, username );
|
||||
emit aclResult( dbid, globalType );
|
||||
return;
|
||||
foreach ( QString knownaccountid, user.knownAccountIds )
|
||||
{
|
||||
if ( username == knownaccountid )
|
||||
{
|
||||
if ( !user.knownDbids.contains( dbid ) )
|
||||
user.knownDbids.append( dbid );
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( found )
|
||||
{
|
||||
emit aclResult( dbid, username, user.acl );
|
||||
i.setValue( user );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// User was not found, create a new user entry
|
||||
ACLRegistry::User user;
|
||||
user.knownDbids.append( dbid );
|
||||
user.knownAccountIds.append( username );
|
||||
if ( globalType != ACLRegistry::NotFound )
|
||||
user.acl = globalType;
|
||||
else
|
||||
{
|
||||
ACLRegistry::ACL acl = globalType;
|
||||
tDebug( LOGVERBOSE ) << "ACL is intially" << acl;
|
||||
#ifndef ENABLE_HEADLESS
|
||||
#ifndef ENABLE_HEADLESS
|
||||
acl = getUserDecision( username );
|
||||
tDebug( LOGVERBOSE ) << "after getUserDecision acl is" << acl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ( acl == ACLRegistry::NotFound || acl == ACLRegistry::AllowOnce || acl == ACLRegistry::DenyOnce )
|
||||
if ( acl == ACLRegistry::NotFound )
|
||||
{
|
||||
emit aclResult( dbid, acl );
|
||||
emit aclResult( dbid, username, acl );
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantHash peerHash;
|
||||
peerHash[ "global" ] = int( acl );
|
||||
m_cache[ dbid ] = peerHash;
|
||||
save();
|
||||
registerAlias( dbid, username );
|
||||
emit aclResult( dbid, acl );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ACLRegistry::registerPeer( const QString& dbid, ACLRegistry::ACL globalType, const QString &username )
|
||||
{
|
||||
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
||||
return;
|
||||
|
||||
if ( globalType == ACLRegistry::NotFound || globalType == ACLRegistry::DenyOnce || globalType == ACLRegistry::AllowOnce )
|
||||
return;
|
||||
|
||||
QVariantHash peerHash;
|
||||
if ( m_cache.contains( dbid ) )
|
||||
peerHash = m_cache[ dbid ].toHash();
|
||||
peerHash[ "global" ] = int( globalType );
|
||||
m_cache[ dbid ] = peerHash;
|
||||
save();
|
||||
registerAlias( dbid, username );
|
||||
}
|
||||
|
||||
|
||||
QPair< QString, ACLRegistry::ACL >
|
||||
ACLRegistry::isAuthorizedUser( const QString &username, ACLRegistry::ACL globalType )
|
||||
{
|
||||
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
||||
return QPair< QString, ACLRegistry::ACL >( QString(), ACLRegistry::NotFound );
|
||||
|
||||
qDebug() << "Current cache keys =" << m_cache.keys();
|
||||
foreach ( QString dbid, m_cache.keys() )
|
||||
{
|
||||
// qDebug() << "Looking up dbid";
|
||||
QVariantHash peerHash = m_cache[ dbid ].toHash();
|
||||
if ( !peerHash.contains( "usernames" ) )
|
||||
continue;
|
||||
|
||||
if ( !peerHash[ "usernames" ].toStringList().contains( username ) )
|
||||
continue;
|
||||
|
||||
if ( globalType != ACLRegistry::NotFound )
|
||||
{
|
||||
peerHash[ "global" ] = int( globalType );
|
||||
m_cache[ dbid ] = peerHash;
|
||||
save();
|
||||
return QPair< QString, ACLRegistry::ACL >( dbid, globalType );
|
||||
user.acl = acl;
|
||||
}
|
||||
|
||||
return QPair< QString, ACLRegistry::ACL >( dbid, ACLRegistry::ACL( peerHash[ "global" ].toInt() ) );
|
||||
}
|
||||
|
||||
return QPair< QString, ACLRegistry::ACL >( QString(), ACLRegistry::NotFound );
|
||||
m_cache.append( user );
|
||||
emit aclResult( dbid, username, user.acl );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ACLRegistry::registerAlias( const QString& dbid, const QString &username )
|
||||
{
|
||||
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
||||
return;
|
||||
|
||||
if ( dbid.isEmpty() || username.isEmpty() )
|
||||
return;
|
||||
|
||||
if ( !m_cache.contains( dbid ) )
|
||||
return;
|
||||
|
||||
QVariantHash peerHash = m_cache[ dbid ].toHash();
|
||||
if ( !peerHash.contains( "usernames" ) )
|
||||
peerHash[ "usernames" ] = QStringList( username );
|
||||
else if ( !peerHash[ "usernames" ].toStringList().contains( username ) )
|
||||
peerHash[ "usernames" ] = peerHash[ "usernames" ].toStringList() + QStringList( username );
|
||||
else
|
||||
return;
|
||||
|
||||
m_cache[ dbid ] = peerHash;
|
||||
save();
|
||||
}
|
||||
|
||||
|
||||
// ACLRegistry::ACL
|
||||
// ACLRegistry::isAuthorizedPath( const QString& dbid, const QString& path )
|
||||
// {
|
||||
// QMutexLocker locker( &m_cacheMutex );
|
||||
//
|
||||
// if( !m_cache.contains( dbid ) )
|
||||
// return ACLRegistry::NotFound;
|
||||
//
|
||||
// QHash< QString, ACL > peerHash = m_cache[dbid];
|
||||
// if( !peerHash.contains( path ) )
|
||||
// {
|
||||
// if( peerHash.contains( "global" ) )
|
||||
// return peerHash["global"];
|
||||
// else
|
||||
// return ACLRegistry::Deny;
|
||||
// }
|
||||
// return peerHash[path];
|
||||
// }
|
||||
//
|
||||
// void
|
||||
// ACLRegistry::authorizePath( const QString& dbid, const QString& path, ACLRegistry::ACL type )
|
||||
// {
|
||||
// TomahawkSettings *s = TomahawkSettings::instance();
|
||||
// if( !s->scannerPaths().contains( path ) )
|
||||
// {
|
||||
// qDebug() << "path selected is not in our scanner path!";
|
||||
// return;
|
||||
// }
|
||||
// QMutexLocker locker( &m_cacheMutex );
|
||||
// QHash< QString, ACLRegistry::ACL > peerHash;
|
||||
// if ( m_cache.contains( dbid ) )
|
||||
// peerHash = m_cache[dbid];
|
||||
// peerHash[path] = type;
|
||||
// m_cache[dbid] = peerHash;
|
||||
// }
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
|
||||
#include <QMessageBox>
|
||||
@@ -230,14 +134,13 @@ ACLRegistry::registerAlias( const QString& dbid, const QString &username )
|
||||
ACLRegistry::ACL
|
||||
ACLRegistry::getUserDecision( const QString &username )
|
||||
{
|
||||
return ACLRegistry::Stream;
|
||||
QMessageBox msgBox;
|
||||
msgBox.setIcon( QMessageBox::Question );
|
||||
msgBox.setText( tr( "Connect to Peer?" ) );
|
||||
msgBox.setInformativeText( tr( "Another Tomahawk instance that claims to be owned by %1 is attempting to connect to you. Select whether to allow or deny this connection.\n\nRemember: Only allow peers to connect if you trust who they are and if you have the legal right for them to stream music from you.").arg( username ) );
|
||||
QPushButton *denyButton = msgBox.addButton( tr( "Deny" ), QMessageBox::HelpRole );
|
||||
QPushButton *alwaysDenyButton = msgBox.addButton( tr( "Always Deny" ), QMessageBox::YesRole );
|
||||
QPushButton *allowButton = msgBox.addButton( tr( "Allow" ), QMessageBox::NoRole );
|
||||
QPushButton *alwaysAllowButton = msgBox.addButton( tr( "Always Allow" ), QMessageBox::ActionRole );
|
||||
QPushButton *denyButton = msgBox.addButton( tr( "Deny" ), QMessageBox::YesRole );
|
||||
QPushButton *allowButton = msgBox.addButton( tr( "Allow" ), QMessageBox::ActionRole );
|
||||
|
||||
msgBox.setDefaultButton( allowButton );
|
||||
msgBox.setEscapeButton( denyButton );
|
||||
@@ -245,13 +148,9 @@ ACLRegistry::getUserDecision( const QString &username )
|
||||
msgBox.exec();
|
||||
|
||||
if( msgBox.clickedButton() == denyButton )
|
||||
return ACLRegistry::DenyOnce;
|
||||
else if( msgBox.clickedButton() == alwaysDenyButton )
|
||||
return ACLRegistry::Deny;
|
||||
else if( msgBox.clickedButton() == allowButton )
|
||||
return ACLRegistry::AllowOnce;
|
||||
else if( msgBox.clickedButton() == alwaysAllowButton )
|
||||
return ACLRegistry::Allow;
|
||||
return ACLRegistry::Stream;
|
||||
|
||||
//How could we get here?
|
||||
tDebug( LOGVERBOSE ) << "ERROR: returning NotFound";
|
||||
@@ -261,8 +160,26 @@ ACLRegistry::getUserDecision( const QString &username )
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
ACLRegistry::load()
|
||||
{
|
||||
QVariantList entryList = TomahawkSettings::instance()->aclEntries();
|
||||
foreach ( QVariant entry, entryList )
|
||||
{
|
||||
if ( !entry.isValid() || !entry.canConvert< ACLRegistry::User >() )
|
||||
continue;
|
||||
ACLRegistry::User entryUser = entry.value< ACLRegistry::User >();
|
||||
m_cache.append( entryUser );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ACLRegistry::save()
|
||||
{
|
||||
TomahawkSettings::instance()->setAclEntries( m_cache );
|
||||
QVariantList entryList;
|
||||
foreach ( ACLRegistry::User user, m_cache )
|
||||
entryList.append( QVariant::fromValue< ACLRegistry::User >( user ) );
|
||||
TomahawkSettings::instance()->setAclEntries( entryList );
|
||||
}
|
@@ -39,46 +39,35 @@ public:
|
||||
static ACLRegistry* instance();
|
||||
|
||||
enum ACL {
|
||||
Allow = 0,
|
||||
NotFound = 0,
|
||||
Deny = 1,
|
||||
NotFound = 2,
|
||||
AllowOnce = 3,
|
||||
DenyOnce = 4
|
||||
Read = 2,
|
||||
Stream = 3
|
||||
};
|
||||
|
||||
struct User {
|
||||
QString uuid;
|
||||
QStringList knownDbids;
|
||||
QStringList knownAccountIds;
|
||||
ACL acl;
|
||||
|
||||
User()
|
||||
: uuid( QUuid::createUuid().toString() )
|
||||
{}
|
||||
|
||||
User( QString p_uuid, QStringList p_knownDbids, QStringList p_knownAccountIds, ACL p_acl )
|
||||
: uuid( p_uuid )
|
||||
, knownDbids( p_knownDbids )
|
||||
, knownAccountIds( p_knownAccountIds )
|
||||
, acl( p_acl )
|
||||
{}
|
||||
};
|
||||
|
||||
ACLRegistry( QObject *parent = 0 );
|
||||
~ACLRegistry();
|
||||
|
||||
/**
|
||||
* @brief Registers the global ACL value for this peer
|
||||
*
|
||||
* @param dbid DBID of peer
|
||||
* @param globalType Global ACL to use for this peer. ACLRegistry::NotFound is invalid and will return immediately.
|
||||
* @param username If not empty, will store the given username along with the new ACL value. Defaults to QString().
|
||||
* @return void
|
||||
**/
|
||||
void registerPeer( const QString &dbid, ACLRegistry::ACL globalType, const QString &username = QString() );
|
||||
|
||||
/**
|
||||
* @brief Checks if peer is authorized, using the username. Optionally, can change authorization of the peer, but only if the peer is found.
|
||||
*
|
||||
* @param username Username for the peer
|
||||
* @param globalType Global ACL to store if peer is found; if ACLRegistry::NotFound, does not change the ACL. Defaults to ACLRegistry::NotFound.
|
||||
* @return QPair< QString, ACLRegistry::ACL >
|
||||
**/
|
||||
QPair< QString, ACLRegistry::ACL > isAuthorizedUser( const QString &username, ACLRegistry::ACL globalType = ACLRegistry::NotFound );
|
||||
|
||||
/**
|
||||
* @brief Registers an alias for a known peer. If you do not know the DBID, you can retrieve it via isAuthorizedUser first.
|
||||
*
|
||||
* @param dbid DBID of peer
|
||||
* @param username Username of the peer to be added to the entry
|
||||
* @return void
|
||||
**/
|
||||
void registerAlias( const QString &dbid, const QString &username );
|
||||
|
||||
signals:
|
||||
void aclResult( QString nodeid, ACLRegistry::ACL peerStatus );
|
||||
void aclResult( QString nodeid, QString username, ACLRegistry::ACL peerStatus );
|
||||
|
||||
public slots:
|
||||
/**
|
||||
@@ -89,16 +78,13 @@ public slots:
|
||||
* @param username If not empty, will store the given username along with the new ACL value. Defaults to QString().
|
||||
* @return ACLRegistry::ACL
|
||||
**/
|
||||
void isAuthorizedPeer( const QString &dbid, ACLRegistry::ACL globalType = ACLRegistry::NotFound, const QString &username = QString() );
|
||||
void isAuthorizedUser( const QString &dbid, const QString &username, ACLRegistry::ACL globalType = ACLRegistry::NotFound );
|
||||
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
ACLRegistry::ACL getUserDecision( const QString &username );
|
||||
#endif
|
||||
|
||||
// ACLRegistry::ACL isAuthorizedPath( const QString &dbid, const QString &path );
|
||||
// void authorizePath( const QString &dbid, const QString &path, ACLRegistry::ACL type );
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Saves the cache.
|
||||
@@ -107,9 +93,14 @@ private:
|
||||
**/
|
||||
void save();
|
||||
|
||||
QVariantHash m_cache;
|
||||
void load();
|
||||
|
||||
QList< ACLRegistry::User > m_cache;
|
||||
|
||||
static ACLRegistry* s_instance;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE( ACLRegistry::ACL );
|
||||
Q_DECLARE_METATYPE( ACLRegistry::User );
|
||||
|
||||
#endif // TOMAHAWK_ACLREGISTRY_H
|
||||
|
@@ -199,20 +199,20 @@ Connection::checkACL()
|
||||
|
||||
QString nodeid = property( "nodeid" ).toString();
|
||||
tDebug( LOGVERBOSE ) << "Checking ACL for" << name();
|
||||
connect( ACLRegistry::instance(), SIGNAL( aclResult( QString, ACLRegistry::ACL ) ), this, SLOT( checkACLResult( QString, ACLRegistry::ACL ) ), Qt::QueuedConnection );
|
||||
QMetaObject::invokeMethod( ACLRegistry::instance(), "isAuthorizedPeer", Qt::QueuedConnection, Q_ARG( QString, nodeid ), Q_ARG( ACLRegistry::ACL, ACLRegistry::NotFound ), Q_ARG( QString, name() ) );
|
||||
connect( ACLRegistry::instance(), SIGNAL( aclResult( QString, QString, ACLRegistry::ACL ) ), this, SLOT( checkACLResult( QString, QString, ACLRegistry::ACL ) ), Qt::QueuedConnection );
|
||||
QMetaObject::invokeMethod( ACLRegistry::instance(), "isAuthorizedUser", Qt::QueuedConnection, Q_ARG( QString, nodeid ), Q_ARG( QString, name() ), Q_ARG( ACLRegistry::ACL, ACLRegistry::NotFound ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Connection::checkACLResult( const QString &nodeid, ACLRegistry::ACL peerStatus )
|
||||
Connection::checkACLResult( const QString &nodeid, const QString &username, ACLRegistry::ACL peerStatus )
|
||||
{
|
||||
if ( nodeid != property( "nodeid" ).toString() )
|
||||
if ( nodeid != property( "nodeid" ).toString() || username != name() )
|
||||
return;
|
||||
|
||||
disconnect( ACLRegistry::instance(), SIGNAL( aclResult( QString, ACLRegistry::ACL ) ) );
|
||||
disconnect( ACLRegistry::instance(), SIGNAL( aclResult( QString, QString, ACLRegistry::ACL ) ) );
|
||||
tDebug( LOGVERBOSE ) << "ACL status is" << peerStatus;
|
||||
if ( peerStatus == ACLRegistry::Allow || peerStatus == ACLRegistry::AllowOnce )
|
||||
if ( peerStatus == ACLRegistry::Stream )
|
||||
{
|
||||
QTimer::singleShot( 0, this, SLOT( doSetup() ) );
|
||||
return;
|
||||
|
@@ -120,7 +120,7 @@ private slots:
|
||||
void readyRead();
|
||||
void doSetup();
|
||||
void checkACL();
|
||||
void checkACLResult( const QString &id, ACLRegistry::ACL peerStatus );
|
||||
void checkACLResult( const QString &nodeid, const QString &username, ACLRegistry::ACL peerStatus );
|
||||
void authCheckTimeout();
|
||||
void bytesWritten( qint64 );
|
||||
void calcStats();
|
||||
|
@@ -628,19 +628,19 @@ TomahawkSettings::setProxyDns( bool lookupViaProxy )
|
||||
}
|
||||
|
||||
|
||||
QVariantHash
|
||||
QVariantList
|
||||
TomahawkSettings::aclEntries() const
|
||||
{
|
||||
QVariant retVal = value( "acl/entries", QVariantHash() );
|
||||
if ( retVal.isValid() && retVal.canConvert< QVariantHash >() )
|
||||
return retVal.toHash();
|
||||
QVariant retVal = value( "acl/entries", QVariantList() );
|
||||
if ( retVal.isValid() && retVal.canConvert< QVariantList >() )
|
||||
return retVal.toList();
|
||||
|
||||
return QVariantHash();
|
||||
return QVariantList();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setAclEntries( const QVariantHash &entries )
|
||||
TomahawkSettings::setAclEntries( const QVariantList &entries )
|
||||
{
|
||||
setValue( "acl/entries", entries );
|
||||
}
|
||||
|
@@ -163,8 +163,8 @@ public:
|
||||
void setProxyDns( bool lookupViaProxy );
|
||||
|
||||
/// ACL settings
|
||||
QVariantHash aclEntries() const;
|
||||
void setAclEntries( const QVariantHash &entries );
|
||||
QVariantList aclEntries() const;
|
||||
void setAclEntries( const QVariantList &entries );
|
||||
|
||||
/// XMPP Component Settings
|
||||
QString xmppBotServer() const;
|
||||
|
Reference in New Issue
Block a user