Adding roles to users in team area in RTC - rtc

I need to add users ( users are already present in repository. I only need to add them.) and roles from a CSV file to team areas. Project area and Team Area already exists.I could successfully add users but not the roles from csv file.
The CSV file format is :
Project name,Team Area name,Members,roles
Project1,User_Role_TA,Alex,Team Member
Project2,TA2,David,Scrum Master
Below is the code for it. It successfully add the users and currently add roles to them from project area but I need to add roles to the users from CSV file. In the below code, If I can get roles from csv file in the line "IRole[] availableRoles = clientProcess.getRoles(area, null);" , I think it should resolve the issue. I am not getting any error but it doesn't add the roles.
while((row = CSVFileReader.readLine()) != null )
{
rowNumber++;
st = new StringTokenizer(row,",");
while (st.hasMoreTokens()) {
projectAreaList.add(st.nextToken());
teamAreaList.add(st.nextToken());
membersList.add(st.nextToken());
roleList.add(st.nextToken());
}
}
for (int i=1; i<rowNumber; i++)
{
projectAreaName = projectAreaList.get(i);
teamAreaName = teamAreaList.get(i);
members = membersList.get(i);
member_roles =roleList.get(i);
URI uri = URI.create(projectAreaName.replaceAll(" ", "%20"));
IProjectArea projectArea = (IProjectArea) processClient.findProcessArea(uri, null, null);
if (projectArea == null)
{
System.out.println("Project Area not found");
}
if (!teamAreaName.equals("NULL")){
List <TeamAreaHandle> teamlist = projectArea.getTeamAreas();
ITeamAreaHandle newTAHandle = findTeamAreaByName(teamlist,teamAreaName,monitor);
if(newTAHandle == null) {
System.out.println("Team Area not found");
}
else {
ITeamArea TA = (ITeamArea)teamRepository.itemManager().fetchCompleteItem(newTAHandle,ItemManager.DEFAULT,monitor);
IRole role = getRole(projectArea);
IContributor user = teamRepository.contributorManager().fetchContributorByUserId(members,monitor);
/*role1 = getRole(area).getId();
if(role1.equalsIgnoreCase(member_roles))
{
user_role = getRole(area);
}*/
IProcessAreaWorkingCopy areaWc = (IProcessAreaWorkingCopy)service.getWorkingCopyManager().createPrivateWorkingCopy(TA);
areaWc.getTeam().addContributorsSettingRoleCast(
new IContributor[] {user},
new IRole[] {role});
areaWc.save(monitor);
}
public static IRole getRole(IProcessArea area) throws TeamRepositoryException {
ITeamRepository repo = (ITeamRepository) area.getOrigin();
IProcessItemService service =(IProcessItemService) repo
.getClientLibrary(IProcessItemService.class);
IClientProcess clientProcess = service.getClientProcess(area, null);
IRole[] availableRoles = clientProcess.getRoles(area, null);
for (int i = 0; i < availableRoles.length; i++) {
return availableRoles[i];
}
throw new IllegalArgumentException("Couldn't find role");
}

Some of the API you are trying to use are private in RTC3.x
See this thread for different options (a bit similar to your code):
ProjectAreaWorkingCopy workingCopy = (ProjectAreaWorkingCopy)manager.getWorkingCopy(project);
this class extends to ProcessAreaWorkingCopy
public class ProjectAreaWorkingCopy extends ProcessAreaWorkingCopy implements IProjectAreaWorkingCopy
In ProcessAreaWorkingCopy setRoleCast retrieves the team and sets the role.
One can set the role at the team level via
team.setRoleCast(contributor, roleCast);
# or
projWc.getTeam().addContributorsSettingRoleCast(new IContributor[] {contributor}, roles);
The OP Kaushambi Suyal reports:
Created a method as mentioned in the thread with few changes and it worked.
Also we need to pass the process area here and not the project area, because I am trying to add roles to users in team area and not project area.

Related

why it is showing project name as "Default" in sitefinity dashboard portal once I run it

I am new to Sitefinity. But I followed steps from tutorial and created the one project named as "SFcmsDemo" and when I run this project and Sitefinity dashboard appears on localhost it is showing name as "Default" instead of "SFcmsDemo", The tutorial I read is showing the correct name in that but when I tried it is showing as "Default". Can anyone please help me find out the root cause and solution for this. I am attaching some screenshot which will help to understand more. Thanks.
Default can be easily changed if you click on it and then Manage Site.
UPDATE
From the decompiled Telerik.Sitefinity.dll (v.12.2):
internal static Site GetOrCreateDefaultSite()
{
Site site;
string str = "CreateDefaultSite";
MultisiteManager manager = MultisiteManager.GetManager(null, str);
using (ElevatedModeRegion elevatedModeRegion = new ElevatedModeRegion(manager))
{
ProjectConfig projectConfig = Config.Get<ProjectConfig>();
Guid siteMapRootNodeId = projectConfig.DefaultSite.SiteMapRootNodeId;
Site site = (
from s in manager.GetSites()
where s.SiteMapRootNodeId == siteMapRootNodeId
select s).FirstOrDefault<Site>();
if (site == null)
{
site = (projectConfig.DefaultSite.Id == Guid.Empty ? manager.CreateSite() : manager.CreateSite(projectConfig.DefaultSite.Id));
site.IsDefault = true;
site.IsOffline = false;
site.site = projectConfig.DefaultSite.site;
site.SiteMapRootNodeId = siteMapRootNodeId;
site.Name = (projectConfig.ProjectName != "/" ? projectConfig.ProjectName : "Default");
....
Note in the last line how it looks in the projectConfig.ProjectName value and if it is equal to "/" then it sets it to "Default"
Now, if we look at the ProjectConfig there is this:
[Browsable(false)]
[ConfigurationProperty("projectName", DefaultValue="/")]
[ObjectInfo(typeof(ConfigDescriptions), Title="ProjectNameTitle", Description="ProjectNameDescription")]
public string ProjectName
{
get
{
return (string)this["projectName"];
}
internal set
{
this["projectName"] = value;
}
}
So, default value is indeed "/", so that's why when the site is created it has a name of Default.

Google API for getting maximum number of licenses in a Google Apps domain

I have a Google Apps Script function used for setting up accounts for new employees in our Google Apps domain.
The first thing it does is makes calls to the Google Admin Settings API and retrieves the currentNumberOfUsers and maximumNumberOfUsers, so it can see if there are available seats (otherwise a subsequent step where the user is created using the Admin SDK Directory API would fail).
It's been working fine until recently when our domain had to migrate from Postini to Google Vault for email archiving.
Before the migration, when creating a Google Apps user using the Admin SDK Directory API, it would increment the currentNumberOfUsers by 1 and the new user account user would automatically have access to all Google Apps services.
Now after the migration, when creating a Google Apps user, they aren't automatically assigned a "license," so I modified my script to use the Enterprise License Manager API and now it assigns a "Google-Apps-For-Business" license. That works fine.
However, the currentNumberOfUsers is now different from the number of assigned licenses, and "Google-Apps-For-Business" is only one of several different types of licenses available.
I can get the current number of assigned "Google-Apps-For-Business" licenses by running this:
var currentXml = AdminLicenseManager.LicenseAssignments.listForProductAndSku('Google-Apps', 'Google-Apps-For-Business', 'domain.com', {maxResults: 1000});
var current = currentXml.items.toString().match(/\/sku\/Google-Apps-For-Business\/user\//g).length;
But the number that produces is different from currentNumberOfUsers.
All I really need to do now is get the maximum number of owned "Google-Apps-For-Business" licenses so the new employee setup script can determine whether there are any available.
I checked the API Reference documentation for the following APIs but...
Enterprise License Manager API → Doesn't have a method for getting the maximum or available number of licenses.
Google Admin Settings API → Doesn't deal with licenses, only "users."
Admin SDK Directory API User resource → Doesn't deal with licenses.
Google Apps Reseller API → This API seems to have what I need, but it's only for Reseller accounts.
I know I can program my new employee setup script to just have a try/catch seeing if it would be able to create the user and assign the license, and end the script execution gracefully if it can't, but that doesn't seem efficient.
Also, part of the old script was that if there were less than X seats available, it would email me a heads-up to order more. I can program a loop that attempts to repeatedly create dummy users and assign them licenses and count the number of times it can do that before it fails, then delete all the dummy users, but, once again, that's not efficient at all.
Any ideas?
Update 3/11/2020: Since the Admin Settings API had shut down a few years ago I've been using the Enterprise License Manager API to get the current number of used licenses, like this:
function getCurrentNumberOfUsedGoogleLicenses(skuId) {
var success = false, error = null, count = 0;
var adminEmail = 'admin#domain.com';
var gSuiteDomain = adminEmail.split('#')[1];
// for more information on the domain-wide delegation:
// https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
// the getDomainWideDelegationService() function uses this:
// https://github.com/gsuitedevs/apps-script-oauth2
var service = getDomainWideDelegationService('EnterpriseLicenseManager: ', 'https://www.googleapis.com/auth/apps.licensing', adminEmail);
if (skuId == 'Google-Apps-Unlimited') var productId = 'Google-Apps';
else return { success: success, error: "Unsupported skuId", count: count };
var requestBody = {};
requestBody.headers = {'Authorization': 'Bearer ' + service.getAccessToken()};
requestBody.method = "GET";
requestBody.muteHttpExceptions = false;
var data, pageToken, pageTokenString;
var maxAttempts = 5;
var currentAttempts = 0;
var pauseBetweenAttemptsSeconds = 3;
loopThroughPages:
do {
if (typeof pageToken === 'undefined') pageTokenString = "";
else pageTokenString = "&pageToken=" + encodeURIComponent(pageToken);
var url = 'https://www.googleapis.com/apps/licensing/v1/product/' + productId + '/sku/' + skuId + '/users?maxResults=1000&customerId=' + gSuiteDomain + pageTokenString;
try {
currentAttempts++;
var response = UrlFetchApp.fetch(url, requestBody);
var result = JSON.parse(response.getContentText());
if (result.items) {
var licenseAssignments = result.items;
var licenseAssignmentsString = '';
for (var i = 0; i < licenseAssignments.length; i++) {
licenseAssignmentsString += JSON.stringify(licenseAssignments[i]);
}
if (skuId == 'Google-Apps-Unlimited') count += licenseAssignmentsString.match(/\/sku\/Google-Apps-Unlimited\/user\//g).length;
currentAttempts = 0; // reset currentAttempts before the next page
}
} catch(e) {
error = "Error: " + e.message;
if (currentAttempts >= maxAttempts) {
error = 'Exceeded ' + maxAttempts + ' attempts to get license count: ' + error;
break loopThroughPages;
}
} // end of try catch
if (result) pageToken = result.nextPageToken;
} while (pageToken);
if (!error) success = true;
return { success: success, error: error, count: count };
}
However, there still does not appear to be a way to get the maximum number available to the domain using this API.
Use CustomerUsageReports.
jay0lee is kind enough to provide the GAM source code in Python. I crudely modified the doGetCustomerInfo() function into Apps Script thusly:
function getNumberOfLicenses() {
var tryDate = new Date();
var dateString = tryDate.getFullYear().toString() + "-" + (tryDate.getMonth() + 1).toString() + "-" + tryDate.getDate().toString();
while (true) {
try {
var response = AdminReports.CustomerUsageReports.get(dateString,{parameters : "accounts:gsuite_basic_total_licenses,accounts:gsuite_basic_used_licenses"});
break;
} catch(e) {
//Logger.log(e.warnings.toString());
tryDate.setDate(tryDate.getDate()-1);
dateString = tryDate.getFullYear().toString() + "-" + (tryDate.getMonth() + 1).toString() + "-" + tryDate.getDate().toString();
continue;
}
};
var availLicenseCount = response.usageReports[0].parameters[0].intValue;
var usedLicenseCount = response.usageReports[0].parameters[1].intValue;
Logger.log("Available licenses:" + availLicenseCount.toString());
Logger.log("Used licenses:" + usedLicenseCount.toString());
return availLicenseCount;
}
I would recommend exploring GAM which is a tool that gives command line access to the administration functions of your domain.

How to add extra data to a member in MDS?

I'm running MDS on a virtual machine and trying to access the service from my host OS.
I've been able to add something to the database but my data is all over the place and in the Master Data Manager (website) I don't see the new member.
I suppose I shouldn't be using Attributes but something else but what and how? Are there tutorials because I can't find any ...?
Here's the code I'm using:
International international = new International();
EntityMembers entityMembers = new EntityMembers();
// Set the modelId, versionId, and entityId.
entityMembers.ModelId = new Identifier { Name = modelName };
entityMembers.VersionId = new Identifier { Name = versionName };
entityMembers.EntityId = new Identifier { Name = entityName };
entityMembers.MemberType = memberType;
Collection<Member> members = new Collection<Member>();
Member aNewMember = new Member();
aNewMember.MemberId = new MemberIdentifier() { Name = employee.FullName, Code = aNewCode, MemberType = memberType };
Collection<MDS.Attribute> attributes = new Collection<MDS.Attribute>();
MDS.Attribute attrOrgUnit = new MDS.Attribute();
attrOrgUnit.Identifier = new Identifier() { Name = "OrganizationalUnit" };
attrOrgUnit.Value = employee.OrganizationalUnit;
attrOrgUnit.Type = AttributeValueType.String;
attributes.Add(attrOrgUnit);
aNewMember.Attributes = attributes.ToArray();
members.Add(aNewMember);
entityMembers.Members = members.ToArray();
// Create a new entity member
OperationResult operationResult = new OperationResult();
clientProxy.EntityMembersCreate(international, entityMembers, false, out operationResult);
HandleOperationErrors(operationResult);
I have been able to fix my own problem.
First of all: creating separate variables with collections and converting them to arrays afterwards is not necessary. The code from the tutorials works but fails to mention that, when adding the service reference, you have to configure it (right-click on the service reference -> configure) to use Collections as "Collection type" instead of arrays and to generate message contracts.
Second, the code above with the attributes is correct and works perfectly. The problem I had which failed to add messages with attributes was unrelated. It was a connection/authentication problem between my Host OS and Guest OS.
Hope this helps someone.

API to update users image - Identity Extended Properties not saving

I'm trying to write a small script to set all users images to their AD image, I did some jumping around in ILSpy and found out what to set using the TFS Server API, however the code needs to be a bit different because I'm using the client API instead.
The code I have below can succesfully iterate through all the users in tfs, look them up in AD, grab the thumbnail, set the property on the TFS identity. But I can't for the life of me figure get the extended property to save back into TFS.
The code doesn't exception, but the property isn't set to the value I set it to when I next run the application.
Does anyone know the way to save extended properties via the client api?
Microsoft.TeamFoundation.Client.TeamFoundationServer teamFoundationServer = new Microsoft.TeamFoundation.Client.TeamFoundationServer("{URL TO TFS}");
FilteredIdentityService service = teamFoundationServer.GetService<FilteredIdentityService>(); ;
IIdentityManagementService2 service2 = teamFoundationServer.GetService<IIdentityManagementService2>();
foreach (var identity in service.SearchForUsers(""))
{
var user = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain), identity.UniqueName);
if (user == null) continue;
var de = new System.DirectoryServices.DirectoryEntry("LDAP://" + user.DistinguishedName);
var thumbNail = de.Properties["thumbnailPhoto"].Value as byte[];
identity.SetProperty("Microsoft.TeamFoundation.Identity.CandidateImage.Data", thumbNail);
identity.SetProperty("Microsoft.TeamFoundation.Identity.CandidateImage.UploadDate", DateTime.UtcNow);
service2.UpdateExtendedProperties(identity);
}
Figured it out, needed to set some additional properties.
Microsoft.TeamFoundation.Client.TeamFoundationServer teamFoundationServer = new Microsoft.TeamFoundation.Client.TeamFoundationServer("http://urltotfs");
FilteredIdentityService service = teamFoundationServer.GetService<FilteredIdentityService>(); ;
IIdentityManagementService2 service2 = teamFoundationServer.GetService<IIdentityManagementService2>();
foreach (var identity in service.SearchForUsers(""))
{
var user = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain), identity.UniqueName);
if (user == null) continue;
var de = new System.DirectoryServices.DirectoryEntry("LDAP://" + user.DistinguishedName);
var thumbNail = de.Properties["thumbnailPhoto"].Value as byte[];
identity.SetProperty("Microsoft.TeamFoundation.Identity.Image.Data", thumbNail);
identity.SetProperty("Microsoft.TeamFoundation.Identity.Image.Type", "image/png");
identity.SetProperty("Microsoft.TeamFoundation.Identity.Image.Id", Guid.NewGuid().ToByteArray());
identity.SetProperty("Microsoft.TeamFoundation.Identity.CandidateImage.Data", null);
identity.SetProperty("Microsoft.TeamFoundation.Identity.CandidateImage.UploadDate", null);
service2.UpdateExtendedProperties(identity);
}

SharpArch.Data.NHibernate.Repository.SaveOrUpdate() don't save

I have this code for filling DB, but after finish, DB is still empty. Only number in hibernate_unique_key table is higher.
The next thing which is interesting is, that during debugging instances has id, after save, but not like 1,2,3... but very high like 60083, 60084, ... etc. (It not seems normal, because there is only several rows for save).
Before that, there was some problems with references and so on, but now there is no error message or exception.
code is there:
using System;
using NHibernate.Cfg;
using SharpArch.Data.NHibernate;
using LaboratorniMetody.Data.NHibernateMaps;
using SharpArch.Core.PersistenceSupport;
using LaboratorniMetody.Core;
namespace LaboratorniMetody.FillSchema
{
class Program
{
private static Configuration configuration;
static void Main(string[] args)
{
configuration = NHibernateSession.Init(new SimpleSessionStorage(), new String[] { "LaboratorniMetody.Data" },
new AutoPersistenceModelGenerator().Generate(),
"../../../../app/LaboratorniMetody.Web/NHibernate.config");
IRepository<Laboratory> LaboratoryRepository = new Repository<Laboratory>();
Laboratory Laboratory1 = new Laboratory() { Name = "Hematologie" };//Method
Laboratory l = LaboratoryRepository.SaveOrUpdate(Laboratory1);
Laboratory Laboratory2 = new Laboratory() { Name = "Patologie" };//Method
LaboratoryRepository.SaveOrUpdate(Laboratory2);
Laboratory Laboratory3 = new Laboratory() { Name = "Laboratoře" };//Method
LaboratoryRepository.SaveOrUpdate(Laboratory3);
}
}
}
I use DB schema genereted by NUnit from Project.Core classes.
Do you have any ideas where i should find problem? I have 2 very similar project which working with no problem. I Copyed this code from one of them and there is practicly no differents (except DB model and so on.)
You need to do your changes in a transaction and commit the transaction afterwards.
using(var tx = NHibernateSession.Current.BeginTransaction())
{
IRepository<Laboratory> LaboratoryRepository = new Repository<Laboratory>();
Laboratory Laboratory1 = new Laboratory() { Name = "Hematologie" };//Method
Laboratory l = LaboratoryRepository.SaveOrUpdate(Laboratory1);
Laboratory Laboratory2 = new Laboratory() { Name = "Patologie" };//Method
LaboratoryRepository.SaveOrUpdate(Laboratory2);
Laboratory Laboratory3 = new Laboratory() { Name = "Laboratoře" };//Method
LaboratoryRepository.SaveOrUpdate(Laboratory3);
tx.Commit();
}
I advise to look at the SharpArchContrib project wiki, which has some samples on using SharpArch in a windows app/service and how to use Transaction attributes from there.
https://github.com/sharparchitecture/Sharp-Architecture-Contrib/wiki/