diceline-chartmagnifierquestion-marktwitter-whiteTwitter_Logo_Blue

Today I Learned

Remove a non-removable MDM profile from macOS without a complete wipe

Non-removable MDM profiles cannot officially removed without doing a full system wipe. This is a problem when you restore a system from Time Machine after you enrolled it into the MDM, as the MDM will break, leaving you unable to re-enroll the machine.

Here's how to remove a non-removable MDM profile

  1. Boot the Mac into Recovery Mode (hold down command+R during startup).
  2. Go to the Utilities menu and open Terminal and type: csrutil disable. This will disable SIP (System Integrity Protection).
  3. Reboot into the OS.
  4. Open the integrated terminal and type:
cd /var/db/ConfigurationProfiles
rm -rf *
mkdir Settings
touch Settings/.profilesAreInstalled
  1. Reboot.
  2. Boot the Mac into Recovery Mode (hold down command+R during startup).
  3. Go to the Utilities menu and open Terminal and type: csrutil enable. This will re-enable SIP.
  4. Reboot into the OS.

The profile will be now removed and you will be able to re-enroll the Mac to your MDM.

How to remove a VPN profile on a MDM enrolled macOS

Restoring from a Time Machine backup can create duplicate MDM VPN profiles.

To manually remove a profile on your macOS, follow these steps:

  • Go to System Preferences and select Profiles.
  • Delete the VPN profile, and enter the user password if requested.
  • Then, go to Network Connections.
  • If you see any connections which start with or include “VPN”, delete them.

Note

If the Button isn’t available,you have to use a terminal command to remove it. Open the integrated Terminal and type

networksetup -removenetworkservice "duplicateVPNProfile"

Using destructuring assignment to dynamically create new functions in JavaScript

// www.codewars.com/kata/525f3eda17c7cd9f9e000b39

const curry = (operand, operator) => (!operator) ? operand : operator(operand);

const [zero, one, two, three, four, five, six, seven, eight, nine] =
  [0,1,2,3,4,5,6,7,8,9].map(operand => ((operator) => curry(operand, operator)));

const plus = (first) => (second) => second + first;
const minus = (first) => (second) => second - first;
const times = (first) => (second) => second * first;
const dividedBy = (first) => (second) => Math.floor(second / first);

Prepare NuxtJS for static deployment

In order to deploy Nuxt as a static website you need to:

  1. Upgrade nuxt to 2.14.0
  2. Set target: 'static' in your nuxt.config.js
  3. Set fallback 404 page:generate: { fallback: '404.html' }
  4. Run nuxt generate

You then need to tell Nginx to properly handle slashes for subpages:


    location /.
    {
        # Remove trailing slash and redirect it
        rewrite ^(.+)/+$ $1 permanent;
        
        # Redirect index.html
        rewrite ^(.+)/index.html$ $1 permanent;
        
        # Serve folder path via index.html
        try_files $uri $uri/index.html =404;
        
        # Serve a custom static error page
        error_page 404 /404.html;
    }

Follow URL redirects from the Terminal

Sometimes you need to follow an url trough multiple redirects. I've created a simple script you can alias into your .bashrc or .zshrc file and then just use it as a regular shell command:

Add this line to .zshrc or .bashrc

# Follow URL
alias checkurl='_checkurl() { curl -v -L $1 2>&1 | egrep "^(> Host:|> GET|> Code|< HTTP|\* SSL)"}; _checkurl'

Then you can use it like so:

checkurl google.com

it will output this:

> GET / HTTP/1.1
> Host: google.com
< HTTP/1.1 301 Moved Permanently
> GET / HTTP/1.1
> Host: www.google.com
< HTTP/1.1 200 OK

Really useful when debugging URLs.

How to add dynamic images in NuxtJS & VueJS

Let's say you have a simple component in NuxtJS and VueJS, a static image for a blog post.

<template>
  <article class="post__image">
    <img class="image" src="~/assets/images/imageName.jpg" alt="post picture">
  </article>
</template>

Simple enough, right? But you don't want to have the same image for every blog post, so maybe you're trying to add it dynamically, getting the image name through a prop and using Vue's v-bind directive, like so:

<template>
  <article class="post__image">
    <img class="image" :src="`~/assets/images/${imageName}.jpg`" :alt="`${imageName} picture`">
  </article>
</template>

<script>
export default {
  name: 'PostImage',
  props: {
    imageName: String
  },
}
</script>

And then you notice that that doesn't work. But why? The vue syntax is correct, so what's the problem? Well, there's something else at play here.

