mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-23 05:53:06 +01:00
305 lines
11 KiB
Python
305 lines
11 KiB
Python
#coding:utf-8
|
|
|
|
"""
|
|
ID: user-management
|
|
ISSUE:
|
|
TITLE: Incorrect results when left join on subquery with constant column
|
|
DESCRIPTION:
|
|
NOTE: there is no difference between user who is granted with admin role when it was created and user who has no granted with this but
|
|
has system privilege 'USER_MANAGEMENT': both of them can *only* add/edit/drop another users and no other actions.
|
|
For example, they can give grants to just created users and can not select for any user-defined tables (until this was explicitly granted).
|
|
|
|
But if we create user <U01> on SELF-SECURITY database and give to him adminn role ('CREATE USER ... GRANT ADMIN ROLE') then this <U01> will
|
|
be able to do such actions: he can grant rights to other users etc.
|
|
In contrary to this, if we create user <U02> in such self-security DB but instead grant to him sytem privilege USER_MANAGEMENT then he
|
|
will NOT be able to do these actions. Only create/alter/drop users will be avaliable to him.
|
|
|
|
Test verifies exactly this case: abilities of user created inSELF-SECURITY database with granting to him privilege USER_MANAGEMENT.
|
|
|
|
We make back-copy of databases.conf and change it by adding alias for new DB which will be self-security and has alias = 'syspriv_usermgr'.
|
|
|
|
Then we make file-level copy of security.db to database defined by alias 'self_usermgr', do connect and apply SQL script that does all
|
|
necessary actions. NOTE that some actions must fail (see comments below, in generated .sql script).
|
|
|
|
Finally, test restores back copy of databases.conf file.
|
|
|
|
Checked on 5.0.0.139 (SS/CS), 4.0.1.2568 (SS/CS).
|
|
FBTEST: bugs.user_management
|
|
"""
|
|
|
|
import pytest
|
|
from firebird.qa import *
|
|
|
|
db = db_factory()
|
|
|
|
act = python_act('db', substitutions=[('.*After line \\d+.*', '')])
|
|
|
|
expected_stdout = """
|
|
STDOUT: WHO_AM_I JOHN_SMITH_DBA_HELPER
|
|
STDOUT: RDB$ROLE_NAME RDB$ADMIN
|
|
STDOUT: RDB$ROLE_IN_USE <false>
|
|
STDOUT: RDB$SYSTEM_PRIVILEGES FFFFFFFFFFFFFFFF
|
|
STDOUT: MON$SEC_DATABASE Self
|
|
STDOUT: WHO_AM_I JOHN_SMITH_DBA_HELPER
|
|
STDOUT: RDB$ROLE_NAME R_FOR_GRANT_REVOKE_ANY_DDL_RIGHT
|
|
STDOUT: RDB$ROLE_IN_USE <true>
|
|
STDOUT: RDB$SYSTEM_PRIVILEGES 0200000000000000
|
|
STDOUT: MON$SEC_DATABASE Self
|
|
STDOUT: Records affected: 2
|
|
STDOUT: SEC$USER_NAME STOCK_BOSS
|
|
STDOUT: SEC$FIRST_NAME foo-rio-bar
|
|
STDOUT: SEC$ADMIN <false>
|
|
STDOUT: SEC$ACTIVE <true>
|
|
STDOUT: SEC$USER_NAME STOCK_MNGR
|
|
STDOUT: SEC$FIRST_NAME <null>
|
|
STDOUT: SEC$ADMIN <false>
|
|
STDOUT: SEC$ACTIVE <false>
|
|
STDOUT: Records affected: 2
|
|
STDOUT: Records affected: 0
|
|
|
|
STDERR: Statement failed, SQLSTATE = 42000
|
|
STDERR: unsuccessful metadata update
|
|
STDERR: -GRANT failed
|
|
STDERR: -no SELECT privilege with grant option on table/view TEST_SS
|
|
|
|
STDERR: Statement failed, SQLSTATE = 28000
|
|
STDERR: no permission for SELECT access to TABLE TEST_SS
|
|
STDERR: -Effective user is JOHN_SMITH_DBA_HELPER
|
|
"""
|
|
|
|
@pytest.mark.skip('FIXME: databases.conf')
|
|
@pytest.mark.version('>=4.0.1')
|
|
def test_1(act: Action):
|
|
pytest.fail("Not IMPLEMENTED")
|
|
|
|
# test_script_1
|
|
#---
|
|
# import os
|
|
# import sys
|
|
# import subprocess
|
|
# from subprocess import Popen
|
|
# import datetime
|
|
# import time
|
|
# import shutil
|
|
# from fdb import services
|
|
# from datetime import datetime as dt
|
|
# from datetime import timedelta
|
|
#
|
|
# os.environ["ISC_USER"] = user_name
|
|
# os.environ["ISC_PASSWORD"] = user_password
|
|
#
|
|
# db_conn.close()
|
|
#
|
|
# #-----------------------------------
|
|
# def showtime():
|
|
# global dt
|
|
# return ''.join( (dt.now().strftime("%H:%M:%S.%f")[:11],'.') )
|
|
#
|
|
# #--------------------------------------------
|
|
#
|
|
# def flush_and_close( file_handle ):
|
|
# # https://docs.python.org/2/library/os.html#os.fsync
|
|
# # If you're starting with a Python file object f,
|
|
# # first do f.flush(), and
|
|
# # then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk.
|
|
# global os
|
|
#
|
|
# file_handle.flush()
|
|
# if file_handle.mode not in ('r', 'rb') and file_handle.name != os.devnull:
|
|
# # otherwise: "OSError: [Errno 9] Bad file descriptor"!
|
|
# os.fsync(file_handle.fileno())
|
|
# file_handle.close()
|
|
#
|
|
# #--------------------------------------------
|
|
#
|
|
# def cleanup( f_names_list ):
|
|
# global os
|
|
# for i in range(len( f_names_list )):
|
|
# if type(f_names_list[i]) == file:
|
|
# del_name = f_names_list[i].name
|
|
# elif type(f_names_list[i]) == str:
|
|
# del_name = f_names_list[i]
|
|
# else:
|
|
# print('Unrecognized type of element:', f_names_list[i], ' - can not be treated as file.')
|
|
# print('type(f_names_list[i])=',type(f_names_list[i]))
|
|
# del_name = None
|
|
#
|
|
# if del_name and os.path.isfile( del_name ):
|
|
# os.remove( del_name )
|
|
#
|
|
# #--------------------------------------------
|
|
#
|
|
#
|
|
# FB_HOME = services.connect(host='localhost', user= user_name, password= user_password).get_home_directory()
|
|
# # Resut: FB_HOME is full path to FB instance home (with trailing slash).
|
|
#
|
|
# if os.name == 'nt':
|
|
# # For Windows we assume that client library is always in FB_HOME dir:
|
|
# FB_CLNT=os.path.join(FB_HOME, 'fbclient.dll')
|
|
# else:
|
|
# # For Linux client library will be searched in 'lib' subdirectory of FB_HOME:
|
|
# FB_CLNT=os.path.join(FB_HOME, 'lib', 'libfbclient.so' )
|
|
#
|
|
#
|
|
# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S")
|
|
#
|
|
# dbconf_cur = os.path.join(FB_HOME, 'databases.conf')
|
|
# dbconf_bak = os.path.join(context['temp_directory'], 'databases_'+dts+'.bak')
|
|
#
|
|
# shutil.copy2( dbconf_cur, dbconf_bak )
|
|
#
|
|
# sec_db = context['isc4_path']
|
|
# tmp_alias = 'syspriv_usermgr'
|
|
#
|
|
# ##############################################################
|
|
#
|
|
# tmp_fdb = os.path.join(context['temp_directory'],'tmp_syspriv_usermgr.fdb')
|
|
# alias_data='''
|
|
# # Temporary added for performing test functional/syspriv/user_management.fbt
|
|
# #
|
|
# %(tmp_alias)s = %(tmp_fdb)s {
|
|
# RemoteAccess = true
|
|
# SecurityDatabase = %(tmp_alias)s
|
|
# }
|
|
# ''' % locals()
|
|
#
|
|
# cleanup( (tmp_fdb,) )
|
|
# shutil.copy2( sec_db, tmp_fdb )
|
|
#
|
|
#
|
|
# f_dbconf=open( dbconf_cur, 'a')
|
|
# f_dbconf.seek(0, 2)
|
|
# f_dbconf.write( alias_data )
|
|
# flush_and_close( f_dbconf )
|
|
#
|
|
#
|
|
# sql_txt = '''
|
|
# set list on;
|
|
# set wng off;
|
|
# set count on;
|
|
# set width mon$user 15;
|
|
# set width mon$role 15;
|
|
# set width sec$plugin 10;
|
|
#
|
|
# -- Create record for SYSDBA in self-security database, table sec$users:
|
|
# connect 'localhost:%(tmp_alias)s' user %(user_name)s password '%(user_password)s';
|
|
#
|
|
# -- not helps... ALTER DATABASE SET LINGER TO 0;
|
|
#
|
|
# create or alter user john_smith_dba_helper password '123';
|
|
# commit;
|
|
#
|
|
# recreate table test_ss(id int);
|
|
# commit;
|
|
#
|
|
# create or alter view v_check as
|
|
# select sec$user_name, sec$first_name, sec$admin,sec$active
|
|
# from sec$users where sec$user_name in (upper('stock_boss'), upper('stock_mngr'))
|
|
# ;
|
|
# grant select on v_check to public;
|
|
# commit;
|
|
#
|
|
# set term ^;
|
|
# execute block as
|
|
# begin
|
|
# execute statement 'drop role r_for_user_management';
|
|
# when any do begin end
|
|
# end^
|
|
# set term ;^
|
|
# commit;
|
|
#
|
|
# -- Add/change/delete non-system records in RDB$TYPES
|
|
# create role r_for_grant_revoke_any_ddl_right set system privileges to USER_MANAGEMENT;
|
|
# commit;
|
|
# grant default r_for_grant_revoke_any_ddl_right to user john_smith_dba_helper;
|
|
# commit;
|
|
#
|
|
# connect 'localhost:%(tmp_alias)s' user john_smith_dba_helper password '123';
|
|
#
|
|
# select current_user as who_am_i,r.rdb$role_name,rdb$role_in_use(r.rdb$role_name),r.rdb$system_privileges,m.mon$sec_database
|
|
# from mon$database m cross join rdb$roles r
|
|
# ;
|
|
# commit;
|
|
#
|
|
# -- set echo on;
|
|
#
|
|
# -- Must PASS:
|
|
# create or alter user stock_boss password '123';
|
|
# alter user stock_boss firstname 'foo-rio-bar' password '456';
|
|
# create or alter user stock_mngr password '123';
|
|
# alter user stock_mngr inactive;
|
|
# commit;
|
|
#
|
|
# -- Must show 2 records (for users who have been just created):
|
|
# select * from v_check;
|
|
#
|
|
# -- must FAIL!
|
|
# grant select on test_ss to stock_mngr;
|
|
# commit;
|
|
#
|
|
# -- must FAIL!
|
|
# select * from test_ss;
|
|
# commit;
|
|
#
|
|
# -- Must PASS:
|
|
# drop user stock_boss;
|
|
# drop user stock_mngr;
|
|
# commit;
|
|
#
|
|
# -- Must show NO records (because users must be successfully dropped):
|
|
# select * from v_check;
|
|
#
|
|
# -- set echo off;
|
|
# commit;
|
|
# connect 'localhost:%(tmp_alias)s';
|
|
# drop user john_smith_dba_helper;
|
|
# commit;
|
|
# ''' % dict(globals(), **locals())
|
|
#
|
|
# f_isql_cmd=open( os.path.join(context['temp_directory'],'tmp_syspriv_usermgr.sql'), 'w')
|
|
# f_isql_cmd.write(sql_txt)
|
|
# flush_and_close( f_isql_cmd )
|
|
#
|
|
# f_isql_log = open( os.path.splitext(f_isql_cmd.name)[0] + '.log', 'w' )
|
|
# f_isql_err = open( os.path.splitext(f_isql_cmd.name)[0] + '.err', 'w' )
|
|
# subprocess.call( [ context['isql_path'], '-q', '-i', f_isql_cmd.name], stdout=f_isql_log, stderr=f_isql_err )
|
|
# flush_and_close( f_isql_log )
|
|
# flush_and_close( f_isql_err )
|
|
#
|
|
# with open( f_isql_log.name, 'r' ) as f:
|
|
# for line in f:
|
|
# if line.split():
|
|
# print('STDOUT: ' + line)
|
|
#
|
|
# with open( f_isql_err.name, 'r' ) as f:
|
|
# for line in f:
|
|
# if line.split():
|
|
# print('STDERR: ' + line)
|
|
#
|
|
#
|
|
# f_shutdown_log=open( os.path.join(context['temp_directory'],'tmp_syspriv_usermgr_shutdown.log'), 'w')
|
|
# subprocess.call( [context['fbsvcmgr_path'],
|
|
# "localhost:service_mgr",
|
|
# "user", user_name, "password", user_password,
|
|
# "expected_db", tmp_fdb,
|
|
# "action_properties", "prp_shutdown_mode", "prp_sm_full", "prp_shutdown_db", "0", "dbname", tmp_fdb,
|
|
# ],
|
|
# stdout = f_shutdown_log,
|
|
# stderr = subprocess.STDOUT
|
|
# )
|
|
# flush_and_close( f_shutdown_log )
|
|
#
|
|
# with open( f_shutdown_log.name, 'r' ) as f:
|
|
# for line in f:
|
|
# if line:
|
|
# print("Unexpected STDERR when try to make full shutdown: "+line)
|
|
#
|
|
# cleanup( (tmp_fdb,) )
|
|
# cleanup( (f_isql_err,f_isql_log,f_isql_cmd,f_shutdown_log) )
|
|
#
|
|
# # Restore original content of databases.conf:
|
|
# ##################
|
|
# shutil.move( dbconf_bak, dbconf_cur )
|
|
#
|
|
#---
|