-
Notifications
You must be signed in to change notification settings - Fork 1
/
member.py
244 lines (186 loc) · 7.84 KB
/
member.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
"""
Profile View
"""
from AccessControl import allow_module
from topp.utils.pretty_date import prettyDate
from zope.component import getMultiAdapter, adapts, adapter
from zope.event import notify
from zope.interface import implements, alsoProvides
from memojito import memoizedproperty, memoize
from Products.Five import BrowserView
from Products.CMFCore.permissions import ModifyPortalContent
from Products.CMFCore.utils import getToolByName
from Products.remember.interfaces import IReMember
from opencore import redirect
from opencore.interfaces import IProject, IConsumeNewMembers
from interfaces import IMemberFolder, IMemberHomePage
from interfaces import IMemberInfo, IFirstLoginEvent
allow_module('opencore.siteui.member')
class MemberInfoView(BrowserView):
"""A view which also provides contextual information about a member."""
implements(IMemberInfo)
def __init__(self, context, request):
self._context = (context,)
self.request = request
self.mtool = getToolByName(context, 'portal_membership')
@property
def context(self):
return self._context[0]
def interfaceInAqChain(self, iface):
chain = self.context.aq_inner.aq_chain
for item in chain:
if iface.providedBy(item):
return item
@memoizedproperty
def member_folder(self):
return self.interfaceInAqChain(IMemberFolder)
@memoizedproperty
def member_object(self):
return self.interfaceInAqChain(IReMember)
@memoizedproperty
def member(self):
"""Returns the member object found by traversing the acquisition chain."""
mf = self.member_folder
if mf is not None:
# XXX we shouldn't rely on the folder id matching the user id;
# maybe store the member id in an annotation on the folder?
return self.mtool.getMemberById(mf.getId())
return self.member_object
@memoizedproperty
def personal_folder(self):
"""Returns the folder of the authenticated member."""
mem_id = self.mtool.getAuthenticatedMember().getId()
return self.mtool.getHomeFolder(mem_id)
@memoizedproperty
def inMemberObject(self):
return self.member_object is not None
@memoizedproperty
def inSelf(self):
return self.inMemberObject and \
self.member_object == self.mtool.getAuthenticatedMember()
@property
def inMemberArea(self):
return self.member_folder is not None
@memoizedproperty
def inPersonalArea(self):
return self.inMemberArea and self.member_folder == self.personal_folder
class ProfileView(BrowserView):
implements(IMemberHomePage)
def __init__(self, context, request):
self.context = context
self.request = request
self.request.set('disable_border', 1)
self.info = None
def _getPortraitURL(self, member):
portrait = member.getProperty('portrait', None)
return portrait and portrait.absolute_url()
def _getWiki(self, memberfolder):
homepage_id = memberfolder.getDefaultPage()
if homepage_id is not None:
homepage = memberfolder._getOb(homepage_id)
return homepage.CookedBody()
return ''
def getUserInfo(self):
"""Returns a dict with user info that gets displayed on profile view"""
if self.info is None:
mtool = getToolByName(self.context, 'portal_membership')
miv = getMultiAdapter((self.context, self.request), name='member_info')
member, memberfolder = miv.member, miv.member_folder
self.info = dict(login=member.getId(),
fullname=member.getFullname(),
membersince=prettyDate(member.created()),
lastlogin=prettyDate(member.getLast_login_time()),
location=member.getLocation(),
prefsurl=member.absolute_url() + '/edit',
portraiturl=self._getPortraitURL(member),
projects=member.getProjects(), # @@@ this should be indexed and then returned by a catalog call
wiki=self._getWiki(memberfolder),
editpermission=mtool.checkPermission(ModifyPortalContent, self.context),
isme=member == mtool.getAuthenticatedMember()
)
return self.info
def getLatestContent(self, limit_per_type=5):
catalog = getToolByName(self.context, 'portal_catalog')
types = ('OpenProject', 'Document')
userinfo = self.getUserInfo()
found = {}
content = catalog.searchResults(Creator = userinfo['login'],
portal_type = types,
sort_on = 'modified',
sort_order = 'reverse')
for item in content:
itemType = item.portal_type
if not found.has_key(itemType):
found[itemType] = []
if len(found[itemType]) < limit_per_type:
found[itemType].append(item)
types = found.keys()
types.sort()
results = []
for t in types:
results.append({'portal_type' : t,
'content_items' : found[t]})
return results
def initializeMemberArea(mtool, request):
"""
This method is triggered by the 'notifyMemberAreaCreated' script
that is called at the end of the membership tool's
createMemberArea() method. Will switch to an event as soon as the
membership tool starts firing one.
"""
member = mtool.getAuthenticatedMember()
member_id = member.getId()
folder = mtool.getHomeFolder(member_id)
alsoProvides(folder, IMemberFolder)
apply_member_folder_redirection(folder, request)
page_id = "%s-home" % member_id
title = "%s Home" % member_id
folder.invokeFactory('Document', page_id, title=title)
folder.setDefaultPage(page_id)
page = getattr(folder, page_id)
# XXX acquisition, ugh @@ huh?
page_text = member.member_index(member_id=member_id)
page.setText(page_text)
# the page is the homepage
alsoProvides(page, IMemberHomePage)
# make profile the default view on the homepage
page.setLayout('profile.html')
class FirstLoginEvent(object):
implements(IFirstLoginEvent)
def __init__(self, member, request):
self.member = member
self.request = request
@adapter(IFirstLoginEvent)
def auto_approve_member(event):
# if there is a parent project in the
# request which implements IConsumeNewMembers,
# automatically register the user as a member
# of the project.
request = event.request
parent = get_parent_project(request)
if parent is not None:
team = parent.getTeams()[0]
if team is not None:
team.joinAndApprove()
def get_parent_project(request):
parents = request.get('PARENTS', tuple())
for parent in parents:
# check the request for a greedy project project,
# ie one that is redirected and marked with IConsumeMembers
if (redirect.IRedirected.providedBy(parent) and
IConsumeNewMembers.providedBy(parent) and
IProject.providedBy(parent)):
return parent
def apply_member_folder_redirection(folder, request):
parent = get_parent_project(request)
if parent:
parent_info = redirect.get_info(parent)
folder_id = folder.getId()
folder_path = parent_info.url
if not folder_path.endswith('/'):
folder_path += '/'
#XXX not crazy about this assuming the folder is 'people'
folder_path += "people/%s" % folder_id
return redirect.activate(folder, url=folder_path)
else:
return redirect.activate(folder)