use Encode;
use dksconfig qw($sitecfg);
use Text::Unidecode;
-
+use Data::Dumper;
sub new {
my $class = shift;
my $retdata = undef;
my $dbh = DBI->connect($sitecfg->{dsn},$sitecfg->{dbuser},$sitecfg->{dbpassword},{PrintError=>0,RaiseError=>0,AutoCommit=>1}) or return $retdata->{error} = "dbquery Connection Error!".$!;
$stat = encode("utf8", $stat);
- # open FILE,">>tmp/sql.log";
- # print FILE "$stat\n";
- # close FILE;
+ open FILE,">>tmp/sql.log";
+ print FILE "$stat\n";
+ close FILE;
my $sth = $dbh->prepare($stat) or return $retdata->{error} = "dbquery".$dbh->errstr. "- SQL: ".$stat;;
my $dbh = DBI->connect($sitecfg->{dsn},$sitecfg->{dbuser},$sitecfg->{dbpassword},{PrintError=>0,RaiseError=>0,AutoCommit=>1}) or return $retdata->{error} = "dbquery Connection Error!".$!;
# $stat = encode("utf8", $stat);
- # open FILE,">>sql.log";
- # print FILE "$stat\n";
- # close FILE;
+ open FILE,">>sql.log";
+ print FILE "$stat\n";
+ close FILE;
my $sth = $dbh->prepare($stat) or return $retdata->{error} = "dbquery: ".$stat;
$sth->execute() or return $retdata->{error} = "dbquery: ".$stat;
while(my $data = $sth->fetchrow_hashref())
my $retdata;
my $dbh = DBI->connect($sitecfg->{dsn},$sitecfg->{dbuser},$sitecfg->{dbpassword},{PrintError=>0,RaiseError=>0,AutoCommit=>1}) or return $retdata->{error} = "dbquery Connection Error!".$!;
# $stat = encode("utf8", $stat);
- # open FILE,">>tmp/sql.log";
- # print FILE "\n==\n$stat\n==\n";
- # close FILE;
+ open FILE,">>tmp/sql.log";
+ print FILE "\n==\n$stat\n==\n";
+ close FILE;
my $sth = $dbh->prepare($stat) or return $retdata->{error} = "dbquerysorted ".$dbh->errstr. "- SQL: ".$stat;;
my $retdata;
my $dbh = DBI->connect($sitecfg->{dsn},$sitecfg->{dbuser},$sitecfg->{dbpassword},{PrintError=>0,RaiseError=>0,AutoCommit=>1}) or return $retdata->{error} = "dbquery Connection Error!".$!;
# $stat = decode("UTF-8", $stat);
- # open FILE,">>tmp/sql.log";
- # print FILE "\n==\n$stat\n==\n";
- # close FILE;
+ open FILE,">>tmp/sql.log";
+ print FILE "\n==\n$stat\n==\n";
+ close FILE;
my $sth = $dbh->prepare($stat) or return $retdata->{error} = "dbexec ".$dbh->errstr. "- SQL: ".$stat;;
$retdata->{success} = $dbh->do($stat) or return $retdata->{error} = "dbexec ".$dbh->errstr. "- SQL: ".$stat;
$dbh->disconnect();
}
push(@ddl,"SELECT count(*) as cnt from ".$tb." WHERE ".join(" AND ",@sqlcond).";");
}
-
+ open FILE,">>tmp/sql.log";
+ print FILE "\n==\n".join("\n",@ddl)."\n==\n";
+ close FILE;
return @ddl;
}
sub getsession($){
my $self = shift;
my $sid = shift;
- my $sql ="select se.idsession,us.id,us.username,us.prename,us.surname,ug.usergroup from sessions se
+ my $sql ="select se.idsession,us.id,us.username,us.prename,us.surname,ug.usergroup,string_agg(distinct(aug.usergroup),',') as othergroups from sessions se
join users us on (us.id=se.id_user)
join usergroups ug on (us.id_usergroup=ug.id)
+left join useringroups uig on (us.id=uig.id_user)
+left join usergroups aug on (aug.id=uig.id_group)
left join appaccess ac on (us.id=ac.id_user)
where se.idsession= '".$self->{db}->securetext($sid)."'
and se.remote_addr= '".$ENV{REMOTE_ADDR}."'
-and se.user_agent='".$ENV{HTTP_USER_AGENT}."' and us.blocked is null;";
+and se.user_agent='".$ENV{HTTP_USER_AGENT}."' and us.blocked is null group by se.id,us.id,ug.id;";
my $res= $self->{db}->dbquerysorted($sql);
my $ret = undef;
if (keys(%{$res}) > 0){
$html->{result} = $res->{0};
}
}
+ elsif ($p->{fn} eq "generatevouchers"){
+ if ($sess->{othergroups} =~ /admin/){
+ my $sql = "INSERT INTO vouchers (voucher, id_price, used, percentdiscount, expiration) VALUES (substring(md5(random()::text),1,9), ".$p->{id_price}.", false, ".$p->{discount}.", date('".$p->{expiration}."'));";
+ foreach (my $i=0..$p->{num}){
+ $db->dbexec($sql);
+ }
+ $html->{result}->{p} = $p;
+ $html->{result}->{sql} = $sql;
+ $html->{result}->{gen} = "OK";
+ }else {
+ $html->{result}->{gen} = "NOT OK";
+ }
+
+ }
elsif ($p->{fn} eq "activateapp"){
$html->{result} = undef;
}
if (($idexists == 0) && ($type eq "upd")){
my @sqlcnt = $db->create_cnt_statement($p);
- my $rnums = 0;
-
+ my $rnums = ();
+ open FILE,">>tmp/process.log";
+ print FILE "\n==\n".Dumper(@sqlcnt)."\n==\n";
+ close FILE;
foreach my $s (@sqlcnt){
use lib ('api/lib');
use File::Basename qw/dirname basename/;
use Template;
-# use Template::Constants qw( :debug );
+use Template::Constants qw( :debug );
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use CGI::Cookie;
print $cgi->header(-type=>$ctype, -charset=>"utf-8",-cookie => $cookie);
# print dirname($ENV{"SCRIPT_FILENAME"});
-my $template = Template->new({INCLUDE_PATH => [dirname($ENV{"SCRIPT_FILENAME"}).'/tmpl']});
-#, DEBUG => DEBUG_ALL}
+my $template = Template->new({INCLUDE_PATH => [dirname($ENV{"SCRIPT_FILENAME"}).'/tmpl'], DEBUG => DEBUG_PLUGINS});
+#}
my @lv = split(/\//,$vars->{filepath});
my $absnum = scalar(@lv)-1;
# }
# print Dumper($vars);
+if ($ENV{"HTTP_HOST"} eq "localhost"){
print "/*";
+;
# # print Dumper($p);
print Dumper($vars);
# # print Dumper($sess);
print "*/";
+}
async:true
});
}
-}
\ No newline at end of file
+}
+
+$( document ).ready(function() {
+ var body = $('body');
+ var contentWrapper = $('.content-wrapper');
+ var scroller = $('.container-scroller');
+ // var footer = $('.footer');
+ var sidebar = $('.sidebar');
+
+ //Add active class to nav-link based on url dynamically
+ //Active class can be hard coded directly in html file also as required
+
+ function addActiveClass(element) {
+ if (current === "") {
+ //for root url
+ if (element.attr('href').indexOf("index.html") !== -1) {
+ element.parents('.nav-item').last().addClass('active');
+ if (element.parents('.sub-menu').length) {
+ element.closest('.collapse').addClass('show');
+ element.addClass('active');
+ }
+ }
+ } else {
+ //for other url
+ if (element.attr('href').indexOf(current) !== -1) {
+ element.parents('.nav-item').last().addClass('active');
+ if (element.parents('.sub-menu').length) {
+ element.closest('.collapse').addClass('show');
+ element.addClass('active');
+ }
+ if (element.parents('.submenu-item').length) {
+ element.addClass('active');
+ }
+ }
+ }
+ }
+
+ var current = location.pathname.split("/").slice(-1)[0].replace(/^\/|\/$/g, '');
+ $('.nav li a', sidebar).each(function() {
+ var $this = $(this);
+ addActiveClass($this);
+ })
+
+ //Close other submenu in sidebar on opening any
+
+ // sidebar.on('show.bs.collapse', '.collapse', function() {
+ // sidebar.find('.collapse.show').collapse('hide');
+ // });
+
+
+ //Change sidebar
+
+ // $('[data-toggle="minimize"]').on("click", function() {
+ // body.toggleClass('sidebar-icon-only');
+ // });
+
+ //checkbox and radios
+ // $(".form-check label,.form-radio label").append('<i class="input-helper"></i>');
+});
+
+(function($) {
+ 'use strict';
+ $(function() {
+ $('[data-toggle="offcanvas"]').on("click", function() {
+ $('.sidebar-offcanvas').toggleClass('active')
+ });
+ });
+})(jQuery);
\ No newline at end of file
field[$("#" +objid).attr('name')] = $("#" + objid).html();
} else if ($("#" + objid)[0].tagName == "SELECT"){
//console.log("is a select field");
- console.log($("#" + objid).selectpicker());
+ //console.log($("#" + objid).selectpicker());
// if ($("#" + objid)[0].dataset.select2Id){
// // console.log("is a select2 field!\n");
// console.log($("#" +objid).attr('name') + "-> " + $("#" +objid).val() );
// }
// else {
field[$("#" +objid).attr('name')] = $("#" + objid).val();
- console.log(field[$("#" +objid).attr('name')]);
+ //console.log(field[$("#" +objid).attr('name')]);
// }
// }if ($("#" + objid)[0].select2Id){
+++ /dev/null
-// (function($) {
-// 'use strict';
-// //Open submenu on hover in compact sidebar mode and horizontal menu mode
-// $(document).on('mouseenter mouseleave', '.sidebar .nav-item', function(ev) {
-// var body = $('body');
-// var sidebarIconOnly = body.hasClass("sidebar-icon-only");
-// var sidebarFixed = body.hasClass("sidebar-fixed");
-// if (!('ontouchstart' in document.documentElement)) {
-// if (sidebarIconOnly) {
-// if (sidebarFixed) {
-// if (ev.type === 'mouseenter') {
-// body.removeClass('sidebar-icon-only');
-// }
-// } else {
-// var $menuItem = $(this);
-// if (ev.type === 'mouseenter') {
-// $menuItem.addClass('hover-open')
-// } else {
-// $menuItem.removeClass('hover-open')
-// }
-// }
-// }
-// }
-// });
-// })(jQuery);
\ No newline at end of file
+++ /dev/null
-(function($) {
- 'use strict';
- $(function() {
- $('[data-toggle="offcanvas"]').on("click", function() {
- $('.sidebar-offcanvas').toggleClass('active')
- });
- });
-})(jQuery);
\ No newline at end of file
+++ /dev/null
-// (function($) {
-// 'use strict';
-// $(function() {
-// $('.file-upload-browse').on('click', function() {
-// var file = $(this).parent().parent().parent().find('.file-upload-default');
-// file.trigger('click');
-// });
-// $('.file-upload-default').on('change', function() {
-// $(this).parent().find('.form-control').val($(this).val().replace(/C:\\fakepath\\/i, ''));
-// });
-// });
-// })(jQuery);
-
-function handleFileSelect(evt) {
- var files = evt.target.files;
- var utype = "";
- if ($("form").attr('id') == "dksrdv_catalog"){
- $("form").prepend('<input type="hidden" id="photo" name="photo" value=""/>');
- for (var i = 0, f; f = files[i]; i++) {
- if (!f.type.match('image.*')) {
- continue;
- }
- var reader = new FileReader();
- reader.onload = (function(theFile) {
- return function(e) {
- $("#preview").attr("src",e.target.result);
- $("#"+utype+"photo").val(e.target.result);
- };
- })(f);
- reader.readAsDataURL(f);
- }
-}
-}
-
-function removephoto(utype){
- $("#preview").attr("src",defaultphoto);
- if (!$("#"+utype+"photo")){
- $("form").prepend('<input type="hidden" id="'+utype+'photo" name="'+utype+'photo" value=""/>');
- }
-}
\ No newline at end of file
+++ /dev/null
-$( document ).ready(function() {
- var body = $('body');
- var contentWrapper = $('.content-wrapper');
- var scroller = $('.container-scroller');
- // var footer = $('.footer');
- var sidebar = $('.sidebar');
-
- //Add active class to nav-link based on url dynamically
- //Active class can be hard coded directly in html file also as required
-
- function addActiveClass(element) {
- if (current === "") {
- //for root url
- if (element.attr('href').indexOf("index.html") !== -1) {
- element.parents('.nav-item').last().addClass('active');
- if (element.parents('.sub-menu').length) {
- element.closest('.collapse').addClass('show');
- element.addClass('active');
- }
- }
- } else {
- //for other url
- if (element.attr('href').indexOf(current) !== -1) {
- element.parents('.nav-item').last().addClass('active');
- if (element.parents('.sub-menu').length) {
- element.closest('.collapse').addClass('show');
- element.addClass('active');
- }
- if (element.parents('.submenu-item').length) {
- element.addClass('active');
- }
- }
- }
- }
-
- var current = location.pathname.split("/").slice(-1)[0].replace(/^\/|\/$/g, '');
- $('.nav li a', sidebar).each(function() {
- var $this = $(this);
- addActiveClass($this);
- })
-
- //Close other submenu in sidebar on opening any
-
- // sidebar.on('show.bs.collapse', '.collapse', function() {
- // sidebar.find('.collapse.show').collapse('hide');
- // });
-
-
- //Change sidebar
-
- // $('[data-toggle="minimize"]').on("click", function() {
- // body.toggleClass('sidebar-icon-only');
- // });
-
- //checkbox and radios
- // $(".form-check label,.form-radio label").append('<i class="input-helper"></i>');
-});
<script src="vendors/jquery/jquery.min.js"></script>
<script src="vendors/bootstrap/js/bootstrap.bundle.min.js"></script>
-<script src="js/off-canvas.js"></script>
-<script src="js/template.js"></script>
<script src="js/backoffice.js"></script>
\ No newline at end of file
[% END %]
</ul>
-[% admcnt = dksdb.prepare("select count(*) as cnt from useringroups where id_user=?;") %]
+[% admcnt = dksdb.prepare("select count(*) as cnt from useringroups uig join usergroups ug on (uig.id_group=ug.id) where uig.id_user=? and ug.usergroup='admin'") %]
[% isadmin = admcnt.execute(session.id) %]
[% IF isadmin > 0 %]
<!-- ADMIN APPS -->
var apiurl = "[% baseurl %]/api/";
function process_data(data,callback){
- // console.log("process data");
- // console.log(JSON.stringify(data));
-
+ console.log("process data");
+ console.log(JSON.stringify(data));
+ console.log(apiurl);
strdata = "";
for (var i in data){
if (typeof(data[i]) == "object"){
}
}
+ console.log(strdata);
+ console.log(callback);
$.ajax({
encoding:"UTF-8",
url: apiurl + 'process.cgi' ,
method: "POST",
data: strdata,
success: function (data){
- // console.log("returned data");
- // console.log(data);
+ console.log("returned data");
+ console.log(data);
if (data && data.result){
callback(data.result);
} else {
function initpage(){
-}
\ No newline at end of file
+}
+$("input.fieldsave").on('blur',function(event){
+ console.log(event);
+ savefield(event.currentTarget.id);
+});
\ No newline at end of file
[% END %]
</select>
</div>
+ <div class="form-group">
+ <label for="blockerd">Block User</label>
+ <input type="checkbox" class="form-control fieldsave" id="blocked" style="width: 50px;" name="users_blocked" value="1" [% IF usr.blocked %] checked [% END %]>
+ </div>
</form>
[% END %]
<h2>Applications</h2>
-[% appdata = dksdb.prepare("select ap.name,ac.id_user,ac.id_app,ac.publicenabled,ac.expiration from appaccess ac join apps ap on (ac.id_app=ap.id) where ac.id_user=?;") %]
+[% appdata = dksdb.prepare("select ac.id,ap.name,ac.id_user,ac.id_app,ac.publicenabled,ac.expiration from appaccess ac join apps ap on (ac.id_app=ap.id) where ac.id_user=?;") %]
<table class="table table-bordered table-hover table-striped" style="width: 100%; margin: 0px;" id="tbl_applications">
<thead class="thead-dark">
<tr>
[% FOREACH uap = appdata.execute(params.id) %]
<tr>
<td>[% uap.name %]</td>
- <td>[% uap.publicenabled %]</td>
- <td>[% uap.expiration %]</td>
+ <td><input type="checkbox" class="form-control fieldsave" value="1" data-ident_appaccess_id="[% uap.id %]" id="publicenabled[% uap.id %]" name="appaccess_publicenabled" [% IF uap.publicenabled %] checked [% END %]></td>
+ <td><input type="date" class="form-control fieldsave" data-ident_appaccess_id="[% uap.id %]" id="expiration[% uap.id %]" name="appaccess_expiration" value="[% uap.expiration %]" /></td>
</tr>
[% END %]
</tbody>
-
-<h1>Utilisateurs</h1>
-
- <table class="table table-bordered table-hover table-striped" style="width: 100%; margin: 0px;" id="tbl_users">
+<table class="table table-bordered table-hover table-striped" style="width: 100%; margin: 0px;" id="tbl_users">
<thead class="thead-dark">
<tr>
<th>Username</th>
<td>[% aus.username %]</td>
<td>[% aus.prename %]</td>
<td>[% aus.surname %]</td>
- <td>[% aus.blocked %]</td>
+ <td>[% IF aus.blocked %] <i class="mdi mdi-check-bold"></i> [% END %]</td>
<td>[% aus.defaultgroup %]</td>
<td>[% aus.apps %]</td>
<td>[% aus.othergroups %]</td>
--- /dev/null
+function initpage(){
+
+}
+
+[% prices = dksdb.prepare("select id,duration,price,package from prices where id_app=? and evaluation = false;") %]
+
+ var appdata = {
+ [% FOREACH modules = dksdb.query("select id,\"name\" from apps where activated=true;") %]
+ [% modules.id %]:{"name":"[% modules.name %]","packages":{
+ [% FOREACH price = prices.execute(modules.id) %]
+ [% price.id %]:{"id":[% price.id %],"package":"[% price.package %]","price":[% price.price %],"duration":[% price.duration %]},
+ [% END %]
+ }},
+ [% END %]
+};
+
+function setpackages(){
+ var idapp= document.getElementById("id_app").value;
+ console.log(appdata);
+ var pkg = document.getElementById("id_package");
+ pkg.innerHTML= "";
+ var pkgdata ="";
+ for (var i in appdata[idapp]['packages']){
+ pkgdata += '<option value="'+appdata[idapp]['packages'][i]['id']+'">'+ appdata[idapp]['packages'][i]['package']+ ' (' + appdata[idapp]['packages'][i]['price'] +'€' + '-' + appdata[idapp]['packages'][i]['duration'] +' mois'+ ')' +'</option>' ;
+ }
+ pkg.innerHTML = pkgdata;
+}
+
+function generate_vouchers(){
+
+ var discpercent = document.getElementById("discount").value/100;
+ process_data(
+ {fn:"generatevouchers",
+ "id_price":document.getElementById("id_package").value,
+ "expiration":document.getElementById("expiration").value,
+ "discount":discpercent,
+ "num":document.getElementById("numvouchers").value,
+
+ },reload_vouchers);
+
+}
+
+function reload_vouchers(data){
+ console.log("Voucher Return");
+ console.log(data);
+ parent.backoffice.loadpage('module/vouchers/index.html','Vouchers');
+ return false;
+}
--- /dev/null
+<form id="frm_voucher">
+ <div class="form-group">
+ <label for="app">Application</label>
+ <select class="form-control" title="rien selectionné" id="id_app" onchange="setpackages();">
+ <option value="none"></option>
+ [% FOREACH ap=dksdb.query("select id,name from apps where activated=true;") %]
+ <option value="[% ap.id %]">[% ap.name %]</option>
+ [% END %]
+ </select>
+ </div>
+ <div class="form-group">
+ <label for="app">Package</label>
+ <select class="form-control" title="rien selectionné" id="id_package" >
+
+ </select>
+ </div>
+ <div class="form-group">
+ <label for="discount">Discount (%)</label>
+ <input type="number" min="1" max="100" class="form-control" id="discount" required value="">
+ </div>
+ <div class="form-group">
+ <label for="numvouchers">Number of Vouchers to generate</label>
+ <input type="number" class="form-control" id="numvouchers" required value="">
+ </div>
+ <div class="form-group">
+ <label for="expiration">Expiration</label>
+ <input type="date" class="form-control" id="expiration" required value="">
+ </div>
+ <div class="form-group">
+ <button class="btn btn-primary" onclick="generate_vouchers();return false;">Generate Vouchers</button>
+ </div>
+</form>
+function initpage(){
+
+}
\ No newline at end of file
+
+<table class="table table-bordered table-hover table-striped" style="width: 100%; margin: 0px;" id="tbl_vouchers">
+ <thead class="thead-dark">
+ <tr>
+ <th>Voucher</th>
+ <th>Expiration</th>
+ <th>Used</th>
+ <th>Application</th>
+ <th>Package</th>
+ <th>Discount</th>
+ <th>Package Price</th>
+ <th>duration (month)</th>
+ <th><button class="btn btn-info" onclick="parent.backoffice.loadpage('module/vouchers/form_voucher.html','Add Vouchers');"><i class="mdi mdi-plus"></i></button></th>
+ </tr>
+ </thead>
+
+ <tbody>
+ [% FOREACH vou = dksdb.query("SELECT vo.id,vo.expiration ,vo.voucher, vo.used, vo.percentdiscount * 100 as discount, vo.expiration,pr.duration,pr.package,pr.price,ap.name as appname,pr.duration
+FROM vouchers vo
+join prices pr on (pr.id=vo.id_price)
+join apps ap on (pr.id_app=ap.id)") %]
+ <tr>
+ <td>[% vou.voucher %]</td>
+ <td>[% vou.expiration %]</td>
+ <td>[% IF vou.used == "1" %] <i class="mdi mdi-check-bold"></i> [% END %]</td>
+ <td>[% vou.appname %]</td>
+ <td>[% vou.package %]</td>
+ <td>[% vou.discount %]%</td>
+ <td>[% vou.price %]€</td>
+ <td>[% vou.duration %]</td>
+ <td>
+ <button class="btn btn-danger" onclick="delete_voucher('[% vou.id %]');"><i class="mdi mdi-trash-can"></i></button>
+ </td>
+ </tr>
+ [% END %]
+ </tbody>
+ </table>
+<script src="[% abspath %]vendors/js-form-validator/js-form-validator.js"></script>
+<script src="[% abspath %]vendors/bootstrap-select/js/bootstrap-select.min.js"></script>
+<script src="[% pagename %].js"></script>
\ No newline at end of file
<button type="submit" name="btnregister" class="btn btn-block btn-primary btn-lg font-weight-medium auth-form-btn">Créer un compte</button>
</div>
<div class="text-center mt-4 font-weight-light">
- vous avez déjà une compte? <a href="[% abspath %]login.html" class="text-primary">se Connecter</a>
+ vous avez déjà un compte? <a href="[% abspath %]login.html" class="text-primary">se Connecter</a>
</div>
</form>
[% ELSIF pagename == 'forgotpassword' %]