mod_feature_update_user_stats_sql.pm 4.73 KB
Newer Older
Robert Anderson's avatar
Robert Anderson committed
1
# Support for updating of user stats
2 3
# Copyright (C) 2007-2016, AllWorldIT
#
Robert Anderson's avatar
Robert Anderson committed
4 5 6 7
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
8
#
Robert Anderson's avatar
Robert Anderson committed
9 10 11 12
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
13
#
Robert Anderson's avatar
Robert Anderson committed
14 15 16 17 18 19 20 21 22 23 24
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

package smradius::modules::features::mod_feature_update_user_stats_sql;

use strict;
use warnings;

# Modules we need
use smradius::constants;
25
use AWITPT::DB::DBLayer;
Robert Anderson's avatar
Robert Anderson committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
use smradius::logging;
use smradius::util;

# Exporter stuff
require Exporter;
our (@ISA,@EXPORT,@EXPORT_OK);
@ISA = qw(Exporter);
@EXPORT = qw(
);
@EXPORT_OK = qw(
);



# Plugin info
our $pluginInfo = {
	Name => "Update User Stats",
	Init => \&init,

	# Accounting hook
	'Feature_Post-Accounting_hook' => \&updateUserStats
};


# Module config
my $config;


## @internal
# Initialize module
sub init
{
	my $server = shift;
	my $scfg = $server->{'inifile'};


	# Enable support for database
	$server->log(LOG_NOTICE,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] Enabling database support");
	if (!$server->{'smradius'}->{'database'}->{'enabled'}) {
		$server->log(LOG_NOTICE,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] Enabling database support.");
		$server->{'smradius'}->{'database'}->{'enabled'} = 1;
	}

	# Default configs...
	$config->{'update_user_stats_query'} = '
		UPDATE
			@TP@users
		SET
			PeriodKey = %{query.PeriodKey},
			TotalTraffic = %{query.TotalTraffic},
			TotalUptime = %{query.TotalUptime},
77 78
			NASIdentifier = %{request.NAS-Identifier},
			LastAcctUpdate = now()
Robert Anderson's avatar
Robert Anderson committed
79
		WHERE
80
			Username = %{user.Username}
Robert Anderson's avatar
Robert Anderson committed
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
	';

	# Setup SQL queries
	if (defined($scfg->{'mod_feature_update_user_stats_sql'})) {
		# Pull in queries
		if (defined($scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'}) &&
				$scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'} ne "") {
			if (ref($scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'}) eq "ARRAY") {
				$config->{'update_user_stats_query'} = join(' ',
						@{$scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'}});
			} else {
				$config->{'update_user_stats_query'} = $scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'};
			}
		}
	}
}


## @updateUserStats($server,$user,$packet)
# Post authentication hook
#
# @param server Server object
# @param user User data
# @param packet Radius packet
#
# @return Result
sub updateUserStats
{
	my ($server,$user,$packet) = @_;

111 112

	# Skip MAC authentication
Nigel Kukard's avatar
Nigel Kukard committed
113
	return MOD_RES_SKIP if (defined($user->{'_UserDB'}->{'Name'}) &&
114
			$user->{'_UserDB'}->{'Name'} eq "SQL User Database (MAC authentication)");
Nigel Kukard's avatar
Nigel Kukard committed
115

116 117
	$server->log(LOG_DEBUG,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] UPDATE USER STATS HOOK");

Robert Anderson's avatar
Robert Anderson committed
118 119 120 121 122
	# Build template
	my $template;
	foreach my $attr ($packet->attributes) {
		$template->{'request'}->{$attr} = $packet->rawattr($attr)
	}
123 124 125 126

	# Add user details
	$template->{'user'}->{'ID'} = $user->{'ID'};
	$template->{'user'}->{'Username'} = $user->{'Username'};
Robert Anderson's avatar
Robert Anderson committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140

	# Current PeriodKey
	my $now = DateTime->now->set_time_zone($server->{'smradius'}->{'event_timezone'});
	$template->{'query'}->{'PeriodKey'} = $now->strftime("%Y-%m");

	# Loop with plugins to find anything supporting getting of usage
	my $accountingUsage;
	foreach my $module (@{$server->{'module_list'}}) {
		# Do we have the correct plugin?
		if ($module->{'Accounting_getUsage'}) {
			$server->log(LOG_INFO,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] Found plugin: '".$module->{'Name'}."'");
			# Fetch users session uptime & bandwidth used
			my $res = $module->{'Accounting_getUsage'}($server,$user,$packet);
			if (!defined($res)) {
141
				$server->log(LOG_ERR,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] No usage data found for user '".$user->{'Username'}."'");
Robert Anderson's avatar
Robert Anderson committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
				return MOD_RES_SKIP;
			}

			$accountingUsage = $res;
		}
	}

	# Add to our template hash
	$template->{'query'}->{'TotalTraffic'} = $accountingUsage->{'TotalDataUsage'};
	$template->{'query'}->{'TotalUptime'} = $accountingUsage->{'TotalSessionTime'};

	# Replace template entries
	my (@dbDoParams) = templateReplace($config->{'update_user_stats_query'},$template);

	# Perform query
	my $sth = DBDo(@dbDoParams);
	if (!$sth) {
159
		$server->log(LOG_ERR,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] Database query failed: ".AWITPT::DB::DBLayer::error());
Robert Anderson's avatar
Robert Anderson committed
160 161 162 163 164 165 166 167 168 169
		return;
	}

	return MOD_RES_ACK;
}



1;
# vim: ts=4