Salesforce: Log Into Community As User ✤

Scenario: You’ve been using Salesforce for some time and, being a progressive person, have jumped aboard the Lightning Experience train with both feet. However, there’s one feature you keep having to go back into Classic for, and it kinda drives you nuts: Log Into Community As User. It’s such a simple button, but it makes life so much easier, and you really notice it when it’s gone, don’t ya?

The solution, at least until Salesforce brings the functionality into Lightning (which I imagine they’ll do any day now), is creating a lighting component, an Apex controller, and dragging your component onto the Contact page builder.

It’s not so complicated, I promise. Create your component and apex class, and copy-and-paste the code below into the appropriate files.

LoginToCommunityAsUser.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" controller="LoginToCommunityAsUser_Controller">
	<aura:attribute type="String" name="MyAccountId" />
	<aura:attribute type="String" name="UserAccountId" />
	<aura:attribute type="String" name="setupId" />
	<aura:attribute type="String" name="userId" />
	<aura:attribute name="recordId" type="Id" />
	<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

	<button class="slds-button slds-button_brand slds-hide" aura:id="button" onclick="{!c.click}">Login to Community as User</button>
</aura:component>

LoginToCommunityAsUserController.js

({
	doInit : function(component, event, helper) {
		var recordId = component.get('v.recordId');
		helper.getOrgId(component).then(function(r) {
			component.set('v.MyAccountId', r);
		});
		helper.getAccountId(component).then(function(r) {
			component.set('v.UserAccountId', r);
		});
		helper.getSetupId(component).then(function(r) {
			component.set('v.setupId', r);
		});
		helper.getUserId(component).then(function(r) {
			component.set('v.userId', r);
			$A.util.removeClass(component.find('button'),'slds-hide');
		});
	},

	click : function(component, event, helper) {
		helper.loginToCommunityAsUser(component);
	}
})

LoginToCommunityAsUserHelper.js

({
	navigateToUrl : function(a) {
		"undefined" !== typeof sforce && "undefined" !== typeof sforce.one ? sforce.one.navigateToURL(a) : window.location = a
	},

	getOrgId : function(component) {
		return new Promise(function(resolve, reject) {
			var action = component.get('c.getOrgId');
			action.setCallback( this, function( response ) {
				resolve( response.getReturnValue() );
			});
			$A.enqueueAction( action );
		});
	},

	getAccountId : function(component) {
		var action = component.get('c.getAccountId'),
				recordId = component.get('v.recordId');
		return new Promise(function(resolve, reject) {
			console.log(recordId);
			action.setParams({
				"recordId" : recordId
			});
			action.setCallback( this, function( response ) {
				console.log(response);
				resolve( response.getReturnValue() );
			});
			$A.enqueueAction( action );
		});
	},

	getSetupId : function(component) {
		return new Promise(function(resolve, reject) {
			var action = component.get('c.getSetupId'),
					recordId = component.get('v.recordId');
			action.setParams({
				"recordId" : recordId
			});
			action.setCallback( this, function( response ) {
				console.log(response);
				resolve( response.getReturnValue() );
			});
			$A.enqueueAction( action );
		});
	},

	getUserId : function(component) {
		return new Promise(function(resolve, reject) {
			var action = component.get('c.getUserId'),
					recordId = component.get('v.recordId');
			action.setParams({
				"recordId" : recordId
			});
			action.setCallback( this, function( response ) {
				resolve( response.getReturnValue() );
			});
			$A.enqueueAction( action );
		});
	},

	loginToCommunityAsUser : function(component) {
		var self = this,
				MyAccountId = component.get('v.MyAccountId'),
				CustomerAccountId = component.get('v.UserAccountId'),
				setupId = component.get('v.setupId'),
				userId = component.get('v.userId');

		self.navigateToUrl('/servlet/servlet.su?oid=' + MyAccountId + '&retURL=' + UserAccountId + '&sunetworkid=' + setupId + '&sunetworkuserid=' + userId);
	}

})

LoginToCommunityAsUser_Controller.cls

public with sharing class LoginToCommunityAsUser_Controller {
	@AuraEnabled
	public static String getOrgId() {
		return UserInfo.getOrganizationId().mid(0,15);
	}

	@AuraEnabled
	public static String getAccountId(String recordId) {
		String id = [select AccountId from Contact WHERE Id =  :recordId].AccountId;
		return id;
	}

	@AuraEnabled
	public static String getSetupId(String recordId) {
		Id userId = getUserId(recordId);
		return String.valueOf([SELECT NetworkId FROM NetworkMember WHERE MemberId = :userId AND Network.Status = 'Live' LIMIT 1]).mid(26,15);
	}

	@AuraEnabled
	public static String getUserId(String recordId) {
		String accountId = [SELECT AccountId FROM Contact WHERE Id = :recordId LIMIT 1].AccountId;
		return [SELECT Id FROM User WHERE AccountId = :accountId AND ContactId = :recordId LIMIT 1].Id;
	}
}

