Sitecore 9 locally without xDB

I wanted to to install Sitecore 9 with “CMS only” mode for local my environment. According to Sitecore documentation Sitecore recommends installing XP topology (Sitecore with xDB) for development. However, I am sitting at the customer and  using my customer license that runs only on CMS mode. For this I needed to use XM topology (Sitecore with only CMS features). The problem is that XM topology in the documentation comes only with scaled configuration. For development separated editorial and delivery environment is a bit overkill and Sitecore documentation does not tell how to install without it I had to write my custom install script.

There is tons of installation posts, just Google it but before starting to install I recommend reading through “Sitecore Experience Platform Installation Guide”. It’s PDF and rather confusing but keep in mind everything related to “XP” is not relevant (except Solr, you still need to install Solr).

So, follow documentation to configure SIF (Sitecore Installation Framework) and Solr. Then make installation script that looks something like this:

#define parameters 
$prefix = "sc9" 
$PSScriptRoot = "C:\sitecore\install\"
# $XConnectCollectionService = "$prefix.xconnect" 
$sitecoreSiteName = "$prefix.sc" 
$SolrUrl = "https://localhost:8983/solr" 
$SolrRoot = "C:\sitecore\solr-6.6.2\" 
$SolrService = "solr6" 
$SqlServer = "localhost" 
$SqlAdminUser = "sa" 
$SqlAdminPassword="YOURSQLPASS" 

 
#install solr cores for xdb 
$solrParams = 
@{     
    Path = "$PSScriptRoot\xconnect-solr.json"     
    SolrUrl = $SolrUrl     
    SolrRoot = $SolrRoot     
    SolrService = $SolrService     
    CorePrefix = $prefix 
} 
Install-SitecoreConfiguration @solrParams -Verbose 
 
#Install Sitecore instance

$sitecoreParams = @{
    Path = "$PSScriptRoot\sitecore-XM1-cm.json"
    Package = "$PSScriptRoot\Sitecore 9.0.1 rev. 171219 (OnPrem)_cm.scwdp.zip"
    LicenseFile = "$PSScriptRoot\license.xml"
    SqlDbPrefix = $prefix
    SqlServer = $SqlServer
    SqlAdminUser = $SqlAdminUser
    SqlAdminPassword = $SqlAdminPassword
    SolrCorePrefix = $prefix
    SolrUrl = $SolrUrl
    Sitename = $sitecoreSiteName
}
    
Install-SitecoreConfiguration @sitecoreParams

 

After set <add key=”role:define” value=”Standalone” /> in web.config.

 

I left Facebook

Joined:
Sunday, June 10, 2007 at 22:13
Closed:
Monday, March 27, 2018 at 18:00

I was in Facebook for 11 years. Though, I really did not use it much and that is the reason why I decided to delete the whole account. Soon enough, I probably join back to Facebook again since as a developer I often need to use their API.

Now I have more time for Reddit and Twitter…. :)

Cheatsheets – JavaScript

The source is https://github.com/LeCoupa/awesome-cheatsheets

/* *******************************************************************************************
 * GLOBAL OBJECTS > ARRAY
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
 * ******************************************************************************************* */


// Global object: properties
Array.length                                         // Reflects the number of elements in an array

// Global object: methods
Array.from(arrayLike[, mapFn[, thisArg]])            // Creates a new Array instance from an array-like or iterable object.
Array.isArray(obj)                                   // Returns true if a variable is an array, if not false.
Array.of(element0[, element1[, ...[, elementN]]])    // Creates a new Array instance with a variable number of arguments, regardless of number or type of the arguments.

// Instance: properties
arr.length                                           // Reflects the number of elements in an array.

// Instance: mutator methods
arr.copyWithin(target, start, end)                   // Copies a sequence of array elements within the array.
arr.fill(value, start, end)                          // Fills all the elements of an array from a start index to an end index with a static value.
arr.pop()                                            // Removes the last element from an array and returns that element.
arr.push([element1[, ...[, elementN]]])              // Adds one or more elements to the end of an array and returns the new length of the array.
arr.reverse()                                        // Reverses the order of the elements of an array in place — the first becomes the last, and the last becomes the first.
arr.shift()                                          // Removes the first element from an array and returns that element.
arr.sort()                                           // Sorts the elements of an array in place and returns the array.
array.splice(start, deleteCount, item1, item2, ...)  // Adds and/or removes elements from an array.
arr.unshift([element1[, ...[, elementN]]])           // Adds one or more elements to the front of an array and returns the new length of the array.

