Вхождение юзера в группу, разворачивание групп

E

EHT

Мля. Действительно: The Lotus Sandbox was closed to all new submissions in 2007. Downloads of previous submissions were still available as an archived resource following that closure, but effective September 2010, downloads from the Lotus Sandbox are no longer available.

Чем она им помешала? закапывают лотус собственными руками :) - яркий пример победы маркетинга над здравым смыслом.

запасливые "буржуи" припрятали песочницу онлайн ;)
сохранить себе в зипе ;) аххтунг 1,6Гб!!!
 
O

Omh

rinsk
Допилил твою процедуру под свой вкус.

Максимально уменьшил число входных параметров (мне маск не нжен был, поэтому его тоже выпилил)
Постарался избавиться от вариантов
Добавил возможность кеширования групп (мне надо будет запускать эту ф-ию в цикле)
Оптимизнул код в цикле по зачитыванию аддресс-буков.

Visual Basic:
Function GetUserGroup(UserNameText As String, UseCache As Boolean) As Variant
    On Error Goto ErrH
    Const SEP = "~"
    Static UserGroupsList List As String
    Static cnt As Integer
    Dim rv As Variant
    
    Redim Init(0) As String
    GetUserGroup = Init
    
    If Len(UserNameText) = 0 Then Exit Function
    
    Dim UserName As New NotesName(UserNameText)
    If UseCache Then
        If Iselement(UserGroupsList(UserNameText)) Then
            rv = Split(UserGroupsList(UserNameText), SEP)
            Goto Final
        End If
    End If
    
    'Read AB   
    If cnt = 0 Then
        Dim session As New NotesSession
        Static AbDbs() As NotesDatabase
        Static AbViews() As NotesView
        Redim Preserve AbDbs(cnt)
        Redim Preserve AbViews(cnt)
        Dim AbView As NotesView
        Forall dbn In session.AddressBooks
            If dbn.IsPublicAddressBook Then
                If Not dbn.IsOpen Then Call dbn.Open("","")
                If dbn.IsOpen Then
                    Set AbView = dbn.GetView("($ServerAccess)")
                    If Not AbView Is Nothing Then
                        Redim Preserve AbDbs(cnt)
                        Redim Preserve AbViews(cnt)
                        Set AbDbs(cnt) = dbn
                        Set AbViews(cnt) = AbView
                        cnt = cnt + 1
                    End If
                End If
            End If
        End Forall
    End If
    
    'EO Read AB       
    Dim k As Integer
    Dim GroupCount As Integer
    Dim Coll As NotesDocumentCollection
    Dim Doc As NotesDocument
    Redim UserGroup(0) As String
    UserGroup(0) = UserName.Canonical
    Dim GroupName As String
    
    Do
        For k = 0 To Ubound(AbViews)
            Set Coll = AbViews(k).GetAllDocumentsByKey(Lcase(UserGroup(GroupCount)), True)
            If Coll.Count > 0 Then
                Set Doc = Coll.GetFirstDocument
                Do While Not Doc Is Nothing
                    GroupName = Doc.GetItemValue("ListName")(0)
                    If Isnull(Arraygetindex(UserGroup, GroupName, 5)) Then
                    If UserGroup(Ubound(UserGroup)) <> "" Then Redim Preserve UserGroup(Ubound(UserGroup) + 1)
                        UserGroup(Ubound(UserGroup)) = GroupName
                    End If
                    Set Doc = Coll.GetNextDocument(Doc)
                Loop
            End If
        Next
        GroupCount = GroupCount + 1
    Loop While GroupCount <= Ubound(UserGroup)
    
    UserGroup(0) = ""
    rv = Fulltrim(UserGroup)
    UserGroupsList(UserNameText) = Implode(rv, SEP)
    
Final:
    GetUserGroup = rv
    Exit Function
ErrH:
    Msgbox Error & | in line | & Erl(), 64, |Lotus Notes (| & Lsi_info(2) & |)|
    Exit Function
End Function
 
Последнее редактирование модератором:

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
232
код
Visual Basic:
If Not dbn.IsOpen Then Call dbn.Open("","")

If dbn.IsOpen Then
...
End If
можно было бы заменить на
Visual Basic:
If Not dbn.IsOpen Then
    If dbn.Open("","") Then
    ...
    End If
End If
ещё я бы в конце сделал
Visual Basic:
rv = Fulltrim(UserGroup)
If Len(rv(0)) > 0 Then GetUserGroup = rv
а впереди бы не делал
Visual Basic:
Redim Init(0) As String
GetUserGroup = Init
анализировать результат на IsEmpty, когда возвращается массив, всегда приятнее :welcome:
 
Последнее редактирование:
O

Omh

анализировать результат на IsEmpty,
Я как-то привык возвращать пустой массив в таких случаях, ну это личные заморочки.

Добавлено: Вообще, я бы сделал ф-ию возвращающей boolean
А заполняемый аррей подавал, как параметр.
True если что-то нашлось, False во всех остальных случаях.

