check that a specific user has specific permission in lightswitch - vb.net

I'm using lightswitch in VB , i need to check is a given user has specific permission ("User") or not
I've tried the below code:
Dim myper = Me.DataWorkspace.SecurityData.Permissions.Where(Function(p) p.Id.Equals("LightSwitchApplication:User", StringComparison.OrdinalIgnoreCase)).SingleOrDefault
If Not myper Is Nothing Then
Dim myu = myper.RolePermissions.SelectMany(Function(u) u.Role.RoleAssignments).Select(Function(us) us.UserName = UserName)
If Not myu Is Nothing Then
' this mean no user has the user permission!
results.AddPropertyError("found")
Else
'user has been found for this permission
results.AddPropertyError("not found")
End If
Else
'this mean no roles has this permission !
End If
but unfortunately the myu object always return nothing i don't know why, sorry for that but I'm new in LINQ.

You should use the Application.User object for this.
In csharp:
if(this.Application.User.HasPermission(Permissions.PermXYZ))
{
//permitted
}

Related

Using LINQ to set up a login page from an access database

I currently have a small table of 4 records of people in an Access Database each with just three fields, Role, Username and Password. Im trying to set up a login page where I'm using LINQ to read the Username and Password fields and then if they are both correct then to login to one of 4 possible roles depending on what role that person is allocated to on database. I currently have this.
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
Dim strUsername As String
Dim strPassword As String
Dim strRole As String
Dim query1 = From loginUsername In database1.tblStaff
Where loginUsername.FirstName = txtUsername.Text
Select loginUsername.FirstName
Dim query2 = From loginPassword In database1.tblStaff
Where loginPassword.Password = txtPassword.Text
Select loginPassword.Password
End Sub
End Class
As you can see, I'm trying to take what the user enters in each text box and match it to the database and then somehow set up an if statement checking if it's right but I'm not sure if I'm even on the right track.
Any help is great, thanks.
I guess it should be something like this (disclaimer: I'm not familiar with VB)
Dim role = (From entry In database1.tblStaff
Where entry .FirstName = txtUsername.Text
AndAlso entry.Password = txtPassword.Text
Select entry.Role)
.FirstOrDefault() 'execute query explicitly
'if a role is null, then login or password incorrect
If role Is Nothing Then
'No match
Else
'Use role here
End If
There is no point to separate queries. You can merge them in a single query
Thank you sm Chris this has been a lifesaver for Yvonne's project! Our group was really struggling with this. You probably already have you answer by now, that code works really well. You just have to add your If statements after:
If query1.Count = 1 And query2.Count = 1 Then
Me.Hide()
FrmExample.Show()
Else
MessageBox.Show("Incorrect username or password", "Warning")
End If
Idk if that's any help, thank you!

Active Directory: Add New User C# / VB

I browsed other questions and couldn't find the answer.
What is the appropriate way to add a new user to a active directory specific group when the "current user" running the application does not have access rights to add new users?
I am currently authenticating as the domain Administrator to do it, but obviously that is a security no-no and I don't want the Administrator user's credentials hard-codeded in my code.
I assume the answers is not in my code itself but that I have to create a user in the Active Directory that has privileges to add users.
So my question is a combination of a AD and a Coding question:
1) How do I create a AD user that ONLY has access rights to add users to specific OU and CN security group?
2) Is their any way possible to not hard-code the password for this user?
Or... am I going about this entirely wrong?
Here is my current VB.NET code:
Public Function CreateUser(ByVal UserName As String, ByVal Password As String, ByVal DisplayName As String) As Boolean
Try
'Dim catalog As Catalog = New Catalog()
Dim de As DirectoryEntry = New DirectoryEntry()
de.Path = "LDAP://OU=TS2xUsers,DC=dc,DC=example,DC=com"
de.AuthenticationType = AuthenticationTypes.Secure
de.Username = "Administrator"
de.Password = "foopassword"
'1. Create user accountd
Dim users As DirectoryEntries = de.Children
Dim newuser As DirectoryEntry = users.Add("CN=" & DisplayName, "user")
newuser.Properties("givenname").Value = DisplayName
newuser.Properties("name").Value = DisplayName
newuser.Properties("displayName").Value = DisplayName
newuser.Properties("SAMAccountName").Value = UserName
newuser.Properties("userPrincipalName").Value = UserName & "#dc.example.com"
'newuser.Properties("OU").Value = "TS2xUsers"
newuser.CommitChanges()
Dim ret As Object = newuser.Invoke("SetPassword", Password)
newuser.CommitChanges()
Dim exp As Integer = CInt(newuser.Properties("userAccountControl").Value)
exp = exp And Not &H2 'enable acccount
exp = exp Or &H10000 'dont expire password
newuser.Properties("userAccountControl").Value = exp
newuser.CommitChanges()
''' 5. Add user account to groups
If MakeTSUser(newuser) = False Then
Return False
newuser.Close()
de.Close()
End If
newuser.Close()
de.Close()
Return True
Catch ex As Exception
MsgBox("Failed to create user due to the following reason: " & ex.Message, MsgBoxStyle.Critical)
Return False
End Try
End Function
Private Function MakeTSUser(ByVal deUser As DirectoryEntry) As Boolean
Try
Dim deRBGroup As New DirectoryEntry
deRBGroup.Path = "LDAP://CN=TSUsers,CN=Builtin,DC=dc,DC=example,DC=com"
deRBGroup.AuthenticationType = AuthenticationTypes.Secure
deRBGroup.Username = "Administrator"
deRBGroup.Password = "foopassword"
Dim deDomainUsers As New DirectoryEntry
deDomainUsers.Path = "LDAP://CN=Domain Users,CN=Users,DC=dc,DC=example,DC=com"
deDomainUsers.AuthenticationType = AuthenticationTypes.Secure
deDomainUsers.Username = "Administrator"
deDomainUsers.Password = "foopassword"
Dim primaryGroupToken As Object = Nothing
deRBGroup.Invoke("Add", New Object() {deUser.Path.ToString()})
deRBGroup.CommitChanges()
'Get Primary Group Token of MYGROUP
deRBGroup.Invoke("GetInfoEx", New Object() {New Object() {"primaryGroupToken"}, 0})
primaryGroupToken = deRBGroup.Properties("primaryGroupToken").Value
'Assign Primary Group Token value of MYROUP to the User's PrimaryGroupID
deUser.Properties("primaryGroupID").Value = primaryGroupToken
deUser.CommitChanges()
'Remove the User from "Domain Users" group
deDomainUsers.Invoke("Remove", New Object() {deUser.Path.ToString()})
deDomainUsers.CommitChanges()
Return True
Catch ex As Exception
Return False
End Try
End Function
What is the appropriate way to add a new user to a active directory specific group when the "current user" running the application does not have access rights to add new users?
Run the app as a user that does have those permissions... but you already know this:
I assume the answers is ... to create a user in the Active Directory that has privileges to add users.
Is their any way possible to not hard-code the password for this user?
Good question. One way to do this by setting up a Windows Scheduled Task. You can setup a task to run on demand, with no actual schedule, and to run as any user you want, including your new service account. You will have to put in the password for that user when you setup the task, but only when you first setup the task, and the actual password won't be stored... only the authentication token, which is not transferable. Then your desktop application can trigger the task to start.
Another way to do this is to grant the unprivileged HR or helpdesk users who run your app permissions to create new users just within your specific OU. In the case of a web app, you can also do this for the user account that runs the web site, as long as you have appropriate logging and auditing in place.
The other option is to create a separate service to create the users, which runs as the appropriate user. This could be a web service, where less-privileged authenticated users can post the new account information, or it could be a Windows service doing something like watching a file share, where your unprivileged users then have the ability or write to the file share. Then your program can know how to call the service or write the correct file formats into the share.

Finding user name of current logged in user using VB.NET

I'm trying to get the user name of the current user. When I log in as Johnny Smith and run my application without administrator privileges it will return me the correct user name, Johnny Smith. But the problem is that when I right click and choose "Run as Administrator", Windows will prompt me with a login screen for the administrator and after login my application returns user name admin, not the user which is logged in currently.
I have tried:
strUserLabel.Text = Environment.UserName
Also
Dim WSHNetwork = CreateObject("WScript.Network")
Dim strUser = ""
While strUser = ""
strUser = WSHNetwork.Username
End While
strUserLabel.Text = strUser
Both return me the administrator user name when prompted as administrator.
In the MSDN documentation, I discovered they changed the definition of property Environment.UserName.
Before .NET 3
Gets the user name of the person who started the current thread.
Starting from version 3
Gets the user name of the person who is currently logged on to the Windows operating system
I think the accepted answer above is a VERY resource intensive way to find a username. It has nested loops with hundreds of items. In my 8GP RAM PC this takes 2+ seconds!
How about:
Username: SystemInformation.Username, and
DomainName: Environment.UserDomainName
Tested in VS2017
I have figured it out. I used this function which will determine which process which the user is using. In my code I defined that look for username of the explorer.exe process.
Function GetUserName() As String
Dim selectQuery As Management.SelectQuery = New Management.SelectQuery("Win32_Process")
Dim searcher As Management.ManagementObjectSearcher = New Management.ManagementObjectSearcher(selectQuery)
Dim y As System.Management.ManagementObjectCollection
y = searcher.Get
For Each proc As Management.ManagementObject In y
Dim s(1) As String
proc.InvokeMethod("GetOwner", CType(s, Object()))
Dim n As String = proc("Name").ToString()
If n = "explorer.exe" Then
Return s(0)
End If
Next
End Function
Index of 0 will return username
Index of 1 will return domain name of user
SystemInformation.Username doesn't work for certain applications. In my case, code is being run as System but explorer.exe is being run as Daniel. SystemInformation.Username reports System.
if using Identity
Dim UserEmail As String = Context.User.Identity.Name.ToString

Request admin credentials for part of a project

I have a fairly basic VB.NET project that allows users to restore certain parts of their profiles, should it ever need to be recreated (IE Favourites, Quick Launch, that sort of thing).
I have added to the project the ability to restore these profile parts on behalf of other users, but for this you should have Administrator privileges for our Domain, and I wish the project to prompt for appropriate credentials.
Is this possible for only part of a project? I've looked in to manifests, but from my (limited) understanding it seems that they are only appropriate for for projects as a whole, as opposed to components of a project. Thanks.
If Username = "" Then
Return False
ElseIf Not Username = CurrentUsername Then
'** Require admin privilages *'
Else
Return True
End If
Answering your comment i got this:
If My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator) Then
MessageBox.Show("Yes")
Else
MessageBox.Show("No")
End If
It tells if your application is being runned as admin or not.
I figured this out in the end (almost). The code below uses a Username and Password supplied in an optional 'Settings' form to check whether the current user is a member of the built-in Administrators group in our Domain.
Public Function IsAuthenticatedUser(ByVal Username As String,
Optional ByVal Group As String = "Administrators") As Boolean
Dim IsAuthenticated As Boolean = False
Try
Using RootContext2 As New PrincipalContext(ContextType.Domain,
"dynedrewett.com",
"DC=dynedrewett,DC=com",
Me.formSettings.txtUsername.Text,
Me.formSettings.txtPassword.Text & "XXX"), _
TheGroup As GroupPrincipal = GroupPrincipal.FindByIdentity(RootContext2, IdentityType.Name, Group), _
TheUser As UserPrincipal = UserPrincipal.FindByIdentity(RootContext2, IdentityType.SamAccountName, Username)
If TheGroup IsNot Nothing AndAlso TheUser IsNot Nothing Then
For Each SingleGroup As Principal In TheGroup.GetMembers(True)
If SingleGroup.Name = TheUser.DisplayName Then
IsAuthenticated = True
Exit For
End If
Next
Else
IsMember = False
End If
TheGroup.Dispose()
TheUser.Dispose()
End Using
Catch Ex As Exception
Dim ErrorForm As New formError(Ex, "Ensure that valid Administrator Credentials are specified in the application Settings.")
End Try
Return IsAuthenticated
End Function

ASP.NET - Deleting Computer Accounts Within AD

I'm building out a decommissioning application that will allow an individual to provide an computer name and the utility will go out and purge the computer record from various locations. I'm running into a problem when attempting to delete a computer account from Active Directory. I'm impersonating a service account that only has rights to "Delete All Child Objects" within a particular OU structure. The code below works if I run it with my domain admin account; however fails with an "Access Denied" when I run it with the impersonated service account. I have verified that the permissions are correct within AD as I can launch Active Directory Users and Computers using a "runas" and providing the service account credentials and I can delete computer objects perfectly fine.
Wondering if anyone has run into this before or has a different way to code this while still utilizing my current OU permissions. My gut tells me the "DeleteTree" method is doing more then just deleting the object.
Any assistance would be appreciated.
Sub Main()
Dim strAsset As String = "computer9002"
Dim strADUsername As String = "serviceaccount#domain.com"
Dim strADPassword As String = "password"
Dim strADDomainController As String = "domaincontroller.domain.com"
Dim objDirectoryEntry As New System.DirectoryServices.DirectoryEntry
Dim objDirectorySearcher As New System.DirectoryServices.DirectorySearcher(objDirectoryEntry)
Dim Result As System.DirectoryServices.SearchResult
Dim strLDAPPath As String = ""
Try
objDirectoryEntry.Path = "LDAP://" & strADDomainController
objDirectoryEntry.Username = strADUsername
objDirectoryEntry.Password = strADPassword
objDirectorySearcher.SearchScope = DirectoryServices.SearchScope.Subtree
objDirectorySearcher.Filter = "(&(ObjectClass=Computer)(CN=" & strAsset & "))"
Dim intRecords As Integer = 0
For Each Result In objDirectorySearcher.FindAll
Console.WriteLine(Result.Path)
Diagnostics.Debug.WriteLine("DN: " & Result.Path)
Dim objComputer As System.DirectoryServices.DirectoryEntry = Result.GetDirectoryEntry()
objComputer.DeleteTree()
objComputer.CommitChanges()
intRecords += 1
Next
If intRecords = 0 Then
Console.WriteLine("No Hosts Found")
End If
Catch e As System.Exception
Console.WriteLine("RESULT: " & e.Message)
End Try
End Sub
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
' set up domain context
Dim ctx As New PrincipalContext(ContextType.Domain, "DOMAIN", strADUsername, strADPassword)
' find a computer
Dim computerToDelete As ComputerPrincipal = ComputerPrincipal.FindByIdentity(ctx, strAsset)
If computerToDelete IsNot Nothing Then
' delete the computer, if found
computerToDelete.Delete()
End If
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Delete Tree is different from delete. You're going to need the Delete Subtree permission on the child computer objects for this to work.