MS Access: Locking Specific Forms Error - ms-access

I am creating a database which has some forms restricted for some users and some are accessible depending on their user type (For example: Admin, User, Guest). I created a visual basic code on the On Load Event of my Main Form and I also call the user type in that form (txtUserType). I want the Admin form to be accessible only by the admins but when I logged in as an admin, the admin form is still locked. Any help on how I can resolve this?
I created a string in my login form for me to be able to call the value of the UserType in my main form. Here is the code:
Dim UserType As String
UserType = DLookup("[UserType]", "tbl_Worker", "[LoginID] = '" &
Me.txtUsername.Value & "'")
Forms![frm_Home]![txtUserType] = UserType
And now the textbox in my main form which is txtUserType shows the user type of who ever is logged in.
My code in the main form is:
Private Sub Form_Load()
If Me.txtUserType = "Admin" Then
Me.NavigationButton419.Enabled = True
Else
Me.NavigationButton419.Enabled = False
End If
End Sub

Try this and report back any issues.
Private Sub Form_Load()
NavigationButton419.Enabled = IsAdmin(txtUsername.Value)
End Sub
Private Function IsAdmin(ByVal Username As String)
IsAdmin = (Nz(DLookup("[UserType]", "tbl_Worker", "[LoginID] = '" & Username & "'"), "Guest") = "Admin")
End Function

3 possible suggestions:
Change the event where you are testing
i.e. instead of
Form_Load
use
Form_Current
Or better yet:
Store the txtUserType Field on a totally different Form (could also be a form that is open as a hidden form)
If Forms!myHiddenForm.txtUserType = "Admin" Then
...
Or a neater way:
create a VBA function in a module
Public Function isSuperUser() As Boolean
If Forms!myHiddenForm.txtUserType = "Admin" Then
isSuperUser = True
Else
isSuperUser = False
End if
End Function
then back on your form
Private Sub Form_Load()
Me.NavigationButton419.Enabled = isSuperUser()
End Sub

As I experimented on different ways to create a solution to the problem and based on other's suggestions, I came up with this and it worked as I wanted to. Here is the code:
Dim UserType As String
UserType = DLookup("[UserType]", "tbl_Worker", "[LoginID] = '" &
Me.txtUsername.Value & "'")
DoCmd.OpenForm "frm_Home"
Forms![frm_Home]![txtUserType] = UserType
If Form_frm_Home.txtUserType = "Admin" Then
Form_frm_Home.NavigationButton438.Enabled = True
Else
Form_frm_Home.NavigationButton438.Enabled = False
End If

Related

How to store user's information for future use from MySQL

