Browse Source

Adiciona feature flag lib (#3693)

Adiciona feature flag lib e refatora Solr para usá-la
pull/3694/head
Edward 1 year ago
committed by GitHub
parent
commit
b495a35c34
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      docker/docker-compose.yaml
  2. 17
      docker/start.sh
  3. 45
      docs/feature-flags.md
  4. 1
      requirements/requirements.txt
  5. 1
      sapl/base/forms.py
  6. 17
      sapl/base/migrations/0059_remove_appconfig_sapl_as_sapn.py
  7. 4
      sapl/base/models.py
  8. 6
      sapl/base/views.py
  9. 9
      sapl/context_processors.py
  10. 3
      sapl/materia/views.py
  11. 4
      sapl/norma/views.py
  12. 3
      sapl/sessao/views.py
  13. 16
      sapl/settings.py
  14. 6
      sapl/templates/base.html
  15. 2
      sapl/templates/base/layouts.yaml
  16. 6
      sapl/templates/materia/materialegislativa_filter.html
  17. 1
      sapl/templates/norma/normajuridica_detail.html
  18. 5
      sapl/templates/norma/normajuridica_filter.html
  19. 8
      sapl/templates/search/search.html
  20. 5
      sapl/templates/sessao/sessaoplenaria_filter.html
  21. 6
      sapl/utils.py

1
docker/docker-compose.yaml

@ -54,6 +54,7 @@ services:
SOLR_COLLECTION: sapl
SOLR_URL: http://solr:solr@saplsolr:8983
IS_ZK_EMBEDDED: 'True'
ENABLE_SAPN: 'False'
TZ: America/Sao_Paulo
volumes:
- sapl_data:/var/interlegis/sapl/data

17
docker/start.sh

@ -39,6 +39,7 @@ create_env() {
echo "SOLR_COLLECTION = ""${SOLR_COLLECTION-sapl}" >> $FILENAME
echo "SOLR_URL = ""${SOLR_URL-http://localhost:8983}" >> $FILENAME
echo "IS_ZK_EMBEDDED = ""${IS_ZK_EMBEDDED-False}" >> $FILENAME
echo "ENABLE_SAPN = ""${ENABLE_SAPN-False}" >> $FILENAME
echo "[ENV FILE] done."
}
@ -85,14 +86,30 @@ if [ "${USE_SOLR-False}" == "True" ] || [ "${USE_SOLR-False}" == "true" ]; then
fi
python3 solr_cli.py -u $SOLR_URL -c $SOLR_COLLECTION -s $NUM_SHARDS -rf $RF -ms $MAX_SHARDS_PER_NODE $ZK_EMBEDDED &
# Enable SOLR switch on, creating if it doesn't exist on database
./manage.py waffle_switch SOLR_SWITCH on --create
else
echo "Solr is offline, not possible to connect."
# Disable Solr switch off, creating if it doesn't exist on database
./manage.py waffle_switch SOLR_SWITCH off --create
fi
else
echo "Solr support is not initialized."
# Disable Solr switch off, creating if it doesn't exist on database
./manage.py waffle_switch SOLR_SWITCH off --create
fi
## Enable/Disable SAPN
if [ "${ENABLE_SAPN-False}" == "True" ] || [ "${ENABLE_SAPN-False}" == "true" ]; then
echo "Enabling SAPN"
./manage.py waffle_switch SAPLN_SWITCH on --create
else
echo "Enabling SAPL"
./manage.py waffle_switch SAPLN_SWITCH off --create
fi
echo "Creating admin user..."
user_created=$(python3 create_admin.py 2>&1)

45
docs/feature-flags.md

@ -0,0 +1,45 @@
### Types
Waffle supports three types of feature flippers:
### Flags
_"Flags can be used to enable a feature for specific users, groups, users meeting
certain criteria (such as being authenticated, or superusers) or a certain percentage
of visitors."_
https://waffle.readthedocs.io/en/stable/types/flag.html
### Switches
_"Switches are simple booleans: they are on or off, for everyone, all the time.
They do not require a request object and can be used in other contexts, such
as management commands and tasks."_
Enabling/Disabling via CLI (example):
./manage.py waffle_switch SOLR_SWITCH on --create
./manage.py waffle_switch SOLR_SWITCH off --create
https://waffle.readthedocs.io/en/stable/types/switch.html
### Samples
_"Samples are on a given percentage of the time. They do not require a request
object and can be used in other contexts, such as management commands and tasks."_
Liga e desliga baseado em amostragem aleatória.
https://waffle.readthedocs.io/en/stable/types/sample.html
### Reference
* Documentation: https://waffle.readthedocs.io/
* Managing from CLI: https://waffle.readthedocs.io/en/stable/usage/cli.html
* Templates: https://waffle.readthedocs.io/en/stable/usage/templates.html
* Views: https://waffle.readthedocs.io/en/stable/usage/views.html
* Decorators: https://waffle.readthedocs.io/en/stable/usage/decorators.html

1
requirements/requirements.txt

@ -11,6 +11,7 @@ django-extra-views==0.12.0
django-model-utils==3.1.2
django-extensions==2.1.4
django-image-cropping==1.2
django-waffle==3.0.0
django-webpack-loader==1.6.0
drf-spectacular==0.18.2
django-ratelimit==3.0.1

1
sapl/base/forms.py

@ -1009,7 +1009,6 @@ class ConfiguracoesAppForm(ModelForm):
'google_recaptcha_site_key',
'google_recaptcha_secret_key',
'google_analytics_id_metrica',
'sapl_as_sapn',
'identificacao_de_documentos',
]

