Resource Users¶
The Users
resource is represented in the LDAP tree as user objects.
To list those LDAP objects run in a terminal:
FILTER='(|(objectClass=ucsschoolStaff)(objectClass=ucsschoolStudent)(objectClass=ucsschoolTeacher))'
univention-ldapsearch -LLL "$FILTER"
UCS@school uses the UDM to access the LDAP directory. UDM properties have different names than their associated LDAP attributes. Their values may also differ. To list the same UDM objects as above, run:
$ FILTER='(|(objectClass=ucsschoolStaff)(objectClass=ucsschoolStudent)(objectClass=ucsschoolTeacher))'
$ udm users/user list --filter "$FILTER"
Kelvin API documentation¶
Please see the Kelvin API documentation section Resource Users about allowed values for the attributes.
User class¶
The ucsschool.kelvin.client.User
class has the following public attributes and methods:
class User(KelvinObject):
def __init__(
self,
name: str = None,
school: str = None,
*,
firstname: str = None,
lastname: str = None,
birthday: datetime.date = None,
disabled: bool = False,
email: str = None,
expiration_date: datetime.date = None,
kelvin_password_hashes: PasswordsHashes = None,
password: str = None,
record_uid: str = None,
roles: List[str],
schools: List[str],
school_classes: Dict[str, List[str]] = None,
workgroups: Dict[str, List[str]] = None,
source_uid: str = None,
udm_properties: Dict[str, Any] = None,
ucsschool_roles: List[str] = None,
dn: str = None,
url: str = None,
session: Session = None,
language: str = None,
**kwargs,
):
self.name = name
self.school = school
self.firstname = firstname
self.lastname = lastname
self.birthday = birthday
self.disabled = disabled
self.email = email
self.expiration_date = expiration_date
self.kelvin_password_hashes = kelvin_password_hashes
self.password = password
self.record_uid = record_uid
self.roles = roles
self.schools = schools
self.school_classes = school_classes or {}
self.workgroups = workgroups or {}
self.source_uid = source_uid
self.udm_properties = udm_properties or {}
self.ucsschool_roles = ucsschool_roles
self.dn = dn
self.url = url
self.session = session
if language:
self.session.language = language
async def reload(self) -> User:
...
async def save(self) -> User:
...
async def delete(self) -> None:
...
def as_dict(self) -> Dict[str, Any]:
...
Note
The field expiration_date
was added to the Kelvin REST API in version 1.5.1
. The client works with prior server versions, but the attribute will not be read or set.
Note
Since the Kelvin REST API client version 2.0.0
, the required argument school has the default argument None. The argument name is not required anymore.
UserResource class¶
ucsschool.kelvin.client.UserResource
class has the following public attributes and methods:
class UserResource(KelvinResource):
def __init__(self, session: Session, language: str = None):
...
async def get(self, **kwargs) -> User:
...
async def get_from_url(self, url: str) -> User:
...
async def search(self, **kwargs) -> AsyncIterator[User]:
...
Create user¶
from ucsschool.kelvin.client import Session, User
async with Session(**credentials) as session:
user = User(
school="DEMOSCHOOL",
schools=["DEMOSCHOOL"],
roles=["student"],
name="test1",
firstname="test",
lastname="one",
record_uid="test1",
source_uid="TESTID",
session=session
)
await user.save()
user.dn
'uid=test1,cn=schueler,cn=users,ou=DEMOSCHOOL,dc=example,dc=com'
Note
Since version 2.0.0
, all attributes except school
, schools
and roles
can be automatically generated on the server by defining a schema. If a schema is defined for an attribute, it can be skipped. The attributes name
and record_uid
have to be passed in either the constructor or a schema must exist. You can find more about schemas in the [UCS@school - Handbuch zur CLI-Import Schnittstelle (german only)](https://docs.software-univention.de/ucsschool-import/5.0/de/configuration/scheme-formatting.html#formatierungsschema).
Retrieve user¶
from ucsschool.kelvin.client import Session, UserResource
async with Session(**credentials) as session:
user = await UserResource(session=session).get(name="test1")
user.as_dict()
{'name': 'test1',
'ucsschool_roles': ['student:school:DEMOSCHOOL'],
'school': 'DEMOSCHOOL',
'firstname': 'test',
'lastname': 'one',
'birthday': None,
'disabled': False,
'email': None,
'expiration_date': None,
'kelvin_password_hashes': None,
'password': None,
'record_uid': 'test1',
'roles': ['student'],
'schools': ['DEMOSCHOOL'],
'school_classes': {},
'workgroups': {},
'source_uid': 'TESTID',
'udm_properties': {},
'dn': 'uid=test1,cn=schueler,cn=users,ou=DEMOSCHOOL,dc=example,dc=com',
'url': 'https://master.ucs.local/ucsschool/kelvin/v1/users/test1'}
Check if user exists¶
from ucsschool.kelvin.client import Session, UserResource
async with Session(**credentials) as session:
if await UserResource(session=session).exists(name="test1"):
print("The user exists!")
Search users¶
The search()
method allows searching for users, using a number of filters.
Most (but now all) attributes support searching inexact, using an asterisk (*
) as placeholder.
In the following examples the search is always limited to users of the school DEMOSCHOOL
.
In the 1. search all users (of the school DEMOSCHOOL
) are searched,
2. users with a username starting with t
,
3. users with a family name starting with tea
and
4. users that have the role teacher
.
from ucsschool.kelvin.client import Session, UserResource
async with Session(**credentials) as session:
async for user in UserResource(session=session).search(school="DEMOSCHOOL"):
print(user)
User('name'='demo_admin', dn='uid=demo_admin,cn=lehrer,cn=users,ou=DEMOSCHOOL,dc=example,dc=com')
User('name'='demo_student', dn='uid=demo_student,cn=schueler,cn=users,ou=DEMOSCHOOL,dc=example,dc=com')
User('name'='demo_teacher', dn='uid=demo_teacher,cn=lehrer,cn=users,ou=DEMOSCHOOL,dc=example,dc=com')
User('name'='test1', dn='uid=test1,cn=schueler,cn=users,ou=DEMOSCHOOL,dc=example,dc=com')
async for user in UserResource(session=session).search(
name="t*", school="DEMOSCHOOL"
):
print(user)
User('name'='test1', dn='uid=test1,cn=schueler,cn=users,ou=DEMOSCHOOL,dc=example,dc=com')
async for user in UserResource(session=session).search(
lastname="tea*", school="DEMOSCHOOL"
):
print(user)
User('name'='demo_teacher', dn='uid=demo_teacher,cn=lehrer,cn=users,ou=DEMOSCHOOL,dc=example,dc=com')
async for user in UserResource(session=session).search(
roles=["teacher"], school="DEMOSCHOOL"
):
print(user)
User('name'='demo_admin', dn='uid=demo_admin,cn=lehrer,cn=users,ou=DEMOSCHOOL,dc=example,dc=com')
User('name'='demo_teacher', dn='uid=demo_teacher,cn=lehrer,cn=users,ou=DEMOSCHOOL,dc=example,dc=com')
Change user properties¶
Get the current user object, change some attributes and save the changes back to LDAP:
from ucsschool.kelvin.client import Session, User, UserResource
async def change_properties(username: str, **changes) -> User:
async with Session(**credentials) as session:
user = await UserResource(session=session).get(name=username)
for property, value in changes.items():
setattr(user, property, value)
return await user.save()
user = await change_properties(
"test1",
firstname="newfn",
lastname="newln",
password="password123",
)
assert user.firstname == "newfn"
assert user.lastname == "newln"
Hint: users cannot be modified, unless their record_uid
and source_uid
attributes are set (as is the case with the demo_*
users).
Move user¶
User objects support changing both school
and name
.
When the school
attribute of a user is changed, the new value must be part of the list in the schools
attribute.
In the following example both school
and name
are changed.
from ucsschool.kelvin.client import Session, User, UserResource
async with Session(**credentials) as session:
user = User(
school="DEMOSCHOOL", schools=["DEMOSCHOOL"],
roles=["student"], name="test1", firstname="test",
lastname="one", record_uid="test1",
source_uid="TESTID", session=session
)
await user.save()
user.dn
'uid=test1,cn=schueler,cn=users,ou=DEMOSCHOOL,dc=example,dc=com'
user.name = "test2"
user.school = "DEMOSCHOOL2"
user.schools = ["DEMOSCHOOL2"]
await user.save()
user.dn
'uid=test2,cn=schueler,cn=users,ou=DEMOSCHOOL2,dc=example,dc=com'
Delete user¶
Get the current user object and delete it:
from ucsschool.kelvin.client import Session, User, UserResource
async with Session(**credentials) as session:
user = await UserResource(session=session).get(name="test1")
await user.delete()
Trying to retrieve the deleted user will raise a ucsschool.kelvin.client.NoObject
exception.