def emit(self, context, request): # Get community in which event occurred and alert members community = find_community(context) if community is None: return # Will be true for a mailin test trace profiles = find_profiles(context) all_names = community.member_names | community.moderator_names threaded = get_config_setting('use_threads_to_send_email', False) in (True, 'true', 'True') # noqa mailer = getUtility(IMailDelivery) if threaded: mailer = ThreadedGeneratorMailDelivery() queue = [] reply_enabled = get_setting(context, 'reply_by_email_enabled', True) for profile in [profiles[name] for name in all_names]: alert = getMultiAdapter((context, profile, request), IAlert) preference = profile.get_alerts_preference(community.__name__) alert = getMultiAdapter((context, profile, request), IAlert) alert.reply_enabled = reply_enabled if preference == IProfile.ALERT_IMMEDIATELY: if threaded: queue.append(alert) else: self._send_immediately(mailer, alert) elif preference in (IProfile.ALERT_DAILY_DIGEST, IProfile.ALERT_WEEKLY_DIGEST, IProfile.ALERT_BIWEEKLY_DIGEST): self._queue_digest(alert, profile, community.__name__) if queue: mailer.sendGenerator(_send_alert_queue, mailer, queue)
def __init__(self, context, request, tz=None): self.context = context self.request = request self.tz = tz self.repo = find_repo(context) self.profiles = find_profiles(context) self.deleted_branch = None self.container_id = context.docid self.error = None self.deleted = [] self.subfolder_path = [] self.can_shred = has_permission(MODERATE, context, request) subfolder = self.request.params.get('subfolder') if subfolder: try: path = decode_trash_path(subfolder) for name, container_id, deleted_item in traverse_trash( self.context, path): if deleted_item is not None: self.deleted_branch = deleted_item self.container_id = container_id self.subfolder_path.append((name, container_id)) except (ValueError, TypeError), e: log.exception("Invalid trash subfolder: %s", subfolder) self.error = e
def chatter_user_info(context, request, userid=None): chatter = find_chatter(context) chatter_url = resource_url(chatter, request) profiles = find_profiles(context) if userid is None: userid = request.GET.get('userid') if userid is None: userid = authenticated_userid(request) profile = profiles.get(userid) profile_url = profile and resource_url(profile, request) or None photo = profile and profile.get('photo') or None if photo is not None: photo_url = thumb_url(photo, request, CHATTER_THUMB_SIZE) else: photo_url = get_static_url(request) + "/images/defaultUser.gif" posts = sum(1 for p in chatter.recentWithCreators(*[userid])) following = sum(1 for u in chatter.listFollowed(userid)) followers = sum(1 for u in chatter.listFollowing(userid)) return { 'creator': getattr(profile, 'title', 'anonymous'), 'creator_url': '%s%s' % (chatter_url, userid), 'creator_profile_url': profile_url, 'creator_image_url': photo_url, 'creator_userid': userid, 'chatter_url': chatter_url, 'posts': posts, 'following': following, 'followers': followers }
def messages(context, request): layout = request.layout_manager.layout info = {} userid = '' info['latest_messages_users'] = latest_messages_users_json(context, request) ## temporary for laying out, will be an ajax call from the frontend info['user_messages'] = [] info['correspondent'] = None if info['latest_messages_users']: userid = info['latest_messages_users'][0]['userid'] user_messages = user_messages_json(context, request, userid) info['user_messages'] = user_messages['data'] info['correspondent'] = user_messages['correspondent'] ## info['api'] = TemplateAPI(context, request, 'Messages') chatter_url = resource_url(find_chatter(context), request) info['chatter_url'] = chatter_url info['chatter_form_url'] = '%sadd_chatter.html' % chatter_url info['context_tools'] = get_context_tools(request, selected='messages') info['page_title'] = 'Chatter: Messages' info['recipient'] = userid current_userid = authenticated_userid(request) profiles = find_profiles(request.context) profile = profiles.get(current_userid) if profile is not None: profile.last_chatter_query = datetime.datetime.utcnow() return info
def send_digests(self, context): mailer = getUtility(IMailDelivery) system_name = get_setting(context, "system_name", "KARL") system_email_domain = get_setting(context, "system_email_domain") sent_from = "%s@%s" % (system_name, system_email_domain) from_addr = "%s <%s>" % (system_name, sent_from) subject = "[%s] Your alerts digest" % system_name template = get_renderer("email_digest.pt").implementation() for profile in find_profiles(context).values(): if not profile._pending_alerts: continue # Perform each in its own transaction, so a problem with one # user's email doesn't block all others transaction.manager.begin() try: attachments = [] for alert in profile._pending_alerts: attachments += alert['attachments'] msg = MIMEMultipart() if attachments else Message() msg["From"] = from_addr msg["To"] = "%s <%s>" % (profile.title, profile.email) msg["Subject"] = subject body_text = template.render( system_name=system_name, alerts=profile._pending_alerts ) if isinstance(body_text, unicode): body_text = body_text.encode("UTF-8") if attachments: body = MIMEText(body_text, 'html', 'utf-8') msg.attach(body) else: msg.set_payload(body_text, "UTF-8") msg.set_type("text/html") for attachment in attachments: msg.attach(attachment) mailer.send([profile.email,], msg) del profile._pending_alerts[:] transaction.manager.commit() except Exception, e: # Log error and continue log.error("Error sending digest to %s <%s>" % (profile.title, profile.email)) b = StringIO() traceback.print_exc(file=b) log.error(b.getvalue()) b.close() transaction.manager.abort()
def show_trash(context, request): repo = find_repo(context) profiles = find_profiles(context) def display_record(record): deleted_by = profiles[record.deleted_by] version = repo.history(record.docid, only_current=True)[0] return { 'date': format_local_date(record.deleted_time), 'deleted_by': { 'name': deleted_by.title, 'url': model_url(deleted_by, request), }, 'restore_url': model_url( context, request, 'restore', query={'docid': str(record.docid), 'name': record.name}), 'title': version.title, } try: contents = repo.container_contents(context.docid) deleted = contents.deleted except: deleted = [] return { 'api': TemplateAPI(context, request, 'Trash'), 'deleted': map(display_record, deleted), }
def followed_chatter(context, request): """ HTML wrapper for 'followed_chatter_json'. """ userid = authenticated_userid(request) other_user = getattr(request, 'chatter_user_id', None) if other_user is not None: request.GET['creators'] = other_user return creators_chatter(context, request) layout = request.layout_manager.layout if layout is not None: layout.add_portlet('chatter.user_info') layout.add_portlet('chatter.show_only') layout.add_portlet('chatter.search') info = followed_chatter_json(context, request) info['api'] = TemplateAPI(context, request, 'Posts') chatter_url = resource_url(find_chatter(context), request) info['chatter_url'] = chatter_url info['chatter_form_url'] = '%sadd_chatter.html' % chatter_url info['context_tools'] = get_context_tools(request) info['page_title'] = 'Chatter: Posts' info['pushdown'] = False info['inline'] = False info['show_more'] = len(info['recent']) >= 40 profiles = find_profiles(request.context) profile = profiles.get(userid) if profile is not None: profile.last_chatter_query = datetime.datetime.utcnow() return info
def __init__(self, context, profile, request): self.context = context self.profile = profile self.request = request self.profiles = profiles = find_profiles(context) self.creator = profiles[context.creator]
def announcements_view(context, request): page_title = 'Site Announcements' api = TemplateAPI(context, request, page_title) userid = authenticated_userid(request) if userid is None: raise Exception("User must be logged in") site = api.site profiles = find_profiles(site) profile = profiles.get(userid, None) if profile is None: raise Exception("User must have a profile") seen = Set() if hasattr(profile, "_seen_announcements"): for item in profile._seen_announcements: seen.add(item) if hasattr(site, 'site_announcements'): newseen = seen.copy() for annc in site.site_announcements: newseen.add(annc['hash']) profile._seen_announcements = PersistentList(list(newseen)) return dict( api=api, seen=list(seen) )
def lock_info_for_view(context, request, from_time=None): """return a structure suitable for displaying in a template""" if is_locked(context, from_time): lock = lock_info(context) userid = lock['userid'] profiles = find_profiles(context) profile = profiles.get(userid, None) if profile is not None: return dict( is_locked=True, url=resource_url(profile, request), name='%s %s' % (profile.firstname, profile.lastname), email=profile.email, ) else: return dict( is_locked=True, url=resource_url(profiles, request), name='Unknown', email='', ) else: return dict( is_locked=False, url=None, name=None, email=None, )
def evolve(root): former_id = None # Create lazily, in case we don't need it profiles = find_profiles(root) search = ICatalogSearch(root) catalog = find_catalog(root) creators = catalog['creator']._fwd_index.keys() modifiers = catalog['modified_by']._fwd_index.keys() userids = set(creators) | set(modifiers) for userid in userids: if userid not in profiles: if former_id is None: former_id = make_unique_name(profiles, 'formeruser') print "Creating profile for former user content:", former_id former_profile = create_content( IProfile, firstname='Former', lastname='User' ) profiles[former_id] = former_profile count, docids, resolver = search(creator=userid) for docid in docids: doc = resolver(docid) print "Updating 'creator' for", resource_path(doc) doc.creator = former_id count, docids, resolver = search(modified_by=userid) for docid in docids: doc = resolver(docid) print "Updating 'modified_by' for", resource_path(doc) doc.modified_by = former_id
def evolve(root): former_id = None # Create lazily, in case we don't need it profiles = find_profiles(root) search = ICatalogSearch(root) catalog = find_catalog(root) creators = catalog['creator']._fwd_index.keys() modifiers = catalog['modified_by']._fwd_index.keys() userids = set(creators) | set(modifiers) for userid in userids: if userid not in profiles: if former_id is None: former_id = make_unique_name(profiles, 'formeruser') print "Creating profile for former user content:", former_id former_profile = create_content(IProfile, firstname='Former', lastname='User') profiles[former_id] = former_profile count, docids, resolver = search(creator=userid) for docid in docids: doc = resolver(docid) print "Updating 'creator' for", resource_path(doc) doc.creator = former_id count, docids, resolver = search(modified_by=userid) for docid in docids: doc = resolver(docid) print "Updating 'modified_by' for", resource_path(doc) doc.modified_by = former_id
def evolve(context): users = find_users(context) profiles = find_profiles(context) for id in bad_users: users.remove(id) del profiles[id]
def request_logger(event): request = event.request if not (request.path.startswith('/static') or request.path.startswith('/newest_feed_items.json')): userid = authenticated_userid(request), if userid is not None: userid = userid[0] email = '' profile = None try: profiles = find_profiles(request.context) except AttributeError: profiles = None if profiles is not None: profile = profiles.get(userid, None) if profile is not None and profile.email: email = '(%s)' % profile.email client_addr = request.remote_addr forwarded = request.headers.get('X-Forwarded-For', None) if forwarded is not None: client_addr = forwarded.split(',')[0].strip() user_agent = 'Unknown browser' if request.user_agent is not None: user_agent = user_agents.parse(request.user_agent) message = '%s - %s - %s %s - %s' % (client_addr, str(user_agent), userid or 'Anonymous', email, request.path) if not (request.path.startswith('/login.html') and client_addr.startswith('195.62.')): logger.info(message)
def get_image_info(image, request, thumb_size=THUMB_SIZE): """Return the info about a particular image, in the format specified by the client's needs. This is used when: - a batch of images are returned - information about the succesfully uploaded image is returned """ profiles = find_profiles(image) creator = profiles[image.creator] width, height = image.image_size image_url = urlparse.urlparse(thumb_url(image, request, DISPLAY_SIZE)) return dict( name = image.__name__, title = image.title, author_name = creator.title, location = breadcrumbs(image, request), image_url = image_url.path, image_width = width, image_height = height, image_size = image.size, thumbnail_url = thumb_url(image, request, thumb_size), last_modified = image.modified.ctime(), # XXX Format? )
def finder(context, request): if IChatterbox.providedBy(request.context): userid = request.view_name path = request.path_info path = path[path.index(userid)+len(userid):] parts = path.split('/') view_name = '' if len(parts) > 1: view_name = parts[1] adapters = request.registry.adapters view_callable = adapters.lookup( (IViewClassifier, request.request_iface, providedBy(request.context)), IView, name=view_name, default=None) if view_callable is not None: profiles = find_profiles(request.context) profile = profiles.get(userid) if profile: request.chatter_user_id = userid response = view_callable(request.context, request) return response debug = asbool(request.registry.settings.get('debug', 'false')) if not debug: response = errorpage(context, request) return response return HTTPNotFound()
def send_digests(self, context): mailer = getUtility(IMailDelivery) system_name = get_setting(context, "system_name", "KARL") system_email_domain = get_setting(context, "system_email_domain") sent_from = "%s@%s" % (system_name, system_email_domain) from_addr = "%s <%s>" % (system_name, sent_from) subject = "[%s] Your alerts digest" % system_name template = get_template("email_digest.pt") for profile in find_profiles(context).values(): if not profile._pending_alerts: continue # Perform each in its own transaction, so a problem with one # user's email doesn't block all others transaction.manager.begin() try: attachments = [] for alert in profile._pending_alerts: attachments += alert['attachments'] msg = MIMEMultipart() if attachments else Message() msg["From"] = from_addr msg["To"] = "%s <%s>" % (profile.title, profile.email) msg["Subject"] = subject body_text = template( system_name=system_name, alerts=profile._pending_alerts, ) if isinstance(body_text, unicode): body_text = body_text.encode("UTF-8") if attachments: body = MIMEText(body_text, 'html', 'utf-8') msg.attach(body) else: msg.set_payload(body_text, "UTF-8") msg.set_type("text/html") for attachment in attachments: msg.attach(attachment) mailer.send(sent_from, [profile.email,], msg) del profile._pending_alerts[:] transaction.manager.commit() except Exception, e: # Log error and continue log.error("Error sending digest to %s <%s>" % (profile.title, profile.email)) b = StringIO() traceback.print_exc(file=b) log.error(b.getvalue()) b.close() transaction.manager.abort()
def validate(self, userid, code): profiles = find_profiles(self.context) profile = profiles.get(userid) window = get_setting(self.context, 'two_factor_auth_code_valid_duration', 300) now = datetime.utcnow() return (strings_differ(code, profile.current_auth_code) or now > (profile.current_auth_code_time_stamp + timedelta(seconds=window)))
def getAuthor(self, email): """ See IMailinDispatcher. """ profiles = find_profiles(self.context) profile = profiles.getProfileByEmail(email) if profile is not None: return profile.__name__
def _send_moderators_changed_email(community, community_href, new_moderators, old_moderators, cur_moderators, prev_moderators): info = _get_common_email_info(community, community_href) subject_fmt = 'Change in moderators for %s' subject = subject_fmt % info['c_title'] body_template = get_renderer( 'templates/email_moderators_changed.pt').implementation() profiles = find_profiles(community) all_moderators = cur_moderators | prev_moderators to_profiles = [profiles[name] for name in all_moderators] to_addrs = ["%s <%s>" % (p.title, p.email) for p in to_profiles] mailer = getUtility(IMailDelivery) msg = MIMEMultipart('alternative') msg['From'] = info['mfrom'] msg['To'] = ",".join(to_addrs) msg['Subject'] = subject bodyhtml = body_template( system_name=info['system_name'], community_href=info['c_href'], community_name=info['c_title'], new_moderators=[profiles[name].title for name in new_moderators], old_moderators=[profiles[name].title for name in old_moderators], cur_moderators=[profiles[name].title for name in cur_moderators], prev_moderators=[profiles[name].title for name in prev_moderators]) bodyplain = html2text.html2text(bodyhtml) htmlpart = MIMEText(bodyhtml.encode('UTF-8'), 'html', 'UTF-8') plainpart = MIMEText(bodyplain.encode('UTF-8'), 'plain', 'UTF-8') msg.attach(plainpart) msg.attach(htmlpart) mailer.send(to_addrs, msg)
def author(self): profiles = find_profiles(self.context) profile = profiles[self.context.creator] return { "name": profile.title, "uri": resource_url(profile, self.request) }
def announcements_view(context, request): page_title = 'Site Announcements' api = TemplateAPI(context, request, page_title) userid = authenticated_userid(request) if userid is None: raise Exception("User must be logged in") site = api.site profiles = find_profiles(site) profile = profiles.get(userid, None) if profile is None: raise Exception("User must have a profile") seen = Set() if hasattr(profile, "_seen_announcements"): for item in profile._seen_announcements: seen.add(item) if hasattr(site, 'site_announcements'): newseen = seen.copy() for annc in site.site_announcements: newseen.add(annc['hash']) profile._seen_announcements = PersistentList(list(newseen)) return dict(api=api, seen=list(seen))
def get_wikitoc_data(context, request): wikiparent = context.__parent__ search = getAdapter(context, ICatalogSearch) count, docids, resolver = search( path = model_path(wikiparent), interfaces = [IWikiPage,] ) items = [] profiles = find_profiles(context) for docid in docids: entry = resolver(docid) tags = getMultiAdapter((entry, request), ITagQuery).tagswithcounts author = entry.creator profile = profiles.get(author, None) profile_url = model_url(profile, request) if profile is not None: author_name = '%s %s' % (profile.firstname, profile.lastname) else: author_name = author items.append(dict( id = "id_" + entry.__name__, name = entry.__name__, title = entry.title, author = author, author_name = author_name, profile_url = profile_url, tags = [tag['tag'] for tag in tags], created = entry.created.isoformat(), modified = entry.modified.isoformat(), )) result = dict( items = items, ) return result
def evolve(root): former_id = 'formeruser' profiles = find_profiles(root) search = ICatalogSearch(root) catalog = find_catalog(root) creators = catalog['creator']._fwd_index.keys() modifiers = catalog['modified_by']._fwd_index.keys() userids = set(creators) | set(modifiers) for userid in userids: if userid not in profiles: if former_id not in profiles: workflow = get_workflow(IProfile, 'security') former_id = make_unique_name(profiles, 'formeruser') print "Creating profile for former user content:", former_id former_profile = create_content(IProfile, firstname='Former', lastname='User') profiles[former_id] = former_profile workflow.initialize(former_profile) workflow.transition_to_state(former_profile, None, 'inactive') count, docids, resolver = search(creator=userid) for docid in docids: doc = resolver(docid) print "Updating 'creator' for", resource_path(doc) doc.creator = former_id count, docids, resolver = search(modified_by=userid) for docid in docids: doc = resolver(docid) print "Updating 'modified_by' for", resource_path(doc) doc.modified_by = former_id
def _get_user_home_path(context, request): """If currently authenticated user has a 'home_path' set, create a response redirecting user to that path. Otherwise return None. """ userid = authenticated_userid(request) if userid is None: return None, None site = find_site(context) profiles = find_profiles(site) profile = profiles.get(userid, None) if profile is None: return None, None home_path = getattr(profile, 'home_path', None) if home_path: # OSI sets this to a single space to mean None home_path = home_path.strip() if not home_path: return None, None tdict = traverse(site, home_path) target = tdict['context'] view_name = tdict['view_name'] subpath = list(tdict['subpath']) if view_name: subpath.insert(0, view_name) return target, subpath
def get_preferred_communities(context, request): profiles = find_profiles(context) userid = authenticated_userid(request) profile = profiles[userid] # old profiles will not have this attribute, so to be safe use getattr preferred_communities = getattr(profile, 'preferred_communities', None) return preferred_communities
def sync(self, data): context = self.context timestamp = data.pop('timestamp', None) if timestamp: context.usersync_timestamp = timestamp elif hasattr(context, 'usersync_timestamp'): del context.usersync_timestamp deactivate_missing = data.pop('deactivate_missing', False) if deactivate_missing: profiles = find_profiles(self.context) missing = set([p.__name__ for p in profiles.values() if p.security_state == 'active' and getattr(p, 'usersync_managed', False)]) else: missing = Empty() users = data.pop('users') for user in users: self.syncuser(user, missing) if data: raise ValueError("Unrecognized keys in user sync data: %s" % data.keys()) if missing: users = find_users(self.context) for username in missing: profile = profiles[username] workflow = get_workflow(IProfile, 'security', profile) workflow.transition_to_state(profile, None, 'inactive') users.remove(username)
def lock_info_for_view(context, request, from_time=None): """return a structure suitable for displaying in a template""" if is_locked(context, from_time): lock = lock_info(context) userid = lock['userid'] profiles = find_profiles(context) profile = profiles.get(userid, None) if profile is not None: return dict( is_locked = True, url = resource_url(profile, request), name = '%s %s' % (profile.firstname, profile.lastname), email = profile.email, ) else: return dict( is_locked = True, url = resource_url(profiles, request), name = 'Unknown', email = '', ) else: return dict( is_locked = False, url = None, name = None, email = None, )
def chatter_user_info(context, request, userid=None): chatter = find_chatter(context) chatter_url = resource_url(chatter, request) profiles = find_profiles(context) if userid is None: userid = request.GET.get('userid') if userid is None: userid = authenticated_userid(request) profile = profiles.get(userid) profile_url = profile and resource_url(profile, request) or None photo = profile and profile.get('photo') or None if photo is not None: photo_url = thumb_url(photo, request, CHATTER_THUMB_SIZE) else: photo_url = get_static_url(request) + "/images/defaultUser.gif" posts = sum(1 for p in chatter.recentWithCreators(*[userid])) following = sum(1 for u in chatter.listFollowed(userid)) followers = sum(1 for u in chatter.listFollowing(userid)) return {'creator': getattr(profile, 'title', 'anonymous'), 'creator_url': '%s%s' % (chatter_url, userid), 'creator_profile_url': profile_url, 'creator_image_url': photo_url, 'creator_userid': userid, 'chatter_url': chatter_url, 'posts': posts, 'following': following, 'followers': followers}
def preview_wikipage_view(context, request, WikiPage=WikiPage): version_num = int(request.params['version_num']) repo = find_repo(context) for version in repo.history(context.docid): if version.version_num == version_num: break else: raise NotFound("No such version: %d" % version_num) page = WikiPage() page.__parent__ = context.__parent__ page.revert(version) is_front_page = (context.__name__ == 'front_page') if is_front_page: community = find_interface(context, ICommunity) page_title = '%s Community Wiki Page' % community.title else: page_title = page.title profiles = find_profiles(context) author = profiles[version.user] # Extra paranoia, probably not strictly necessary. I just want to make # extra special sure that the temp WikiPage object we create above # doesn't accidentally get attached to the persistent object graph. transaction.doom() return { 'date': format_local_date(version.archive_time), 'author': author.title, 'title': page_title, 'body': page.cook(request), }
def _send_moderators_changed_email(community, community_href, new_moderators, old_moderators, cur_moderators, prev_moderators): info = _get_common_email_info(community, community_href) subject_fmt = 'Change in moderators for %s' subject = subject_fmt % info['c_title'] body_template = get_renderer( 'templates/email_moderators_changed.pt').implementation() profiles = find_profiles(community) all_moderators = cur_moderators | prev_moderators to_profiles = [profiles[name] for name in all_moderators] to_addrs = ["%s <%s>" % (p.title, p.email) for p in to_profiles] mailer = getUtility(IMailDelivery) msg = Message() msg['From'] = info['mfrom'] msg['To'] = ",".join(to_addrs) msg['Subject'] = subject body = body_template( system_name=info['system_name'], community_href=info['c_href'], community_name=info['c_title'], new_moderators=[profiles[name].title for name in new_moderators], old_moderators=[profiles[name].title for name in old_moderators], cur_moderators=[profiles[name].title for name in cur_moderators], prev_moderators=[profiles[name].title for name in prev_moderators]) if isinstance(body, unicode): body = body.encode("UTF-8") msg.set_payload(body, "UTF-8") msg.set_type('text/html') mailer.send(to_addrs, msg)
def evolve(context): out = codecs.getwriter('UTF-8')(sys.stdout) # Fix strange user db inconsistency from (hopefully) distant past. # Some users in the db have user info but their login is missing from # the logins dict. users = find_users(context) logins = users.logins for id in users.byid.keys(): login = users.get_by_id(id)['login'] if login not in logins: logins[login] = id # Convert profiles to new workflow. workflow = get_workflow(IProfile, 'security') for profile in find_profiles(context).values(): print >> out, ("Updating security workflow for profile: %s" % profile.__name__) if not hasattr(profile, 'security_state'): # 'formeruser' was added without initializing workflow, oops. workflow.initialize(profile) workflow.transition_to_state(profile, None, 'inactive') continue assert profile.security_state == 'profile' assert not has_custom_acl(profile) profile.security_state = 'active' workflow.reset(profile)
def evolve(context): out = codecs.getwriter('UTF-8')(sys.stdout) # Fix strange user db inconsistency from (hopefully) distant past. # Some users in the db have user info but their login is missing from # the logins dict. users = find_users(context) logins = users.logins for id in users.byid.keys(): login = users.get_by_id(id)['login'] if login not in logins: logins[login] = id # Convert profiles to new workflow. workflow = get_workflow(IProfile, 'security') for profile in find_profiles(context).values(): print >>out, ("Updating security workflow for profile: %s" % profile.__name__) if not hasattr(profile, 'security_state'): # 'formeruser' was added without initializing workflow, oops. workflow.initialize(profile) workflow.transition_to_state(profile, None, 'inactive') continue assert profile.security_state == 'profile' assert not has_custom_acl(profile) profile.security_state = 'active' workflow.reset(profile)
def evolve(root): former_id = 'formeruser' profiles = find_profiles(root) search = ICatalogSearch(root) catalog = find_catalog(root) creators = catalog['creator']._fwd_index.keys() modifiers = catalog['modified_by']._fwd_index.keys() userids = set(creators) | set(modifiers) for userid in userids: if userid not in profiles: if former_id not in profiles: workflow = get_workflow(IProfile, 'security') former_id = make_unique_name(profiles, 'formeruser') print "Creating profile for former user content:", former_id former_profile = create_content( IProfile, firstname='Former', lastname='User' ) profiles[former_id] = former_profile workflow.initialize(former_profile) workflow.transition_to_state(former_profile, None, 'inactive') count, docids, resolver = search(creator=userid) for docid in docids: doc = resolver(docid) print "Updating 'creator' for", model_path(doc) doc.creator = former_id count, docids, resolver = search(modified_by=userid) for docid in docids: doc = resolver(docid) print "Updating 'modified_by' for", model_path(doc) doc.modified_by = former_id
def finder(context, request): if IChatterbox.providedBy(request.context): userid = request.view_name path = request.path_info path = path[path.index(userid) + len(userid):] parts = path.split('/') view_name = '' if len(parts) > 1: view_name = parts[1] adapters = request.registry.adapters view_callable = adapters.lookup( (IViewClassifier, request.request_iface, providedBy( request.context)), IView, name=view_name, default=None) if view_callable is not None: profiles = find_profiles(request.context) profile = profiles.get(userid) if profile: request.chatter_user_id = userid response = view_callable(request.context, request) return response debug = asbool(request.registry.settings.get('debug', 'false')) if not debug: response = errorpage(context, request) return response return HTTPNotFound()
def sync(self, data): context = self.context timestamp = data.pop('timestamp', None) if timestamp: context.usersync_timestamp = timestamp elif hasattr(context, 'usersync_timestamp'): del context.usersync_timestamp deactivate_missing = data.pop('deactivate_missing', False) if deactivate_missing: profiles = find_profiles(self.context) missing = set([ p.__name__ for p in profiles.values() if p.security_state == 'active' and getattr(p, 'usersync_managed', False) ]) else: missing = Empty() users = data.pop('users') for user in users: self.syncuser(user, missing) if data: raise ValueError("Unrecognized keys in user sync data: %s" % data.keys()) if missing: users = find_users(self.context) for username in missing: profile = profiles[username] workflow = get_workflow(IProfile, 'security', profile) workflow.transition_to_state(profile, None, 'inactive') users.remove(username)
def messages(context, request): layout = request.layout_manager.layout info = {} userid = '' info['latest_messages_users'] = latest_messages_users_json( context, request) ## temporary for laying out, will be an ajax call from the frontend info['user_messages'] = [] info['correspondent'] = None if info['latest_messages_users']: userid = info['latest_messages_users'][0]['userid'] user_messages = user_messages_json(context, request, userid) info['user_messages'] = user_messages['data'] info['correspondent'] = user_messages['correspondent'] ## info['api'] = TemplateAPI(context, request, 'Messages') chatter_url = resource_url(find_chatter(context), request) info['chatter_url'] = chatter_url info['chatter_form_url'] = '%sadd_chatter.html' % chatter_url info['context_tools'] = get_context_tools(request, selected='messages') info['page_title'] = 'Chatter: Messages' info['recipient'] = userid current_userid = authenticated_userid(request) profiles = find_profiles(request.context) profile = profiles.get(current_userid) if profile is not None: profile.last_chatter_query = datetime.datetime.utcnow() return info
def __init__(self, context, request): self.context = context self.request = request self.community = find_interface(context, ICommunity) self.profiles = find_profiles(context) self.api = TemplateAPI(context, request) self.filestore = get_filestore(context, request, 'accept-invitation')
def wrap_external_link_view(context, request): external_url = request.params.get('external_url', None) remote_addr = request.environ.get('REMOTE_ADDR', None) if not external_url: raise ValueError, 'No external_url provided' profiles = find_profiles(context) userid = authenticated_userid(request) if not userid: raise Forbidden('You are not logged in') profile = profiles.get(userid) if not profile: raise Forbidden('No profile found for user %s' % userid) first_name = profile.firstname last_name = profile.lastname key = generate_ticket(context, first_name, last_name, profile.email, remote_addr, external_url) if external_url.find('?') != -1: location = '%s&karl_authentication_ticket=%s' % (external_url, key) else: location = '%s?karl_authentication_ticket=%s' % (external_url, key) return HTTPFound(location = location)
def preview_wikipage_view(context, request, WikiPage=WikiPage, tz=None): version_num = int(request.params['version_num']) repo = find_repo(context) for version in repo.history(context.docid): if version.version_num == version_num: break else: raise NotFound("No such version: %d" % version_num) page = WikiPage() page.__parent__ = context.__parent__ page.revert(version) is_front_page = (context.__name__ == 'front_page') if is_front_page: community = find_interface(context, ICommunity) page_title = '%s Community Wiki Page' % community.title else: page_title = page.title profiles = find_profiles(context) author = profiles[version.user] # Extra paranoia, probably not strictly necessary. I just want to make # extra special sure that the temp WikiPage object we create above # doesn't accidentally get attached to the persistent object graph. transaction.doom() return { 'date': format_local_date(version.archive_time, tz), 'author': author.title, 'title': page_title, 'body': page.cook(request), }
def handle_submit(self, converted): try: context = self.context request = self.request key = request.params.get('key') if not key or len(key) != 40: e = ResetFailed() e.page_title = 'Password Reset URL Problem' raise e users = find_users(context) user = users.get_by_login(converted['login']) if user is None: raise ValidationError(login='******') userid = user.get('id') if userid is None: userid = user['login'] profiles = find_profiles(context) profile = profiles.get(userid) if profile is None: raise ValidationError(login='******') if key != getattr(profile, 'password_reset_key', None): e = ResetFailed() e.page_title = 'Password Reset Confirmation Problem' raise e now = datetime.datetime.now() t = getattr(profile, 'password_reset_time', None) if t is None or now - t > max_reset_timedelta: e = ResetFailed() e.page_title = 'Password Reset Confirmation Key Expired' raise e # The key matched. Clear the key and reset the password. profile.password_reset_key = None profile.password_reset_time = None password = converted['password'].encode('UTF-8') users.change_password(userid, password) request.session['password_expired'] = False profile.password_expiration_date = (datetime.datetime.utcnow() + datetime.timedelta(days=180)) max_retries = request.registry.settings.get('max_login_retries', 8) context.login_tries[converted['login']] = max_retries page_title = 'Password Reset Complete' api = TemplateAPI(context, request, page_title) return render_to_response( 'templates/reset_complete.pt', dict(api=api, login=converted['login'], password=converted['password']), request=request, ) except ResetFailed, e: api = TemplateAPI(context, request, e.page_title) return render_to_response('templates/reset_failed.pt', dict(api=api), request=request)
def get_wikitoc_data(context, request): wikiparent = context.__parent__ search = getAdapter(context, ICatalogSearch) count, docids, resolver = search(path=resource_path(wikiparent), interfaces=[ IWikiPage, ]) items = [] profiles = find_profiles(context) for docid in docids: entry = resolver(docid) tags = getMultiAdapter((entry, request), ITagQuery).tagswithcounts author = entry.creator profile = profiles.get(author, None) profile_url = resource_url(profile, request) if profile is not None: author_name = '%s %s' % (profile.firstname, profile.lastname) else: author_name = author items.append( dict( id="id_" + entry.__name__, name=entry.__name__, title=entry.title, author=author, author_name=author_name, profile_url=profile_url, tags=[tag['tag'] for tag in tags], created=entry.created.isoformat(), modified=entry.modified.isoformat(), )) result = dict(items=items, ) return result
def modified_by_title(self): if self._modified_by_title is None: profiles = find_profiles(self.context) profile_name = self.context.modified_by or self.context.creator profile = self._find_profile(profile_name) self._modified_by_title = profile and profile.title return self._modified_by_title
def __init__(self, context, request, page_title=None): self.settings = dict(get_settings(context)) self.settings.update(self.config_settings) self.site = site = find_site(context) self.context = context self.request = request self.userid = authenticated_userid(request) self.app_url = app_url = request.application_url self.profile_url = app_url + '/profiles/%s' % self.userid self.here_url = self.context_url = resource_url(context, request) self.view_url = resource_url(context, request, request.view_name) self.read_only = not is_normal_mode(request.registry) self.static_url = get_static_url(request) self.resource_devel_mode = is_resource_devel_mode() self.browser_upgrade_url = request.registry.settings.get( 'browser_upgrade_url', '') # this data will be provided for the client javascript self.karl_client_data = {} # Provide a setting in the INI to fully control the entire URL # to the static. This is when the proxy runs a different port # number, or to "pipeline" resources on a different URL path. full_static_path = self.settings.get('full_static_path', False) if full_static_path: if '%d' in full_static_path: # XXX XXX note self._start_time is needed... and not _start_time # XXX XXX since this was a trivial bug, there is chance that # XXX XXX this actually never runs! TODO testing??? full_static_path = full_static_path % self._start_time self.static_url = full_static_path self.page_title = page_title self.system_name = self.title = self.settings.get('title', 'KARL') self.user_is_admin = 'group.KarlAdmin' in effective_principals(request) self.can_administer = has_permission('administer', site, request) self.can_email = has_permission('email', site, request) self.admin_url = resource_url(site, request, 'admin.html') date_format = get_user_date_format(context, request) self.karl_client_data['date_format'] = date_format # XXX XXX XXX This will never work from peoples formish templates # XXX XXX XXX (edit_profile and derivates) because, in those form # XXX XXX XXX controllers, the api is instantiated from __init__, # XXX XXX XXX where request.form is still unset!!! (From all other # XXX XXX XXX formcontrollers the api is instantiated from __call__, # XXX XXX XXX which is why this works. A chicken-and-egg problem, really. if hasattr(request, 'form') and getattr(request.form, 'errors', False): # This is a failed form submission request, specify an error message self.error_message = u'Please correct the indicated errors.' self.site_announcements = getattr(self.site, "site_announcements", []) profiles = find_profiles(self.site) profile = profiles is not None and profiles.get(self.userid, None) or None self.unseen_site_announcements = [] if profile is not None and hasattr(profile, "_seen_announcements") \ and hasattr(site, "site_announcements"): for item in site.site_announcements: if item['hash'] not in profile._seen_announcements: self.unseen_site_announcements.append(item)
def modified_by_url(self): if self._modified_by_url is None: profiles = find_profiles(self.context) profile_name = self.context.modified_by or self.context.creator profile = self._find_profile(profile_name) self._modified_by_url = profile and resource_url(profile, self.request) return self._modified_by_url
def creator_url(self): if self._profiles is None: self._profiles = find_profiles(self.context) if self._profile is None: self._profile = self._profiles.get(self.context.creator, None) if self._creator_url is None: self._creator_url = resource_url(self._profile, self.request) return self._creator_url
def creator_title(self): if self._profiles is None: self._profiles = find_profiles(self.context) if self._profile is None: self._profile = self._profiles.get(self.context.creator, None) if self._creator_title is None: self._creator_title = getattr(self._profile, "title", "no profile title") return self._creator_title
def form_defaults(self): records = [] community = self.community profiles = find_profiles(self.context) moderator_names = community.moderator_names view_type = self.request.GET.get('type', 'moderators') if view_type == 'moderators': for mod_name in moderator_names: profile = profiles[mod_name] sortkey = (0, '%s, %s' % (profile.lastname, profile.firstname)) record = { 'sortkey': sortkey, 'name': mod_name, 'title': profile.title, 'moderator': True, 'member': True, 'resend': False, 'remove': False, 'invite': False, } records.append(record) if view_type == 'members': member_batch = self.member_batch = _member_profile_batch( self.context, self.request, 100) member_entries = member_batch['entries'] for i in range(len(member_entries)): profile = member_entries[i] sortkey = (1, '%s, %s' % (profile.lastname, profile.firstname)) record = { 'sortkey': sortkey, 'name': profile.__name__, 'title': profile.title, 'member': True, 'moderator': False, 'resend': False, 'remove': False, 'invite': False, } records.append(record) if view_type == 'invitations': for invitation in self._getInvitations(): sortkey = (2, invitation.email) record = { 'sortkey': sortkey, 'title': invitation.email, 'name': invitation.__name__, 'member': False, 'moderator': False, 'resend': False, 'remove': False, 'invite': True, } records.append(record) records.sort(key=lambda x: x['sortkey']) return {'members': records}
def show_forum_view(context, request): page_title = context.title api = TemplateAPI(context, request, page_title) actions = [] if has_permission('create', context, request): actions.append(('Add Forum Topic', 'add_forum_topic.html')) if has_permission('edit', context, request): actions.append(('Edit', 'edit.html')) if has_permission('delete', context, request): actions.append(('Delete', 'delete.html')) profiles = find_profiles(context) karldates = getUtility(IKarlDates) topic_batch = get_topic_batch(context, request) topic_entries = topic_batch['entries'] topics = [] for topic in topic_entries: D = {} profile = profiles.get(topic.creator) posted_by = getattr(profile, 'title', None) date = karldates(topic.created, 'longform') D['url'] = resource_url(topic, request) D['title'] = topic.title D['posted_by'] = posted_by D['date'] = date D['number_of_comments'] = len(topic['comments']) topics.append(D) # In the intranet side, the backlinks should go to the show_forums # view (the default) forums = context.__parent__ backto = { 'href': resource_url(forums, request), 'title': forums.title, } # Get a layout layout_provider = get_layout_provider(context, request) layout = layout_provider('generic') ux2_layout = request.layout_manager.layout ux2_layout.section_style = "none" return render_to_response( 'templates/show_forum.pt', dict(api = api, actions = actions, title = context.title, topics = topics, batch_info = topic_batch, backto=backto, old_layout=layout), request=request, )