xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
<root> / inc / admin.inc.php (1127ab1a4ff007ef0420873a721f7329faaa30bc) (9,031B) (mode 100644) [raw]
<?php
$INC = isset($INC) ? $INC : dirname(__FILE__);
require_once($INC . "/user.inc.php");

/*
 * Event functions
 */
$rg_admin_functions = array(
	6000 => "rg_admin_invite",
	6001 => "rg_admin_invite_one"
);
rg_event_register_functions($rg_admin_functions);

/*
 * Event for invites
 */
function rg_admin_invite($db, $event)
{
	$ret = array();

	rg_log_ml("DEBUG: event[list]=" . print_r($event['list'], TRUE));
	foreach ($event['list'] as $line) {
		$line = trim($line);
		if (empty($line))
			continue;

		$t = explode('|', $line, 2);

		$ret[] = array_merge($event,
			array(
				'category' => 6001,
				'prio' => 100,
				'email' => trim($t[0]),
				'name' => trim($t[1])
			)
		);
	}

	return $ret;
}

/*
 * Event for invites (one e-mail version)
 */
function rg_admin_invite_one($db, $event)
{
	global $rg_admin_email;

	$rg = array();
	$subject = preg_replace('/{NAME}/', $event['name'], $event['subject']);
	$subject = "=?UTF-8?B?" . base64_encode(trim($subject)) . "?=";
	$header = rg_template("mail/common.head.txt", $rg);
	$body = preg_replace('/{NAME}/', $event['name'], $event['body']);

	$r = mail($event['email'], $subject, $body, $header,
		"-f $rg_admin_email");

	if ($r === FALSE)
		return FALSE;

	return array();
}

/*
 * Deals with invites
 */
function rg_admin_invites_high_level($db, $rg)
{
	rg_log_enter("rg_admin_invites_high_level");

	$ret = "";

	$inv = array();
	$inv['list'] = "";
	$inv['subject'] = "";
	$inv['body'] = "";

	$errmsg = array();
	$show_form = TRUE;
	while (1) {
		if (rg_var_int("doit") == 0)
			break;

		$inv['list'] = rg_var_str("inv::list");
		$inv['subject'] = rg_var_str("inv::subject");
		$inv['body'] = rg_var_str("inv::body");

		if (!rg_valid_referer()) {
			$errmsg[] = "invalid referer; try again";
			break;
		}

		if (!rg_token_valid($db, $rg, FALSE)) {
			$errmsg[] = "invalid token; try again";
			break;
		}

		if (empty($inv['list'])) {
			$errmsg[] = "list is empty";
			break;
		}

		if (empty($inv['subject'])) {
			$errmsg[] = "subject is empty";
			break;
		}

		if (empty($inv['body'])) {
			$errmsg[] = "body is empty";
			break;
		}

		$list = explode("\n", trim($inv['list']));
		foreach ($list as $line) {
			$line = trim($line);
			if (empty($line))
				continue;

			$t = explode('|', $line, 2);
			if (count($t) != 2) {
				$errmsg[] = 'invalid line: ' . rg_xss_safe($line);
			} else {
				if (!strstr($t[0], '@'))
					$errmsg[] = 'invalid e-mail in line: ' . rg_xss_safe($line);
			}
		}
		if (!empty($errmsg))
			break;

		$event = array(
			'category' => 6000,
			'prio' => 50);
		$event = array_merge($event, $inv);
		$event['list'] = $list;
		$r = rg_event_add($db, $event);
		if ($r !== TRUE) {
			$errmsg[] = "cannot add event (" . rg_event_error() . ")";
			break;
		}

		rg_event_signal_daemon("", 0);

		$ret .= rg_template("admin/invites/sent.html", $rg);
		$show_form = FALSE;
                break;
	}

	if ($show_form) {
		$rg['inv'] = $inv;
		$rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
		$rg['rg_form_token'] = rg_token_get($db, $rg);
		$ret .= rg_template("admin/invites/invites.html", $rg);
	}

	rg_log_exit();
	return $ret;
}