Now, all you have to do is drag your brand new component onto your Contact page in page page builder, and you should be good to roll. May this be as useful to you as it is to me.

7 Alternatives to Google Firing Mr. James Damore ✤

A white man lost his job this week after saying something stupid and predictably controversial, and the Internet lost its shit. How could Google fire a man for speaking his mind? It’s almost as if we all forgot that for most of us in the real world (read: outside Sillicon Valley pseudo utopic mindset), saying a stupid thing is very likely to get you fired. It’s probably the #1 cause of people getting fired, followed by, I dunno, doing drugs at work? I don’t really know, because everyone I know who’s been fired (as opposed to laid off) was fired, at least in part, for saying some stupid things.

So, in the spirit of reconcialiation, here are some alternatives Google should consider for next time:

  1. Openly and publically call one of your employees a sexist misogynist, put him on unpaid leave for a bit, and then move on as if nothing happened. I’m sure no one would treat him any differently and he wouldn’t have any problems working with or reporting to females in the future.

  2. Collectively stop sitting with him at the cafeteria. It’s not technically harassment, because it’s more like an absence of attention. This could not backfire in any way.

  3. What if Alphabet started Google 2 and moved everyone who wasn’t named James Damore to the new company, along with all of its assets? It’d be like the ultimate “No Homers” club, presuming they have at least one other James Damore on staff. James would get to pretend he got one heck of a promotion, and no one would ever have to talk to him again.

  4. Put him on an all-female team of developers. Start placing bets like it was a game of Survivor.

  5. Wage total psychological warfare by modifying every search result he ever looks up to slowly convince him that he is, in fact, a woman, no matter what his past experiences have told him. Eventually the cognitive dissonance would drive him mad, and he’d leave of his own accord.

  6. Promote him to a super secret R&D lab of one. Patent everything he ever does, but never ever let any of it go into production.

  7. Change his ringtone to “Damn it Jim! You’re an engineer, not a biologist.”

Mistakes I've Made: A Biography ✤

Ever feel like a total fuck up? I have. Almost every day in fact.

More recently, here are some profoundly stupid mistakes I’ve made in my short Salesforce Development career to date:

  1. I spent 7 full business days trying to figure out how to get images to upload to the Salesforce database from a Lightning Component. I rewrote it several dozen times in different ways. When it finally seemed to sort of work, we decided to upload to AWS instead. Easier and more cost effective in the long run. D’oh!
  2. I spent nearly 2 days trying to figure out to use a component a colleague had made rather than ask for help, because I was embarassed to admit I was stuck. D’oh!
  3. I wrote a super slick component and Apex class to query the Google Places API to auto fill an address form, only to see Salesforce announce they were releasing the same thing soon. Also I might have been able to get around the need to pipe the API through an Apex class if I’d RTFM’d.
  4. I’ve programmatically written half a dozen bits of functionality that were already available as drag and drop components. Oops.
  5. I’ve publicly reached out to other developers on Twitter and Stackexchange asking for help, outing my total n00b status.
  6. I’ve written SOQL queries within for loops within SOQL queries within for loops within… you get the picture. Holy governor limits, Batman.
  7. I’ve created massive methods of spaghetti code that I could no longer follow within just hours of creating it. Refactoring is fun, kids.

What’s my point in sharing these faux-pas? Simply this: development is messy. It’s never as good as we’d like it to be. We do embarrassing stuff all the time. There’s no such thing as genius programmers. Some of us are just better at hiding our mistakes than others.

State Obsolete ✤

What follows is a bit of speculative fiction, because why not?

In the late 2010s, cryptocurrencies like Bitcoin and Euthereum were dipping their toes into mainstream economics. For years, they had been dismissed by polite society as little more than a curiosity and something that criminals used to do their business.

How foolish we were.

In the end (or perhaps I should say: in the beginning), it wasn’t Bitcoin that took over the world. Instead, we had a plethora of currencies floating in different markets for different purposes. They were mostly interchangeable. But to discuss the cryptocurrency wars is to miss the larger culture war that was taking place. It was a war that would shape the economic, political, and social spheres forever, without firing a single shot.

The shift arguably began when young people started asking to get paid in crypto instead of hard currency. It was easier for them to use and the value kept climbing, which made saving much easier. Long attacked as “deflationary”, cryptocoins were infinitely divisible but extremely limited in supply. So, a $1 in coin today would easily double to $2 in just a few short months back then.

The gold rush mentality brought hordes of people to convert their real money for digital coin. As they did so, the value of “real” currency dropped, as the demand for it decreased.

The switch to cryptocoin was messy. While early adopters made a fortune, those late to the game found their life savings evaporate. It didn’t take long for everyone to jump on board, but the losses were horrific. Like those who didn’t survive financial crashes of the past, many took their own lives.