I have a very simple application where a user will login and be redirected to the dashboard. I got the login part working, however, my next goal is to be able to store the users information for later use on other forms.
Example: User "admin" logs in successfully. I need to be able to store every column in the table for admin so that we can call the user's information for welcome messages, user information form, etc without having to query the database everytime.
I believe this can be accomplished with a class, however, I'm unsure how to rewrite my login script to save all details into a class.
I've tried creating a class, and adding Public Shared properties for each column but I'm not sure how to get every column into the class rather than just the username.
Imports MySql.Data.MySqlClient
Public Class frmLogin
'count is number of invalid login attempts
Dim count As Integer
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
count = count + 1
Dim x As New MySqlConnection
Dim admin As New MySqlCommand
Dim dr1 As MySqlDataReader
ConnectDatabase()
admin.Connection = conn
admin.CommandText = "SELECT user.username, user.password FROM user WHERE user.username = '" & txtUsername.Text & "' and user.password = '" & txtPassword.Text & "'"
dr1 = admin.ExecuteReader
If dr1.HasRows Then
'Read the data
dr1.Read()
Me.Hide()
frmDashboard.Show()
Else
MsgBox("Invalid Username or Password! " & vbCrLf & count & " out of 3 attempts remaining.")
If count >= 3 Then
MsgBox("You have exceeded the maximum number of attempts to login. Account has been disabled. Please contact OJFS helpdesk at extension 100.", MsgBoxStyle.Critical)
txtUsername.Enabled = False
txtPassword.Enabled = False
End If
End If
Connect.conn.Close()
End Sub
Dim Assistance As Boolean = False
Private Sub linkLoginHelp_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles linkLoginHelp.LinkClicked
If Assistance = True Then
Me.Height = 284
Me.CenterToScreen()
Assistance = False
txtUsername.Select()
Else
Me.Height = 463
Me.CenterToScreen()
Assistance = True
txtUsername.Select()
End If
End Sub
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
Application.Exit()
End Sub
End Class
The Using...End Using blocks ensure that your database objects are closed and disposed even if there is an error.
Of course in a real application you would NEVER store passwords as plain text.
Comments in line.
'Your class might look something like this
Public Class User
Public Shared ID As Integer
Public Shared Name As String
Public Shared Department As String
Public Shared Address As String
End Class
Private count As Integer
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
count = count + 1
'keep connections local for better control
'pass the connection strings directly to the constructor of the connection
Using cn As New MySqlConnection("Your connection string")
'pass the query and the connection directly to the constructor of the commmand
Using cmd As New MySqlCommand("SELECT * FROM user WHERE user.username = #User and user.password = #Password;", cn)
'Always use parameters to avoid SQL injection
cmd.Parameters.Add("#User", MySqlDbType.VarChar).Value = txtUsername.Text
cmd.Parameters.Add("#Password", MySqlDbType.VarChar).Value = txtPassword.Text
'Open the Connection at the last possible minute.
cn.Open()
Using dr1 = cmd.ExecuteReader
If dr1.HasRows Then
dr1.Read()
'The indexes of the data reader depent on th order of the fields in the database
User.ID = CInt(dr1(0))
User.Name = dr1(1).ToString
User.Department = dr1(2).ToString
User.Address = dr1(3).ToString
Me.Hide()
frmDashboard.Show()
Return 'a successful login will end here
End If
End Using 'closes and disposed the reader
End Using 'close and disposes the command
End Using 'closes and dipose the connection
MsgBox("Invalid Username or Password! " & vbCrLf & count & " out of 3 attempts remaining.")
If count >= 3 Then
MsgBox("You have exceeded the maximum number of attempts to login. Account has been disabled. Please contact OJFS helpdesk at extension 100.", MsgBoxStyle.Critical)
btnLogin.Enabled = False 'Instead of the text boxes disable the button.
'If you just disable the text boxes they can keep clicking the button and opening connections.
End If
End Sub

Microsoft Access - Login

just curious if it is possible to store a label with someones login name.
i would like it so that when a check box is ticked, it will show the username of the person who is logged (checked by "Bob").
Thankyou
In your project, define a public variable strUserName and set the value to strUserName = Environ("Username") on Form load or from User table defined.
Using the click event of the checkbox set the label caption.
Public strUsername As String
Private Sub chk1_Click()
If Me.chk1.Value Then
Me.lbl_username.Caption = strUsername
Else
Me.lbl_username.Caption = ""
End If
End Sub
Private Sub Form_Load()
strUsername = Environ("Username")
End Sub

Unable to filter datasheet form after inserting value in ms access