/*
 * Prepares an instalation for first use
 */
function rg_init($db, $rg)
{
	global $rg_admin_name;
	global $rg_admin_email;

	rg_prof_start("rg_init");
	rg_log_enter("rg_init");

	$ret = '';

	$doit = rg_var_uint('doit');
	if ($doit == 0) {
		$rg['init']['username'] = 'admin';
		$rg['init']['realname'] = $rg_admin_name;
		$rg['init']['email'] = $rg_admin_email;
		$rg['init']['pass'] = '';
		$rg['init']['pass2'] = '';
		$rg['init']['session_time'] = 600;
	}

	$errmsg = array();
	$load_form = TRUE;
	while ($doit == 1) {
		$rg['init'] = array();
		$rg['init']['uid'] = 0;
		$rg['init']['is_admin'] = 1;
		$rg['init']['rights'] = rg_rights_all('user');
		$rg['init']['confirm_token'] = '';
		$rg['init']['plan_id'] = 1;
		$rg['init']['username'] = rg_var_str('init::username');
		$rg['init']['realname'] = rg_var_str('init::realname');
		$rg['init']['email'] = rg_var_str('init::email');
		$rg['init']['pass'] = rg_var_str('init::pass');
		$rg['init']['pass2'] = rg_var_str('init::pass2');
		$rg['init']['session_time'] = rg_var_uint('init::session_time');
		$rg['init']['confirmed'] = 1; /* = no need to confirm */

		if (!rg_valid_referer()) {
			$errmsg[] = "invalid referer; try again";
			break;
		}

		if (!rg_token_valid($db, $rg, FALSE)) {
			$errmsg[] = "invalid token; try again";
			break;
		}

		$r = rg_user_edit($db, $rg['init']);
		if ($r === FALSE) {
			$errmsg[] = rg_user_error();
			break;
		}

		rg_state_set($db, 'first_install', time());

		$ret .= rg_template('user/create_ok.html', $rg);
		$load_form = FALSE;
		break;
	}

	if ($load_form) {
		$rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
		$rg['rg_form_token'] = rg_token_get($db, $rg);
		$ret .= rg_template("admin/init.html", $rg);
	}

	rg_log_exit();
	rg_prof_end("rg_init");
	return $ret;
}

/*
 * Helper for rg_admin_report1 - suggestion report
 */
function rg_admin_report1_suggestions($db, $from, $to)
{
	$ret = array();
	$ret['yesterday'] = "";

	// Total
	$sql = "SELECT COUNT(*) AS total FROM suggestions";
	$res = rg_sql_query($db, $sql);
	if ($res === FALSE) {
		$ret['total'] = "ERR";
	} else {
		$row = rg_sql_fetch_array($res);
		$ret['total'] = $row['total'];
	}
	rg_sql_free_result($res);

	// Yesterday - not yet because we do not have itime
	/*
	$sql = "SELECT uid, suggestion FROM suggestions"
		. " WHERE itime >= $y_start"
		. " AND itime <= $y_end";
	$res = rg_sql_query($db, $sql);
	if ($res === FALSE) {
		$ret['yesterday'] = "ERR";
	} else {
		$count = 0;
		$list = '';
		while (($row = rg_sql_fetch_array($res))) {
			$count++;
			$list .= sprintf("%8u %s\n",
				$row['uid'], $row['suggestion']);
		}
		if ($count)
			$ret['yesterday'] = "\nYesterday suggestions"
				. " (" . $count . "):\n" . $list;
	}
	rg_sql_free_result($res);
	*/

	return $ret;
}

/*
 * Send some daily statistics to the admin
 */
