Skip to content

Commit

Permalink
Changed Oracle test-user creation to grant privileges instead of roles
Browse files Browse the repository at this point in the history
because the roles (specifically RESOURCE) are deprecated.
Also added optional support for creating views in tests, and made an
introspection test fail (rather than skip)  if a view cannot be created
due to lacking privileges.

Refs #18782

Thanks Tim Graham for review, and Josh Smeaton
  • Loading branch information
shaib committed Sep 24, 2014
1 parent a170922 commit d128eac
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 7 deletions.
24 changes: 21 additions & 3 deletions django/db/backends/oracle/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from django.conf import settings
from django.db.backends.creation import BaseDatabaseCreation
from django.db.utils import DatabaseError
from django.utils.six.moves import input


Expand Down Expand Up @@ -172,9 +173,25 @@ def _create_test_user(self, cursor, parameters, verbosity):
TEMPORARY TABLESPACE %(tblspace_temp)s
QUOTA UNLIMITED ON %(tblspace)s
""",
"""GRANT CONNECT, RESOURCE TO %(user)s""",
"""GRANT CREATE SESSION,
CREATE TABLE,
CREATE SEQUENCE,
CREATE PROCEDURE,
CREATE TRIGGER
TO %(user)s""",
]
self._execute_statements(cursor, statements, parameters, verbosity)
# Most test-suites can be run without the create-view privilege. But some need it.
extra = "GRANT CREATE VIEW TO %(user)s"
try:
self._execute_statements(cursor, [extra], parameters, verbosity, allow_quiet_fail=True)
except DatabaseError as err:
description = str(err)
if 'ORA-01031' in description:
if verbosity >= 2:
print("Failed to grant CREATE VIEW permission to test user. This may be ok.")
else:
raise

def _execute_test_db_destruction(self, cursor, parameters, verbosity):
if verbosity >= 2:
Expand All @@ -194,15 +211,16 @@ def _destroy_test_user(self, cursor, parameters, verbosity):
]
self._execute_statements(cursor, statements, parameters, verbosity)

def _execute_statements(self, cursor, statements, parameters, verbosity):
def _execute_statements(self, cursor, statements, parameters, verbosity, allow_quiet_fail=False):
for template in statements:
stmt = template % parameters
if verbosity >= 2:
print(stmt)
try:
cursor.execute(stmt)
except Exception as err:
sys.stderr.write("Failed (%s)\n" % (err))
if (not allow_quiet_fail) or verbosity >= 2:
sys.stderr.write("Failed (%s)\n" % (err))
raise

def _get_test_db_params(self):
Expand Down
29 changes: 26 additions & 3 deletions docs/ref/databases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -672,14 +672,37 @@ database user must have privileges to run the following commands:
* CREATE PROCEDURE
* CREATE TRIGGER

To run Django's test suite, the user needs these *additional* privileges:
To run a project's test suite, the user usually needs these *additional*
privileges:

* CREATE USER
* DROP USER
* CREATE TABLESPACE
* DROP TABLESPACE
* CONNECT WITH ADMIN OPTION
* RESOURCE WITH ADMIN OPTION
* CREATE SESSION WITH ADMIN OPTION
* CREATE TABLE WITH ADMIN OPTION
* CREATE SEQUENCE WITH ADMIN OPTION
* CREATE PROCEDURE WITH ADMIN OPTION
* CREATE TRIGGER WITH ADMIN OPTION

Note that, while the RESOURCE role has the required CREATE TABLE, CREATE
SEQUENCE, CREATE PROCEDURE and CREATE TRIGGER privileges, and a user
granted RESOURCE WITH ADMIN OPTION can grant RESOURCE, such a user cannot
grant the individual privileges (e.g. CREATE TABLE), and thus RESOURCE
WITH ADMIN OPTION is not usually sufficient for running tests.

Some test suites also create views; to run these, the user also needs
the CREATE VIEW WITH ADMIN OPTION privilege. In particular, this is needed
for Django's own test suite.

.. versionchanged:: 1.8

Prior to Django 1.8, the test user was granted the CONNECT and RESOURCE
roles, so the extra privileges required for running the test suite were
different.

All of these privileges are included in the DBA role, which is appropriate
for use on a private developer's database.

The Oracle database backend uses the ``SYS.DBMS_LOB`` package, so your user
will require execute permissions on it. It's normally accessible to all users
Expand Down
10 changes: 10 additions & 0 deletions docs/releases/1.8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,16 @@ The end of upstream support periods was reached in July 2010 for Oracle 9.2,
January 2012 for Oracle 10.1, and July 2013 for Oracle 10.2. As a consequence,
Django 1.8 sets 11.1 as the minimum Oracle version it officially supports.

Specific privileges used instead of roles for tests on Oracle
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Earlier versions of Django granted the CONNECT and RESOURCE roles to the test
user on Oracle. These roles have been deprecated, so Django 1.8 uses the
specific underlying privileges instead. This changes the privileges required
of the main user for running tests (unless the project is configured to avoid
creating a test user). The exact privileges required now are detailed in
:ref:`Oracle notes <oracle-notes>`.

``AbstractUser.last_login`` allows null values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion tests/introspection/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def test_table_names_with_views(self):
'from introspection_article;')
except DatabaseError as e:
if 'insufficient privileges' in str(e):
self.skipTest("The test user has no CREATE VIEW privileges")
self.fail("The test user has no CREATE VIEW privileges")
else:
raise

Expand Down

0 comments on commit d128eac

Please sign in to comment.