Executando verificação de segurança...
25

Recriei o backend do tabnews com java e spring boot!

Começo esse conteúdo falando que o back-end não está em "nivel profissional", e a aplicação teve como foco estudar a linguagem. Agora, vou documentar o processo que tive para construir esse lado do servidor com java.

Pra começar, eu procurei pelo maior número de "variaveis" que eu pude encontrar no tabnews original. Para as variaveis do usuário, como por exemplo, nome, bio, ..., eu fiz o seguinte UserModel.

@Entity
@Data
public class UserModel {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String username;
    private String bio;
    private Integer tabcoins;
    private Integer tabcash;
    private String email;
    private String senha;
    @Enumerated
    private Features features;
}

Que logo mais pra frente, retoraria nas requisições do insomnia algo tipo isso

{
	"id": 1,
	"username": "cristian1",
	"bio": "pirir pororo piriru",
	"tabcoins": 0,
	"tabcash": 0,
	"email": "[email protected]",
	"senha": "123",
	"features": {
		"create_content": true,
		"create_session": true,
		"edit_content": true,
		"edit_user": true,
		"delete_content": true
	}
}
@Entity
@Data
public class UserModel {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String username;
    private String bio;
    private Integer tabcoins;
    private Integer tabcash;
    private String email;
    private String senha;
    @Enumerated
    private Features features;
}```

Para as Features

```java
@Embeddable
@Data
public class Features {
    private Boolean create_content;
    private Boolean create_session;
    private Boolean edit_content;
    private Boolean edit_user;
    private Boolean delete_content;
}

Agora o modelo das postagens

@Entity
@Data
public class PostModel {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private Integer parent_id;
    private Integer writer_id;
    private String text;
    private Calendar date;

    public void setWriter_id(Integer writer_id) {
        this.writer_id = writer_id;
    }

    public void setDate(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        this.date = calendar;
    }
}

Que no insmonia retornaria mais ou menos assim.

{
	"id": 2,
	"parent_id": 1,
	"writer_id": 123,
	"text": "ola mundo",
	"date": "2024-02-10T05:42:05.082+00:00"
 }

Terminando de mostrar as propriedes das postagens e dos usuarios, vamo fazer isso funcionar.

Aqui eu estou usando o ResponseEntity para retornar os codigos de BAD_REQUEST e ACCEPT

  public ResponseEntity<Object> register(@RequestBody UserModel newUser)

Aqui vamo chegar se o nome ou/e o email já estão em uso

 UserModel existingEmail = userRepository.findByEmail(newUser.getEmail());  
      UserModel existingName = userRepository.findByUsername(newUser.getUsername());

      if (existingEmail != null) {
          return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Email já cadastrado");
      }
      if (existingName != null) {
          return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Nome ja esta sendo ultilizado");
      }

Agora aqui vamos colocar os setter e salvar o usuario

 Features features = new Features();
      features.setCreate_content(true);
      features.setCreate_session(true);
      features.setDelete_content(true);
      features.setEdit_content(true);
      features.setEdit_user(true);

      newUser.setFeatures(features);
      newUser.setTabcash(0);
      newUser.setTabcoins(0);
      UserModel savedUser = userRepository.save(newUser);
  
      return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);

Pretendo mais para frente fazer com que as features sejam ativadas logo depois de verificar a conta, mas por agora já está bom.

Agora vamos mexer no PostController.
Pra começar vou procurar no userRepository, pelo criador do post

      Optional<UserModel> optionalUser = userRepository.findById(newPost.getWriter_id());

Aqui primeiramente vou checar se o usuario tem a feature de Criar Conteudo.
Logo depois vamos definir que o user_writer sera o user definidor por nós no insomnia

"writer_id": 1

Em seguida vamo setar a data em que o post foi criado.
E por último mas nao menos importante vamo checar se tem algum conteudo no Text

"text": "ola mundo",
 if(user.getFeatures().getCreate_content().equals(true)) {
            
            postRepository.save(newPost);
  
            newPost.setWriter_id(user.getId());
            newPost.setDate(calendar.getTime());
                  if(newPost.getText().equals(null)) {
                 
                    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Escreva um texto para postar");
                  } 
          }

      } else {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Usuario nao existe");

      }

Oque eu escrevi nessa postagem, é apenas um resumo do código, quem quiser ve-lo na sua forma atual, acesse o repositorio no gitub:https://github.com/CristianRsouza/Tabnews-Backend

Vale resaltar que o esse código e apenas um pequenisisimo resumo comparado com oque o filipe fez com o tabnews, e que e um estudo de um jovem de 15 anos que está tentando se adaptar a área.

Se algume tiver alguma dica ou ideia vou ficar muito feliz em ler seu comentario, muito obrigado por ler até aqui.

E pra caso não nos vermos mais, um bom dia, boa tarde e boa noite.

4

bacana man....
Uma dica, o padrão dos nomes das variáveis no java é camelCase...
acredito, que vc tenha usado com underline (por exemplo o -> parent_id), por causa do JSON.
Mas tem como vc usar annotation do jackson para contornar isso:

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class PaymentDTOResponse {
	
	private boolean 	success;
	private Long 		rowsCount;	
	private List<Payment> 	reportDetails;
}

nesse exemplo acima:

rowsCount é -> rows_count
e reportDetails é -> report_details no JSON ...

também tem como usar uma annotation a nível de atributo, e especificar o nome no JSON....
mas, eu não lembro qual é essa anotação do jackson rs

3
3

Parabéns, são projetos como esse que te diferencia dos demais. E pela sua idade você está se saindo muito bem. Comecei com a mesma idade e depois de 2 anos as oportunidades começaram a surgir. Um dica: Não caia no conto dos 6 meses

2

Primeiramente, parabéns pelo projeto! É exatamente esse tipo de iniciativa em buscar desafios diferentes e novas formas de pensar que te diferenciam!

Vou apenas te dar pequenas sugestões que podem te ajudar a melhorar um pouco o codigo, nesse trecho abaixo, você pode simplesmente omitir o .equals(true) já que o if já está recebendo um metodo que retorna um boolean, nesses casos o if apenas considera se o retorno do metodo é true:

if(user.getFeatures().getCreate_content().equals(true)) {
    ///
}

// Sugestão:
if(user.getFeatures().getCreate_content()) {
    ///
}

Uma outra opção que gosto de usar nesses cenarios é quebrar essas pequenas condições em métodos, pois isso facilita a reutilização e a criação de testes unitários, pode ocorrer de você ter que usar essa verificação do usuario poder criar conteudo em mais de uma classe para situações diversas, ter isso centralizado num metodo facilita e evita a reescrita de codigo:

// Sugestão:
if(isUserWithCreateContentPermission(user) {
    ///
}

private boolean isUserWithCreateContentPermission(User user) {
    return user.getFeatures().getCreate_content();
}
2

Misericórdia, tá com tempo!

Mandou mesmo um Javão da opressão, brincadeira.

Ficou muito bacana, pra ficar legal mesmo remove o Lombok e deixa só com o Java Record.

Abraços, tá de parabéns.

1

Que insano cara!!! Foi uma ótima ideia se inspirar na tabnews, definitivamente espetacular mano.
Obs: O link do projeto no github que cê colocou tá quebrado. Bons estudos maninho 🤓

1