def lost_password(request): """ Presents lost password page - sends password reset link to specified email address. This link is valid only for 10 minutes """ form = forms.LostPasswordForm(request.POST, csrf_context=request) if request.method == "POST" and form.validate(): user = UserService.by_email(form.email.data) if user: UserService.regenerate_security_code(user) user.security_code_date = datetime.datetime.utcnow() email_vars = { "user": user, "request": request, "email_title": "AppEnlight :: New password request", } UserService.send_email( request, recipients=[user.email], variables=email_vars, template="/email_templates/lost_password.jinja2", ) msg = ( "Password reset email had been sent. " "Please check your mailbox for further instructions." ) request.session.flash(_(msg)) return HTTPFound(location=request.route_url("lost_password")) return {"form": form}
def users_create(request): """ Returns users list """ form = forms.UserCreateForm(MultiDict(request.safe_json_body or {}), csrf_context=request) if form.validate(): log.info("registering user") # probably not needed in the future since this requires root anyways # lets keep this here in case we lower view permission in the future # if request.registry.settings['appenlight.disable_registration']: # return HTTPUnprocessableEntity(body={'error': 'Registration is currently disabled.'}) user = User() # insert new user here DBSession.add(user) form.populate_obj(user) UserService.regenerate_security_code(user) UserService.set_password(user, user.user_password) user.status = 1 if form.status.data else 0 request.session.flash(_("User created")) DBSession.flush() return user.get_dict(exclude_keys=[ "security_code_date", "notes", "security_code", "user_password", ]) else: return HTTPUnprocessableEntity(body=form.errors_json)
def test_regenerate_security_code(self, db_session): created_user = add_user(db_session) old_code = created_user.security_code UserService.regenerate_security_code(created_user) new_code = created_user.security_code assert old_code != new_code assert len(new_code) == 64
def register_user_with_group(user_name, group_name, email, password, db_session): # type: (Str, Str, Str, Str, Session) -> None """ Registers the user if missing and associate him to a group specified by name, also created if missing. :param user_name: name of the user to create (if missing) and to make part of the group (if specified) :param group_name: name of the group to create (if missing and specified) and to make the user join (if not already) :param email: email of the user to be created (if missing) :param password: password of the user to be created (if missing) :param db_session: database connexion to apply changes .. warning:: Should be employed only for **special** users/groups in this module as other expected API behaviour and operations will not be applied (ex: create additional permissions or user-group references). """ if not GroupService.by_group_name(group_name, db_session=db_session): new_group = models.Group(group_name=group_name) # noqa db_session.add(new_group) registered_group = GroupService.by_group_name(group_name=group_name, db_session=db_session) registered_user = UserService.by_user_name(user_name, db_session=db_session) if not registered_user: new_user = models.User(user_name=user_name, email=email) # noqa UserService.set_password(new_user, password) UserService.regenerate_security_code(new_user) db_session.add(new_user) if group_name is not None: registered_user = UserService.by_user_name(user_name, db_session=db_session) else: print_log("User '{}' already exist".format(user_name), level=logging.DEBUG) try: # ensure the reference between user/group exists (user joined the group) user_group_refs = BaseService.all(models.UserGroup, db_session=db_session) user_group_refs_tup = [(ref.group_id, ref.user_id) for ref in user_group_refs] if (registered_group.id, registered_user.id) not in user_group_refs_tup: group_entry = models.UserGroup(group_id=registered_group.id, user_id=registered_user.id) # noqa db_session.add(group_entry) except Exception: # noqa: W0703 # nosec: B110 # in case reference already exists, avoid duplicate error db_session.rollback()
def regenerate_security_code(self): """ .. deprecated:: 0.8 :return: """ return UserService.regenerate_security_code(self)
def users_password(request): """ Sets new password for user account """ user = request.user form = forms.ChangePasswordForm(MultiDict(request.unsafe_json_body), csrf_context=request) form.old_password.user = user if form.validate(): UserService.regenerate_security_code(user) UserService.set_password(user, form.new_password.data) msg = ("Your password got updated. " "Next time log in with your new credentials.") request.session.flash(_(msg)) return True else: return HTTPUnprocessableEntity(body=form.errors_json) return False
def update_user_view(request): """ Update user information by user name. """ user = ar.get_user_matchdict_checked_or_logged(request) new_user_name = ar.get_multiformat_body(request, "user_name", default=user.user_name) new_email = ar.get_multiformat_body(request, "email", default=user.email) new_password = ar.get_multiformat_body(request, "password", default=user.user_password) update_username = user.user_name != new_user_name and new_user_name is not None update_password = user.user_password != new_password and new_password is not None update_email = user.email != new_email and new_email is not None ax.verify_param( any([update_username, update_password, update_email]), is_true=True, with_param=False, # params are not useful in response for this case content={"user_name": user.user_name}, http_error=HTTPBadRequest, msg_on_fail=s.User_PATCH_BadRequestResponseSchema.description) # user name change is admin-only operation if update_username: ax.verify_param( get_constant("MAGPIE_ADMIN_GROUP"), is_in=True, param_compare=uu.get_user_groups_checked(request.user, request.db), with_param=False, http_error=HTTPForbidden, msg_on_fail=s.User_PATCH_ForbiddenResponseSchema.description) # logged user updating itself is forbidden if it corresponds to special users # cannot edit reserved keywords nor apply them to another user forbidden_user_names = [ get_constant("MAGPIE_ADMIN_USER", request), get_constant("MAGPIE_ANONYMOUS_USER", request), get_constant("MAGPIE_LOGGED_USER", request), ] check_user_name_cases = [user.user_name, new_user_name ] if update_username else [user.user_name] for check_user_name in check_user_name_cases: ax.verify_param( check_user_name, not_in=True, param_compare=forbidden_user_names, param_name="user_name", http_error=HTTPForbidden, content={"user_name": str(check_user_name)}, msg_on_fail=s.User_PATCH_ForbiddenResponseSchema.description) if update_username: uu.check_user_info(user_name=new_user_name, check_email=False, check_password=False, check_group=False) existing_user = ax.evaluate_call( lambda: UserService.by_user_name(new_user_name, db_session=request.db), fallback=lambda: request.db.rollback(), http_error=HTTPForbidden, msg_on_fail=s.User_PATCH_ForbiddenResponseSchema.description) ax.verify_param( existing_user, is_none=True, with_param=False, http_error=HTTPConflict, msg_on_fail=s.User_PATCH_ConflictResponseSchema.description) user.user_name = new_user_name if update_email: uu.check_user_info(email=new_email, check_name=False, check_password=False, check_group=False) user.email = new_email if update_password: uu.check_user_info(password=new_password, check_name=False, check_email=False, check_group=False) UserService.set_password(user, new_password) UserService.regenerate_security_code(user) return ax.valid_http(http_success=HTTPOk, detail=s.Users_PATCH_OkResponseSchema.description)
def create_user(user_name, password, email, group_name, db_session): # type: (Str, Optional[Str], Str, Optional[Str], Session) -> HTTPException """ Creates a user if it is permitted and not conflicting. Password must be set to ``None`` if using external identity. Created user will immediately assigned membership to the group matching :paramref:`group_name` (can be :py:data:`MAGPIE_ANONYMOUS_GROUP` for minimal access). If no group is provided, this anonymous group will be applied by default, creating a user effectively without any permissions other than ones set directly for him. Furthermore, the user will also *always* be associated with :py:data:`MAGPIE_ANONYMOUS_GROUP` (if not already explicitly or implicitly requested with :paramref:`group_name`) to allow access to resources with public permission. Argument :paramref:`group_name` **MUST** be an existing group if provided. :returns: valid HTTP response on successful operation. """ def _get_group(grp_name): # type: (Str) -> models.Group ax.verify_param(grp_name, not_none=True, not_empty=True, matches=True, param_compare=ax.PARAM_REGEX, param_name="group_name", http_error=HTTPBadRequest, msg_on_fail=s.UserGroup_Check_BadRequestResponseSchema.description) grp = ax.evaluate_call(lambda: GroupService.by_group_name(grp_name, db_session=db_session), http_error=HTTPForbidden, msg_on_fail=s.UserGroup_GET_ForbiddenResponseSchema.description) ax.verify_param(grp, not_none=True, http_error=HTTPNotFound, with_param=False, msg_on_fail=s.UserGroup_Check_NotFoundResponseSchema.description) return grp # Check that group already exists if group_name is None: group_name = get_constant("MAGPIE_ANONYMOUS_GROUP") is_internal = password is not None check_user_info(user_name, email, password, group_name, check_password=is_internal) group_checked = _get_group(group_name) # Check if user already exists user_checked = ax.evaluate_call(lambda: UserService.by_user_name(user_name=user_name, db_session=db_session), http_error=HTTPForbidden, msg_on_fail=s.User_Check_ForbiddenResponseSchema.description) ax.verify_param(user_checked, is_none=True, with_param=False, http_error=HTTPConflict, msg_on_fail=s.User_Check_ConflictResponseSchema.description) # Create user with specified name and group to assign new_user = models.User(user_name=user_name, email=email) # noqa if is_internal: UserService.set_password(new_user, password) UserService.regenerate_security_code(new_user) ax.evaluate_call(lambda: db_session.add(new_user), fallback=lambda: db_session.rollback(), http_error=HTTPForbidden, msg_on_fail=s.Users_POST_ForbiddenResponseSchema.description) # Fetch user to update fields new_user = ax.evaluate_call(lambda: UserService.by_user_name(user_name, db_session=db_session), http_error=HTTPForbidden, msg_on_fail=s.UserNew_POST_ForbiddenResponseSchema.description) def _add_to_group(usr, grp): # type: (models.User, models.Group) -> None group_entry = models.UserGroup(group_id=grp.id, user_id=usr.id) # noqa ax.evaluate_call(lambda: db_session.add(group_entry), fallback=lambda: db_session.rollback(), http_error=HTTPForbidden, msg_on_fail=s.UserGroup_GET_ForbiddenResponseSchema.description) # Assign user to group new_user_groups = [group_name] _add_to_group(new_user, group_checked) # Also add user to anonymous group if not already done anonym_grp_name = get_constant("MAGPIE_ANONYMOUS_GROUP") if group_checked.group_name != anonym_grp_name: _add_to_group(new_user, _get_group(anonym_grp_name)) new_user_groups.append(anonym_grp_name) return ax.valid_http(http_success=HTTPCreated, detail=s.Users_POST_CreatedResponseSchema.description, content={"user": uf.format_user(new_user, new_user_groups)})
def register(request): """ Render register page with form Also handles oAuth flow for registration """ login_url = request.route_url("ziggurat.routes.sign_in") if request.query_string: query_string = "?%s" % request.query_string else: query_string = "" referrer = "%s%s" % (request.path, query_string) if referrer in [login_url, "/register", "/register?sign_in=1"]: referrer = "/" # never use the login form itself as came_from sign_in_form = forms.SignInForm( came_from=request.params.get("came_from", referrer), csrf_context=request ) # populate form from oAuth session data returned by authomatic social_data = request.session.get("zigg.social_auth") if request.method != "POST" and social_data: log.debug(social_data) user_name = social_data["user"].get("user_name", "").split("@")[0] form_data = {"user_name": user_name, "email": social_data["user"].get("email")} form_data["user_password"] = str(uuid.uuid4()) form = forms.UserRegisterForm(MultiDict(form_data), csrf_context=request) form.user_password.widget.hide_value = False else: form = forms.UserRegisterForm(request.POST, csrf_context=request) if request.method == "POST" and form.validate(): log.info("registering user") # insert new user here if request.registry.settings["appenlight.disable_registration"]: request.session.flash(_("Registration is currently disabled.")) return HTTPFound(location=request.route_url("/")) new_user = User() DBSession.add(new_user) form.populate_obj(new_user) UserService.regenerate_security_code(new_user) new_user.status = 1 UserService.set_password(new_user, new_user.user_password) new_user.registration_ip = request.environ.get("REMOTE_ADDR") if social_data: handle_social_data(request, new_user, social_data) email_vars = { "user": new_user, "request": request, "email_title": "AppEnlight :: Start information", } UserService.send_email( request, recipients=[new_user.email], variables=email_vars, template="/email_templates/registered.jinja2", ) request.session.flash(_("You have successfully registered.")) DBSession.flush() headers = security.remember(request, new_user.id) return HTTPFound(location=request.route_url("/"), headers=headers) settings = request.registry.settings social_plugins = {} if settings.get("authomatic.pr.twitter.key", ""): social_plugins["twitter"] = True if settings.get("authomatic.pr.google.key", ""): social_plugins["google"] = True if settings.get("authomatic.pr.github.key", ""): social_plugins["github"] = True if settings.get("authomatic.pr.bitbucket.key", ""): social_plugins["bitbucket"] = True return { "form": form, "sign_in_form": sign_in_form, "social_plugins": social_plugins, }
def main(): parser = argparse.ArgumentParser( description="Populate AppEnlight database", add_help=False ) parser.add_argument( "-c", "--config", required=True, help="Configuration ini file of application" ) parser.add_argument("--username", default=None, help="User to create") parser.add_argument("--password", default=None, help="Password for created user") parser.add_argument("--email", default=None, help="Email for created user") parser.add_argument( "--auth-token", default=None, help="Auth token for created user" ) args = parser.parse_args() config_uri = args.config setup_logging(config_uri) env = bootstrap(config_uri) request = env["request"] with get_current_request().tm: group = GroupService.by_id(1) if not group: group = Group( id=1, group_name="Administrators", description="Top level permission owners", ) DBSession.add(group) permission = GroupPermission(perm_name="root_administration") group.permissions.append(permission) create_user = True if args.username else None while create_user is None: response = input("Do you want to create a new admin? (n)\n").lower() if is_yes(response or "n"): create_user = True elif is_no(response or "n"): create_user = False if create_user: csrf_token = request.session.get_csrf_token() user_name = args.username print("*********************************************************") while user_name is None: response = input("What is the username of new admin?\n") form = UserRegisterForm( user_name=response, csrf_token=csrf_token, csrf_context=request ) form.validate() if form.user_name.errors: print(form.user_name.errors[0]) else: user_name = response print('The admin username is "{}"\n'.format(user_name)) print("*********************************************************") email = args.email while email is None: response = input("What is the email of admin account?\n") form = UserRegisterForm( email=response, csrf_token=csrf_token, csrf_context=request ) form.validate() if form.email.errors: print(form.email.errors[0]) else: email = response print('The admin email is "{}"\n'.format(email)) print("*********************************************************") user_password = args.password confirmed_password = args.password while user_password is None or confirmed_password is None: response = getpass.getpass("What is the password for admin account?\n") form = UserRegisterForm( user_password=response, csrf_token=csrf_token, csrf_context=request ) form.validate() if form.user_password.errors: print(form.user_password.errors[0]) else: user_password = response response = getpass.getpass("Please confirm the password.\n") if user_password == response: confirmed_password = response else: print("Passwords do not match. Please try again") print("*********************************************************") with get_current_request().tm: if create_user: group = GroupService.by_id(1) user = User(user_name=user_name, email=email, status=1) UserService.regenerate_security_code(user) UserService.set_password(user, user_password) DBSession.add(user) token = AuthToken(description="Uptime monitoring token") if args.auth_token: token.token = args.auth_token user.auth_tokens.append(token) group.users.append(user) print("USER CREATED") print(json.dumps(user.get_dict())) print("*********************************************************") print("AUTH TOKEN") print(json.dumps(user.auth_tokens[0].get_dict()))