Thủ thuật Log-In, Phân quyền dùng VBA (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

lethanhnhan

Thành viên chính thức
Tham gia
27/5/07
Bài viết
76
Được thích
249
Chào các bạn,
Chắc có lẻ đây là câu hỏi mà các bạn thường gặp khi "trình độ lập trình VBA" của mình "có vẻ khả quan" !
_Làm thế nào để tôi phân quyền người dùng trên các worksheet?
_Làm thế nào để tôi phần quyền người dùng trên các form?
...và các câu hỏi gần như có cùng mục đích.

Tôi xin giới thiệu với các bạn "một giải pháp củ chuối" hy vọng các bạn hài lòng.

Để phân quyền tôi phải biết được tên người dùng.
Tôi muốn người dùng phải Log-In khi workbook mở ra, tôi dùng đọan code sau:
Mã:
Private Sub Workbook_Open()
    On Error GoTo Workbook_Open_Error
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = False
    End With
    frmLogIn.Show
    Call ActionB4CloseOpen("OPEN")
ErrorExit:
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = True
    End With
    Exit Sub

Workbook_Open_Error:
    If bCentralErrorHandler("ThisWorkbook", "Workbook_Open", , False) Then
        Stop
        Resume
    Else
        Resume ErrorExit
    End If
End Sub


Khi workbook được mở tôi hiện form bắt buộc người dùng log-in
Log-In.jpg


Tòan bộ code của form này như sau:
Mã:
Option Explicit
Dim iCount As Long
Private Sub cmdLogIn_Click()
    Dim sUserName As String, sUserSoSanh As String
    Dim sPass As String, sPassSoSanh As String
    Dim sRight As String
    Dim rngRange As Range
    On Error GoTo cmdLogIn_Click_Error
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = False
    End With
    If iCount > 3 Then
        MsgBox "You have enter more than " & iCount & " times!" & vbCrLf & _
               "Pls, contact your Administrator.", vbOKOnly, "Inf"
        End
    End If
    sUserName = txtTenTruyCap.Text
    sUserSoSanh = UserExist(sUserName)
    'Check the user name
    If Len(Trim(sUserSoSanh)) = 0 Then
        MsgBox "This user does not exist!", vbOKOnly, "Inf"
        txtTenTruyCap.Text = ""
        txtPass.Text = ""
        txtTenTruyCap.SetFocus
        iCount = iCount + 1
    End If

    sPass = txtPass.Text
    'Get Password
    sPassSoSanh = GetUserPassword(sUserName)
    'Get right of User
    sRight = GetUserRight(sUserName)
    If sPass = sPassSoSanh And Len(Trim(sUserSoSanh)) > 0 Then
        If Len(Trim(sRight)) > 0 Then
            MsgBox "Welcome to             " & vbCrLf & _
                   "STOCK COUNT HELPER TOOL " & vbCrLf & _
                   "Author: Le Van Duyet" & vbCrLf & _
                   "You have accessed with " & sRight & " right.", vbOKOnly, "Inf"
            Application.Range("UserName").Value = sUserSoSanh
        Else
            MsgBox "Welcome to             " & vbCrLf & _
                   "STOCK COUNT HELPER TOOL " & vbCrLf & _
                   "Author: Le Van Duyet" & vbCrLf & _
                   "You have accessed with " & "?" & " right.", vbOKOnly, "Inf"
            iCount = iCount + 1
            Application.Range("UserName").Value = sUserSoSanh
        End If
    ElseIf Len(Trim(sUserSoSanh)) > 0 Then
        MsgBox "Wrong Password !" & vbCrLf & _
               "Pls enter again.", vbOKOnly, "Inf"
        txtPass.Text = ""
        txtPass.SetFocus
        iCount = iCount + 1
        Exit Sub

    End If

    If sRight = "Admin" And Len(Trim(sUserSoSanh)) > 0 Then
        'Neu quyen la admin thi se mo cac sheet
        'de cap nhat du lieu
        Call ActionB4CloseOpen("ACCESSDATA")
        Me.Hide
    ElseIf Len(Trim(sUserSoSanh)) > 0 Then
        MsgBox "You can only enter data!", vbOKOnly, "Inf"
        Call ActionB4CloseOpen("OPEN")
        Me.Hide
    End If

ErrorExit:
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = True
    End With
    Exit Sub

cmdLogIn_Click_Error:
    If bCentralErrorHandler("frmLogIn", "cmdLogIn_Click", , False) Then
        Stop
        Resume
    Else
        Resume ErrorExit
    End If


End Sub

Private Sub cmdThoat_Click()
    End
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'Do not allow the user close the form by clicking the X button
    If CloseMode = vbFormControlMenu Then
        Cancel = True
    End If
End Sub


Lê Thanh Nhân
 
Khi người dùng nhập vào textbox txtTenTruyCap, dựa vào dữ liệu nhập vào này mà chúng ta lấy password để so sánh.
Đầu tiên chúng ta kiểm tra xem tên người dùng này có tồn tại hay không? Nếu hàm trả về chuổi rỗng thì người dùng không tồn tại (Coi chừng lỗi injection !).
Mã:
Public Function UserExist(UserName As String) As String
    Dim rs As ADODB.Recordset
    Dim strSQL As String

    On Error GoTo UserExist_Error
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = False
    End With
    If gcnAccess.state = ObjectStateEnum.adStateClosed Then
        Call ConnectToDatabase
    End If
    'Then get the data
    If gcnAccess.state = ObjectStateEnum.adStateClosed Then
        gcnAccess.Open
        strSQL = "SELECT User " & _
                 "FROM tbUsers " & _
                 "WHERE User = '" & UserName & "';"
        Set rs = New ADODB.Recordset
        rs.CursorType = adOpenStatic
        rs.Open strSQL, gcnAccess

        If rs.RecordCount = 0 Then
            UserExist = ""
        Else
            UserExist = rs.Fields(0)
        End If
    End If
ErrorExit:
    If gcnAccess.state = ObjectStateEnum.adStateOpen Then
        gcnAccess.Close
    End If
    If IsNull(rs) Then
        If rs.state = adStateOpen Then
            rs.Close
            Set rs = Nothing
        End If
    End If
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = True
    End With
    Exit Function
UserExist_Error:
    If bCentralErrorHandler("MainMod", "UserExist", , False) Then
        Stop
        Resume
    Else
        Resume ErrorExit
    End If
End Function
Chúng ta dựa vào câu truy vấn:
Mã:
strSQL = "SELECT User " & _
                 "FROM tbUsers " & _
                 "WHERE User = '" & UserName & "';"
Nếu tên người dùng tồn tại thì với câu truy vấn này sẽ trả về tên người dùng.
Sau đó chúng ta sẽ xem quyền của người dùng.
Mã:
Public Function GetUserPassword(UserName As String) As String
    Dim rs As ADODB.Recordset
    Dim strSQL As String
    On Error GoTo GetUserPassword_Error
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = False
    End With
    If gcnAccess.state = ObjectStateEnum.adStateClosed Then
        Call ConnectToDatabase
    End If
    'Then get the data
    If gcnAccess.state = ObjectStateEnum.adStateClosed Then
        gcnAccess.Open
        strSQL = "SELECT Pass " & _
                 "FROM tbUsers " & _
                 "WHERE User = '" & UserName & "';"
        Set rs = New ADODB.Recordset
        rs.CursorType = adOpenStatic
        rs.Open strSQL, gcnAccess

        If rs.RecordCount = 0 Then
            GetUserPassword = ""
        Else
            GetUserPassword = rs.Fields(0)
        End If
    End If

ErrorExit:
    If gcnAccess.state = ObjectStateEnum.adStateOpen Then
        gcnAccess.Close
        bConnected = False
    End If
    If IsNull(rs) Then
        If rs.state = adStateOpen Then
            rs.Close
            Set rs = Nothing
        End If
    End If
    With Application
        .Calculation = xlCalculationManual
        .ScreenUpdating = True
    End With
    Exit Function

GetUserPassword_Error:

    If bCentralErrorHandler("MainModule", "GetUserPassword", , False) Then
        Stop
        Resume
    Else
        Resume ErrorExit
    End If
End Function

Tương tự trên hàm này sẽ trả về chuỗi phân quyền của người dùng. Ở đây trong bảng tbUsers tôi phân quyền là Admin và NormalUser.
Ngòai ra dựa vào ý tửơng này các bạn có thể cho biết với quyền Admin họăc NormalUser thì sẽ được truy cập đến các form nào, các thủ tục nào,...

Và cuối cùng nếu tên người dùng tồn tại ta sẽ ghi vào
Mã:
Application.Range("UserName").Value = sUserSoSanh
Nằm trong một worksheet mà người dùng bình thừơng không có quyền truy cập. Với việc lưu lại tên người dùng này, chúng ta sẽ lưu tên người dùng cùng với những thao tác với cơ sở dữ liệu như: xóa, sửa...

Ngòai ra chúng ta còn dựa vào biến đếm
Dim iCount As Long
Khai báo vào đầu module để đếm số lần nhập sai của người dùng. Nếu lớn hơn 3 lần thì..."bye bye và thóat".

Lê Thanh Nhân
 
Tương ứng với mỗi hành động mà ta cho hiện worksheet nào.
Sau đây là một "thủ tục củ chuối" nữa nhằm hiện, ẩn các worksheet tùy thuộc vào hành động của người dùng.
Ở đây tôi chia làm 3 hành động: CLOSE, OPEN và ACCESSDATA. Các bạn có thể phát triển thêm.
Mã:
Sub ActionB4CloseOpen(sCloseOpen As String)
    Dim sLeft3 As String, sWsName As String
    Dim i As Integer, WsCount As Integer
    Dim sWsVisible As String, sWsMenu As String
    Dim sWsAccessData As String, sWsAccessData1 As String
On Error GoTo ActionB4CloseOpen_Error
   With Application
      .Calculation = xlCalculationManual
      .ScreenUpdating = False
   End With
    On Error Resume Next
    sWsVisible = "HID_FIRST": sWsMenu = "SHO_MENU"
    sWsAccessData = "HID_DATA": sWsAccessData1 = "HID_SAP_CODE"
    WsCount = Application.ThisWorkbook.Worksheets.Count
    With Application.ThisWorkbook
        If sCloseOpen = "CLOSE" Then
            .Worksheets(sWsVisible).Visible = xlSheetVisible
            For i = 1 To WsCount
                sWsName = .Worksheets(i).Name
                If sWsName <> sWsVisible Then
                    .Worksheets(i).Visible = xlSheetVeryHidden
                End If
            Next i
        ElseIf sCloseOpen = "OPEN" Then
            For i = 1 To WsCount
                sWsName = .Worksheets(i).Name
                sLeft3 = Mid(sWsName, 1, 3)
                If sLeft3 = "SHO" Or sLeft3 = "SAP" Then
                    .Worksheets(i).Visible = xlSheetVisible
                Else
                    .Worksheets(i).Visible = xlSheetVeryHidden
                End If
            Next i
            .Worksheets(sWsMenu).Activate
        ElseIf sCloseOpen = "ACCESSDATA" Then
            .Worksheets(sWsAccessData).Visible = xlSheetVisible
            For i = 1 To WsCount
                sWsName = .Worksheets(i).Name
                If sWsName <> sWsVisible Then
                    .Worksheets(i).Visible = xlSheetVeryHidden
                End If
            Next i
            .Worksheets(sWsAccessData1).Visible = xlSheetVisible
        End If

    End With

ErrorExit:
   With Application
      .Calculation = xlCalculationManual
      .ScreenUpdating = True
   End With
   Exit Sub
ActionB4CloseOpen_Error:
If bCentralErrorHandler("MainMod", "ActionB4CloseOpen", , False) Then
     Stop
     Resume
Else
     Resume ErrorExit
End If
End Sub

Lê Thanh Nhân
 
Anh Duyệt!(Có lộn người không nhỉ?)
Việc phân quyền trong EX bị giới hạn trong khoảng bao nhiêu người vậy anh??
 
NEO đã viết:
Anh Duyệt!
Việc phân quyền trong EX bị giới hạn trong khoảng bao nhiêu người vậy anh??
Như trên tôi đã giới thiệu. Nếu bạn đọc kỹ đoạn mã, bạn sẽ thấy ta phân quyền khi người dùng log-in mở file Excel. Và việc phân quyền này là trên cơ sở dữ liệu Access. Do đó theo tôi nghĩ là nó sẽ "OK" cho doanh nghiệp vừa và nhỏ.

Lê Văn Duyệt
 
Em bị lỗi này rồi, anh chỉ em cách khai báo nha
"User-difined typed not defined"
Dim rs As ADODB.Recordset
 
Lần chỉnh sửa cuối:
bigbigworld đã viết:
Em bị lỗi này rồi, anh chỉ em cách khai báo nha
"User-difined typed not defined"
Dim rs As ADODB.Recordset
Trước khi sử dụng phải khai báo
set rs= New ADODB.Recordset

Lê Thanh Nhân
 
lethanhnhan đã viết:
Trước khi sử dụng phải khai báo
set rs= New ADODB.Recordset

Lê Thanh Nhân

bạn có "lethanhnhan" này bạn có thể nào giởi fiel đó lên cho mình xem không zậy chứ mình không biết " xác định các textbox và CommandButton1 đâu khó lắm, bạn nào làm cái này xong cho mình file đó đi! thank:=\+ )(&&@@ --=-- }}}}}
 
ongtrungducmx25 đã viết:
bạn "lethanhnhan" này bạn có thể nào giởi fiel đó lên cho mình xem không zậy chứ mình không biết " xác định các textbox và CommandButton1 đâu khó lắm, bạn nào làm cái này xong cho mình file đó đi! thank:=\+ )(&&@@ --=-- }}}}}

Chào bạn ongtrungducmx25,
Như trên tôi đã giới thiệu, đó là một thủ thuật nho nhỏ nhằm phân quyền trong ứng dụng của bạn.

Ví dụ dựa trên tên người dùng nhập vào chúng ta có thể lấy về chuổi dữ liệu phân quyền.
Ví dụ ta có các trường trong bảng :

tb_user1.jpg


_User: là trường để lưu trữ tên truy cập.
_Pass: để lưu trữ Password của người dùng.
_Right: chuổi phân quyền.
Như trên tôi đã giới thiệu bạn phải thiết kế form để cho người dùng đăng nhập vào mỗi khi workbook_Open, hoặc bạn dùng thủ tục Auto_Open.
Sau khi người dùng nhập vào bạn sẽ kiểm tra:
_Tên người dùng có tồn tại hay không?
_Nếu tên người dùng đúng thì mới kiểm tra Password có đúng hay không?
_Sau đó tiếp tục để lấy về chuỗi phân quyền. Ví dụ: chuổi phân quyền như sau: frmEdit, frmMain
Khi phân quyền dùng form thì chúng ta sẽ dựa vào chuổi này để cho hiện form hay không bằng việc dùng hàm instr() để kiểm tra xem tên form có trong chuỗi này hay không.
Còn việc kết nối với CSDL để lấy về chuỗi này thì tôi đã giới thiệu ở trên.

File đính kèm là file của form log-in và form thay đổi Password. Bạn tham khảo nha.

Lê Văn Duyệt
 

File đính kèm

bạn "Lê Văn Duyệt" nè mình mở file của bạn hoài mà không được nó báo lỗi gì mà không mở được bạn chỉ mình mở đi nhé!có video cho bạn xem nhé
 

File đính kèm

Gởi ongtrungducmx25,
Bạn ơi, đó là hai file form *.frm. Bạn vào VBA, chọn File/Import File và chọn đường dẫn đến file tôi gởi cho bạn. Chương trình sẽ cập nhật hai form vào.
Lúc đó bạn có thể xem mã của chương trình.
Bạn cũng có thể làm như sau: Extract ra một thư mục, sau đó bạn chọn Open with và bạn chọn Note Pad để xem code.

Chúc bạn thành công.

Lê Văn Duyệt
 
mình làm được cái này chứ,nhưng hai form của bạn bị lỗi gì rồi đó mình mở thì nó thông báo lỗi nhiều lắm bạn xem lại file của mình đi nhé! hay là bạn chép vào 2 file.from của bạn vào excel luôn nhé để mình tham khảo?Thank
 
Lần chỉnh sửa cuối:
ongtrungducmx25 đã viết:
mình làm được cái này chứ,nhưng hai form của bạn bị lỗi gì rồi đó mình mở thì nó thông báo lỗi nhiều lắm bạn xem lại file của mình đi nhé! hay là bạn chép vào 2 file.from của bạn vào excel luôn nhé để mình tham khảo?Thank
Vấn đề là bạn phải biết thông báo lỗi gì?
Tôi chắc chắn đó là việc bạn phải reference đến các *.ocx.

Lê Văn Duyệt
 
nhưng vấn đề ở chỗ là ko biết đó là file ocx gì. Mong được các bạn giúp đỡ
 
Bác ongtrungducmx25 Tại sao tôi không Dowload được File của Bác ? Hay bác đã thay đường dẫn ?
vbmenu_register("postmenu_24990", true);
 
bạn muốn lấy file gì nói rõ hơn nhé! đường dẫn nào chưa hiểu ý bạn nhé
 
Mô hình Phân quyền

Em thường thiết kế phân quyền trong ứng dụng như thế này:

+ Trong một doanh nghiệp thì có các bộ phần: Giám đốc, Kế toán, Bán hàng, Marketing... Một table chứa tên các bộ phận này gọi là tbGroup.
+ Trong mỗi Group lại có các thành viên (nhân viên), một table chứa các thành viên gọi là tbUser.
+ Một table liệt kê tất cả các chức năng sử dụng trong ứng dụng gọi là tbFunction.
+ Một table thể hiện nội dung phân quyền gọi là tbRight

Việc phân quyền là phân cho nhóm chứ không phân cho User, khi phân cho nhóm "Bán hàng" thực hiện {"Cáo cáo 1"; "Báo cáo 2"} thì tất cả các thành viên trong nhóm này có quyền như nhau.

Mô hình quan hệ giữa các table như sau:
RightRls.jpg

Khi thiết kế màn hình Login (Đăng nhập), để kiểm tra thông tin user hợp lệ thì dùng câu lệnh truy vấn:

SELECT tbGroup.Level, tbRight.*
FROM (tbGroup INNER JOIN tbRight ON tbGroup.GroupID=tbRight.GroupID) INNER JOIN tbUser ON tbGroup.GroupID=tbUser.GroupID
WHERE (((tbUser.UserID)='tuan') AND ((tbUser.Password)='123'));

Nếu thỏa mãn điều kiện, nội dung trong Recordset sẽ như dưới đây:
RightLogin.jpg
 

File đính kèm

Tuân nhảy sang Data base rùi ah? :)

