Standard that has contributed to the reliability of software that needs to meet complex models such as multi-business models

Asked

Viewed 344 times

6

Taking as an example a software that needs to meet a multicompany model, I would like to know from you if there are any standards adopted to deal with this type of situation?

Describing the condition a little more, let’s take as an example a software for accounting companies. It has a register of companies because it needs to meet N companies. Of each company we will have the register of customers, suppliers among others.

So this is how it needs to work:

  1. The user will have access to certain companies;
  2. The user needs to set to the system which company he will be performing the accounting processes;
  3. The system presents the data of certain registrations that were made for this company and records the new entries for the same.
  4. The user can at any time set to the system that he will work for another company and this performs the tasks as already mentioned.

So, in this condition I would like to know if there is a standard that assists in this kind of software architecture in order to help protect information from company to company and also help, of course, in the development for environments that require this kind of control?
That is, a standard to ensure that a company’s "A" data will not be mixed, presented or deleted in a company B. Hence, contribute to the reliability of the software.

An example, however small, is welcome to facilitate understanding!

1 answer

9


I believe the pattern multi-tenant ("multi-tenant") would be suitable for this case - although it is a single operator of a single company to access the various tenants. That article briefly describes the philosophy behind the multitenancy.

A real example

Instead of explaining the theory, I’m going to use a project from my company to exemplify: we built management software (ERP) focused on the third sector. The idea was to make local installation in the larger customers, and offer as Saas to the smaller ones. This second stage was not put into practice (yet), but the software was built according to this philosophy. In the cited article, it would correspond to model 4 ("Multi-tenant via the entire stack of shared software") - because there is only one instance of the application and a single BD.

A table tenant is the "heart" of the system: a row of this table is created for each customer, and this row partitions the entire bank. Any additional system table of the two one:

  1. has a foreign key for a row in that table; or:
  2. has [at least] a foreign key to another table that satisfies items 1 or 2.

Examples (fictitious; multitenancy key field marked with *):

tenant         linha_atuacao                        projeto
id  nome       id  tenant* nome                     id linha* nome
---------      -------------------------------      ------------------------------
1   ONG A      1   1       Educação                 1  2      Educação Ambiental
2   ONG B      2   1       Meio Ambiente            2  2      Ecovilas
               3   2       Criança e Juventude      3  2      Amazônia Sustentável

The user table also satisfies this restriction, of course. So that if a user is logged in, he belongs to one and only one tenant. Each view that requires user authentication (i.e. all of which read or write data, basically...) gets that user’s ID tenant right after authentication (i.e. it is stored in a session variable).

It remains to ensure that a user request will not accidentally affect a user’s data tenant that is not yours. There are those who prefer to do this within the database itself (so that it is not necessary to trust that the programmers will not make any mistake, because the views to which they have access are already filtered by tenant, both for reading and writing), but in my case I did in the same application layer.

  • The system uses Django’s ORM to access the database (i.e. without raw SQL), so it was only a matter of customizing it to enforce this restriction. I did it through a manager (the object that translates API calls to SQL queries) standardized for all models.
  • When preparing a reading query, it automatically adds the joinnecessary to ensure that only results of that tenant. Instead of:

    Projeto.objects.filter(nome="Ecovilas")
    # select * from projeto where nome = "Ecovilas";
    

    User-filtered custom API is used:

    Projeto.objects.list(request.user).filter(nome="Ecovilas")
    # que internamente corresponde a:
    # Projeto.objects.filter(linha__tenant__id=request.user.tenant).filter(nome="Ecovilas")
    #
    # select * from projeto p join linha_atuacao l on p.linha = l.id
    #                         join tenant t on l.tenant = t.id
    #          where t.id = 1 and nome="Ecovilas";
    
  • When preparing a writing query, it is a little more complicated... If the model is type 1 (foreign key to tenant) it automatically adds the right value in the field. Then, regardless of the type, it makes a query for each foreign key of the model (as if making a reading, in the pattern described above) to ensure that it belongs to the same tenant. Only then does it create/update/remove the actual line.

    linha = LinhaAtuacao.objects.create(nome="Dignidade e Direitos")
    # insert into linha_atuacao(nome) values("Dignidade e Direitos");
    
    Projeto.objects.create(linha=linha, nome="Creche X")
    # insert into projeto(linha_id, nome) values(3, "Creche X");
    

    Using the custom API:

    linha = LinhaAtuacao.objects.new(request.user)(nome="Dignidade e Direitos")
    # insert into linha_atuacao(tenant, nome) values(2, "Dignidade e Direitos");
    
    Projeto.objects.new(request.user)(linha=linha, nome="Creche X")
    # select * from linha_atuacao l join tenant t on l.tenant = t.id
    #          where t.id = 2 and l.id = 3;
    # insert into projeto(linha_id, nome) values(3, "Creche X");
    

    If anyone (in this case only has one) of selects fail - return no result - an exception is made instead of doing the insert ('cause you were trying to assign a line to a tenant as foreign key to another tenant).

One last detail: in the case of a shared terminal (where two or more tenants can access the same system, one after the other) it is important to ensure that nothing in the UI when one of them does logout. Although in my case this scenario was not foreseen (in your is - since it is the same user who will touch the data of several companies, one at a time), I chose to clean all the screens and reload page (is a web application) right after the logout, pro next that enter can not read data from previous.

Access "cross-tenant"

In your case, making the same user switch from one company to another is easy: just facilitate the process of making logout with a user account (from a tenant) and soon after login with another account (from another account tenant), without the need for re-use.

In my view, the problem has gone a little further: each NGO has several funders, and it has to be accountable to each one of them. Already a funder can provide resources to several Ngos, and it was foreseen that my system eventually should give access (read) to a funder to the data of all its conveniences - but only those data that are made available for this by tenant. As far as I know, there is nothing ready in that sense, so I’m still cracking my head to take care of all the details (the project is currently on hiatus).

Additional references

  • If you Google by "microsoft multi-tenant" you will find a series of articles (in English) that discuss the subject in depth (including citing other possible strategies to implement multitenancy).
  • According to my partner (who graduated in Business Administration, is not in the area of Computing) even before the Saas model and the idea of multitenancy there were already systems that employed the concept of "bosses" - in this case not necessarily clients apart, but key entities around which all other data revolved (well that’s what you’re looking for). However, I myself do not know the subject well nor do I have good references to indicate. But second this article on the SAP system the concept is the same, and seems to correspond almost 100% to the standard of multitenancy that I know.

    I don’t know if this is just an SAP thing or a standard used elsewhere - or if it fulfills the goal of contributing to system reliability, as asked in the question. But it’s an extra reference, if you’re willing, you can go look for more information.

  • Finally, if you are interested in taking a look, here is a link to my system code (the part that implements multitenancy and, a little above, other unrelated things). It is extremely poorly documented and "gambiarrado", and does not contain a complete example that you can download and already run (because only the library of "utilities" - and not the complete system - was released as free software), but it is better than nothing... I think...
  • 6

    Boy, this Stack Overflow thing is no joke, no. One asks the most specific question in the world and receives the most expert answer on the planet. Bra.vo!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.