Behind the scenes, webpack replaces the image path with a module request at build time. That's fine for static images, because their paths are known at build time, but for dynamic images it's a different story, as webpack can't know what their paths will evaluate to at run time, so that won't work.

The solution is to make a module request for the images, so that webpack can work its magic on them before loading them on the page. That's done by using require(...), with the correct image path.

So your images will have to be loaded like this:

<img 
    class="image" 
    :src="require(`~/assets/images/${this.imageName}.jpg`)" 
    :alt="`${imageName} picture`"
>

You could also clean that up a bit, and extract the require part into a computed property, for better readability:

<template>
  <article class="post__image">
    <img class="image" :src="imageSource" :alt="`${imageName} picture`">
  </article>
</template>

<script>
export default {
  name: 'PostWithImage',
  props: {
    imageName: String
  },
  computed: {
    imageSource() {
      return require(`~/assets/images/${this.imageName}.jpg`)
    },
  }
}
</script>

How to delete multiple databases using MYSQL

When you have to delete 100+ databases created by a botched deployment script you have a few options available:

1. Plain SQL

You'll have to run this query and then copy paste the result into a second query.


SELECT
	GROUP_CONCAT( CONCAT( 'DROP DATABASE `', SCHEMA_NAME, '`;' ) SEPARATOR ' ' ) AS DELETE_QUERY
FROM
	information_schema.SCHEMATA 
WHERE
	SCHEMA_NAME LIKE '{DBNAME}%'

2. Stored procedure

This allows you to create a stored procedure that will run your query in one go.

CREATE PROCEDURE clean () BEGIN

	SET @QUERY := (
		SELECT
			CONCAT( 'DROP DATABASE `', SCHEMA_NAME, '`;' ) 
		FROM
			`information_schema`.`SCHEMATA` 
		WHERE
			SCHEMA_NAME LIKE '{DBNAME}%' 
			LIMIT 1 
		);
	PREPARE stmt 
	FROM
		@QUERY;
	EXECUTE stmt;
	DEALLOCATE PREPARE stmt;
	
END;
CALL clean ();
DROP PROCEDURE clean;

vue-cli-service environment variables

While you can find detailed information in the official docs, I dare to spoil the fun for you:

1. All app variables are pulled in if they are prefixed with VUE_APP_.

Example: VUE_APP_API_URL.

You can now access the variables in your application like this: process.env.APP_URL.

2. All e2e variables are fetched if they are prefixed withCYPRESS_.

Example: CYPRESS_APP_URL.

You can now access the variables in your tests like this: Cypress.env('APP_URL').

Loop through a list of VueJS components

Ever wondered how you can loop through a list of VueJS components?

Let's say you have an array of components and you want to render them dynamically:

data() {
    return {
        components: ['ComponentOne', 'ComponentTwo', 'ComponentThree']       
    }
}

It's simple. We just need to use vue's dynamic component.

###Let's see how:

<ul>
    <li v-for="component, index in components" :key="index">
        <component :is="component"></component>
    </li>
</ul>

Just make sure to register all the used components where you need them.

How to use chmod to change permissions

For a long time I've been afraid of using the shell command chmod. That because I didn't understand how it works and I feared breaking things. Today though, I learned how easy it is actually. No, not to break things, but to use the chmod command.

A Unix system allows for multiple users with different access rights, which can be changed in the shell by using this command.

The permissions are for reading, writing and executing (rwx) and are expressed for all three types of users a file or folder has. It will come in the form of rwxrwxrwx where the first batch of three characters (rwx), belong to the owner, the second to the group, and the third to all the other users (owner/group/other).

Sure, (rwx rwx rwx) would mean that everybody has all the access rights to that particular file or folder. And we all know that's not a good idea. So, most often you'll see something like rw-r--r-- which means that only the owner has the right to read and write, while everybody else can only read that particular file.

Now onto chmod, which can be used with either a symbolic or a numeric notation for the access settings. You've probably seen somebody else type chmod 644 file_name on your computer, leaving you wondering about what that means.

That's the numeric notation.

If you think about the access rights as a series of bits, the whole thing would look like this:

rwx rwx rwx = 111 111 111
rw- r-- r-- = 110 100 100
rw- r-x --- = 110 101 000

That translates into

rwx rwx rwx = chmod 777
rw- r-- r-- = chmod 644
rw- r-x --- = chmod 650

because in binary notation:

100 = 4
101 = 5
110 = 6
111 = 7

And now you've got a simple rule on how to construct your chmod command depending on what permissions you need to set.

The rwxr--r-- access rights means chmod 744, rw-r----- is chmod 640, and so on.

Simple enough, right?