Merge pull-request: Github authentication #162
This commit is contained in:
parent
f70ac7d65f
commit
06d0b7048e
|
|
@ -1,6 +1,7 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- "5.6"
|
||||
- "5.5"
|
||||
- "5.4"
|
||||
- "5.3"
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ Features
|
|||
- Tasks with different colors, categories, sub-tasks, attachments, Markdown support for the description
|
||||
- Automatic actions
|
||||
- Users management with a basic privileges separation (administrator or regular user)
|
||||
- External authentication: Google Account and LDAP/ActiveDirectory
|
||||
- External authentication: Google and GitHub accounts as well as LDAP/ActiveDirectory
|
||||
- Webhooks to create tasks from an external software
|
||||
- Host anywhere (shared hosting, VPS, Raspberry Pi or localhost)
|
||||
- No external dependencies
|
||||
|
|
@ -104,6 +104,7 @@ Documentation
|
|||
|
||||
- [LDAP authentication](docs/ldap-authentication.markdown)
|
||||
- [Google authentication](docs/google-authentication.markdown)
|
||||
- [GitHub authentication](docs/github-authentication.markdown)
|
||||
|
||||
#### Developers
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use Model\LastLogin;
|
|||
* @property \Model\Config $config
|
||||
* @property \Model\File $file
|
||||
* @property \Model\Google $google
|
||||
* @property \Model\GitHub $gitHub
|
||||
* @property \Model\LastLogin $lastLogin
|
||||
* @property \Model\Ldap $ldap
|
||||
* @property \Model\Project $project
|
||||
|
|
|
|||
|
|
@ -299,4 +299,68 @@ class User extends Base
|
|||
|
||||
$this->response->redirect('?controller=user');
|
||||
}
|
||||
|
||||
/**
|
||||
* GitHub authentication
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function gitHub()
|
||||
{
|
||||
$code = $this->request->getStringParam('code');
|
||||
|
||||
if ($code) {
|
||||
$profile = $this->gitHub->getGitHubProfile($code);
|
||||
|
||||
if (is_array($profile)) {
|
||||
|
||||
// If the user is already logged, link the account otherwise authenticate
|
||||
if ($this->acl->isLogged()) {
|
||||
|
||||
if ($this->gitHub->updateUser($this->acl->getUserId(), $profile)) {
|
||||
$this->session->flash(t('Your GitHub account was successfully linked to your profile.'));
|
||||
}
|
||||
else {
|
||||
$this->session->flashError(t('Unable to link your GitHub Account.'));
|
||||
}
|
||||
|
||||
$this->response->redirect('?controller=user');
|
||||
}
|
||||
else if ($this->gitHub->authenticate($profile['id'])) {
|
||||
$this->response->redirect('?controller=app');
|
||||
}
|
||||
else {
|
||||
$this->response->html($this->template->layout('user_login', array(
|
||||
'errors' => array('login' => t('GitHub authentication failed')),
|
||||
'values' => array(),
|
||||
'no_layout' => true,
|
||||
'title' => t('Login')
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->response->redirect($this->gitHub->getAuthorizationUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a GitHub account
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function unlinkGitHub()
|
||||
{
|
||||
$this->checkCSRFParam();
|
||||
|
||||
$this->gitHub->revokeGitHubAccess();
|
||||
|
||||
if ($this->gitHub->unlink($this->acl->getUserId())) {
|
||||
$this->session->flash(t('Your GitHub account is no longer linked to your profile.'));
|
||||
}
|
||||
else {
|
||||
$this->session->flashError(t('Unable to unlink your GitHub Account.'));
|
||||
}
|
||||
|
||||
$this->response->redirect('?controller=user');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ return array(
|
|||
'German' => 'Deutsch',
|
||||
'French' => 'Französisch',
|
||||
'Polish' => 'Polnisch',
|
||||
'Portuguese (Brazilian)' => 'Portugisisch (Brasilien)',
|
||||
'Portuguese (Brazilian)' => 'Portugiesisch (Brasilien)',
|
||||
'Spanish' => 'Spanisch',
|
||||
'Chinese (Simplified)' => 'Chinesisch',
|
||||
'Chinese (Simplified)' => 'Chinesisch (vereinfacht)',
|
||||
'None' => 'Kein',
|
||||
'edit' => 'bearbeiten',
|
||||
'Edit' => 'Bearbeiten',
|
||||
|
|
@ -27,16 +27,16 @@ return array(
|
|||
'Grey' => 'Grau',
|
||||
'Save' => 'Speichern',
|
||||
'Login' => 'Anmelden',
|
||||
'Official website:' => 'Offizielle Website :',
|
||||
'Official website:' => 'Offizielle Website:',
|
||||
'Unassigned' => 'Nicht zugeordnet',
|
||||
'View this task' => 'Aufgabe ansehen',
|
||||
'Remove user' => 'Benutzer löschen',
|
||||
'Do you really want to remove this user: "%s"?' => 'Willst Du diesen Benutzer wirklich löschen : « %s » ?',
|
||||
'Do you really want to remove this user: "%s"?' => 'Willst Du diesen Benutzer wirklich löschen: «%s»?',
|
||||
'New user' => 'Neuer Benutzer',
|
||||
'All users' => 'Alle Benutzer',
|
||||
'Username' => 'Benutzername',
|
||||
'Password' => 'Passwort',
|
||||
'Default Project' => 'Standard Projekt',
|
||||
'Default Project' => 'Standardprojekt',
|
||||
'Administrator' => 'Administrator',
|
||||
'Sign in' => 'Anmelden',
|
||||
'Users' => 'Benutzer',
|
||||
|
|
@ -70,37 +70,37 @@ return array(
|
|||
'Disable' => 'Deaktivieren',
|
||||
'Enable' => 'Aktivieren',
|
||||
'New project' => 'Neues Projekt',
|
||||
'Do you really want to remove this project: "%s"?' => 'Möchtest Du dieses Projekt wirklich löschen : « %s » ?',
|
||||
'Do you really want to remove this project: "%s"?' => 'Möchtest Du dieses Projekt wirklich löschen: «%s»?',
|
||||
'Remove project' => 'Projekt löschen',
|
||||
'Boards' => 'Tafel',
|
||||
'Edit the board for "%s"' => 'Modifier le tableau pour « %s »',
|
||||
'Edit the board for "%s"' => 'Tafel für «%s» bearbeiten',
|
||||
'All projects' => 'Alle Projekte',
|
||||
'Change columns' => 'Spalten ändern',
|
||||
'Add a new column' => 'Neue Spalte hinzufügen',
|
||||
'Title' => 'Titel',
|
||||
'Add Column' => 'Neue Spalte',
|
||||
'Project "%s"' => 'Projekt « %s »',
|
||||
'Project "%s"' => 'Projekt «%s»',
|
||||
'Nobody assigned' => 'Kein Zuständiger zugeordnet',
|
||||
'Assigned to %s' => 'Zuständiger: %s',
|
||||
'Remove a column' => 'Spalte löschen',
|
||||
'Remove a column from a board' => 'Eine Spalte von einer Tafel löschen',
|
||||
'Unable to remove this column.' => 'Löschen dieser Spalte nicht möglich.',
|
||||
'Do you really want to remove this column: "%s"?' => 'Willst Du diese Spalte wirklich löschen : « %s » ?',
|
||||
'This action will REMOVE ALL TASKS associated to this column!' => 'Diese Aktion wird ALLE AUFGABEN löschen !',
|
||||
'Do you really want to remove this column: "%s"?' => 'Willst Du diese Spalte wirklich löschen: «%s»?',
|
||||
'This action will REMOVE ALL TASKS associated to this column!' => 'Diese Aktion wird ALLE AUFGABEN löschen!',
|
||||
'Settings' => 'Einstellungen',
|
||||
'Application settings' => 'Applikationseinstellungen',
|
||||
'Language' => 'Sprache',
|
||||
'Webhooks token:' => 'Webhooks token:',
|
||||
'More information' => 'Mehr Informationen',
|
||||
'Database size:' => 'Datenbank Größe :',
|
||||
'Database size:' => 'Datenbankgröße:',
|
||||
'Download the database' => 'Download der Datenbank',
|
||||
'Optimize the database' => 'Optimieren der Datenbank',
|
||||
'(VACUUM command)' => '(VACUUM command)',
|
||||
'(Gzip compressed Sqlite file)' => '(Gzip komprimierte sqlite Datei)',
|
||||
'User settings' => 'Benutzer Eintellungen',
|
||||
'My default project:' => 'Mein Standard Projekt : ',
|
||||
'User settings' => 'Benutzereinstellungen',
|
||||
'My default project:' => 'Mein Standardprojekt:',
|
||||
'Close a task' => 'Aufgabe schließen',
|
||||
'Do you really want to close this task: "%s"?' => 'Willst Du diese Aufgabe wirklich schließen : « %s » ?',
|
||||
'Do you really want to close this task: "%s"?' => 'Willst Du diese Aufgabe wirklich schließen: «%s»?',
|
||||
'Edit a task' => 'Aufgabe bearbeiten',
|
||||
'Column' => 'Spalte',
|
||||
'Color' => 'Farbe',
|
||||
|
|
@ -108,18 +108,18 @@ return array(
|
|||
'Create another task' => 'Neue Aufgabe erstellen',
|
||||
'New task' => 'Neue Aufgabe',
|
||||
'Open a task' => 'Öffne eine Aufgabe',
|
||||
'Do you really want to open this task: "%s"?' => 'Willst Du diese Aufgabe wirklich öffnen : « %s » ?',
|
||||
'Do you really want to open this task: "%s"?' => 'Willst Du diese Aufgabe wirklich öffnen: «%s»?',
|
||||
'Back to the board' => 'Zurück zur Tafel',
|
||||
'Created on %B %e, %G at %k:%M %p' => 'Erstellt am %d.%m.%Y um %H:%M',
|
||||
'There is nobody assigned' => 'Ein gibt keinen Zuständigen',
|
||||
'Column on the board:' => 'Spalten auf diesem Tafel : ',
|
||||
'Column on the board:' => 'Spalten auf diesem Tafel:',
|
||||
'Status is open' => 'Status ist geöffnet',
|
||||
'Status is closed' => 'Status ist geschlossen',
|
||||
'close this task' => 'Aufgabe schließen',
|
||||
'open this task' => 'Aufgabe öffnen',
|
||||
'There is no description.' => 'Es gibt keine Erklärung.',
|
||||
'There is no description.' => 'Es gibt keine Beschreibung.',
|
||||
'Add a new task' => 'Eine neue Aufgabe hinzufügen',
|
||||
'The username is required' => 'Der Butzutzername wird benötigt',
|
||||
'The username is required' => 'Der Benutzername wird benötigt',
|
||||
'The maximum length is %d characters' => 'Die maximale Länge sind %d Zeichen',
|
||||
'The minimum length is %d characters' => 'Die minimale Länge sind %d Zeichen',
|
||||
'The password is required' => 'Das Passwort wird benötigt',
|
||||
|
|
@ -133,12 +133,12 @@ return array(
|
|||
'The project is required' => 'Das Projekt wird benötigt',
|
||||
'The color is required' => 'Die Farbe wird benötigt',
|
||||
'The id is required' => 'Die ID wird benötigt',
|
||||
'The project id is required' => 'Die Projekt ID wird benötogt',
|
||||
'The project name is required' => 'Der Projekt Name wird benötigt',
|
||||
'This project must be unique' => 'Der Projekt Name muss eindeutig sein',
|
||||
'The project id is required' => 'Die Projekt ID wird benötigt',
|
||||
'The project name is required' => 'Der Projektname wird benötigt',
|
||||
'This project must be unique' => 'Der Projektname muss eindeutig sein',
|
||||
'The title is required' => 'Der Titel wird benötigt',
|
||||
'The language is required' => 'Die Sprache wird benötigt',
|
||||
'There is no active project, the first step is to create a new project.' => 'Es gibt kein aktives Projekt. Der erste Schritt ist ein Projekt erstellen.',
|
||||
'There is no active project, the first step is to create a new project.' => 'Es gibt kein aktives Projekt. Der erste Schritt ist ein Projekt zu erstellen.',
|
||||
'Settings saved successfully.' => 'Die Einstellungen wurden erfolgreich gespeichert.',
|
||||
'Unable to save your settings.' => 'Speicher der Einstellungen nicht möglich.',
|
||||
'Database optimization done.' => 'Optimieren der Datenbank abgeschlossen.',
|
||||
|
|
@ -148,7 +148,7 @@ return array(
|
|||
'Unable to update this project.' => 'Ändern des Projekts nicht möglich.',
|
||||
'Unable to remove this project.' => 'Löschen des Projekts nicht möglich.',
|
||||
'Project removed successfully.' => 'Löschen des Projekts erfolgreich.',
|
||||
'Project activated successfully.' => 'Aktivieren des Projekts erolgreich.',
|
||||
'Project activated successfully.' => 'Aktivieren des Projekts erfolgreich.',
|
||||
'Unable to activate this project.' => 'Aktivieren des Projekts nicht möglich.',
|
||||
'Project disabled successfully.' => 'Deaktivieren des Projekts erfolgreich.',
|
||||
'Unable to disable this project.' => 'Deaktivieren des Projekts nicht möglich.',
|
||||
|
|
@ -171,24 +171,24 @@ return array(
|
|||
'Backlog' => 'Ideen',
|
||||
'Work in progress' => 'In Arbeit',
|
||||
'Done' => 'Erledigt',
|
||||
'Application version:' => 'Programmversion :',
|
||||
'Completed on %B %e, %G at %k:%M %p' => 'Erledigt am %d.%m.%Y à %H:%M',
|
||||
'Application version:' => 'Programmversion:',
|
||||
'Completed on %B %e, %G at %k:%M %p' => 'Erledigt am %d.%m.%Y um %H:%M',
|
||||
'%B %e, %G at %k:%M %p' => '%d.%m.%Y um %H:%M',
|
||||
'Date created' => 'Erstellung am',
|
||||
'Date created' => 'Erstellt am',
|
||||
'Date completed' => 'Erledigt am',
|
||||
'Id' => 'ID',
|
||||
'No task' => 'Keine Aufgabe',
|
||||
'Completed tasks' => 'Erledigte Aufgaben',
|
||||
'List of projects' => 'Liste der Projekte',
|
||||
'Completed tasks for "%s"' => 'Erledigte Aufaben für « %s »',
|
||||
'%d closed tasks' => '%d erledigte Augaben',
|
||||
'Completed tasks for "%s"' => 'Erledigte Aufgaben für «%s»',
|
||||
'%d closed tasks' => '%d erledigte Aufgaben',
|
||||
'no task for this project' => 'Keine Aufgaben in diesem Projekt',
|
||||
'Public link' => 'Öffentlicher Link',
|
||||
'There is no column in your project!' => 'Es gibt keine Spalte in Deinem Projekt!',
|
||||
'There is no column in your project!' => 'Es gibt keine Spalte in deinem Projekt!',
|
||||
'Change assignee' => 'Zuständigkeit ändern',
|
||||
'Change assignee for the task "%s"' => 'Zuständigkeit für diese Aufgabe ändern: « %s »',
|
||||
'Change assignee for the task "%s"' => 'Zuständigkeit für diese Aufgabe ändern: «%s»',
|
||||
'Timezone' => 'Zeitzone',
|
||||
'Sorry, I didn\'t found this information in my database!' => 'Diese Information wurde in der Datenbank nicht gefunden !',
|
||||
'Sorry, I didn\'t found this information in my database!' => 'Diese Information wurde in der Datenbank nicht gefunden!',
|
||||
'Page not found' => 'Seite nicht gefunden',
|
||||
'Story Points' => 'Umfang',
|
||||
'limit' => 'Limit',
|
||||
|
|
@ -197,17 +197,17 @@ return array(
|
|||
'Edit project access list' => 'Projekt Zugangsberechtigungen bearbeiten',
|
||||
'Edit users access' => 'Benutzerzugang bearbeiten',
|
||||
'Allow this user' => 'Diesen Benutzer authorisieren',
|
||||
'Project access list for "%s"' => 'Projekt Zugangsliste für « %s »',
|
||||
'Only those users have access to this project:' => 'Nur diese Benutzer haben Zugang zum Projekt :',
|
||||
'Project access list for "%s"' => 'Projekt Zugangsliste für «%s»',
|
||||
'Only those users have access to this project:' => 'Nur diese Benutzer haben Zugang zum Projekt:',
|
||||
'Don\'t forget that administrators have access to everything.' => 'Vergiss nicht, dass Administratoren überall Zugang haben.',
|
||||
'revoke' => 'verbieten',
|
||||
'List of authorized users' => 'Liste der authorisieren Benutzer',
|
||||
'List of authorized users' => 'Liste der authorisierten Benutzer',
|
||||
'User' => 'Benutzer',
|
||||
'Everybody have access to this project.' => 'Jedem hat Zugang zu diesem Projekt.',
|
||||
'Everybody have access to this project.' => 'Jeder hat Zugang zu diesem Projekt.',
|
||||
'You are not allowed to access to this project.' => 'Du hast keinen Zugang zu diesem Projekt.',
|
||||
'Comments' => 'Kommentare',
|
||||
'Post comment' => 'kommentieren',
|
||||
'Write your text in Markdown' => 'Schreibe Deinen Text in Markdown',
|
||||
'Write your text in Markdown' => 'Schreibe deinen Text in Markdown',
|
||||
'Leave a comment' => 'Kommentar abgeben',
|
||||
'Comment is required' => 'Ein Kommentar wird benötigt',
|
||||
'Leave a description' => 'Beschreibung',
|
||||
|
|
@ -226,8 +226,8 @@ return array(
|
|||
'Unable to create your automatic action.' => 'Deine automatische Aktion konnte nicht erstellt werden.',
|
||||
'Remove an action' => 'Aktion löschen',
|
||||
'Unable to remove this action.' => 'Aktion konnte nicht gelöscht werden',
|
||||
'Action removed successfully.' => 'Action wurde erfolgreich gelöscht.',
|
||||
'Automatic actions for the project "%s"' => 'Automatische Aktionen für dieses Projekt « %s »',
|
||||
'Action removed successfully.' => 'Aktion wurde erfolgreich gelöscht.',
|
||||
'Automatic actions for the project "%s"' => 'Automatische Aktionen für das Projekt «%s»',
|
||||
'Defined actions' => 'Definierte Aktionen',
|
||||
'Add an action' => 'Aktion hinzufügen',
|
||||
'Event name' => 'Ereignis',
|
||||
|
|
@ -235,15 +235,15 @@ return array(
|
|||
'Action parameters' => 'Aktionsparameter',
|
||||
'Action' => 'Aktion',
|
||||
'Event' => 'Ereignis',
|
||||
'When the selected event occurs execute the corresponding action.' => 'Wenn des gewählte Ereignis eintritt, führe die passende Aktion aus.',
|
||||
'When the selected event occurs execute the corresponding action.' => 'Wenn des gewählte Ereignis eintritt, führe die zugehörige Aktion aus.',
|
||||
'Next step' => 'Nächster Schritt',
|
||||
'Define action parameters' => 'Aktionsparameter definieren',
|
||||
'Save this action' => 'Aktion speichern',
|
||||
'Do you really want to remove this action: "%s"?' => 'Willst Du diese Aktion wirklich löschen « %s » ?',
|
||||
'Do you really want to remove this action: "%s"?' => 'Willst Du diese Aktion wirklich löschen «%s»?',
|
||||
'Remove an automatic action' => 'Löschen einer automatischen Aktion',
|
||||
'Close the task' => 'Aufgabe schießen',
|
||||
'Close the task' => 'Aufgabe schließen',
|
||||
'Assign the task to a specific user' => 'Aufgabe einem Benutzer zuordnen',
|
||||
'Assign the task to the person who does the action' => 'Aufgabe dem Benutzer zuordnen der die Aktion aufgeführt hat',
|
||||
'Assign the task to the person who does the action' => 'Aufgabe dem Benutzer zuordnen der die Aktion ausgeführt hat',
|
||||
'Duplicate the task to another project' => 'Aufgabe in ein anderes Projekt kopieren',
|
||||
'Move a task to another column' => 'Aufgabe in eine andere Spalte verschieben',
|
||||
'Move a task to another position in the same column' => 'Aufgabe an eine andere Position in der gleichen Spalte verschieben',
|
||||
|
|
@ -268,7 +268,7 @@ return array(
|
|||
'Do you really want to remove this comment?' => 'Willst Du diesen Kommentar wirklich löschen?',
|
||||
'Only administrators or the creator of the comment can access to this page.' => 'Nur Administratoren und der Ersteller des Kommentars könne diese Seite verwenden.',
|
||||
'Details' => 'Details',
|
||||
'Current password for the user "%s"' => 'Aktuelles Passwort für den Benutzer « %s »',
|
||||
'Current password for the user "%s"' => 'Aktuelles Passwort für den Benutzer «%s»',
|
||||
'The current password is required' => 'Das aktuelle Passwort wird benötigt',
|
||||
'Wrong password' => 'Falsches Passwort',
|
||||
'Reset all tokens' => 'Alle Tokens zurücksetzten',
|
||||
|
|
@ -278,8 +278,8 @@ return array(
|
|||
'Login date' => 'Anmeldedatum',
|
||||
'Authentication method' => 'Anmeldemethode',
|
||||
'IP address' => 'IP Adresse',
|
||||
'User agent' => 'Benutzer Agent',
|
||||
'Persistent connections' => 'Bestende Verbindungen',
|
||||
'User agent' => 'User Agent',
|
||||
'Persistent connections' => 'Bestehende Verbindungen',
|
||||
'No session' => 'Keine Session',
|
||||
'Expiration date' => 'Ablaufdatum',
|
||||
'Remember Me' => 'Angemeldet bleiben',
|
||||
|
|
@ -291,23 +291,31 @@ return array(
|
|||
'Closed' => 'Geschlossen',
|
||||
'Search' => 'Suchen',
|
||||
'Nothing found.' => 'Nichts gefunden.',
|
||||
'Search in the project "%s"' => 'Suche im Projekt « %s »',
|
||||
'Search in the project "%s"' => 'Suche im Projekt «%s»',
|
||||
'Due date' => 'Fälligkeitsdatum',
|
||||
'Others formats accepted: %s and %s' => 'Andere akzepierte Formate : %s und %s',
|
||||
'Description' => 'Beschreibung',
|
||||
'%d comments' => '%d Kommentare',
|
||||
'%d comment' => '%d Kommentar',
|
||||
'Email address invalid' => 'EMail Adresse ungültig',
|
||||
'Your Google Account is not linked anymore to your profile.' => 'Dein Google Accout ist nicht mit den Profil verbunden.',
|
||||
'Unable to unlink your Google Account.' => 'Trennung der Verbindung mit dem Google Accout nicht möglich.',
|
||||
'Your Google Account is not linked anymore to your profile.' => 'Dein Google Account ist nicht mehr mit deinem Profil verbunden.',
|
||||
'Unable to unlink your Google Account.' => 'Trennung der Verbindung mit deinem Google Account nicht möglich.',
|
||||
'Google authentication failed' => 'Zugang mit Google nicht möglich',
|
||||
'Unable to link your Google Account.' => 'Verbindung mit dem Google Accout nicht möglich.',
|
||||
'Your Google Account is linked to your profile successfully.' => 'Der Google Account wurde erfolgreich verbunden.',
|
||||
'Unable to link your Google Account.' => 'Verbindung mit deinem Google Account nicht möglich.',
|
||||
'Your Google Account is linked to your profile successfully.' => 'Dein Google Account wurde erfolgreich verbunden.',
|
||||
'Email' => 'Email',
|
||||
'Link my Google Account' => 'Verbinde meinen Google Account',
|
||||
'Unlink my Google Account' => 'Verbindung mit meinem Google Account trennen',
|
||||
'Login with my Google Account' => 'Anmelden mit meinem Google Account',
|
||||
'Project not found.' => 'Das Projekt wurde nicht gefunden.',
|
||||
'Your GitHub account was successfully linked to your profile.' => 'Dein GitHub Account wurde erfolgreich mit deinem Profil verbunden.',
|
||||
'Unable to link your GitHub Account.' => 'Verbindung mit deinem GitHub Account nicht möglich.',
|
||||
'GitHub authentication failed' => 'Zugang mit GitHub nicht möglich',
|
||||
'Your GitHub account is no longer linked to your profile.' => 'Dein GitHub Account ist nicht mehr mit deinem Profil verbunden.',
|
||||
'Unable to unlink your GitHub Account.' => 'Trennung der Verbindung mit deinem GitHub Account nicht möglich.',
|
||||
'Login with my GitHub Account' => 'Anmelden mit meinem GitHub Account',
|
||||
'Link my GitHub Account' => 'Mit meinem GitHub Account verbinden',
|
||||
'Unlink my GitHub Account' => 'Verbindung mit meinem GitHub Account trennen',
|
||||
// 'Task #%d' => '',
|
||||
// 'Task removed successfully.' => '',
|
||||
// 'Unable to remove this task.' => '',
|
||||
|
|
|
|||
|
|
@ -376,4 +376,12 @@ return array(
|
|||
'Unable to upload the file.' => 'No pude cargar el fichero.',
|
||||
'Actions' => 'Acciones',
|
||||
// 'Display another project' => '',
|
||||
// 'Your GitHub account was successfully linked to your profile.' => '',
|
||||
// 'Unable to link your GitHub Account.' => '',
|
||||
// 'GitHub authentication failed' => '',
|
||||
// 'Your GitHub account is no longer linked to your profile.' => '',
|
||||
// 'Unable to unlink your GitHub Account.' => '',
|
||||
// 'Login with my GitHub Account' => '',
|
||||
// 'Link my GitHub Account' => '',
|
||||
// 'Unlink my GitHub Account' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -374,4 +374,12 @@ return array(
|
|||
'Maximum size: ' => 'Taille maximum : ',
|
||||
'Unable to upload the file.' => 'Impossible de transférer le fichier.',
|
||||
'Display another project' => 'Afficher un autre projet',
|
||||
'Your GitHub account was successfully linked to your profile.' => 'Votre compte Github est désormais lié avec votre profile.',
|
||||
'Unable to link your GitHub Account.' => 'Impossible de lier votre compte Github.',
|
||||
'GitHub authentication failed' => 'L\'authentification avec Github à échouée',
|
||||
'Your GitHub account is no longer linked to your profile.' => 'Votre compte Github n\'est plus relié avec votre profile.',
|
||||
'Unable to unlink your GitHub Account.' => 'Impossible de déconnecter votre compte Github.',
|
||||
'Login with my GitHub Account' => 'Se connecter avec mon compte Github',
|
||||
'Link my GitHub Account' => 'Lier mon compte Github',
|
||||
'Unlink my GitHub Account' => 'Ne plus utiliser mon compte Github',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -377,4 +377,12 @@ return array(
|
|||
// 'Maximum size: ' => '',
|
||||
// 'Unable to upload the file.' => '',
|
||||
// 'Display another project' => '',
|
||||
// 'Your GitHub account was successfully linked to your profile.' => '',
|
||||
// 'Unable to link your GitHub Account.' => '',
|
||||
// 'GitHub authentication failed' => '',
|
||||
// 'Your GitHub account is no longer linked to your profile.' => '',
|
||||
// 'Unable to unlink your GitHub Account.' => '',
|
||||
// 'Login with my GitHub Account' => '',
|
||||
// 'Link my GitHub Account' => '',
|
||||
// 'Unlink my GitHub Account' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -374,4 +374,12 @@ return array(
|
|||
// 'Maximum size: ' => '',
|
||||
// 'Unable to upload the file.' => '',
|
||||
// 'Display another project' => '',
|
||||
// 'Your GitHub account was successfully linked to your profile.' => '',
|
||||
// 'Unable to link your GitHub Account.' => '',
|
||||
// 'GitHub authentication failed' => '',
|
||||
// 'Your GitHub account is no longer linked to your profile.' => '',
|
||||
// 'Unable to unlink your GitHub Account.' => '',
|
||||
// 'Login with my GitHub Account' => '',
|
||||
// 'Link my GitHub Account' => '',
|
||||
// 'Unlink my GitHub Account' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -376,4 +376,12 @@ return array(
|
|||
'Maximum size: ' => 'Maxstorlek: ',
|
||||
'Unable to upload the file.' => 'Kunde inte ladda upp filen.',
|
||||
// 'Display another project' => '',
|
||||
// 'Your GitHub account was successfully linked to your profile.' => '',
|
||||
// 'Unable to link your GitHub Account.' => '',
|
||||
// 'GitHub authentication failed' => '',
|
||||
// 'Your GitHub account is no longer linked to your profile.' => '',
|
||||
// 'Unable to unlink your GitHub Account.' => '',
|
||||
// 'Login with my GitHub Account' => '',
|
||||
// 'Link my GitHub Account' => '',
|
||||
// 'Unlink my GitHub Account' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -382,4 +382,12 @@ return array(
|
|||
// 'Maximum size: ' => '',
|
||||
// 'Unable to upload the file.' => '',
|
||||
// 'Display another project' => '',
|
||||
// 'Your GitHub account was successfully linked to your profile.' => '',
|
||||
// 'Unable to link your GitHub Account.' => '',
|
||||
// 'GitHub authentication failed' => '',
|
||||
// 'Your GitHub account is no longer linked to your profile.' => '',
|
||||
// 'Unable to unlink your GitHub Account.' => '',
|
||||
// 'Login with my GitHub Account' => '',
|
||||
// 'Link my GitHub Account' => '',
|
||||
// 'Unlink my GitHub Account' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class Acl extends Base
|
|||
* @var array
|
||||
*/
|
||||
private $public_actions = array(
|
||||
'user' => array('login', 'check', 'google'),
|
||||
'user' => array('login', 'check', 'google', 'github'),
|
||||
'task' => array('add'),
|
||||
'board' => array('readonly'),
|
||||
);
|
||||
|
|
@ -32,7 +32,7 @@ class Acl extends Base
|
|||
'app' => array('index'),
|
||||
'board' => array('index', 'show', 'assign', 'assigntask', 'save', 'check'),
|
||||
'project' => array('tasks', 'index', 'forbidden', 'search'),
|
||||
'user' => array('index', 'edit', 'update', 'forbidden', 'logout', 'index', 'unlinkgoogle'),
|
||||
'user' => array('index', 'edit', 'update', 'forbidden', 'logout', 'index', 'unlinkgoogle', 'unlinkgithub'),
|
||||
'config' => array('index', 'removeremembermetoken'),
|
||||
'comment' => array('create', 'save', 'confirm', 'remove', 'update', 'edit', 'forbidden'),
|
||||
'file' => array('create', 'save', 'download', 'confirm', 'remove', 'open', 'image'),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
require __DIR__.'/../../vendor/OAuth/bootstrap.php';
|
||||
|
||||
use OAuth\Common\Storage\Session;
|
||||
use OAuth\Common\Consumer\Credentials;
|
||||
use OAuth\Common\Http\Uri\UriFactory;
|
||||
use OAuth\ServiceFactory;
|
||||
use OAuth\Common\Http\Exception\TokenResponseException;
|
||||
|
||||
/**
|
||||
* GitHub model
|
||||
*
|
||||
* @package model
|
||||
*/
|
||||
class GitHub extends Base
|
||||
{
|
||||
/**
|
||||
* Authenticate a GitHub user
|
||||
*
|
||||
* @access public
|
||||
* @param string $github_id GitHub user id
|
||||
* @return boolean
|
||||
*/
|
||||
public function authenticate($github_id)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
$user = $userModel->getByGitHubId($github_id);
|
||||
|
||||
if ($user) {
|
||||
|
||||
// Create the user session
|
||||
$userModel->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$lastLogin = new LastLogin($this->db, $this->event);
|
||||
$lastLogin->create(
|
||||
LastLogin::AUTH_GITHUB,
|
||||
$user['id'],
|
||||
$userModel->getIpAddress(),
|
||||
$userModel->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a GitHub account for a given user
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @return boolean
|
||||
*/
|
||||
public function unlink($user_id)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
return $userModel->update(array(
|
||||
'id' => $user_id,
|
||||
'github_id' => '',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user table based on the GitHub profile information
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @param array $profile GitHub profile
|
||||
* @return boolean
|
||||
* @todo Don't overwrite existing email/name with empty GitHub data
|
||||
*/
|
||||
public function updateUser($user_id, array $profile)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
return $userModel->update(array(
|
||||
'id' => $user_id,
|
||||
'github_id' => $profile['id'],
|
||||
'email' => $profile['email'],
|
||||
'name' => $profile['name'],
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GitHub service instance
|
||||
*
|
||||
* @access public
|
||||
* @return \OAuth\OAuth2\Service\GitHub
|
||||
*/
|
||||
public function getService()
|
||||
{
|
||||
$uriFactory = new UriFactory();
|
||||
$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER);
|
||||
$currentUri->setQuery('controller=user&action=gitHub');
|
||||
|
||||
$storage = new Session(false);
|
||||
|
||||
$credentials = new Credentials(
|
||||
GITHUB_CLIENT_ID,
|
||||
GITHUB_CLIENT_SECRET,
|
||||
$currentUri->getAbsoluteUri()
|
||||
);
|
||||
|
||||
$serviceFactory = new ServiceFactory();
|
||||
|
||||
return $serviceFactory->createService(
|
||||
'gitHub',
|
||||
$credentials,
|
||||
$storage,
|
||||
array('')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authorization URL
|
||||
*
|
||||
* @access public
|
||||
* @return \OAuth\Common\Http\Uri\Uri
|
||||
*/
|
||||
public function getAuthorizationUrl()
|
||||
{
|
||||
return $this->getService()->getAuthorizationUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GitHub profile information from the API
|
||||
*
|
||||
* @access public
|
||||
* @param string $code GitHub authorization code
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getGitHubProfile($code)
|
||||
{
|
||||
try {
|
||||
$gitHubService = $this->getService();
|
||||
$gitHubService->requestAccessToken($code);
|
||||
|
||||
return json_decode($gitHubService->request('user'), true);
|
||||
}
|
||||
catch (TokenResponseException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes this user's GitHub tokens for Kanboard
|
||||
*
|
||||
* @access public
|
||||
* @return bool|array
|
||||
* @todo Currently this simply removes all our tokens for this user, ideally it should
|
||||
* restrict itself to the one in question
|
||||
*/
|
||||
public function revokeGitHubAccess()
|
||||
{
|
||||
try {
|
||||
$gitHubService = $this->getService();
|
||||
|
||||
$basicAuthHeader = array('Authorization' => 'Basic ' .
|
||||
base64_encode(GITHUB_CLIENT_ID.':'.GITHUB_CLIENT_SECRET));
|
||||
|
||||
return json_decode($gitHubService->request('/applications/'.GITHUB_CLIENT_ID.'/tokens', 'DELETE', null, $basicAuthHeader), true);
|
||||
}
|
||||
catch (TokenResponseException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ class LastLogin extends Base
|
|||
const AUTH_REMEMBER_ME = 'remember_me';
|
||||
const AUTH_LDAP = 'ldap';
|
||||
const AUTH_GOOGLE = 'google';
|
||||
const AUTH_GITHUB = 'github';
|
||||
|
||||
/**
|
||||
* Create a new record
|
||||
|
|
|
|||
|
|
@ -51,6 +51,18 @@ class User extends Base
|
|||
return $this->db->table(self::TABLE)->eq('google_id', $google_id)->findOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific user by the GitHub id
|
||||
*
|
||||
* @access public
|
||||
* @param string $github_id GitHub user id
|
||||
* @return array
|
||||
*/
|
||||
public function getByGitHubId($github_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('github_id', $github_id)->findOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific user by the username
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,7 +3,12 @@
|
|||
namespace Schema;
|
||||
|
||||
use Core\Security;
|
||||
const VERSION = 19;
|
||||
const VERSION = 20;
|
||||
|
||||
function version_20($pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE users ADD COLUMN github_id VARCHAR(30)");
|
||||
}
|
||||
|
||||
function version_19($pdo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,12 @@
|
|||
namespace Schema;
|
||||
use Core\Security;
|
||||
|
||||
const VERSION = 19;
|
||||
const VERSION = 20;
|
||||
|
||||
function version_20($pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE users ADD COLUMN github_id TEXT");
|
||||
}
|
||||
|
||||
function version_19($pdo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,14 +48,27 @@
|
|||
<?= Helper\form_checkbox('is_admin', t('Administrator'), 1, isset($values['is_admin']) && $values['is_admin'] == 1 ? true : false) ?><br/>
|
||||
<?php endif ?>
|
||||
|
||||
<ul>
|
||||
<?php if (GOOGLE_AUTH && Helper\is_current_user($values['id'])): ?>
|
||||
<li>
|
||||
<?php if (empty($values['google_id'])): ?>
|
||||
<a href="?controller=user&action=google<?= Helper\param_csrf() ?>"><?= t('Link my Google Account') ?></a>
|
||||
<?php else: ?>
|
||||
<a href="?controller=user&action=unlinkGoogle<?= Helper\param_csrf() ?>"><?= t('Unlink my Google Account') ?></a>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (GITHUB_AUTH && Helper\is_current_user($values['id'])): ?>
|
||||
<li>
|
||||
<?php if (empty($values['github_id'])): ?>
|
||||
<a href="?controller=user&action=gitHub<?= Helper\param_csrf() ?>"><?= t('Link my GitHub Account') ?></a>
|
||||
<?php else: ?>
|
||||
<a href="?controller=user&action=unlinkGitHub<?= Helper\param_csrf() ?>"><?= t('Unlink my GitHub Account') ?></a>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
|
|
|
|||
|
|
@ -18,12 +18,20 @@
|
|||
|
||||
<?= Helper\form_checkbox('remember_me', t('Remember Me'), 1) ?><br/>
|
||||
|
||||
<ul>
|
||||
<?php if (GOOGLE_AUTH): ?>
|
||||
<p>
|
||||
<li>
|
||||
<a href="?controller=user&action=google"><?= t('Login with my Google Account') ?></a>
|
||||
</p>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (GITHUB_AUTH): ?>
|
||||
<li>
|
||||
<a href="?controller=user&action=gitHub"><?= t('Login with my GitHub Account') ?></a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
|
||||
<div class="form-actions">
|
||||
<input type="submit" value="<?= t('Sign in') ?>" class="btn btn-blue"/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ defined('GOOGLE_AUTH') or define('GOOGLE_AUTH', false);
|
|||
defined('GOOGLE_CLIENT_ID') or define('GOOGLE_CLIENT_ID', '');
|
||||
defined('GOOGLE_CLIENT_SECRET') or define('GOOGLE_CLIENT_SECRET', '');
|
||||
|
||||
// GitHub authentication
|
||||
defined('GITHUB_AUTH') or define('GITHUB_AUTH', false);
|
||||
defined('GITHUB_CLIENT_ID') or define('GITHUB_CLIENT_ID', '');
|
||||
defined('GITHUB_CLIENT_SECRET') or define('GITHUB_CLIENT_SECRET', '');
|
||||
|
||||
$loader = new Loader;
|
||||
$loader->execute();
|
||||
|
||||
|
|
|
|||
|
|
@ -249,11 +249,21 @@ input.form-date {
|
|||
padding-left: 0;
|
||||
}
|
||||
|
||||
.form-column ul {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.form-login {
|
||||
padding-left: 20px;
|
||||
width: 430px;
|
||||
}
|
||||
|
||||
.form-column li,
|
||||
.form-login li {
|
||||
margin-left: 25px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
/* alerts */
|
||||
.alert {
|
||||
padding: 8px 35px 8px 14px;
|
||||
|
|
|
|||
|
|
@ -43,3 +43,12 @@ define('GOOGLE_CLIENT_ID', '');
|
|||
|
||||
// Google client secret key (Get this value from the Google developer console)
|
||||
define('GOOGLE_CLIENT_SECRET', '');
|
||||
|
||||
// Enable/disable GitHub authentication
|
||||
define('GITHUB_AUTH', false);
|
||||
|
||||
// GitHub client id (Copy it from your settings -> Applications -> Developer applications)
|
||||
define('GITHUB_CLIENT_ID', '');
|
||||
|
||||
// GitHub client secret key (Copy it from your settings -> Applications -> Developer applications)
|
||||
define('GITHUB_CLIENT_SECRET', '');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
GitHub Authentication
|
||||
=====================
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
- OAuth GitHub API credentials (available in your [Settings > Applications > Developer applications](https://github.com/settings/applications))
|
||||
|
||||
How does this work?
|
||||
-------------------
|
||||
|
||||
The GitHub authentication in Kanboard uses the [OAuth 2.0](http://oauth.net/2/) protocol, so any user of Kanboard can be linked to a GitHub account. When that is done, they no longer need to manually login with their Kanboard account, but can simply automatically login with their GitHub account.
|
||||
|
||||
How to link a GitHub account
|
||||
----------------------------------
|
||||
|
||||
1. Login to Kanboard with the desired user
|
||||
2. Go to the **Edit user** page and click on the link **Link my GitHub Account**
|
||||
3. You are redirected to the GitHub **Authorize application** form, authorize Kanboard by clicking on the button **Accept**
|
||||
4. Finally, you are redirected to Kanboard and now your user account is linked to your GitHub account
|
||||
5. During the process, Kanboard has updated your full name and your email address based on your GitHub profile, if either of those are publically available
|
||||
6. Log out of Kanboard and you should be able to login directly with GitHub by clicking on the link **Login with my GitHub Account**
|
||||
|
||||
Installation instructions
|
||||
-------------------------
|
||||
|
||||
### Setting up OAuth 2.0
|
||||
|
||||
If you know what you're doing, you can directly go to the ["Register a new OAuth application"](https://github.com/settings/applications/new) site, set everything up and skip to [Setting up Kanboard](#setting-up-kanboard) below.
|
||||
|
||||
Summarizing the [official GitHub documentation](https://developer.github.com/guides/basics-of-authentication/#registering-your-app):
|
||||
|
||||
- Open your [**Settings**](https://github.com/settings), select [**Applications**](https://github.com/settings/applications) from the sidebar and click on [**Register new application**](https://github.com/settings/applications/new) on the top, next to where it says **Developer applications**
|
||||
- Fill out the form with whatever values you like, only the **Authorization callback URL** _must_ be: **http://YOUR_SERVER/?controller=user&action=gitHub**
|
||||
|
||||
### Setting up Kanboard
|
||||
|
||||
Either create a new `config.php` file or copy and rename the `config.default.php` file and set the following values:
|
||||
|
||||
```php
|
||||
// Enable/disable GitHub authentication
|
||||
define('GITHUB_AUTH', true);
|
||||
|
||||
// GitHub client id (Copy it from your settings -> Applications -> Developer applications)
|
||||
define('GITHUB_CLIENT_ID', 'YOUR_GITHUB_CLIENT_ID');
|
||||
|
||||
// GitHub client secret key (Copy it from your settings -> Applications -> Developer applications)
|
||||
define('GITHUB_CLIENT_SECRET', 'YOUR_GITHUB_CLIENT_SECRET');
|
||||
|
||||
```
|
||||
|
||||
Notes
|
||||
-----
|
||||
**Important:** _*Never*_ store your GITHUB_CLIENT_ID or GITHUB_CLIENT_SECRET in GitHub or somewhere with full public access in general!
|
||||
|
||||
Kanboard uses these information from your public GitHub profile:
|
||||
|
||||
- Full name
|
||||
- Public email address
|
||||
- GitHub unique id
|
||||
|
||||
The GitHub unique id is used to link the local user account and the GitHub account.
|
||||
Loading…
Reference in New Issue