Về phân quyền mình hay dùng một mảng bit hay chuỗi 010101 để chia quyền có hay không. thông thường nếu lưu quyền vào database thường hay dễ bị vọc. Sếp là người quản lý nhưng lại ít am hiểu máy tính ==> mã hóa 128 bit là ăn chắc, sau đó cắt lấy 8 ký tự đầu để so sánh ==> quyền

Kiểu trên rất tùy biến và có thể bổ sung khá tiện.
Giải thuật mã 128 thì tìm nhé "SHA128".

@Tuanvuni: Năm mới nâng cấp trang bluesoft.net đi.
Mình hỗ trợ host và thiết kế cho. có gì PM nhé.
 
+ Trong một doanh nghiệp thì có các bộ phần: Giám đốc, Kế toán, Bán hàng, Marketing... Một table chứa tên các bộ phận này gọi là tbGroup.
+ Trong mỗi Group lại có các thành viên (nhân viên), một table chứa các thành viên gọi là tbUser.
+ Một table liệt kê tất cả các chức năng sử dụng trong ứng dụng gọi là tbFunction.
+ Một table thể hiện nội dung phân quyền gọi là tbRight
Sorry nếu mình không đúng, nhưng nếu là mình thì mình có 1 mô hình khác dù mình chưa làm lần nào:
1. 2 table Function và Right mình gom làm 1 và dàn hàng ngang, mỗi function là 1 field, loại dữ liệu là Yes/No. Như vậy tiện cho việc add user mới trên form: chỉ việc click đánh dấu check cho mỗi function có Right.
Còn nếu hàng dọc thì có thể sai hoặc sót function, đồng thời phải nhập liệu vừa cho FunctionID vừa nhập liệu cho Allowance.
2. Table Group là liệt kê các group: kế toán, bán hàng, tiếp thị; còn level sẽ là 1 bảng khác liệt kê mức độ truy cập của user.

