Imports System
'import IRemoteSession explicitly to aSub naming conflicts
Imports Plumtree.Remote.PRC

Imports RemoteSessionFactory = Plumtree.Remote.PRC.RemoteSessionFactory


Imports Plumtree.Remote.PRC.Collaboration
Imports Plumtree.Remote.PRC.Collaboration.Project
Imports Plumtree.Remote.PRC.Collaboration.Discussion
Imports Plumtree.Remote.PRC.Collaboration.Security
Imports System.Collections
Imports System.Text



' Command line example which demonstrates security management for different
' collaboration objects, such as adding a member and a group to a project role,
' setting the access level for a role, and setting the access level on individual
' collaboration objects. 

Public Class SecurityCommandLineExample
    'constants for endpoint, username, password and other command line args
    Public Shared ReadOnly ENDPOINT As String = "-endpoint"
    Public Shared ReadOnly USERNAME As String = "-username"
    Public Shared ReadOnly PASSWORD As String = "-password"

    Shared projectManager As IProjectManager
    Shared discussionManager As IDiscussionManager


    Public Shared Sub Main(ByVal args() As String)
        'make the arguments into a hashtable
        Dim argsMap As Hashtable = ParseParameters(args)

        'get a remote session Imports the soap endpoint, username, and password
        Dim endpointUri As System.Uri = CType(argsMap.Item(ENDPOINT), System.Uri)
        Dim usernameStr As String = CType(argsMap.Item(USERNAME), String)
        Dim passwordStr = CType(argsMap.Item(PASSWORD), String)
        Dim remoteSession As IRemoteSession = RemoteSessionFactory.GetExplicitLoginContext(endpointUri, usernameStr, passwordStr)

        'get a collab factory and a project manager
        Dim collabFactory As ICollaborationFactory = remoteSession.GetCollaborationFactory()
        projectManager = collabFactory.GetProjectManager()
        discussionManager = collabFactory.GetDiscussionManager()

        'create and store a project
        Dim project As IProject = CreateAndStoreProject("Sample Project", "Description for Sample Project")

        'retrieve the member role of the project 
        Dim memberRole As IRole = project.GetRole(RoleTypes.Member)

        'add administrator (id=1) to the member role
        AddMemberToRole(memberRole, 1)

        'change the member role to have ADMIN access level for DOCUMENT functional area 
        SetAccessLevelForFunctionalArea(memberRole, AccessLevels.Admin, FunctionalAreas.Document)

        'now create and store a discussion
        Dim discussion As IDiscussion = CreateAndStoreDiscussion(project, "Sample Discussion", "Description for Sample Discussion")

        SetAccessLevelForDiscussion(Discussion, RoleTypes.Member, AccessLevels.Read)

        'add administrator (id=1) to the member role
        RemoveMemberFromRole(memberRole, 1)
    End Sub


    'creates a project - please see Project Example for detailed documentation
    Public Shared Function CreateAndStoreProject(ByVal name As String, ByVal description As String) As IProject
        Dim project As IProject = projectManager.CreateProject(name, description)
        project.Store()
        Return project
    End Function

    'creates a discussion
    Public Shared Function CreateAndStoreDiscussion(ByVal project As IProject, ByVal name As String, ByVal description As String) As IDiscussion
        Dim discussion As IDiscussion = discussionManager.CreateDiscussion(project, name, description)

        'store the discussion to get the ID
        discussion.Store()
        Console.WriteLine("Created discussion has name=" + discussion.Name + ", ID=" + CStr(discussion.ID))
        Return discussion
    End Function
    'add a member to a role
    Public Shared Sub AddMemberToRole(ByVal role As IRole, ByVal userID As Integer)
        'add the member to the role 
        role.AddMember(userID, MemberTypes.User)

        'store the role to persist change
        role.Store()

        Dim memberIDs() As Integer = role.GetMemberIDs(MemberQueryTypes.AllUsers)
        Console.WriteLine("Updated role " + role.Name + " - added user to role with ID = " + CStr(memberIDs(0)))

    End Sub
    'remove a member from a role
    Public Shared Sub RemoveMemberFromRole(ByVal role As IRole, ByVal userID As Integer)
        'remove the member from the role 
        role.RemoveMember(userID, MemberTypes.User)

        'store the role to persist change
        role.Store()

        Dim memberIDs() As Integer = role.GetMemberIDs(MemberQueryTypes.AllUsers)
        If memberIDs.Length = 0 Then
            Console.WriteLine("Successfully removed " + CStr(userID) + " from role " + role.Name)
        Else
            Console.WriteLine("Failed to remove " + CStr(userID) + " from role " + role.Name)
        End If
    End Sub

    Public Shared Sub SetAccessLevelForFunctionalArea(ByVal role As IRole, ByVal accessLevel As AccessLevels, ByVal functionalArea As FunctionalAreas)
        'change role to have the supplied access level for the functional area
        role.SetAccessLevel(functionalArea, accessLevel)

        'store the role to persist the access level change
        role.Store()

        Console.WriteLine("Updated role " + role.Name + " with access level set to " + CStr(role.GetAccessLevel(functionalArea)) + " for " + CStr(functionalArea))
    End Sub

    Public Shared Sub SetAccessLevelForDiscussion(ByVal discussion As IDiscussion, ByVal roleType As RoleTypes, ByVal accessLevel As AccessLevels)
        'first check if the current user has the permission to edit security for the discussion
        Dim hasPermission As Boolean = discussion.IsActionAllowed(DiscussionPermissions.EditSecurity)

        If (hasPermission) Then
            Console.WriteLine("Current user has permission to edit security on discussion.")

            'first disable Imports project default security
            discussion.DefaultSecurity = False
            'then change discussion to have the supplied access level for the role type
            discussion.SetAccessLevel(roleType, accessLevel)

            'store the discussion to persist the access level change
            discussion.Store()

            Console.WriteLine("Set discussion with name=" + discussion.Name + " to have access level " + CStr(discussion.GetAccessLevel(roleType)) + " for " + CStr(roleType))
        Else
            Console.WriteLine("Current user does not have sufficient permission to edit security on discussion.")
        End If
    End Sub

    'helper method to parse command line parameters
    Public Shared Function ParseParameters(ByVal args() As String) As Hashtable
        Dim map As Hashtable = New Hashtable
        'make the args into a list for easier processing
        Dim argsList As ArrayList = New ArrayList
        Dim i As Integer
        For i = 0 To args.Length - 1
            argsList.Add(args(i))
        Next
        'put the args into the map
        GetArg(map, argsList, ENDPOINT, "Endpoint not specified")
        GetArg(map, argsList, USERNAME, "Username not specified")
        GetArg(map, argsList, PASSWORD, "Password not specified")
        Return map
    End Function

    'helper method to get parameters
    Public Shared Sub GetArg(ByVal map As Hashtable, ByVal argsList As ArrayList, ByVal arg As String, ByVal errorMessage As String)
        'get the position of the argument        
        Dim position As Integer = argsList.IndexOf(arg)

        'if not found and required, squawk and quit
        If position = -1 Then
            ErrorUsage(errorMessage)
        Else
            'special case for create, remove, and search
            Dim value As Object = Nothing
            'check for index out of bounds exceptions
            If position + 1 = argsList.Count Then
                ErrorUsage("Unable to find corresponding argument for " + arg)
            End If
            value = argsList(position + 1)

            'special case for endpoint and project id
            If arg.Equals(ENDPOINT) Then
                value = New Uri(CType(value, String))
            End If
            'only add things once
            If Not map.ContainsKey(arg) Then
                map.Add(arg, value)
            End If
        End If
    End Sub


    'method to print out an error message, usage, and exit
    Public Shared Sub ErrorUsage(ByVal errorMessage As String)
        Console.WriteLine(errorMessage)
        Console.WriteLine(Chr(10))
        PrintUsage()
        Environment.Exit(2)
    End Sub
    'prints usage
    Public Shared Sub PrintUsage()
        Dim usage As StringBuilder = New StringBuilder
        usage.Append(Chr(10) + "Usage: SecurityCommandLineExample " + Chr(10))
        usage.Append(ENDPOINT)
        usage.Append(" http:'myserver:8080/ptapi/services/QueryInterfaceAPI Chr(10)")
        usage.Append(USERNAME)
        usage.Append(" administrator -password """"" + Chr(10))

        Console.WriteLine(usage.ToString())
    End Sub
end class