Skip to content
Browse files

The getUserId() function returns only strings

privacyIDEA works with a user ID type string so we enforce that the
`getUserId()`-function only returns strings.

Fixes #1825
Also fixes #862 (yay!)
  • Loading branch information...
plettich committed Aug 27, 2019
1 parent 2608889 commit d5b19a47e1799f27763baaf6b3d943410ce76363
@@ -60,12 +60,13 @@
import yaml
import threading
import functools
import six

from .UserIdResolver import UserIdResolver

import ldap3
from ldap3 import Server, Tls, Connection
from ldap3 import Tls
from ldap3.core.exceptions import LDAPOperationResult
from ldap3.core.results import RESULT_SIZE_LIMIT_EXCEEDED
import ssl
@@ -76,7 +77,6 @@
from passlib.hash import ldap_salted_sha1
import hashlib
import binascii
from privacyidea.lib.crypto import urandom, geturandom
from privacyidea.lib.utils import is_true
from privacyidea.lib.framework import get_app_local_store
import datetime
@@ -87,7 +87,6 @@
import uuid
from ldap3.utils.conv import escape_bytes
from operator import itemgetter
from six import string_types

CACHE = {}

@@ -539,7 +538,7 @@ def _ldap_attributes_to_user_object(self, attributes):
if ldap_k == map_v:
if ldap_k == "objectGUID":
# An objectGUID should be no list, since it is unique
if isinstance(ldap_v, string_types):
if isinstance(ldap_v, six.string_types):
ret[map_k] = ldap_v.strip("{").strip("}")
raise Exception("The LDAP returns an objectGUID, that is no string: {0!s}".format(type(ldap_v)))
@@ -573,6 +572,7 @@ def getUserId(self, LoginName):
:param LoginName: The login name from the credentials
:type LoginName: string
:return: UserId as found for the LoginName
:rtype: str
userid = ""
@@ -626,11 +626,11 @@ def getUserId(self, LoginName):

for entry in r:
userid = self._get_uid(entry, self.uidtype)
userid = str(self._get_uid(entry, self.uidtype))

return userid

def getUserList(self, searchDict):
def getUserList(self, searchDict=None):
:param searchDict: A dictionary with search parameters
:type searchDict: dict
@@ -253,7 +253,7 @@ def getUsername(self, userId):
:param userid: The userid in this resolver
:type userid: string
:return: username
:rtype: string
:rtype: str
fields = self.descDict.get(userId)
index = self.sF["username"]
@@ -269,7 +269,7 @@ def getUserId(self, LoginName):
# We do not encode the LoginName anymore, as we are
# storing unicode in nameDict now.
if LoginName in self.nameDict:
return self.nameDict[LoginName]
return str(self.nameDict[LoginName])
return ""

@@ -293,7 +293,7 @@ def getSearchFields(self, searchDict=None):

return self.searchFields

def getUserList(self, searchDict):
def getUserList(self, searchDict=None):
get a list of all users matching the search criteria of the searchdict
@@ -133,7 +133,7 @@ def getUserId(self, loginName):
# ("userName", loginName)})
#return res.get("Resources", [{}])[0].get("externalId")
# It seems that the userName is the userId
return loginName
return str(loginName)

def getUserList(self, searchDict=None):
@@ -34,12 +34,13 @@
import yaml
import binascii
import re
import six

from privacyidea.lib.resolvers.UserIdResolver import UserIdResolver

from sqlalchemy import and_
from sqlalchemy import create_engine
from sqlalchemy import Integer
from sqlalchemy import Integer, cast, String
from sqlalchemy.orm import sessionmaker, scoped_session

import traceback
@@ -356,9 +357,11 @@ def getUserInfo(self, userId):
def _get_userid_filter(self, userId):
column = getattr(self.TABLE,"userid"))
if isinstance(column.type, Integer):
return column == userId
# since our user ID is usually a string we need to cast
return column == int(userId)
# otherwise we cast the column to string (in case of postgres UUIDs)
return cast(column, String).like(userId)

def getUsername(self, userId):
@@ -378,6 +381,7 @@ def getUserId(self, LoginName):
:param LoginName: The login name from the credentials
:type LoginName: string
:return: UserId as found for the LoginName
:rtype: str
userid = ""

@@ -395,7 +399,7 @@ def getUserId(self, LoginName):
raise Exception("More than one user with loginname"
" %s found!" % LoginName)
user = self._get_user_from_mapped_object(r)
userid = user["id"]
userid = str(user["id"])
except Exception as exx: # pragma: no cover
log.error("Could not get the userinformation: {0!r}".format(exx))

@@ -128,7 +128,7 @@ def getUserId(self, loginName):
:param loginName: The login name of the user
:type loginName: sting
:return: The ID of the user
:rtype: string or int
:rtype: str
return "dummy_user_id"

@@ -182,7 +182,7 @@ def test_01_sqlite_resolver(self):

user = "cornelius"
user_id = y.getUserId(user)
self.assertTrue(user_id == 3, user_id)
self.assertEqual(user_id, '3', user_id)

rid = y.getResolverId()
@@ -296,8 +296,9 @@ def test_05_add_user_update_delete(self):
stored_password = y.TABLE.filter_by(username="achmed").first().password
self.assertTrue(stored_password.startswith("{SSHA256}"), stored_password)

# we assume here the uid is of type int
uid = y.getUserId("achmed")
self.assertTrue(uid > self.num_users)
self.assertGreater(int(uid), self.num_users)

r = y.update_user(uid, {"username": "achmed2",
"password": "test"})
@@ -440,7 +440,7 @@ def test_12_multiple_resolvers(self):
# Now, query the user and populate the cache
self.assertEqual(UserCache.query.count(), 0)
user1 = User('wordpressuser', self.sql_realm)
self.assertEqual(user1.uid, 6)
self.assertEqual(user1.uid, '6')
# Assert it was found in reso_b (as it does not have a phone number)!
self.assertEqual(user1.resolver, 'reso_b')
self.assertEqual(UserCache.query.filter(UserCache.username == 'wordpressuser',
@@ -458,7 +458,7 @@ def test_12_multiple_resolvers(self):
# Now, it should be located in reso_a!
user2 = User('wordpressuser', self.sql_realm)
self.assertEqual(user2.uid, 6)
self.assertEqual(user2.uid, '6')
self.assertEqual(user2.resolver, 'reso_a')
# ... but the cache still contains entries for both!
resolver_query = UserCache.query.filter(UserCache.username == 'wordpressuser',

0 comments on commit d5b19a4

Please sign in to comment.
You can’t perform that action at this time.