// Instance: accessor methods
arr.concat(value1[, value2[, ...[, valueN]]])        // Returns a new array comprised of this array joined with other array(s) and/or value(s).
arr.includes(searchElement, fromIndex)               // Determines whether an array contains a certain element, returning true or false as appropriate.
arr.indexOf(searchElement[, fromIndex])              // Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found.
arr.join(separator)                                  // Joins all elements of an array into a string.
arr.lastIndexOf(searchElement, fromIndex)            // Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found.
arr.slice(begin, end)                                // Extracts a section of an array and returns a new array.
arr.toString()                                       // Returns a string representing the array and its elements. Overrides the Object.prototype.toString() method.
arr.toLocaleString(locales, options)                 // Returns a localized string representing the array and its elements. Overrides the Object.prototype.toLocaleString() method.

// Instance: iteration methods
arr.entries()                                        // Returns a new Array Iterator object that contains the key/value pairs for each index in the array.
arr.every(callback[, thisArg])                       // Returns true if every element in this array satisfies the provided testing function.
arr.filter(callback[, thisArg])                      // Creates a new array with all of the elements of this array for which the provided filtering function returns true.
arr.find(callback[, thisArg])                        // Returns the found value in the array, if an element in the array satisfies the provided testing function or undefined if not found.
arr.findIndex(callback[, thisArg])                   // Returns the found index in the array, if an element in the array satisfies the provided testing function or -1 if not found.
arr.forEach(callback[, thisArg])                     // Calls a function for each element in the array.
arr.keys()                                           // Returns a new Array Iterator that contains the keys for each index in the array.
arr.map(callback[, initialValue])                    // Creates a new array with the results of calling a provided function on every element in this array.
arr.reduce(callback[, initialValue])                 // Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.
arr.reduceRight(callback[, initialValue])            // Apply a function against an accumulator and each value of the array (from right-to-left) as to reduce it to a single value.
arr.some(callback[, initialValue])                   // Returns true if at least one element in this array satisfies the provided testing function.
arr.values()                                         // Returns a new Array Iterator object that contains the values for each index in the array.
/* *******************************************************************************************
 * GLOBAL OBJECTS > ARRAY
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
 * ******************************************************************************************* */


// Global object: properties
Array.length                                         // Reflects the number of elements in an array

// Global object: methods
Array.from(arrayLike[, mapFn[, thisArg]])            // Creates a new Array instance from an array-like or iterable object.
Array.isArray(obj)                                   // Returns true if a variable is an array, if not false.
Array.of(element0[, element1[, ...[, elementN]]])    // Creates a new Array instance with a variable number of arguments, regardless of number or type of the arguments.

// Instance: properties
arr.length                                           // Reflects the number of elements in an array.

// Instance: mutator methods
arr.copyWithin(target, start, end)                   // Copies a sequence of array elements within the array.
arr.fill(value, start, end)                          // Fills all the elements of an array from a start index to an end index with a static value.
arr.pop()                                            // Removes the last element from an array and returns that element.
arr.push([element1[, ...[, elementN]]])              // Adds one or more elements to the end of an array and returns the new length of the array.
arr.reverse()                                        // Reverses the order of the elements of an array in place — the first becomes the last, and the last becomes the first.
arr.shift()                                          // Removes the first element from an array and returns that element.
arr.sort()                                           // Sorts the elements of an array in place and returns the array.
array.splice(start, deleteCount, item1, item2, ...)  // Adds and/or removes elements from an array.
arr.unshift([element1[, ...[, elementN]]])           // Adds one or more elements to the front of an array and returns the new length of the array.

