diff --git a/VERSION b/VERSION
index 1d0ba9ea182b0f7354f3daf12120744ec5e0c2f8..8f0916f768f0487bcf8d33827ce2c8dcecb645c1 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.4.0
+0.5.0
diff --git a/lib/SeMeet/Controller/Groups.pm b/lib/SeMeet/Controller/Groups.pm
index 789a030567287d6b289b895d48a3ab20f335e22b..a98755dc84eecc3f0acaa45a127dbb686385ad44 100644
--- a/lib/SeMeet/Controller/Groups.pm
+++ b/lib/SeMeet/Controller/Groups.pm
@@ -14,7 +14,7 @@ sub list($c) {
     );
 
     my @groups = ();
-# TODO: filter
+
     GROUP:
     while ( my $group = $groups->next()) {
         push @groups, $c->spec_filter({
diff --git a/lib/SeMeet/Controller/Users.pm b/lib/SeMeet/Controller/Users.pm
new file mode 100644
index 0000000000000000000000000000000000000000..e3ea8dff8c6ad2d87f2f9a6dc9de19da04441530
--- /dev/null
+++ b/lib/SeMeet/Controller/Users.pm
@@ -0,0 +1,69 @@
+package SeMeet::Controller::Users;
+use Mojo::Base 'Mojolicious::Controller', -signatures;
+
+use utf8;
+use JSON;
+use constant REDIS_CACHE_LIFETIME => 60;
+
+sub list($c) {
+    $c->openapi->valid_input or return;
+    my $args = $c->validation->output;
+
+    my $cache_key = sprintf('USERS %s', $args->{search} || 'ALL');
+    if ($c->redis->db->exists( $cache_key )) {
+        $c->render(openapi => from_json($c->redis->db->get( $cache_key )));
+        return;
+    }
+
+    my $groups = $c->schema->resultset('Group')->search(
+        { permissions => { ilike => 'org-%' }}, # TODO: samostatny priznak?
+        { order_by => 'name', }
+    );
+
+    my %groups = ();
+
+    GROUP:
+    while ( my $group = $groups->next()) {
+        my $name = $group->name;
+
+        next GROUP if $name !~ s/^(KS|MS)\s+//i;
+
+        my $type = $1;
+
+        $name =~ s/\s+členové a RegP//i;
+        $groups{$type}->{$group->octid} = $name;
+    }
+
+    my $users = $c->iapi->get('octopus/users?search=' . $args->{search});
+
+    my @users = ();
+
+    USER:
+    foreach my $user ( @{ $users } ) {
+
+        my ($ks, $ms);
+
+        GROUP:
+        foreach my $id (@{ $user->{groups} }) {
+            if ( my $group = $groups{KS}->{$id} ) {
+                $ks //= $group;
+            }
+            if ( my $group = $groups{MS}->{$id} ) {
+                $ms //= $group;
+            }
+        }
+
+        push @users, $c->spec_filter({
+            id          => $user->{id},
+            name        => $user->{displayname},
+            username    => $user->{username},
+            region      => join ' - ', grep { defined } ($ks, $ms),
+        }, 'UserInList')
+    }
+
+    $c->redis->db->set( $cache_key, to_json(\@users), 'EX', REDIS_CACHE_LIFETIME );
+    $c->render( openapi => \@users );
+}
+
+1;
+
diff --git a/openapi.yaml b/openapi.yaml
index ee4791be141eb235fea203f13d6fe6393b53e73f..5672914486c1155d64b956b4a91341a574370861 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -66,6 +66,14 @@ components:
         name:
           type: string
           readOnly: true
+        username:
+          type: string
+          readOnly: true
+          nullable: true
+        region:
+          type: string
+          nullable: true
+          readOnly: true
 
 paths:
   /meets:
@@ -216,14 +224,13 @@ paths:
         204:
           description: Mistnost je smazana
 
-  /meets/{id}/unauthorized_groups:
+  /groups:
     get:
       x-mojo-to: groups#list
       tags:
-        - meets
         - groups
-      summary: "Seznam nezarazenych skupin"
-      operationId: searchUnauthorizeGroups
+      summary: "Hledani skupin"
+      operationId: searchGroups
       parameters:
       - name: search
         in: query
@@ -241,6 +248,30 @@ paths:
                 items:
                   $ref: '#/components/schemas/GroupInList'
 
+  /users:
+    get:
+      x-mojo-to: users#list
+      tags:
+        - users
+      summary: "Hledani osob"
+      operationId: searchUsers
+      parameters:
+      - name: search
+        in: query
+        description: Search query
+        schema:
+          type: string
+          example: 'Ivan'
+      responses:
+        200:
+          description: Seznam osob
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/UserInList'
+
   /meets/{id}/group:
     post:
       x-mojo-to: meets#add_groups
diff --git a/templates/includes/meet_moderators.html.ep b/templates/includes/meet_moderators.html.ep
index a6ed19032e893e4e94e2d23d84dc022b9d736a96..2b637bbc7e17e8dbc036593e0bc4c9b8501683bd 100644
--- a/templates/includes/meet_moderators.html.ep
+++ b/templates/includes/meet_moderators.html.ep
@@ -16,7 +16,7 @@
     <div class="overflow-y-auto h-64 mb-4 border p-2 text-sm" v-if="users.length > 0">
     <div v-for="user in users" class="checkbox form-field__control mb-1" >
      <input name="users" type="checkbox" v-bind:title="user.id" v-bind:value="user.id"  v-model="selected_users" >
-     <label>{{user.name}}</label>
+     <label style="max-width: 100%">{{user.name}} ({{ user.username }})<span v-if="user.region.length > 0" class="text-grey-300 text-xs"> | {{ user.region }}</span></label>
     </div>
     </div>
     <div class="form-field" v-if="selected_users.length > 0">
diff --git a/templates/meet.html.ep b/templates/meet.html.ep
index 2186586a9f5d961e89a1f50ef0f3a5ff4fbeeffe..d9904a968812372938449fd84dff75c60b2071ee 100644
--- a/templates/meet.html.ep
+++ b/templates/meet.html.ep
@@ -31,8 +31,9 @@
 <script type="module">
   import { createApp } from 'https://cdn-unpkg.pirati.cz/petite-vue@0.2.2/dist/petite-vue.es.js'
 
-  const GROUPS_URL      = '/api/meets/<%= stash->{id} %>/unauthorized_groups';
-  const USERS_URL       = '<%= config->{iapi} %>octopus/users';
+  const GROUPS_URL      = '/api/groups';
+  const USERS_URL       = '/api/users';
+//const USERS_URL       = '<%= config->{iapi} %>octopus/users';
   const MEET_URL        = '/api/meets/<%= stash->{id} %>';
   const ADD_GROUPS_URL  = '/api/meets/<%= stash->{id} %>/group';
   const ADD_USERS_URL   = '/api/meets/<%= stash->{id} %>/moderator';