diff --git a/apps/systemtags/appinfo/app.php b/apps/systemtags/appinfo/app.php
index d07902f777ff109eaa56c5be1d98709d44707929..d3886993f8fd3d894cc12c441d1863c7f755443b 100644
--- a/apps/systemtags/appinfo/app.php
+++ b/apps/systemtags/appinfo/app.php
@@ -28,6 +28,7 @@ $eventDispatcher->addListener(
 		\OC_Util::addVendorStyle('select2/select2');
 		\OCP\Util::addScript('select2-toggleselect');
 		\OCP\Util::addScript('oc-backbone-webdav');
+		\OCP\Util::addScript('systemtags/systemtags');
 		\OCP\Util::addScript('systemtags/systemtagmodel');
 		\OCP\Util::addScript('systemtags/systemtagsmappingcollection');
 		\OCP\Util::addScript('systemtags/systemtagscollection');
diff --git a/apps/systemtags/js/systemtagsinfoview.js b/apps/systemtags/js/systemtagsinfoview.js
index b1820bfcd91e7f36860ab2187cb4a7509e20c51f..2e808f9a84f80647d7a50ad9cdfa21f1ad7a64b8 100644
--- a/apps/systemtags/js/systemtagsinfoview.js
+++ b/apps/systemtags/js/systemtagsinfoview.js
@@ -9,6 +9,15 @@
  */
 
 (function(OCA) {
+
+	function modelToSelection(model) {
+		var data = model.toJSON();
+		if (!OC.isUserAdmin() && !data.userAssignable) {
+			data.locked = true;
+		}
+		return data;
+	}
+
 	/**
 	 * @class OCA.SystemTags.SystemTagsInfoView
 	 * @classdesc
@@ -36,8 +45,9 @@
 				multiple: true,
 				allowActions: true,
 				allowCreate: true,
+				isAdmin: OC.isUserAdmin(),
 				initSelection: function(element, callback) {
-					callback(self.selectedTagsCollection.toJSON());
+					callback(self.selectedTagsCollection.map(modelToSelection));
 				}
 			});
 
@@ -108,7 +118,7 @@
 				this.selectedTagsCollection.fetch({
 					success: function(collection) {
 						collection.fetched = true;
-						self._inputView.setData(collection.toJSON());
+						self._inputView.setData(collection.map(modelToSelection));
 						self.$el.removeClass('hidden');
 					}
 				});
diff --git a/apps/systemtags/tests/js/systemtagsinfoviewSpec.js b/apps/systemtags/tests/js/systemtagsinfoviewSpec.js
index 971ad8fc17e3ae0592a445033cee30552c392a6c..0fb4e7b22c2288f8d277a5ac256249b150f7cba9 100644
--- a/apps/systemtags/tests/js/systemtagsinfoviewSpec.js
+++ b/apps/systemtags/tests/js/systemtagsinfoviewSpec.js
@@ -20,13 +20,16 @@
 */
 
 describe('OCA.SystemTags.SystemTagsInfoView tests', function() {
+	var isAdminStub;
 	var view;
 
 	beforeEach(function() {
 		view = new OCA.SystemTags.SystemTagsInfoView();
 		$('#testArea').append(view.$el);
+		isAdminStub = sinon.stub(OC, 'isUserAdmin').returns(true);
 	});
 	afterEach(function() {
+		isAdminStub.restore();
 		view.remove();
 		view = undefined;
 	});
@@ -73,7 +76,7 @@ describe('OCA.SystemTags.SystemTagsInfoView tests', function() {
 			view = new OCA.SystemTags.SystemTagsInfoView();
 			view.selectedTagsCollection.add([
 				{id: '1', name: 'test1'},
-				{id: '3', name: 'test3'}
+				{id: '3', name: 'test3', userVisible: false, userAssignable: false}
 			]);
 
 			var callback = sinon.stub();
@@ -83,7 +86,31 @@ describe('OCA.SystemTags.SystemTagsInfoView tests', function() {
 			expect(callback.getCall(0).args[0]).toEqual([{
 				id: '1', name: 'test1', userVisible: true, userAssignable: true
 			}, {
-				id: '3', name: 'test3', userVisible: true, userAssignable: true
+				id: '3', name: 'test3', userVisible: false, userAssignable: false
+			}]);
+
+			inputViewSpy.restore();
+		});
+		it('sets locked flag on non-assignable tags when user is not an admin', function() {
+			isAdminStub.returns(false);
+
+			var inputViewSpy = sinon.spy(OC.SystemTags, 'SystemTagsInputField');
+			var element = $('<input type="hidden" val="1,3"/>');
+			view.remove();
+			view = new OCA.SystemTags.SystemTagsInfoView();
+			view.selectedTagsCollection.add([
+				{id: '1', name: 'test1'},
+				{id: '3', name: 'test3', userAssignable: false}
+			]);
+
+			var callback = sinon.stub();
+			inputViewSpy.getCall(0).args[0].initSelection(element, callback);
+
+			expect(callback.calledOnce).toEqual(true);
+			expect(callback.getCall(0).args[0]).toEqual([{
+				id: '1', name: 'test1', userVisible: true, userAssignable: true
+			}, {
+				id: '3', name: 'test3', userVisible: true, userAssignable: false, locked: true
 			}]);
 
 			inputViewSpy.restore();
diff --git a/core/css/systemtags.css b/core/css/systemtags.css
index 5c667e5454773bd6a6905b72aab4f4e4424e9395..d847baa680036c860b1aa2a0d4be0ec2e10e3e5c 100644
--- a/core/css/systemtags.css
+++ b/core/css/systemtags.css
@@ -69,6 +69,11 @@
 	margin: 0;
 	line-height: 20px;
 }
+
+.systemtags-select2-container .select2-choices .select2-search-choice.select2-locked .label {
+	font-style: italic;
+}
+
 .systemtags-select2-container .select2-choices .select2-search-choice-close {
 	display: none;
 }
diff --git a/core/js/systemtags/systemtagmodel.js b/core/js/systemtags/systemtagmodel.js
index e6014977d2ba6a325bd5d7d18059a8a1d106e0e9..62bf3a70084e93c0cd764221644679aae42bbeae 100644
--- a/core/js/systemtags/systemtagmodel.js
+++ b/core/js/systemtags/systemtagmodel.js
@@ -37,8 +37,8 @@
 			return {
 				id: data.id,
 				name: data.name,
-				userVisible: data.userVisible === '1',
-				userAssignable: data.userAssignable === '1'
+				userVisible: data.userVisible === true || data.userVisible === '1',
+				userAssignable: data.userAssignable === true || data.userAssignable === '1'
 			};
 		}
 	});
diff --git a/core/js/systemtags/systemtagsinputfield.js b/core/js/systemtags/systemtagsinputfield.js
index facacc50e22acddaf065a41c61a4bdba3fd47d99..b90ecbe426564dd2f644eddee4a5a6937835d75a 100644
--- a/core/js/systemtags/systemtagsinputfield.js
+++ b/core/js/systemtags/systemtagsinputfield.js
@@ -17,7 +17,11 @@
 	var RESULT_TEMPLATE =
 		'<span class="systemtags-item{{#if isNew}} new-item{{/if}}" data-id="{{id}}">' +
 		'    <span class="checkmark icon icon-checkmark"></span>' +
+		'{{#if isAdmin}}' +
+		'    <span class="label">{{{tagMarkup}}}</span>' +
+		'{{else}}' +
 		'    <span class="label">{{name}}</span>' +
+		'{{/if}}' +
 		'{{#allowActions}}' +
 		'    <span class="systemtags-actions">' +
 		'        <a href="#" class="rename icon icon-rename" title="{{renameTooltip}}"></a>' +
@@ -25,6 +29,14 @@
 		'{{/allowActions}}' +
 		'</span>';
 
+	var SELECTION_TEMPLATE =
+		'{{#if isAdmin}}' +
+		'    <span class="label">{{{tagMarkup}}}</span>' +
+		'{{else}}' +
+		'    <span class="label">{{name}}</span>' +
+		'{{/if}}' +
+		'<span class="comma">,&nbsp;</span>';
+
 	var RENAME_FORM_TEMPLATE =
 		'<form class="systemtags-rename-form">' +
 		'    <label class="hidden-visually" for="{{cid}}-rename-input">{{renameLabel}}</label>' +
@@ -63,6 +75,7 @@
 		 * @param {bool} [options.multiple=false] whether to allow selecting multiple tags
 		 * @param {bool} [options.allowActions=true] whether tags can be renamed/delete within the dropdown
 		 * @param {bool} [options.allowCreate=true] whether new tags can be created
+		 * @param {bool} [options.isAdmin=true] whether the user is an administrator
 		 * @param {Function} options.initSelection function to convert selection to data
 		 */
 		initialize: function(options) {
@@ -71,6 +84,7 @@
 			this._multiple = !!options.multiple;
 			this._allowActions = _.isUndefined(options.allowActions) || !!options.allowActions;
 			this._allowCreate = _.isUndefined(options.allowCreate) || !!options.allowCreate;
+			this._isAdmin = !!options.isAdmin;
 
 			if (_.isFunction(options.initSelection)) {
 				this._initSelection = options.initSelection;
@@ -223,9 +237,15 @@
 		_queryTagsAutocomplete: function(query) {
 			var self = this;
 			this.collection.fetch({
-				success: function() {
+				success: function(collection) {
+					var tagModels = collection.filterByName(query.term);
+					if (!self._isAdmin) {
+						tagModels = _.filter(tagModels, function(tagModel) {
+							return tagModel.get('userAssignable');
+						});
+					}
 					query.callback({
-						results: _.invoke(self.collection.filterByName(query.term), 'toJSON')
+						results: _.invoke(tagModels, 'toJSON')
 					});
 				}
 			});
@@ -247,7 +267,25 @@
 			}
 			return this._resultTemplate(_.extend({
 				renameTooltip: t('core', 'Rename'),
-				allowActions: this._allowActions
+				allowActions: this._allowActions,
+				tagMarkup: this._isAdmin ? OC.SystemTags.getDescriptiveTag(data)[0].innerHTML : null,
+				isAdmin: this._isAdmin
+			}, data));
+		},
+
+		/**
+		 * Formats a single selection item
+		 *
+		 * @param {Object} data data to format
+		 * @return {string} HTML markup
+		 */
+		_formatSelection: function(data) {
+			if (!this._selectionTemplate) {
+				this._selectionTemplate = Handlebars.compile(SELECTION_TEMPLATE);
+			}
+			return this._selectionTemplate(_.extend({
+				tagMarkup: this._isAdmin ? OC.SystemTags.getDescriptiveTag(data)[0].innerHTML : null,
+				isAdmin: this._isAdmin
 			}, data));
 		},
 
@@ -266,6 +304,8 @@
 				this._newTag = {
 					id: -1,
 					name: term,
+					userAssignable: true,
+					userVisible: true,
 					isNew: true
 				};
 			} else {
@@ -279,11 +319,20 @@
 			var self = this;
 			var ids = $(element).val().split(',');
 
+			function modelToSelection(model) {
+				var data = model.toJSON();
+				if (!self._isAdmin && !data.userAssignable) {
+					// lock static tags for non-admins
+					data.locked = true;
+				}
+				return data;
+			}
+
 			function findSelectedObjects(ids) {
 				var selectedModels = self.collection.filter(function(model) {
-					return ids.indexOf(model.id) >= 0;
+					return ids.indexOf(model.id) >= 0 && (self._isAdmin || model.get('userVisible'));
 				});
-				return _.invoke(selectedModels, 'toJSON');
+				return _.map(selectedModels, modelToSelection);
 			}
 
 			this.collection.fetch({
@@ -316,10 +365,7 @@
 				},
 				initSelection: _.bind(this._initSelection, this),
 				formatResult: _.bind(this._formatDropDownResult, this),
-				formatSelection: function(tag) {
-					return '<span class="label">' + escapeHTML(tag.name) + '</span>' +
-						'<span class="comma">,&nbsp;</span>';
-				},
+				formatSelection: _.bind(this._formatSelection, this),
 				createSearchChoice: this._allowCreate ? _.bind(this._createSearchChoice, this) : undefined,
 				sortResults: function(results) {
 					var selectedItems = _.pluck(self.$tagsField.select2('data'), 'id');
diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js
index d1c7873f0eac81d62722598dd133cf05c81d0464..d13691845a7d4ec9a0d3724d58691e7e43bfac46 100644
--- a/core/js/tests/specHelper.js
+++ b/core/js/tests/specHelper.js
@@ -86,6 +86,7 @@ window.firstDay = 0;
 // setup dummy webroots
 /* jshint camelcase: false */
 window.oc_debug = true;
+window.oc_isadmin = false;
 // FIXME: oc_webroot is supposed to be only the path!!!
 window.oc_webroot = location.href + '/';
 window.oc_appswebroots = {
diff --git a/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js b/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js
index dc8d2ec82ff638cbd1d93bd7a96f22cf03f64b45..07e926cd2a9ba34553a2c116573be6544b5df80d 100644
--- a/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js
+++ b/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js
@@ -27,8 +27,6 @@ describe('OC.SystemTags.SystemTagsInputField tests', function() {
 		select2Stub = sinon.stub($.fn, 'select2');
 		select2Stub.returnsThis();
 		$('#testArea').append($container);
-		view = new OC.SystemTags.SystemTagsInputField();
-		$container.append(view.$el);
 	});
 	afterEach(function() {
 		select2Stub.restore();
@@ -36,273 +34,384 @@ describe('OC.SystemTags.SystemTagsInputField tests', function() {
 		view.remove();
 		view = undefined;
 	});
-	describe('rendering', function() {
-		beforeEach(function() {
-			view.render();
-		});
-		it('calls select2 on rendering', function() {
-			expect(view.$el.find('input[name=tags]').length).toEqual(1);
-			expect(select2Stub.called).toEqual(true);
-		});
-		it('formatResult renders rename button', function() {
-			var opts = select2Stub.getCall(0).args[0];
-			var $el = $(opts.formatResult({id: '1', name: 'test'}));
-			expect($el.find('.label').text()).toEqual('test');
-			expect($el.find('.rename').length).toEqual(1);
-		});
-	});
-	describe('initSelection', function() {
-		var fetchStub;
-		var testTags;
+
+	describe('general behavior', function() {
+		var $dropdown;
 
 		beforeEach(function() {
-			fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch');
-			testTags = [
-				new OC.SystemTags.SystemTagModel({id: '1', name: 'test1'}),
-				new OC.SystemTags.SystemTagModel({id: '2', name: 'test2'}),
-				new OC.SystemTags.SystemTagModel({id: '3', name: 'test3'}),
-			];
-			view.render();
-		});
-		afterEach(function() {
-			fetchStub.restore();
-		});
-		it('grabs values from the full collection', function() {
-			var $el = view.$el.find('input');
-			$el.val('1,3');
-			var opts = select2Stub.getCall(0).args[0];
-			var callback = sinon.stub();
-			opts.initSelection($el, callback);
-
-			expect(fetchStub.calledOnce).toEqual(true);
-			view.collection.add(testTags);
-			fetchStub.yieldTo('success', view.collection);
-
-			expect(callback.calledOnce).toEqual(true);
-			var models = callback.getCall(0).args[0];
-			expect(models.length).toEqual(2);
-			expect(models[0].id).toEqual('1');
-			expect(models[0].name).toEqual('test1');
-			expect(models[1].id).toEqual('3');
-			expect(models[1].name).toEqual('test3');
-		});
-	});
-	describe('tag selection', function() {
-		beforeEach(function() {
+			view = new OC.SystemTags.SystemTagsInputField();
+			$('.testInputContainer').append(view.$el);
+			$dropdown = $('<div class="select2-dropdown"></div>');
+			select2Stub.withArgs('dropdown').returns($dropdown);
+			$('#testArea').append($dropdown);
+
 			view.render();
-			var $el = view.$el.find('input');
-			$el.val('1');
-
-			view.collection.add([
-				new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}),
-				new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}),
-				new OC.SystemTags.SystemTagModel({id: '3', name: 'abd'}),
-			]);
-		});
-		afterEach(function() {
 		});
-		it('does not create dummy tag when user types non-matching name', function() {
-			var opts = select2Stub.getCall(0).args[0];
-			var result = opts.createSearchChoice('abc');
-			expect(result).not.toBeDefined();
-		});
-		it('creates dummy tag when user types non-matching name', function() {
-			var opts = select2Stub.getCall(0).args[0];
-			var result = opts.createSearchChoice('abnew');
-			expect(result.id).toEqual(-1);
-			expect(result.name).toEqual('abnew');
-			expect(result.isNew).toEqual(true);
+		describe('rendering', function() {
+			it('calls select2 on rendering', function() {
+				expect(view.$el.find('input[name=tags]').length).toEqual(1);
+				expect(select2Stub.called).toEqual(true);
+			});
+			it('formatResult renders rename button', function() {
+				var opts = select2Stub.getCall(0).args[0];
+				var $el = $(opts.formatResult({id: '1', name: 'test'}));
+				expect($el.find('.rename').length).toEqual(1);
+			});
 		});
-		it('creates the real tag and fires select event after user selects the dummy tag', function() {
-			var selectHandler = sinon.stub();
-			view.on('select', selectHandler);
-			var createStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'create');
-			view.$el.find('input').trigger(new $.Event('select2-selecting', {
-				object: {
-					id: -1,
-					name: 'newname',
-					isNew: true
-				}
-			}));
-
-			expect(createStub.calledOnce).toEqual(true);
-			expect(createStub.getCall(0).args[0]).toEqual({
-				name: 'newname',
-				userVisible: true,
-				userAssignable: true
+		describe('tag selection', function() {
+			beforeEach(function() {
+				var $el = view.$el.find('input');
+				$el.val('1');
+
+				view.collection.add([
+					new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}),
+					new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}),
+					new OC.SystemTags.SystemTagModel({id: '3', name: 'abd', userAssignable: false}),
+				]);
 			});
-
-			var newModel = new OC.SystemTags.SystemTagModel({
-				id: '123',
-				name: 'newname',
-				userVisible: true,
-				userAssignable: true
+			it('does not create dummy tag when user types non-matching name', function() {
+				var opts = select2Stub.getCall(0).args[0];
+				var result = opts.createSearchChoice('abc');
+				expect(result).not.toBeDefined();
 			});
+			it('creates dummy tag when user types non-matching name', function() {
+				var opts = select2Stub.getCall(0).args[0];
+				var result = opts.createSearchChoice('abnew');
+				expect(result.id).toEqual(-1);
+				expect(result.name).toEqual('abnew');
+				expect(result.isNew).toEqual(true);
+				expect(result.userVisible).toEqual(true);
+				expect(result.userAssignable).toEqual(true);
+			});
+			it('creates the real tag and fires select event after user selects the dummy tag', function() {
+				var selectHandler = sinon.stub();
+				view.on('select', selectHandler);
+				var createStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'create');
+				view.$el.find('input').trigger(new $.Event('select2-selecting', {
+					object: {
+						id: -1,
+						name: 'newname',
+						isNew: true
+					}
+				}));
+
+				expect(createStub.calledOnce).toEqual(true);
+				expect(createStub.getCall(0).args[0]).toEqual({
+					name: 'newname',
+					userVisible: true,
+					userAssignable: true
+				});
 
-			// not called yet
-			expect(selectHandler.notCalled).toEqual(true);
-
-			select2Stub.withArgs('data').returns([{
-				id: '1',
-				name: 'abc'
-			}]);
+				var newModel = new OC.SystemTags.SystemTagModel({
+					id: '123',
+					name: 'newname',
+					userVisible: true,
+					userAssignable: true
+				});
 
-			createStub.yieldTo('success', newModel);
+				// not called yet
+				expect(selectHandler.notCalled).toEqual(true);
 
-			expect(select2Stub.lastCall.args[0]).toEqual('data');
-			expect(select2Stub.lastCall.args[1]).toEqual([{
+				select2Stub.withArgs('data').returns([{
 					id: '1',
 					name: 'abc'
-				},
-				newModel.toJSON()
-			]);
+				}]);
 
-			expect(selectHandler.calledOnce).toEqual(true);
-			expect(selectHandler.getCall(0).args[0]).toEqual(newModel);
+				createStub.yieldTo('success', newModel);
 
-			createStub.restore();
-		});
-		it('triggers select event after selecting an existing tag', function() {
-			var selectHandler = sinon.stub();
-			view.on('select', selectHandler);
-			view.$el.find('input').trigger(new $.Event('select2-selecting', {
-				object: {
-					id: '2',
-					name: 'def'
-				}
-			}));
-
-			expect(selectHandler.calledOnce).toEqual(true);
-			expect(selectHandler.getCall(0).args[0]).toEqual(view.collection.get('2'));
-		});
-		it('triggers deselect event after deselecting an existing tag', function() {
-			var selectHandler = sinon.stub();
-			view.on('deselect', selectHandler);
-			view.$el.find('input').trigger(new $.Event('select2-removing', {
-				choice: {
-					id: '2',
-					name: 'def'
-				}
-			}));
-
-			expect(selectHandler.calledOnce).toEqual(true);
-			expect(selectHandler.getCall(0).args[0]).toEqual('2');
-		});
-	});
-	describe('autocomplete', function() {
-		var fetchStub, opts;
+				expect(select2Stub.lastCall.args[0]).toEqual('data');
+				expect(select2Stub.lastCall.args[1]).toEqual([{
+						id: '1',
+						name: 'abc'
+					},
+					newModel.toJSON()
+				]);
 
-		beforeEach(function() {
-			fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch');
-			view.render();
-			opts = select2Stub.getCall(0).args[0];
+				expect(selectHandler.calledOnce).toEqual(true);
+				expect(selectHandler.getCall(0).args[0]).toEqual(newModel);
 
-			view.collection.add([
-				new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}),
-				new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}),
-				new OC.SystemTags.SystemTagModel({id: '3', name: 'abd'}),
-			]);
-		});
-		afterEach(function() {
-			fetchStub.restore();
-		});
-		it('completes results', function() {
-			var callback = sinon.stub();
-			opts.query({
-				term: 'ab',
-			   	callback: callback
+				createStub.restore();
+			});
+			it('triggers select event after selecting an existing tag', function() {
+				var selectHandler = sinon.stub();
+				view.on('select', selectHandler);
+				view.$el.find('input').trigger(new $.Event('select2-selecting', {
+					object: {
+						id: '2',
+						name: 'def'
+					}
+				}));
+
+				expect(selectHandler.calledOnce).toEqual(true);
+				expect(selectHandler.getCall(0).args[0]).toEqual(view.collection.get('2'));
+			});
+			it('triggers deselect event after deselecting an existing tag', function() {
+				var selectHandler = sinon.stub();
+				view.on('deselect', selectHandler);
+				view.$el.find('input').trigger(new $.Event('select2-removing', {
+					choice: {
+						id: '2',
+						name: 'def'
+					}
+				}));
+
+				expect(selectHandler.calledOnce).toEqual(true);
+				expect(selectHandler.getCall(0).args[0]).toEqual('2');
 			});
-			expect(fetchStub.calledOnce).toEqual(true);
-
-			fetchStub.yieldTo('success', view.collection);
-
-			expect(callback.calledOnce).toEqual(true);
-			expect(callback.getCall(0).args[0].results).toEqual([
-				{
-					id: '1',
-				   	name: 'abc',
-				   	userVisible: true,
-					userAssignable: true
-				},
-				{
-					id: '3',
-				   	name: 'abd',
-				   	userVisible: true,
-					userAssignable: true
-				}
-			]);
 		});
-	});
-	describe('tag actions', function() {
-		var $dropdown, opts;
+		describe('tag actions', function() {
+			var opts;
 
-		beforeEach(function() {
-			$dropdown = $('<div class="select2-dropdown"></div>');
-			select2Stub.withArgs('dropdown').returns($dropdown);
-			$('#testArea').append($dropdown);
+			beforeEach(function() {
 
-			view.render();
+				opts = select2Stub.getCall(0).args[0];
 
-			opts = select2Stub.getCall(0).args[0];
+				view.collection.add([
+					new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}),
+				]);
 
-			view.collection.add([
-				new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}),
-			]);
+				$dropdown.append(opts.formatResult(view.collection.get('1').toJSON()));
 
-			$dropdown.append(opts.formatResult(view.collection.get('1').toJSON()));
+			});
+			it('displays rename form when clicking rename', function() {
+				$dropdown.find('.rename').mouseup();
+				expect($dropdown.find('form.systemtags-rename-form').length).toEqual(1);
+				expect($dropdown.find('form.systemtags-rename-form input').val()).toEqual('abc');
+			});
+			it('renames model and submits change when submitting form', function() {
+				var saveStub = sinon.stub(OC.SystemTags.SystemTagModel.prototype, 'save');
+				$dropdown.find('.rename').mouseup();
+				$dropdown.find('form input').val('abc_renamed');
+				$dropdown.find('form').trigger(new $.Event('submit'));
 
-		});
-		afterEach(function() {
-		});
-		it('displays rename form when clicking rename', function() {
-			$dropdown.find('.rename').mouseup();
-			expect($dropdown.find('form.systemtags-rename-form').length).toEqual(1);
-			expect($dropdown.find('form.systemtags-rename-form input').val()).toEqual('abc');
-		});
-		it('renames model and submits change when submitting form', function() {
-			var saveStub = sinon.stub(OC.SystemTags.SystemTagModel.prototype, 'save');
-			$dropdown.find('.rename').mouseup();
-			$dropdown.find('form input').val('abc_renamed');
-			$dropdown.find('form').trigger(new $.Event('submit'));
+				expect(saveStub.calledOnce).toEqual(true);
+				expect(saveStub.getCall(0).args[0]).toEqual({'name': 'abc_renamed'});
 
-			expect(saveStub.calledOnce).toEqual(true);
-			expect(saveStub.getCall(0).args[0]).toEqual({'name': 'abc_renamed'});
+				expect($dropdown.find('.label').text()).toEqual('abc_renamed');
+				expect($dropdown.find('form').length).toEqual(0);
 
-			expect($dropdown.find('.label').text()).toEqual('abc_renamed');
-			expect($dropdown.find('form').length).toEqual(0);
+				saveStub.restore();
+			});
+			it('deletes model and submits change when clicking delete', function() {
+				var destroyStub = sinon.stub(OC.SystemTags.SystemTagModel.prototype, 'destroy');
 
-			saveStub.restore();
-		});
-		it('deletes model and submits change when clicking delete', function() {
-			var destroyStub = sinon.stub(OC.SystemTags.SystemTagModel.prototype, 'destroy');
+				expect($dropdown.find('.delete').length).toEqual(0);
+				$dropdown.find('.rename').mouseup();
+				// delete button appears
+				expect($dropdown.find('.delete').length).toEqual(1);
+				$dropdown.find('.delete').mouseup();
 
-			expect($dropdown.find('.delete').length).toEqual(0);
-			$dropdown.find('.rename').mouseup();
-			// delete button appears
-			expect($dropdown.find('.delete').length).toEqual(1);
-			$dropdown.find('.delete').mouseup();
+				expect(destroyStub.calledOnce).toEqual(true);
+				expect(destroyStub.calledOn(view.collection.get('1')));
 
-			expect(destroyStub.calledOnce).toEqual(true);
-			expect(destroyStub.calledOn(view.collection.get('1')));
+				destroyStub.restore();
+			});
+		});
+		describe('setting data', function() {
+			it('sets value when calling setValues', function() {
+				var vals = ['1', '2'];
+				view.setValues(vals);
+				expect(select2Stub.lastCall.args[0]).toEqual('val');
+				expect(select2Stub.lastCall.args[1]).toEqual(vals);
+			});
+			it('sets data when calling setData', function() {
+				var vals = [{id: '1', name: 'test1'}, {id: '2', name: 'test2'}];
+				view.setData(vals);
+				expect(select2Stub.lastCall.args[0]).toEqual('data');
+				expect(select2Stub.lastCall.args[1]).toEqual(vals);
+			});
+		});
+	});
 
-			destroyStub.restore();
+	describe('as admin', function() {
+		beforeEach(function() {
+			view = new OC.SystemTags.SystemTagsInputField({
+				isAdmin: true
+			});
+			view.render();
+			$('.testInputContainer').append(view.$el);
+		});
+		it('formatResult renders tag name with visibility', function() {
+			var opts = select2Stub.getCall(0).args[0];
+			var $el = $(opts.formatResult({id: '1', name: 'test', userVisible: false, userAssignable: false}));
+			expect($el.find('.label').text()).toEqual('test (invisible, not assignable)');
+		});
+		it('formatSelection renders tag name with visibility', function() {
+			var opts = select2Stub.getCall(0).args[0];
+			var $el = $(opts.formatSelection({id: '1', name: 'test', userVisible: false, userAssignable: false}));
+			expect($el.text().trim()).toEqual('test (invisible, not assignable),');
+		});
+		describe('initSelection', function() {
+			var fetchStub;
+			var testTags;
+
+			beforeEach(function() {
+				fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch');
+				testTags = [
+					new OC.SystemTags.SystemTagModel({id: '1', name: 'test1'}),
+					new OC.SystemTags.SystemTagModel({id: '2', name: 'test2'}),
+					new OC.SystemTags.SystemTagModel({id: '3', name: 'test3', userAssignable: false}),
+				];
+			});
+			afterEach(function() {
+				fetchStub.restore();
+			});
+			it('grabs values from the full collection', function() {
+				var $el = view.$el.find('input');
+				$el.val('1,3');
+				var opts = select2Stub.getCall(0).args[0];
+				var callback = sinon.stub();
+				opts.initSelection($el, callback);
+
+				expect(fetchStub.calledOnce).toEqual(true);
+				view.collection.add(testTags);
+				fetchStub.yieldTo('success', view.collection);
+
+				expect(callback.calledOnce).toEqual(true);
+				var models = callback.getCall(0).args[0];
+				expect(models.length).toEqual(2);
+				expect(models[0].id).toEqual('1');
+				expect(models[0].name).toEqual('test1');
+				expect(models[1].id).toEqual('3');
+				expect(models[1].name).toEqual('test3');
+			});
+		});
+		describe('autocomplete', function() {
+			var fetchStub, opts;
+
+			beforeEach(function() {
+				fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch');
+				opts = select2Stub.getCall(0).args[0];
+
+				view.collection.add([
+					new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}),
+					new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}),
+					new OC.SystemTags.SystemTagModel({id: '3', name: 'abd', userAssignable: false}),
+				]);
+			});
+			afterEach(function() {
+				fetchStub.restore();
+			});
+			it('completes results', function() {
+				var callback = sinon.stub();
+				opts.query({
+					term: 'ab',
+					callback: callback
+				});
+				expect(fetchStub.calledOnce).toEqual(true);
+
+				fetchStub.yieldTo('success', view.collection);
+
+				expect(callback.calledOnce).toEqual(true);
+				expect(callback.getCall(0).args[0].results).toEqual([
+					{
+						id: '1',
+						name: 'abc',
+						userVisible: true,
+						userAssignable: true
+					},
+					{
+						id: '3',
+						name: 'abd',
+						userVisible: true,
+						userAssignable: false
+					}
+				]);
+			});
 		});
 	});
-	describe('setting data', function() {
+
+	describe('as user', function() {
 		beforeEach(function() {
+			view = new OC.SystemTags.SystemTagsInputField({
+				isAdmin: false
+			});
 			view.render();
+			$('.testInputContainer').append(view.$el);
 		});
-		it('sets value when calling setValues', function() {
-			var vals = ['1', '2'];
-			view.setValues(vals);
-			expect(select2Stub.lastCall.args[0]).toEqual('val');
-			expect(select2Stub.lastCall.args[1]).toEqual(vals);
+		it('formatResult renders tag name only', function() {
+			var opts = select2Stub.getCall(0).args[0];
+			var $el = $(opts.formatResult({id: '1', name: 'test'}));
+			expect($el.find('.label').text()).toEqual('test');
+		});
+		it('formatSelection renders tag name only', function() {
+			var opts = select2Stub.getCall(0).args[0];
+			var $el = $(opts.formatSelection({id: '1', name: 'test'}));
+			expect($el.text().trim()).toEqual('test,');
+		});
+		describe('initSelection', function() {
+			var fetchStub;
+			var testTags;
+
+			beforeEach(function() {
+				fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch');
+				testTags = [
+					new OC.SystemTags.SystemTagModel({id: '1', name: 'test1'}),
+					new OC.SystemTags.SystemTagModel({id: '2', name: 'test2'}),
+					new OC.SystemTags.SystemTagModel({id: '3', name: 'test3', userAssignable: false}),
+				];
+				view.render();
+			});
+			afterEach(function() {
+				fetchStub.restore();
+			});
+			it('grabs values from the full collection', function() {
+				var $el = view.$el.find('input');
+				$el.val('1,3');
+				var opts = select2Stub.getCall(0).args[0];
+				var callback = sinon.stub();
+				opts.initSelection($el, callback);
+
+				expect(fetchStub.calledOnce).toEqual(true);
+				view.collection.add(testTags);
+				fetchStub.yieldTo('success', view.collection);
+
+				expect(callback.calledOnce).toEqual(true);
+				var models = callback.getCall(0).args[0];
+				expect(models.length).toEqual(2);
+				expect(models[0].id).toEqual('1');
+				expect(models[0].name).toEqual('test1');
+				expect(models[1].id).toEqual('3');
+				expect(models[1].name).toEqual('test3');
+			});
 		});
-		it('sets data when calling setData', function() {
-			var vals = [{id: '1', name: 'test1'}, {id: '2', name: 'test2'}];
-			view.setData(vals);
-			expect(select2Stub.lastCall.args[0]).toEqual('data');
-			expect(select2Stub.lastCall.args[1]).toEqual(vals);
+		describe('autocomplete', function() {
+			var fetchStub, opts;
+
+			beforeEach(function() {
+				fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch');
+				view.render();
+				opts = select2Stub.getCall(0).args[0];
+
+				view.collection.add([
+					new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}),
+					new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}),
+					new OC.SystemTags.SystemTagModel({id: '3', name: 'abd', userAssignable: false}),
+				]);
+			});
+			afterEach(function() {
+				fetchStub.restore();
+			});
+			it('completes results excluding non-assignable tags', function() {
+				var callback = sinon.stub();
+				opts.query({
+					term: 'ab',
+					callback: callback
+				});
+				expect(fetchStub.calledOnce).toEqual(true);
+
+				fetchStub.yieldTo('success', view.collection);
+
+				expect(callback.calledOnce).toEqual(true);
+				expect(callback.getCall(0).args[0].results).toEqual([
+					{
+						id: '1',
+						name: 'abc',
+						userVisible: true,
+						userAssignable: true
+					}
+				]);
+			});
 		});
 	});
 });