Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding local user managment #39

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/config-sample.ini
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ password = password
database = ska-db

[ldap]
enabled = 0
; Address to connect to LDAP server
host = ldaps://ldap.example.com:636
; Use StartTLS for connection security (recommended if using ldap:// instead
Expand Down
10 changes: 6 additions & 4 deletions core.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
require('ldap.php');
require('email.php');

$ldap_options = array();
$ldap_options[LDAP_OPT_PROTOCOL_VERSION] = 3;
$ldap_options[LDAP_OPT_REFERRALS] = !empty($config['ldap']['follow_referrals']);
$ldap = new LDAP($config['ldap']['host'], $config['ldap']['starttls'], $config['ldap']['bind_dn'], $config['ldap']['bind_password'], $ldap_options);
if ($config['ldap']['enabled'] == 1) {
$ldap_options = array();
$ldap_options[LDAP_OPT_PROTOCOL_VERSION] = 3;
$ldap_options[LDAP_OPT_REFERRALS] = !empty($config['ldap']['follow_referrals']);
$ldap = new LDAP($config['ldap']['host'], $config['ldap']['starttls'], $config['ldap']['bind_dn'], $config['ldap']['bind_password'], $ldap_options);
}
setup_database();

$relative_frontend_base_url = (string)parse_url($config['web']['baseurl'], PHP_URL_PATH);
Expand Down
159 changes: 159 additions & 0 deletions migrations/004.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php
$migration_name = 'Add local usermanagment';

function free_results($database) {
do {
if ($res = $database->store_result()) {
$res->free();
}
} while ($database->more_results() && $database->next_result());
}

$this->database->autocommit(FALSE);

$result = $this->database->query("
SELECT uid FROM user WHERE uid = 'keys-sync'
");
if ($result) {
if($result->num_rows === 0) {
$result->close();
$result = $this->database->multi_query("
INSERT INTO entity SET type = 'user';
INSERT INTO user SET entity_id = (
SELECT LAST_INSERT_ID()
), uid = 'keys-sync', name = 'Synchronization script', email = '', auth_realm = 'local', admin = 1;
");
free_results($this->database);
} else {
$result->close();
$this->database->query("
UPDATE user SET auth_realm = 'local', active = 1 WHERE uid = 'keys-sync';
");
}
}


$this->database->multi_query("
CREATE TABLE `entity_event_2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`entity_id` int(10) unsigned NOT NULL,
`actor_id` int(10) unsigned,
`date` datetime NOT NULL,
`details` mediumtext NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_entity_event_entity_id` (`entity_id`),
KEY `FK_entity_event_actor_id` (`actor_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT entity_event_2 SELECT * FROM entity_event;

DROP TABLE entity_event;
RENAME TABLE entity_event_2 TO entity_event;

ALTER TABLE `entity_event`
ADD CONSTRAINT `FK_entity_event_actor_id` FOREIGN KEY (`actor_id`) REFERENCES `entity` (`id`) ON DELETE SET NULL,
ADD CONSTRAINT `FK_entity_event_entity_id` FOREIGN KEY (`entity_id`) REFERENCES `entity` (`id`) ON DELETE CASCADE;
");
free_results($this->database);


$this->database->multi_query("
CREATE TABLE `group_event_2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`group` int(10) unsigned NOT NULL,
`entity_id` int(10) unsigned,
`date` datetime NOT NULL,
`details` mediumtext NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_group_event_group` (`group`),
KEY `FK_group_event_entity` (`entity_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT;

INSERT group_event_2 SELECT * FROM group_event;

DROP TABLE group_event;
RENAME TABLE group_event_2 TO group_event;

ALTER TABLE `group_event`
ADD CONSTRAINT `FK_group_event_entity` FOREIGN KEY (`entity_id`) REFERENCES `entity` (`id`) ON DELETE SET NULL,
ADD CONSTRAINT `FK_group_event_group` FOREIGN KEY (`group`) REFERENCES `group` (`entity_id`) ON DELETE CASCADE;
");
free_results($this->database);


$this->database->multi_query("
CREATE TABLE `group_member_2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`group` int(10) unsigned NOT NULL,
`entity_id` int(10) unsigned NOT NULL,
`add_date` datetime NOT NULL,
`added_by` int(10) unsigned,
PRIMARY KEY (`id`),
UNIQUE KEY `group_entity_id` (`group`, `entity_id`),
KEY `FK_group_member_entity` (`entity_id`),
KEY `FK_group_member_entity_2` (`added_by`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT;

INSERT group_member_2 SELECT * FROM group_member;

DROP TABLE group_member;
RENAME TABLE group_member_2 TO group_member;

ALTER TABLE `group_member`
ADD CONSTRAINT `FK_group_member_entity` FOREIGN KEY (`entity_id`) REFERENCES `entity` (`id`) ON DELETE CASCADE,
ADD CONSTRAINT `FK_group_member_entity_2` FOREIGN KEY (`added_by`) REFERENCES `entity` (`id`) ON DELETE SET NULL,
ADD CONSTRAINT `FK_group_member_group` FOREIGN KEY (`group`) REFERENCES `group` (`entity_id`) ON DELETE CASCADE
");
free_results($this->database);


$this->database->multi_query("
CREATE TABLE `server_event_2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`server_id` int(10) unsigned NOT NULL,
`actor_id` int(10) unsigned,
`date` datetime NOT NULL,
`details` mediumtext NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_server_log_server` (`server_id`),
KEY `FK_server_event_actor_id` (`actor_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT server_event_2 SELECT * FROM server_event;

DROP TABLE server_event;
RENAME TABLE server_event_2 TO server_event;

ALTER TABLE `server_event`
ADD CONSTRAINT `FK_server_event_actor_id` FOREIGN KEY (`actor_id`) REFERENCES `entity` (`id`) ON DELETE SET NULL,
ADD CONSTRAINT `FK_server_log_server` FOREIGN KEY (`server_id`) REFERENCES `server` (`id`) ON DELETE CASCADE;
");
free_results($this->database);


$this->database->multi_query("
CREATE TABLE `server_note_2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`server_id` int(10) unsigned NOT NULL,
`entity_id` int(10) unsigned,
`date` datetime NOT NULL,
`note` mediumtext NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_server_note_server` (`server_id`),
KEY `FK_server_note_user` (`entity_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT server_note_2 SELECT * FROM server_note;

DROP TABLE server_note;
RENAME TABLE server_note_2 TO server_note;

ALTER TABLE `server_note`
ADD CONSTRAINT `FK_server_note_entity` FOREIGN KEY (`entity_id`) REFERENCES `entity` (`id`) ON DELETE SET NULL,
ADD CONSTRAINT `FK_server_note_server` FOREIGN KEY (`server_id`) REFERENCES `server` (`id`) ON DELETE CASCADE
");
free_results($this->database);

$this->database->commit();

$this->database->autocommit(TRUE);
2 changes: 1 addition & 1 deletion model/migrationdirectory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MigrationDirectory extends DBDirectory {
/**
* Increment this constant to activate a new migration from the migrations directory
*/
const LAST_MIGRATION = 3;
const LAST_MIGRATION = 4;

public function __construct() {
parent::__construct();
Expand Down
17 changes: 17 additions & 0 deletions model/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,23 @@ public function update() {
}
}

/**
* Delete the given user.
*/
public function delete() {
if(is_null($this->entity_id)) throw new BadMethodCallException('User must be in directory before it can be removed');
$stmt = $this->database->prepare("DELETE FROM entity WHERE id = ?");
$stmt->bind_param('d', $this->entity_id);
$stmt->execute();
$stmt->close();
$stmt = $this->database->prepare("DELETE FROM user WHERE entity_id = ?");
$stmt->bind_param('d', $this->entity_id);
$stmt->execute();
$stmt->close();

$this->sync_remote_access();
}

/**
* Magic getter method - if superior field requested, return User object of user's superior
* @param string $field to retrieve
Expand Down
41 changes: 29 additions & 12 deletions model/userdirectory.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,22 @@ public function add_user(User $user) {
$user_active = $user->active;
$user_admin = $user->admin;
$user_email = $user->email;
$stmt = $this->database->prepare("INSERT INTO entity SET type = 'user'");
$stmt->execute();
$user->entity_id = $stmt->insert_id;
$stmt = $this->database->prepare("INSERT INTO user SET entity_id = ?, uid = ?, name = ?, email = ?, active = ?, admin = ?");
$stmt->bind_param('dsssdd', $user->entity_id, $user_id, $user_name, $user_email, $user_active, $user_admin);
$stmt->execute();
$stmt->close();
try {
$stmt = $this->database->prepare("INSERT INTO entity SET type = 'user'");
$stmt->execute();
$user->entity_id = $stmt->insert_id;
$stmt = $this->database->prepare("INSERT INTO user SET entity_id = ?, uid = ?, name = ?, email = ?, active = ?, admin = ?, auth_realm = ?");
$stmt->bind_param('dsssdds', $user->entity_id, $user_id, $user_name, $user_email, $user_active, $user_admin, $user->auth_realm);
$stmt->execute();
$stmt->close();
} catch(mysqli_sql_exception $e) {
if($e->getCode() == 1062) {
// Duplicate entry
throw new UserAlreadyExistsException("User {$user->uid} already exists");
} else {
throw $e;
}
}
}

/**
Expand Down Expand Up @@ -82,6 +91,8 @@ public function get_user_by_id($id) {
* @throws UserNotFoundException if no user with that uid exists
*/
public function get_user_by_uid($uid) {
global $config;
$ldap_enabled = $config['ldap']['enabled'];
if(isset($this->cache_uid[$uid])) {
return $this->cache_uid[$uid];
}
Expand All @@ -93,11 +104,16 @@ public function get_user_by_uid($uid) {
$user = new User($row['entity_id'], $row);
$this->cache_uid[$uid] = $user;
} else {
$user = new User;
$user->uid = $uid;
$this->cache_uid[$uid] = $user;
$user->get_details_from_ldap();
$this->add_user($user);
if ($ldap_enabled == 1) {
$user = new User;
$user->uid = $uid;
$this->cache_uid[$uid] = $user;
$user->auth_realm = 'LDAP';
$user->get_details_from_ldap();
$this->add_user($user);
} else {
throw new UserNotFoundException('User does not exist.');
}
}
$stmt->close();
return $user;
Expand Down Expand Up @@ -148,3 +164,4 @@ public function list_users($include = array(), $filter = array()) {
}

class UserNotFoundException extends Exception {}
class UserAlreadyExistsException extends Exception {}
21 changes: 14 additions & 7 deletions requesthandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,32 @@
ob_start();
set_exception_handler('exception_handler');

if(isset($_SERVER['PHP_AUTH_USER'])) {
$active_user = $user_dir->get_user_by_uid($_SERVER['PHP_AUTH_USER']);
} else {
throw new Exception("Not logged in.");
}

// Work out where we are on the server
$base_path = dirname(__FILE__);
$base_url = dirname($_SERVER['SCRIPT_NAME']);
$request_url = $_SERVER['REQUEST_URI'];
$relative_request_url = preg_replace('/^'.preg_quote($base_url, '/').'/', '/', $request_url);
$absolute_request_url = 'http'.(isset($_SERVER['HTTPS']) ? 's' : '').'://'.$_SERVER['HTTP_HOST'].$request_url;

if(isset($_SERVER['PHP_AUTH_USER'])) {
try {
$active_user = $user_dir->get_user_by_uid($_SERVER['PHP_AUTH_USER']);
} catch(UserNotFoundException $ex) {
require('views/error403.php');
die;
}
} else {
throw new Exception("Not logged in.");
}

if(empty($config['web']['enabled'])) {
require('views/error503.php');
die;
}

if(!$active_user->active) {
require('views/error403.php');
die;
}

if(!empty($_POST)) {
Expand All @@ -62,10 +68,11 @@
if(isset($router->view)) {
$view = path_join($base_path, 'views', $router->view.'.php');
if(file_exists($view)) {
if($active_user->auth_realm == 'LDAP' || $router->public) {
if($active_user->auth_realm == 'LDAP' || $active_user->auth_realm == 'local' || $router->public) {
require($view);
} else {
require('views/error403.php');
die;
}
} else {
throw new Exception("View file $view missing.");
Expand Down
22 changes: 14 additions & 8 deletions scripts/ldap_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,28 @@
$active_user->uid = 'keys-sync';
$active_user->name = 'Synchronization script';
$active_user->email = '';
$active_user->auth_realm = 'local';
$active_user->active = 1;
$active_user->admin = 1;
$active_user->developer = 0;
$user_dir->add_user($active_user);
}

try {
$sysgrp = $group_dir->get_group_by_name($config['ldap']['admin_group_cn']);
} catch(GroupNotFoundException $e) {
$sysgrp = new Group;
$sysgrp->name = $config['ldap']['admin_group_cn'];
$sysgrp->system = 1;
$group_dir->add_group($sysgrp);
$ldap_enabled = $config['ldap']['enabled'];

if($ldap_enabled == 1) {
try {
$sysgrp = $group_dir->get_group_by_name($config['ldap']['admin_group_cn']);
} catch(GroupNotFoundException $e) {
$sysgrp = new Group;
$sysgrp->name = $config['ldap']['admin_group_cn'];
$sysgrp->system = 1;
$group_dir->add_group($sysgrp);
}
}

foreach($users as $user) {
if($user->auth_realm == 'LDAP') {
if($user->auth_realm == 'LDAP' && $ldap_enabled == 1) {
$active = $user->active;
try {
$user->get_details_from_ldap();
Expand Down
1 change: 1 addition & 0 deletions scripts/sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
$active_user->uid = 'keys-sync';
$active_user->name = 'Synchronization script';
$active_user->email = '';
$active_user->auth_realm = 'local';
$active_user->active = 1;
$active_user->admin = 1;
$active_user->developer = 0;
Expand Down
4 changes: 4 additions & 0 deletions templates/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ function show_event($event) {
<a href="<?php outurl('/groups/'.urlencode($event->group->name))?>" class="group"><?php out($event->group->name) ?></a>
<?php } ?>
</td>
<?php if(is_null($event->actor->uid)) { ?>
<td>removed</td>
<?php } else { ?>
<td><a href="<?php outurl('/users/'.urlencode($event->actor->uid))?>" class="user"><?php out($event->actor->uid) ?></a></td>
<?php } ?>
<td><?php out($details, ESC_NONE) ?></td>
<td class="nowrap"><?php out($event->date) ?></td>
</tr>
Expand Down
Loading