diff --git a/config.yaml b/config.yaml
index 039f3d1..d1245b8 100644
--- a/config.yaml
+++ b/config.yaml
@@ -7,10 +7,8 @@ googleAnalytics: "UA-22087729-1"
params:
author: "Renne Rocha"
-
- siteName: "Hugo Tania is Amazing"
- siteDesc: "Hugo is Absurdly Fast!"
-
+ siteName: "Sharing what I learn about software development mainly"
+ siteDesc: "Sharing what I learn about software development mainly"
colorScheme:
toggle: true
@@ -43,7 +41,7 @@ params:
menu:
header:
- - name: Postagens
+ - name: Articles
url: "/articles/"
footer:
- name: RSS
diff --git a/content/posts/20070921-iniciando-ie-powerbuilder.md b/content/posts/20070921-iniciando-ie-powerbuilder.md
new file mode 100644
index 0000000..2cc6174
--- /dev/null
+++ b/content/posts/20070921-iniciando-ie-powerbuilder.md
@@ -0,0 +1,45 @@
+---
+title: "Iniciando o Internet Explorer a partir do PowerBuilder"
+publishdate: 2007-09-21
+tags: ["powerbuilder"]
+slug: iniciando-ie-com-powerbuilder
+---
+
+Esta semana tive que iniciar um projeto em que a principal funcionalidade seria executar a partir de um botão em uma window o Internet Explorer na máquina do cliente, abrindo uma determinada URL. Pensei em usar inicialmente a função `Run()`, porém uma das limitações do projeto era que a janela do navegador não poderia ter nenhuma barra de ferramentas disponível (endereço, status, favoritos, etc)
+
+Como não é possível iniciar o IE em linha de comando com parâmetros para ocultar essas barras de ferramentas tive que procurar outra solução. Pesquisando dentro da empresa, me sugeriram utilizar um objeto OLE para fazer essa tarefa.
+
+Pesquisando no site do MSDN, descobri o objeto [InternetExplorer](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752084(v=vs.85)?redirectedfrom=MSDN) que permite trabalhar com uma instância do IE. Você pode configurar diversas propriedades desse objeto (como exibição das barras de ferramentas, tamanho da janela, etc).
+
+Bom, no final fiz o seguinte código (utilizei o PowerBuilder 7) dentro do evento `clicked()` de um botão:
+
+```
+OLEObject uo_ie
+uo_ie = CREATE OLEObject
+Integer ii_handleoleobject = -999
+
+ii_handleoleobject = uo_ie.ConnectToNewObject("InternetExplorer.Application")
+IF ii_handleoleobject < 0 THEN
+ DESTROY uo_ie
+ MessageBox('Erro','Não foi ´possível criar o objeto OLE')
+ELSE
+ uo_ie.AddressBar = FALSE
+ uo_ie.MenuBar = FALSE
+ uo_ie.Resizable = FALSE
+ uo_ie.StatusBar = FALSE
+ uo_ie.ToolBar = FALSE
+ uo_ie.Visible = TRUE
+ uo_ie.Left = 200
+ uo_ie.Top = 200
+ uo_ie.Height = 500
+ uo_ie.Width = 500
+ uo_ie.Navigate(is_urlchamada)
+ SetForegroundWindow(uo_ie.HWND)
+END IF
+```
+
+Declarando uma função externa (para que a janela recém-criada fique ativada):
+
+```
+FUNCTION boolean SetForegroundWindow( long hWnd ) LIBRARY "USER32"
+```
diff --git a/content/posts/validando-dados-extraidos-com-scrapy.md b/content/posts/20190308-validando-dados-extraidos-com-scrapy.md
similarity index 99%
rename from content/posts/validando-dados-extraidos-com-scrapy.md
rename to content/posts/20190308-validando-dados-extraidos-com-scrapy.md
index 5d52889..dc8d49b 100644
--- a/content/posts/validando-dados-extraidos-com-scrapy.md
+++ b/content/posts/20190308-validando-dados-extraidos-com-scrapy.md
@@ -2,6 +2,7 @@
title: "Validando dados extraídos com Scrapy"
publishdate: 2019-03-08
tags: ["scrapy", "scraping", "monitoramento"]
+slug: validando-dados-extraidos-com-scrapy
---
Como você garante a qualidade e a confiabilidade dos dados que você está
diff --git a/content/posts/monitorando-seus-projetos-de-raspagem-de-dados.md b/content/posts/20220113-monitorando-seus-projetos-de-raspagem-de-dados.md
similarity index 99%
rename from content/posts/monitorando-seus-projetos-de-raspagem-de-dados.md
rename to content/posts/20220113-monitorando-seus-projetos-de-raspagem-de-dados.md
index 1e12e5e..ce1bf1d 100644
--- a/content/posts/monitorando-seus-projetos-de-raspagem-de-dados.md
+++ b/content/posts/20220113-monitorando-seus-projetos-de-raspagem-de-dados.md
@@ -2,6 +2,7 @@
title: "Monitorando seus projetos de raspagem de dados"
publishdate: 2022-01-13
tags: ["monitoramento", "scrapy", "raspagem de dados", "python", "spidermon"]
+slug: monitorando-seus-projetos-de-raspagem-de-dados
---
Quando passamos a extrair dados de uma página com regularidade, com
diff --git a/content/posts/revisao-de-codigo-extraindo-dados-do-site-aos-fatos.md b/content/posts/20220408-revisao-de-codigo-extraindo-dados-do-site-aos-fatos.md
similarity index 97%
rename from content/posts/revisao-de-codigo-extraindo-dados-do-site-aos-fatos.md
rename to content/posts/20220408-revisao-de-codigo-extraindo-dados-do-site-aos-fatos.md
index b40228b..18772e5 100644
--- a/content/posts/revisao-de-codigo-extraindo-dados-do-site-aos-fatos.md
+++ b/content/posts/20220408-revisao-de-codigo-extraindo-dados-do-site-aos-fatos.md
@@ -2,6 +2,7 @@
title: "Revisão de Código: Extraindo dados do site 'Aos Fatos'"
publishdate: 2022-04-08
tags: ["revisão de código", "scrapy", "raspagem de dados", "python", "live"]
+slug: revisao-de-codigo-extraindo-dados-do-site-aos-fatos
---
Algumas semanas atrás, fiz a revisão de um código para extrair informações de
diff --git a/content/posts/testando-multiplas-chamadas-de-um-mock.md b/content/posts/20221107-testando-multiplas-chamadas-de-um-mock.md
similarity index 98%
rename from content/posts/testando-multiplas-chamadas-de-um-mock.md
rename to content/posts/20221107-testando-multiplas-chamadas-de-um-mock.md
index c1568c4..5fc6f72 100644
--- a/content/posts/testando-multiplas-chamadas-de-um-mock.md
+++ b/content/posts/20221107-testando-multiplas-chamadas-de-um-mock.md
@@ -2,6 +2,7 @@
title: "Testando múltiplas chamadas de uma função com mocks"
publishdate: 2022-11-07
tags: ["python", "testes", "pytest"]
+slug: testando-multiplas-chamadas-de-um-mock
---
Em algumas situações durante o teste e alguma função, queremos confirmar
diff --git a/content/posts/sobre-perguntas-muito-vagas.md b/content/posts/20221111-sobre-perguntas-muito-vagas.md
similarity index 97%
rename from content/posts/sobre-perguntas-muito-vagas.md
rename to content/posts/20221111-sobre-perguntas-muito-vagas.md
index a041662..fb0e8d7 100644
--- a/content/posts/sobre-perguntas-muito-vagas.md
+++ b/content/posts/20221111-sobre-perguntas-muito-vagas.md
@@ -2,6 +2,7 @@
title: "Sobre perguntas muito vagas em grupos de discussão"
publishdate: 2022-11-11
tags: ["perguntas"]
+slug: sobre-perguntas-muito-vagas
---
Eu acompanho diversos grupos de tecnologia por email (hoje nem tanto),
diff --git a/content/posts/extending-django-user-profile-model.md b/content/posts/20230424-extending-django-user-profile-model.md
similarity index 99%
rename from content/posts/extending-django-user-profile-model.md
rename to content/posts/20230424-extending-django-user-profile-model.md
index 2a4d92f..e8f2cc0 100644
--- a/content/posts/extending-django-user-profile-model.md
+++ b/content/posts/20230424-extending-django-user-profile-model.md
@@ -2,7 +2,7 @@
title: "Extending built-in Django User with a Profile Model"
date: 2023-04-24T19:28:40-03:00
tags: ["django", "user", "python"]
-draft: false
+slug: extending-django-user-profile-model
---
The [user authentication](https://docs.djangoproject.com/en/4.2/topics/auth/#user-authentication-in-django) system provided by Django is extremely powerful
diff --git a/content/posts/20230501-extending-django-user-with-custom-model.md b/content/posts/20230501-extending-django-user-with-custom-model.md
new file mode 100644
index 0000000..72a7752
--- /dev/null
+++ b/content/posts/20230501-extending-django-user-with-custom-model.md
@@ -0,0 +1,237 @@
+---
+title: "Extending built-in Django User with a custom Model"
+date: 2023-05-01T19:28:40-03:00
+tags: ["django", "user", "python"]
+slug: extending-django-user-with-custom-model
+---
+
+The [user authentication](https://docs.djangoproject.com/en/4.2/topics/auth/#user-authentication-in-django) system provided by Django is extremely powerful
+and handles most of the authentication (Am I who I say I am?) and authorization (Am I
+authorized to do what I want to do?) needs of an web project. User accounts, groups
+and permissions, methods for handling passwords securely are part of this system.
+
+Generally, this is adequate for most projects; however, there are situations where it becomes necessary to modify the behavior of a **User** or alter how their data is stored in the database. It should be noted that modifying the authorization and/or authentication process of a **User** will not be covered in this post.
+
+Creating a user profile model is one solution to extend and modify the behavior of a **User**, as [discussed before]({{< ref "20230424-extending-django-user-profile-model" >}}), but that approach has some caveats that are solved with the use of a
+custom user model.
+
+# Custom User model
+
+We can tell Django which is the model that will replace the built-in
+`django.contrib.auth.models.User` model in the system. This is done by
+providing a value to `AUTH_USER_MODEL` in your project.
+
+{{}}
+# myproject/myproject/settings.py
+AUTH_USER_MODEL = "users.CustomUser"
+{{}}
+
+> Usually I create a `users` application to group all custom user related
+> code to keep everything in the same context
+
+It is highly recommended that you do this configuration at the beginning
+of the project, as after you have created your database tables, it will
+require you to fix your schema, moving data between tables and reapplying
+some migrations manually (see [#25313](https://code.djangoproject.com/ticket/25313)
+for an overview of the steps involved).
+
+Now we need to create our custom model.
+
+This new user model can handle different authentication and authorization
+schemes, can use different fields (e.g. email) to identify the user or
+any other requirement that is not satisfied using the default Django user
+model.
+
+## Adding new fields to default User model
+
+If the default **[User](https://docs.djangoproject.com/en/4.2/ref/contrib/auth/#django.contrib.auth.models.User)** model has everything we need and we want
+to add some extra profile fields keeping authentication and authorization as
+it is, create a custom model inheriting from `AbstractUser` would be enough.
+
+{{}}
+# myproject/users/models.py
+from django.contrib.auth.models import AbstractUser
+
+class CustomUser(AbstractUser):
+ date_of_birth = models.DateField(null=True)
+{{}}
+
+{{}}
+# myproject/myproject/settings.py
+AUTH_USER_MODEL = "users.CustomUser"
+{{}}
+
+As we will not create a new table to store the user related information, there is
+no need for additional database queries to retrieve related models. We also don't
+need to worry if a related model is created or not reducing the complexity of
+the system.
+
+## AbstractBaseUser
+
+If we want to use a different field as the identifier (other than `email`),
+use a different authorization system and/or having more control on what
+fields we have in our user model, a custom model inheriting from
+`AbstractBaseUser` is the choice.
+
+`AbstractBaseUser` is the core implementation of a **User**. It has a
+`password` field and methods to store and validate it securely. A
+`last_login` datetime field and everything else is up to us to provide.
+
+If using the default authentication backend, our model must have a single unique
+field that will be the identifier of our user such as email address, username or
+any other unique attribute.
+
+You configure that attribute using `USERNAME_FIELD` that defines what is
+the field that will uniquely identify the user.
+
+
+
+
+
+`EMAIL_FIELD`
+
+`REQUIRED_FIELDS`
+
+`is_active` is an attribute on `AbstractBaseUser` defaulting to `True`
+
+As an example, we will define a custom user that will use the email address
+as the identifier, has the date of birth as one required field can store
+the phone number and has a flag field in the database to indicate if the user
+is active or not.
+
+{{}}
+# myproject/users/models.py
+from django.contrib.auth.models import AbstractBaseUser
+
+class CustomUser(AbstractBaseUser):
+ USERNAME_FIELD = "email"
+ EMAIL_FIELD = "email"
+ REQUIRED_FIELDS = ["date_of_birth", ]
+
+ date_of_birth = models.EmailField(unique=True)
+ email = models.EmailField(unique=True)
+ is_active = models.BooleanField(default=True)
+ phone_number = models.CharField(max_length=16, blank=True)
+{{}}
+
+
+
+FROM DOCS Authentication backends provide an extensible system for when a username and password stored with the user model need to be authenticated against a different service than Django’s default.
+
+TODO: list all fields that are created with this
+
+Any other fields needs to be created.
+
+ is_active is a property set to True, but you can define if you want
+
+USERNAME_FIELD is needed identifier unique = True
+EMAIL_FIELD to specifi what is the email field
+REQUIRED_FIELDS fields required when createsuperuser
+
+If we want to use `email` as the identifier of an user,
+we need to set `USERNAME_FIELD` property
+
+{{}}
+# myproject/users/models.py
+class CustomUser(AbstractBaseUser):
+ USERNAME_FIELD = "email"
+
+ email = models.EmailField()
+{{}}
+
+One drawback is you need to specify a Custom Manager implementing
+two methods: `create_user` and `create_superuser`. This is required
+so we willll be able to run `python manage.py createsuperuser`
+and `python manage.py create-user`.
+
+If some fields (TODO list what fields) from `ABstractUser` are there, you can
+use the built-in UserManager
+FROM DOCS username, email, is_staff, is_active, is_superuser, last_login, and date_joined fields the same as Django’s default user, you can install Django’s UserManager
+
+{{}}
+# myproject/users/models.py
+class CustomUser(AbstractBaseUser):
+ USERNAME_FILED = "email"
+
+ email = models.EmailField()
+
+ objects = UserManager()
+{{}}
+
+If you don't want to use Django Admin (very unlikely), you're done,
+and you can create/manage your users and authentication backend will
+be able.
+
+However, if you want to use this custom user model with Django admin, there are
+some extra steps.
+
+We need some fields and methods:
+`is_staff` so you have access to django admin
+`is_active` inactive users can't access django admin
+
+to manage permissions to edit registered models
+`has_perm`
+`has_module_perms()`
+***we don't need to use the built-in permission system (see PermissionMixin)***
+
+And `UserCreationForm`< `UserChangeForm` and `PasswordResetForm` (if we don't have email field)
+needs to be customized so we can use that.
+
+Also we need a custom UserAdmin to use our custom forms.
+
+This is a lot of things, and sometimes difficult to remember. The docs
+are ok to describe the process, but IMO this should be much simpler :-P
+
+If by any chance you want to use django model permission, you can
+use PermissionMixin, so you have access to groups, etc (to be honest, I
+never saw anything using permission, but groups)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sometimes the username may not be the way you want to identify an user
+(an email or social number would be more suitable for your project)
+or we have different requirements for authorization and permission. In
+those cases creating a custom user model is a option.
+
+This has advatanges over the user of a user profile model and solve some
+of the caveats of that approach such as:
+
+- We won't need an extra database table to store your custom fields, so
+ there is no performance problems to access them;
+- As the table that we store the User data required for Django authentication
+ is the same, we don't need to bother if your profile fields will be available
+ or not
+
+When creating a custom user model, we have two different options
+If you are going to this path, you can create your custom user
+inheriting from two different classes:
+
+
+
+
+
+
+If using Django Admin, we also need to register this new model.
+
+{{}}
+# myproject/users/admin.py
+from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin
+from .models import CustomUser
+
+admin.site.register(CustomUser, UserAdmin)
+{{}}
\ No newline at end of file