Mô hình như sau:

RelationPQ.jpg


Form nhập liệu ngoài ra có thể tùy biến như sau: Nếu Group là Acc thì chỉ hiện 3 field AccFunc của bộ phận Kế toán, nếu Group là Sale thì chỉ hiện 3 field SaleFunc của bộ phận Sale, tương tự cho bộ phận Tiếp thị:

Sale.jpg



Acc.jpg


Đồng thời có thể mặc định 1 số field có giá trị True, chẳng hạn như nếu Group là Admin thì tất cả lập tức được gán giá trị True:

Adm.jpg


khi test user đăng nhập thành công ta sẽ có:

TestUser.jpg


File mình đang làm, nếu TuanVNUNI thấy hứng thú, mình sẽ gởi lên.
 
Lần chỉnh sửa cuối:
Longnh đã viết:
Về phân quyền mình hay dùng một mảng bit hay chuỗi 010101 để chia quyền có hay không. thông thường nếu lưu quyền vào database thường hay dễ bị vọc. Sếp là người quản lý nhưng lại ít am hiểu máy tính ==> mã hóa 128 bit là ăn chắc, sau đó cắt lấy 8 ký tự đầu để so sánh ==> quyền

Vụ này nghe hấp dẫn đây. Bác có thể chia sẻ anh em chút demo không?