17
sapl/base/migrations/0059_remove_appconfig_sapl_as_sapn.py

@ -0,0 +1,17 @@
# Generated by Django 2.2.28 on 2023-11-27 00:23
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('base', '0058_appconfig_ordenacao_pesquisa_materia'),
]
operations = [
migrations.RemoveField(
model_name='appconfig',
name='sapl_as_sapn',
),
]

4
sapl/base/models.py

@ -107,10 +107,6 @@ class AppConfig(models.Model):
default="",
verbose_name=_('Esfera Federação'),
choices=ESFERA_FEDERACAO_CHOICES)
sapl_as_sapn = models.BooleanField(
verbose_name=_(
'Utilizar SAPL apenas como SAPL-Normas?'),
choices=YES_NO_CHOICES, default=False)
# MÓDULO PARLAMENTARES

6
sapl/base/views.py

@ -50,8 +50,8 @@ from sapl.relatorios.views import (relatorio_estatisticas_acesso_normas)
from sapl.sessao.models import (Bancada, SessaoPlenaria)
from sapl.settings import EMAIL_SEND_USER
from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, mail_service_configured,
SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, google_recaptcha_configured, sapl_as_sapn,
get_client_ip)
SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, google_recaptcha_configured,
get_client_ip, sapn_is_enabled)
from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, EstatisticasAcessoNormasForm)
from .models import AppConfig, CasaLegislativa
@ -62,7 +62,7 @@ def get_casalegislativa():
class IndexView(TemplateView):
def get(self, request, *args, **kwargs):
if sapl_as_sapn():
if sapn_is_enabled():
return redirect('/norma/pesquisar')
return TemplateView.get(self, request, *args, **kwargs)

9
sapl/context_processors.py

@ -3,8 +3,7 @@ import logging
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from sapl.utils import google_recaptcha_configured as google_recaptcha_configured_utils,\
sapl_as_sapn as sapl_as_sapn_utils
from sapl.utils import google_recaptcha_configured as google_recaptcha_configured_utils, sapn_is_enabled
from sapl.utils import mail_service_configured as mail_service_configured_utils
@ -36,10 +35,10 @@ def google_recaptcha_configured(request):
return {'google_recaptcha_configured': True}
def sapl_as_sapn(request):
def enable_sapn(request):
return {
'sapl_as_sapn': sapl_as_sapn_utils(),
'sapl_as_sapn': sapn_is_enabled(),
'nome_sistema': _('Sistema de Apoio ao Processo Legislativo')
if not sapl_as_sapn_utils()
if not sapn_is_enabled()
else _('Sistema de Apoio à Publicação de Leis e Normas')
}