// Instance: accessor methods
arr.concat(value1[, value2[, ...[, valueN]]])        // Returns a new array comprised of this array joined with other array(s) and/or value(s).
arr.includes(searchElement, fromIndex)               // Determines whether an array contains a certain element, returning true or false as appropriate.
arr.indexOf(searchElement[, fromIndex])              // Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found.
arr.join(separator)                                  // Joins all elements of an array into a string.
arr.lastIndexOf(searchElement, fromIndex)            // Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found.
arr.slice(begin, end)                                // Extracts a section of an array and returns a new array.
arr.toString()                                       // Returns a string representing the array and its elements. Overrides the Object.prototype.toString() method.
arr.toLocaleString(locales, options)                 // Returns a localized string representing the array and its elements. Overrides the Object.prototype.toLocaleString() method.

// Instance: iteration methods
arr.entries()                                        // Returns a new Array Iterator object that contains the key/value pairs for each index in the array.
arr.every(callback[, thisArg])                       // Returns true if every element in this array satisfies the provided testing function.
arr.filter(callback[, thisArg])                      // Creates a new array with all of the elements of this array for which the provided filtering function returns true.
arr.find(callback[, thisArg])                        // Returns the found value in the array, if an element in the array satisfies the provided testing function or undefined if not found.
arr.findIndex(callback[, thisArg])                   // Returns the found index in the array, if an element in the array satisfies the provided testing function or -1 if not found.
arr.forEach(callback[, thisArg])                     // Calls a function for each element in the array.
arr.keys()                                           // Returns a new Array Iterator that contains the keys for each index in the array.
arr.map(callback[, initialValue])                    // Creates a new array with the results of calling a provided function on every element in this array.
arr.reduce(callback[, initialValue])                 // Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.
arr.reduceRight(callback[, initialValue])            // Apply a function against an accumulator and each value of the array (from right-to-left) as to reduce it to a single value.
arr.some(callback[, initialValue])                   // Returns true if at least one element in this array satisfies the provided testing function.
arr.values()                                         // Returns a new Array Iterator object that contains the values for each index in the array.

After 10 years with in Mac I changed back to PC

In 2006 when Apple launched their first fully aluminium Macbook Pro I switched from IBM Lenovo Thinkpad to Apple camp. This was the time when I saw Windows was not going anywhere and Apple was the one that was changing the course of the web development tooling. After slowly switching everything I own from PC based tech to Apple-based tech 10 years ago, I can say without reservation; Jobs was bang-on here.

They’ve figured out how to make more money, but not how to make better products. Sure right now they are fine, but in 10 years? They very well might go the route of Xerox.

Apple is  incredibly successful currently and is still a dominant force in the tech market. Though Apple has had somewhat lackluster keynotes for their iDevices and Macs the past few years with very little innovation is seen with significantly higher price. And now in this past year we’ve seen a dongle future which no one was asking for.

I have never been particularly Apple or Microsoft fanboy but I have always wanted to have the best computer and software to work with. Although like most developers I do have soft spot to open platforms that allows me to configure my device to my needs. So, when Apple released Macbook Pros last autumn like many other Web Developers I started to search for alternative for it. I settled to Dell XPS 13 with touch screen but I waited 1 month so I could feel MacPro touchbar myself instead of reading reviews. When I had my hands on MacPro at the store I was ready for decision. I am buying Dell. I chose XPS with Windows because I am working quite a lot with .NET and I don’t like to boot virtual machine all the time like I did in Mac. But on hindsight I think I would have probably be happier with Linux as a host and Windows as virtual machine.

Dell Experience

My honeymoon lasted about ~3 weeks with Dell XPS. First thing I had problem with for Wireless. I started to loose wireless access and then suddenly sometimes computer freezed and crashed. But after couple of week I got bios and driver update and the problem disappeared. But then new problem occurred. When computer goes to sleep CPU jumps to 100% and never goes down. There is ngentask.exe that is ran by something that opens ngen.exe that is not dying. I have made custom .bat file that I run to kill it manually. These kind of problems I never had with Mac because yeah, Mac just works or it doesn’t work at all. Also, quite frankly I did not use to have many of these kind of issues with old Windows either. These driver and instability issues were kind of issues that I always had with Linux. But I have found workaround so now the machine is running fine.

Dell XPS is OK looking laptop I think. I think it is one of the best looking laptops that you can get but having it side-by-side with new MacBook Pro I think MacBook is prettier. But not a lot prettier. I think XPS comes close and the way Dell has changed themselves in recent years they might come up with something soon that might beat Apple on design even. That would be interesting power change. :)