@Tuanvuni: Năm mới nâng cấp trang bluesoft.net đi.
Mình hỗ trợ host và thiết kế cho. có gì PM nhé.

Cảm ơn bác trước! Vụ này năm mới sẽ phải nhờ bác giúp hai tay đấy!


ptm0412 đã viết:
File mình đang làm, nếu TuanVNUNI thấy hứng thú, mình sẽ gởi lên.

Ngày trước em cũng nghĩ làm theo cách của bác nhưng em nghĩ các chức năng sẽ có rất nhiều (>255), nếu bố trí theo cột sẽ mất nhiều, em chưa thử không biết giới hạn các cột trong Access là bao nhiêu? Khi nào bác làm file demo xong thì gửi lên dây anh em cùng học hỏi thêm.
 
TuanVNUNI đã viết:
Ngày trước em cũng nghĩ làm theo cách của bác nhưng em nghĩ các chức năng sẽ có rất nhiều (>255), nếu bố trí theo cột sẽ mất nhiều,

Nhiều hơn mình tưởng tượng. nhưng mình nghĩ cũng sẽ có cách. Sơ bộ thì ý tưởng thế này:

1. level như cũ và gồm tối đa 5 level bình quân cho 4 bộ phận = 20. Thí dụ Bộ phận Kế toán gồm các level: KT trưởng, phó, KT tổng hợp,(nhiều khi 3 level này là 1), 5 NormalUser 1, 2, 3, 4, 5. Các Normal User khác nhau ở phân công chứ không khác ở chức vụ. Sale ít hơn, Tiếp thị còn ít hơn nữa.
2. Mỗi level gồm tối đa 10 chức năng con thí dụ Kế toán tiền mặt: Form thu chi, báo cáo Quỹ, báo cáo nhanh, sổ cái tiền mặt, Report phiếu thu chi, In Phiếu thu chi. Cái này mình gom lại trên 1 form của Kế toán thu chi. nghĩa là khi level là NormalUserCash, thì chỉ mở được 1 form, từ form đó làm được đủ các việc cần thiết của Cash như mở form con nhập liệu, lập báo cáo, in báo cáo.
Tương tự KT kho, level là NormalUserInventory chỉ mở được 1 form kho, trên form đó sẽ có đủ nhập liệu nhập kho xuất kho, in phiếu nhập xuất, báo cáo tồn kho chi tiết và tổng hợp.
KT kho không mở được form của KT tiền mặt thì đương nhiên sẽ không mở được các thứ khác nằm trong form đó.
Mỗi nhân viên đực mở form nào, KTTH được phép mở mấy form, Kế toán phó được phép mở mấy form, xác định bởi các AccFunc1, 2, 3 . . .

