Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

portal.py 5.3KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. # -*- test-case-name: twisted.cred.test.test_cred -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. The point of integration of application and authentication.
  6. """
  7. from zope.interface import Interface, providedBy
  8. from twisted.cred import error
  9. from twisted.internet import defer
  10. from twisted.internet.defer import maybeDeferred
  11. from twisted.python import failure, reflect
  12. class IRealm(Interface):
  13. """
  14. The realm connects application-specific objects to the
  15. authentication system.
  16. """
  17. def requestAvatar(avatarId, mind, *interfaces):
  18. """
  19. Return avatar which provides one of the given interfaces.
  20. @param avatarId: a string that identifies an avatar, as returned by
  21. L{ICredentialsChecker.requestAvatarId<twisted.cred.checkers.ICredentialsChecker.requestAvatarId>}
  22. (via a Deferred). Alternatively, it may be
  23. C{twisted.cred.checkers.ANONYMOUS}.
  24. @param mind: usually None. See the description of mind in
  25. L{Portal.login}.
  26. @param interfaces: the interface(s) the returned avatar should
  27. implement, e.g. C{IMailAccount}. See the description of
  28. L{Portal.login}.
  29. @returns: a deferred which will fire a tuple of (interface,
  30. avatarAspect, logout), or the tuple itself. The interface will be
  31. one of the interfaces passed in the 'interfaces' argument. The
  32. 'avatarAspect' will implement that interface. The 'logout' object
  33. is a callable which will detach the mind from the avatar.
  34. """
  35. class Portal:
  36. """
  37. A mediator between clients and a realm.
  38. A portal is associated with one Realm and zero or more credentials checkers.
  39. When a login is attempted, the portal finds the appropriate credentials
  40. checker for the credentials given, invokes it, and if the credentials are
  41. valid, retrieves the appropriate avatar from the Realm.
  42. This class is not intended to be subclassed. Customization should be done
  43. in the realm object and in the credentials checker objects.
  44. """
  45. def __init__(self, realm, checkers=()):
  46. """
  47. Create a Portal to a L{IRealm}.
  48. """
  49. self.realm = realm
  50. self.checkers = {}
  51. for checker in checkers:
  52. self.registerChecker(checker)
  53. def listCredentialsInterfaces(self):
  54. """
  55. Return list of credentials interfaces that can be used to login.
  56. """
  57. return list(self.checkers.keys())
  58. def registerChecker(self, checker, *credentialInterfaces):
  59. if not credentialInterfaces:
  60. credentialInterfaces = checker.credentialInterfaces
  61. for credentialInterface in credentialInterfaces:
  62. self.checkers[credentialInterface] = checker
  63. def login(self, credentials, mind, *interfaces):
  64. """
  65. @param credentials: an implementor of
  66. L{twisted.cred.credentials.ICredentials}
  67. @param mind: an object which implements a client-side interface for
  68. your particular realm. In many cases, this may be None, so if the
  69. word 'mind' confuses you, just ignore it.
  70. @param interfaces: list of interfaces for the perspective that the mind
  71. wishes to attach to. Usually, this will be only one interface, for
  72. example IMailAccount. For highly dynamic protocols, however, this
  73. may be a list like (IMailAccount, IUserChooser, IServiceInfo). To
  74. expand: if we are speaking to the system over IMAP, any information
  75. that will be relayed to the user MUST be returned as an
  76. IMailAccount implementor; IMAP clients would not be able to
  77. understand anything else. Any information about unusual status
  78. would have to be relayed as a single mail message in an
  79. otherwise-empty mailbox. However, in a web-based mail system, or a
  80. PB-based client, the ``mind'' object inside the web server
  81. (implemented with a dynamic page-viewing mechanism such as a
  82. Twisted Web Resource) or on the user's client program may be
  83. intelligent enough to respond to several ``server''-side
  84. interfaces.
  85. @return: A deferred which will fire a tuple of (interface,
  86. avatarAspect, logout). The interface will be one of the interfaces
  87. passed in the 'interfaces' argument. The 'avatarAspect' will
  88. implement that interface. The 'logout' object is a callable which
  89. will detach the mind from the avatar. It must be called when the
  90. user has conceptually disconnected from the service. Although in
  91. some cases this will not be in connectionLost (such as in a
  92. web-based session), it will always be at the end of a user's
  93. interactive session.
  94. """
  95. for i in self.checkers:
  96. if i.providedBy(credentials):
  97. return maybeDeferred(
  98. self.checkers[i].requestAvatarId, credentials
  99. ).addCallback(self.realm.requestAvatar, mind, *interfaces)
  100. ifac = providedBy(credentials)
  101. return defer.fail(
  102. failure.Failure(
  103. error.UnhandledCredentials(
  104. "No checker for %s" % ", ".join(map(reflect.qual, ifac))
  105. )
  106. )
  107. )