Scan all the documents in a View - lotus-domino

So, this my code. It gets only the first document. But what I want to do is read a specific document. The view is a collection of usernames and passwords. So, for example : The username is in the 5th document, then the program will scan the view until it finds the right document. Sorry for my poor explanation. I hope you understand my problem.
On Error Goto e
Dim db As NotesDatabase
Dim view As NotesView
Dim results As Variant
Dim cmd As String
Dim d As NotesDocument, flag As Integer, upw As String, uname As String
Set db = source.Database
uname = Inputbox("Enter Username")
Set view = db.GetView("Registration View")
Set d = view.GetFirstDocument()
'cmd = {#DbLookup("";"48257E00:00089AF5";"RegView";1)}
'results = Evaluate(cmd)
Dim pw As String, un As String
'Forall Username In results
' Msgbox username(1)
'End Forall
If Not d Is Nothing Then
un = d.userfield(0)
pw = d.passfield(0)
If un <> uname Then
Msgbox "Username invalid!"
End If
If un = uname Then
upw = Inputbox("Enter Password")
If pw <> upw Then
Msgbox "Password invalid!"
End If
If pw = upw Then
Msgbox "Log In succesful!"
flag = 1
End If
End If
End If
If flag <> 1 Then Call source.Close()
Exit Sub
e:
Print Error, Erl

Instead of using view.getFirstDocument you should use view.getDocumentByKey(uname,true) which return the document with the key uname in the first column in the view
Make sure the first column In the view is set to sorted
If no document is found using the key then getDocumentByKey returns nothing

You can create a view with the first column userfield and the second column passfield. The first column has to be sorted.
In your code build an array of uname and upw
Dim strSearch (0 to 1) as String
Dim viewSearch as NotesView
Dim doc as NotesDocument
viewSearch = db.getView("YourSearchView")
strSearch(0) = uname
strSearch(1) = upw
Set doc = db.getDocumentByKey(strSearch, true)
If(Not doc is nothing)Then
Print "Login successfull"
Else
Print "Wrong username or password"
End if
If you want to use a two step check of username and then password you can create two search views and use the first for check if the username exists and the second for checking the given username and password.

Of course you could cycle through the complete view and compare each single entry, but that will be quite slow. In your code the complete "cycling" is missing. You would need to use a do - while loop to run through all entries in the view:
Set d = view.GetFirstDocument()
Do
un = d.userfield(0)
pw = d.passfield(0)
'- here comes the rest of your code, if password is right - exit
If flag = 1 then exitLoop = True
Set d = view.GetNextDocument( d )
if d is Nothing then exitLoop = True
Loop until exitLoop
But this is quite inefficient. If your view is sortey by username (if not, create one that is), then use getDocumentbyKey as suggested by Thomas.
Set d = view.GetDocumentByKey( uname )
If not d is Nothing then
un = d.userfield
The question is WHY would one do something like this: Notes / Domino has a great security concept and saving all usernames and passwords in a view, where everybody can simple read the passwords by checking the document properties is -sorry to say- stupid and does not give you even one more bit of security...

Related

GetByKey() not working in some users in SAP B1

So I have this problem where I want to get DocEntry in OPCH table so I use the GetByKey(). The problem is that it works in all users except this particular user where GetByKey() returns false when I logged in to this specific user.
here is my code:
Sub SaveTransmit(ByVal tForm As SAPbouiCOM.Form)
Dim tMatrix As SAPbouiCOM.Matrix = Nothing
tMatrix = tForm.Items.Item("3").Specific
Dim MyDoc As SAPbobsCOM.Documents = oCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oPurchaseInvoices)
Dim mtRow As Integer = tMatrix.RowCount
For xxxt As Integer = 1 To mtRow
tCheckE = tMatrix.Columns.Item("Col0").Cells.Item(xxxt).Specific
tCheckB = tMatrix.Columns.Item("Col1").Cells.Item(xxxt).Specific 'Checkbox
Dim koji As Boolean = tCheckB.Checked
If koji = True Then
If MyDoc.GetByKey(tCheckE.Value) Then
'some codes
End if
End if
Next
End Sub
I don't know if this is a bug in SAP B1 or I need to configure this specific user.
This sounds like some kind of permission issue. Validate license ( prof vs limited ), data owner or general authorization.

Take list box selection, add value to other list box without allowing duplicates