3. Các bộ phận khác cũng tương tự như vậy.

Tóm lại là do cơ cấu tổ chức chung, phối hợp giữa cấu trúc Database, cấu trúc tổ chức form, cấu trúc tổ chức Report.

Khi nào bác làm file demo xong thì gửi lên dây anh em cùng học hỏi thêm
Chắc mình không dám làm nhiều hơn vì chưa làm bao giờ. Chỉ có file của bài 19, nhưng sợ các cao thủ cười cho. Vì

Ngày trước em cũng nghĩ làm theo cách của bác
Bạn đã nghĩ thì cũng đã biết làm, mình chen vào đây lại là múa rìu qua mắt thợ nữa. Hìii, thôi cũng không sợ xấu, đưa lên luôn.
 

File đính kèm

Lần chỉnh sửa cuối:
To:Ptm0412,

Mình làm như thế này các bạn có thấy ổn không?
_ TbRight của mình chỉ có một trường chứa các chuổi phân quyền cho các chức năng. Ví dụ: fnUpdate, fnDelete, fnEdit,...
Như vậy sRight = "fnUpdate, fnDelete, fnEdit,..."
Chuỗi này được mã hóa và đưa vào bảng dữ liệu.
Mỗi khi mình kiểm tra sẽ được giải mã và kiểm tra. Nếu với từng người dùng chuỗi đại diện cho chức năng mà tồn tại trong sRight thì coi như là người này được thực hiện thao tác này.
_ Tương tự như vậy: mình cũng có trường để phân quyền đến từng form.
(Đối với việc này mình muốn đưa ra một trường khác cho dễ đó mà)

Lê Văn Duyệt
 