Windows Experience

As coming from Macbook Air I would say Windows is good OS. Although, I am very familiar with Windows but not so much with Windows 10 and the whole metro “tile experience”. There are many things better on Windows but then some are worse. To me Windows 10 feels a bit clunky, metro UI and start menu is awful imho. I removed all Metro Apps it feels like old Yahoo Portal with tons of Gif animations when opening start menu with those apps. Window Management is fantastic Mac and Linux should just copy that 1-to-1. Opening apps like Windows key + just start to type is great, a bit like usage of Finder shortcut on Mac but on Windows typeahead makes ugly jumping as you type program or command. These small details makes Windows usage lesser experience than Mac. But Windows is OK, it is not bad. I miss in Mac more software than in Windows. The only thing that I really miss is Sketch -app on Mac. Everything else for me has (usually better) alternative on Windows.

One thing with Windows that I was positively surprised is touch screen. I assumed I would never use touch screen on laptop but I was wrong. I do use it a lot. It is great when showing something to someone on the screen, browsing internet casually etc…

Conclusion

Will I stay on PC? Probably yes, I don’t think I will be going back to Mac unless they come up with powerful workhorse Macbook Pro without touchbar so I can run Virtual machines with Windows 10 and SQL server. This is unlikely to happen though.

Will I stay on Windows? Probably no, I am quite sure I am going to Linux on the next laptop. If the amount of time that I have to spend on drivers and configuration is this much on Windows 10 then mind as well run light Linux setup and have virtual machines for working just like I had it previously on my Mac.

 

Setting up global constants on Angular 2 enviroment

Do you use different API calls on dev, test and production in your Angular 2 application?

If so, you can use CLI ‘./environments/’.  At build time, environments/environment will be replaced by environments/environment.dev.ts or environments/environment.prod.ts, depending on the current CLI environment. You can also add as many environments here as you like. Just remember to define them at ‘./angular-cli.json’.

To reference in your code just use:

import { environment } from ‘../environments/environment’;

And then simply declare and use:

environment: any = environment;

environment.APIURL; // URL to web API

 

 

Difference between Virtual Machine and Docker

Docker containers wrap a piece of software in a complete filesystem that contains everything needed to run: code, runtime, system tools, system libraries – anything that can be installed on a server. This guarantees that the software will always run the same, regardless of its environment.

This illustration Source: https://www.docker.com/what-docker shows quite well how it is different from normal Virtual Machine (OK, Hypervisor can be installed on bare metal/infrastructure so but the illustration does give an idea).

virtual-machine-compare-docker

A full virtualized system gets its own set of resources allocated to it, and does minimal sharing. You get more isolation, but it is much heavier (requires more resources). With docker you get less isolation, but the containers are lightweight (require fewer resources). So you could easily run thousands of containers on a host, and it won’t even blink.

There are pros and cons for each type of virtualized system. If you want full isolation with guaranteed resources, a full VM is the way to go. If you just want to isolate processes from each other and want to run a ton of them on a reasonably sized host, then Docker is your friend.

My Skype account was hacked, it was sending spam containing Baidu links

I consider myself quite “hack proof” when it comes to web. I use Password Manager, I don’t use same passwords (but I used to). I never open files that I receive in mail. If I need to do something really critical I have virtual machine that I boot up that runs plain Linux with no extras installed. But still I got hacked… how is this possible?

Background

Last Friday around 14:45 while working on my Mac, I suddenly started to get messages from many of my contacts saying: “What is this link?”, “Hi JP, long time…”
I started to look previous messages and I saw a link to Baidu. I panicked. I signed off from Skype immediately and started to think what the h…. has happen? My first thought was a malware. But I have not installed anything special recently. But I immediately started full virus scan and took computer out of web. I opened my Windows machine and started to Google answers. Strange thing was that I was not allowed to delete Baidu links from my message history. Usually in Skype I am able to delete messages I send. This sounded fishy as it looked like it is not actually “me” who send those messages.

So what happen?