I have two list boxes on a form I am making. The first list box is linked to a table with various company names. The goal I am after is after double clicking a companies name, the value is inserted in the second list box.
It worked fine until I tried to add code to prevent duplicates from appearing in the second list box, so you couldn't accidentally insert the same company twice. I have tried several different iterations, but with no luck. Anyone able to help with this one? My end goal would be for a msgbox to pop up alerting the user that duplicates are not allowed.
Private Sub ContractorLstbx_DblClick(Cancel As Integer)
Dim found As Boolean
found = False
Dim ID As Long
Dim Contractor As String
For Each newItem In Me.ContractorLstbx.ItemsSelected
For j = 0 To Me.SelectedContractorLst.ListCount - 1
If (Me!ContractorLstbx.ItemData(newItem).Column(1) = Me.SelectedContractorLst.ItemData(j).Column(1)) Then
found = True
Exit For
End If
Next j
If found = False Then
ID = Me.ContractorLstbx.ItemData(newItem)
Me.SelectedContractorLst.AddItem ContractorLstbx!.ItemData(newItem).Column(0) & ";" & Me!ContractorLstbx.ItemData(newItem).Column(1)
End If
found = False
Next newItem
End Sub
This is the full code for your solution. I tried it on test sample and working fine. just copy and paste the code. If you need your comparison to be case sensitive (I mean A <> a) then use Option Compare Binary as in my code below. If it is required to be case insensitive (A = a) just leave the default Option Compare Database or better force it using Option Compare Text
Option Compare Binary
Private Sub ContractorLstbx_DblClick(Cancel As Integer)
Dim found As Boolean
found = False
Dim ID As Long
Dim Contractor As String
For i = 0 To Me.ContractorLstbx.ItemsSelected.Count - 1
For j = 0 To Me.SelectedContractorLst.ListCount - 1
If (Me.ContractorLstbx.Column(1, Me.ContractorLstbx.ItemsSelected(i)) = Me.SelectedContractorLst.Column(1, j)) Then
found = True
Exit For
End If
Next j
If found = False Then
ID = Me.ContractorLstbx.ItemData(Me.ContractorLstbx.ItemsSelected(i))
Me.SelectedContractorLst.AddItem (ContractorLstbx.Column(0, Me.ContractorLstbx.ItemsSelected(i)) & ";" & Me.ContractorLstbx.Column(1, Me.ContractorLstbx.ItemsSelected(i)))
End If
found = False
Next i
End Sub

Referencing an entire data set instead of a single Cell

I am creating a login form for users to log into using a database. I was wondering if there is a way in which i could get the program to search the entire table instead of a certain item. Here is my code so far.
Dim UserInputtedUsername As String
Dim UserInputtedPassword As String
UserInputtedUsername = txtAdminUsername.Text
UserInputtedPassword = txtAdminPassword.Text
sqlrunnerQuery = "SELECT * FROM tblLogin"
daRunners = New OleDb.OleDbDataAdapter(sqlrunnerQuery, RunnerConnection)
daRunners.Fill(dsRunner, "Login")
If UserInputtedUsername = dsadminlogin.Tables("Login").Rows(0).Item(2) And UserInputtedPassword = dsadminlogin.Tables("Login").Rows(0).Item(3) Then
Form1.Show()
ElseIf MsgBox("You have entered incorrect details") Then
End If
End Sub
Instead if searching the (in-memory) DataSet for your user serach the database in the first place. Therefore you have to use a WHERE in the sql query(with guessed column names):
sqlrunnerQuery = "SELECT * FROM tblLogin WHERE UserName=#UserName AND PassWord=#PassWord"
Note that i've used sql-parameters to prevent sql-injection. You add them in this way:
daRunners = New OleDb.OleDbDataAdapter(sqlrunnerQuery, RunnerConnection)
daRunners.SelectCommand.Parameters.AddWithValue("#UserName", txtAdminUsername.Text)
daRunners.SelectCommand.Parameters.AddWithValue("#PassWord", txtAdminPassword.Text)
Now the table is empty if there is no such user.
If dsadminlogin.Tables("Login").Rows.Count = 0 Then
MsgBox("You have entered incorrect details")
End If
For the sake of completeteness, you can search a complete DataTable with DataTable.Select. But i prefer LINQ-To-DataSet. Here's a simple example:
Dim grishamBooks = From bookRow in tblBooks
Where bookRow.Field(Of String)("Author") = "John Grisham"
Dim weHaveGrisham = grishamBooks.Any()

MS access Encrypt Users Passwords Stored in User Table (SQL)

