SOURCE CODE: z_get_user_privileges

File uploaded by Daniel Becker Bighelini Champion on Feb 22, 2018Last modified by Daniel Becker Bighelini Champion on Feb 22, 2018
Version 2Show Document
  • View in full screen mode

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:

////////////////////////////////////////////////////////////////////////////
// Modulo:          z_get_user_privileges.spl
// Autor:          Daniel Becker Bighelini
// Criado em:          21/02/2018
// Modificado por:     Daniel Becker Bighelini
// Modificado em:     22/02/2018
////////////////////////////////////////////////////////////////////////////


api::z_get_user_privileges(string zs_persid, ...)
{
     ////////////////////////////////////////////////////////////////////////
     // Metodo:           z_get_user_privileges
     // Autor:          Daniel Becker Bighelini
     // Criado em:          21/02/2018
     // Modificado por:     Daniel Becker Bighelini
     // Modificado em:     22/02/2018
     //
     // Parametros de entrada:
     // ARG #0 : (string) zs_persid          Persistent_id do objeto
     // ARG #1 : (uuid) zu_who          [OPCIONAL] Usuario que tera seus privilegios consultados.
     //                                                          Se nao for informado, usuario atual sera utilizado.
     // ARG #2 : (string) zs_constraint     [OPCIONAL] Tipos de restricao de particao de dados consultadas.
     //                                                          (ALL / VIEW / PREUPDATE / UPDATE / CREATE / DELETE / DEFAULTS).
     //                                                          Se nao for informado, todas restricoes serao verificadas.
     // ARG #3 : (int)  zi_depurar          [OPCIONAL] Nivel de depuracao da funcao 0-nenhum / 1-resumido / 2-detalhado.
     // ARG #4 : (string) zs_metodo          [OPCIONAL] Nome do metodo chamador desta funcao.
     //
     // Resultado:
     //          Obtem as permissoes efetivas do usuario em relacao ao FUNC GROUP do objeto e
     // as DATA PARTITIONS vigentes do usuario em relacao ao objeto.
     //
     // Exemplo:
     //          z_get_user_privileges('iss_wf:999999')
     //          z_get_user_privileges('iss_wf:999999', U'FF0AB8C91A2A2049B243D3FFB2CD78D9')
     //          z_get_user_privileges('iss_wf:999999', U'FF0AB8C91A2A2049B243D3FFB2CD78D9', 'UPDATE')
     //          z_get_user_privileges('iss_wf:999999', U'FF0AB8C91A2A2049B243D3FFB2CD78D9', 'ALL', 1)
     //          z_get_user_privileges('iss_wf:999999', U'FF0AB8C91A2A2049B243D3FFB2CD78D9', 'ALL', 1, 'teste')
     ////////////////////////////////////////////////////////////////////////
     // Atribuindo variaveis
     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);

     /*
     // Funcoes para obter informacoes sobre o login do usuario
     // Somente funcionam quando executadas no contexto de uma trigger
     logf(SIGNIFICANT, cnt::get_login_user_role_name());
     logf(SIGNIFICANT, cnt::get_login_user_interface_type());
     logf(SIGNIFICANT, cnt::get_login_user_grant_level());
     logf(SIGNIFICANT, cnt::get_grant_level_string_val(cnt::get_login_user_grant_level()));
     */

     
     // Entrada para debug mode
     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);
     }
     
     // Define a variavel de retorno dos privilegios do usuario
     string zs_privileges;
     zs_privileges = '';
     
     // Redefine o tipo de restricao que sera consultada convertendo em maiusculas
     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;
     }

     // Redefine o tipo de restricao que sera consultada convertendo em maiusculas
     if (is_empty(zs_constraint)) zs_constraint = 'ALL';
     zs_constraint = upcase(zs_constraint);

     // Redefine o usuario que sera consultado
     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);
     }

     ////////////////////////////////////////////////////
     // Consultando a FACTORY do objeto
     ////////////////////////////////////////////////////
     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);
     
     ////////////////////////////////////////////////////
     // Consultando o ACESSO FUNCIONAL da 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);

     ////////////////////////////////////////////////////
     // Consultando o nome da FUNCAO ATUAL do usuario logado
     ////////////////////////////////////////////////////
     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);
     
     ////////////////////////////////////////////////////
     // Consultando o ID, PARTICAO DE DADOS e outros
     // atributos da FUNCAO IDENTIFICADA
     ////////////////////////////////////////////////////
     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");
     
     ////////////////////////////////////////////////////
     // Consultando as PERMISSOES DO ACESSO FUNCIONAL
     // associado com a FUNCAO
     ////////////////////////////////////////////////////
     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) {
          ////////////////////////////////////////////////////
          // Instanciando O ACESSO FUNCIONAL associado com a FUNCAO
          ////////////////////////////////////////////////////
          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];
          
          // Define os niveis de acesso da FUNC_GROUP
          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;
          }
          
          // Define os tipos de restricoes de DATA PARTITION
          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';

          // Define os privilegios iniciais da variavel de retorno
          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);
          
          ////////////////////////////////////////////////////
          // Consultando as RESTRICOES DA PARTICAO DE DADOS da factory
          ////////////////////////////////////////////////////
          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++) {
                         ////////////////////////////////////////////////////
                         // Instanciando O ACESSO FUNCIONAL associado com a FUNCAO
                         ////////////////////////////////////////////////////
                         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);
                         // Implementar tratamento de @root.pgroups no futuro
                         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);
                         }
                    } // Fim do FOR

               } 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);
          } // Fim do IF
          
     } 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);
     
     ////////////////////////////////////////////////////
     // RETORNA VALORES
     ////////////////////////////////////////////////////
     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;
     // Fim do codigo
    ///////////////////////////////////     
}

 

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);
   //send_wait(0, top_object(), "call_attr", "api", "z_get_user_privileges", zs_persid, zu_who, "ALL");
   //send_wait(0, top_object(), "call_attr", "api", "z_get_user_privileges", zs_persid, zu_who, "PREUPDATE", zi_depurar, zs_metodo);
   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!

Attachments

Outcomes