3
sapl/materia/views.py

@ -2132,9 +2132,6 @@ class MateriaLegislativaPesquisaView(FilterView):
context['show_results'] = show_results_filter_set(qr)
context['USE_SOLR'] = settings.USE_SOLR if hasattr(
settings, 'USE_SOLR') else False
return context

4
sapl/norma/views.py

@ -28,7 +28,7 @@ from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux,
MasterDetailCrud, make_pagination)
from sapl.materia.models import Orgao
from sapl.utils import show_results_filter_set, get_client_ip,\
sapl_as_sapn
sapn_is_enabled
from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm,
NormaPesquisaSimplesForm, NormaRelacionadaForm,
@ -187,8 +187,6 @@ class NormaPesquisaView(FilterView):
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr)
context['USE_SOLR'] = settings.USE_SOLR if hasattr(
settings, 'USE_SOLR') else False
return context

3
sapl/sessao/views.py

@ -3997,9 +3997,6 @@ class PesquisarSessaoPlenariaView(FilterView):
context['page_range'] = make_pagination(
page_obj.number, paginator.num_pages)
context['USE_SOLR'] = settings.USE_SOLR if hasattr(
settings, 'USE_SOLR') else False
return context
def get(self, request, *args, **kwargs):

16
sapl/settings.py

@ -80,6 +80,8 @@ INSTALLED_APPS = (
'crispy_forms',
'floppyforms',
'waffle',
'drf_spectacular',
'rest_framework',
'rest_framework.authtoken',
@ -137,6 +139,7 @@ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django_prometheus.middleware.PrometheusAfterMiddleware',
'waffle.middleware.WaffleMiddleware',
]
if DEBUG:
INSTALLED_APPS += ('debug_toolbar',)
@ -210,8 +213,7 @@ TEMPLATES = [
'sapl.context_processors.parliament_info',
'sapl.context_processors.mail_service_configured',
'sapl.context_processors.google_recaptcha_configured',
'sapl.context_processors.sapl_as_sapn',
'sapl.context_processors.enable_sapn',
],
'debug': DEBUG
},
@ -255,6 +257,16 @@ DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL', cast=str, default='')
SERVER_EMAIL = config('SERVER_EMAIL', cast=str, default='')
EMAIL_RUNNING = None
# Feature Flag
WAFFLE_FLAG_DEFAULT = False
WAFFLE_SWITCH_DEFAULT = False
WAFFLE_CREATE_MISSING_FLAGS = True
WAFFLE_LOG_MISSING_FLAGS = True
WAFFLE_CREATE_MISSING_SWITCHES = True
WAFFLE_LOG_MISSING_SWITCHES = True
WAFFLE_ENABLE_ADMIN_PAGES = True
MAX_DOC_UPLOAD_SIZE = 150 * 1024 * 1024 # 150MB
MAX_IMAGE_UPLOAD_SIZE = 2 * 1024 * 1024 # 2MB
DATA_UPLOAD_MAX_MEMORY_SIZE = 10 * 1024 * 1024 # 10MB

6
sapl/templates/base.html

