From 784a6b9b0ef228b8c99ab26c0b7627f3e43bff89 Mon Sep 17 00:00:00 2001
From: Sebastian Kehr <kehr@ub.uni-leipzig.de>
Date: Fri, 6 Sep 2019 11:02:56 +0200
Subject: [PATCH] refs #15998 [fid_adlr] user management forms related changes
 * mark required fields in registration forms * map job title to requested
 permission * account for generalization of user creation form * translation
 fix * adjustments needed for hydration * build attributes after submit of
 user creation form * added newsletter boolean flag * adjust user update form
 * use hydrator for all user forms * translation fixes * override not-empty
 validator for newsletter field * fixup: adjust newsletter field options *
 adjust translations in user profile view and update form * include user group
 in user update form * adjust user update form spec * rename property for less
 confusion * rename user property and according form fields * fix input filter
 spec for newsletter field * render job_title element as select field * remove
 job_title element from update form * grant permissions on user creation *
 display user group as non-editable field in update form * changes to job
 title field in update form * display job title update notice * use custom
 validator for home address fields * let first line of first address be
 optional * let user specify default delivery address * adjust permissions
 configuration * adjust permissoins translations * customize admin edit form *
 user update form style hotfix * revision of admin edit form

---
 fid_adlr/config/vufind/fid.ini                |  33 +-
 module/fid_adlr/config/address-collection.php | 294 ++++++++++++++++++
 module/fid_adlr/config/admin-edit-form.php    |  44 +++
 module/fid_adlr/config/module.config.php      |  29 +-
 module/fid_adlr/config/user-create-form.php   | 153 +++++++++
 module/fid_adlr/config/user-update-form.php   | 162 ++++++++++
 .../InputFilter/UserCreateFormInputFilter.php |  49 +++
 .../InputFilter/UserUpdateFormInputFilter.php |  35 +++
 .../src/Validator/HomeAddressField.php        |  51 +++
 themes/fid_adlr/languages/de.ini              |   1 +
 themes/fid_adlr/languages/en.ini              |   3 +-
 themes/fid_adlr/languages/fid/de.ini          |  50 +++
 themes/fid_adlr/languages/fid/en.ini          |  51 +++
 themes/fid_adlr/scss/compiled.scss            |   6 +-
 .../fid_adlr/templates/fid/user/create.phtml  | 240 ++++++++++++++
 .../fid/user/home-address-fieldset.phtml      | 116 +++++++
 .../fid/user/office-address-fieldset.phtml    | 111 +++++++
 .../fid_adlr/templates/fid/user/update.phtml  | 192 ++++++++++++
 .../templates/myresearch/profile.phtml        |  56 ++++
 19 files changed, 1661 insertions(+), 15 deletions(-)
 create mode 100644 module/fid_adlr/config/address-collection.php
 create mode 100644 module/fid_adlr/config/admin-edit-form.php
 create mode 100644 module/fid_adlr/config/user-create-form.php
 create mode 100644 module/fid_adlr/config/user-update-form.php
 create mode 100644 module/fid_adlr/src/InputFilter/UserCreateFormInputFilter.php
 create mode 100644 module/fid_adlr/src/InputFilter/UserUpdateFormInputFilter.php
 create mode 100644 module/fid_adlr/src/Validator/HomeAddressField.php
 create mode 100644 themes/fid_adlr/languages/fid/de.ini
 create mode 100644 themes/fid_adlr/languages/fid/en.ini
 create mode 100644 themes/fid_adlr/templates/fid/user/create.phtml
 create mode 100644 themes/fid_adlr/templates/fid/user/home-address-fieldset.phtml
 create mode 100644 themes/fid_adlr/templates/fid/user/office-address-fieldset.phtml
 create mode 100644 themes/fid_adlr/templates/fid/user/update.phtml
 create mode 100644 themes/fid_adlr/templates/myresearch/profile.phtml

diff --git a/fid_adlr/config/vufind/fid.ini b/fid_adlr/config/vufind/fid.ini
index 5e74077a2d0..8fff457b289 100644
--- a/fid_adlr/config/vufind/fid.ini
+++ b/fid_adlr/config/vufind/fid.ini
@@ -22,4 +22,35 @@ relative_path = ../../../fid/config/vufind/fid.ini
 ;####################################################################
 
 [Client]
