def localize_users_to_org(org, users, sort=False): # Set cached state for when the users are viewed from a particular Organization. # For each user, set: # * user_settings_task, which holds the account project's settings Task, if created # * user_settings_dict, which holds that Task's current answers as a dict, if the Task was created # * can_see_org_settings, which holds whether the user is in the org's organization project org_members = org.get_organization_project().get_members() if len(users) > 1: org_members = set(org_members) # pre-load # Get the account projects of all of the users in batch. account_project_root_tasks = { } for pm in ProjectMembership.objects.filter( user__in=users, project__organization=org, project__is_account_project=True)\ .select_related("project", "project__root_task", "project__root_task__module"): account_project_root_tasks[pm.user] = pm.project.root_task # Get the account_settings answer object for all of the account projects in batch. # Load all TaskAnswerHistory objects that answer the "account_settings" question # in each account project. This gives us the whole history of answers. Take the # most recent (reverse sort + take first) for each project. from guidedmodules.models import TaskAnswerHistory account_project_settings = { } for ansh in TaskAnswerHistory.objects\ .filter( taskanswer__task__in=account_project_root_tasks.values(), taskanswer__question__key="account_settings", )\ .select_related("taskanswer__task__module", "taskanswer__question", "answered_by")\ .prefetch_related("answered_by_task__module__questions")\ .order_by('-id'): account_project_settings.setdefault( ansh.taskanswer.task, ansh.answered_by_task.first() ) # Get all of the current answers for the settings tasks. from guidedmodules.models import Task settings = { } for task, question, answer in Task.get_all_current_answer_records(account_project_settings.values()): settings.setdefault(task, {})[question.key] = (answer.get_value() if answer else None) # Set attributes on each user instance. for user in users: user.localized_to = org user.user_settings_task = account_project_settings.get(account_project_root_tasks.get(user)) user.user_settings_task_answers = settings.get(user.user_settings_task, None) user.can_see_org_settings = (user in org_members) # Apply a standard sort. if sort: users.sort(key = lambda user : user.name_and_email())
def get_open_tasks(self, user): # Get all tasks that the user might want to continue working on # (except for the project root task). from guidedmodules.models import Task return [ task for task in Task.get_all_tasks_readable_by(user, self.organization) .filter(project=self, editor=user) \ .order_by('-updated')\ .select_related('project') if not task.is_finished() and task != self.root_task ]
def has_read_priv(self, user): # Who can see this project? Team members + anyone with read privs to a task within # this project + anyone that's a guest in dicussion within this project. # See get_all_participants for the inverse of this function. from guidedmodules.models import Task if ProjectMembership.objects.filter(project=self, user=user).exists(): return True if Task.get_all_tasks_readable_by(user, self.organization, recursive=True).filter(project=self).exists(): return True for d in self.get_discussions_in_project_as_guest(user): return True return False
def get_projects_with_read_priv(user, organization, filters={}, excludes={}): # Gets all projects a user has read priv to, excluding # account and organization profile projects, and sorted # in reverse chronological order by modified date. projects = set() if not user.is_authenticated: return projects # Add all of the Projects the user is a member of within the Organization # that the user is on the subdomain of. for pm in ProjectMembership.objects\ .filter(project__organization=organization, user=user)\ .filter(**{ "project__"+k: v for k, v in filters.items() })\ .exclude(**{ "project__"+k: v for k, v in excludes.items() })\ .select_related('project__root_task__module')\ .prefetch_related('project__root_task__module__questions'): projects.add(pm.project) if pm.is_admin: # Annotate with whether the user is an admin of the project. pm.project.user_is_admin = True # Add projects that the user is the editor of a task in, even if # the user isn't a team member of that project. from guidedmodules.models import Task for task in Task.get_all_tasks_readable_by(user, organization)\ .filter(**{ "project__"+k: v for k, v in filters.items() })\ .exclude(**{ "project__"+k: v for k, v in excludes.items() })\ .order_by('-created')\ .select_related('project__root_task__module')\ .prefetch_related('project__root_task__module__questions'): projects.add(task.project) # Add projects that the user is participating in a Discussion in # as a guest. from discussion.models import Discussion for d in Discussion.objects.filter(organization=organization, guests=user): if d.attached_to is not None: # because it is generic there is no cascaded delete and the Discussion can become dangling if not filters or d.attached_to.task.project in Project.objects.filter(**filters): if not excludes or d.attached_to.task.project not in Project.objects.exclude(**filters): projects.add(d.attached_to.task.project) # Don't show system projects. system_projects = set(p for p in projects if p.is_organization_project or p.is_account_project) projects -= system_projects # Sort. projects = sorted(projects, key = lambda x : x.updated, reverse=True) return projects