Trying to determine the permissions some users have between 2 tables

  • We've got a legacy MS Access application which is the front-end to a SQL Server 2012 database. Our users will normally get into the Access application for doing their regular work, but some know how to jump out of the application and go directly to the underlying linked SQL tables. (Personally I don't like this, but like I said, this is a legacy app and that's the way whoever wrote it 10+ years ago set it up.)

    The issue is the users want to be able to add some records to one lookup table. They can to others, but not to one of table. I've gotten into SSMS and looked at the permissions between one lookup table they can add records to and the lookup table they cannot add records to, from Access. When I look at the table properties | Permissions they are identical. No one, group or role has been either granted or denied access. They're both in the dbo schema. There are no triggers for either.

    I'm at a loss as to how to explain why they cannot add records to one table but can to another. I don't see any differences, as far as permissions go. Is there something I'm missing? Is this possibly a MS Access issue?

    Kindest Regards, Rod Connect with me on LinkedIn.

  • This was removed by the editor as SPAM

  • Rod at work - Monday, January 23, 2017 12:15 PM

    We've got a legacy MS Access application which is the front-end to a SQL Server 2012 database. Our users will normally get into the Access application for doing their regular work, but some know how to jump out of the application and go directly to the underlying linked SQL tables. (Personally I don't like this, but like I said, this is a legacy app and that's the way whoever wrote it 10+ years ago set it up.)

    The issue is the users want to be able to add some records to one lookup table. They can to others, but not to one of table. I've gotten into SSMS and looked at the permissions between one lookup table they can add records to and the lookup table they cannot add records to, from Access. When I look at the table properties | Permissions they are identical. No one, group or role has been either granted or denied access. They're both in the dbo schema. There are no triggers for either.

    I'm at a loss as to how to explain why they cannot add records to one table but can to another. I don't see any differences, as far as permissions go. Is there something I'm missing? Is this possibly a MS Access issue?

    GUI is not the best way to view permissions, run this against the database and check the output

    SET NOCOUNT ON

    DECLARE @sql NVARCHAR(MAX)

    SET @sql = ''

    --========================================================

    --script database roles from the database

    --========================================================

    IF (SELECT COUNT(*) FROM sys.database_principals WHERE type = 'R' AND is_fixed_role <> 1 AND principal_id > 4) = 0

    BEGIN

    SELECT @sql = @sql + '/*No database roles found*/'

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    ELSE

    BEGIN

    SELECT @sql = '/*Scripting all database roles' + CHAR(10) +

    '===================================================================================*/' + CHAR(13)

    --SELECT @sql = @sql + 'USE ' + QUOTENAME(DB_NAME(DB_ID())) + CHAR(10) --+ 'GO' + CHAR(10)

    SELECT @sql = @sql + 'CREATE ROLE ' + QUOTENAME(dp.name) + ' AUTHORIZATION ' + QUOTENAME(dp2.name) + CHAR(13)

    FROM sys.database_principals dp INNER JOIN sys.database_principals dp2

    ON dp.owning_principal_id = dp2.principal_id

    WHERE dp.type = 'R' AND dp.is_fixed_role <> 1 AND dp.principal_id > 4

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    SET @sql = ''

    --=======================================================

    --script all schema permissions

    --=======================================================

    SELECT @sql = '/*Scripting all user schema permissions' + CHAR(10) +

    '===================================================================================*/' + CHAR(13)

    --Script the permission grants on the schemas

    SELECT @sql = @sql + CHAR(13) + dp.state_desc COLLATE latin1_general_ci_as + ' ' +

    dp.permission_name + ' ON ' + dp.class_desc + '::' + QUOTENAME(sch.name) +

    ' TO ' + QUOTENAME(dp2.name) + ' AS ' + QUOTENAME(dp3.name)

    FROM sys.database_permissions dp

    INNER JOIN sys.schemas sch ON dp.grantor_principal_id = sch.principal_id

    INNER JOIN sys.database_principals dp2 ON dp.grantee_principal_id = dp2.principal_id

    INNER JOIN sys.database_principals dp3 ON dp.grantor_principal_id = dp3.principal_id

    WHERE dp.class = 3 --dp.major_id BETWEEN 1 AND 8

    PRINT @sql + CHAR(13) + CHAR(13)

    SET @sql = ''

    --=========================================================

    --script Application roles from the database

    --=========================================================

    IF (SELECT COUNT(*) FROM sys.database_principals WHERE type = 'A') = 0

    BEGIN

    SELECT @sql = @sql + '/*No application roles found*/'

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    ELSE

    BEGIN

    SELECT @sql = '/*Scripting all application roles' + CHAR(10) +

    '===================================================================================*/' + CHAR(13)

    --SELECT @sql = @sql + 'USE ' + QUOTENAME(DB_NAME(DB_ID())) + CHAR(10) --+ 'GO' + CHAR(10)

    SELECT @sql = @sql + 'CREATE APPLICATION ROLE ' + dp.name + ' WITH DEFAULT_SCHEMA = ' +

    QUOTENAME(dp.default_schema_name) + ', PASSWORD = N''P@ssw0rd1''' + CHAR(10)

    FROM sys.database_principals dp

    WHERE dp.type = 'A' AND dp.is_fixed_role <> 1 AND dp.principal_id > 4

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    SET @sql = ''

    --===============================================================

    --got the roles so now we need to get any nested role permissions

    --===============================================================

    IF (SELECT COUNT(*) from sys.database_principals dp inner join sys.database_role_members drm

    ON dp.principal_id = drm.member_principal_id inner join sys.database_principals dp2

    ON drm.role_principal_id = dp2.principal_id WHERE dp.type = 'R') = 0

    BEGIN

    SELECT @sql = + '/*No nested roles found*/'

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    ELSE

    BEGIN

    SELECT @sql = '/*Scripting all nested roles' + CHAR(10) +

    '===================================================================================*/' + CHAR(13)

    --SELECT @sql = @sql + 'USE ' + QUOTENAME(DB_NAME(DB_ID())) + CHAR(10) --+ 'GO' + CHAR(10)

    SELECT @sql = @sql + 'EXEC sp_addrolemember ''' + dp2.name + ''', ''' + dp.name + '''' + CHAR(10)

    FROM sys.database_principals dp

    INNER JOIN sys.database_role_members drm

    ON dp.principal_id = drm.member_principal_id

    INNER JOIN sys.database_principals dp2

    ON drm.role_principal_id = dp2.principal_id

    WHERE dp.type = 'R'

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    SET @sql = ''

    --=================================================================

    --Now all the object level permissions

    --=================================================================

    IF(SELECTCOUNT(*) FROM sys.database_permissions dbpe INNER JOIN sys.database_principals dbpr

    ON dbpr.principal_id = dbpe.grantee_principal_id INNER JOIN sys.objects obj

    ON dbpe.major_id = obj.object_id WHERE obj.type NOT IN ('IT','S','X')) = 0

    BEGIN

    SELECT @sql = + '/*No database user object GRANTS found*/'

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    ELSE

    BEGIN

    SELECT @sql = '/*Scripting all database user object GRANTS' + CHAR(10) +

    '===================================================================================*/' + CHAR(13)

    --SELECT @sql = @sql + 'USE ' + QUOTENAME(DB_NAME(DB_ID())) + CHAR(13) --+ 'GO'

    PRINT @sql --+ CHAR(10)

    SET @sql = ''

    IF OBJECT_ID('tempdb..#objgrants') IS NOT NULL

    BEGIN

    DROP TABLE #objgrants

    END

    CREATE TABLE #objgrants(

    state_descVARCHAR(60)

    , perm_nameNVARCHAR(128)

    , sch_nameNVARCHAR(128)

    , maj_IDNVARCHAR(128)

    , nameNVARCHAR(128)

    , pr_nameNVARCHAR(128)

    )

    DECLARE @state_desc VARCHAR(60)

    DECLARE @perm_name NVARCHAR(128), @sch_name NVARCHAR(128), @maj_ID NVARCHAR(128)

    DECLARE @name NVARCHAR(128), @pr_name NVARCHAR(128)

    INSERT INTO #objgrants

    SELECT CASE dbpe.[state] WHEN 'W' THEN 'GRANT'

    ELSE dbpe.state_desc COLLATE Latin1_General_CI_AS

    END AS [state_desc]

    , dbpe.permission_name COLLATE Latin1_General_CI_AS AS perm_name

    , sch.name AS sch_name

    , OBJECT_NAME(dbpe.major_id) AS maj_ID

    , dbpr.name AS name

    , CASE dbpe.[state] WHEN 'W' THEN '] WITH GRANT OPTION'

    ELSE ']' END AS pr_name

    FROM sys.database_permissions dbpe INNER JOIN sys.database_principals dbpr

    ON dbpr.principal_id = dbpe.grantee_principal_id

    INNER JOIN sys.objects obj ON dbpe.major_id = obj.object_id

    INNER JOIN sys.schemas sch ON obj.schema_id = sch.schema_id

    WHERE obj.type NOT IN ('IT','S','X')

    ORDER BY dbpr.name, obj.name

    WHILE (SELECT COUNT(*) FROM #objgrants) > 0

    BEGIN

    SELECT TOP 1 @state_desc = state_desc, @perm_name = perm_name, @sch_name = sch_name,

    @maj_ID = maj_ID, @name = name, @pr_name = pr_name FROM #objgrants

    SELECT @sql = @sql + @state_desc + ' ' + @perm_name +

    ' ON [' + @sch_name + '].[' + @maj_ID + '] TO [' + @name + @pr_name

    PRINT @sql

    SET @sql = ''

    DELETE FROM #objgrants WHERE state_desc = @state_desc AND perm_name = @perm_name

    AND sch_name = @sch_name AND maj_ID = @maj_ID AND name = @name AND pr_name = @pr_name

    END

    PRINT CHAR(13)

    DROP TABLE #objgrants

    END

    SET @sql = ''

    --=================================================================

    --Now script all the database roles the user have permissions to

    --=================================================================

    IF(SELECT COUNT(*) FROM sys.database_principals dp

    INNER JOIN sys.database_role_members drm ON dp.principal_id = drm.role_principal_id

    INNER JOIN sys.database_principals dp2 ON drm.member_principal_id = dp2.principal_id

    WHERE dp2.principal_id > 4 AND dp2.type <> 'R') = 0

    BEGIN

    SELECT @sql = + '/*No database user role GRANTS found*/'

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    ELSE

    BEGIN

    SELECT @sql = '/*Scripting all database user role permissions' + CHAR(10) +

    '===================================================================================*/' + CHAR(13)

    --SELECT @sql = @sql + 'USE ' + QUOTENAME(DB_NAME(DB_ID())) + CHAR(13) + CHAR(10)

    SELECT @sql = @sql + 'EXEC sp_addrolemember ''' + dp.name + ''', ''' + dp2.name + '''' + CHAR(13)

    FROM sys.database_principals dp

    INNER JOIN sys.database_role_members drm ON dp.principal_id = drm.role_principal_id

    INNER JOIN sys.database_principals dp2 ON drm.member_principal_id = dp2.principal_id

    WHERE dp2.principal_id > 4 AND dp2.type <> 'R'

    PRINT @sql + CHAR(13) + CHAR(13)

    END

    SET @sql = ''

    SELECT @sql = '--Finished!' + CHAR(13) + 'Please ensure you check the script output before executing' +

    CHAR(13) + 'against your target database.'

    PRINT @sql

    -----------------------------------------------------------------------------------------------------------

    "Ya can't make an omelette without breaking just a few eggs" 😉

  • Wryan138 - Monday, January 23, 2017 10:34 PM

    Rod,Have you checked that there is a Primary Key on the "bad"lookup table.Wayne

    I had not. I just did and found that there is no primary key associated with that lookup table. Do you think that could have something to do with the problem? Applying a primary key would be easy enough and at this point as there's not a lot of records and all of the records that are there are unique, as far as what I would choose for the primary key.

    Kindest Regards, Rod Connect with me on LinkedIn.

Viewing 4 posts - 1 through 3 (of 3 total)

You must be logged in to reply to this topic. Login to reply