My database is Access front end which is linked to SQL tables, is there a way of Encrypting/Hashing the passwords that are stored in my user table?
I have seen something about Hashbytes and Salt? but not sure how to implement it?
thank you in advance for your help
There is no native way to encrypt/decrypt in Access, but it's not hard to create your own. You can use the old "Zebras" method, by assigning different letters to the alphabet (you could also use some numbers or other ASCII characters instead):
Public Function Encrypt(strvalue As String) As String
Const LowerAlpha As String = "abcdefghijklmnopqrstuvwxyz"
Const LowerSub As String = "zebrascdfghijklmnopqtuvwxy" 'zebras
Const UpperAlpha As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Const UpperSub As String = "ZEBRASCDFGHIJKLMNOPQTUVWXY" 'ZEBRAS
Dim lngi As Long
Dim lngE As Long
Dim strEncrypt As String
Dim strLetter As String
If strvalue & "" = "" Then Exit Function
For lngi = 1 To Len(strvalue)
strLetter = Mid(strvalue, lngi, 1)
Select Case Asc(strLetter)
Case 65 To 90 'Uppercase
'Find position in alpha string
For lngE = 1 To Len(UpperAlpha)
If Mid(UpperAlpha, lngE, 1) = strLetter Then GoTo USub
Next
USub:
strEncrypt = strEncrypt & Mid(UpperSub, lngE, 1)
Case 97 To 122 'Lowercase
'Find position in alpha string
For lngE = 1 To Len(LowerAlpha)
If Mid(LowerAlpha, lngE, 1) = strLetter Then GoTo LSub
Next
LSub:
strEncrypt = strEncrypt & Mid(LowerSub, lngE, 1)
Case Else 'Do not substitute
strEncrypt = strEncrypt & strLetter
End Select
Next
'Now pass this string through ROT13 for another tier of security
For lngi = 1 To Len(strEncrypt)
Encrypt = Encrypt & Chr(Asc(Mid(strEncrypt, lngi, 1)) + 13)
Next
End Function
Then work backwards to decrypt:
Public Function Decrypt(strvalue As String) As String
Const LowerAlpha As String = "abcdefghijklmnopqrstuvwxyz"
Const LowerSub As String = "zebrascdfghijklmnopqtuvwxy" 'zebras
Const UpperAlpha As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Const UpperSub As String = "ZEBRASCDFGHIJKLMNOPQTUVWXY" 'ZEBRAS
Dim lngi As Long
Dim lngE As Long
Dim strDecrypt As String
Dim strLetter As String
If strvalue & "" = "" Then Exit Function
'Reverse the ROT13 cipher
For lngi = 1 To Len(strvalue)
strDecrypt = strDecrypt & Chr(Asc(Mid(strvalue, lngi, 1)) - 13)
Next
'Now reverse the encryption
For lngi = 1 To Len(strDecrypt)
strLetter = Mid(strDecrypt, lngi, 1)
Select Case Asc(strLetter)
Case 65 To 90 'Uppercase
'Find position in sub string
For lngE = 1 To Len(UpperSub)
If Mid(UpperSub, lngE, 1) = strLetter Then GoTo USub
Next
USub:
Decrypt = Decrypt & Mid(UpperAlpha, lngE, 1)
Case 97 To 122 'Lowercase
'Find position in sub string
For lngE = 1 To Len(LowerSub)
If Mid(LowerSub, lngE, 1) = strLetter Then GoTo LSub
Next
LSub:
Decrypt = Decrypt & Mid(LowerAlpha, lngE, 1)
Case Else 'Do not substitute
Decrypt = Decrypt & strLetter
End Select
Next
End Function
Unfortunately, if you modify or encrypt the connection in the linked table then you will find that you cannot connect to SQL serer. Any suggesting here about having some “encryption” routine will NOT WORK and is NOT relevant since if you modify or mess with the connection strings in your linked tables, then the linked tables will fail. Thus the ONLY possible way this could work is if you take the encrypted connection, de-crept and re-link to SQL server with the plan text connect strings with the user ID and password in plain sight. At this point any user placing their cursor over a linked table will see the user id and password in plain sight (so you gain little if anything by this suggested approach).
The two solutions are:
1 – use windows authentication on SQL server. That means the plain text connections in the Access linked tables do NOT require the user id and password.
2 – use cached logons. This is the RECOMMENDED solution.
Thus you DO NOT include the uid and password in the connection string. Thus there is no need to worry about users looking at the connection string.
What you thus do on startup is execute a logon. The VERY INSTANT you execute a SQL logon, then all linked tables WITHOUT userid/password WILL NOW WORK!
The logon code I use is thus this:
Function TestLogin(strcon As String) As Boolean
On Error GoTo TestError
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb()
Set qdf = dbs.CreateQueryDef("")
qdf.Connect = strcon
qdf.ReturnsRecords = False
'Any VALID SQL statement that runs on server will work below.
' this does assume user has enough rights to query built in
' system tables
qdf.SQL = "SELECT 1 as test"
qdf.Execute
TestLogin = True
Exit Function
TestError:
TestLogin = False
Exit Function
End Function
How to achieve this is outlined in detail here:
Power Tip: Improve the security of database connections
http://blogs.office.com/b/microsoft-access/archive/2011/04/08/power-tip-improve-the-security-of-database-connections.aspx
It makes LITTLE sense to encrypt the connection string, since then on startup you have to re-link with plain connection strings NOW in sight. And worse is on shutdown you have to re-link the tables gain, else they all be in that linked state with full uid/passwords in plain sight.
Not only is such a process time consuming, but prone to MUCH failure and if the application is shutdown incorrect then the “proposed” schemes here of using custom linking will not only fail, but are impractical solutions.
So using cached logons and passwords results in NOT having to include password and logon in those strings. You can prompt a user for their uid/password, execute the logon and NOW all linked tables like magic will use that logon/pass and do NOT have to be linked and thus you don’t have to store the userid/logon in the application or in the linked table(s) connection strings.

