internal static Identity ResolveUser(VSTSConnection vstsConn, string userName) { Debug.Assert(vstsConn != null, "Null vstsConn handle"); Debug.Assert(userName != null, "Null userName param"); if (m_gss == null) { TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(vstsConn.bisUri); m_gss = (IGroupSecurityService)tfs.GetService(typeof(IGroupSecurityService)); } // Get the user identity Identity userIdentity = null; try { userIdentity = m_gss.ReadIdentityFromSource(SearchFactor.AccountName, userName); } catch (Exception ex) { // if there is some Active Directory issue, currently GSS throws GroupSecuritySubsystemException // bug#57749 plans to give specific exception for this.. // we are handling Exception here as the bug 57749 lists this exception as well // as one of the possible exception that can be thrown // for this exception assume that the user cannot be resolved Logger.Write(LogSource.WorkItemTracking, TraceLevel.Warning, "Could not resolve user {0} because of {1}", userName, ex.Message); } return(userIdentity); }
/// <summary> /// Execute a query given a list of name/value/relation sets as criteria /// </summary> /// <param name="vstsConn"></param> /// <param name="checkList"></param> /// <returns></returns> public static WorkItemCollection ExecuteVstsQuery(VSTSConnection vstsConn, ArrayList checkList) { StringBuilder curquery = new StringBuilder("Select ID from workitems where "); foreach (WorkItemNameValueRelation namevaluerelation in checkList) { if (checkList.IndexOf(namevaluerelation) != 0) { curquery.Append(" AND "); } curquery.Append(" ["); curquery.Append(namevaluerelation.Name); // name curquery.Append("] "); curquery.Append(namevaluerelation.Relation); // relation // no need to put '' for int types if (namevaluerelation.DataType == WorkItemNameValueRelation.QueryDataType.String) { curquery.Append(" '"); } curquery.Append(namevaluerelation.Value); // value if (namevaluerelation.DataType == WorkItemNameValueRelation.QueryDataType.String) { curquery.Append("'"); } } Logger.Write(LogSource.WorkItemTracking, TraceLevel.Verbose, "Executing Query : {0}", curquery.ToString()); return(vstsConn.store.Query(curquery.ToString())); }
/// <summary> /// Constructor for VSTS work Item Helper /// </summary> /// <param name="conn">Team Foundation Connection</param> /// <param name="witName">Work Item Type Name</param> /// <param name="maps">Field Maps reference</param> /// <param name="userMap">User Maps refernce</param> /// <param name="sourceConvIndex">Source Converter Index</param> public VSTSWorkItemHelper(VSTSConnection conn, string witName, FieldMaps maps, UserMappings userMap, int sourceConvIndex, string fieldMapFile) { m_vstsConnection = conn; m_maps = maps; m_witName = witName; m_userMappings = userMap; m_fieldMapFile = fieldMapFile; // validate the field mappings ValidateFieldMaps(); // build the field mappings BuildFieldMappings(); CurClient.WorkItemType witType = m_vstsConnection.GetWorkItemType(m_witName); m_convSourceIndex = sourceConvIndex; // Check if the Duplicate WI ID is used by CQ! if (witType.FieldDefinitions.Contains(m_duplicateWiId) && !m_fieldMappings.Contains(m_duplicateWiId)) { m_canSetDuplicateWiId = true; } m_wi = CreateNewWorkItem(); // prepare intial work item snapshot with all required and available field values foreach (string reqField in m_requiredFieldsForCreatingWI) { Field fld = m_wi.Fields[reqField]; Debug.Assert(fld != null, "Null handle for core field while preparing initial snapshot"); if (fld != null) { Logger.Write(LogSource.WorkItemTracking, TraceLevel.Verbose, "Base WI Snapshot - Field [{0}], Value [{1}]", fld.ReferenceName, fld.Value); m_baseWiSnapShot.Add(fld.ReferenceName, fld.Value); } } m_baseWiSnapShot.Add(VSTSConstants.CreatedDateFieldRefName, VSTSConstants.CurrentDate); m_baseWiSnapShot.Add(VSTSConstants.CreatedByFieldRefName, "Converter"); m_MigStatusField = m_wi.Fields[m_migrationStatusFieldName]; VSTSConstants.MigrationStatusField = m_MigStatusField.ReferenceName; // initialize web service URI's WSHelper.SetupProxy(conn.Tfs.Name); }
/// <summary> /// Find a work item that satisfies given checkList /// </summary> /// <param name="vstsConn"></param> /// <param name="checkList"></param> /// <returns></returns> public static WorkItem FindWorkItem(VSTSConnection vstsConn, ArrayList checkList) { WorkItemCollection workitems = ExecuteVstsQuery(vstsConn, checkList); Debug.Assert(workitems.Count <= 1, "Work Item " + " was migrated more than once"); WorkItem localWI = null; if (workitems != null && workitems.Count > 0) { localWI = vstsConn.store.GetWorkItem(workitems[0].Id); } return(localWI); }
/// <summary> /// Handle catching DeniedOrNotExistException in case /// path looked up for is not found /// </summary> /// <param name="path"></param> /// <returns></returns> internal static Node FindNodeInSubTree(VSTSConnection vstsConn, string path, Node.TreeType type) { Node localNode = null; try { localNode = vstsConn.project.FindNodeInSubTree(path, type); } catch (DeniedOrNotExistException) { // try to create the given css path if (path.IndexOfAny(VSTSConstants.UnsupportedCSSChars) > -1) { String newPath = AreaPathRegEx.Replace(path, "_"); Logger.Write(LogSource.WorkItemTracking, TraceLevel.Warning, "Generating new CSS path from [{0}] to [{1}]", path, newPath); localNode = FindNodeInSubTree(vstsConn, newPath, type); } else { try { // try to create the CSS path if (Css == null) { Css = (ICommonStructureService)vstsConn.Tfs.GetService(typeof(ICommonStructureService)); } SetDefaultCSSUri(Css, vstsConn.projectName); if (type == Node.TreeType.Area) { CreateCSSPath(Css, path, RootAreaNodeUri); } else if (type == Node.TreeType.Iteration) { CreateCSSPath(Css, path, RootIterationNodeUri); } // after creating CSS path, sync the CSS tree if (VstsProjectInfo == null) { VstsProjectInfo = Css.GetProjectFromName(vstsConn.projectName); } WSHelper.SyncBisCSS(VstsProjectInfo); // refresh the connection vstsConn.Refresh(); // try to get the id now try { localNode = vstsConn.project.FindNodeInSubTree(path, type); } catch (DeniedOrNotExistException) { localNode = null; Logger.Write(LogSource.WorkItemTracking, TraceLevel.Warning, "Cannot find the CSS path {0} even after creating", path); } } finally { } } } return(localNode); }
/// <summary> /// Validate users in UserMap. .should be part of TFSEveryone group /// </summary> /// <param name="usersMap"></param> public static void ValidateCurrituckUsers(UserMappingsUserMap[] usersMap, VSTSConnection vstsConn, string userMapFile) { if (usersMap == null || usersMap.Length == 0) { // null user maps allowed.. bug#11100 return; } Logger.WritePerf(LogSource.WorkItemTracking, "Validating users on Work Item Tracking"); // there can be multiple source users mapped to one currituck users.. // since currituck user validation is costly, will store the currituck user once validated Hashtable processedUsers = new Hashtable(TFStringComparer.UserName); Display.StartProgressDisplay(VSTSResource.VstsValidatingUsers); try { StringBuilder invalidUsers = new StringBuilder(); foreach (UserMappingsUserMap uMap in usersMap) { Debug.Assert(uMap.To != null, "Found null user in UserMap"); if (!ResolvedUsers.ContainsKey(uMap.To) && !processedUsers.ContainsKey(uMap.To)) { processedUsers.Add(uMap.To, null); Logger.Write(LogSource.WorkItemTracking, TraceLevel.Verbose, "Verifying ClientUserName in BIS: {0}", uMap.To); // Get the user identity Identity user = ResolveUser(vstsConn, uMap.To); if (user == null) { // add in the invalid users list if (invalidUsers.Length > 0) { invalidUsers.Append(", "); } invalidUsers.Append(uMap.To); } else { // work item tracking now works in two modes.. Account Name and Friendly Name // if the current mode is "Friendly Name".. add the alias->friendly name in Resolved users if (vstsConn.store.UserDisplayMode == UserDisplayMode.FriendlyName) { ResolvedUsers.Add(uMap.To, user.DisplayName); } else { // add alias->alias in Resolved Users ResolvedUsers.Add(uMap.To, uMap.To); } } } } if (invalidUsers.Length > 0) { Logger.Write(LogSource.WorkItemTracking, TraceLevel.Error, "Invalid Users in usermap file: {0}", invalidUsers.ToString()); string errMsg = UtilityMethods.Format( VSTSResource.VstsInvalidUsers, userMapFile, invalidUsers.ToString()); Common.ConverterMain.MigrationReport.WriteIssue(String.Empty, errMsg, string.Empty, null, string.Empty, ReportIssueType.Critical); throw new ConverterException(errMsg); } } finally { Display.StopProgressDisplay(); Logger.WritePerf(LogSource.WorkItemTracking, "Validation of users on Work Item Tracking completed"); } }
/// <summary> /// Check the field name in Store.FieldCollection and come out with a unique field name /// and the corresponding unique refname /// </summary> /// <param name="conn">VSTS connection handle</param> /// <param name="witdFldDef">Field Definition handle</param> /// <param name="usedFieldNames">list of already used field names</param> public static void ValidateFieldNames(VSTSConnection conn, ref Common.FieldDefinition witdFldDef, Hashtable usedFieldNames, Hashtable usedFieldRefNames) { Debug.Assert(conn != null); Debug.Assert(witdFldDef != null); WorkItemStore store = conn.store; FieldDefinitionCollection fldDefCollection = store.FieldDefinitions; // if this field is already used in current schema, append numbers to it monotonically increasing if (usedFieldNames[witdFldDef.name] != null) { int i = 1; while (usedFieldNames[witdFldDef.name + i.ToString(CultureInfo.InvariantCulture)] != null) { i++; } // got a field which is not there in existing list witdFldDef.name = witdFldDef.name + i.ToString(CultureInfo.InvariantCulture); } if (fldDefCollection.Contains(witdFldDef.name)) { FieldDefinition currituckFldDef = fldDefCollection[witdFldDef.name]; string witdtype = witdFldDef.type.ToString(); string vstsFldType = currituckFldDef.FieldType.ToString(); if (String.Equals(witdtype, vstsFldType, StringComparison.OrdinalIgnoreCase)) { // reuse the same refname from the existing field in store witdFldDef.refname = currituckFldDef.ReferenceName; } else { // generate new field based on using field name and type.. witdFldDef.name = witdFldDef.name + " " + witdtype; // recheck if this new field exists in the currituck ValidateFieldNames(conn, ref witdFldDef, usedFieldNames, usedFieldRefNames); } } else { // this field does not exist in curritcuk.. // check if this is one of the core internal field not supposed to be used by the customer /* * fix for bug#11206 * there is additional constraint that some of the core fields names are internal * and cannot be used by the user... for temporary solution listing out all those * core fields.. shall go out once there is some better solution from currituck */ if (!VSTSConstants.TfsInternalFields.ContainsKey(witdFldDef.name)) { // can use this safely with our own type and refname witdFldDef.refname = ReferenceNamePrefix + witdFldDef.name; // remove unwanted characters from refname // if the refname is taken from Currituck, there would not be any unwanted characters to be replaced witdFldDef.refname = FieldRefNameRegEx.Replace(witdFldDef.refname, "_"); // see if this refname is already used with some other field in tfs // or in the current schema, append numbers to it monotonically increasing if (fldDefCollection.Contains(witdFldDef.refname) || usedFieldRefNames.ContainsKey(witdFldDef.refname)) { string newFldRefName = String.Empty; // generate a unique ref name int suffix = 1; do { newFldRefName = String.Concat(witdFldDef.refname, suffix++); }while (fldDefCollection.Contains(newFldRefName) || usedFieldRefNames.ContainsKey(newFldRefName)); witdFldDef.refname = newFldRefName; } } else { /* * If the field name happen to be one of the intenal core field name, treat as * that is a existing field with different type and generate new field name */ // generate new field based using field name and type.. witdFldDef.name = witdFldDef.name + " " + witdFldDef.type.ToString(); // recheck if this new field exists in the currituck ValidateFieldNames(conn, ref witdFldDef, usedFieldNames, usedFieldRefNames); } } }
/// <summary> /// Get the work item given its id! /// </summary> /// <param name="conn"></param> /// <param name="id"></param> /// <returns></returns> public static WorkItem GetWorkItemForId(VSTSConnection conn, int id) { return(conn.store.GetWorkItem(id)); }