diff --git a/src/IDF/Form/UserAccount.php b/src/IDF/Form/UserAccount.php index 3d1ded1..806e625 100644 --- a/src/IDF/Form/UserAccount.php +++ b/src/IDF/Form/UserAccount.php @@ -82,6 +82,16 @@ class IDF_Form_UserAccount extends Pluf_Form 'size' => 15, ), )); + + $this->fields['ssh_key'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Your public SSH key'), + 'initial' => '', + 'widget_attrs' => array('rows' => 3, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'help_text' => __('Be careful to provide your public key and not your private key!') + )); } @@ -107,8 +117,22 @@ class IDF_Form_UserAccount extends Pluf_Form $update_pass = true; } $this->user->setFromFormData($this->cleaned_data); + // Get keys + $keys = $this->user->get_idf_key_list(); + if ($keys->count() > 0) { + $key = $keys[0]; + } else { + $key = new IDF_Key(); + $key->user = $this->user; + } + $key->content = $this->cleaned_data['ssh_key']; if ($commit) { $this->user->update(); + if ($key->id != '') { + $key->update(); + } else { + $key->create(); + } if ($update_pass) { /** * [signal] diff --git a/src/IDF/Key.php b/src/IDF/Key.php new file mode 100644 index 0000000..d480321 --- /dev/null +++ b/src/IDF/Key.php @@ -0,0 +1,100 @@ +_a['table'] = 'idf_keys'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'user' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('user'), + ), + 'content' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'verbose' => __('ssh key'), + ), + ); + // WARNING: Not using getSqlTable on the Pluf_User object to + // avoid recursion. + $t_users = $this->_con->pfx.'users'; + $this->_a['views'] = array( + 'join_user' => + array( + 'join' => 'LEFT JOIN '.$t_users + .' ON '.$t_users.'.id='.$this->_con->qn('user'), + 'select' => $this->getSelect().', ' + .$t_users.'.login AS login', + 'props' => array('login' => 'login'), + ) + ); + } + + function postSave($create=false) + { + /** + * [signal] + * + * IDF_Key::postSave + * + * [sender] + * + * IDF_Key + * + * [description] + * + * This signal allows an application to perform special + * operations after the saving of a SSH Key. + * + * [parameters] + * + * array('key' => $key, + * 'created' => true/false) + * + */ + $params = array('key' => $this, 'created' => $create); + Pluf_Signal::send('IDF_Key::postSave', + 'IDF_Key', $params); + } + +} diff --git a/src/IDF/Migrations/10SshKey.php b/src/IDF/Migrations/10SshKey.php new file mode 100644 index 0000000..bed7cbb --- /dev/null +++ b/src/IDF/Migrations/10SshKey.php @@ -0,0 +1,52 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_10SshKey_down($params=null) +{ + $models = array( + 'IDF_Key', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/src/IDF/Migrations/Install.php b/src/IDF/Migrations/Install.php index ecd442f..6f2cb75 100644 --- a/src/IDF/Migrations/Install.php +++ b/src/IDF/Migrations/Install.php @@ -45,6 +45,7 @@ function IDF_Migrations_Install_setup($params=null) 'IDF_Review', 'IDF_Review_Patch', 'IDF_Review_FileComment', + 'IDF_Key', ); $db = Pluf::db(); $schema = new Pluf_DB_Schema($db); @@ -82,6 +83,7 @@ function IDF_Migrations_Install_teardown($params=null) $perm = Pluf_Permission::getFromString('IDF.project-authorized-user'); if ($perm) $perm->delete(); $models = array( + 'IDF_Key', 'IDF_Review_FileComment', 'IDF_Review_Patch', 'IDF_Review', diff --git a/src/IDF/Plugin/SyncGit/Cron.php b/src/IDF/Plugin/SyncGit/Cron.php new file mode 100644 index 0000000..e11336c --- /dev/null +++ b/src/IDF/Plugin/SyncGit/Cron.php @@ -0,0 +1,60 @@ +template; + $keys = Pluf::factory('IDF_Key')->getList(array('view'=>'join_user')); + $cmd = Pluf::f('idf_plugin_syncgit_path_gitserve', '/bin/false'); + $authorized_keys = Pluf::f('idf_plugin_syncgit_path_authorized_keys', false); + if (false == $authorized_keys) { + throw new Pluf_Exception_SettingError('Setting git_path_authorized_keys not set.'); + } + if (!is_writable($authorized_keys)) { + throw new Exception('Cannot create file: '.$authorized_keys); + } + $out = ''; + foreach ($keys as $key) { + if (strlen($key->content) > 40 // minimal check + and preg_match('/^[a-zA-Z][a-zA-Z0-9_.-]*(@[a-zA-Z][a-zA-Z0-9.-]*)?$/', $key->login)) { + $content = str_replace("\n", '', $key->content); + $out .= sprintf($template, $cmd, $key->login, $content)."\n"; + } + } + file_put_contents($authorized_keys, $out, LOCK_EX); + } +} diff --git a/src/IDF/Plugin/SyncGit/Serve.php b/src/IDF/Plugin/SyncGit/Serve.php index 7e487d6..5a25696 100644 --- a/src/IDF/Plugin/SyncGit/Serve.php +++ b/src/IDF/Plugin/SyncGit/Serve.php @@ -36,11 +36,6 @@ class IDF_Plugin_SyncGit_Serve public $commands_write = array('git-receive-pack', 'git receive-pack'); /** - * Check that the command is authorized. - */ - - - /** * Serve a git request. * * @param string Username. @@ -120,7 +115,7 @@ class IDF_Plugin_SyncGit_Serve exit(1); } $cmd = $env['SSH_ORIGINAL_COMMAND']; - chdir(Pluf::f('git_home_dir', '/home/git')); + chdir(Pluf::f('idf_plugin_syncgit_git_home_dir', '/home/git')); $serve = new IDF_Plugin_SyncGit_Serve(); try { $new_cmd = $serve->serve($username, $cmd); @@ -171,11 +166,11 @@ class IDF_Plugin_SyncGit_Serve $request->user = $user; if (true === IDF_Precondition::accessTabGeneric($request, 'source_access_rights')) { if ($mode == 'readonly') { - return array(Pluf::f('git_base_repositories', '/home/git/repositories'), + return array(Pluf::f('idf_plugin_syncgit_base_repositories', '/home/git/repositories'), $project->shortname); } if (true === IDF_Precondition::projectMemberOrOwner($request)) { - return array(Pluf::f('git_base_repositories', '/home/git/repositories'), + return array(Pluf::f('idf_plugin_syncgit_base_repositories', '/home/git/repositories'), $project->shortname); } } diff --git a/src/IDF/Views/User.php b/src/IDF/Views/User.php index f4672f6..1cf8725 100644 --- a/src/IDF/Views/User.php +++ b/src/IDF/Views/User.php @@ -124,10 +124,17 @@ class IDF_Views_User unset($data['password']); $form = new IDF_Form_UserAccount($data, $params); } + $keys = $request->user->get_idf_key_list(); + if ($keys->count() > 0 and strlen($keys[0]->content) > 30) { + $ssh_key = Pluf_Template::markSafe(''.Pluf_esc(substr($keys[0]->content, 0, 30)).'...
'.__('Troncated for security reasons.').''); + } else { + $ssh_key = __('You have not upload your public SSH key yet.'); + } return Pluf_Shortcuts_RenderToResponse('idf/user/myaccount.html', array('page_title' => __('Your Account'), 'api_key' => $api_key, 'ext_pass' => $ext_pass, + 'ssh_key' => $ssh_key, 'form' => $form), $request); } diff --git a/src/IDF/relations.php b/src/IDF/relations.php index 4e0ef39..bcf991f 100644 --- a/src/IDF/relations.php +++ b/src/IDF/relations.php @@ -37,7 +37,7 @@ $m['IDF_Review'] = array('relate_to' => array('IDF_Project', 'Pluf_User', 'IDF_T 'relate_to_many' => array('IDF_Tag', 'Pluf_User')); $m['IDF_Review_Patch'] = array('relate_to' => array('IDF_Review', 'Pluf_User')); $m['IDF_Review_FileComment'] = array('relate_to' => array('IDF_Review_Patch', 'Pluf_User')); - +$m['IDF_Key'] = array('relate_to' => array('Pluf_User')); Pluf_Signal::connect('Pluf_Template_Compiler::construct_template_tags_modifiers', array('IDF_Middleware', 'updateTemplateTagsModifiers')); diff --git a/src/IDF/templates/idf/user/myaccount.html b/src/IDF/templates/idf/user/myaccount.html index 7e77518..82a0da4 100644 --- a/src/IDF/templates/idf/user/myaccount.html +++ b/src/IDF/templates/idf/user/myaccount.html @@ -46,6 +46,14 @@ {$form.f.password2|unsafe} + +{$form.f.ssh_key.labelTag}: +{if $form.f.ssh_key.errors}{$form.f.ssh_key.fieldErrors}{/if} +{$ssh_key}
+{$form.f.ssh_key|unsafe}
+{$form.f.ssh_key.help_text} + + {trans 'Extra password'}: {$ext_pass}