diff --git a/test/javascripts/acceptance/admin-user-badges-test.js.es6 b/test/javascripts/acceptance/admin-user-badges-test.js.es6
new file mode 100644
index 00000000000..135392a42d0
--- /dev/null
+++ b/test/javascripts/acceptance/admin-user-badges-test.js.es6
@@ -0,0 +1,9 @@
+import { acceptance } from "helpers/qunit-helpers";
+
+acceptance("Admin - Users Badges", { loggedIn: true });
+
+QUnit.test("lists badges", async assert => {
+  await visit("/admin/users/1/eviltrout/badges");
+
+  assert.ok(exists(`span[data-badge-name="Badge 8"]`));
+});
diff --git a/vendor/assets/javascripts/lodash.js b/vendor/assets/javascripts/lodash.js
index f5e6c650843..ff88ef8f68c 100644
--- a/vendor/assets/javascripts/lodash.js
+++ b/vendor/assets/javascripts/lodash.js
@@ -1,7 +1,7 @@
 /**
  * @license
  * Lodash (Custom Build) <https://lodash.com/>
- * Build: `lodash include="each,filter,map,range,first,isEmpty,chain,extend,every,omit,merge,union,sortBy,uniq,intersection,reject,compact,reduce,debounce,throttle,values,pick,keys,flatten,min,max,isArray,delay,isString,isEqual,without,invoke,clone,findIndex,find" minus="template" -d`
+ * Build: `lodash include="each,filter,map,range,first,isEmpty,chain,extend,every,omit,merge,union,sortBy,uniq,intersection,reject,compact,reduce,debounce,throttle,values,pick,keys,flatten,min,max,isArray,delay,isString,isEqual,without,invoke,clone,findIndex,find,groupBy" minus="template" -d`
  * Copyright JS Foundation and other contributors <https://js.foundation/>
  * Released under MIT license <https://lodash.com/license>
  * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
@@ -285,6 +285,27 @@
     return func.apply(thisArg, args);
   }
 
+  /**
+   * A specialized version of `baseAggregator` for arrays.
+   *
+   * @private
+   * @param {Array} [array] The array to iterate over.
+   * @param {Function} setter The function to set `accumulator` values.
+   * @param {Function} iteratee The iteratee to transform keys.
+   * @param {Object} accumulator The initial aggregated object.
+   * @returns {Function} Returns `accumulator`.
+   */
+  function arrayAggregator(array, setter, iteratee, accumulator) {
+    var index = -1,
+        length = array == null ? 0 : array.length;
+
+    while (++index < length) {
+      var value = array[index];
+      setter(accumulator, value, iteratee(value), array);
+    }
+    return accumulator;
+  }
+
   /**
    * A specialized version of `_.forEach` for arrays without support for
    * iteratee shorthands.
@@ -1794,6 +1815,24 @@
     return -1;
   }
 
+  /**
+   * Aggregates elements of `collection` on `accumulator` with keys transformed
+   * by `iteratee` and values set by `setter`.
+   *
+   * @private
+   * @param {Array|Object} collection The collection to iterate over.
+   * @param {Function} setter The function to set `accumulator` values.
+   * @param {Function} iteratee The iteratee to transform keys.
+   * @param {Object} accumulator The initial aggregated object.
+   * @returns {Function} Returns `accumulator`.
+   */
+  function baseAggregator(collection, setter, iteratee, accumulator) {
+    baseEach(collection, function(value, key, collection) {
+      setter(accumulator, value, iteratee(value), collection);
+    });
+    return accumulator;
+  }
+
   /**
    * The base implementation of `_.assign` without support for multiple sources
    * or `customizer` functions.
@@ -3451,6 +3490,23 @@
     return copyObject(source, getSymbolsIn(source), object);
   }
 
+  /**
+   * Creates a function like `_.groupBy`.
+   *
+   * @private
+   * @param {Function} setter The function to set accumulator values.
+   * @param {Function} [initializer] The accumulator object initializer.
+   * @returns {Function} Returns the new aggregator function.
+   */
+  function createAggregator(setter, initializer) {
+    return function(collection, iteratee) {
+      var func = isArray(collection) ? arrayAggregator : baseAggregator,
+          accumulator = initializer ? initializer() : {};
+
+      return func(collection, setter, getIteratee(iteratee, 2), accumulator);
+    };
+  }
+
   /**
    * Creates a function like `_.assign`.
    *
@@ -5621,6 +5677,37 @@
     return func(collection, getIteratee(iteratee, 3));
   }
 
+  /**
+   * Creates an object composed of keys generated from the results of running
+   * each element of `collection` thru `iteratee`. The order of grouped values
+   * is determined by the order they occur in `collection`. The corresponding
+   * value of each key is an array of elements responsible for generating the
+   * key. The iteratee is invoked with one argument: (value).
+   *
+   * @static
+   * @memberOf _
+   * @since 0.1.0
+   * @category Collection
+   * @param {Array|Object} collection The collection to iterate over.
+   * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
+   * @returns {Object} Returns the composed aggregate object.
+   * @example
+   *
+   * _.groupBy([6.1, 4.2, 6.3], Math.floor);
+   * // => { '4': [4.2], '6': [6.1, 6.3] }
+   *
+   * // The `_.property` iteratee shorthand.
+   * _.groupBy(['one', 'two', 'three'], 'length');
+   * // => { '3': ['one', 'two'], '5': ['three'] }
+   */
+  var groupBy = createAggregator(function(result, value, key) {
+    if (hasOwnProperty.call(result, key)) {
+      result[key].push(value);
+    } else {
+      baseAssignValue(result, key, [value]);
+    }
+  });
+
   /**
    * Creates an array of values by running each element in `collection` thru
    * `iteratee`. The iteratee is invoked with three arguments:
@@ -7581,6 +7668,7 @@
   lodash.delay = delay;
   lodash.filter = filter;
   lodash.flatten = flatten;
+  lodash.groupBy = groupBy;
   lodash.intersection = intersection;
   lodash.iteratee = iteratee;
   lodash.keys = keys;