Hi guys,
I developed a new custom method in the SDM tool API that allows you to verify that the data partitions and access permissions of a specific object are being respected according to the respective logged user's role.
Very useful for users who have developed new webengine operations in the tool that change attributes of an object in 'one-click' mode.
HOW TO USE?
1) Copy the file 'z_get_user_privileges.spl' and 'z_get_user_privileges.mod' to the $NX_ROOT/site/mods/majic;
2) Restart the SDM services.
SOURCE CODE:
api::z_get_user_privileges(string zs_persid, ...)
{
int zi_i, zi_depurar;
uuid zu_who;
string zs_msg, zs_constraint, zs_metodo;
zs_metodo = 'z_get_user_privileges';
zs_msg = '';
if (argc>0) zs_persid = (string) argv[0];
if (argc>1) zu_who = (uuid) argv[1];
if (argc>2) zs_constraint = (string) argv[2];
if (argc>3) zi_depurar = (int) argv[3];
if (argc>4) zs_metodo = format("%s %s", argv[4], zs_metodo);
if (zi_depurar > 0) {
z_bloco_inicio(zi_depurar, zs_metodo);
logf(SIGNIFICANT, "%s Quant. de argumentos : %d", zs_metodo, argc);
for (zi_i=0; zi_i<argc; zi_i++) {
logf(SIGNIFICANT, "%s ARG #%s : %s", zs_metodo, zi_i, argv[zi_i]);
}
} else {
logf(SIGNIFICANT, "%s '%s' '%s' '%s'", zs_metodo, zs_persid, zu_who, zs_constraint);
}
string zs_privileges;
zs_privileges = '';
if (is_empty(zs_persid)) {
zs_msg = format("%s ERRO ao executar: PERSID do objeto NAO foi informado", zs_metodo);
set_error(1);
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
if (is_empty(zs_constraint)) zs_constraint = 'ALL';
zs_constraint = upcase(zs_constraint);
if (is_empty(zu_who)) {
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Identificando usuario logado...", zs_metodo);
send_wait(0, top_object(), "call_attr", "cnt", "current_user_id");
if (msg_error() || is_empty(msg[0])) {
zs_msg = format("%s ERRO ao identificar usuario logado: '%s'", zs_metodo, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
zu_who = msg[0];
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Usuario logado: '%s'", zs_metodo, zu_who);
}
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Consultando FACTORY do objeto '%s'...", zs_metodo, zs_persid);
send_wait(0, top_object(), "call_attr", "api", "get_object_values", zu_who, zs_persid, 0, "producer_id");
if (msg_error()) {
zs_msg = format("%s ERRO ao consultar o atributo 'producer_id' do objeto '%s': '%s'", zs_metodo, zs_persid, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
string zs_factory;
zs_factory = msg[1];
if (zi_depurar > 0) logf(SIGNIFICANT, "%s FACTORY identificada: '%s'", zs_metodo, zs_factory);
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Consultando FUNC_GROUP da factory '%s'...", zs_metodo, zs_factory);
send_wait(0, top_object(), "call_attr", "api", "get_func_access", zs_factory);
if (msg_error()) {
zs_msg = format("%s ERRO ao consultar o 'Func Group' da factory '%s': '%s'", zs_metodo, zs_factory, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
string zs_func_group;
zs_func_group = msg[2];
if (zi_depurar > 0) logf(SIGNIFICANT, "%s FUNC_GROUP identificado: '%s'", zs_metodo, zs_func_group);
string zs_role;
if ((string) thread_userid() != "superuser") {
zs_role = cnt::get_login_user_role_name();
} else {
zs_msg = format("%s ERRO ao identificar a ROLE do usuario '%s'.", zs_metodo);
set_error(1);
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
if (zi_depurar > 0) logf(SIGNIFICANT, "%s ROLE NAME identificada: '%s'", zs_metodo, zs_role);
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Consultando atributos da ROLE '%s'...", zs_metodo, zs_role);
send_wait(0, top_object(), "call_attr", "role", "val_by_key", "name", zs_role, 3, "id", "override_cnt_datapart", "data_partition");
if (msg_error()) {
zs_msg = format("%s ERRO ao consultar atributos da ROLE '%s': '%s'", zs_metodo, zs_role, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
int zi_role_id, zi_data_partition, zi_override_cnt_datapart;
zi_role_id = msg[1];
zi_override_cnt_datapart = msg[2];
zi_data_partition = (int) expand(format("&{%s = cnt.id->domain}", zu_who));
if (zi_depurar > 0) logf(SIGNIFICANT, "%s ROLE ID identificada: %d", zs_metodo, zi_role_id);
if (is_empty(zi_data_partition) || zi_data_partition == 0 || zi_override_cnt_datapart == 1) {
zi_data_partition = msg[3];
if (zi_depurar > 0) logf(SIGNIFICANT, "%s DATA PARTITION ID da ROLE identificada: %s", zs_metodo, zi_data_partition);
} else {
if (zi_depurar > 0) logf(SIGNIFICANT, "%s DATA PARTITION ID do USUARIO identificada: %s", zs_metodo, zi_data_partition);
}
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Substituir particao de dados do contato: %s", zs_metodo, zi_override_cnt_datapart == 1 ? "SIM" : "NAO");
string zs_producer_far, zs_far_wc;
zs_producer_far = 'func_access_role';
zs_far_wc = format("func_access='%s' AND role=%d", zs_func_group, zi_role_id);
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Consultando a FUNC_GROUP '%s' na ROLE '%s'...", zs_metodo, zs_func_group, zs_role);
send_wait(0, top_object(), "call_attr", zs_producer_far, "sync_fetch", "MLIST_STATIC", zs_far_wc, -1, 0);
if (msg_error()) {
zs_msg = format("%s ERRO ao consultar o producer '%s' utilizando a clausula '%s': '%s'", zs_metodo, zs_producer_far, zs_far_wc, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
object zo_far_list;
int zi_far_count;
zo_far_list = msg[0];
zi_far_count = msg[1];
if (zi_far_count > 0) {
send_wait(0, zo_far_list, "dob_by_index", "DEFAULT", 0, 0);
if (msg_error()) {
zs_msg = format("%s ERRO ao instanciar o objeto da lista no producer '%s': '%s'", zs_metodo, zs_producer_far, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
object zo_far;
zo_far = msg[0];
string zs_access_level;
switch (zo_far.access_level.access_level) {
case 0: zs_access_level = 'none'; break;
case 1: zs_access_level = 'view'; break;
case 2: zs_access_level = 'modify'; break;
default: zs_access_level = 'unknow'; break;
}
enum {LINS=6};
string zs_dcon_type[LINS];
zs_dcon_type[0] = 'VIEW';
zs_dcon_type[1] = 'PREUPDATE';
zs_dcon_type[2] = 'UPDATE';
zs_dcon_type[3] = 'CREATE';
zs_dcon_type[4] = 'DELETE';
zs_dcon_type[5] = 'DEFAULTS';
string zs_permission;
zs_privileges = format("ACCESS_LEVEL=%s", zs_access_level);
for (zi_i=0; zi_i<LINS; zi_i++) {
zs_permission = 'yes';
if (zs_constraint == 'ALL' || zs_dcon_type[zi_i] == zs_constraint) {
if (zs_dcon_type[zi_i] == 'VIEW' && zs_access_level == 'none') {
zs_permission = 'no';
} else if ((zs_dcon_type[zi_i] == 'PREUPDATE' || zs_dcon_type[zi_i] == 'UPDATE' || zs_dcon_type[zi_i] == 'CREATE' || zs_dcon_type[zi_i] == 'DELETE') && zs_access_level != 'modify') {
zs_permission = 'no';
}
zs_privileges = format("%s;%s=%s", zs_privileges, zs_dcon_type[zi_i], zs_permission);
}
}
if (zi_depurar > 0) logf(SIGNIFICANT, "%s ACCESS LEVEL da FUNC_GROUP '%s': '%s'", zs_metodo, zs_func_group, zo_far.access_level.sym);
if (!is_empty(zi_data_partition)) {
string zs_producer_dcon, zs_dcon_wc;
zs_producer_dcon = 'dcon';
zs_dcon_wc = format("delete_flag=0 AND dom_id=%d AND tbl_id.obj_name='%s'", zi_data_partition, zs_factory);
if (zs_constraint != 'ALL') {
for (zi_i=0; zi_i<LINS; zi_i++) {
if (zs_dcon_type[zi_i] == zs_constraint) {
zs_dcon_wc += format(" AND type=%d", zi_i);
break;
}
}
if (zi_i == LINS) {
zs_msg = format("%s ERRO ao processar o tipo de restricao '%s': Somente sao permitidos os valores ALL/VIEW/PREUPDATE/UPDATE/CREATE/DELETE/DEFAULTS.", zs_metodo, zs_constraint);
set_error(1);
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
}
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Consultando as CONSTRAINS (%s) da DATA PARTITION '%d'...", zs_metodo, zs_constraint, zi_data_partition);
send_wait(0, top_object(), "call_attr", zs_producer_dcon, "sync_fetch", "MLIST_STATIC", zs_dcon_wc, -1, 0);
if (msg_error()) {
zs_msg = format("%s ERRO ao consultar o producer '%s' utilizando a clausula '%s': '%s'", zs_metodo, zs_producer_dcon, zs_dcon_wc, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
object zo_dcon_list;
int zi_dcon_count;
zo_dcon_list = msg[0];
zi_dcon_count = msg[1];
if (zi_dcon_count > 0) {
for (zi_i=0; zi_i<zi_dcon_count; zi_i++) {
send_wait(0, zo_dcon_list, "dob_by_index", "DEFAULT", zi_i, zi_i);
if (msg_error()) {
zs_msg = format("%s ERRO ao instanciar o objeto da lista no producer '%s': '%s'", zs_metodo, zs_producer_dcon, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
object zo_dcon;
zo_dcon = msg[0];
string zs_dcon_constraint_majic;
int zi_dcon_type;
zs_dcon_constraint_majic = zo_dcon.constraint_majic;
zi_dcon_type = zo_dcon.type;
zs_dcon_constraint_majic = gsub(zs_dcon_constraint_majic, "@root.id", format("U'%s'", zu_who));
zs_dcon_constraint_majic = gsub(zs_dcon_constraint_majic, "@root.role", (string) zi_role_id);
if (zi_depurar > 0) logf(SIGNIFICANT, "%s CONSTRAINT MAJIC (%s): '%s'", zs_metodo, zo_dcon.type.sym, zs_dcon_constraint_majic);
if (zs_dcon_type[zi_dcon_type] != "DEFAULTS") {
string zs_wc;
zs_wc = format("persistent_id='%s' AND (%s)", zs_persid, zs_dcon_constraint_majic);
if (zi_depurar > 1) logf(SIGNIFICANT, "%s WHERE CLAUSE: '%s'", zs_metodo, zs_wc);
send_wait(0, top_object(), "call_attr", "api", "api_select_count", zs_factory, zs_wc);
if (msg_error()) {
zs_msg = format("%s ERRO ao contabilizar registros no producer '%s' utilizando a clausula '%s': '%s'", zs_metodo, zs_factory, zs_wc, msg[0]);
set_error(msg_error());
set_return_data(0, zs_msg);
logf(ERROR, "%s", zs_msg);
z_bloco_fim(zi_depurar, zs_metodo);
return zs_msg;
}
int zi_count;
zi_count = msg[0];
if (zi_count == 0) {
zs_privileges = gsub(zs_privileges, format(";%s=yes", zs_dcon_type[zi_dcon_type]), format(";%s=no", zs_dcon_type[zi_dcon_type]));
}
} else {
if (zi_depurar > 0) logf(SIGNIFICANT, "%s AVISO: Restricao DEFAULTS IGNORADA!", zs_metodo);
}
}
} else {
if (zi_depurar > 0) logf(SIGNIFICANT, "%s AVISO: Nenhuma CONSTRAINT do tipo '%s' foi encontrada.", zs_metodo, zs_constraint);
}
} else {
if (zi_depurar > 0) logf(SIGNIFICANT, "%s AVISO: Nenhuma DATA PARTITION foi definida na ROLE e usuario.", zs_metodo);
}
} else {
if (zi_depurar > 0) logf(SIGNIFICANT, "%s AVISO: A FUNC_GROUP '%s' NAO foi localizada na ROLE '%s': '%s'", zs_metodo, zs_func_group, zs_role);
}
if (zi_depurar > 0) logf(SIGNIFICANT, "%s PRIVILEGIOS: '%s'", zs_metodo, zs_privileges);
int zi_return_count, zi_delim, zi_idx;
string zs_return[7], zs_key, zs_value;
zi_idx = 0;
zi_return_count = split(zs_return, zs_privileges, ';');
for (zi_i=0; zi_i<zi_return_count; zi_i++) {
if (zi_depurar > 0) logf(SIGNIFICANT, "%s Retornando '%s'...", zs_metodo, zs_return[zi_i]);
zi_delim = sindex(zs_return[zi_i], '=');
zs_key = substr(zs_return[zi_i], 0, zi_delim);
zs_value = substr(zs_return[zi_i], zi_delim + 1);
set_return_data(zi_idx, zs_key);
set_return_data(zi_idx+1, zs_value);
zi_idx+=2;
}
z_bloco_fim(zi_depurar, zs_metodo);
return zs_privileges;
}
EXAMPLE:
void z_test()
{
int zi_depurar;
zi_depurar = 1;
string zs_metodo, zs_msg;
zs_metodo = 'z_test';
string zs_persid;
zs_persid = 'iss_wf:587983';
uuid zu_who;
zu_who = (uuid) 'F1CA5A43A27AE04DB88D4EDF438D42BF';
send_wait(0, top_object(), "call_attr", "api", "z_get_user_privileges", zs_persid);
if (msg_error()) {
zs_msg = format("%s ERRO ao consultar privilegios do usuario: '%s'", zs_metodo, msg[0]);
printf("ERRO ao consultar privilegios do usuario: '%s'", msg[0]);
return zs_msg;
}
int i;
for (i=0;i<msg_length();i++) {
printf("%s\n", msg[i]);
}
}
RETURN (bop_cmd -u servicedesk -f z_teste.spl "z_test()")
ACCESS_LEVEL
modify
VIEW
yes
PREUPDATE
yes
UPDATE
yes
CREATE
yes
DELETE
yes
DEFAULTS
yes
Enjoy!