Я сильно не люблю возвращать из ф-ии varinat
И ещё сильнее не люблю - возвращать объект.

Может переделаю, но пока и так годится.
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
232
Вообще, я бы сделал ф-ию возвращающей boolean
Часто так делаю.
А иногда возвращаю Integer - код ошибки, или 0, если всё нормально; иногда это очень удобно.

А заполняемый аррей подавал, как параметр.
Делаю так редко, т.к. не нравятся лишние телодвижения по созданию массива в вызывающей функции.

И ещё сильнее не люблю - возвращать объект.
Функция специально для инициализации объекта - просто и сердито ))
Иногда полезно, когда в вызывающем коде тебе не интересно, чего тебе вернула функция (возвращение объектов классов-наследников), просто дальше работаешь общими методами, которые описаны в классе-родителе.
 

NetWood

Lotus Team
17.04.2008
565
96
BIT
174
Подниму веточку :) Вот так все работает. И для вложенных групп тоже.
Visual Basic:
Use "GroupManager" 'fedotxxl Klido
%INCLUDE "lsconst"

...
'тут кое-какие Dim поремлены за ненужностью в примере

user = Cstr(web.session.DocumentContext.Remote_User(0))        'это у кого как юзер будет

Set dbreggroup = web.session.GetDatabase("", profile.GetItemValue("NABGroupFile")(0))    'тут тоже кто как напишет

'поехали юзать ГрупМенеджер
Dim gman As New NotesGroupManager(True)
Dim group As NotesGroup
Dim allmembers As Variant
Dim ismemb As Boolean

Call gman.LoadAddressBook(dbreggroup)

Set group = gman.getGroup("Hispaniola Crew")
If Not (group Is Nothing) Then       
    'there is such a group       
    allmembers = group.AllMembers
    
    'собственно проверяем входит юзер в группу(подгруппу) или нет
    ismemb = Not(Isnull(Arraygetindex(allmembers, user, 5)))
End If
 
Последнее редактирование модератором:
H

hosm

А можно и я вклинюсь :)
По сабжу: точно знаю, что есть Notes С API-шная функция, которая сообщает имеет ли право человек редактировать документ. Поищу на досуге.
что-то вот не вижу найденного... У меня коллега недавно интересовался чем-то похожим.
Есть ли нечто готовое для определения, может ли человек читать и/или редактировать документ? просто обычно либо перебор полей authors-readers либо получение и проверка валидности дока юзается.
 
I

iki

Я уже как-топоднимал эту тему. Вот почитайте.
https://codeby.net/threads/37803.html

Резюмируя: Если надо проверять на серваке - анализируйте names.nsf варианов как это делать предложили много.

Если на локале:
Visual Basic:
Private Const NOTE_FLAGS% = 7
Private Const NOTE_FLAG_READONLY% = &H0001
Declare Private Sub W32_NSFNoteGetInfo Lib "nnotes.dll" Alias "NSFNoteGetInfo" (ByVal hNote As Long, ByVal Note_Member As Integer, Value_ptr As Integer)

'Myclass.canEdit
'****************************

Public Function canEdit () As Integer
On Error GoTo errHandler
Const FuncName = "Myclass.canEdit()"

Dim hNote As Long
Dim NoteFlags As Integer

hNote& = Me.GetDoc().HANDLE
If hNote& <> 0 Then
    Call W32_NSFNoteGetInfo(hNote&, NOTE_FLAGS%, NoteFlags)
End If

If NoteFlags And NOTE_FLAG_READONLY% Then Me.canEdit = False Else Me.canEdit = True

GoTo endH
errHandler:
    Error Err, "(" & LibName & ") " & FuncName & ", стр." & Erl & Chr (10) & _
"UniversalID: " & Me.GetUniversalId () & Chr (10) & Error$
endH:
End Function
 
Последнее редактирование модератором:

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
232
Не помню где взял один класс..
После переделки (вырубки индусского кода и оптимизаций) получилось что-то такое:
Visual Basic:
Const VN_AB_VIMGROUPS = "($VIMGroups)"
Const IN_GROUPMEMBERS = "Members"

%REM
    Description: разворачивание групп; вложенность поддерживается
