head 1.13;
access;
symbols
AS_AFTER_RESTRUCTURING:1.13;
locks; strict;
comment @# @;
1.13
date 2002.10.10.15.26.43; author thl; state Exp;
branches;
next 1.12;
1.12
date 2002.10.10.15.10.18; author thl; state Exp;
branches;
next 1.11;
1.11
date 2002.10.10.15.08.54; author thl; state Exp;
branches;
next 1.10;
1.10
date 2002.10.10.14.05.03; author thl; state Exp;
branches;
next 1.9;
1.9
date 2002.10.10.11.49.31; author thl; state Exp;
branches;
next 1.8;
1.8
date 2002.10.10.11.42.27; author thl; state Exp;
branches;
next 1.7;
1.7
date 2002.10.10.08.32.22; author thl; state Exp;
branches;
next 1.6;
1.6
date 2002.10.10.07.23.00; author thl; state Exp;
branches;
next 1.5;
1.5
date 2002.10.10.07.12.46; author thl; state Exp;
branches;
next 1.4;
1.4
date 2002.10.10.06.59.26; author thl; state Exp;
branches;
next 1.3;
1.3
date 2002.10.10.06.57.12; author thl; state Exp;
branches;
next 1.2;
1.2
date 2002.10.09.14.15.44; author thl; state Exp;
branches;
next 1.1;
1.1
date 2002.10.09.14.12.11; author thl; state Exp;
branches;
next ;
desc
@@
1.13
log
@relation overriding through distance works as designed, at least for some arbitrary test cases
@
text
@#!/bin/sh -- # -*- perl -*-
eval 'exec perl -S $0 ${1+"$@@"}'
if $running_under_some_shell;
##
## AS -- Accounting System
## Copyright (c) 2002 Cable & Wireless Deutschland
## Copyright (c) 2002 Ralf S. Engelschall
##
## This file is part of AS, an accounting system which can be
## found at http://as.is.eu.cw.com/
##
## 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.0 of the License, or (at your option) any later version.
##
## 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.
##
## 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
## USA, or contact The OSSP Project .
##
## orm.pl: object relation model
##
require 5.006;
use strict;
use Getopt::Long;
use IO;
# default configuration
my $cfg = {
"verbose" => 0
};
# command line parsing
Getopt::Long::Configure("bundling");
my $result = GetOptions(
'v|verbose' => \$cfg->{verbose},
) || die "option parsing failed";
# RS_i ns b R nt RT_i
# A_i ----->* S =====> T *<---- Z_i
#
# A_i equivalence object(s)
# RS_i source equivalence relationship(s)
# ns equivalence maximum distance from source S
# S source object
# b relationship include/exclude
# R relationship
# T target object
# RT_i target scope relationship(s)
# nt scope maximum distance from target T
# Z_i scope object(s)
# class / uuid[] mapping
my $CU = {
"user" => [ "u1", "u2", "u3", "u4" ],
"group" => [ "g1", "g2" ],
"account" => [ "a1", "a2" ],
"role" => [ "r1" ],
"container" => [ "c1", "c2", "c3" ]
};
# uuid / class mapping
my $UC = {};
foreach my $c (keys(%{$CU})) {
foreach my $u (@@{$CU->{$c}}) {
$UC->{$u} = $c;
}
};
sub getclass
{
my ($UC, $u) = @@_;
my $c = $UC->{$u};
return $c;
}
# defined class relations
# @@DR := { } = { ... }
# S,R,T primary key
# S,T possibly wildcards
my $DR = [
# direct user and recursive search for proxy
# has read and write access
# account and every object having this account as_parent
{
"RS_i" => [ "proxy" ],
"S" => [ "user" ],
"R" => [ "read", "write" ],
"T" => [ "account" ],
"RT_i" => [ "parent" ]
},
# group and every object that is_member_of
# has _read/write_access_to an
# account and every object having this account as_parent
{
"RS_i" => [ "member" ],
"S" => [ "group" ],
"R" => [ "read", "write" ],
"T" => [ "account" ],
"RT_i" => [ "parent" ]
},
# group and every object that is_member_of
# has _read/write_access_to an
# account and every object having this account as_parent
{
"RS_i" => [ "occupant", "proxy" ],
"S" => [ "role" ],
"R" => [ "read", "write", "manage" ],
"T" => [ "account" ],
"RT_i" => [ "parent" ]
},
# group and every object that is_member_of
# has _read/write_access_to an
# account and every object having this account as_parent
{
"RS_i" => [ "occupant" ],
"S" => [ "role" ],
"R" => [ "manage" ],
"T" => [ "*" ],
"RT_i" => [ "parent" ]
},
# user
# is_proxy_of
# user
{
"RS_i" => [ "proxy" ],
"S" => [ "user" ],
"R" => [ "proxy" ],
"T" => [ "user" ],
"RT_i" => [ ]
},
# user
# is_occupant_of
# role
{
"RS_i" => [ ],
"S" => [ "user" ],
"R" => [ "occupant" ],
"T" => [ "role" ],
"RT_i" => [ ]
},
# account
# has as_parent an
# account
{
"RS_i" => [ "account" ],
"S" => [ "account" ],
"R" => [ "*" ],
"T" => [ "account" ],
"RT_i" => [ ]
},
# user and group
# can be memberof
# group
{
"RS_i" => [ ],
"S" => [ "user", "group" ],
"R" => [ "member" ],
"T" => [ "group" ],
"RT_i" => [ ]
},
# user and every object that is_proxy_of
# can_manage
# anything and every object having this thing as parent
{
"RS_i" => [ "proxy" ],
"S" => [ "user" ],
"R" => [ "manage" ],
"T" => [ "*" ],
"RT_i" => [ "parent" ]
}
];
dumpdefinedrelations($DR);
sub dumpdefinedrelations
{
my ($DR) = @@_;
print "\ndumping defined relations\n";
dumpdefinedrelation("RS_i", "S" , "R", "T" , "RT_i");
dumpdefinedrelation("-"x80, "-"x80, "-"x80, "-"x80, "-"x80);
foreach my $i (@@{$DR}) {
foreach my $rsi (defined @@{$i->{"RS_i"}} ? @@{$i->{"RS_i"}} : " - ") {
foreach my $s (@@{$i->{"S"}}) {
foreach my $r (@@{$i->{"R"}}) {
foreach my $t (@@{$i->{"T"}}) {
foreach my $rti (defined @@{$i->{"RT_i"}} ? @@{$i->{"RT_i"}} : " - ") {
dumpdefinedrelation($rsi, $s, $r, $t, $rti);
}
}
}
}
}
}
}
sub dumpdefinedrelation
{
my ($RS_i, $S, $R, $T, $RT_i) = @@_;
print " " . substr $RS_i . " "x80, 0, 15;
print " " . substr $S . " "x80, 0, 15;
print " " . substr $R . " "x80, 0, 20;
print " " . substr $T . " "x80, 0, 15;
print " " . substr $RT_i . " "x80, 0, 15;
print " \n";
}
# set instance relations
# @@SR := { } = { ... }
# SR = n
my $SR = [
# trustees
{ "S" => "g1", "ns" => "oo", "b" => "+", "R" => "read", "nt" => "oo", "T" => "a1" },
{ "S" => "u1", "ns" => "oo", "b" => "+", "R" => "write", "nt" => "oo", "T" => "a2" },
{ "S" => "r1", "ns" => "oo", "b" => "+", "R" => "manage", "nt" => "oo", "T" => "a1" },
{ "S" => "u4", "ns" => "oo", "b" => "-", "R" => "read", "nt" => "oo", "T" => "a1" },
{ "S" => "u4", "ns" => "oo", "b" => "+", "R" => "read", "nt" => "oo", "T" => "a2" },
# account structure
{ "S" => "a1", "ns" => "oo", "b" => "+", "R" => "parent", "nt" => "oo", "T" => "a2" },
# group membership
{ "S" => "u1", "ns" => "oo", "b" => "+", "R" => "member", "nt" => "oo", "T" => "g1" },
{ "S" => "g2", "ns" => "oo", "b" => "+", "R" => "member", "nt" => "oo", "T" => "g1" },
{ "S" => "u2", "ns" => "oo", "b" => "+", "R" => "member", "nt" => "oo", "T" => "g2" },
{ "S" => "u4", "ns" => "oo", "b" => "+", "R" => "member", "nt" => "oo", "T" => "g2" },
# proxies
{ "S" => "u2", "ns" => "oo", "b" => "+", "R" => "proxy", "nt" => "oo", "T" => "u1" },
{ "S" => "u3", "ns" => "oo", "b" => "+", "R" => "proxy", "nt" => "oo", "T" => "u2" }
];
dumpsetrelations($SR);
sub dumpsetrelations
{
my ($SR) = @@_;
print "\ndumping set relations\n";
dumpsetrelation("S" , "ns" , "b" , "R" , "nt" , "T" );
dumpsetrelation("-"x80, "-"x80, "-"x80, "-"x80, "-"x80, "-"x80);
foreach my $i (@@{$SR}) {
dumpsetrelation($i->{S}, $i->{ns}, $i->{b}, $i->{R}, $i->{nt}, $i->{T});
}
}
sub dumpsetrelation
{
my ($S, $ns,$b, $R, $nt, $T) = @@_;
print " " . substr $S . " "x80, 0, 15;
print " " . substr $ns . " "x80, 0, 2;
print " " . substr $b . " "x80, 0, 1;
print " " . substr $R . " "x80, 0, 20;
print " " . substr $nt . " "x80, 0, 2;
print " " . substr $T . " "x80, 0, 15;
print " \n";
}
# FUNCTION querysetrelations($SR, $S, $R, $T, @@Q);
# INPUT
# function takes $SR (set relations),
# a $S (source), $R (relation), $T (target) triple and
# an array listing the desired result fields as input.
# Any of $S, $R and $T may be wildcards.
# OUTPUT
# It returns an array of arrays holding the desired fields.
# EXAMPLE
# querysetrelations($SR, "*", "*", "g1", ["S", "R"]); exit;
sub querysetrelations
{
my ($SR, $S, $R, $T, $Q) = @@_;
my @@O = ();
#printf "querysetrelations(..., %s, %s, %s, ...)\n", rightstr(" ", $S, 3), rightstr(" ", $R, 10), rightstr(" ", $T, 3) if($cfg->{verbose} == 1);
foreach my $sr (@@{$SR}) {
if ( ($S eq "*" || $S eq $sr->{S})
&& ($R eq "*" || $R eq $sr->{R})
&& ($T eq "*" || $T eq $sr->{T})
) {
my @@o = ();
foreach my $q (@@{$Q}) {
push @@o, $sr->{$q};
}
push @@O, \@@o;
}
}
if($cfg->{verbose} == 1) {
foreach my $o (@@O) {
print "querysetrelations=";
foreach my $i (@@{$o}) {
print "***$i*** ";
}
print "\n";
}
}
return @@O;
}
# FUNCTION getimmediateequiv($UC, $DR, $S, $R, $T);
# INPUT
# function takes $UC (uuid/class lookup), $DR (defined relations) and
# a $S (source), $R (relation), $T (target) triple as input.
# OUTPUT
# It returns an array of all immediate (non recursive) equivalences
# FIXME
# strategy issue: when hunting down $DR for relationships multiple matches
# could be found. Three options to handle them came into my mind
# 1.) the closest match is a default only and the most general match is taken
# 2.) the closest match is the most individual and is taken over more general matches
# 3.) the summary of all matches are taken
# The first two will require a definition of what a "closest match" is.
# Currently, only the third is implemented
#
sub getimmediateextensions
{
my ($UC, $DR, $S, $R, $T) = @@_;
#printf "getimmediateextensions(...) object relation %s %s %s ", rightstr(" ", $S, 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3);
$S = getclass($UC, $S);
$T = getclass($UC, $T);
#printf "becomes class relation %s %s %s:", rightstr(" ", $S, 7), rightstr(" ", $R, 6), rightstr(" ", $T, 7);
my $rsi = {};
my $rti = {};
foreach my $dr (@@{$DR}) {
foreach my $s (@@{$dr->{"S"}}) {
foreach my $r (@@{$dr->{"R"}}) {
foreach my $t (@@{$dr->{"T"}}) {
if ( ($s eq "*" || $s eq $S)
&& ($r eq "*" || $r eq $R)
&& ($t eq "*" || $t eq $T)
) {
foreach my $i (@@{$dr->{"RS_i"}}) {
$rsi->{$i} = 1;
};
foreach my $i (@@{$dr->{"RT_i"}}) {
$rti->{$i} = 1;
};
}
}
}
}
}
my @@RSI = ();
foreach my $i (keys %{$rsi}) {
push @@RSI, $i;
#print " $i";
}
#print "; ";
my @@RTI = ();
foreach my $i (keys %{$rti}) {
push @@RTI, $i;
#print " $i";
}
#print "\n";
return \@@RSI, \@@RTI;
}
sub rightstr
{
my ($f, $s, $l) = @@_;
my $r = $f x $l . $s;
$r = substr($r, length($r) - $l, $l);
return $r;
}
# configured to effective relationship algorithm
#function drcr2er(@@DR, @@SR): @@ER { // O(n^3)
my $ER = geteffectiverelations($UC, $DR, $SR);
dumpeffectiverelations($ER);
sub dumpeffectiverelations
{
my ($ER) = @@_;
print "\ndumping effective relations\n";
dumpeffectiverelation("S" , "ns" , "b" , "R" , "nt" , "T" );
dumpeffectiverelation("-"x80, "-"x80, "-"x80, "-"x80, "-"x80, "-"x80);
foreach my $i (sort keys %{$ER}) {
my $x = $ER->{$i};
dumpeffectiverelation($x->{S}, $x->{ns}, $x->{b}, $x->{R}, $x->{nt}, $x->{T});
}
}
sub dumpeffectiverelation
{
my ($S, $ns, $b, $R, $nt, $T,) = @@_;
print " " . substr $S . " "x80, 0, 15;
print " " . substr $ns . " "x80, 0, 2;
print " " . substr $b . " "x80, 0, 1;
print " " . substr $R . " "x80, 0, 20;
print " " . substr $nt . " "x80, 0, 2;
print " " . substr $T . " "x80, 0, 15;
print " \n";
}
# effective relationships (calculated result)
# @@ER := { } = 0
sub geteffectiverelations
{
my ($UC, $DR, $SR) = @@_;
my $ER = {};
foreach my $sr (@@{$SR}) {
if($cfg->{verbose} == 1) {
print "geteffectiverelations processing set relationship";
dumpsetrelation($sr->{"S"}, $sr->{"ns"}, $sr->{"b"}, $sr->{"R"}, $sr->{"nt"}, $sr->{"T"});
}
# equivalence
my $EQR = {};
addequivrelation($EQR, $sr->{"S"}, 0);
resolveequivrelations($EQR, $UC, $DR, $SR, $sr->{"S"}, $sr->{"ns"}, $sr->{"b"}, $sr->{"R"}, $sr->{"nt"}, $sr->{"T"}, 1);
if($cfg->{verbose} == 1) {
foreach my $eqr (keys %{$EQR}) {
print "geteffectiverelations eqr=$eqr $EQR->{$eqr}\n";
}
}
# relation
if($cfg->{verbose} == 1) {
print "geteffectiverelations $sr->{b}, $sr->{R}\n";
}
# scope
my $SCR = {};
addscoperelation($SCR, $sr->{"T"}, 0);
resolvescoperelations($SCR, $UC, $DR, $SR, $sr->{"S"}, $sr->{"ns"}, $sr->{"b"}, $sr->{"R"}, $sr->{"nt"}, $sr->{"T"}, 1);
if($cfg->{verbose} == 1) {
foreach my $scr (keys %{$SCR}) {
print "geteffectiverelations scr=$scr $SCR->{$scr}\n";
}
}
# effective
foreach my $eqr (keys %{$EQR}) {
foreach my $scr (keys %{$SCR}) {
print "geteffectiverelations $eqr, $EQR->{$eqr}, $sr->{b}, $sr->{R}, $SCR->{$scr}, $scr\n" if($cfg->{verbose} == 1);
addeffectiverelation($ER, $eqr, $EQR->{$eqr}, $sr->{"b"}, $sr->{"R"}, $SCR->{$scr}, $scr);
}
}
}
return $ER;
}
sub resolveequivrelations
{
my ($EQR, $UC, $DR, $SR, $S, $ns, $b, $R, $nt, $T, $d) = @@_;
print "resolveequivrelations(..., $S, $ns, $b, $R, $nt, $T, $d)\n" if($cfg->{verbose} == 1);
if (($ns ne "oo") && ($ns < $d)) {
print "resolveequivrelations reached or exceeded max nesting $ns > $d\n" if($cfg->{verbose} == 1);
return;
}
my ($IE, $DUMMY) = getimmediateextensions($UC, $DR, $S, $R, $T);
print "resolveequivrelations looking at @@{$IE} -> $S\n" if($cfg->{verbose} == 1);
foreach my $ie (@@{$IE}) {
my @@QR = querysetrelations($SR, "*", $ie, $S, ["S"]);
foreach my $qr (@@QR) {
printf "resolveequivrelations query for %s -> %s found %s receives implicit relation %s to %s\n",
rightstr(" ", $ie, 6), rightstr(" ", $S, 3), rightstr(" ", $qr->[0], 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3) if($cfg->{verbose} == 1);
addequivrelation($EQR, $qr->[0], $d);
$d = $d + 1;
print "resolveequivrelations running a recursion >>>$d resolveequivrelations(..., $qr->[0], $R, $T, $d)\n" if($cfg->{verbose} == 1);
resolveequivrelations($EQR, $UC, $DR, $SR, $qr->[0], $ns, $b, $R, $nt, $T, $d);
print "resolveequivrelations back from recursion <<<$d resolveequivrelations(..., $qr->[0], $R, $T, $d)\n" if($cfg->{verbose} == 1);
$d = $d - 1;
}
}
}
sub resolvescoperelations
{
my ($SCR, $UC, $DR, $SR, $S, $ns, $b, $R, $nt, $T, $d) = @@_;
print "resolvescoperelations(..., $S, $ns, $b, $R, $nt, $T, $d)\n" if($cfg->{verbose} == 1);
if (($nt ne "oo") && ($nt < $d)) {
print "resolvescoperelations reached or exceeded max nesting $nt > $d\n" if($cfg->{verbose} == 1);
return;
}
my ($DUMMY, $IS) = getimmediateextensions($UC, $DR, $S, $R, $T);
print "resolvescoperelations looking at $T <- @@{$IS}\n" if($cfg->{verbose} == 1);
foreach my $is (@@{$IS}) {
my @@QR = querysetrelations($SR, $T, $is, "*", ["T"]);
foreach my $qr (@@QR) {
printf "resolvescoperelations query for %s <- %s found %s receives implicit relation %s to %s\n",
rightstr(" ", $is, 6), rightstr(" ", $T, 3), rightstr(" ", $qr->[0], 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3) if($cfg->{verbose} == 1);
addscoperelation($SCR, $qr->[0], $d);
$d = $d + 1;
print "resolvescoperelations running a recursion >>>$d resolvescoperelations(..., $qr->[0], $R, $T, $d)\n" if($cfg->{verbose} == 1);
resolvescoperelations($SCR, $UC, $DR, $SR, $S, $ns, $b, $R, $nt, $qr->[0], $d);
print "resolvescoperelations back from recursion <<<$d resolvescoperelations(..., $qr->[0], $R, $T, $d)\n" if($cfg->{verbose} == 1);
$d = $d - 1;
}
}
}
sub addequivrelation
{
my ($EQR, $S, $ns) = @@_;
$EQR->{"$S"} = $ns;
}
sub addscoperelation
{
my ($SCR, $T, $nt) = @@_;
$SCR->{"$T"} = $nt;
}
sub addeffectiverelation
{
my ($ER, $S, $ns, $b, $R, $nt, $T) = @@_;
my $key = $T . "*" . $R . "*" . $S;
my $er = $ER->{$key};
if (not defined($er)) {
$ER->{$key} = { "S" => $S, "ns" => $ns, "b" => $b, "R" => $R, "nt" => $nt, "T" => $T };
} else {
print "addeffectiverelation $er->{ns} <=> $ns && $er->{nt} <=> $nt\n" if($cfg->{verbose} == 1);
if (($er->{"ns"} == $ns) && ($er->{"nt"} == $nt)) { print "addeffectiverelation #1!\n" if($cfg->{verbose} == 1); } #, resolve b via R-specific conflict flag (prefer include or exlude) FIXME
if (($er->{"ns"} == $ns) && ($er->{"nt"} < $nt)) { print "addeffectiverelation #2!\n" if($cfg->{verbose} == 1); } # (nop)
if (($er->{"ns"} == $ns) && ($er->{"nt"} > $nt)) { print "addeffectiverelation #3!\n" if($cfg->{verbose} == 1); $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; } #
if (($er->{"ns"} < $ns) && ($er->{"nt"} == $nt)) { print "addeffectiverelation #4!\n" if($cfg->{verbose} == 1); } # (nop)
if (($er->{"ns"} < $ns) && ($er->{"nt"} < $nt)) { print "addeffectiverelation #5!\n" if($cfg->{verbose} == 1); } # (nop)
if (($er->{"ns"} < $ns) && ($er->{"nt"} > $nt)) { print "addeffectiverelation #6!\n" if($cfg->{verbose} == 1); $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; } #
if (($er->{"ns"} > $ns) && ($er->{"nt"} == $nt)) { print "addeffectiverelation #7!\n" if($cfg->{verbose} == 1); $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; } #
if (($er->{"ns"} > $ns) && ($er->{"nt"} < $nt)) { print "addeffectiverelation #8!\n" if($cfg->{verbose} == 1); $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; } #
if (($er->{"ns"} > $ns) && ($er->{"nt"} > $nt)) { print "addeffectiverelation #9!\n" if($cfg->{verbose} == 1); $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; } #
}
}
@
1.12
log
@flush; it sums up the relations but at least distance hehaves unexpected
@
text
@d222 2
a223 1
{ "S" => "u4", "ns" => "oo", "b" => "-", "R" => "read", "nt" => "oo", "T" => "a2" },
d413 1
a413 1
print "DEBUG: eqr=$eqr $EQR->{$eqr}\n";
d418 1
a418 1
print "DEBUG: $sr->{b}, $sr->{R}\n";
d426 1
a426 1
print "DEBUG: scr=$scr $SCR->{$scr}\n";
d432 2
a433 2
print "DEBUG: $eqr, $EQR->{$eqr}, $sr->{b}, $sr->{R}, $scr, $SCR->{$scr}\n" if($cfg->{verbose} == 1);
addeffectiverelation($ER, $eqr, $EQR->{$eqr}, $sr->{b}, $sr->{R}, $scr, $SCR->{$scr});
d513 10
a522 9
if (($er->{"ns"} = $ns) && ($er->{"nt"} = $nt)) { print "DEBUG: #1!\n"; } #, resolve b via R-specific conflict flag (prefer include or exlude) FIXME
if (($er->{"ns"} = $ns) && ($er->{"nt"} > $nt)) { print "DEBUG: #2!\n"; } # (nop)
if (($er->{"ns"} = $ns) && ($er->{"nt"} < $nt)) { $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; print "DEBUG: #3!\n"; } #
if (($er->{"ns"} > $ns) && ($er->{"nt"} = $nt)) { print "DEBUG: #4!\n"; } # (nop)
if (($er->{"ns"} > $ns) && ($er->{"nt"} > $nt)) { print "DEBUG: #5!\n"; } # (nop)
if (($er->{"ns"} > $ns) && ($er->{"nt"} < $nt)) { $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; print "DEBUG: #6!\n"; } #
if (($er->{"ns"} < $ns) && ($er->{"nt"} = $nt)) { $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; print "DEBUG: #7!\n"; } #
if (($er->{"ns"} < $ns) && ($er->{"nt"} > $nt)) { $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; print "DEBUG: #8!\n"; } #
if (($er->{"ns"} < $ns) && ($er->{"nt"} < $nt)) { $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; print "DEBUG: #9!\n"; } #
@
1.11
log
@flush; it sums up the relations but at least distance hehaves unexpected
@
text
@d513 8
a520 8
if (($er->{"ns"} = $ns) && ($er->{"nt"} < $nt)) { print "DEBUG: #2!\n"; } # (nop)
if (($er->{"ns"} = $ns) && ($er->{"nt"} > $nt)) { $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; print "DEBUG: #3!\n"; } #
if (($er->{"ns"} < $ns) && ($er->{"nt"} = $nt)) { print "DEBUG: #4!\n"; } # (nop)
if (($er->{"ns"} < $ns) && ($er->{"nt"} < $nt)) { print "DEBUG: #5!\n"; } # (nop)
if (($er->{"ns"} < $ns) && ($er->{"nt"} > $nt)) { $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; print "DEBUG: #6!\n"; } #
if (($er->{"ns"} > $ns) && ($er->{"nt"} = $nt)) { $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; print "DEBUG: #7!\n"; } #
if (($er->{"ns"} > $ns) && ($er->{"nt"} < $nt)) { $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; print "DEBUG: #8!\n"; } #
if (($er->{"ns"} > $ns) && ($er->{"nt"} > $nt)) { $er->{"ns"} = $ns; $er->{"S"} = $S; $er->{"b"} = $b; $er->{"T"} = $T; $er->{"nt"} = $nt; print "DEBUG: #9!\n"; } #
@
1.10
log
@calculate equivalence and scope independent of each other; track distance
@
text
@d222 1
d377 3
a379 2
foreach my $i (@@{$ER}) {
dumpeffectiverelation($i->{S}, $i->{ns}, $i->{b}, $i->{R}, $i->{nt}, $i->{T});
d400 1
d402 1
a402 1
if($cfg->{verbose} == 0) {
d406 1
d410 8
a417 2
foreach my $eqr (keys %{$EQR}) {
print "DEBUG: eqr=$eqr $EQR->{$eqr}\n";
d419 1
a419 1
print "DEBUG: $sr->{b}, $sr->{R}\n";
d423 11
a433 2
foreach my $scr (keys %{$SCR}) {
print "DEBUG: scr=$scr $SCR->{$scr}\n";
a435 2
my $ER = [];
#addeffectiverelation($ER, $qr->[0], $d, $b, $R, 0, $T);
d506 16
a521 1
push @@{$ER}, { "S" => $S, "ns" => $ns, "b" => $b, "R" => $R, "nt" => $nt, "T" => $T };
@
1.9
log
@cosmetics
@
text
@d219 1
a219 1
{ "S" => "g1", "ns" => 0 , "b" => "+", "R" => "read", "nt" => "oo", "T" => "a1" },
d223 1
a223 1
{ "S" => "a2", "ns" => "oo", "b" => "+", "R" => "parent", "nt" => "oo", "T" => "a1" },
d230 1
a230 1
{ "S" => "u2", "ns" => 0 , "b" => "+", "R" => "proxy", "nt" => "oo", "T" => "u1" },
d272 1
a272 1
#printf "querysetrelations(..., %s, %s, %s, ...)\n", rightstr(" ", $S, 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3) if($cfg->{verbose} == 1);
d290 1
a290 1
print "$i ";
d314 1
a314 1
sub getimmediateequiv
d318 1
a318 1
#printf "getimmediateequiv(...) object relation %s %s %s ", rightstr(" ", $S, 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3);
d323 1
d333 1
a333 1
$rsi->{$i} = 1 }
d335 4
d343 1
a343 1
my @@O = ();
d345 7
a351 1
push @@O, $i;
d355 1
a355 1
return @@O;
a396 1
my $ER = [];
d399 1
a399 1
if($cfg->{verbose} == 1) {
d403 13
a415 2
addeffectiverelation($ER, $sr->{"S"}, 0, $sr->{"b"}, $sr->{"R"}, 0, $sr->{"T"});
resolveequivrelations($ER, $UC, $DR, $SR, $sr->{"ns"}, $sr->{"S"}, $sr->{"b"}, $sr->{"R"}, $sr->{"T"}, 0);
d417 2
d424 1
a424 1
my ($ER, $UC, $DR, $SR, $ns, $S, $b, $R, $T, $d) = @@_;
d426 1
a426 1
#print "resolveequivrelations(..., $S, $ns, $b, $R, $T, $d)\n";
d428 1
a428 1
print "resolveequivrelations reached or exceeded max nesting $ns > $d\n";
d431 3
a433 3
my @@IE = getimmediateequiv($UC, $DR, $S, $R, $T);
#print "resolveequivrelations looking at @@IE of $S\n";
foreach my $ie (@@IE) {
d436 3
a438 2
printf "resolveequivrelations query for %s of %s found %s receives implicit relation %s to %s\n", rightstr(" ", $ie, 6), rightstr(" ", $S, 3), rightstr(" ", $qr->[0], 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3);
addeffectiverelation($ER, $qr->[0], $d, $b, $R, 0, $T);
d440 3
a442 3
#print "resolveequivrelations running a recursion >>>$d resolveequivrelations(..., $qr->[0], $R, $T, $d)\n";
resolveequivrelations($ER, $UC, $DR, $SR, $ns, $qr->[0], $b, $R, $T, $d);
#print "resolveequivrelations back from recursion <<<$d resolveequivrelations(..., $qr->[0], $R, $T, $d)\n";
d446 38
@
1.8
log
@resolveequivrelations() recursively resolves all equivalences
@
text
@d371 1
a371 2
my ($ds, $S, $b, $R, $T, $ts) = @@_;
print " " . substr $ds . " "x80, 0, 5;
d373 1
d375 2
a376 1
print " " . substr $R . " "x80, 0, 15;
a377 1
print " " . substr $ts . " "x80, 0, 5;
@
1.7
log
@implement querysetrelations(), a poor mans SQL-like "select from"
@
text
@d31 1
a31 1
#FIXME use strict;
d72 1
a72 1
foreach $u (@@{$CU->{$c}}) {
d219 1
a219 1
{ "S" => "g1", "ns" => "oo", "b" => "+", "R" => "read", "nt" => "oo", "T" => "a1" },
d230 1
a230 1
{ "S" => "u2", "ns" => "oo", "b" => "+", "R" => "proxy", "nt" => "oo", "T" => "u1" },
d270 1
a270 1
my @@O;
d272 1
a272 1
printf "querysetrelations(..., %s, %s, %s, ...)\n", rightstr(" ", $S, 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3) if($cfg->{verbose} == 1);
d295 2
d318 1
a318 1
printf "getimmediateequiv (object relations %s %s %s) ", rightstr(" ", $S, 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3);
d321 1
a321 1
printf "become class relations %s %s %s:", rightstr(" ", $S, 7), rightstr(" ", $R, 6), rightstr(" ", $T, 7);
d323 1
a323 1
foreach $dr (@@{$DR}) {
d338 7
a344 9
foreach my $i (keys %{$rsi}) { print " $i"; } print "\n";
return @@rsi;
}
sub queryforsetrelations
{
my ($UC, $DR, $S, $R, $T) = @@_;
printf "getdefinedrelations (object relations %s %s %s) ", rightstr(" ", $S, 3), rightstr(" ", $R, 6), rightstr(" ", $T, 3);
d350 1
a350 1
$r = $f x $l . $s;
d363 1
a363 1
dumpeffectiverelation("ds" , "S" , "b" , "R" , "T" , "ts" );
d366 1
a366 1
dumpeffectiverelation($i->{ds}, $i->{S}, $i->{b}, $i->{R}, $i->{T}, $i->{ts});
d388 14
a401 8
foreach $sr (@@{$SR}) {
print "processing set relationship" if($cfg->{verbose} == 1);
dumpsetrelation($sr->{"S"}, $sr->{"ns"}, $sr->{"b"}, $sr->{"R"}, $sr->{"nt"}, $sr->{"T"}) if($cfg->{verbose} == 1);
getimmediateequiv($UC, $DR, $sr->{"S"}, $sr->{"R"}, $sr->{"T"});
#my @@EQ = (); #
#<$RS_i,$ns>
lookup_ns_and_rsi_in_dr($DR, $sr->{S}, $sr->{R}, $sr->{T})
d403 18
a421 5
$ER = [
{ "ds" => 3, "S" => "foo", "b" => "+", "R" => "loves", "T" => "bar", "ts" => 2 },
{ "ds" => 0, "S" => "quux", "b" => "+", "R" => "needs", "T" => "none", "ts" => 1 }
];
return $ER;
d424 1
a424 1
sub lookup_ns_and_rsi_in_dr
d426 2
a427 1
my ($DR, $S, $R, $T) = @@_;
@
1.6
log
@describe operation and limitations of getimmediateequiv
@
text
@d257 40
d338 7
@
1.5
log
@getimmediateequiv now uses hash to remove duplicates and supports wildcard relations
@
text
@d257 15
@
1.4
log
@flush before getimmediateequiv moves from array to hash
@
text
@d154 1
a154 1
"RS_i" => [ ],
d156 1
a156 1
"R" => [ "parent" ],
d267 10
a276 7
foreach my $s (@@{$dr->{"S"}}) {
foreach my $r (@@{$dr->{"R"}}) {
foreach my $t (@@{$dr->{"T"}}) {
if ($s eq "*" && $r eq $R && $t eq "*") { foreach my $i (@@{$dr->{"RS_i"}}) { $rsi->$i } };
if ($s eq "*" && $r eq $R && $t eq $T ) { foreach my $i (@@{$dr->{"RS_i"}}) { $rsi->$i } };
if ($s eq $S && $r eq $R && $t eq "*") { foreach my $i (@@{$dr->{"RS_i"}}) { $rsi->$i } };
if ($s eq $S && $r eq $R && $t eq $T ) { foreach my $i (@@{$dr->{"RS_i"}}) { $rsi->$i } };
d281 1
a281 1
foreach my $i (key %{$rsi}) { print " $i"; } print "\n";
@
1.3
log
@flush before getimmediateequiv moves from array to hash
@
text
@d265 1
a265 1
my @@rsi;
d270 4
a273 4
if ($s eq "*" && $r eq $R && $t eq "*") { foreach my $i (@@{$dr->{"RS_i"}}) { push @@rsi, $i } };
if ($s eq "*" && $r eq $R && $t eq $T ) { foreach my $i (@@{$dr->{"RS_i"}}) { push @@rsi, $i } };
if ($s eq $S && $r eq $R && $t eq "*") { foreach my $i (@@{$dr->{"RS_i"}}) { push @@rsi, $i } };
if ($s eq $S && $r eq $R && $t eq $T ) { foreach my $i (@@{$dr->{"RS_i"}}) { push @@rsi, $i } };
d278 1
a278 1
foreach my $i (@@rsi) { print " $i"; } print "\n";
@
1.2
log
@cosmetics
@
text
@d60 26
a85 2
# defined relationships (pre-configured input)
# @@DR := { } = { ... }
d90 2
a91 2
# user and every object that is_proxy_of
# has _read/write_access_to an
d94 1
a94 2
"RS_i" => [ "is_proxy_of" ],
"ns" => 1,
d96 1
a96 1
"R" => [ "has_read_access_to", "has_write_access_to" ],
d98 1
a98 2
"nt" => "oo",
"RT_i" => [ "as_parent" ]
d104 1
a104 2
"RS_i" => [ "is_member_of" ],
"ns" => "oo",
d106 1
a106 1
"R" => [ "has_read_access_to", "has_write_access_to" ],
d108 1
a108 2
"nt" => "oo",
"RT_i" => [ "as_parent" ]
d114 1
a114 2
"RS_i" => [ "is_occupant_of" ],
"ns" => "oo",
d116 1
a116 1
"R" => [ "has_read_access_to", "has_write_access_to" ],
d118 11
a128 2
"nt" => "oo",
"RT_i" => [ "as_parent" ]
d134 1
a134 2
"RS_i" => [ ],
"ns" => 0,
d136 1
a136 1
"R" => [ "is_proxy_of" ],
a137 1
"nt" => 0,
a144 1
"ns" => 0,
d146 1
a146 1
"R" => [ "is_occupant_of" ],
a147 1
"nt" => 0,
a154 1
"ns" => 0,
d156 1
a156 1
"R" => [ "as_parent" ],
a157 1
"nt" => 0,
a164 1
"ns" => 0,
d166 1
a166 1
"R" => [ "is_member_of" ],
a167 1
"nt" => 0,
d174 1
a174 2
"RS_i" => [ "is_proxy_of" ],
"ns" => 0,
d176 1
a176 1
"R" => [ "can_manage" ],
d178 1
a178 2
"nt" => 0,
"RT_i" => [ "parent_is" ]
d186 2
a187 2
dumpdefinedrelation("RS_i", "ns" , "S" , "R", "T" , "nt" , "RT_i");
dumpdefinedrelation("-"x80, "-"x80, "-"x80, "-"x80, "-"x80, "-"x80, "-"x80);
a188 2
$ns = $i->{"ns" };
$nt = $i->{"nt" };
d194 1
a194 1
dumpdefinedrelation($rsi, $ns, $s, $r, $t, $nt, $rti);
d205 1
a205 1
my ($RS_i, $ns, $S, $R, $T, $nt, $RT_i) = @@_;
a206 1
print " " . substr $ns . " "x80, 0, 2;
a209 1
print " " . substr $nt . " "x80, 0, 2;
a212 3
#foreach $i (@@{$DR}) {
# print "$i->{R}->[0]\n";
#}
d214 2
a215 2
# set relations
# @@SR := { } = { ... }
d219 3
a221 2
{ "S" => "group-1", "b" => "+", "R" => "has_read_access_to", "T" => "account-1" },
{ "S" => "user-1", "b" => "+", "R" => "has_write_access_to", "T" => "account-2" },
d223 1
a223 1
{ "S" => "account-2", "b" => "+", "R" => "as_parent", "T" => "account-1" },
d225 7
a231 7
{ "S" => "user-1", "b" => "+", "R" => "is_member_of", "T" => "group-1" },
{ "S" => "group-2", "b" => "+", "R" => "is_member_of", "T" => "group-1" },
{ "S" => "user-2", "b" => "+", "R" => "is_member_of", "T" => "group-2" },
{ "S" => "user-4", "b" => "+", "R" => "is_member_of", "T" => "group-2" },
# proxies
{ "S" => "user-2", "b" => "+", "R" => "is_proxy_of", "T" => "user-1" },
{ "S" => "user-3", "b" => "+", "R" => "is_proxy_of", "T" => "user-2" }
d238 2
a239 2
dumpsetrelation("S" , "b" , "R" , "T" );
dumpsetrelation("-"x80, "-"x80, "-"x80, "-"x80);
d241 1
a241 1
dumpsetrelation($i->{S}, $i->{b}, $i->{R}, $i->{T});
d247 7
a253 5
my ($S, $b, $R, $T) = @@_;
print " " . substr $S . " "x80, 0, 15;
print " " . substr $b . " "x80, 0, 1;
print " " . substr $R . " "x80, 0, 15;
print " " . substr $T . " "x80, 0, 15;
d257 33
d292 1
a292 1
my $ER = geteffectiverelations($DR, $SR);
d320 1
a320 1
my ($DR, $SR) = @@_;
d324 3
a326 2
print "processing set relationship" if($cfg->{verbose} == 1);
dumpsetrelation($sr->{S}, $sr->{b}, $sr->{R}, $sr->{T}) if($cfg->{verbose} == 1);
@
1.1
log
@flush and break at "object class vs. instance" and "usefulness outside acl" problems
@
text
@d167 1
a167 1
print "dumping defined relations\n";
d221 1
a221 1
#dumpsetrelations($SR);
d225 1
a225 1
print "dumping set relations\n";
d250 1
a250 1
print "dumping effective relations\n";
@