function rg_admin_report1($db, $rg)
{
	global $rg_admin_email;

	$body = '';

	$y_start = gmmktime(0, 0, 0, gmdate("m"), gmdate("d") - 1);
	$y_end = gmmktime(0, 0, 0, gmdate("m"), gmdate("d")) - 1;

	$body .= "Report between " . gmdate('Y-m-d H:i:s', $y_start)
		. " and " . gmdate('Y-m-d H:i:s', $y_end) . " UTC\n";

	$sql = "SELECT COUNT(*) AS total FROM users";
	$res = rg_sql_query($db, $sql);
	if ($res === FALSE) {
		$total_users = "ERR";
	} else {
		$row = rg_sql_fetch_array($res);
		$total_users = $row['total'];
		$body .= "\nTotal users: " . $total_users . "\n";
	}
	rg_sql_free_result($res);

	$sql = "SELECT COUNT(*) AS total FROM repos";
	$res = rg_sql_query($db, $sql);
	if ($res === FALSE) {
		$total_repos = "ERR";
	} else {
		$row = rg_sql_fetch_array($res);
		$total_repos = $row['total'];
		$body .= "\nTotal repositories: " . $total_users . "\n";
	}
	rg_sql_free_result($res);

	$sql = "SELECT username, realname FROM users"
		. " WHERE itime >= $y_start"
		. " AND itime <= $y_end";
	$res = rg_sql_query($db, $sql);
	if ($res === FALSE) {
		$users = "ERR";
	} else {
		$users = 0;
		$list = '';
		while (($row = rg_sql_fetch_array($res))) {
			$users++;
			$list .= sprintf("%30s %s\n",
				$row['username'], $row['realname']);
		}
		if ($users)
			$body .= "\nYesterday users (" . $users . "):\n" . $list;
	}
	rg_sql_free_result($res);

	$sql = "SELECT name, description FROM repos"
		. " WHERE itime >= $y_start"
		. " AND itime <= $y_end";
	$res = rg_sql_query($db, $sql);
	if ($res === FALSE) {
		$repos = "ERR";
	} else {
		$repos = 0;
		$list = '';
		while (($row = rg_sql_fetch_array($res))) {
			$repos++;
			$desc = substr($row['description'], 0, 50);
			$desc = preg_replace('/\s/', ' ', $desc);
			$list .= $row['name'] . " - " . $desc . "\n";
		}
		if ($repos)
			$body .= "\nYesterday repos (" . $repos . "):\n" . $list;
	}
	rg_sql_free_result($res);

	$sug = rg_admin_report1_suggestions($db, $y_start, $y_end);
	$body .= "\n\nTotal suggestions: " . $sug['total'] . "\n";
	$body .= $sug['yesterday'] . "\n";

	$rg['ui::email'] = $rg_admin_email;
	$rg['mail::subject'] = 'RocketGit daily report'
		. ' [' . $users . '/' . $total_users . ']'
		. ' [' . $repos . '/' . $total_repos . ']';
	$rg['mail::body'] = $body;
	rg_mail_template("mail/admin/report1", $rg);
}

/*
 * Function to clean the log files
 * It is called by both crons (under apache and under rocketgit users)
 */
function rg_clean_logs($dir)
{
	global $rg_logs_lifetime;

	if ($rg_logs_lifetime == 0)
		return;

	$files = glob($dir . "/*.log");
	if ($files === FALSE) {
		rg_log("Cannot select logs for delete");
		return FALSE;
	}

	$limit_ts = gmmktime(0, 0, 0, gmdate('m'), gmdate('d') - $rg_logs_lifetime);
	$limit = gmdate("Ymd", $limit_ts);
	rg_log("limit_ts=$limit_ts limit=$limit");

	foreach ($files as $file) {
		$ymd = preg_replace('/.*-([0-9]*)\.log/', '$1', $file);
		//rg_log("file=$file ymd=$ymd");

		if ($ymd >= $limit)
			continue;

		rg_log("Deleting old log file $file");
		$r = unlink($file);
		if ($r === FALSE)
			rg_log("Cannot delete file $file!");
	}
}

?>
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master