diff --git a/mopidy/frontends/mpd/exceptions.py b/mopidy/frontends/mpd/exceptions.py index 2a18b2f3..53a31dd9 100644 --- a/mopidy/frontends/mpd/exceptions.py +++ b/mopidy/frontends/mpd/exceptions.py @@ -39,6 +39,11 @@ class MpdArgError(MpdAckError): super(MpdArgError, self).__init__(*args, **kwargs) self.error_code = 2 # ACK_ERROR_ARG +class MpdPasswordError(MpdAckError): + def __init__(self, *args, **kwargs): + super(MpdPasswordError, self).__init__(*args, **kwargs) + self.error_code = 3 # ACK_ERROR_PASSWORD + class MpdUnknownCommand(MpdAckError): def __init__(self, *args, **kwargs): super(MpdUnknownCommand, self).__init__(*args, **kwargs) diff --git a/mopidy/frontends/mpd/protocol/connection.py b/mopidy/frontends/mpd/protocol/connection.py index 0ce3ef51..65811d09 100644 --- a/mopidy/frontends/mpd/protocol/connection.py +++ b/mopidy/frontends/mpd/protocol/connection.py @@ -1,5 +1,6 @@ +from mopidy import settings from mopidy.frontends.mpd.protocol import handle_pattern -from mopidy.frontends.mpd.exceptions import MpdNotImplemented +from mopidy.frontends.mpd.exceptions import MpdPasswordError @handle_pattern(r'^close$') def close(frontend): @@ -33,7 +34,11 @@ def password_(frontend, password): This is used for authentication with the server. ``PASSWORD`` is simply the plaintext password. """ - raise MpdNotImplemented # TODO + # You will not get to this code without being authenticated. This is for + # when you are already authenticated, and are sending additional 'password' + # requests. + if settings.MPD_SERVER_PASSWORD != password: + raise MpdPasswordError(u'incorrect password', command=u'password') @handle_pattern(r'^ping$') def ping(frontend): diff --git a/tests/frontends/mpd/connection_test.py b/tests/frontends/mpd/connection_test.py index 21753054..e7bb74de 100644 --- a/tests/frontends/mpd/connection_test.py +++ b/tests/frontends/mpd/connection_test.py @@ -1,5 +1,6 @@ import unittest +from mopidy import settings from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher from mopidy.mixers.dummy import DummyMixer @@ -9,6 +10,9 @@ class ConnectionHandlerTest(unittest.TestCase): self.b = DummyBackend(mixer_class=DummyMixer) self.h = dispatcher.MpdDispatcher(backend=self.b) + def tearDown(self): + settings.runtime.clear() + def test_close(self): result = self.h.handle_request(u'close') self.assert_(u'OK' in result) @@ -21,9 +25,20 @@ class ConnectionHandlerTest(unittest.TestCase): result = self.h.handle_request(u'kill') self.assert_(u'OK' in result) - def test_password(self): + def test_valid_password_is_accepted(self): + settings.MPD_SERVER_PASSWORD = u'topsecret' + result = self.h.handle_request(u'password "topsecret"') + self.assert_(u'OK' in result) + + def test_invalid_password_is_not_accepted(self): + settings.MPD_SERVER_PASSWORD = u'topsecret' result = self.h.handle_request(u'password "secret"') - self.assert_(u'ACK [0@0] {} Not implemented' in result) + self.assert_(u'ACK [3@0] {password} incorrect password' in result) + + def test_any_password_is_not_accepted_when_password_check_turned_off(self): + settings.MPD_SERVER_PASSWORD = False + result = self.h.handle_request(u'password "secret"') + self.assert_(u'ACK [3@0] {password} incorrect password' in result) def test_ping(self): result = self.h.handle_request(u'ping')