def db_generate_password_reset_token(session, user): """ Transaction for issuing password reset tokens :param session: An ORM session :param user: The user for which issuing a password reset token """ user.reset_password_token = generateRandomKey() user.reset_password_date = datetime_now() if user.last_login > datetime_null(): template = 'password_reset_validation' else: template = 'account_activation' user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': template, 'user': user_desc, 'reset_token': user.reset_password_token, 'node': db_admin_serialize_node(session, user.tid, user.language), 'notification': db_get_notification(session, user.tid, user.language) } State.format_and_send_mail(session, user.tid, user_desc, template_vars)
def db_user_update_user(session, tid, user_session, request): """ Transaction for updating an existing user :param session: An ORM session :param tid: A tenant ID :param user_session: A session of the user invoking the transaction :param request: A user request data :return: A user model """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] user.public_name = request['public_name'] if request[ 'public_name'] else request['name'] if request['password']: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, request['old_password'], user.salt, user.password): raise errors.InvalidOldPassword user_session.cc = set_user_password(tid, user, request['password'], user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey() user_desc = user_serialize_user(session, user, user.language) user_desc['mail_address'] = request['mail_address'] template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, tid, user.language), 'notification': db_get_notification(session, tid, user.language) } State.format_and_send_mail(session, tid, user_desc, template_vars) parse_pgp_options(user, request) return user
def signup(session, request, language): """ Transact handling the registration of a new signup :param session: An ORM session :param request: A user request :param language: A language of the request """ config = ConfigFactory(session, 1) if not config.get_val('enable_signup'): raise errors.ForbiddenOperation request['activation_token'] = generateRandomKey(32) request['language'] = language # Delete the tenants created for the same subdomain that have still not been activated # Ticket reference: https://github.com/globaleaks/GlobaLeaks/issues/2640 subquery = session.query(models.Tenant.id) \ .filter(models.Signup.subdomain == request['subdomain'], not_(models.Signup.activation_token.is_(None)), models.Tenant.id == models.Signup.tid, models.Tenant.subdomain == models.Signup.subdomain) \ .subquery() session.query(models.Tenant).filter( models.Tenant.id.in_(subquery)).delete(synchronize_session=False) tenant_id = db_preallocate_tenant(session, { 'label': request['subdomain'], 'subdomain': request['subdomain'] }).id signup = models.Signup(request) signup.tid = tenant_id session.add(signup) # We need to send two emails # # The first one is sent to the platform owner with the activation email. # # The second goes to the instance administrators notifying them that a new # platform has been added. signup_dict = serialize_signup(signup) # Email 1 - Activation Link template_vars = { 'type': 'signup', 'node': db_admin_serialize_node(session, 1, language), 'notification': db_get_notification(session, 1, language), 'signup': signup_dict } State.format_and_send_mail(session, 1, {'mail_address': signup.email}, template_vars) # Email 2 - Admin Notification for user_desc in db_get_users(session, 1, 'admin'): template_vars = { 'type': 'admin_signup_alert', 'node': db_admin_serialize_node(session, 1, user_desc['language']), 'notification': db_get_notification(session, 1, user_desc['language']), 'user': user_desc, 'signup': signup_dict } State.format_and_send_mail(session, 1, user_desc, template_vars)
def signup_activation(session, token, hostname, language): """ Transaction registering the activation of a platform registered via signup :param session: An ORM session :param token: A activation token :param language: A language of the request """ config = ConfigFactory(session, 1) if not config.get_val('enable_signup'): raise errors.ForbiddenOperation ret = session.query(models.Signup, models.Tenant) \ .filter(models.Signup.activation_token == token, models.Tenant.id == models.Signup.tid).one_or_none() if ret is None: return {} signup, tenant = ret[0], ret[1] signup.activation_token = None mode = config.get_val('mode') db_initialize_tenant(session, tenant, mode) password_admin = generateRandomKey(16) password_receiver = generateRandomKey(16) node_name = signup.organization_name if signup.organization_name else signup.subdomain wizard = { 'node_language': signup.language, 'node_name': node_name, 'admin_username': '******', 'admin_name': signup.name + ' ' + signup.surname, 'admin_password': password_admin, 'admin_mail_address': signup.email, 'receiver_username': '******', 'receiver_name': signup.name + ' ' + signup.surname, 'receiver_password': password_receiver, 'receiver_mail_address': signup.email, 'profile': 'default', 'skip_recipient_account_creation': False, 'enable_developers_exception_notification': True } db_wizard(session, signup.tid, hostname, wizard) template_vars = { 'type': 'activation', 'node': db_admin_serialize_node(session, 1, language), 'notification': db_get_notification(session, 1, language), 'signup': serialize_signup(signup), 'password_admin': wizard['admin_password'], 'password_recipient': wizard['receiver_password'] } State.format_and_send_mail(session, 1, {'mail_address': signup.email}, template_vars) db_refresh_memory_variables(session, [signup.tid])
def db_user_update_user(session, tid, user_session, request): """ Updates the specified user. This version of the function is specific for users that with comparison with admins can change only few things: - real name - email address - preferred language - the password (with old password check) - pgp key raises: globaleaks.errors.ResourceNotFound` if the receiver does not exist. """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] new_password = request['password'] old_password = request['old_password'] if new_password: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, old_password, user.salt, user.password): raise errors.InvalidOldPassword # Regenerate the password hash only if different from the best choice on the platform if user.hash_alg != GCE.HASH: user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() password_hash = GCE.hash_password(new_password, user.salt) # Check that the new password is different form the current password if user.password == password_hash: raise errors.PasswordReuseError user.password = password_hash user.password_change_date = datetime_now() if State.tenant_cache[tid].encryption: enc_key = GCE.derive_key(request['password'].encode(), user.salt) if not user_session.cc: # Th First first password change triggers the generation # of the user encryption private key and its backup user_session.cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_bkp_key, user.crypto_rec_key = GCE.generate_recovery_key( user_session.cc) # If the user had already enabled two factor before encryption was not enable # encrypt the two factor secret if user.two_factor_secret: user.two_factor_secret = GCE.asymmetric_encrypt( user.crypto_pub_key, user.two_factor_secret) user.crypto_prv_key = GCE.symmetric_encrypt( enc_key, user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey(32) user_desc = user_serialize_user(session, user, user.language) user_desc['mail_address'] = request['mail_address'] template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, tid, user.language), 'notification': db_get_notification(session, tid, user.language) } State.format_and_send_mail(session, tid, user_desc, template_vars) # If the platform allows users to change PGP keys, process it if State.tenant_cache[tid]['enable_user_pgp_key_upload'] is True: parse_pgp_options(user, request) return user
def db_user_update_user(session, tid, user_session, request): """ Updates the specified user. This version of the function is specific for users that with comparison with admins can change only few things: - real name - email address - preferred language - the password (with old password check) - pgp key raises: globaleaks.errors.ResourceNotFound` if the receiver does not exist. """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] new_password = request['password'] old_password = request['old_password'] if new_password: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, old_password, user.salt, user.password): raise errors.InvalidOldPassword user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(new_password, user.salt) user.password_change_date = datetime_now() if State.tenant_cache[1].encryption: enc_key = GCE.derive_key(request['password'].encode(), user.salt) if not user_session.cc: user_session.cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_prv_key = GCE.symmetric_encrypt(enc_key, user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey(32) user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, 1, user.language), 'notification': db_get_notification(session, tid, user.language) } State.format_and_send_mail(session, tid, user_desc, template_vars) # If the platform allows users to change PGP keys, process it if State.tenant_cache[tid]['enable_user_pgp_key_upload'] is True: parse_pgp_options(user, request) return user