Gửi anh ptm0412
Theo cách của anh em thấy không ổn.
+ Table "GroupTb", ngoài cho biết tên thì không thể hiện tác dụng gì?
+ Table "RightTb" thể hiện sự phân quyền theo từng nhân viên và các chức năng theo cột. Có ba điểm không ổn:
1- Với những nhân viên có chung một quyền thì ta vẫn phải tạo quyền cho từng người một mà lẽ ra chỉ cần phân quyền cho một nhóm là xong, dù trong nhóm có hàng trăm người;
2- Các chức năng thể hiện theo cột, khó mà thể hiện được một cái tên rõ ràng Func1, Func2,...ta không biết nó làm những cái gì (vì không có ghi chú), tên cột chỉ là để ghi mã ngắn gọn, nếu muốn ghi rõ thì độ dài chuỗi chỉ tối đa là 64 ký tự nhưng khi lập trình sẽ rất khó khăn. Các chức năng trong một ứng dụng có hàng trăm nếu chỉ có tên Func1, Func2 chắc chắn chính người lập trình cũng không thể nhớ nổi, điều nữa là không chỉ định được các chức năng thuộc module nào? Khi lập trình, các chức năng thường phải chia theo module: Nhân sự, Tiền lương, Bán hàng, Kế toán,....Điều nữa anh sẽ thiết kế form phân quyền cho người dùng như thế nào?
3- Lập trình rất khó khăn. Giả sử có 100 chức năng thì trong lập trình, để gán chức năng vào CSDL anh phải làm như thế này:
Rs.Fields("Func1").Value=True
Rs.Fields("Func2").Value=False
...
Rs.Fields("Func100").Value=False

Những phân tích ở trên là do ngày trước em đã làm một PM bán hàng và đã thiết kế phần phân quyền như anh đã làm và về sau phải làm lại toàn bộ phần phân quyền. Nếu với mô hình anh đưa ra mà thành công thì cũng rất đáng để học hỏi đó. Nếu có thể anh có thể làm demo được không?

levanduyet đã viết:
Mình làm như thế này các bạn có thấy ổn không?
_ TbRight của mình chỉ có một trường chứa các chuổi phân quyền cho các chức năng. Ví dụ: fnUpdate, fnDelete, fnEdit,...
Như vậy sRight = "fnUpdate, fnDelete, fnEdit,..."
Chuỗi này được mã hóa và đưa vào bảng dữ liệu.
Mỗi khi mình kiểm tra sẽ được giải mã và kiểm tra. Nếu với từng người dùng chuỗi đại diện cho chức năng mà tồn tại trong sRight thì coi như là người này được thực hiện thao tác này.
_ Tương tự như vậy: mình cũng có trường để phân quyền đến từng form.
(Đối với việc này mình muốn đưa ra một trường khác cho dễ đó mà)

Có thể em chưa hiểu hết ý đồ của anh nhưng em vẫn thấy không ổn?
TbRight chỉ có một cột là tự mình làm khó chính mình rồi, anh sẽ phải diễn tả sự phân quyền theo chuỗi, trong chuỗi đó còn phải thể hiện quyền cho từng User nữa...Anh phải viết một loạt các hàm để nhận biết các đoạn phân quền mà không dễ dàng gì.

Môt hình phân quyền mà bài trước em đưa ra là đã thiết kế thành công với các ứng dụng em đã làm.

Tạo Group và User:
User.jpg


Phân quyền:
Rights.jpg
 
Hic, mình chưa làm vụ này lần nào, cái mình đưa ra chỉ là 1 ý tưởng. Cụ thể là thế này:

1.- Khi mở PM lên sẽ là 1 form khởi động, tạm gọi là Main.
- Từ form Main này sẽ có những commandButton gọi ra những form chức năng con cấp 1 tạm gọi là Sub1st.
- Nếu group là Accounting thì cmdAccBtton.Enable = True, các button khác sẽ có Enable = False, tạm hiểu là nhân viên Kế toán chỉ vào đựợc Sub1stAccForm mà không vào được Sub1stSaleForm.

2. Đối với từng bộ phận: thí dụ bộ phận KT:
- Trên Sub1stAccForm sẽ có những CmdButton để mở những form con cấp 2 tạm gọi là Sub2nd.
- Nếu Level = NormalUserCash, ta sẽ cho cmdCashButton.Enable = True, các CmdButton khác có Enable= False, nghĩa là nhân viên KT tiền mặt chỉ vào được Sub2ndCashForm có phần hành của mình mà không vào được Sub2ndInventoryForm của phần hành kho hoặc các phần hành khác.
- Các nhân viên KT tổng hợp có level = General sẽ có thể mở nhiều Form liên quan đến phần vịệc của mình, thì với Level của nhân viên đó, sẽ được Enable = True cho 2, 3 hoặc 4 CmdButton theo phân công.
- Trưởng phòng KT đượng nhiên được quyền vào tất cả các Sub2ndForm của bộ phận KT có trong Sub1stAccForm , mọi Command button đều có Enable = True

3. Trên các Sub2ndForm sẽ có các CmdButton chức năng nữa như: nhập liệu, sửa chữa dữ liệu, xem báo cáo loại A, báo cáo loại B. . . , in báo cáo X, báo cáo Y của Kho này, công trình kia.
- Chính các AccFunction quy định cho biết trong 3 NormalUser cùng level, ai vào phần nào, ai được vào cả 3 phần, ai được in phiếu thu chi, ai được in sổ quỹ. . . tất cả là gán giá trị cho Property Enable = true hay False

