diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php
new file mode 100644
index 000000000..4414dc476
--- /dev/null
+++ b/src/Controller/DashboardController.php
@@ -0,0 +1,119 @@
+Auth->allow(['add', 'edit']);
+ $this->Auth->allow('index');
+ }
+ /**
+ * Index method
+ *
+ * @return \Cake\Http\Response|null
+ */
+ public function index()
+ {
+ $startTime = microtime(true);
+ $this->viewBuilder()->setLayout('frontend');
+ $session = $this->getRequest()->getSession();
+ // check login
+ // disable encryption for cookies
+ //$this->Cookie->configKey('User', 'encryption', false);
+ //$this->Cookie->read('GRADIDO_LOGIN');
+ $session_id = intval($this->request->getCookie('GRADIDO_LOGIN', ''));
+ $ip = $this->request->clientIp();
+ if(!$session->check('client_ip')) {
+ $session->write('client_ip', $ip);
+ }
+
+ // login server cannot detect host ip
+ //echo "client ip: $ip
";
+ //echo $session_id;
+ if($session_id != 0 && $session->read('session_id') != $session_id) {
+
+ $http = new Client();
+ try {
+ $loginServer = Configure::read('LoginServer');
+ $url = $loginServer['host'] . ':' . $loginServer['port'];
+ //$url = 'http://***REMOVED***';
+ $response = $http->get($url . '/login', ['session_id' => $session_id]);
+ $json = $response->getJson();
+
+ if(isset($json) && count($json) > 0) {
+
+ if($json['state'] === 'success' && intval($json['user']['email_checked']) === 1) {
+ //echo "email checked: " . $json['user']['email_checked'] . ";
";
+ $session->destroy();
+ foreach($json['user'] as $key => $value) {
+ if($key === 'state') { continue; }
+ $session->write('StateUser.' . $key, $value );
+ }
+ $session->write('session_id', $session_id);
+ $stateUserTable = TableRegistry::getTableLocator()->get('StateUsers');
+ if($json['user']['public_hex'] != '') {
+ $public_key_bin = hex2bin($json['user']['public_hex']);
+ $stateUserQuery = $stateUserTable->find('all')->where(['public_key' => $public_key_bin]);
+ if($stateUserQuery->count() == 1) {
+ $stateUser = $stateUserQuery->first();
+ $session->write('StateUser.id', $stateUser['id']);
+ //echo $stateUser['id'];
+ } else {
+ $newStateUser = $stateUserTable->newEntity();
+ $newStateUser->public_key = $public_key_bin;
+ $newStateUser->first_name = $json['user']['first_name'];
+ $newStateUser->last_name = $json['user']['last_name'];
+ $stateUserTable->save($newStateUser);
+ $session->write('StateUser.id', $newStateUser->id);
+ //echo $newStateUser->id;
+ }
+ }
+
+
+ // for debugging
+
+ $this->set('user', $json['user']);
+ $this->set('json', $json);
+ $this->set('timeUsed', microtime(true) - $startTime);
+
+ } else {
+ if($json['state'] === 'not found' ) {
+ $this->Flash->error(__('invalid session'));
+ //echo $json['user']['email_checked'];
+ //var_dump($json);
+ //
+ return $this->redirect(Router::url('/', true) . 'account/', 303);
+ }
+ }
+ }
+
+ } catch(\Exception $e) {
+ $msg = $e->getMessage();
+ $this->Flash->error(__('error http request: ') . $msg);
+
+ //continue;
+ }
+
+ } else {
+ return $this->redirect(Router::url('/', true) . 'account/', 303);
+ }
+ }
+
+
+}
diff --git a/src/Form/CreationForm.php b/src/Form/CreationForm.php
new file mode 100644
index 000000000..5bf2fef33
--- /dev/null
+++ b/src/Form/CreationForm.php
@@ -0,0 +1,66 @@
+addField('receiver_pubkey_hex', ['type' => 'string'])
+ ->addField('receiver', ['type' => 'select'])
+ ->addField('amount', ['type' => 'decimal', 'precision' => 2])
+ ->addField('memo', ['type' =>'string', 'default' => '']);
+ }
+
+ function validationDefault(Validator $validator)
+ {
+ $validator->setProvider('custom', 'App\Model\Validation\TransactionValidation');
+ /*
+ $validator->add('receiver_pubkey_hex', 'length', [
+ 'rule' => ['length', 64],
+ 'message' => 'a valid pubkey in hex format is required (64 character)'
+ ])->add('receiver_pubkey_hex_select', 'length', [
+ 'rule' => ['length', 64],
+ 'message' => 'a valid pubkey in hex format is required (64 character)',
+ ]);
+*/
+ // TODO: add validation for used character to prevent hacking attempts
+ $validator->add('memo', 'length', [
+ 'rule' => ['maxLength', 150],
+ 'message' => 'max 150 character'
+ ])
+ ->ascii('memo', __('Only Ascii Character allowed'))
+ ->allowEmptyString('memo', null, 'create')
+ ->add('receiver_pubkey_hex', 'custom', [
+ 'rule' => 'hexKey64',
+ 'provider' => 'custom',
+ 'message' => 'a valid pubkey in hex format is required (64 character)'
+ ])
+ ->allowEmptyString('receiver_pubkey_hex', null, 'create')
+ ->add('amount', 'custom', [
+ 'rule' => 'amount',
+ 'provider' => 'custom',
+ 'message' => __('Please give a valid number with maximal 2 decimal places')
+ ]);
+ return $validator;
+ }
+ /*
+ * $validator->add('title', 'custom', [
+ 'rule' => 'customRule',
+ 'provider' => 'custom',
+ 'message' => 'The title is not unique enough'
+]);
+ */
+
+ protected function _execute(array $data)
+ {
+ // Send an email.
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/Model/Validation/TransactionValidation.php b/src/Model/Validation/TransactionValidation.php
new file mode 100644
index 000000000..aba5828a1
--- /dev/null
+++ b/src/Model/Validation/TransactionValidation.php
@@ -0,0 +1,33 @@
+ 'en_GB']);
+ $numberparts = preg_split('/\./', $checkFloatVal);
+ //var_dump($numberparts);
+ if(isset($numberparts[1]) && strlen($numberparts[1]) > 2) return false;
+
+ $floatVal = floatval(Number::format($value, ['places' => 4, 'locale' => 'en_GB']));
+ //echo "floatVal: $floatVal
";
+ return $floatVal != 0.0;
+ }
+
+ public static function hexKey64($value, array $context) {
+ if(strlen($value) != 64) return false;
+ if(preg_match('/^[[:xdigit:]]*$/', $value)) {
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/Template/Dashboard/index.ctp b/src/Template/Dashboard/index.ctp
new file mode 100644
index 000000000..39e20243c
--- /dev/null
+++ b/src/Template/Dashboard/index.ctp
@@ -0,0 +1,25 @@
+
+