-baseUrl = https://bbi-admin.finc.info/adlr-alpha.1
\ No newline at end of file
+baseUrl = https://bbi-admin.finc.info/adlr-alpha.1
+
+[Security]
+access_levels[] = limited_access
+access_levels[] = full_access
+access_levels[] = extended_access
+
+[UserProfile]
+role_display[] = "extended_access"
+role_display[] = "full_access"
+role_display[] = "limited_access"
+role_display_priority[] = "extended_access>full_access>limited_access"
+role_display_order = "extended_access>full_access>limited_access"
+
+[Admin]
+; Whitelist of all fields that admins shall be able
+; to change for other users
+;editable_user_fields[] = 'HomeLibrary'
+editable_user_fields[] = 'Permissions'
+editable_user_fields[] = 'Salutation'
+editable_user_fields[] = 'JobTitle'
+
+;list of user fields to be shown in overview table
+overview_fields[] = 'UserName'
+overview_fields[] = 'Firstname'
+overview_fields[] = 'Lastname'
+overview_fields[] = 'Permissions'
+
+; List of all available user permissions
+permission_options[] = 'limited_access'
+permission_options[] = 'full_access'
+permission_options[] = 'extended_access'
diff --git a/module/fid_adlr/config/address-collection.php b/module/fid_adlr/config/address-collection.php
new file mode 100644
index 00000000000..b376aabdd8d
--- /dev/null
+++ b/module/fid_adlr/config/address-collection.php
@@ -0,0 +1,294 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use fid\InputFilter\RootAwareBaseInputFilter;
+use fid_adlr\Validator\HomeAddressField;
+use Zend\Filter\StringTrim;
+use Zend\Form\Element\Hidden;
+use Zend\Form\Element\Text;
+use Zend\Form\InputFilterProviderFieldset;
+use Zend\Validator\NotEmpty;
+use Zend\Validator\StringLength;
+
+return [
+    'spec' => [
+        'elements' => [
+            'address_0' => [
+                'spec' => [
+                    'elements' => [
+                        'line2'   => [
+                            'spec' => [
+                                'attributes' => [
+                                    'required' => true,
+                                ],
+                            ],
+                        ],
+                        'zip'     => [
+                            'spec' => [
+                                'attributes' => [
+                                    'required' => true,
+                                ],
+                            ],
+                        ],
+                        'city'    => [
+                            'spec' => [
+                                'attributes' => [
+                                    'required' => true,
+                                ],
+                            ],
+                        ],
+                        'country' => [
+                            'spec' => [
+                                'attributes' => [
+                                    'required' => true,
+                                ],
+                            ],
+                        ],
+                    ],
+                    'options'  => [
+                        'template'          => 'office-address-fieldset.phtml',
+                        'input_filter_spec' => [
+                            'line2'   => [
+                                'validators' => [
+                                    NotEmpty::class => [
+                                        'options' => [
+                                            'type' => NotEmpty::ALL,
+                                        ],
+                                    ],
+                                ],
+                            ],
+                            'zip'     => [
+                                'validators' => [
+                                    NotEmpty::class => [
+                                        'options' => [
+                                            'type' => NotEmpty::ALL,
+                                        ],
+                                    ],
+                                ],
+                            ],
+                            'city'    => [
+                                'validators' => [
+                                    NotEmpty::class => [
+                                        'options' => [
+                                            'type' => NotEmpty::ALL,
+                                        ],
+                                    ],
+                                ],
+                            ],
+                            'country' => [
+                                'validators' => [
+                                    NotEmpty::class => [
+                                        'options' => [
+                                            'type' => NotEmpty::ALL,
+                                        ],
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            'address_1' => [
+                'spec' => [
+                    'name'     => 1,
+                    'type'     => InputFilterProviderFieldset::class,
+                    'elements' => [
+                        'id'      => [
+                            'spec' => [
+                                'name' => 'id',
+                                'type' => Hidden::class,
+                            ],
+                        ],
+                        'line1'   => [
+                            'spec' => [
+                                'name'    => 'line1',
+                                'type'    => Text::class,
+                                'options' => [
+                                    'label' => 'label_address_1_line_1',
+                                ],
+                            ],
+                        ],
+                        'line2'   => [
+                            'spec' => [
+                                'name'    => 'line2',
+                                'type'    => Text::class,
+                                'options' => [
+                                    'label' => 'label_address_1_line_2',
+                                ],
+                            ],
+                        ],
+                        'zip'     => [
+                            'spec' => [
+                                'name'    => 'zip',
+                                'type'    => Text::class,
+                                'options' => [
+                                    'label' => 'label_address_1_zip',
+                                ],
+                            ],
+                        ],
+                        'city'    => [
+                            'spec' => [
+                                'name'    => 'city',
+                                'type'    => Text::class,
+                                'options' => [
+                                    'label' => 'label_address_1_city',
+                                ],
+                            ],
+                        ],
+                        'country' => [
+                            'spec' => [
+                                'name'    => 'country',
+                                'type'    => Text::class,
+                                'options' => [
+                                    'label' => 'label_address_1_country',
+                                ],
+                            ],
+                        ],
+                    ],
+                    'options'  => [
+                        'label'             => 'label_address_1',
+                        'template'          => 'home-address-fieldset.phtml',
+                        'input_filter_spec' => [
+                            'type'    => RootAwareBaseInputFilter::class,
+                            'line1'   => [
+                                'name'       => 'line1',
+                                'filters'    => [
+                                    StringTrim::class => [
+                                        'name' => StringTrim::class,
+                                    ],
+                                ],
+                                'validators' => [
+                                    NotEmpty::class         => [
+                                        'name'    => NotEmpty::class,
+                                        'options' => [
+                                            'type' => NotEmpty::NULL,
+                                        ],
+                                    ],
+                                    StringLength::class     => [
+                                        'name'    => StringLength::class,
+                                        'options' => [
+                                            'max' => 255
+                                        ]
+                                    ],
+                                    HomeAddressField::class => [
+                                        'name' => HomeAddressField::class
+                                    ],
+                                ],
+                            ],
+                            'line2'   => [
+                                'name'       => 'line2',
+                                'required'   => false,
+                                'filters'    => [
+                                    StringTrim::class => [
+                                        'name' => StringTrim::class,
+                                    ],
+                                ],
+                                'validators' => [
+                                    StringLength::class => [
+                                        'name'    => StringLength::class,
+                                        'options' => [
+                                            'max' => 255
+                                        ]
+                                    ],
+                                ],
+                            ],
+                            'zip'     => [
+                                'name'       => 'zip',
+                                'filters'    => [
+                                    StringTrim::class => [
+                                        'name' => StringTrim::class,
+                                    ],
+                                ],
+                                'validators' => [
+                                    NotEmpty::class         => [
+                                        'name'    => NotEmpty::class,
+                                        'options' => [
+                                            'type' => NotEmpty::NULL,
+                                        ],
+                                    ],
+                                    StringLength::class     => [
+                                        'name'    => StringLength::class,
+                                        'options' => [
+                                            'max' => 255
+                                        ]
+                                    ],
+                                    HomeAddressField::class => [
+                                        'name' => HomeAddressField::class
+                                    ],
+                                ],
+                            ],
+                            'city'    => [
+                                'name'       => 'city',
+                                'filters'    => [
+                                    StringTrim::class => [
+                                        'name' => StringTrim::class,
+                                    ],
+                                ],
+                                'validators' => [
+                                    NotEmpty::class         => [
+                                        'name'    => NotEmpty::class,
+                                        'options' => [
+                                            'type' => NotEmpty::NULL,
+                                        ],
+                                    ],
+                                    StringLength::class     => [
+                                        'name'    => StringLength::class,
+                                        'options' => [
+                                            'max' => 255
+                                        ]
+                                    ],
+                                    HomeAddressField::class => [
+                                        'name' => HomeAddressField::class
+                                    ],
+                                ],
+                            ],
+                            'country' => [
+                                'name'       => 'country',
+                                'filters'    => [
+                                    StringTrim::class => [
+                                        'name' => StringTrim::class,
+                                    ],
+                                ],
+                                'validators' => [
+                                    NotEmpty::class         => [
+                                        'name'    => NotEmpty::class,
+                                        'options' => [
+                                            'type' => NotEmpty::NULL,
+                                        ],
+                                    ],
+                                    StringLength::class     => [
+                                        'name'    => StringLength::class,
+                                        'options' => [
+                                            'max' => 255
+                                        ]
+                                    ],
+                                    HomeAddressField::class => [
+                                        'name' => HomeAddressField::class
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+];
diff --git a/module/fid_adlr/config/admin-edit-form.php b/module/fid_adlr/config/admin-edit-form.php
new file mode 100644
index 00000000000..e2ac11468fb
--- /dev/null
+++ b/module/fid_adlr/config/admin-edit-form.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use Zend\Form\Element\Select;
+
+return [
+    'elements' => [
+        'job_title' => [
+            'spec' => [
+                'type'    => Select::class,
+                'options' => [
+                    'value_options' => [
+                        'job_title_2',
+                        'job_title_3',
+                        'job_title_4',
+                        'job_title_5',
+                        'job_title_6',
+                        'job_title_7',
+                        'job_title_8',
+                        'job_title_9',
+                    ],
+                ],
+            ],
+        ],
+    ],
+];
\ No newline at end of file
diff --git a/module/fid_adlr/config/module.config.php b/module/fid_adlr/config/module.config.php
index c291ff51dff..40fcfd912f1 100644
--- a/module/fid_adlr/config/module.config.php
+++ b/module/fid_adlr/config/module.config.php
@@ -16,9 +16,9 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * @author  Gregor Gawol <gawol@ub.uni-leipzig.de>
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
  * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
  */
-namespace fid_adlr\Module\Configuration;
 
 use fid_adlr\Controller\MyResearchController;
 use fid_adlr\Controller\MyResearchControllerFactory;
@@ -27,48 +27,53 @@ use Zend\Router\Http\Regex;
 use Zend\ServiceManager\Factory\InvokableFactory;
 
 $config = [
-    'controllers'        => [
+    'forms'        => [
+        'user-create-form' => require 'user-create-form.php',
+        'user-update-form' => require 'user-update-form.php',
+        'admin-edit-form'  => require 'admin-edit-form.php',
+    ],
+    'controllers'  => [
         'factories' => [
-            MyResearchController::class      => MyResearchControllerFactory::class
+            MyResearchController::class => MyResearchControllerFactory::class
         ],
-        'aliases' => [
+        'aliases'   => [
             'my-research' => MyResearchController::class,
         ],
     ],
     'view_helpers' => [
-        'aliases' => [
+        'aliases'   => [
             'rss' => Rss::class,
         ],
         'factories' => [
             Rss::class => InvokableFactory::class,
         ],
     ],
-    'router'             => [
+    'router'       => [
         'routes' => [
             'myresearch' => [
                 'type'          => Regex::class,
                 'options'       => [
                     'regex' => '/(?i)myresearch',
-                    'spec'  =>'/myresearch'
+                    'spec'  => '/myresearch'
                 ],
                 'may_terminate' => true,
                 'child_routes'  => [
                     'databases' => [
-                        'type'          => Regex::class,
-                        'options'       => [
+                        'type'    => Regex::class,
+                        'options' => [
                             'regex'    => '/(?i)(databases|dbis|licenses)',
                             'defaults' => [
                                 'controller' => MyResearchController::class,
                                 'action'     => 'databases',
                             ],
-                            'spec'=>'/databases'
+                            'spec'     => '/databases'
                         ],
                     ],
                 ],
             ],
         ],
     ],
-    'vufind'      => [
+    'vufind'       => [
         'plugin_managers'              => [
             'recorddriver' => [
                 'factories' => [
@@ -93,7 +98,7 @@ $config = [
                     'acquisitionpda'  => 'finc\RecordTab\AcquisitionPDA',
                     'topics'          => 'finc\RecordTab\Topics',
                     'descriptionlido' => 'finc\RecordTab\DescriptionLido',
-                    'toc' => 'fid_adlr\RecordTab\TOC'
+                    'toc'             => 'fid_adlr\RecordTab\TOC'
                 ],
             ],
         ],
diff --git a/module/fid_adlr/config/user-create-form.php b/module/fid_adlr/config/user-create-form.php
new file mode 100644
index 00000000000..d4ddf59ba3d
--- /dev/null
+++ b/module/fid_adlr/config/user-create-form.php
@@ -0,0 +1,153 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use fid_adlr\InputFilter\UserCreateFormInputFilter;
+use Zend\Filter\Boolean;
+use Zend\Filter\StringTrim;
+use Zend\Filter\ToInt;
+use Zend\Form\Element\Checkbox;
+use Zend\Form\Element\Select;
+use Zend\Form\Element\Text;
+use Zend\Validator\NotEmpty;
+use Zend\Validator\StringLength;
+
+return [
+    'elements'     => [
+        'college'   => [
+            'spec' => [
+                'attributes' => [
+                    'required' => true,
+                ],
+            ],
+        ],
+        'job_title' => [
+            'spec' => [
+                'type'    => Select::class,
+                'options' => [
+                    'empty_option'  => '',
+                    'value_options' => [
+                        'job_title_2',
+                        'job_title_3',
+                        'job_title_4',
+                        'job_title_5',
+                        'job_title_6',
+                        'job_title_7',
+                        'job_title_8',
+                        'job_title_9',
+                    ],
+                ],
+            ],
+        ],
+        'addresses' => require 'address-collection.php',
+        'data'      => [
+            'spec' => [
+                'elements' => [
+                    'phone'            => [
+                        'spec' => [
+                            'name'    => 'phone',
+                            'type'    => Text::class,
+                            'options' => [
+                                'label' => 'label_phone',
+                            ],
+                        ],
+                    ],
+                    'newsletter'       => [
+                        'spec' => [
+                            'name'    => 'newsletter',
+                            'type'    => Checkbox::class,
+                            'options' => [
+                                'label' => 'label_newsletter',
+                            ],
+                        ],
+                    ],
+                    'delivery_address' => [
+                        'spec' => [
+                            'name'    => 'delivery_address',
+                            'type'    => Checkbox::class,
+                            'options' => [
+                                'label' => 'label_delivery_address',
+                            ],
+                        ],
+                    ],
+                ],
+                'options'  => [
+                    'input_filter_spec' => [
+                        'phone'            => [
+                            'name'       => 'phone',
+                            'required'   => false,
+                            'filters'    => [
+                                StringTrim::class => [
+                                    'name' => StringTrim::class,
+                                ],
+                            ],
+                            'validators' => [
+                                StringLength::class => [
+                                    'name'    => StringLength::class,
+                                    'options' => [
+                                        'max' => 255
+                                    ],
+                                ],
+                            ],
+                        ],
+                        'newsletter'       => [
+                            'name'       => 'newsletter',
+                            'filters'    => [
+                                Boolean::class => [
+                                    'name' => Boolean::class,
+                                ],
+                            ],
+                            'validators' => [
+                                NotEmpty::class => [
+                                    'name'    => NotEmpty::class,
+                                    'options' => [
+                                        'type' => NotEmpty::NULL,
+                                    ],
+                                ],
+                            ],
+                        ],
+                        'delivery_address' => [
+                            'name'       => 'delivery_address',
+                            'filters'    => [
+                                ToInt::class => [
+                                    'name' => ToInt::class,
+                                ],
+                            ],
+                            'validators' => [
+                                NotEmpty::class        => [
+                                    'name'    => NotEmpty::class,
+                                    'options' => [
+                                        'type' => NotEmpty::NULL,
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+    'input_filter' => [
+        'type'    => UserCreateFormInputFilter::class,
+        'college' => [
+            'required' => true,
+        ],
+    ],
+];
\ No newline at end of file
diff --git a/module/fid_adlr/config/user-update-form.php b/module/fid_adlr/config/user-update-form.php
new file mode 100644
index 00000000000..6ad253cca0a
--- /dev/null
+++ b/module/fid_adlr/config/user-update-form.php
@@ -0,0 +1,162 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use fid_adlr\InputFilter\UserUpdateFormInputFilter;
+use Zend\Filter\Boolean;
+use Zend\Filter\StringTrim;
+use Zend\Filter\ToInt;
+use Zend\Form\Element\Checkbox;
+use Zend\Form\Element\Select;
+use Zend\Form\Element\Text;
+use Zend\Validator\NotEmpty;
+use Zend\Validator\StringLength;
+
+return [
+    'elements'     => [
+        'job_title' => [
+            'spec' => [
+                'name'       => 'job_title',
+                'type'       => Select::class,
+                'options'    => [
+                    'label'         => 'label_job_title',
+                    'value_options' => [
+                        'job_title_0',
+                        'job_title_1',
+                        'job_title_2',
+                        'job_title_3',
+                        'job_title_4',
+                        'job_title_5',
+                        'job_title_6',
+                        'job_title_7',
+                        'job_title_8',
+                        'job_title_9',
+                    ],
+                ],
+                'attributes' => [
+                    'disabled' => true,
+                ],
+            ],
+        ],
+        'college'   => [
+            'spec' => [
+                'attributes' => [
+                    'required' => true,
+                ],
+            ],
+        ],
+        'addresses' => require 'address-collection.php',
+        'data'      => [
+            'spec' => [
+                'elements' => [
+                    'phone'            => [
+                        'spec' => [
+                            'name'    => 'phone',
+                            'type'    => Text::class,
+                            'options' => [
+                                'label' => 'label_phone',
+                            ],
+                        ],
+                    ],
+                    'newsletter'       => [
+                        'spec' => [
+                            'name'    => 'newsletter',
+                            'type'    => Checkbox::class,
+                            'options' => [
+                                'label' => 'label_newsletter',
+                            ],
+                        ],
+                    ],
+                    'delivery_address' => [
+                        'spec' => [
+                            'name'    => 'delivery_address',
+                            'type'    => Checkbox::class,
+                            'options' => [
+                                'label' => 'label_delivery_address',
+                            ],
+                        ],
+                    ],
+                ],
+                'options'  => [
+                    'input_filter_spec' => [
+                        'phone'            => [
+                            'name'       => 'phone',
+                            'required'   => false,
+                            'filters'    => [
+                                StringTrim::class => [
+                                    'name' => StringTrim::class,
+                                ],
+                            ],
+                            'validators' => [
+                                StringLength::class => [
+                                    'name'    => StringLength::class,
+                                    'options' => [
+                                        'max' => 255
+                                    ],
+                                ],
+                            ],
+                        ],
+                        'newsletter'       => [
+                            'name'       => 'newsletter',
+                            'filters'    => [
+                                Boolean::class => [
+                                    'name' => Boolean::class,
+                                ],
+                            ],
+                            'validators' => [
+                                NotEmpty::class => [
+                                    'name'    => NotEmpty::class,
+                                    'options' => [
+                                        'type' => NotEmpty::NULL,
+                                    ],
+                                ],
+                            ],
+                        ],
+                        'delivery_address' => [
+                            'name'       => 'delivery_address',
+                            'filters'    => [
+                                ToInt::class => [
+                                    'name' => ToInt::class,
+                                ],
+                            ],
+                            'validators' => [
+                                NotEmpty::class => [
+                                    'name'    => NotEmpty::class,
+                                    'options' => [
+                                        'type' => NotEmpty::NULL,
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+    'input_filter' => [
+        'type'      => UserUpdateFormInputFilter::class,
+        'job_title' => [
+            'required' => false,
+        ],
+        'college'   => [
+            'required' => true,
+        ],
+    ],
+];
diff --git a/module/fid_adlr/src/InputFilter/UserCreateFormInputFilter.php b/module/fid_adlr/src/InputFilter/UserCreateFormInputFilter.php
new file mode 100644
index 00000000000..e43c9a0582c
--- /dev/null
+++ b/module/fid_adlr/src/InputFilter/UserCreateFormInputFilter.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+namespace fid_adlr\InputFilter;
+
+use fid\InputFilter\RootAwareBaseInputFilter;
+
+class UserCreateFormInputFilter extends RootAwareBaseInputFilter
+{
+    public function getValues()
+    {
+        $values = parent::getValues();
+        $permission = $this->getPermission($values);
+        $permissions = [$permission => 'granted'];
+        return compact('permissions') + $values;
+    }
+
+    protected function getPermission($values): string
+    {
+        switch ($values['job_title']) {
+            case '6':
+            case '7':
+            case '9':
+                return 'limited_access';
+            case '8':
+                return 'extended_access';
+            default:
+                return 'full_access';
+        }
+    }
+}
diff --git a/module/fid_adlr/src/InputFilter/UserUpdateFormInputFilter.php b/module/fid_adlr/src/InputFilter/UserUpdateFormInputFilter.php
new file mode 100644
index 00000000000..1d727615db2
--- /dev/null
+++ b/module/fid_adlr/src/InputFilter/UserUpdateFormInputFilter.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+namespace fid_adlr\InputFilter;
+
+use fid\InputFilter\RootAwareBaseInputFilter;
+
+class UserUpdateFormInputFilter extends RootAwareBaseInputFilter
+{
+    public function getValues()
+    {
+        $values = parent::getValues();
+        unset($values['job_title']);
+
+        return $values;
+    }
+}
diff --git a/module/fid_adlr/src/Validator/HomeAddressField.php b/module/fid_adlr/src/Validator/HomeAddressField.php
new file mode 100644
index 00000000000..576d59786e3
--- /dev/null
+++ b/module/fid_adlr/src/Validator/HomeAddressField.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+namespace fid_adlr\Validator;
+
+use fid\InputFilter\RootAwareBaseInputFilter;
+use Zend\Validator\AbstractValidator;
+
+class HomeAddressField extends AbstractValidator
+{
+    public const ERROR = 'error';
+
+    protected $messageTemplates
+        = [
+            self::ERROR => 'error_home_address_value',
+        ];
+
+    public function isValid($value, array $context = null)
+    {
+        $empty = $context['line1'] . $context['line2'] . $context['zip']
+            . $context['city'] . $context['country'] === '';
+
+        $values = $context[RootAwareBaseInputFilter::ROOT]->getValues();
+        $valid = $values['data']['delivery_address'] ? $value !== ''
+            : $empty || $value !== '';
+
+        if (!$valid) {
+            $this->error(self::ERROR);
+        }
+
+        return $valid;
+    }
+}
\ No newline at end of file
diff --git a/themes/fid_adlr/languages/de.ini b/themes/fid_adlr/languages/de.ini
index 6c2af50f7d6..65ff6f8f242 100644
--- a/themes/fid_adlr/languages/de.ini
+++ b/themes/fid_adlr/languages/de.ini
@@ -1,3 +1,4 @@
+Your Profile = Mein Nutzerkonto
 Forgot Password = Passwort vergessen?
 Services for subject specialists = Service für Fachreferate
 Username = E-Mail-Adresse
diff --git a/themes/fid_adlr/languages/en.ini b/themes/fid_adlr/languages/en.ini
index 86e12c7ff7f..ac95267f5cf 100644
--- a/themes/fid_adlr/languages/en.ini
+++ b/themes/fid_adlr/languages/en.ini
@@ -1,6 +1,7 @@
+Your Profile = My account
 Forgot Password = Forgot your password?
 Services for subject specialists = Services for subject specialists
-Username = E-Mail Address
+Username = Email address
 
 ; DBIS / Licenses
 dbis_hint = "Notice"
diff --git a/themes/fid_adlr/languages/fid/de.ini b/themes/fid_adlr/languages/fid/de.ini
new file mode 100644
index 00000000000..8fa799053f1
--- /dev/null
+++ b/themes/fid_adlr/languages/fid/de.ini
@@ -0,0 +1,50 @@
+user_update_form_title = Persönliche Angaben ändern
+required_fields_note = Mit einem * markierte Felder müssen ausgefüllt werden.
+
+label_job_title = Nutzergruppe
+job_title_0 = HochschullehrerIn (Prof., Jun.-Prof., Dozent, PD)
+job_title_1 = Akademischer Mittelbau (Wiss./Akad. MitarbeiterIn/AssistentIn)
+job_title_2 = Akademischer Mittelbau (Lehrkraft für besondere Aufgaben)
+job_title_3 = DoktorandIn/StipendiatIn (ohne Stelle an einer Hochschule/Forschungsinstitution)
+job_title_4 = LehrbeauftragteR
+job_title_5 = Mitglied einer Fachgesellschaft (ohne Stelle an einer Hochschule/Forschungsinstitution)
+job_title_6 = StudentIn (Bachelor)
+job_title_7 = StudentIn (Master)
+job_title_8 = BibliothekarIn/FachreferentIn in Bibliotheken/ArchivarIn
+job_title_9 = Sonstige
+
+job_title_notice_prefix = Falls Sie Ihre Nutzergruppe aktualisieren möchten, schreiben Sie uns bitte eine
+job_title_notice_suffix = Nachricht
+
+label_college = Hochschule/Einrichtung
+
+label_address_0 = Dienstadresse
+label_address_0_line_1 = Abteilung/Adresszusatz
+label_address_0_line_2 = Straße/Nr.
+label_address_0_zip = PLZ
+label_address_0_city = Ort
+label_address_0_country = Land
+
+label_address_1 = Privatadresse
+label_address_1_line_1 = Straße/Nr.
+label_address_1_line_2 = Adresszusatz
+label_address_1_zip = PLZ
+label_address_1_city = Ort
+label_address_1_country = Land
+
+error_home_address_value = "Dieser Wert wird benötigt."
+
+label_delivery_address = Meine Privatadresse als Lieferadresse verwenden
+label_newsletter = Ja, ich möchte regelmäßig Informationen zu Neuerungen und Neuerscheinungen bei adlr.link per E-Mail erhalten (ca. 1x monatlich).
+
+granted_groups = Zugriff auf
+requested_groups = Zugriff beantragt
+label_access_level_limited_access = Alle Dienstleistungen
+label_access_level_full_access = Alle Dienstleistungen und Lizenzen
+label_access_level_extended_access = Alle Dienstleistungen, Lizenzen und Internsicht
+
+permission_limited_access = "Zugriff auf alle Dienstleistungen"
+permission_full_access = "Zugriff auf alle Dienstleistungen und Lizenzen"
+permission_extended_access = "Zugriff auf alle Dienstleistungen, Lizenzen und Internsicht"
+
+Edit Account = Persönliche Angaben ändern
\ No newline at end of file
diff --git a/themes/fid_adlr/languages/fid/en.ini b/themes/fid_adlr/languages/fid/en.ini
new file mode 100644
index 00000000000..f94e2da4928
--- /dev/null
+++ b/themes/fid_adlr/languages/fid/en.ini
@@ -0,0 +1,51 @@
+user_update_form_title = Change account data
+required_fields_note = All fields marked with an asterisk * are required.
+
+label_job_title = User group
+job_title_0 = Faculty staff (Full/Associate professor, Reader, Senior lecturer)
+job_title_1 = Faculty staff (Assistant professor, Lecturer)
+job_title_2 = Faculty staff (Instructor)
+job_title_3 = Doctoral student/Scholarship holder (without a position at a university/research institution)
+job_title_4 = Adjunct/Visiting Lecturer
+job_title_5 = Member of a scientific association (without position at a university/research institution)
+job_title_6 = Student (Bachelor)
+job_title_7 = Student (Master)
+job_title_8 = Librarian/Subject specialist in libraries/Archivist
+job_title_9 = Other
+
+job_title_notice_prefix = If you would like to update your user group, please send us a
+job_title_notice_suffix = message
+
+label_college = University/institution
+label_salutation = Form of address
+
+label_address_0 = Office address
+label_address_0_line_1 = Department
+label_address_0_line_2 = Street/no.
+label_address_0_zip = Postal code
+label_address_0_city = City
+label_address_0_country = Country
+
+label_address_1 = Home address
+label_address_1_line_1 = Street/no.
+label_address_1_line_2 = Address supplement
+label_address_1_zip = Postal code
+label_address_1_city = City
+label_address_1_country = Country
+
+error_home_address_value = "This value is required."
+
+label_delivery_address = Use my home address as delivery address
+label_newsletter = Yes, I would like to receive regular information about new releases and improvements at adlr.link by e-mail (approx. once a month).
+
+Edit Account = Change account data
+
+granted_groups = Access to
+requested_groups = Access requested
+label_access_level_limited_access = All services
+label_access_level_full_access = All services and licenses
+label_access_level_extended_access = All services and licenses and staff view
+
+permission_limited_access = "Access to all services"
+permission_full_access = "Access to services and licenses"
+permission_extended_access = "Access to all services and licenses and staff view"
\ No newline at end of file
diff --git a/themes/fid_adlr/scss/compiled.scss b/themes/fid_adlr/scss/compiled.scss
index 1e3e6fce155..3a026b2d7ba 100644
--- a/themes/fid_adlr/scss/compiled.scss
+++ b/themes/fid_adlr/scss/compiled.scss
@@ -2118,4 +2118,8 @@ footer {
     background-size: calc(100%/2 + #{$container-lg}/4);
   }
 }
-// +++++ Footer - END
\ No newline at end of file
+// +++++ Footer - END
+
+#user-update-form [name=job_title] + p {
+  padding: 15px;
+}
\ No newline at end of file
diff --git a/themes/fid_adlr/templates/fid/user/create.phtml b/themes/fid_adlr/templates/fid/user/create.phtml
new file mode 100644
index 00000000000..4a4c5b91399
--- /dev/null
+++ b/themes/fid_adlr/templates/fid/user/create.phtml
@@ -0,0 +1,240 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author   Gregor Gawol <gawol@ub.uni-leipzig.de>
+ * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use Zend\Form\Element;
+use Zend\Form\Element\Checkbox;
+use Zend\Form\Element\Submit;
+use Zend\Form\Form;
+use Zend\Form\View\Helper\FormElementErrors;
+use Zend\Form\View\Helper\FormLabel;
+use Zend\Form\View\Helper\FormRadio;
+use Zend\Form\View\Helper\FormSelect;
+use Zend\Form\View\Helper\FormSubmit;
+
+/** @var Form $form */
+/** @var FormLabel $formLabel */
+/** @var FormRadio $formRadio */
+/** @var FormSelect $formSelect */
+/** @var FormSubmit $formSubmit */
+/** @var FormElementErrors $formElementErrors */
+$form = $this->form;
+$formLabel = $this->formLabel();
+$formRadio = $this->formRadio();
+$formSelect = $this->formSelect();
+$formSubmit = $this->formSubmit();
+$formElementErrors = $this->formElementErrors();
+$formLabel->setTranslatorTextDomain('fid');
+$formSelect->setTranslatorTextDomain('fid');
+$formRadio->setTranslatorTextDomain('fid');
+$formSubmit->setTranslatorTextDomain('fid');
+$formElementErrors->setTranslatorTextDomain('fid');
+$this->headTitle($title = $this->translate("fid::user_create_form_title"));
+?>
+
+<h2><?= $title ?></h2>
+<div><?= $this->transEsc("fid::required_fields_note") ?></div>
+<?= $this->flashmessages() ?>
+<?= $this->form()->openTag($form) ?>
+<br/>
+
+<? /* username */ ?>
+<?php
+/** @var Element\Text $elemUsername */
+$elemUsername = $form->get('username');
+$elemUsername->setLabelAttributes(['class' => 'col-md-4']);
+$elemUsername->setAttributes(['class' => 'form-control', 'disabled' => 1]);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemUsername) ?>
+    <?= $this->formElement($elemUsername) ?>
+    <?= $this->formElementErrors($elemUsername) ?>
+    <?php
+    $elemUsername->removeAttribute('disabled');
+    $elemUsername->setAttribute('type', 'hidden');
+    ?>
+    <?= $this->formElement($elemUsername) ?>
+</div>
+
+<? /* password */ ?>
+<?php
+/** @var Element\Password $elemPassword */
+$elemPassword = $form->get('password');
+$elemPassword->setLabelAttributes(['class' => 'col-md-4']);
+$elemPassword->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemPassword) ?>
+    <?= $this->formElement($elemPassword) ?>
+    <?= $this->formElementErrors($elemPassword) ?>
+</div>
+
+<? /* password confirmation */ ?>
+<?php
+/** @var Element\Password $elemPasswordConfirmation */
+$elemPasswordConfirmation = $form->get('password_confirmation');
+$elemPasswordConfirmation->setLabelAttributes(['class' => 'col-md-4']);
+$elemPasswordConfirmation->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemPasswordConfirmation) ?>
+    <?= $this->formElement($elemPasswordConfirmation) ?>
+    <?= $this->formElementErrors($elemPasswordConfirmation) ?>
+</div>
+
+<? /* salutation */ ?>
+<?php
+/** @var Element\Select $elemSalutation */
+$elemSalutation = $form->get('salutation');
+$elemSalutation->setLabelAttributes(['class' => 'col-md-4']);
+$elemSalutation->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemSalutation) ?>
+    <?= $this->formSelect($elemSalutation) ?>
+</div>
+
+<? /* academic title */ ?>
+<?php
+/** @var Element\Text $elemAcademicTitle */
+$elemAcademicTitle = $form->get('academic_title');
+$elemAcademicTitle->setLabelAttributes(['class' => 'col-md-4']);
+$elemAcademicTitle->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemAcademicTitle) ?>
+    <?= $this->formElement($elemAcademicTitle) ?>
+</div>
+
+<? /* firstname */ ?>
+<?php
+/** @var Element\Text $elemFirstname */
+$elemFirstname = $form->get('firstname');
+$elemFirstname->setLabelAttributes(['class' => 'col-md-4']);
+$elemFirstname->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemFirstname) ?>
+    <?= $this->formElement($elemFirstname) ?>
+    <?= $this->formElementErrors($elemFirstname) ?>
+</div>
+
+<? /* lastname */ ?>
+<?php
+/** @var Element\Text $elemLastname */
+$elemLastname = $form->get('lastname');
+$elemLastname->setLabelAttributes(['class' => 'col-md-4']);
+$elemLastname->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemLastname) ?>
+    <?= $this->formElement($elemLastname) ?>
+    <?= $this->formElementErrors($elemLastname) ?>
+</div>
+
+<? /* home library */ ?>
+<?php
+/** @var Element\Select $elemHomeLibrary */
+$elemHomeLibrary = $form->get('home_library');
+$elemHomeLibrary->setLabelAttributes(['class' => 'col-md-4']);
+$elemHomeLibrary->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemHomeLibrary) ?>
+    <?= $this->formSelect($elemHomeLibrary) ?>
+    <?= $this->formElementErrors($elemHomeLibrary) ?>
+</div>
+
+<? /* user group */ ?>
+<?php
+/** @var Element\Radio $elemJobTitle */
+$elemJobTitle = $form->get('job_title');
+$elemJobTitle->setLabelAttributes(['class' => 'col-md-4']);
+$elemJobTitle->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemJobTitle) ?>
+    <?= $this->formSelect($elemJobTitle) ?>
+    <?= $this->formElementErrors($elemJobTitle) ?>
+</div>
+
+<? /* phone */ ?>
+<?php
+/** @var Element\Text $elemPhone */
+$elemPhone = $form->get('data')->get('phone');
+$elemPhone->setLabelAttributes(['class' => 'col-md-4']);
+$elemPhone->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemPhone) ?>
+    <?= $this->formElement($elemPhone) ?>
+    <?= $this->formElementErrors($elemPhone) ?>
+</div>
+
+<? /* addresses */ ?>
+<?= $this->render('address-collection.phtml') ?>
+
+<? /* newsletter */ ?>
+<?php
+/** @var Checkbox $elemNewsletter */
+$elemNewsletter = $form->get('data')->get('newsletter');
+$elemNewsletter->setAttribute('id', 'newsletter');
+?>
+<div class="form-group eula">
+    <div>
+        <?= $this->formElement($elemNewsletter) ?>
+        <?= $this->formLabel($elemNewsletter) ?>
+    </div>
+    <?= $this->formElementErrors($elemNewsletter) ?>
+</div>
+
+<? /* eula privacy policy */ ?>
+<?php
+/** @var Checkbox $elemEulaAccepted */
+$elemEulaAccepted = $form->get('eula_accepted');
+$elemEulaAccepted->setAttribute('id', 'eula-accepted');
+?>
+<div class="form-group eula">
+    <div>
+        <?= $this->formElement($elemEulaAccepted) ?>
+        <?= $this->formLabel()->openTag($elemEulaAccepted) ?>
+        <?= $this->translate("fid::policy_text") ?>
+        <?php $url = $this->url('fid/user/policy') ?>
+        <a data-lightbox
+           href="<?= $url ?>"><?= $this->translate("fid::policy") ?></a>
+        <?= $this->translate("fid::terms_text") ?>
+        <?php $url = $this->url('fid/user/terms') ?>
+        <a data-lightbox
+           href="<?= $url ?>"><?= $this->translate("fid::terms") ?></a>.
+        <?= $this->formLabel()->closeTag($elemEulaAccepted) ?>
+    </div>
+    <?= $this->formElementErrors($elemEulaAccepted) ?>
+</div>
+
+<? /* submit button */ ?>
+<?php
+/** @var Submit $elemSubmit */
+$elemSubmit = $form->get('submit');
+$elemSubmit->setAttributes(['class' => 'btn btn-primary']);
+?>
+
+<div class="form-group"><?= $this->formSubmit($elemSubmit) ?></div>
+<?= $this->form()->closeTag($form) ?>
diff --git a/themes/fid_adlr/templates/fid/user/home-address-fieldset.phtml b/themes/fid_adlr/templates/fid/user/home-address-fieldset.phtml
new file mode 100644
index 00000000000..d2ff25ea31a
--- /dev/null
+++ b/themes/fid_adlr/templates/fid/user/home-address-fieldset.phtml
@@ -0,0 +1,116 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use Zend\Form\Element;
+use Zend\Form\Fieldset;
+
+/** @var Fieldset $address */
+$address = $this->address;
+?>
+
+<h3><?= $this->translate('fid::' . $address->getLabel()) ?></h3>
+
+<? /* id */ ?>
+<?php
+$elemId = $address->get('id');
+if ($elemId->getValue()) {
+    echo $this->formElement($elemId);
+}
+?>
+
+<? /* phone */ ?>
+<?php
+/** @var Element\Text $elemDeliveryAddress */
+$elemDeliveryAddress = $this->form->get('data')->get('delivery_address');
+$elemDeliveryAddress->setAttribute('id', 'delivery_address');
+?>
+<div class="form-group eula">
+    <div>
+        <?= $this->formElement($elemDeliveryAddress) ?>
+        <?= $this->formLabel($elemDeliveryAddress) ?>
+    </div>
+    <?= $this->formElementErrors($elemDeliveryAddress) ?>
+</div>
+
+<? /* first line */ ?>
+<?php
+/** @var Element\Text $elemLine1 */
+$elemLine1 = $address->get('line1');
+$elemLine1->setLabelAttributes(['class' => 'col-md-4']);
+$elemLine1->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemLine1) ?>
+    <?= $this->formElement($elemLine1) ?>
+    <?= $this->formElementErrors($elemLine1) ?>
+</div>
+
+<? /* second line */ ?>
+<?php
+/** @var Element\Text $elemLine2 */
+$elemLine2 = $address->get('line2');
+$elemLine2->setLabelAttributes(['class' => 'col-md-4']);
+$elemLine2->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemLine2) ?>
+    <?= $this->formElement($elemLine2) ?>
+    <?= $this->formElementErrors($elemLine2) ?>
+</div>
+
+<? /* address zip */ ?>
+<?php
+/** @var Element\Text $elemZip */
+$elemZip = $address->get('zip');
+$elemZip->setLabelAttributes(['class' => 'col-md-4']);
+$elemZip->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemZip) ?>
+    <?= $this->formElement($elemZip) ?>
+    <?= $this->formElementErrors($elemZip) ?>
+</div>
+
+<? /* city */ ?>
+<?php
+/** @var Element\Text $elemCity */
+$elemCity = $address->get('city');
+$elemCity->setLabelAttributes(['class' => 'col-md-4']);
+$elemCity->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemCity) ?>
+    <?= $this->formElement($elemCity) ?>
+    <?= $this->formElementErrors($elemCity) ?>
+</div>
+
+<? /* country */ ?>
+<?php
+/** @var Element\Text $elemCountry */
+$elemCountry = $address->get('country');
+$elemCountry->setLabelAttributes(['class' => 'col-md-4']);
+$elemCountry->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemCountry) ?>
+    <?= $this->formElement($elemCountry) ?>
+    <?= $this->formElementErrors($elemCountry) ?>
+</div>
diff --git a/themes/fid_adlr/templates/fid/user/office-address-fieldset.phtml b/themes/fid_adlr/templates/fid/user/office-address-fieldset.phtml
new file mode 100644
index 00000000000..4a46f71455e
--- /dev/null
+++ b/themes/fid_adlr/templates/fid/user/office-address-fieldset.phtml
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use fid\Service\DataTransferObject\Address;
+use Zend\Form\Fieldset;
+use Zend\Form\Element;
+
+/** @var Fieldset $address */
+$address = $this->address;
+?>
+
+<h3><?= $this->translate('fid::' . $address->getLabel()) ?></h3>
+
+<? /* id */ ?>
+<?= $this->formElement($address->get('id')) ?>
+
+<? /* third line */ ?>
+<?php
+/** @var Element\Text $college */
+$college = $this->form->get('college');
+$college->setLabelAttributes(['class' => 'col-md-4']);
+$college->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+  <?= $this->formLabel($college) ?>
+  <?= $this->formElement($college) ?>
+  <?= $this->formElementErrors($college) ?>
+</div>
+
+<? /* first line */ ?>
+<?php
+/** @var Element\Text $elemLine1 */
+$elemLine1 = $address->get('line1');
+$elemLine1->setLabelAttributes(['class' => 'col-md-4']);
+$elemLine1->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+  <?= $this->formLabel($elemLine1) ?>
+  <?= $this->formElement($elemLine1) ?>
+  <?= $this->formElementErrors($elemLine1) ?>
+</div>
+
+<? /* second line */ ?>
+<?php
+/** @var Element\Text $elemLine2 */
+$elemLine2 = $address->get('line2');
+$elemLine2->setLabelAttributes(['class' => 'col-md-4']);
+$elemLine2->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+  <?= $this->formLabel($elemLine2) ?>
+  <?= $this->formElement($elemLine2) ?>
+  <?= $this->formElementErrors($elemLine2) ?>
+</div>
+
+<? /* address zip */ ?>
+<?php
+/** @var Element\Text $elemZip */
+$elemZip = $address->get('zip');
+$elemZip->setLabelAttributes(['class' => 'col-md-4']);
+$elemZip->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+  <?= $this->formLabel($elemZip) ?>
+  <?= $this->formElement($elemZip) ?>
+  <?= $this->formElementErrors($elemZip) ?>
+</div>
+
+<? /* city */ ?>
+<?php
+/** @var Element\Text $elemCity */
+$elemCity = $address->get('city');
+$elemCity->setLabelAttributes(['class' => 'col-md-4']);
+$elemCity->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+  <?= $this->formLabel($elemCity) ?>
+  <?= $this->formElement($elemCity) ?>
+  <?= $this->formElementErrors($elemCity) ?>
+</div>
+
+<? /* country */ ?>
+<?php
+/** @var Element\Text $elemCountry */
+$elemCountry = $address->get('country');
+$elemCountry->setLabelAttributes(['class' => 'col-md-4']);
+$elemCountry->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+  <?= $this->formLabel($elemCountry) ?>
+  <?= $this->formElement($elemCountry) ?>
+  <?= $this->formElementErrors($elemCountry) ?>
+</div>
diff --git a/themes/fid_adlr/templates/fid/user/update.phtml b/themes/fid_adlr/templates/fid/user/update.phtml
new file mode 100644
index 00000000000..79862f41373
--- /dev/null
+++ b/themes/fid_adlr/templates/fid/user/update.phtml
@@ -0,0 +1,192 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author   Gregor Gawol <gawol@ub.uni-leipzig.de>
+ * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use Zend\Form\Element;
+use Zend\Form\Element\Checkbox;
+use Zend\Form\Element\Submit;
+use Zend\Form\Form;
+use Zend\Form\View\Helper\FormElementErrors;
+use Zend\Form\View\Helper\FormLabel;
+use Zend\Form\View\Helper\FormRadio;
+use Zend\Form\View\Helper\FormSelect;
+use Zend\Form\View\Helper\FormSubmit;
+
+/** @var Form $form */
+/** @var FormLabel $formLabel */
+/** @var FormRadio $formRadio */
+/** @var FormSelect $formSelect */
+/** @var FormSubmit $formSubmit */
+/** @var FormElementErrors $formElementErrors */
+$form = $this->form;
+$formLabel = $this->formLabel();
+$formRadio = $this->formRadio();
+$formSelect = $this->formSelect();
+$formSubmit = $this->formSubmit();
+$formElementErrors = $this->formElementErrors();
+$formLabel->setTranslatorTextDomain('fid');
+$formSelect->setTranslatorTextDomain('fid');
+$formRadio->setTranslatorTextDomain('fid');
+$formSubmit->setTranslatorTextDomain('fid');
+$formElementErrors->setTranslatorTextDomain('fid');
+$this->headTitle($title = $this->translate("fid::user_update_form_title"));
+?>
+
+<h2><?= $title ?></h2>
+<div><?= $this->transEsc("fid::required_fields_note") ?></div>
+<?= $this->flashmessages() ?>
+<?= $this->form()->openTag($form) ?>
+<br/>
+
+<? /* id */ ?>
+<?= $this->formElement($form->get('id')) ?>
+
+<? /* salutation */ ?>
+<?php
+/** @var Element\Select $elemSalutation */
+$elemSalutation = $form->get('salutation');
+$elemSalutation->setLabelAttributes(['class' => 'col-md-4']);
+$elemSalutation->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemSalutation) ?>
+    <?= $this->formSelect($elemSalutation) ?>
+</div>
+
+<? /* academic title */ ?>
+<?php
+/** @var Element\Text $elemAcademicTitle */
+$elemAcademicTitle = $form->get('academic_title');
+$elemAcademicTitle->setLabelAttributes(['class' => 'col-md-4']);
+$elemAcademicTitle->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemAcademicTitle) ?>
+    <?= $this->formElement($elemAcademicTitle) ?>
+</div>
+
+<? /* firstname */ ?>
+<?php
+/** @var Element\Text $elemFirstname */
+$elemFirstname = $form->get('firstname');
+$elemFirstname->setLabelAttributes(['class' => 'col-md-4']);
+$elemFirstname->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemFirstname) ?>
+    <?= $this->formElement($elemFirstname) ?>
+    <?= $this->formElementErrors($elemFirstname) ?>
+</div>
+
+<? /* lastname */ ?>
+<?php
+/** @var Element\Text $elemLastname */
+$elemLastname = $form->get('lastname');
+$elemLastname->setLabelAttributes(['class' => 'col-md-4']);
+$elemLastname->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemLastname) ?>
+    <?= $this->formElement($elemLastname) ?>
+    <?= $this->formElementErrors($elemLastname) ?>
+</div>
+
+<? /* home library */ ?>
+<?php
+/** @var Element\Select $elemHomeLibrary */
+$elemHomeLibrary = $form->get('home_library');
+$elemHomeLibrary->setLabelAttributes(['class' => 'col-md-4']);
+$elemHomeLibrary->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemHomeLibrary) ?>
+    <?= $this->formSelect($elemHomeLibrary) ?>
+    <?= $this->formElementErrors($elemHomeLibrary) ?>
+</div>
+
+<? /* user group */ ?>
+<?php
+/** @var Element\Select $elemJobTitle */
+$elemJobTitle = $form->get('job_title');
+$elemJobTitle->setLabelAttributes(['class' => 'col-md-4']);
+$elemJobTitle->setAttributes(['class' => 'form-control']);
+?>
+
+<div class="form-group">
+    <?= $this->formLabel($elemJobTitle) ?>
+    <?= $this->formElement($elemJobTitle) ?>
+    <?= $this->formElementErrors($elemJobTitle) ?>
+    <p>
+        <span>
+            <?= $this->translate('fid::job_title_notice_prefix') ?>
+        </span>
+        <a target="_blank" href="<?= $this->url('fid/user/update') ?>">
+            <?= $this->translate('fid::job_title_notice_suffix') ?></a>.
+    </p>
+</div>
+
+<? /* phone */ ?>
+<?php
+/** @var Element\Text $elemPhone */
+$elemPhone = $form->get('data')->get('phone');
+$elemPhone->setLabelAttributes(['class' => 'col-md-4']);
+$elemPhone->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemPhone) ?>
+    <?= $this->formElement($elemPhone) ?>
+    <?= $this->formElementErrors($elemPhone) ?>
+</div>
+
+<? /* addresses */ ?>
+<?= $this->render('address-collection.phtml') ?>
+
+<? /* newsletter */ ?>
+<?php
+/** @var Checkbox $elemNewsletter */
+$elemNewsletter = $form->get('data')->get('newsletter');
+$elemNewsletter->setAttribute('id', 'newsletter');
+?>
+<div class="form-group eula">
+    <div>
+        <?= $this->formElement($elemNewsletter) ?>
+        <?= $this->formLabel($elemNewsletter) ?>
+    </div>
+    <?= $this->formElementErrors($elemNewsletter) ?>
+</div>
+
+<? /* submit button */ ?>
+<?php
+/** @var Submit $elemSubmit */
+$elemSubmit = $form->get('submit');
+$elemSubmit->setAttributes(['class' => 'btn btn-primary']);
+?>
+<div class="form-group">
+    <div class="col-lg-11 col-md-9 col-sm-11 col-xs-12">
+        <?= $this->formSubmit($elemSubmit) ?>
+        <a href="<?= $this->url('myresearch-profile') ?>"
+           class="btn btn-primary">
+            <?= $this->transEsc('Cancel') ?>
+        </a>
+    </div>
+</div>
+
+<?= $this->form()->closeTag($form) ?>
diff --git a/themes/fid_adlr/templates/myresearch/profile.phtml b/themes/fid_adlr/templates/myresearch/profile.phtml
new file mode 100644
index 00000000000..b6365decbd8
--- /dev/null
+++ b/themes/fid_adlr/templates/myresearch/profile.phtml
@@ -0,0 +1,56 @@
+<!-- finc: myresearch - profile -->
+<?php
+// Set up page title:
+$this->headTitle($this->translate('My Profile'));
+
+// Set up breadcrumbs:
+$this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Profile') . '</li>';
+
+// Template for use by the renderArray helper:
+$arrTemplate = '<tr><th>%%LABEL%%:</th><td> %%VALUE%%</td></tr>';
+
+$profile = $this->profile;
+if (is_array($profile)) {
+    $groups = $this->UserGroups($profile['user']->getPermissions());
+    $profile['group'] = $groups->granted();
+    $profile['requested_group'] = $groups->requested();
+    $profile['job_title'] = $this->translate('fid::job_title_' . $profile['user']->getJobTitle());
+    $profile['home_library'] = $profile['libs'][$profile['user']->getHomeLibrary()]->getLabel();
+    $profile['college'] = $profile['user']->getCollege();
+}
+?>
+
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('Your Profile')?></h2>
+  <?=$this->flashmessages();?>
+  <?php if (is_array($this->profile)): ?>
+    <table class="table table-striped">
+      <?=$this->renderArray(
+        $arrTemplate,
+        $profile,
+        array_merge(
+          [
+            $this->transEsc('fid::label_username') => 'email',
+          ],
+          $profile['firstname'] ? [$this->transEsc('fid::label_firstname') => 'firstname'] : [],
+          $profile['lastname'] ? [$this->transEsc('fid::label_lastname') => 'lastname'] : [],
+          [
+            $this->transEsc('fid::label_college') => 'college',
+            $this->transEsc('fid::label_home_library') => 'home_library',
+            $this->transEsc('fid::label_job_title') => 'job_title',
+            $this->transEsc('fid::granted_groups') => 'group',
+            $this->transEsc('fid::requested_groups') => 'requested_group'
+          ]
+        )
+      )?>
+  </table>
+  <a href="<?=$this->url('fid/user/update')?>" class="btn btn-primary"><?=$this->transEsc('fid::Edit Account')?></a>
+  <?php elseif ('ils-none' !== $this->ils()->getOfflineMode() && $this->patronLoginView && !empty($this->patronLoginView->getTemplate())): ?>
+    <?=$this->partial($this->patronLoginView);?>
+  <?php endif; ?>
+</div>
+
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'profile'])?>
+</div>
+<!-- finc: myresearch - profile - END -->
-- 
GitLab