| |
@@ -0,0 +1,274 @@
|
| |
+ # -*- coding: utf-8 -*-
|
| |
+
|
| |
+ from __future__ import unicode_literals
|
| |
+
|
| |
+ __requires__ = ["SQLAlchemy >= 0.8"]
|
| |
+ import pkg_resources
|
| |
+
|
| |
+ import unittest
|
| |
+ import sys
|
| |
+ import os
|
| |
+ import tests
|
| |
+ import pagure.lib
|
| |
+ import pagure.ui.remoteuser_login
|
| |
+ from mock import patch, MagicMock
|
| |
+
|
| |
+ sys.path.insert(
|
| |
+ 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ class PagureFlaskRemoteUserLogintests(tests.SimplePagureTest):
|
| |
+ """ Tests for remote_login authentication of pagure """
|
| |
+
|
| |
+ def setUp(self):
|
| |
+ """ Create the application with PAGURE_AUTH set to remoteuser. """
|
| |
+ super(PagureFlaskRemoteUserLogintests, self).setUp()
|
| |
+
|
| |
+ app = pagure.flask_app.create_app(
|
| |
+ {"DB_URL": self.dbpath, "PAGURE_AUTH": "remoteuser"}
|
| |
+ )
|
| |
+ # Remove the log handlers for the tests
|
| |
+ app.logger.handlers = []
|
| |
+
|
| |
+ self.app = app.test_client()
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_front_page_without_remote_user(self):
|
| |
+ """ Test the front page without remote_user set """
|
| |
+ output1 = self.app.get("/")
|
| |
+ o1data = output1.get_data(as_text=True)
|
| |
+ self.assertEqual(output1.status_code, 200)
|
| |
+ self.assertIn("<title>Home - Pagure</title>", o1data)
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_front_page_with_remote_user(self):
|
| |
+ """ test the front page with remote_user set """
|
| |
+ o1data = self.app.get("/").get_data(as_text=True)
|
| |
+ output2 = self.app.get("/", environ_base={"REMOTE_USER": "foo"})
|
| |
+ o2data = output2.get_data(as_text=True)
|
| |
+ self.assertEqual(output2.status_code, 200)
|
| |
+ self.assertIn("<title>Home - Pagure</title>", o2data)
|
| |
+ self.assertEqual(o1data, o2data)
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_new_user_page(self):
|
| |
+ """ Check new user page """
|
| |
+ output = self.app.get(
|
| |
+ "/user/remote/new",
|
| |
+ environ_base={"REMOTE_USER": "foo"},
|
| |
+ follow_redirects=True,
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertIn(
|
| |
+ "<title>New user from REMOTE_USER - Pagure</title>", output_text
|
| |
+ )
|
| |
+ self.assertIn('Create new account for "foo"', output_text)
|
| |
+ self.assertIn(
|
| |
+ '<form action="/user/remote/new" method="post">', output_text
|
| |
+ )
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_new_user_no_csrf(self):
|
| |
+ """ don't accept without csrf token """
|
| |
+ output = self.app.post(
|
| |
+ "/user/remote/new",
|
| |
+ environ_base={"REMOTE_USER": "foo"},
|
| |
+ data={"fullname": "foo m. atic", "email_address": "foo@bar.com"},
|
| |
+ follow_redirects=True,
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertIn(
|
| |
+ "<title>New user from REMOTE_USER - Pagure</title>", output_text
|
| |
+ )
|
| |
+ self.assertIn(
|
| |
+ '<form action="/user/remote/new" method="post">', output_text
|
| |
+ )
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_new_user_no_email(self):
|
| |
+ """ don't accept without email """
|
| |
+ csrf_token = (
|
| |
+ self.app.post(
|
| |
+ "/user/remote/new", environ_base={"REMOTE_USER": "foo"}
|
| |
+ )
|
| |
+ .get_data(as_text=True)
|
| |
+ .split('name="csrf_token" type="hidden" value="')[1]
|
| |
+ .split('">')[0]
|
| |
+ )
|
| |
+ output = self.app.post(
|
| |
+ "/user/remote/new",
|
| |
+ environ_base={"REMOTE_USER": "foo"},
|
| |
+ data={
|
| |
+ "fullname": "foo m. atic",
|
| |
+ "email_address": None,
|
| |
+ "csrf_token": csrf_token,
|
| |
+ },
|
| |
+ follow_redirects=True,
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertIn(
|
| |
+ "<title>New user from REMOTE_USER - Pagure</title>", output_text
|
| |
+ )
|
| |
+ self.assertIn(
|
| |
+ '<form action="/user/remote/new" method="post">', output_text
|
| |
+ )
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_new_user_exists(self):
|
| |
+ """ submit form with proper data but existing user """
|
| |
+ csrf_token = (
|
| |
+ self.app.post(
|
| |
+ "/user/remote/new", environ_base={"REMOTE_USER": "foo"}
|
| |
+ )
|
| |
+ .get_data(as_text=True)
|
| |
+ .split('name="csrf_token" type="hidden" value="')[1]
|
| |
+ .split('">')[0]
|
| |
+ )
|
| |
+ output = self.app.post(
|
| |
+ "/user/remote/new",
|
| |
+ environ_base={"REMOTE_USER": "foo"},
|
| |
+ data={
|
| |
+ "fullname": "foo m. atic",
|
| |
+ "email_address": "bar@baz.test",
|
| |
+ "csrf_token": csrf_token,
|
| |
+ },
|
| |
+ follow_redirects=True,
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertIn(
|
| |
+ "<title>New user from REMOTE_USER - Pagure</title>", output_text
|
| |
+ )
|
| |
+ self.assertIn("User already exists!", output_text)
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_new_user_page_no_remote_user(self):
|
| |
+ """ Can't submit without remote_user """
|
| |
+ csrf_token = (
|
| |
+ self.app.post(
|
| |
+ "/user/remote/new", environ_base={"REMOTE_USER": "foo"}
|
| |
+ )
|
| |
+ .get_data(as_text=True)
|
| |
+ .split('name="csrf_token" type="hidden" value="')[1]
|
| |
+ .split('">')[0]
|
| |
+ )
|
| |
+ items = pagure.lib.query.search_user(self.session)
|
| |
+ self.assertEqual(2, len(items))
|
| |
+ output = self.app.post(
|
| |
+ "/user/remote/new",
|
| |
+ data={
|
| |
+ "fullname": "foo m. atic",
|
| |
+ "email_address": "foobar@example.com",
|
| |
+ "csrf_token": csrf_token,
|
| |
+ },
|
| |
+ follow_redirects=True,
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertIn("Server malconfiguration", output_text)
|
| |
+ self.assertIn("<title>Home - Pagure</title>", output_text)
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
|
| |
+ def test_new_user(self):
|
| |
+ """ Test the /user/remote/new endpoint with valid data """
|
| |
+ csrf_token = (
|
| |
+ self.app.post(
|
| |
+ "/user/remote/new", environ_base={"REMOTE_USER": "foobar"}
|
| |
+ )
|
| |
+ .get_data(as_text=True)
|
| |
+ .split('name="csrf_token" type="hidden" value="')[1]
|
| |
+ .split('">')[0]
|
| |
+ )
|
| |
+ items = pagure.lib.query.search_user(self.session)
|
| |
+ self.assertEqual(2, len(items))
|
| |
+ output = self.app.post(
|
| |
+ "/user/remote/new",
|
| |
+ environ_base={"REMOTE_USER": "foobar"},
|
| |
+ data={
|
| |
+ "fullname": "foo m. atic",
|
| |
+ "email_address": "foobar@example.com",
|
| |
+ "csrf_token": csrf_token,
|
| |
+ },
|
| |
+ follow_redirects=True,
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertIn("<title>Home - Pagure</title>", output_text)
|
| |
+ self.assertIn("Welcome", output_text)
|
| |
+ items = pagure.lib.query.search_user(self.session)
|
| |
+ self.assertEqual(3, len(items))
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ @patch.dict("pagure.config.config", {"CHECK_SESSION_IP": False})
|
| |
+ def test_login_valid(self):
|
| |
+ """ Test to use /login/ with valid user """
|
| |
+ user = tests.FakeUser(username="pingou")
|
| |
+ with tests.user_set(self.app.application, user):
|
| |
+ output = self.app.get(
|
| |
+ "/login/",
|
| |
+ environ_base={"REMOTE_USER": "pingou"},
|
| |
+ follow_redirects=True,
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertIn("<title>Home - Pagure</title>", output_text)
|
| |
+ self.assertNotIn(">Log In</a>", output_text)
|
| |
+ self.assertNotIn(">Log Out</a>", output_text)
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_login_no_remoteuser(self):
|
| |
+ """ Test to use /login/ without remote_user """
|
| |
+ output = self.app.post("/login", follow_redirects=True)
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ self.assertIn(
|
| |
+ "<title>New user from REMOTE_USER - Pagure</title>",
|
| |
+ output.get_data(as_text=True),
|
| |
+ )
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ def test_login_new_remoteuser(self):
|
| |
+ """ Test to use /login/ with yet-unknown remote_user """
|
| |
+ output = self.app.post(
|
| |
+ "/login",
|
| |
+ environ_base={"REMOTE_USER": "foobarbaz"},
|
| |
+ follow_redirects=True,
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ self.assertIn(
|
| |
+ "<title>New user from REMOTE_USER - Pagure</title>",
|
| |
+ output.get_data(as_text=True),
|
| |
+ )
|
| |
+
|
| |
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "remoteuser"})
|
| |
+ @patch.dict("pagure.config.config", {"CHECK_SESSION_IP": False})
|
| |
+ def test_login_createproj_settings(self):
|
| |
+ """ Test that user can login, create project and see
|
| |
+ Settings button of own project """
|
| |
+ tests.create_projects(self.session)
|
| |
+ tests.create_projects_git(os.path.join(self.path, "repos"))
|
| |
+ output = self.app.get("/test", environ_base={"REMOTE_USER": "pingou"})
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ self.assertIn("<title>Overview - test - Pagure</title>", output_text)
|
| |
+ user = tests.FakeUser(username="pingou")
|
| |
+ with tests.user_set(self.app.application, user):
|
| |
+ output = self.app.get(
|
| |
+ "/test", environ_base={"REMOTE_USER": "pingou"}
|
| |
+ )
|
| |
+ self.assertEqual(output.status_code, 200)
|
| |
+ output_text = output.get_data(as_text=True)
|
| |
+ self.assertIn(
|
| |
+ "<title>Overview - test - Pagure</title>", output_text
|
| |
+ )
|
| |
+ self.assertIn(
|
| |
+ '<span class="d-none d-md-inline">Settings</span>', output_text
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ if __name__ == "__main__":
|
| |
+ unittest.main(verbosity=2)
|
| |
This patch adds support for REMOTE_USER authentication, which relies on webserver/reverse proxy-induced authentication. New users are asked to provide full name and email address. /login/ and /user/remote/new/ need to be protected by webserver. Anonymous access is still possible, open sessions are tracked by token similar to local login auth. Set
PAGURE_AUTH = 'remoteuser'
in pagure.cfg to enable.Example for a simple file-based Apache httpd config (only what's relevant for auth):
This should also work with other mod_auth modules like Kerberos/SAML/OIDC and with any WSGI-compatible webserver or reverse proxy.