After Googling I found online many comments and posts dating all the way back to 2015 having similar experience with Skype. One of the best threads I was able to find was in Skype forum in Security, Privacy, Trust and Safety -channel.

It turns out Skype and Microsoft are having a critical issue as hackers are able to log in into out Microsoft Accounts using Skype name and Password without Two-Factor-Authentication. This is for all “non merged” accounts (Remember, Microsoft bought Skype and then decided to merge logins with Microsoft). Skype login’s are added to the Microsoft account as a login option without informing people and “Enabled” it by default.

I was using my @outlook.com account to login to my Skype on my computers and phone. But there was still the original Skype username “jpkeisala” enabled with full access and I had not changed password of that username for ages. This same username used to be a username that I was using for many services back in the day. So I look at which sites has been hacked by https://haveibeenpwned.com/ and https://www.leakedsource.com/ and yes… Quite a few.

Ok, now I was sure that this is not malware but hacking. So I went to check https://account.live.com/Activity for susipcious activites and report to support page.

skype-hacked-from-buenos-aires
Bingo! I have not been Buenos Aires, Argentina. Someone is using my login.

So, now I have to change my password and find out how to avoid this in the future.

Solution

Based on my empirical investigation, you (probably) don’t have malware or virus, your username and password is hacked and spam links are sent from web and not from your computer. You need to reset password on Microsoft and deselect Skype name.

Secure your account

  1. Login into https://account.microsoft.com with your Microsoft Account
  2. Go to “Security and Privacy”
  3. Under “Account Security”, select “More security settings”
  4. Under “Sign-in preferences”, select “Change sign-in preferences”
  5. Deselect “Skype name”
  6. Press [Save]
  7. And if not already done, enable “Two-step verification”
  8. In https://account.microsoft.com/ Change your password.

Clean up spam messages

To clean up spam from your contact you can go to web.skype.com, it’s possible to delete messages there. I had ~200 contacts and I had to clean them up one by one. Phew…

I will update this post if I still have issues.

Headless CMS

I have been coining an idea for a while about headless CMS. Naturally, it turns out that my idea is not that unique. In fact there is already a startups like http://www.contentful.comhttp://www.prismic.iohttp://www.osmek.comhttp://www.cloudcms.comhttp://www.webhook.com far away on this development.
Idea of Headless CMS surfaced again when I have been looking these static site generators. I found couple of weeks ago Grav, Grav is no-db cms. Basically every page is created as markdown editor on a tree structure on the disk. Then the site runs on top of HTTPHeader generating routing based on the structure on the disk. Grav is built on Symfony (PHP). Benefits on this approach is to be able to provide base structure for a site using markdown that is very similar to static site generators but it can also extended by hooking to database for example if you run a pizzeria you may have “static” content on markdown files and booking a table functionality on database driven. It also has backoffice as a plugin, so you get admin where editor can manage markdown files. Naturally, pages are file based you can have backoffice anywhere and then just have runtime and markdown files deployed to live server. This makes it more secure.  Anyway, Grav is worth of checking out if you are interested to look “different” thinking how to create a CMS.
Anywhoooo… back to headless CMS. I was considering since the internet is built more and more from Web Components. How hard would it be to build in Angular2 based CMS that has no serverside techology dependencies, instead it runs solely on JSON api. Though, I do need some kind of JSON store like Firebase to keep things hooked together.

Application Pool Identity folder permissions in Sitecore

windows-server

ApplicationPoolIdentity is the best practice to use in IIS7. It is a dynamically created, unprivileged account. To add file system security for a particular application pool see IIS.net’s “Application Pool Identities”.

Here is a quick guide how to add rights to correct AppPool -profile on Windows Explorer

  1. Open Windows Explorer
  2. Select Sitecore installation directory.
  3. Right click the file and select “Properties”
  4. Select the “Security” tab
  5. Click the “Edit” and then “Add” button
  6. Click the “Locations” button and make sure you select thelocal machine. (Not the Windows domain if the server belongs to one.)
  7. Enter “IIS AppPool\Sitecore” in the “Enter the object names to select:” text box. (Don’t forget to change “Sitecore” here to whatever you named your application pool.)
  8. Click the “Check Names” button and click “OK”.

Refer to Sitecore Installation and Security guide for proper settings.