Search code examples
asp.net-mvcmembership-providersimplemembership

Get user (as a IPrincipal) by UserId or check role of any user?


A colleague of mine wrote some simple code for testing if user in our system has correct data in database (for example a company owner needs to actually be set as an owner of some company, have correct roles assigned to him etc). The code that he made is placed directly in the MVC application (rather than rely on code written in the database), but he made a small mistake and instead of validating roles of some specific user, he used HttpContext.Current.User. The testing mechanism is still in early stages and doesn't break the application in any way (even if it works incorrectly). The colleague is out of office and I was asked to fix the bug (I would have to do it even if he was at office though).

There is a number of ways in which I can fix the bug, but I was thinking of one that looks like it's not going to make me rewrite everything from scratch. I was thinking that if I could somehow get a user by specific UserId (that's what we get on the input of the action) as an IPrincipal object I wouldnh't have to change a lot of the code. However I can't seem to find any information about such operation on the internet.

In short: Can I get a user (other than the current one) by UserId and have the result as IPrincipal? If yes, how do I achieve that? If no, is there some other standard way to check if specific user (user with specific UserId) has some specific role assigned to them?

Of course I can patch some function in SQL for checking roles or pull a UserProfile by UserId, extract name, get user by the name and finally check the roles. However both of those solutions sound more like a workaround to me and I'd rather use something more standard if possible.


Solution

  • Being unable to find the right answer to the question I ended up writing a scalar function in the database and using it through linq. Code of the function:

    CREATE function [dbo].[UserIsInRole](@UserId int, @Role nvarchar(MAX))
    RETURNS bit
    AS
    BEGIN
        DECLARE @amount int
        SELECT
            @amount = COUNT(UserId)
        FROM
            [dbo].webpages_UsersInRoles uir
            JOIN [dbo].webpages_Roles r ON
            (
                r.RoleId = uir.RoleId AND
                (
                    r.RoleName = @Role OR
                    @Role LIKE r.RoleName + ',%' OR
                    @Role LIKE '%,'+ r.RoleName + ',%' OR
                    @Role LIKE '%,'+ r.RoleName
                )
            )
        WHERE
            uir.UserId = @UserId
      RETURN IIF(@amount > 0, 1, 0)
    END
    

    Note that you can provide multiple roles on the input and the function will return true if the user in question fits any of them.