4. Các AccFunction và SaleFUnction là tuỳ biến cho các bộ phận do cơ cấu tổ chức của các bộ phận là khác nhau: Thí dụ bộ phận Sale phân công nhân viên theo khu vực thị trường, mỗi nhân viên phụ trách thí dụ 1 vùng miền thì có quyền truy cập dữ liệu trong khu vực do mình phụ trách. Nếu dữ liệu là chung cho cả phòng KD, thì căn cứ vào SaleFunction, dùng Query lọc dữ liệu theo vùng thị trường đó, hoặc lọc theo UserID nếu đặt trường USerID vào table dữ liệu chung. Như vậy không động chạm đến dữ liệu của người khác.

Anh Duyet đã viết:
_ TbRight của mình chỉ có một trường chứa các chuổi phân quyền cho các chức năng. Ví dụ: fnUpdate, fnDelete, fnEdit,...
Như vậy sRight = "fnUpdate, fnDelete, fnEdit,..."
Chuỗi này được mã hóa và đưa vào bảng dữ liệu.
Mỗi khi mình kiểm tra sẽ được giải mã và kiểm tra. Nếu với từng người dùng chuỗi đại diện cho chức năng mà tồn tại trong sRight thì coi như là người này được thực hiện thao tác này.
Mình thấy chuỗi phân quyền gồm nhiều chức năng mà lại nằm trong 1 field sẽ khó:
- Khi tạo User mới hoặc phân công lại nhân sự, việc gõ lại chuỗi phân quyền đòi hỏi chính xác cao, không được gõ sai dù 1 ký tự
- Khi tìm các chức năng của 1 User phải phân tích chuỗi để tách ra 3 hoặc 4 chuỗi con, mỗi chuỗi con mới là căn cứ để xác định quyền. Tách chuỗi không phải là khó, mà là khổ, tự làm khổ mình.

Vài ý tưởng thô thiển không biết có thích hợp không, vì mình chỉ mới chèo trong ao cạn nên chưa lường hết mọi vấn đề ngoài biển lớn.
 
Lần chỉnh sửa cuối:
Bổ sung:
Nếu phần mềm không dùng Startup Form mà dùng menu, thì cũng đơn giản là hiện menu này, không hiện menu kia, Enable dòng menu này, Disable dòng Menu kia.
Còn các trường Group, Level, SubFunction chẳng qua là biện pháp chia để trị: 200 = 4 x 5 x 10
Không biết có đúng hoặc có phù hợp không nữa.
 
Lần chỉnh sửa cuối:
To: TuanVNUNI,

TuanVNUNI đã viết:
TbRight chỉ có một cột là tự mình làm khó chính mình rồi
Em hiểu sai ý anh rồi. Dĩ nhiên trong bảng này còn có UserID.

TuanVNUNI đã viết:
Anh phải viết một loạt các hàm để nhận biết các đoạn phân quền mà không dễ dàng gì
Chỉ cần dùng hàm tìm chuổi này trong chuổi kia thôi mà!
ptm0412 đã viết:
- Khi tạo User mới hoặc phân công lại nhân sự, việc gõ lại chuỗi phân quyền đòi hỏi chính xác cao, không được gõ sai dù 1 ký tự
Ai lại đi làm thế. Khi phân quyền, cũng tương tự như TuanVNUNI, chọn CheckBox => Xây dựng chuổi phân quyền mà!

Lê Văn Duyệt
 
Sorry anh Duyệt. Mình chưa thấy được toàn cục, do chỉ đọc được 1 đoạn ngắn quá không suy rộng được thêm. Ừ phải, ai lại đi làm thế, tại mình hiểu sai thôi.
Phải đọc kỹ lại từ đầu topic thôi.
 
TuanVNUNI đã viết:
Việc phân quyền là phân cho nhóm chứ không phân cho User, khi phân cho nhóm "Bán hàng" thực hiện {"Cáo cáo 1"; "Báo cáo 2"} thì tất cả các thành viên trong nhóm này có quyền như nhau.
Vậy tuân cho anh hỏi, như vậy sẽ không linh động. Vậy nếu chúng ta muốn phân quyền kết hợp giữa Group và User thì ta nên thiết kế lại mô hình quan hệ giữa các tables như thế nào?

Xin các bạn khác, đã từng có kinh nghiệm về cái vụ này cho ý kiến.

LTN
 
lethanhnhan đã viết:
Vậy tuân cho anh hỏi, như vậy sẽ không linh động. Vậy nếu chúng ta muốn phân quyền kết hợp giữa Group và User thì ta nên thiết kế lại mô hình quan hệ giữa các tables như thế nào?

Xin các bạn khác, đã từng có kinh nghiệm về cái vụ này cho ý kiến.

LTN

Ý anh là những người trong một Group lại có người có quyền cao hơn hoặc thấp hơn?
Trong tblUser em đã thiết kế một trường Level, trường này có giá trị 1,2,3,...Trong tblFunction, thiết kế thêm một trường Level để gán giá trị 1,2,..tuỳ vào tính quản trị của mỗi chức năng. Như vậy ta co một cơ sở quan hệ ràng buộc giữa các table
(tblUser.GroupID= tblGroup.GroupID And tblUser.Level=tblFunction.Level)
Theo cách thiết kế trên, anh hoàn toàn có thể làm được tất cả.
 
