mod_feature_update_user_stats_sql.pm 4.73 KB
Newer Older
1
# Support for updating of user stats
2 3
# Copyright (C) 2007-2016, AllWorldIT
#
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
#
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
#
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;
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()
79
		WHERE
80
			Username = %{user.Username}
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");

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'};
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'}."'");
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());
160 161 162 163 164 165 166 167 168 169
		return;
	}

	return MOD_RES_ACK;
}



1;
# vim: ts=4