Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(get): get more infos from user (DEV-641) #181

Merged
merged 9 commits into from Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/dsp-tools-create.md
Expand Up @@ -394,8 +394,8 @@ This object contains user definitions. A user has the following elements:
- _familyName_: surname of the user
- _password_: password of the user
- _lang_: the default language of the user: "en", "de", "fr", "it" (optional, default: "en")
- _groups_: List of groups the user belongs to. The name of the group has to be provided with the ontology's namespace,
p.ex. "onto:editors". The given ontology defined in the same ontology file has no name, so only ":editors" is required
- _groups_: List of groups the user belongs to. The name of the group has to be provided with the project's shortname,
p.ex. "shortname:editors". The project defined in the same ontology file has no name, so only ":editors" is required
if the user belongs to the group "editors". (optional)
- _projects_: List of projects the user belongs to. The project name has to be followed by a ":" and either "member"
or "admin". This indicates if the new user has admin rights in the given project or is an ordinary
Expand Down
56 changes: 48 additions & 8 deletions knora/dsplib/models/user.py
@@ -1,3 +1,4 @@
from __future__ import annotations
import json
import os
import sys
Expand Down Expand Up @@ -368,7 +369,7 @@ def in_projects(self) -> dict[str, bool]:
return self._in_projects

@in_projects.setter
def in_project(self, value: Any):
def in_projects(self, value: Any):
raise BaseError(
'Project membership cannot be modified directly! Use methods "addToProject" and "rmFromProject"')

Expand Down Expand Up @@ -444,7 +445,7 @@ def has_changed(self, name: str):
return name in self._changed

@classmethod
def fromJsonObj(cls, con: Connection, json_obj: Any):
def fromJsonObj(cls, con: Connection, json_obj: Any) -> User:
"""
Internal method! Should not be used directly!

Expand Down Expand Up @@ -678,7 +679,7 @@ def getAllUsers(con: Connection) -> list[Any]:
return list(map(lambda a: User.fromJsonObj(con, a), result['users']))

@staticmethod
def getAllUsersForProject(con: Connection, proj_shortcode: str) -> list[Any]:
def getAllUsersForProject(con: Connection, proj_shortcode: str) -> Optional[list[User]]:
"""
Get a list of all users that belong to a project(static method)

Expand All @@ -689,7 +690,7 @@ def getAllUsersForProject(con: Connection, proj_shortcode: str) -> list[Any]:

result = con.get(User.ROUTE)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I think about it, there is a route to get all users for a specific project, it's:
/admin/projects/shortcode/{{project_shortcode}}/members

It's probably easier to use this for getAllUsersForProject directly. There are also groups and projects for the user.

if 'users' not in result:
raise BaseError("Request got no users!")
return None
all_users = result["users"]
project_users = []
for user in all_users:
Expand All @@ -699,17 +700,56 @@ def getAllUsersForProject(con: Connection, proj_shortcode: str) -> list[Any]:
for proj in project:
if proj["id"] == "http://rdfh.ch/projects/" + proj_shortcode:
project_users.append(user)
return list(map(lambda a: User.fromJsonObj(con, a), project_users))

def createDefinitionFileObj(self):
user = {
# find out the 'groups' and 'projects' of every user
jnussbaum marked this conversation as resolved.
Show resolved Hide resolved
for user in project_users:
user_iri_esc = urllib.parse.quote_plus(user["id"])
project_memberships = con.get(f'/admin/users/iri/{user_iri_esc}/project-memberships')
admin_group_memberships = con.get(f'/admin/users/iri/{user_iri_esc}/project-admin-memberships')
normal_group_memberships = con.get(f'/admin/users/iri/{user_iri_esc}/group-memberships')

for adm_group in admin_group_memberships['projects']:
user['projects'].append(f"{adm_group['shortname']}:admin")

for project in project_memberships['projects']:
if f"{project['shortname']}:admin" not in user['projects']:
user['projects'].append(f"{project['shortname']}:member")

for group in normal_group_memberships['groups']:
project_prefix = group['project']['shortname']
user['groups'].append(f"{project_prefix}:{group['name']}")

user['groups'].reverse()
jnussbaum marked this conversation as resolved.
Show resolved Hide resolved

# convert to User objects
res: list[User] = list(map(lambda a: User.fromJsonObj(con, a), project_users))
jnussbaum marked this conversation as resolved.
Show resolved Hide resolved

# add the informations about projects and groups to the User objects
jnussbaum marked this conversation as resolved.
Show resolved Hide resolved
for project_user, res_user in zip(project_users, res):
res_user._in_groups = res_user._in_groups | set(project_user['groups'])
for proj in project_user['projects']:
proj_name, admin = proj.split(':')
res_user._in_projects[proj_name] = bool(admin=='admin')

return res

def createDefinitionFileObj(self) -> dict[str, Union[str, list[str], None]]:
user: dict[str, Union[str, list[str], None]] = {
"username": self.username,
"email": self.email,
"givenName": self.givenName,
"familyName": self.familyName,
"password": "",
"lang": self.lang.value
}
if self.lang:
user["lang"] = self.lang.value
user["groups"] = list(self._in_groups)
user["projects"] = list()
for proj, is_admin in self._in_projects.items():
if is_admin:
user["projects"].append(f"{proj}:admin")
else:
user["projects"].append(f"{proj}:member")
return user

def print(self) -> None:
Expand Down
11 changes: 6 additions & 5 deletions knora/dsplib/utils/onto_get.py
Expand Up @@ -62,11 +62,12 @@ def get_ontology(project_identifier: str, outfile: str, server: str, user: str,
print("Getting users...")
users_obj = []
users = User.getAllUsersForProject(con=con, proj_shortcode=project.shortcode)
for user in users:
users_obj.append(user.createDefinitionFileObj())
if verbose:
print(f"\tGot user '{user.username}'")
project_obj["users"] = users_obj
if users:
for usr in users:
users_obj.append(usr.createDefinitionFileObj())
if verbose:
print(f"\tGot user '{usr.username}'")
project_obj["users"] = users_obj

# get the lists
if verbose:
Expand Down