blob: 4a0a47dc486ca8d88586c1ba8b81d1a0db242f24 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6"""A class to display the hosting home page."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import logging
12import ezt
13
14import settings
15from businesslogic import work_env
16from framework import exceptions
17from framework import permissions
18from framework import servlet
19from framework import template_helpers
20from framework import urls
21from project import project_views
22from sitewide import projectsearch
23from sitewide import sitewide_helpers
24
25
26class HostingHome(servlet.Servlet):
27 """HostingHome shows the project list and link to create a project."""
28
29 _PAGE_TEMPLATE = 'sitewide/hosting-home-page.ezt'
30
31 def GatherPageData(self, mr):
32 """Build up a dictionary of data values to use when rendering the page.
33
34 Args:
35 mr: commonly used info parsed from the request.
36
37 Returns:
38 Dict of values used by EZT for rendering the page.
39 """
40 redirect_msg = self._MaybeRedirectToDomainDefaultProject(mr)
41 logging.info(redirect_msg)
42
43 can_create_project = permissions.CanCreateProject(mr.perms)
44
45 # Kick off the search pipeline, it has its own promises for parallelism.
46 pipeline = projectsearch.ProjectSearchPipeline(mr, self.services)
47
48 # Meanwhile, determine which projects the signed-in user has starred.
49 with work_env.WorkEnv(mr, self.services) as we:
50 starred_projects = we.ListStarredProjects()
51 starred_project_ids = {p.project_id for p in starred_projects}
52
53 # A dict of project id to the user's membership status.
54 project_memberships = {}
55 if mr.auth.user_id:
56 with work_env.WorkEnv(mr, self.services) as we:
57 owned, _archive_owned, member_of, contrib_of = (
58 we.GetUserProjects(mr.auth.effective_ids))
59 project_memberships.update({proj.project_id: 'Owner' for proj in owned})
60 project_memberships.update(
61 {proj.project_id: 'Member' for proj in member_of})
62 project_memberships.update(
63 {proj.project_id: 'Contributor' for proj in contrib_of})
64
65 # Finish the project search pipeline.
66 pipeline.SearchForIDs(domain=mr.request.host)
67 pipeline.GetProjectsAndPaginate(mr.cnxn, urls.HOSTING_HOME)
68 project_ids = [p.project_id for p in pipeline.visible_results]
69 star_count_dict = self.services.project_star.CountItemsStars(
70 mr.cnxn, project_ids)
71
72 # Make ProjectView objects
73 project_view_list = [
74 project_views.ProjectView(
75 p, starred=p.project_id in starred_project_ids,
76 num_stars=star_count_dict.get(p.project_id),
77 membership_desc=project_memberships.get(p.project_id))
78 for p in pipeline.visible_results]
79 return {
80 'can_create_project': ezt.boolean(can_create_project),
81 'learn_more_link': settings.learn_more_link,
82 'projects': project_view_list,
83 'pagination': pipeline.pagination,
84 }
85
86 def _MaybeRedirectToDomainDefaultProject(self, mr):
87 """If there is a relevant default project, redirect to it."""
88 project_name = settings.domain_to_default_project.get(mr.request.host)
89 if not project_name:
90 return 'No configured default project redirect for this domain.'
91
92 project = None
93 try:
94 project = self.services.project.GetProjectByName(mr.cnxn, project_name)
95 except exceptions.NoSuchProjectException:
96 pass
97
98 if not project:
99 return 'Domain default project %s not found' % project_name
100
101 if not permissions.UserCanViewProject(
102 mr.auth.user_pb, mr.auth.effective_ids, project):
103 return 'User cannot view default project: %r' % project
104
105 project_url = '/p/%s' % project_name
106 self.redirect(project_url, abort=True)
107 return 'Redirected to %r' % project_url