The bigger shift, though, would come to institutions.

The first institutions to feel the crunch were the banks.

As cryptocurrencies, by their very nature, did not allow for the “creation of money”, fractional reserve banking was not a viable option in the new financial order. While those who had the means did finish paying off their existing debts, the banks was severely limited in their ability to issue loans and collect interest. As the creation of money had long been the real source of the bank industry’s wealth, their only option was to raise interest rates. It wasn’t long before rates spiraled so out of control that no one was willing to pay.

The shift for them came faster than anyone had anticipated. As people withdrew their funds to purchase the more lucrative cryptocoin, a run-on-the-banks quickly occured. It was gradual at first, but when the first few banks started to fail, people rushed to withdraw their savings. Of course, due to fractional reserve banking, there was only enough for a fraction of the people. It was a house of cards, and the unimaginable happened. The banks failed. All of them.

As the banks failed, so did the system of credit they had built.

Next came the governments. Governments the world over had always relied on two primary mechanisms to fund their existence. The first was their control over the national currency. They could always print more money, regardless of how that devalued the money already in existence. It was a form of invisible taxation, but they called it inflation and told us it was for our own good.

The second mechanism was, of course, taxation itself. Income tax, sales tax, revenue tax, property tax… the list goes on. But most of these taxes depended on the government’s ability to monitor transactions. Without the ability to reliably know how much money was exchanging hands, it was difficult for them to know how much you owed them.

Most governments tried to crack down on cryptocurrencies for this very reason, but it was too late. The genie was out of the bottle, and there was no putting it back in.

Every day, as citizens moved more and more of their finances to anonymous and untraceable cryptocoin, government revenue decreased. As revenue decreased, they turned to lendors. But lendors – both banks and nation states alike – were in the same crunch, unable to help. Ironically, they attempted to appeal to the owners of cryptocurrencies to borrow from them. But it was plain as day that any coin lent to a government was never going to get repaid, and even if it did, the interest earned wouldn’t compare to the value of simply allowing your coin to appreciate in value.

As a result, public services got slashed. First, of course, was pensions and social aid. They’d wanted to take those away for years, anyway. Gone was the social safety net, no matter how much you, as a private citizen, had paid into it.

Then, infrastructure and investments. The government can’t invest what it doesn’t have.

Privatization was inevitable. It was also unofficial and gradual.

As public services degraded, those who had the means began investing in the services they wanted. Private police forces; private roads; private hospitals. Some of these were even illegal, but the state was too weak to do anything about it.

Eventually, one by one, the governments of the world failed. They became obsolete. The services people demanded of them were fulfilled by other, private players.

Many a would-be warlord tried to take their place, but found themselves in the same boat. People simply refused to value the old forms of currency that the warlords of the past could loot and horde. From cash to gold to diamonds and other rare metals, these were of no real value, because they were so easy to steal. Instead, people kept their wealth in crypto, away from prying eyes and out of reach of would-be thieves.

There was anarchy, absolutely. But there was no real power to fill the void. Power had always relied on wealth and violence – carrot and stick – to institute itself. Without the ability to monopolize wealth, violence was of limited use. The stick alone could not rally people to a cause.

It was a cruel reality, to be sure. A world where those who had, had everything. And those who didn’t, often might as well have not existed at all.

But for many places in the world, this was nothing new. On the African continent; South America; a good portion of Asia; and a larger chunk of “the West” than anyone liked to admit, most people had always had no one they could rely on. The social safety net was a phenomenon of Western of bureaucracy, and hardly universal.

For some, the new reality was absolutely crushing. They simply couldn’t make the shift. For many, though, the shift meant they were finally free to make their own destinies. Without government, there were no borders keeping them tied to unproductive land. No one to tell them they didn’t have the right to exploit the abundance of natural resources around the world.

No one to tell them “no”.

To be continued.

Code is not your friend. ✤

Hello world, and welcome to A Terrible Good: Software Development For Fun and Profit.

If you’ve been in software development for any length of time, you’ve surely succumbed to our most terrible disease: the tendency to see all problems as solvable by code. It’s a sort of myopia. The world becomes reduced to bits and bytes; zeroes and ones; mashed together with various logic operators to produce desired results.

Don’t believe me? Try talking to a non-coder and see how long it takes for their eyes to glaze over.

So that’s the downside: the tendency to lose touch, to see everything as a system, and to think code is the solution to all problems. (Even when the problem calls for a simple hammer.)

The upshot is that you and I have a terrific opportunity to do real good in the world – so long as we can step back and see the forest for the trees.

The key, I believe, is knowing, deep down inside, that code is not our friend.

Code is like fire. Used properly, it can power civilizations. Used improperly, we’ll bury ourselves in spaghetti code until we just hit the big delete key in the sky.

To paraphrase Einstein, we need as little code as possible, but no less.