summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/Auth/Ldap.php2
-rw-r--r--app/Controller/User.php4
-rw-r--r--app/Core/Lexer.php2
-rw-r--r--app/Locale/da_DK/translations.php2
-rw-r--r--app/Locale/de_DE/translations.php2
-rw-r--r--app/Locale/es_ES/translations.php2
-rw-r--r--app/Locale/fi_FI/translations.php2
-rw-r--r--app/Locale/fr_FR/translations.php2
-rw-r--r--app/Locale/hu_HU/translations.php2
-rw-r--r--app/Locale/it_IT/translations.php2
-rw-r--r--app/Locale/ja_JP/translations.php2
-rw-r--r--app/Locale/nl_NL/translations.php2
-rw-r--r--app/Locale/pl_PL/translations.php2
-rw-r--r--app/Locale/pt_BR/translations.php2
-rw-r--r--app/Locale/ru_RU/translations.php2
-rw-r--r--app/Locale/sr_Latn_RS/translations.php2
-rw-r--r--app/Locale/sv_SE/translations.php2
-rw-r--r--app/Locale/th_TH/translations.php2
-rw-r--r--app/Locale/tr_TR/translations.php2
-rw-r--r--app/Locale/zh_CN/translations.php2
-rw-r--r--app/Model/TaskFilter.php80
-rw-r--r--app/Model/TaskFinder.php3
-rw-r--r--app/Model/User.php8
-rw-r--r--app/Template/listing/show.php18
-rw-r--r--app/Template/search/results.php20
-rw-r--r--app/Template/user/create_local.php (renamed from app/Template/user/new.php)1
-rw-r--r--app/Template/user/create_remote.php57
-rw-r--r--app/Template/user/index.php3
-rw-r--r--app/Template/user/layout.php3
-rw-r--r--app/constants.php1
30 files changed, 205 insertions, 31 deletions
diff --git a/app/Auth/Ldap.php b/app/Auth/Ldap.php
index 3ee6ec9b..c1459b4e 100644
--- a/app/Auth/Ldap.php
+++ b/app/Auth/Ldap.php
@@ -46,7 +46,7 @@ class Ldap extends Base
else {
// We create automatically a new user
- if ($this->createUser($username, $result['name'], $result['email'])) {
+ if (LDAP_ACCOUNT_CREATION && $this->createUser($username, $result['name'], $result['email'])) {
$user = $this->user->getByUsername($username);
}
else {
diff --git a/app/Controller/User.php b/app/Controller/User.php
index 189d068d..10a3a931 100644
--- a/app/Controller/User.php
+++ b/app/Controller/User.php
@@ -60,7 +60,9 @@ class User extends Base
*/
public function create(array $values = array(), array $errors = array())
{
- $this->response->html($this->template->layout('user/new', array(
+ $is_remote = $this->request->getIntegerParam('remote') == 1 || (isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1);
+
+ $this->response->html($this->template->layout($is_remote ? 'user/create_remote' : 'user/create_local', array(
'timezones' => $this->config->getTimezones(true),
'languages' => $this->config->getLanguages(true),
'board_selector' => $this->projectPermission->getAllowedProjects($this->userSession->getId()),
diff --git a/app/Core/Lexer.php b/app/Core/Lexer.php
index 3887dc82..0a237254 100644
--- a/app/Core/Lexer.php
+++ b/app/Core/Lexer.php
@@ -33,6 +33,7 @@ class Lexer
"/^(category:)/" => 'T_CATEGORY',
"/^(column:)/" => 'T_COLUMN',
"/^(project:)/" => 'T_PROJECT',
+ "/^(swimlane:)/" => 'T_SWIMLANE',
"/^(ref:)/" => 'T_REFERENCE',
"/^(reference:)/" => 'T_REFERENCE',
"/^(\s+)/" => 'T_WHITESPACE',
@@ -116,6 +117,7 @@ class Lexer
case 'T_CATEGORY':
case 'T_COLUMN':
case 'T_PROJECT':
+ case 'T_SWIMLANE':
$next = next($tokens);
if ($next !== false && $next['token'] === 'T_STRING') {
diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php
index c40574d9..5f55f3e8 100644
--- a/app/Locale/da_DK/translations.php
+++ b/app/Locale/da_DK/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php
index 37f759b2..90c029ba 100644
--- a/app/Locale/de_DE/translations.php
+++ b/app/Locale/de_DE/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php
index f5259012..a2efe2c5 100644
--- a/app/Locale/es_ES/translations.php
+++ b/app/Locale/es_ES/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php
index 4093947f..ddbb26c3 100644
--- a/app/Locale/fi_FI/translations.php
+++ b/app/Locale/fi_FI/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php
index 558c4f4d..1c4c76ee 100644
--- a/app/Locale/fr_FR/translations.php
+++ b/app/Locale/fr_FR/translations.php
@@ -998,4 +998,6 @@ return array(
'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => 'Si vous cochez la case « Interdir le formulaire d\'authentification », les identifiants entrés dans le formulaire d\'authentification seront ignorés.',
'By @%s on Gitlab' => 'Par @%s sur Gitlab',
'Gitlab issue comment created' => 'Commentaire créé sur un ticket Gitlab',
+ 'New remote user' => 'Créer un utilisateur distant',
+ 'New local user' => 'Créer un utilisateur local',
);
diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php
index 5d82f3e1..f1bd1453 100644
--- a/app/Locale/hu_HU/translations.php
+++ b/app/Locale/hu_HU/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php
index 5493d218..6dd60c18 100644
--- a/app/Locale/it_IT/translations.php
+++ b/app/Locale/it_IT/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php
index 3ced5ea1..e52f82b6 100644
--- a/app/Locale/ja_JP/translations.php
+++ b/app/Locale/ja_JP/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php
index 688f988d..ed8be05b 100644
--- a/app/Locale/nl_NL/translations.php
+++ b/app/Locale/nl_NL/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php
index c61ec77c..9f8641a0 100644
--- a/app/Locale/pl_PL/translations.php
+++ b/app/Locale/pl_PL/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php
index b5f4d0e0..68de0368 100644
--- a/app/Locale/pt_BR/translations.php
+++ b/app/Locale/pt_BR/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php
index 40e49952..3b7d678c 100644
--- a/app/Locale/ru_RU/translations.php
+++ b/app/Locale/ru_RU/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php
index 7a731c15..f3369341 100644
--- a/app/Locale/sr_Latn_RS/translations.php
+++ b/app/Locale/sr_Latn_RS/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php
index 73c94287..db552359 100644
--- a/app/Locale/sv_SE/translations.php
+++ b/app/Locale/sv_SE/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php
index ae81e16a..c4d608bd 100644
--- a/app/Locale/th_TH/translations.php
+++ b/app/Locale/th_TH/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php
index 61210ddd..afb88744 100644
--- a/app/Locale/tr_TR/translations.php
+++ b/app/Locale/tr_TR/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php
index 37bbda95..cd2518fd 100644
--- a/app/Locale/zh_CN/translations.php
+++ b/app/Locale/zh_CN/translations.php
@@ -996,4 +996,6 @@ return array(
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
// 'By @%s on Gitlab' => '',
// 'Gitlab issue comment created' => '',
+ // 'New remote user' => '',
+ // 'New local user' => '',
);
diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php
index 377ec3c6..0dbadbf8 100644
--- a/app/Model/TaskFilter.php
+++ b/app/Model/TaskFilter.php
@@ -71,6 +71,9 @@ class TaskFilter extends Base
case 'T_REFERENCE':
$this->filterByReference($value);
break;
+ case 'T_SWIMLANE':
+ $this->filterBySwimlaneName($value);
+ break;
}
}
@@ -101,6 +104,25 @@ class TaskFilter extends Base
}
/**
+ * Create a new subtask query
+ *
+ * @access public
+ * @return \PicoDb\Table
+ */
+ public function createSubtaskQuery()
+ {
+ return $this->db->table(Subtask::TABLE)
+ ->columns(
+ Subtask::TABLE.'.user_id',
+ Subtask::TABLE.'.task_id',
+ User::TABLE.'.name',
+ User::TABLE.'.username'
+ )
+ ->join(User::TABLE, 'id', 'user_id', Subtask::TABLE)
+ ->neq(Subtask::TABLE.'.status', Subtask::STATUS_DONE);
+ }
+
+ /**
* Clone the filter
*
* @access public
@@ -247,6 +269,30 @@ class TaskFilter extends Base
}
/**
+ * Filter by swimlane name
+ *
+ * @access public
+ * @param array $values List of swimlane name
+ * @return TaskFilter
+ */
+ public function filterBySwimlaneName(array $values)
+ {
+ $this->query->beginOr();
+
+ foreach ($values as $swimlane) {
+ if ($swimlane === 'default') {
+ $this->query->eq(Task::TABLE.'.swimlane_id', 0);
+ }
+ else {
+ $this->query->ilike(Swimlane::TABLE.'.name', $swimlane);
+ $this->query->addCondition(Task::TABLE.'.swimlane_id=0 AND '.Project::TABLE.'.default_swimlane '.$this->db->getDriver()->getOperator('ILIKE')." '$swimlane'");
+ }
+ }
+
+ $this->query->closeOr();
+ }
+
+ /**
* Filter by category id
*
* @access public
@@ -313,7 +359,6 @@ class TaskFilter extends Base
$this->query->beginOr();
foreach ($values as $assignee) {
-
switch ($assignee) {
case 'me':
$this->query->eq(Task::TABLE.'.owner_id', $this->userSession->getId());
@@ -327,7 +372,40 @@ class TaskFilter extends Base
}
}
+ $this->filterBySubtaskAssignee($values);
+
$this->query->closeOr();
+
+ return $this;
+ }
+
+ /**
+ * Filter by subtask assignee names
+ *
+ * @access public
+ * @param array $values List of assignees
+ * @return TaskFilter
+ */
+ public function filterBySubtaskAssignee(array $values)
+ {
+ $subtaskQuery = $this->createSubtaskQuery();
+ $subtaskQuery->beginOr();
+
+ foreach ($values as $assignee) {
+ if ($assignee === 'me') {
+ $subtaskQuery->eq(Subtask::TABLE.'.user_id', $this->userSession->getId());
+ }
+ else {
+ $subtaskQuery->ilike(User::TABLE.'.username', '%'.$assignee.'%');
+ $subtaskQuery->ilike(User::TABLE.'.name', '%'.$assignee.'%');
+ }
+ }
+
+ $subtaskQuery->closeOr();
+
+ $this->query->in(Task::TABLE.'.id', $subtaskQuery->findAllByColumn('task_id'));
+
+ return $this;
}
/**
diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php
index 2b0453a5..47a67a35 100644
--- a/app/Model/TaskFinder.php
+++ b/app/Model/TaskFinder.php
@@ -88,11 +88,14 @@ class TaskFinder extends Base
Category::TABLE.'.name AS category_name',
Category::TABLE.'.description AS category_description',
Board::TABLE.'.title AS column_name',
+ Swimlane::TABLE.'.name AS swimlane_name',
+ Project::TABLE.'.default_swimlane',
Project::TABLE.'.name AS project_name'
)
->join(User::TABLE, 'id', 'owner_id', Task::TABLE)
->join(Category::TABLE, 'id', 'category_id', Task::TABLE)
->join(Board::TABLE, 'id', 'column_id', Task::TABLE)
+ ->join(Swimlane::TABLE, 'id', 'swimlane_id', Task::TABLE)
->join(Project::TABLE, 'id', 'project_id', Task::TABLE);
}
diff --git a/app/Model/User.php b/app/Model/User.php
index 36b7194c..b6804abc 100644
--- a/app/Model/User.php
+++ b/app/Model/User.php
@@ -377,6 +377,7 @@ class User extends Base
new Validators\Unique('username', t('The username must be unique'), $this->db->getConnection(), self::TABLE, 'id'),
new Validators\Email('email', t('Email address invalid')),
new Validators\Integer('is_admin', t('This value must be an integer')),
+ new Validators\Integer('is_ldap_user', t('This value must be an integer')),
);
}
@@ -409,7 +410,12 @@ class User extends Base
new Validators\Required('username', t('The username is required')),
);
- $v = new Validator($values, array_merge($rules, $this->commonValidationRules(), $this->commonPasswordValidationRules()));
+ if (isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1) {
+ $v = new Validator($values, array_merge($rules, $this->commonValidationRules()));
+ }
+ else {
+ $v = new Validator($values, array_merge($rules, $this->commonValidationRules(), $this->commonPasswordValidationRules()));
+ }
return array(
$v->execute(),
diff --git a/app/Template/listing/show.php b/app/Template/listing/show.php
index 06940678..fc8a607b 100644
--- a/app/Template/listing/show.php
+++ b/app/Template/listing/show.php
@@ -10,13 +10,12 @@
<table class="table-fixed table-small">
<tr>
<th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th>
- <th class="column-8"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th>
- <th class="column-8"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th>
+ <th class="column-10"><?= $paginator->order(t('Swimlane'), 'tasks.swimlane_id') ?></th>
+ <th class="column-10"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th>
+ <th class="column-10"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th>
<th><?= $paginator->order(t('Title'), 'tasks.title') ?></th>
<th class="column-10"><?= $paginator->order(t('Assignee'), 'users.username') ?></th>
<th class="column-10"><?= $paginator->order(t('Due date'), 'tasks.date_due') ?></th>
- <th class="column-10"><?= $paginator->order(t('Date created'), 'tasks.date_creation') ?></th>
- <th class="column-10"><?= $paginator->order(t('Date completed'), 'tasks.date_completed') ?></th>
<th class="column-5"><?= $paginator->order(t('Status'), 'tasks.is_active') ?></th>
</tr>
<?php foreach ($paginator->getCollection() as $task): ?>
@@ -25,6 +24,9 @@
<?= $this->url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?>
</td>
<td>
+ <?= $this->e($task['swimlane_name'] ?: $task['default_swimlane']) ?>
+ </td>
+ <td>
<?= $this->e($task['column_name']) ?>
</td>
<td>
@@ -44,14 +46,6 @@
<?= dt('%B %e, %Y', $task['date_due']) ?>
</td>
<td>
- <?= dt('%B %e, %Y', $task['date_creation']) ?>
- </td>
- <td>
- <?php if ($task['date_completed']): ?>
- <?= dt('%B %e, %Y', $task['date_completed']) ?>
- <?php endif ?>
- </td>
- <td>
<?php if ($task['is_active'] == \Model\Task::STATUS_OPEN): ?>
<?= t('Open') ?>
<?php else: ?>
diff --git a/app/Template/search/results.php b/app/Template/search/results.php
index 1d8cc6e2..04cb6a19 100644
--- a/app/Template/search/results.php
+++ b/app/Template/search/results.php
@@ -1,14 +1,13 @@
<table class="table-fixed table-small">
<tr>
<th class="column-8"><?= $paginator->order(t('Project'), 'tasks.project_id') ?></th>
- <th class="column-8"><?= $paginator->order(t('Id'), 'tasks.id') ?></th>
- <th class="column-8"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th>
- <th class="column-8"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th>
+ <th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th>
+ <th class="column-10"><?= $paginator->order(t('Swimlane'), 'tasks.swimlane_id') ?></th>
+ <th class="column-10"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th>
+ <th class="column-10"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th>
<th><?= $paginator->order(t('Title'), 'tasks.title') ?></th>
<th class="column-10"><?= $paginator->order(t('Assignee'), 'users.username') ?></th>
<th class="column-10"><?= $paginator->order(t('Due date'), 'tasks.date_due') ?></th>
- <th class="column-10"><?= $paginator->order(t('Date created'), 'tasks.date_creation') ?></th>
- <th class="column-10"><?= $paginator->order(t('Date completed'), 'tasks.date_completed') ?></th>
<th class="column-5"><?= $paginator->order(t('Status'), 'tasks.is_active') ?></th>
</tr>
<?php foreach ($paginator->getCollection() as $task): ?>
@@ -20,6 +19,9 @@
<?= $this->url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?>
</td>
<td>
+ <?= $this->e($task['swimlane_name'] ?: $task['default_swimlane']) ?>
+ </td>
+ <td>
<?= $this->e($task['column_name']) ?>
</td>
<td>
@@ -39,14 +41,6 @@
<?= dt('%B %e, %Y', $task['date_due']) ?>
</td>
<td>
- <?= dt('%B %e, %Y', $task['date_creation']) ?>
- </td>
- <td>
- <?php if ($task['date_completed']): ?>
- <?= dt('%B %e, %Y', $task['date_completed']) ?>
- <?php endif ?>
- </td>
- <td>
<?php if ($task['is_active'] == \Model\Task::STATUS_OPEN): ?>
<?= t('Open') ?>
<?php else: ?>
diff --git a/app/Template/user/new.php b/app/Template/user/create_local.php
index 0db1e824..aeec300f 100644
--- a/app/Template/user/new.php
+++ b/app/Template/user/create_local.php
@@ -2,6 +2,7 @@
<div class="page-header">
<ul>
<li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('All users'), 'user', 'index') ?></li>
+ <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New remote user'), 'user', 'create', array('remote' => 1)) ?></li>
</ul>
</div>
<section>
diff --git a/app/Template/user/create_remote.php b/app/Template/user/create_remote.php
new file mode 100644
index 00000000..52661585
--- /dev/null
+++ b/app/Template/user/create_remote.php
@@ -0,0 +1,57 @@
+<section id="main">
+ <div class="page-header">
+ <ul>
+ <li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('All users'), 'user', 'index') ?></li>
+ <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New local user'), 'user', 'create') ?></li>
+ </ul>
+ </div>
+ <form method="post" action="<?= $this->url->href('user', 'save') ?>" autocomplete="off">
+
+ <?= $this->form->csrf() ?>
+ <?= $this->form->hidden('is_ldap_user', array('is_ldap_user' => 1)) ?>
+
+ <div class="form-column">
+ <?= $this->form->label(t('Username'), 'username') ?>
+ <?= $this->form->text('username', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?><br/>
+
+ <?= $this->form->label(t('Name'), 'name') ?>
+ <?= $this->form->text('name', $values, $errors) ?><br/>
+
+ <?= $this->form->label(t('Email'), 'email') ?>
+ <?= $this->form->email('email', $values, $errors) ?><br/>
+
+ <?= $this->form->label(t('Google Id'), 'google_id') ?>
+ <?= $this->form->password('google_id', $values, $errors) ?><br/>
+
+ <?= $this->form->label(t('Github Id'), 'github_id') ?>
+ <?= $this->form->password('github_id', $values, $errors) ?><br/>
+ </div>
+
+ <div class="form-column">
+ <?= $this->form->label(t('Add project member'), 'project_id') ?>
+ <?= $this->form->select('project_id', $projects, $values, $errors) ?><br/>
+
+ <?= $this->form->label(t('Timezone'), 'timezone') ?>
+ <?= $this->form->select('timezone', $timezones, $values, $errors) ?><br/>
+
+ <?= $this->form->label(t('Language'), 'language') ?>
+ <?= $this->form->select('language', $languages, $values, $errors) ?><br/>
+
+ <?= $this->form->checkbox('notifications_enabled', t('Enable notifications'), 1, isset($values['notifications_enabled']) && $values['notifications_enabled'] == 1 ? true : false) ?>
+ <?= $this->form->checkbox('is_admin', t('Administrator'), 1, isset($values['is_admin']) && $values['is_admin'] == 1 ? true : false) ?>
+ <?= $this->form->checkbox('disable_login_form', t('Disallow login form'), 1, isset($values['disable_login_form']) && $values['disable_login_form'] == 1) ?>
+ </div>
+
+ <div class="form-actions">
+ <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
+ <?= t('or') ?>
+ <?= $this->url->link(t('cancel'), 'user', 'index') ?>
+ </div>
+ </form>
+ <div class="alert alert-info">
+ <ul>
+ <li><?= t('Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.') ?></li>
+ <li><?= t('If you check the box "Disallow login form", credentials entered in the login form will be ignored.') ?></li>
+ </ul>
+ </div>
+</section> \ No newline at end of file
diff --git a/app/Template/user/index.php b/app/Template/user/index.php
index fc575466..edf043a6 100644
--- a/app/Template/user/index.php
+++ b/app/Template/user/index.php
@@ -2,7 +2,8 @@
<div class="page-header">
<?php if ($this->user->isAdmin()): ?>
<ul>
- <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New user'), 'user', 'create') ?></li>
+ <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New local user'), 'user', 'create') ?></li>
+ <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New remote user'), 'user', 'create', array('remote' => 1)) ?></li>
</ul>
<?php endif ?>
</div>
diff --git a/app/Template/user/layout.php b/app/Template/user/layout.php
index e60ab77d..a27f359b 100644
--- a/app/Template/user/layout.php
+++ b/app/Template/user/layout.php
@@ -3,7 +3,8 @@
<?php if ($this->user->isAdmin()): ?>
<ul>
<li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('All users'), 'user', 'index') ?></li>
- <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New user'), 'user', 'create') ?></li>
+ <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New local user'), 'user', 'create') ?></li>
+ <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New remote user'), 'user', 'create', array('remote' => 1)) ?></li>
</ul>
<?php endif ?>
</div>
diff --git a/app/constants.php b/app/constants.php
index 7270db23..83fba468 100644
--- a/app/constants.php
+++ b/app/constants.php
@@ -35,6 +35,7 @@ defined('LDAP_ACCOUNT_FULLNAME') or define('LDAP_ACCOUNT_FULLNAME', 'displayname
defined('LDAP_ACCOUNT_EMAIL') or define('LDAP_ACCOUNT_EMAIL', 'mail');
defined('LDAP_ACCOUNT_ID') or define('LDAP_ACCOUNT_ID', '');
defined('LDAP_USERNAME_CASE_SENSITIVE') or define('LDAP_USERNAME_CASE_SENSITIVE', false);
+defined('LDAP_ACCOUNT_CREATION') or define('LDAP_ACCOUNT_CREATION', true);
// Google authentication
defined('GOOGLE_AUTH') or define('GOOGLE_AUTH', false);