def get_private_graphs_cif(self): graphs = [x for x in self.get_user_graph_cif() if x] return { "@context": [ "http://purl.org/catalyst/jsonld", {"local": get_global_base_url() + '/data/'}], "@graph": graphs }
def send_change_password_email( request, profile, email=None, subject=None, text_body=None, html_body=None, discussion=None, sender_name=None, welcome=False, immediate=False): mailer = get_mailer(request) localizer = request.localizer route_maker = create_get_route(request, discussion) data = dict( assembl="Assembl", name=profile.name, confirm_url=get_global_base_url() + route_maker( 'welcome' if welcome else 'do_password_change', token=password_change_token(profile))) sender_email = config.get('assembl.admin_email') if discussion: data.update(dict( discussion_topic=discussion.topic, discussion_url=discussion.get_url())) sender_name = sender_name or discussion.topic if sender_name: sender_name = normalize_email_name(sender_name) sender = '"%s" <%s>' % (sender_name, sender_email) sender_name = Header(sender_name, 'utf-8').encode() if len(sender) > 255: sender = sender_email else: sender = sender_email subject = (subject or localizer.translate( _("Request for password change"))).format(**data) #subject = Header(subject, 'utf-8').encode() # Fails in some cases??? if text_body is None or html_body is not None: # if text_body and no html_body, html_body remains None. html_body = html_body or localizer.translate(_(u"""<p>Hello, {name}!</p> <p>We have received a request to change the password on your {assembl} account. Please <a href="{confirm_url}">click here to confirm your password change</a>.</p> <p>If you did not ask to reset your password please disregard this email.</p> <p>Best regards,<br />The {assembl} Team</p> """)) text_body = text_body or localizer.translate(_(u"""Hello, {name}! We have received a request to change the password on your {assembl} account. To confirm your password change please click on the link below. <{confirm_url}> If you did not ask to reset your password please disregard this email. Best regards, The {assembl} Team """)) message = Message( subject=subject, sender=sender, recipients=["%s <%s>" % ( profile.name, email or profile.get_preferred_email())], body=text_body.format(**data), html=html_body.format(**data)) if immediate: mailer.send_immediately(message) else: mailer.send(message)
def get_base_url(self): """Get the base URL of this server Tied to discussion so that we can support virtual hosts or communities in the future and access the urls when we can't rely on pyramid's current request (such as when celery generates notifications) Temporarily equivalent to get_global_base_url """ return get_global_base_url()
def login_view(request): if request.scheme == "http"\ and asbool(config.get("accept_secure_connection")): return HTTPFound(get_global_base_url(True) + request.path_qs) force_providers = request.matched_route.name.endswith('_forceproviders') if request.matched_route.name == 'contextual_login': contextual_login = get_social_autologin(request) if contextual_login: return HTTPFound(contextual_login) return get_login_context(request, force_providers)
def get_discussion_url(): from ..auth.util import get_current_discussion from assembl.lib.frontend_urls import FrontendUrls from assembl.lib.utils import get_global_base_url discussion = get_current_discussion() if discussion: front_end_urls = FrontendUrls(discussion) return front_end_urls.get_discussion_url() else: return get_global_base_url()
def get_base_url(self, require_secure=None): """Get the base URL of this server Tied to discussion so that we can support virtual hosts or communities in the future and access the urls when we can't rely on pyramid's current request (such as when celery generates notifications) Temporarily equivalent to get_global_base_url """ return get_global_base_url(require_secure)
def get_public_graphs_cif(self): graphs = [x for x in self.get_extract_graphs_cif() if x] graphs.append({ "@id": "assembl:discussion_%d_data" % (self.id), "@graph": [x for x in self.get_discussion_graph_cif() if x] }) return { "@context": [ "http://purl.org/catalyst/jsonld", {"local": get_global_base_url() + '/data/'}], "@graph": graphs }
def assembl_register_view(request): slug = request.matchdict.get('discussion_slug', "") next_view = handle_next_view(request) if not request.params.get('email'): if request.scheme == "http"\ and asbool(config.get("accept_secure_connection")): return HTTPFound(get_global_base_url(True) + request.path_qs) response = get_login_context(request) return response forget(request) session = AgentProfile.default_db localizer = request.localizer name = request.params.get('name', '').strip() if not name or len(name) < 3: return dict(get_default_context(request), error=localizer.translate(_( "Please use a name of at least 3 characters"))) password = request.params.get('password', '').strip() password2 = request.params.get('password2', '').strip() email = request.params.get('email', '').strip() if not is_email(email): return dict(get_default_context(request), error=localizer.translate(_( "This is not a valid email"))) email = EmailString.normalize_email_case(email) # Find agent account to avoid duplicates! if session.query(AbstractAgentAccount).filter_by( email_ci=email, verified=True).count(): return dict(get_default_context(request), error=localizer.translate(_( "We already have a user with this email."))) if password != password2: return dict(get_default_context(request), error=localizer.translate(_( "The passwords should be identical"))) # TODO: Validate password quality # otherwise create. validate_registration = asbool(config.get( 'assembl.validate_registration_emails')) user = User( name=name, password=password, verified=not validate_registration, creation_date=datetime.utcnow() ) email_account = EmailAccount( email=email, verified=not validate_registration, profile=user ) session.add(user) session.add(email_account) discussion = discussion_from_request(request) if discussion: permissions = get_permissions(Everyone, discussion.id) if not (P_SELF_REGISTER in permissions or P_SELF_REGISTER_REQUEST in permissions): discussion = None if discussion: _now = datetime.utcnow() agent_status = AgentStatusInDiscussion( agent_profile=user, discussion=discussion, first_visit=_now, last_visit=_now, user_created_on_this_discussion=True) session.add(agent_status) session.flush() if not validate_registration: if asbool(config.get('pyramid.debug_authorization')): # for debugging purposes from assembl.auth.password import email_token print "email token:", request.route_url( 'user_confirm_email', token=email_token(email_account)) headers = remember(request, user.id) user.last_login = datetime.utcnow() request.response.headerlist.extend(headers) if discussion: maybe_auto_subscribe(user, discussion) # TODO: Tell them to expect an email. return HTTPFound(location=next_view) return HTTPFound(location=maybe_contextual_route( request, 'confirm_emailid_sent', email_account_id=email_account.id))
def get_default_context(request, **kwargs): kwargs.update(default_context) from ..auth.util import get_user, get_current_discussion if request.scheme == "http"\ and asbool(config.get("require_secure_connection")): raise HTTPFound(get_global_base_url(True) + request.path_qs) react_url = '/static2' use_webpack_server = asbool(config.get('use_webpack_server')) if use_webpack_server: # Allow to specify a distinct webpack_host in configuration. # Useful for development tests of social auth through a reverse tunnel. # Otherwise fallback on public_hostname, then localhost. webpack_host = config.get( 'webpack_host', config.get('public_hostname', 'localhost')) react_url = 'http://%s:%d' % ( webpack_host, int(config.get('webpack_port', 8000))) socket_proxied = asbool(config.get('changes_websocket_proxied')) websocket_port = None if socket_proxied \ else config.get('changes_websocket_port') secure_socket = socket_proxied and ( asbool(config.get("require_secure_connection")) or (asbool(config.get("accept_secure_connection")) and request.url.startswith('https:'))) application_url = get_global_base_url() socket_url = get_global_base_url( secure_socket, websocket_port) + config.get('changes_prefix') localizer = request.localizer _ = TranslationStringFactory('assembl') user = get_user(request) if user and user.username: user_profile_edit_url = request.route_url( 'profile_user', type='u', identifier=user.username.username) elif user: user_profile_edit_url = request.route_url( 'profile_user', type='id', identifier=user.id) else: user_profile_edit_url = None web_analytics_piwik_script = config.get( 'web_analytics_piwik_script') or False discussion = get_current_discussion() if (web_analytics_piwik_script and discussion and discussion.web_analytics_piwik_id_site): web_analytics_piwik_script = web_analytics_piwik_script % ( discussion.web_analytics_piwik_id_site, discussion.web_analytics_piwik_id_site) else: web_analytics_piwik_script = False web_analytics_piwik_custom_variable_size = config.get('web_analytics_piwik_custom_variable_size') if not web_analytics_piwik_custom_variable_size: web_analytics_piwik_custom_variable_size = 5 help_url = config.get('help_url') or '' if discussion and discussion.help_url: help_url = discussion.help_url if help_url and "%s" in help_url: help_url = help_url % localizer.locale_name first_login_after_auto_subscribe_to_notifications = False if (user and discussion and discussion.id and user.is_first_visit and discussion.subscribe_to_notifications_on_signup and user.is_participant(discussion.id)): first_login_after_auto_subscribe_to_notifications = True locales = config.get('available_languages').split() countries_for_locales = defaultdict(set) for locale in locales: countries_for_locales[get_language(locale)].add(get_country(locale)) show_locale_country = { locale: (len(countries_for_locales[get_language(locale)]) > 1) for locale in locales} jedfilename = os.path.join( os.path.dirname(__file__), '..', 'locale', localizer.locale_name, 'LC_MESSAGES', 'assembl.jed.json') if not os.path.exists(jedfilename) and '_' in localizer.locale_name: jedfilename = os.path.join( os.path.dirname(__file__), '..', 'locale', get_language(localizer.locale_name), 'LC_MESSAGES', 'assembl.jed.json') assert os.path.exists(jedfilename) from ..models.facebook_integration import language_sdk_existance fb_lang_exists, fb_locale = language_sdk_existance( get_language(localizer.locale_name), countries_for_locales) def process_export_list(ls): return map(lambda s: s.strip(), ls.split(",")) social_settings = { 'fb_export_permissions': config.get('facebook.export_permissions'), 'fb_debug': asbool(config.get('facebook.debug_mode')), 'fb_app_id': config.get('facebook.consumer_key'), 'fb_api_version': config.get('facebook.api_version') or '2.2', 'supported_exports': process_export_list( config.get('supported_exports_list')) } # A container for all analytics related settings. All future # analytics based settings that will be exposed to the templates # should be included in this dictionary analytics_settings = { 'enabled': True if web_analytics_piwik_script else False, } if analytics_settings.get('enabled', False): analytics_settings['piwik'] = { 'script': web_analytics_piwik_script, 'host': config.get('piwik_host') } analytics_url = config.get('web_analytics_piwik_url', None) get_route = create_get_route(request, discussion) providers = get_provider_data(get_route) errors = request.session.pop_flash() if kwargs.get('error', None): errors.append(kwargs['error']) if errors: kwargs['error'] = '<br />'.join(errors) messages = request.session.pop_flash('message') if messages: kwargs['messages'] = '<br />'.join(messages) admin_email = config.get('assembl.admin_email', None) # If an admin_email is improperly configured, raise an error if admin_email is None or admin_email is '': raise HTTPInternalServerError(explanation="Assembl MUST have an admin_email configured in order to operate.") theme_name, theme_relative_path = get_theme_info(discussion) node_env = os.getenv('NODE_ENV', 'production') under_test = bool(config.get('under_test') or False) base = dict( kwargs, request=request, application_url=application_url, get_route=get_route, user=user, templates=get_template_views(), discussion=discussion or {}, # Templates won't load without a discussion object preferences=discussion.preferences if discussion else {}, user_profile_edit_url=user_profile_edit_url, locale=localizer.locale_name, locales=locales, fb_lang_exists=fb_lang_exists, fb_locale=fb_locale, social_settings=social_settings, show_locale_country=show_locale_country, NODE_ENV=node_env, theme_name=theme_name, theme_relative_path=theme_relative_path, minified_js=config.get('minified_js') or False, web_analytics=analytics_settings, analytics_url=analytics_url, help_url=help_url, socket_url=socket_url, REACT_URL=react_url, elasticsearch_lang_indexes=config.get('elasticsearch_lang_indexes', 'en fr'), first_login_after_auto_subscribe_to_notifications=first_login_after_auto_subscribe_to_notifications, sentry_dsn=config.get('sentry_dsn', ''), activate_tour=str(config.get('activate_tour') or False).lower(), providers=providers, providers_json=json.dumps(providers), translations=io.open(jedfilename, encoding='utf-8').read(), admin_email=admin_email, under_test=under_test ) base.update({ "opengraph_locale": get_opengraph_locale(request), "get_description": get_description(request), "get_landing_page_image": get_landing_page_image(), "private_social_sharing": private_social_sharing(), "get_topic": get_topic(request), "get_discussion_url": get_discussion_url(), "discussion_title": discussion_title(), }) base.update(get_v1_resources_hash()) return base
def get_url(self, *args): return get_global_base_url(True)
def get_default_context(request, **kwargs): kwargs.update(default_context) from ..auth.util import get_user, get_current_discussion if request.scheme == "http"\ and asbool(config.get("require_secure_connection")): raise HTTPFound(get_global_base_url(True) + request.path_qs) react_url = '/static2' use_webpack_server = asbool(config.get('use_webpack_server')) if use_webpack_server: # Allow to specify a distinct webpack_host in configuration. # Useful for development tests of social auth through a reverse tunnel. # Otherwise fallback on public_hostname, then localhost. webpack_host = config.get('webpack_host', config.get('public_hostname', 'localhost')) react_url = 'http://%s:%d' % (webpack_host, int(config.get('webpack_port', 8000))) socket_proxied = asbool(config.get('changes_websocket_proxied')) websocket_port = None if socket_proxied \ else config.get('changes_websocket_port') secure_socket = socket_proxied and ( asbool(config.get("require_secure_connection")) or (asbool(config.get("accept_secure_connection")) and request.url.startswith('https:'))) application_url = get_global_base_url() socket_url = get_global_base_url( secure_socket, websocket_port) + config.get('changes_prefix') localizer = request.localizer _ = TranslationStringFactory('assembl') user = get_user(request) if user and user.username: user_profile_edit_url = request.route_url( 'profile_user', type='u', identifier=user.username.username) elif user: user_profile_edit_url = request.route_url('profile_user', type='id', identifier=user.id) else: user_profile_edit_url = None web_analytics_piwik_script = config.get( 'web_analytics_piwik_script') or False discussion = get_current_discussion() if (web_analytics_piwik_script and discussion and discussion.web_analytics_piwik_id_site): web_analytics_piwik_script = web_analytics_piwik_script % ( discussion.web_analytics_piwik_id_site, discussion.web_analytics_piwik_id_site) else: web_analytics_piwik_script = False web_analytics_piwik_custom_variable_size = config.get( 'web_analytics_piwik_custom_variable_size') if not web_analytics_piwik_custom_variable_size: web_analytics_piwik_custom_variable_size = 5 help_url = config.get('help_url') or '' if discussion and discussion.help_url: help_url = discussion.help_url if help_url and "%s" in help_url: help_url = help_url % localizer.locale_name first_login_after_auto_subscribe_to_notifications = False if (user and discussion and discussion.id and user.is_first_visit and discussion.subscribe_to_notifications_on_signup and user.is_participant(discussion.id)): first_login_after_auto_subscribe_to_notifications = True locales = config.get('available_languages').split() countries_for_locales = defaultdict(set) for locale in locales: countries_for_locales[get_language(locale)].add(get_country(locale)) show_locale_country = { locale: (len(countries_for_locales[get_language(locale)]) > 1) for locale in locales } jedfilename = os.path.join(os.path.dirname(__file__), '..', 'locale', localizer.locale_name, 'LC_MESSAGES', 'assembl.jed.json') if not os.path.exists(jedfilename) and '_' in localizer.locale_name: jedfilename = os.path.join(os.path.dirname(__file__), '..', 'locale', get_language(localizer.locale_name), 'LC_MESSAGES', 'assembl.jed.json') assert os.path.exists(jedfilename) from ..models.facebook_integration import language_sdk_existance fb_lang_exists, fb_locale = language_sdk_existance( get_language(localizer.locale_name), countries_for_locales) def process_export_list(ls): return map(lambda s: s.strip(), ls.split(",")) social_settings = { 'fb_export_permissions': config.get('facebook.export_permissions'), 'fb_debug': asbool(config.get('facebook.debug_mode')), 'fb_app_id': config.get('facebook.consumer_key'), 'fb_api_version': config.get('facebook.api_version') or '2.2', 'supported_exports': process_export_list(config.get('supported_exports_list')) } # A container for all analytics related settings. All future # analytics based settings that will be exposed to the templates # should be included in this dictionary analytics_settings = { 'enabled': True if web_analytics_piwik_script else False, } if analytics_settings.get('enabled', False): analytics_settings['piwik'] = { 'script': web_analytics_piwik_script, 'host': config.get('piwik_host') } analytics_url = config.get('web_analytics_piwik_url', None) get_route = create_get_route(request, discussion) providers = get_provider_data(get_route) errors = request.session.pop_flash() if kwargs.get('error', None): errors.append(kwargs['error']) if errors: kwargs['error'] = '<br />'.join(errors) messages = request.session.pop_flash('message') if messages: kwargs['messages'] = '<br />'.join(messages) admin_email = config.get('assembl.admin_email', None) # If an admin_email is improperly configured, raise an error if admin_email is None or admin_email is '': raise HTTPInternalServerError( explanation= "Assembl MUST have an admin_email configured in order to operate.") theme_name, theme_relative_path = get_theme_info(discussion) node_env = os.getenv('NODE_ENV', 'production') under_test = bool(config.get('under_test') or False) base = dict( kwargs, request=request, application_url=application_url, get_route=get_route, user=user, templates=get_template_views(), discussion=discussion or {}, # Templates won't load without a discussion object preferences=discussion.preferences if discussion else {}, user_profile_edit_url=user_profile_edit_url, locale=localizer.locale_name, locales=locales, fb_lang_exists=fb_lang_exists, fb_locale=fb_locale, social_settings=social_settings, show_locale_country=show_locale_country, NODE_ENV=node_env, theme_name=theme_name, theme_relative_path=theme_relative_path, minified_js=config.get('minified_js') or False, web_analytics=analytics_settings, analytics_url=analytics_url, help_url=help_url, socket_url=socket_url, REACT_URL=react_url, elasticsearch_lang_indexes=config.get('elasticsearch_lang_indexes', 'en fr'), first_login_after_auto_subscribe_to_notifications= first_login_after_auto_subscribe_to_notifications, sentry_dsn=config.get('sentry_dsn', ''), activate_tour=str(config.get('activate_tour') or False).lower(), providers=providers, providers_json=json.dumps(providers), translations=io.open(jedfilename, encoding='utf-8').read(), admin_email=admin_email, under_test=under_test) base.update({ "opengraph_locale": get_opengraph_locale(request), "get_description": get_description(request), "get_landing_page_image": get_landing_page_image(), "private_social_sharing": private_social_sharing(), "get_topic": get_topic(request), "get_discussion_url": get_discussion_url(), "discussion_title": discussion_title(), }) return base
def assembl_register_view(request): slug = request.matchdict.get('discussion_slug', "") next_view = handle_next_view(request) if not request.params.get('email'): if request.scheme == "http"\ and asbool(config.get("accept_secure_connection")): return HTTPFound(get_global_base_url(True) + request.path_qs) response = get_login_context(request) return response forget(request) session = AgentProfile.default_db localizer = request.localizer name = request.params.get('name', '').strip() if not name or len(name) < 3: return dict(get_default_context(request), error=localizer.translate(_( "Please use a name of at least 3 characters"))) password = request.params.get('password', '').strip() password2 = request.params.get('password2', '').strip() email = request.params.get('email', '').strip() if not is_email(email): return dict(get_default_context(request), error=localizer.translate(_( "This is not a valid email"))) email = EmailString.normalize_email_case(email) # Find agent account to avoid duplicates! if session.query(AbstractAgentAccount).filter_by( email_ci=email, verified=True).count(): return dict(get_default_context(request), error=localizer.translate(_( "We already have a user with this email."))) if password != password2: return dict(get_default_context(request), error=localizer.translate(_( "The passwords should be identical"))) # TODO: Validate password quality # otherwise create. validate_registration = asbool(config.get( 'assembl.validate_registration_emails')) user = User( name=name, password=password, verified=not validate_registration, creation_date=datetime.utcnow() ) email_account = EmailAccount( email=email, verified=not validate_registration, profile=user ) session.add(user) session.add(email_account) discussion = discussion_from_request(request) if discussion: permissions = get_permissions(Everyone, discussion.id) if not (P_SELF_REGISTER in permissions or P_SELF_REGISTER_REQUEST in permissions): discussion = None if discussion: _now = datetime.utcnow() agent_status = AgentStatusInDiscussion( agent_profile=user, discussion=discussion, first_visit=_now, last_visit=_now, user_created_on_this_discussion=True) session.add(agent_status) session.flush() if not validate_registration: if asbool(config.get('pyramid.debug_authorization')): # for debugging purposes from assembl.auth.password import email_token print "email token:", request.route_url( 'user_confirm_email', token=email_token(email_account)) headers = remember(request, user.id) user.successful_login() request.response.headerlist.extend(headers) if discussion: maybe_auto_subscribe(user, discussion) # TODO: Tell them to expect an email. return HTTPFound(location=next_view) return HTTPFound(location=maybe_contextual_route( request, 'confirm_emailid_sent', email_account_id=email_account.id))