%END REM
Class GroupExpander
    'объект БД АК (для того, чтобы представление групп не обнулялось)
    Private m_ndbAB As NotesDatabase
    'представление, по которому будет производиться поиск групп
    Private m_nvGroup As NotesView
    'счётчик пользователей группы
    Private m_iMember As Integer
    
    Sub New(ndbAB As NotesDatabase)
        Set Me.m_ndbAB = ndbAB
        Set Me.m_nvGroup = Me.m_ndbAB.GetView(VN_AB_VIMGROUPS)
        Call Me.m_nvGroup.Refresh()
    End Sub
    
    
    %REM
        Description: установка другой АК
    %END REM
    Public Property Set AddressBook As NotesDatabase
        Set Me.m_ndbAB = Me.AddressBook
    End Property
    
    
    %REM
    Description: получение всех пользователей группы с помощью перебора; рекурсивная :(
    Возвращаемые значения:
        - Empty - если группа не найдена;
        - в остальных случаях - массив
    %END REM
    Public Function ExplodeGroup(sGroupName As String) As Variant
        Dim arrMembers() As String
        Dim ndGroup As NotesDocument
        
        If CStr(GetThreadInfo(1)) <> CStr(GetThreadInfo(10)) Then
            Me.m_iMember = 0    'обнуляем, т.к. метод может вызываться извне несколько раз, к примеру, в цикле
        End If
        
        Set ndGroup = Me.m_nvGroup.GetDocumentByKey(sGroupName)
        If ndGroup Is Nothing Then Exit Function
        
        arrMembersAll = ndGroup.GetItemValue(IN_GROUPMEMBERS)
        If Len(arrMembersAll(0)) > 0 Then
            For i% = 0 To UBound(arrMembersAll)
                sEntry$ = arrMembersAll(i%)
                If InStr(sEntry$, "CN=") <> 0 Then        'ускоряем, чтобы "взрывал" только группы!
                    'это имя в системе пользователя
                    ReDim Preserve arrMembers(Me.m_iMember)
                    arrMembers(Me.m_iMember) = sEntry$
                    Me.m_iMember = Me.m_iMember + 1
                Else
                    'это группа
                    Call Me.ExplodeGroup(sEntry$)
                End If
            Next
        Else
            ReDim arrMembers(Me.m_iMember)
        End If
        
        Me.ExplodeGroup = ArrayUnique(arrMembers)
    End Function
    
    
    %REM
        Description: определяет, есть ли пользователь в указанной группе
        работает по методу перебора
    %END REM
    Public Function IsMemberUser(sGroupName As String, sUserName As String) As Boolean
        Dim arrMembers As Variant
        arrMembers = Me.ExplodeGroup(sGroupName)
        If Not IsEmpty(arrMembers) Then
            Me.IsMemberUser = Not IsNull(ArrayGetIndex(arrMembers, sUserName, 5))
        End If
    End Function
    
    
    %REM
        Description: определяет, есть ли пользователь в указанной группе
        работает по @ExpandNameList
    %END REM
    Public Function IsMemberUserEx(sGroupName As String, sUserName As String) As Boolean
        Dim arrMembers As Variant
        arrMembers = Evaluate(|@ExpandNameList("| & Me.m_ndbAB.Server & |":"| & Me.m_ndbAB.FilePath & |";"| & sGroupName & |")|)
        Me.IsMemberUserEx = Not IsNull(ArrayGetIndex(arrMembers, sUserName, 5))
    End Function

End Class
Особенности:
1. Ищет только в установленной АК (я всегда знаю, в какой АК у меня какие группы); если надо будет юзать для нескольких АК, то можно сделать внешний класс с перебором.
2. Инициализация представления в New, если хотите, используйте внешний обработчик ошибок..
Достоинство: не надо использовать кучу кода типа "NotesGroupManager", которую всю и не используешь никогда. Только функционал разворачивания групп.
 
Последнее редактирование:
T

turumbay

На днях зарелизилась от
Кроме прочего, имееца:
NotesGroupManager: makes it easy to scan and manage group memberships in public and private address books, including groups with subgroups.
Ну и чисто посмотреть на хороший LS код...
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
232
turumbay
NotesGroupManager обсуждался на предыдущей странице, его там допиливали и оптимизировали..
Дело как раз в том, чтобы использовать то, что нужно, а не эту гору кода, большинство из которого и не используешь никогда.

Версия 1.3 от 27.05.2011.
P.S. Я бы сказал "нормальный код", и то не весь. Такое ощущение, что писался разными людьми.
 
T

turumbay

Версия 1.3 от 27.05.2011.
Упс. Жерард заявил о выходе версии 1.3 две недели назад( 31 октября 2011 ). . Это меня и смутило - решил, что обсуждали что-то более древнее и есть новая версия либы. Сорри.
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
232
Что-то на нашей рекурсивной функциональности стали чаще сыпаться ошибки 'Out of stack space' с кодом 28 при попытке получить список пользователей группы.
Попробовал NotesGroupManager, который тут выше советуют. Как оказалось, он такой же - в Property Get Members рекурсивно вызывает метод GetGroup...

Ребят, может кто где-то видел нерекурсивное получение списка всех пользователей переданной группы?
 

savl

Lotus Team
28.10.2011
2 624
314
BIT
517
'Out of stack space' с кодом 28
Если не ошибаюсь это 210-211 вызовов, дальше идет ошибка. Группа в группе... Зацикливание?
Не пробовали группы учитывать, которые уже проходили? Чтобы их не разворачивать повторно.
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
232
@savl
Там кеш доков-групп есть, эта ситуация решается. Просто большая вложенность групп. Код всегда на одном и том же месте валится - при попытке получения дока группы с помощью GetDocumentByKey.
Ладно, перепишу на нерекурсивнную структуру; думал, может у кого-то уже есть.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!