VB.NET - How to see if Current User's Group Name matches a specified Group Name using Active Directory Roles and SID's

I'm trying to match up a specific group name and see if it exists for the currently logged in user using Active Directory roles. If the Group Name exists for the Current User, I want that group name to be displayed in a drop down list.
Example: If current user is in BIG Group, display BIG in drop down list.
Problem: All I am getting is SIDs and I'm not able to get anything to match up to the group name and nothing will show up in the drop down list.
I also get the following Error:
Error: Object variable or WIth block variable not set.
How do I fix this??
here is the code I am using:
Private Sub GetMarketingCompanies()
' code to populate marketing company drop down list based on the current logged in users active directory group that
' corresponds to which marketing company they are in
Dim irc As IdentityReferenceCollection
Dim ir As IdentityReference
irc = WindowsIdentity.GetCurrent().Groups
Dim strGroupName As String
For Each ir In irc
' Dim mktGroup As IdentityReference = ir.Translate(GetType(NTAccount))
MsgBox(mktGroup.Value)
Debug.WriteLine(mktGroup.Value)
strGroupName = mktGroup.Value.ToString
Next
For Each UserGroup In WindowsIdentity.GetCurrent().Groups
If mktGroup.Value = "BIG" Then
Dim Company = ac1.Cast(Of MarketingCompany).Where(Function(ac) ac.MarketingCompanyShort = "BIG").FirstOrDefault
If Company IsNot Nothing Then
marketingCo.Items.Add(String.Format("{0} | {1}", Company.MarketingCompanyShort, Company.MarketingCompanyName))
End If
End If
Next
Thanks for looking!
Any helpful answers will be up-voted!
I'm not sure what you are referring to by roles but the following will list the current users groups (both local and domain):
For Each ir As IdentityReference In WindowsIdentity.GetCurrent.Groups
Debug.WriteLine(CType(ir.Translate(GetType(NTAccount)), NTAccount).Value)
Next
In response to your answer - Strikes me that if this is what you want to do the following is probably more efficient and easier to read:
Dim p As WindowsPrincipal = New WindowsPrincipal(WindowsIdentity.GetCurrent())
If p.IsInRole("ALG\ACOMP_USER_ADMIN") Then
'load all groups
ElseIf p.IsInRole("ALG\ACOMP_USER_BIG") Then
'load BIG groups
ElseIf p.IsInRole("ALG\ACOMP_USER_AMG") Then
'load AMG groups
'etc
End If
I ended up doing the following to fix the code:
deleting the the For loop that calls UserGroup In WindowsIdentity.GetCurrent().Groups
putting all the code under the For Each Loop that calls IdentityReference In IdentityReferenceCollection
adding mcisloaded boolean variable to make the admin, not admin if statements work
disabling MsgBox(mktGroup.Value) as this was just for trial and error to see what values were getting returned
Here's the code:
Private Sub GetMarketingCompanies()
Try
Dim ac1 As Array
ac1 = proxy.GetMarketingCompanyNames("test", "test")
' code to populate marketing company drop down list based on the current logged in users active directory group that
' corresponds to which marketing company they are in
Dim irc As IdentityReferenceCollection
Dim ir As IdentityReference
irc = WindowsIdentity.GetCurrent().Groups
Dim strGroupName As String
Dim mcisloaded As Boolean
' Translate the current user's active directory groups
For Each ir In irc
Dim mktGroup As IdentityReference = ir.Translate(GetType(NTAccount))
' MsgBox(mktGroup.Value)
Debug.WriteLine(mktGroup.Value)
strGroupName = mktGroup.Value.ToString
' If the user is in the admin group, load all marketing companies
If mktGroup.Value = "ALG\ACOMP_USER_ADMIN" Then
mcisloaded = True
For Each item In ac1
marketingCo.Items.Add(String.Format("{0} | {1}", item.MarketingCompanyShort, item.MarketingCompanyName))
Next
End If
'If the user is not in the admin group, load marketing companies individually
If Not mktGroup.Value = "ALG\ACOMP_USER_ADMIN" Then
mcisloaded = False
If mcisloaded = False Then
If mktGroup.Value = "ALG\ACOMP_USER_BIG" Then
Dim Company = ac1.Cast(Of MarketingCompany).Where(Function(ac) ac.MarketingCompanyShort = "BIG").FirstOrDefault
If Company IsNot Nothing Then
marketingCo.Items.Add(String.Format("{0} | {1}", Company.MarketingCompanyShort, Company.MarketingCompanyName))
End If
End If
If mktGroup.Value = "ALG\ACOMP_USER_AMG" Then
Dim Company = ac1.Cast(Of MarketingCompany).Where(Function(ac) ac.MarketingCompanyShort = "AMG").FirstOrDefault
If Company IsNot Nothing Then
marketingCo.Items.Add(String.Format("{0} | {1}", Company.MarketingCompanyShort, Company.MarketingCompanyName))
End If
End If
' ... Code for loading the rest of the marketing groups
End If
End If
Update 6-7-11: Here's a cleaner version of cycling through all the active directory group names by using a string splitter to get the last 3 letters that identifies the marketing company, instead of a series of if statements for each marketing company:
Private Sub GetMarketingCompanies()
Try
Dim marketingCompanyNamesArray As Array
marketingCompanyNamesArray = proxy.GetMarketingCompanyNames("test", "test")
' code to populate marketing company drop down list based on the current logged in users active directory group that
' corresponds to which marketing company they are in
Dim identityReferenceCollection As IdentityReferenceCollection
Dim identityReference As IdentityReference
identityReferenceCollection = WindowsIdentity.GetCurrent().Groups
Dim strGroupName As String
Dim mcisloaded As Boolean
' Translate the current user's active directory groups
For Each identityReference In identityReferenceCollection
Dim mktGroup As IdentityReference = identityReference.Translate(GetType(NTAccount))
' MsgBox(mktGroup.Value)
' Debug.WriteLine(mktGroup.Value)
strGroupName = mktGroup.Value.ToString
' Locally User group is ALG\ACOMP_USER_ADMIN , deployed ALGWEB\ACOMP_USER_ADMIN
' If the user is in the admin group, load all marketing companies
If mktGroup.Value = "ALG\ACOMP_USER_ADMIN" Then
mcisloaded = True
For Each item In marketingCompanyNamesArray
marketingCo.Items.Add(String.Format("{0} | {1}", item.MarketingCompanyShort, item.MarketingCompanyName))
Next
Else
'If not admin user (mcisloaded = False) load each group individually if it appears in AD
' For Each UserGroup In WindowsIdentity.GetCurrent().Groups that begins with ALG\ACOMP_USER, load marketing companies
Dim MarketingCompanyShortName As String = ""
Dim mktGroupName As String = mktGroup.Value
If mktGroupName.StartsWith("ALG\ACOMP_USER") Then
Dim marketingGroupNameParts() As String = Split(mktGroupName, "_")
'Load MarketingCompanyShortName from the end of marketingGroupNameParts - example: ACOMP_USER_BIG
MarketingCompanyShortName = marketingGroupNameParts(2)
'If MarketingCompanyShortName exists, load it into the dropdownlist
Dim Company = marketingCompanyNamesArray.Cast(Of MarketingCompany).Where(Function(ac) ac.MarketingCompanyShort = MarketingCompanyShortName).FirstOrDefault
If Company IsNot Nothing Then
marketingCo.Items.Add(String.Format("{0} | {1}", Company.MarketingCompanyShort, Company.MarketingCompanyName))
End If
End If
End If