I am using a datahseet subform in my main form for the realtime view of entries added in the table via the main form. This subform filters data on load event and checks with users windows username and compares it with data, it should only show data of respective owner. That means it willl filter the name field and shows only the entries made by the respective user(to unable users to edit each other's entries). It works well with the below code which I used in this datasheet form's vba :
Option Compare Database
Option Explicit
Dim GetUserName As String
Dim GetEmpID As String
Dim RecCount As String
Public Sub GetValues()
Dim obj1 As Object
Set obj1 = CreateObject("WScript.Network")
GetUserName = DLookup("[BAFUser]", "BAF_User", "[BRID] = '" & obj1.UserName & "'")
RecCount = DCount("[ID]", "Mau_con", "[AdvisorName] = '" & GetUserName & "'")
Set obj1 = Nothing
End Sub
Private Sub Form_AfterInsert()
Call Form_Load
End Sub
Private Sub Form_Load()
Call GetValues
If RecCount > 0 Then
Dim strOpen As String
strOpen = "[AdvisorName] = '" & GetUserName & "'"
Me.Filter = strOpen
Me.FilterOn = True
Me.Recordset.MoveLast
End If
End Sub
It filters the data on load but problems arises when a new user comes and login, then it will skip the if loop and will work normally, I tried to requery the form after making first entry by the new user & I also tried to call form_load in after insert event but both did not work.
But it filters the data once we close it and reopen it.
What is the best way to overcome this ?
Please ask if any other information needed.
Thanks in Advance.

Role-based access control used in MS Access

I am currently working on a project were one of the requirements are to use the users windows login as their login for MS Access, where they would then click there role to gain access into the system. I have never done this before but I have set up a login screen in Access which pulls data from a table. I have code that successfully pulls the users windows login but I am having trouble after this. The table name is tblUser and the users are General User, HR, and Admin. Currently, In the table I have the roles assigned number with General User = 1, HR = 2, Admin = 3.
The Login Screen:
Log On
General User
HR
Admin
Code that pulls the user information:
Private Sub Form_Load()
Stop
Debug.Print Environ("UserName")
Debug.Print Environ$("ComputerName")
Dim strVar As String
Dim i As Long
For i = 1 To 255
strVar = Environ$(i)
If LenB(strVar) = 0& Then Exit For
Debug.Print strVar
Next
End Sub
Below is the code that I built for my login screen in the past. Through drawing everything out it seems as though it would be the same process but I am not to sure. Is there anything that I can do to the code below?
Private Sub btnLogin_Click()
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("tblUser", dbOpenSnapshot, dbReadOnly)
rs.FindFirst "UserName='" & Me.txtUserName & "'"
If rs.NoMatch = True Then
Me.lblWrongUser.Visible = True
Me.txtUserName.SetFocus
Exit Sub
End If
Me.lblWrongUser.Visible = False
If rs!Password <> Nz(Me.txtPassword, "") Then
Me.lblWrongPass.Visible = True
Me.txtPassword.SetFocus
Exit Sub
End If
Me.lblWrongPass.Visible = False
If rs!EmployeeType_ID = 3 Then
Dim prop As Property
On Error GoTo SetProperty
Set prop = CurrentDb.CreateProperty("AllowBypassKey", dbBoolean, False)
CurrentDb.Properties.Append prop
SetProperty:
If MsgBox("Would you like to turn on the bypass key?", vbYesNo, "Allow Bypass") = vbYes Then
CurrentDb.Properties("AllowBypassKey") = True
Else
CurrentDb.Properties("AllowBypassKey") = False
End If
End If
DoCmd.OpenForm "frmPersonal_Information"
DoCmd.Close acForm, Me.Name
End Sub
I hope this is enough information for what I am trying to accomplish. If anymore information is needed please let me know. Thank you.
You do not need a login screen if the roles are tied to your Windows/Active Directory logins. You should make the assumption that the logged on user in Windows is legitimately using the workstation (and if that is not a safe assumption you need to look into your IT policies).
Access does not support roles and permissions. After accessing which user is currently logged on and getting their role from tblUser will have to:
Lock down the back end and especially access to the tables.
Lock down most of the user interface inherent to Access and only allow your front end forms to be used.
For each form of your front end manually make sure that whatever policies you wish to enforce are enforced using VBA.
Ultimately no matter what you do, somebody that knows how to use Access well can bypass any kind of lockdown you put in place. If you need to guard against more than casual curiosity and honest errors, you will need to combine Access with a much more robust DBMS like SQL server or MySQL.

VBA code that changes the background color of a form after update

I need some code that when a check box is unchecked it will change the background color of my form and return it back to its original color when checked. The code i have for the check box currently locks a combo box when a value is chosen. Example below
Private Sub AccessKeyNo_AfterUpdate()
If MsgBox("Do you want to assign Access Key " & Me.AccessKeyNo & "?", _
vbYesNo) = vbYes Then
Me.GuestAccessKeyID = Me.AccessKeyNo
If Me.Dirty Then Me.Dirty = False
Me.AccessKeyNo.Requery
Me.AccessKeyNo = Null
Me.MyCheckBox = IsNull(Me.GuestAccessKeyID)
End If
End Sub
In a standard module (not the form module -- the scope of the constants would be limited to form, thus you wouldn't be able to reuse them):
Public Const colorBlue_Cornflower = "15714765"
Public Const colorTan_Encarnacion = "11398133"
Now in the module for the form:
Dim colorThis as String, booWhatever as Boolean
booWhatever = Me.MyCheckBox ''Use of the variable can prevent problems
If booWhatever Then
colorThis = colorBlue_Cornflower
Else
colorThis = colorTan_Encarnacion
End If
subFrm.Form.Section(acDetail).BackColor = colorThis
subFrm.Form.Section(acHeader).BackColor = colorThis
subFrm.Form.Repaint