TuanVNUNI đã viết:
Ý anh là những người trong một Group lại có người có quyền cao hơn hoặc thấp hơn?
Vì theo anh thấy trong SAP phân quyền cho mỗi chức năng.
Ví dụ:
_ Anh vẫn có thể vào các chức năng, nhưng trước khi thực hiện hệ thống sẽ kiểm tra việc phân quyền. Em xem hình sau:
Mỗi chức năng để thực hiện người ta sẽ dùng T-Code (giống như shortcut vậy)
SAP.jpg


Lê Văn Duyệt
 
Theo mô hình của em cũng là phân cho từng chức năng đấy.

(*) Khi phân quyền cho một nhóm (Group) sẽ thực hiện như sau:
+ Load tất cả các chức năng từ tblFunction ra form giao diện người dùng (UI)
Các chức năng được liệt kê chi tiết: Phiếu Thu: Tạo; Sửa;Xoá, Phieu Chi:.....
+ Thực hiện việc tick chọn các chức năng cho phép chạy với nhóm
+ Lưu toàn bộ chức năng được tick chọn vào một table có tên tblRight

(*) Khi người dùng thực hiên "Đăng nhập", hệ thống sẽ thực hiện:
+ Lấy toàn bộ thông tin từ các table có quan hệ của UserID đã đăng nhập thành công. Các thông tin được lưu trong một Query/View có tên qryUserRight - Kết quả của một truy vấn móc nối giữa các table có quan về Group,User,Right,Function.
+ Khi người dùng thực hiện một chức năng, chương trình sẽ tìm mã chức năng đó trong trong table qryUserRight, kiểm tra xem có và được tick không?
 
- Sau khi gán 1 User vào 1 Group thì ban đầu các User đó đều có quyền của Group đó.
- Tuy nhiên, sau khi assign vào Group rồi thì vẫn có thể thay đổi lại quyền của User đó (hạn chế bớt đi)

Anh Duyệt sướng thật đấy, được làm việc với SAP.
 
Xin chào các anh. Các Anh cho em hỏi với, để giới hạn thời gian sử dụng (hoặc số lần chạy) của chương trình (sau khi đã cho username và password) thì tạo code như thế nào ạ ?
 
hix, đọc xong mà vẫn không hiểu gì cả.Sao excel lại dính đến access vậy? Không biết có bài viết nào hường dẫn 1 cách cơ bản mối liên kết database giữa access và excel và cách truy xuất qua lại là như thế nào không?
Anh em nào có xin vui lòng share link nhé.
Xin chân thành cám ơn.
 
Vấn đề là bạn phải biết thông báo lỗi gì?
Tôi chắc chắn đó là việc bạn phải reference đến các *.ocx.

Lê Văn Duyệt
thật sự là khi nhìn vào form từ notepad mới thấy được bác duyệt không đưa mọi người hàm convert VNI to Unicode, được dùng trong msgbox
File của bác mình mở mãi mà không được, import cứ báo lỗi.
Bác có thể cho mọi người luôn bằng xls được kô ạh, import chắc kô mất đến 1p của bác đâu nhỉ.
Thanks bác nhá
 
thật sự là khi nhìn vào form từ notepad mới thấy được bác duyệt không đưa mọi người hàm convert VNI to Unicode, được dùng trong msgbox
File của bác mình mở mãi mà không được, import cứ báo lỗi.
Cái này đã có trên diễn đàn. Bạn vui lòng tìm kiếm bài của A.Tuân.

Lê Văn Duyệt
 
Vba

Thật phức tạp! sao các ông khong phân quyền người dùng theo kiểu mã khoá đi
Hoạc thiết kế 1 trang Web sau do cho người dùng đăng ký qua trang Web đó.
có rất nhiều cách hay hơn nữa.
 
Thật phức tạp! sao các ông khong phân quyền người dùng theo kiểu mã khoá đi
Hoạc thiết kế 1 trang Web sau do cho người dùng đăng ký qua trang Web đó.
có rất nhiều cách hay hơn nữa.

ông nói gì ông hiểu không vậy
ông biết người ta đang nói tới vấn đề gì không?
 
Xin chào các anh. Các Anh cho em hỏi với, để giới hạn thời gian sử dụng (hoặc số lần chạy) của chương trình (sau khi đã cho username và password) thì tạo code như thế nào ạ ?
Lúc đăng nhập , kiểm tra user & pass , đúng ghi nhận số lần đăng nhập n (n=n+1); thời gian = start time = giờ trên win (hoặc tự tạo bộ đếm)
Lúc thoát chỉ ghi nhân end time, spend time = end time-star time ; s=s+s'
check n, if true then exit
check s, if true then exit
 
Đề nghị chúng ta khi trao đổi trên diễn đàn đề nghị sử dụng từ xưng hô cho hợp lý để khỏi phiền người khác. Rất mong các bạn chú ý vấn đề này
 
Chào bạn Lê Văn Duyệt,

tôi có một file access được split thành 2 phần: database và Client nhập liệu, xem báo cáo. đối với phần client thì cài trên nhiều máy tính khác nhau để kết nối vào database. trong file client thi tôi dùng chức năng phân quyền của access để tạo group, user... cho người dùng --> tôi được file workgroup tương ứng. tuy nhiên khi dùng mở file client trên một máy tính mà mình chưa join vào file workgroup kia thì access sẽ chọn file mặc định trong máy tính đó. dẫn đến hậu quả là file client vẫn có thể mở full mà không có ngăn cản nào. Anh có thể giúp tôi khắc phục tình trạng này được không?

Trân trọng cám ơn

Hùng
 

Bài viết mới nhất

Back
Top Bottom