@ -1,6 +1,7 @@
<!DOCTYPE html>
{% load i18n staticfiles menus %}
{% load common_tags %}
{% load waffle_tags %}
{% load render_bundle from webpack_loader %}
{% load webpack_static from webpack_loader %}
@ -11,13 +12,10 @@
<head>
<meta charset="utf-8">
<title>{% block head_title %}{% if sapl_as_sapn %}SAPL-Normas - {% else %}SAPL - {%endif%}{{nome_sistema}}{% endblock %}</title>
<title>{% block head_title %}{% switch "SAPLN_SWITCH" %}SAPL-Normas - {% else %}SAPL - {%endswitch%}{{nome_sistema}}{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#343a40">
{% block head_content %}
<link rel="icon" href="{% webpack_static 'img/favicon.ico' %}" type="image/png">
{% block webpack_loader_css %}

2
sapl/templates/base/layouts.yaml

@ -20,7 +20,7 @@ UserDetail:
AppConfig:
{% trans 'Configurações Gerais' %}:
- esfera_federacao sapl_as_sapn
- esfera_federacao
#{% trans 'Módulo Parlamentares' %}:
#{% trans 'Módulo Mesa Diretora' %}:

6
sapl/templates/materia/materialegislativa_filter.html

@ -1,18 +1,18 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load tz %}
{% load waffle_tags %}
{% load crispy_forms_tags common_tags%}
{% load webpack_static from webpack_loader %}
{% block actions %}
<div class="actions btn-group" role="group">
{% if USE_SOLR %}
{% switch "SOLR_SWITCH" %}
<a href="{% url 'sapl.base:haystack_search' %}" class="btn btn-outline-primary">
Pesquisa Textual
</a>
{% endif %}
{% endswitch %}
{% if perms.materia.add_materialegislativa %}
<a href="{% url 'sapl.materia:materialegislativa_create' %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar Matéria Legislativa {% endblocktrans %}

1
sapl/templates/norma/normajuridica_detail.html

@ -1,5 +1,6 @@
{% extends "crud/detail.html" %}
{% load i18n common_tags %}
{% load waffle_tags %}
{% load render_bundle from webpack_loader %}
{% block webpack_loader_css %}

5
sapl/templates/norma/normajuridica_filter.html

@ -1,14 +1,15 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load waffle_tags %}
{% load crispy_forms_tags common_tags %}
{% block actions %}
<div class="actions btn-group float-right" role="group">
{% if USE_SOLR %}
{% switch "SOLR_SWITCH" %}
<a href="{% url 'sapl.base:haystack_search' %}" class="btn btn-outline-primary">
Pesquisa Textual
</a>
{% endif %}
{% endswitch %}
{% if perms.norma.add_normajuridica %}
<a href="{% url 'sapl.norma:normajuridica_create' %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar Norma Jurídica {% endblocktrans %}

8
sapl/templates/search/search.html

@ -1,7 +1,7 @@
{% extends 'crud/form.html' %}
{% load crispy_forms_tags %}
{% load common_tags %}
{% load waffle_tags %}
{% block base_content %}
<h1><legend>Pesquisa Textual</legend></h1>
</br>
@ -11,9 +11,7 @@
{{ form.q|as_crispy_field }}
</div>
</div>
{% if not sapl_as_sapn %}
{% switch "SAPLN_SWITCH" %}
<div class="row">
<div class="col-md-8">
<h3> Em quais tipos de documento deseja pesquisar?</h3>
@ -27,7 +25,7 @@
{{ form.models }}
</div>
</div>
{% endif %}
{% endswitch %}
<div class="row">
<div class="col-md-12">

5
sapl/templates/sessao/sessaoplenaria_filter.html

@ -1,14 +1,15 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load waffle_tags %}
{% load crispy_forms_tags common_tags %}
{% block actions %}
<div class="actions btn-group float-right" role="group">
{% if USE_SOLR %}
{% switch "SOLR_SWITCH" %}
<a href="{% url 'sapl.base:haystack_search' %}" class="btn btn-outline-primary">
Pesquisa Textual
</a>
{% endif %}
{% endswitch %}
{% if perms.sessao %}
<a href="{% url 'sapl.sessao:sessaoplenaria_create' %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar Sessão Plenária {% endblocktrans %}

6
sapl/utils.py

@ -1061,9 +1061,9 @@ def google_recaptcha_configured():
return not AppConfig.attr('google_recaptcha_site_key') == ''
def sapl_as_sapn():
from sapl.base.models import AppConfig
return AppConfig.attr('sapl_as_sapn')
def sapn_is_enabled():
import waffle
return waffle.switch_is_active('SAPLN_SWITCH')
def timing(f):

Loading…
Cancel
Save