diff --git a/lib/private/App/AppStore/Manager.php b/lib/private/App/AppStore/Manager.php
index 1c7f09a817eb315d5d2da588752ccc4988453af2..4498918da70497c167931d2317fe6fe10042cea9 100644
--- a/lib/private/App/AppStore/Manager.php
+++ b/lib/private/App/AppStore/Manager.php
@@ -29,10 +29,13 @@ use OC\App\AppStore\Fetcher\AppFetcher;
 class Manager {
 
 	public function __construct(AppFetcher $appFetcher) {
-		$this->apps = $appFetcher->get();
+		$apps = $appFetcher->get();
+		foreach ($apps as $app) {
+			$this->apps[$app['id']] = $app;
+		}
 	}
 
 	public function getApp(string $appId) {
-		return $this->apps;
+		return $this->apps[$appId];
 	}
 }
\ No newline at end of file
diff --git a/settings/Controller/AppSettingsController.php b/settings/Controller/AppSettingsController.php
index ac6e5d1850d10258c2f39a01e924af85fce11ec4..a44a252a747644397b49166ecc07fb7e53d3a19c 100644
--- a/settings/Controller/AppSettingsController.php
+++ b/settings/Controller/AppSettingsController.php
@@ -334,12 +334,12 @@ class AppSettingsController extends Controller {
 	 */
 	public function listApps($category = '') {
 		$appClass = new \OC_App();
+		$manager = \OC::$server->query(\OC\App\AppStore\Manager::class);
 
 		switch ($category) {
 			// installed apps
 			case 'installed':
 				$apps = $appClass->listAllApps();
-
 				foreach($apps as $key => $app) {
 					$newVersion = $this->installer->isUpdateAvailable($app['id']);
 					$apps[$key]['update'] = $newVersion;
@@ -481,6 +481,14 @@ class AppSettingsController extends Controller {
 			return $app;
 		}, $apps);
 
+		// Add app store dump for app to data
+		$apps = array_map(function($appData) use ($manager) {
+			$appStoreData = $manager->getApp($appData['id']);
+			$appData['appstoreData'] = $appStoreData;
+			$appData['preview'] = isset($appStoreData['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/'.base64_encode($appStoreData['screenshots'][0]['url']) : '';
+			return $appData;
+		}, $apps);
+
 		return new JSONResponse(['apps' => $apps, 'status' => 'success']);
 	}
 
diff --git a/settings/src/components/appDetails.vue b/settings/src/components/appDetails.vue
index 5467b1ffb101f528a40a99ff1746babe28471d31..70078d87c6414db46d140478ba2d7ee862c37869 100644
--- a/settings/src/components/appDetails.vue
+++ b/settings/src/components/appDetails.vue
@@ -25,7 +25,7 @@
 		<a class="close icon-close" href="#" v-on:click="hideAppDetails"><span class="hidden-visually">Close</span></a>
 		<h2>{{ app.name }}</h2>
 		<img :src="app.preview" width="100%" />
-		<app-score v-if="app.ratingNumThresholdReached" :score="app.score"></app-score>
+		<app-score v-if="app.appstoreData.ratingNumOverall > 5" :score="app.appstoreData.ratingOverall"></app-score>
 		<div class="app-author">
 			{{ author }}
 			{{ licence }}
@@ -38,6 +38,19 @@
 			<input v-if="!app.active && !app.needsDownload" class="enable" type="button" :value="t('settings','Enable')" v-on:click="enable(app.id)" :disabled="!app.canInstall" />
 			<input v-if="!app.active && app.needsDownload" class="enable needs-download" type="button" :value="t('settings', 'Enable')" :disabled="!app.canInstall"/>
 		</div>
+		<div class="app-groups" v-if="app.active">
+			<div class="groups-enable" v-if="app.active && canLimitToGroups(app)">
+				<input type="checkbox" :value="app.id" v-model="groupCheckedAppsData" v-on:change="setGroupLimit" class="groups-enable__checkbox checkbox" :id="prefix('groups_enable', app.id)">
+				<label :for="prefix('groups_enable', app.id)">Auf Gruppen beschränken</label>
+				<input type="hidden" class="group_select" title="Alle" value="">
+				<multiselect v-if="isLimitedToGroups(app)" :options="groups" :value="appGroups" @select="addGroupLimitation" @remove="removeGroupLimitation"
+							 :placeholder="t('settings', 'Limit app usage to groups')"
+							 label="name" track-by="id" class="multiselect-vue"
+							 :multiple="true" :close-on-select="false">
+					<span slot="noResult">{{t('settings', 'No results')}}</span>
+				</multiselect>
+			</div>
+		</div>
 		<p class="documentation">
 			<a class="appslink" v-if="app.website" :href="app.website" target="_blank" rel="noreferrer noopener">{{ t('settings', 'Visit website') }} ↗</a>
 			<a class="appslink" v-if="app.bugs" :href="app.bugs" target="_blank" rel="noreferrer noopener">{{ t('settings', 'Report a bug') }} ↗</a>
@@ -65,7 +78,9 @@
 <script>
 import Multiselect from 'vue-multiselect';
 import AppScore from './appList/appScore';
+import AppManagement from './appManagement';
 export default {
+	mixins: [AppManagement],
 	name: 'appDetails',
 	props: ['category', 'app'],
 	components: {
diff --git a/settings/src/components/appList.vue b/settings/src/components/appList.vue
index 08809cf9b2b47284ba7e2f8114dcfc6058bfafd5..60029aa59fcb29f08777fda5d60dd535cefa2f2a 100644
--- a/settings/src/components/appList.vue
+++ b/settings/src/components/appList.vue
@@ -116,58 +116,6 @@ export default {
 		prefix(prefix, content) {
 			return prefix + '_' + content;
 		},
-		isLimitedToGroups(app) {
-			if (app.groups.length || this.groupCheckedAppsData.includes(app.id)) {
-				return true;
-			}
-			return false;
-		},
-		canLimitToGroups(app) {
-			if (app.types && app.types.includes('filesystem')
-				|| app.types.includes('prelogin')
-				|| app.types.includes('authentication')
-				|| app.types.includes('logging')
-				|| app.types.includes('prevent_group_restriction')) {
-				return false;
-			}
-			return true;
-		},
-		addGroupLimitation(appId, group) {
-			let currentGroups = this.$store.apps.find(app => app.id === appId).groups;
-			currentGroups.push(group);
-			this.$store.dispatch('enableApp', { appId: appId, groups: groups});
-		},
-		removeGroupLimitation(appId, group) {
-			let currentGroups = this.$store.apps.find(app => app.id === appId).groups;
-			currentGroups.push(group);
-			let index = currentGroups.indexOf(group);
-			if (index > -1) {
-				currentGroups.splice(index, 1);
-			}
-			this.$store.dispatch('enableApp', { appId: appId, groups: groups});
-		},
-		enable(appId) {
-			this.$store.dispatch('enableApp', { appId: appId })
-				.catch((error) => { OC.Notification.show(error)});
-		},
-		disable(appId) {
-			this.$store.dispatch('disableApp', { appId: appId })
-				.catch((error) => { OC.Notification.show(error)});
-		},
-		remove() {},
-		install() {},
-		createUser() {
-			this.loading = true;
-			this.$store.dispatch('addUser', {
-				userid: this.newUser.id,
-				password: this.newUser.password,
-				email: this.newUser.mailAddress,
-				groups: this.newUser.groups.map(group => group.id),
-				subadmin: this.newUser.subAdminsGroups.map(group => group.id),
-				quota: this.newUser.quota.id,
-				language: this.newUser.language.code,
-			}).then(() => this.resetForm());
-		}
 	}
 }
 </script>
diff --git a/settings/src/components/appList/appItem.vue b/settings/src/components/appList/appItem.vue
index 8797fd88bd91386b9ff57d08423942d80fac3bf5..b2fb86f955a56afb2244079bda762ded9a69e107 100644
--- a/settings/src/components/appList/appItem.vue
+++ b/settings/src/components/appList/appItem.vue
@@ -26,8 +26,8 @@
 			<div v-if="!app.preview" class="icon-settings-dark"></div>
 			<img v-if="!app.previewAsIcon && app.preview" :src="app.preview"  width="100%" />
 			<svg v-if="app.previewAsIcon && app.preview" width="32" height="32" viewBox="0 0 32 32">
-				<defs><filter id="invertIconApps-606"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix></filter></defs>
-				<image x="0" y="0" width="32" height="32" preserveAspectRatio="xMinYMin meet" filter="url(#invertIconApps-606)" :xlink:href="app.preview" class="app-icon"></image>
+				<defs><filter :id="filterId"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix></filter></defs>
+				<image x="0" y="0" width="32" height="32" preserveAspectRatio="xMinYMin meet" :filter="filterUrl" :xlink:href="app.preview" class="app-icon"></image>
 			</svg>
 		</div>
 		<div class="app-name" v-on:click="showAppDetails">
@@ -70,9 +70,11 @@
 <script>
 	import Multiselect from 'vue-multiselect';
 	import AppScore from './appScore';
+	import AppManagement from '../appManagement';
 
 	export default {
 		name: 'appItem',
+		mixins: [AppManagement],
 		props: {
 			app: {},
 			category: {},
@@ -90,14 +92,19 @@
 				groupCheckedAppsData: false,
 				loading: false,
 				scrolled: false,
+				filterId: '',
 			};
 		},
 		mounted() {
 			if (this.app.groups.length > 0) {
 				this.groupCheckedAppsData = true;
 			}
+			this.filterId = 'invertIconApps' + Math.floor((Math.random() * 100 )) + new Date().getSeconds() + new Date().getMilliseconds();
 		},
 		computed: {
+			filterUrl() {
+				return `url(#${this.filterId})`;
+			},
 			appstoreUrl() {
 				return `https://apps.nextcloud.com/apps/${this.app.id}`;
 			},
@@ -129,71 +136,6 @@
 			prefix(prefix, content) {
 				return prefix + '_' + content;
 			},
-			isLimitedToGroups(app) {
-				if (this.app.groups.length || this.groupCheckedAppsData) {
-					return true;
-				}
-				return false;
-			},
-			setGroupLimit: function() {
-				if (!this.groupCheckedAppsData) {
-					this.$store.dispatch('enableApp', {appId: this.app.id, groups: []});
-				}
-			},
-			canLimitToGroups(app) {
-				if (app.types && app.types.includes('filesystem')
-					|| app.types.includes('prelogin')
-					|| app.types.includes('authentication')
-					|| app.types.includes('logging')
-					|| app.types.includes('prevent_group_restriction')) {
-					return false;
-				}
-				return true;
-			},
-			addGroupLimitation(group) {
-				let groups = this.app.groups.concat([]).concat([group.id]);
-				this.$store.dispatch('enableApp', { appId: this.app.id, groups: groups});
-			},
-			removeGroupLimitation(group) {
-				let currentGroups = this.app.groups.concat([]);
-				let index = currentGroups.indexOf(group.id);
-				if (index > -1) {
-					currentGroups.splice(index, 1);
-				}
-				this.$store.dispatch('enableApp', { appId: this.app.id, groups: currentGroups});
-			},
-			enable(appId) {
-				this.$store.dispatch('enableApp', { appId: appId, groups: [] })
-					.catch((error) => { OC.Notification.show(error)});
-			},
-			disable(appId) {
-				this.$store.dispatch('disableApp', { appId: appId })
-					.catch((error) => { OC.Notification.show(error)});
-			},
-			remove(appId) {
-				this.$store.dispatch('uninstallApp', { appId: appId })
-					.catch((error) => { OC.Notification.show(error)});
-			},
-			install(appId) {
-				this.$store.dispatch('installApp', { appId: appId })
-					.catch((error) => { OC.Notification.show(error)});
-			},
-			update(appId) {
-				this.$store.dispatch('updateApp', { appId: appId })
-					.catch((error) => { OC.Notification.show(error)});
-			},
-			createUser() {
-				this.loading = true;
-				this.$store.dispatch('addUser', {
-					userid: this.newUser.id,
-					password: this.newUser.password,
-					email: this.newUser.mailAddress,
-					groups: this.newUser.groups.map(group => group.id),
-					subadmin: this.newUser.subAdminsGroups.map(group => group.id),
-					quota: this.newUser.quota.id,
-					language: this.newUser.language.code,
-				}).then(() => this.resetForm());
-			}
 		}
 	}
 </script>
diff --git a/settings/src/components/appManagement.vue b/settings/src/components/appManagement.vue
new file mode 100644
index 0000000000000000000000000000000000000000..24f560409004f21ce2248585005b7afd26bcbf48
--- /dev/null
+++ b/settings/src/components/appManagement.vue
@@ -0,0 +1,81 @@
+<!--
+  - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+  -
+  - @author Julius Härtl <jus@bitgrid.net>
+  -
+  - @license GNU AGPL version 3 or any later version
+  -
+  - This program is free software: you can redistribute it and/or modify
+  - it under the terms of the GNU Affero General Public License as
+  - published by the Free Software Foundation, either version 3 of the
+  - License, or (at your option) any later version.
+  -
+  - This program is distributed in the hope that it will be useful,
+  - but WITHOUT ANY WARRANTY; without even the implied warranty of
+  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  - GNU Affero General Public License for more details.
+  -
+  - You should have received a copy of the GNU Affero General Public License
+  - along with this program. If not, see <http://www.gnu.org/licenses/>.
+  -
+  -->
+
+<script>
+	export default {
+		methods: {
+			isLimitedToGroups(app) {
+				if (this.app.groups.length || this.groupCheckedAppsData) {
+					return true;
+				}
+				return false;
+			},
+			setGroupLimit: function() {
+				if (!this.groupCheckedAppsData) {
+					this.$store.dispatch('enableApp', {appId: this.app.id, groups: []});
+				}
+			},
+			canLimitToGroups(app) {
+				if (app.types && app.types.includes('filesystem')
+					|| app.types.includes('prelogin')
+					|| app.types.includes('authentication')
+					|| app.types.includes('logging')
+					|| app.types.includes('prevent_group_restriction')) {
+					return false;
+				}
+				return true;
+			},
+			addGroupLimitation(group) {
+				let groups = this.app.groups.concat([]).concat([group.id]);
+				this.$store.dispatch('enableApp', { appId: this.app.id, groups: groups});
+			},
+			removeGroupLimitation(group) {
+				let currentGroups = this.app.groups.concat([]);
+				let index = currentGroups.indexOf(group.id);
+				if (index > -1) {
+					currentGroups.splice(index, 1);
+				}
+				this.$store.dispatch('enableApp', { appId: this.app.id, groups: currentGroups});
+			},
+			enable(appId) {
+				this.$store.dispatch('enableApp', { appId: appId, groups: [] })
+					.catch((error) => { OC.Notification.show(error)});
+			},
+			disable(appId) {
+				this.$store.dispatch('disableApp', { appId: appId })
+					.catch((error) => { OC.Notification.show(error)});
+			},
+			remove(appId) {
+				this.$store.dispatch('uninstallApp', { appId: appId })
+					.catch((error) => { OC.Notification.show(error)});
+			},
+			install(appId) {
+				this.$store.dispatch('installApp', { appId: appId })
+					.catch((error) => { OC.Notification.show(error)});
+			},
+			update(appId) {
+				this.$store.dispatch('updateApp', { appId: appId })
+					.catch((error) => { OC.Notification.show(error)});
+			}
+		}
+	}
+</script>
diff --git a/settings/src/views/Apps.vue b/settings/src/views/Apps.vue
index b24123e4affc9f399c08e6c9e8282bf1ca6cc429..d59a62ee22cfb9b997e41efed7ea98a241410c8b 100644
--- a/settings/src/views/Apps.vue
+++ b/settings/src/views/Apps.vue
@@ -24,7 +24,7 @@
 	<div id="app">
 		<app-navigation :menu="menu" />
 		<app-list :category="category" :app="currentApp" :search="search"></app-list>
-		<div id="app-sidebar" v-if="id">
+		<div id="app-sidebar" v-if="id && currentApp">
 			<app-details :category="category" :app="currentApp"></app-details>
 		</div>
 	</div>