A Account API é responsável pela gestão das contas de usuário no domínio store. Ela realiza operações de cadastro, consulta, atualização e exclusão de contas, servindo como base para autenticação e relacionamento entre os demais serviços (auth, order, product, etc.).
Trusted layer e segurança
Toda requisição externa entra pelo gateway. As rotas /qccount/** são protegidas: é obrigatório enviar Authorization: Bearer <jwt>.
Visão geral
Interface (account): define o contrato (DTOs e Feign) consumido por outros módulos/fronts.
Service (account-service): implementação REST, regras de negócio, persistência (JPA), e migrações (Flyway).
packagestore.account;importjava.util.List;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.HttpStatus;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.server.ResponseStatusException;importorg.springframework.web.servlet.support.ServletUriComponentsBuilder;@RestControllerpublicclassAccountResourceimplementsAccountController{@AutowiredprivateAccountServiceaccountService;@OverridepublicResponseEntity<AccountOut>create(AccountInin){// parser AccountIn to AccountAccountaccount=AccountParser.to(in);Accountsaved=accountService.create(account);// parser Account to AccountOut and build to// HATEAOS standardreturnResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(saved.id()).toUri()).body(AccountParser.to(saved));}@OverridepublicResponseEntity<AccountOut>findById(Stringid){returnResponseEntity.ok(AccountParser.to(accountService.findById(id)));}@OverridepublicResponseEntity<AccountOut>findByEmailAndPassword(AccountInin){returnResponseEntity.ok().body(AccountParser.to(accountService.findByEmailAndPassword(in.email(),in.password())));}@OverridepublicResponseEntity<List<AccountOut>>findAll(){returnResponseEntity.ok().body(AccountParser.to(accountService.findAll()));}@OverridepublicResponseEntity<Void>delete(Stringid){returnResponseEntity.noContent().build();}@OverridepublicResponseEntity<AccountOut>whoAmI(StringidAccount){finalAccountfound=accountService.findById(idAccount);if(found==null){thrownewResponseStatusException(HttpStatus.NOT_FOUND);}returnResponseEntity.ok(AccountParser.to(found));}}
packagestore.account;importjava.nio.charset.StandardCharsets;importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmException;importjava.util.Base64;importjava.util.List;importjava.util.stream.StreamSupport;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.HttpStatus;importorg.springframework.stereotype.Service;importorg.springframework.web.server.ResponseStatusException;@ServicepublicclassAccountService{privateLoggerlooger=LoggerFactory.getLogger(AccountService.class);@AutowiredprivateAccountRepositoryaccountRepository;publicAccountcreate(Accountaccount){if(null==account.password()){thrownewResponseStatusException(HttpStatus.BAD_REQUEST,"Password is mandatory!");}// clean special caractersaccount.password(account.password().trim());if(account.password().length()<4){thrownewResponseStatusException(HttpStatus.BAD_REQUEST,"Password is too short!");}if(null==account.email()){thrownewResponseStatusException(HttpStatus.BAD_REQUEST,"Email is mandatory!");}if(accountRepository.findByEmail(account.email())!=null)thrownewResponseStatusException(HttpStatus.BAD_REQUEST,"Email already have been registered!");account.sha256(hash(account.password()));returnaccountRepository.save(newAccountModel(account)).to();}publicList<Account>findAll(){returnStreamSupport.stream(accountRepository.findAll().spliterator(),false).map(AccountModel::to).toList();}publicAccountfindById(Stringid){returnaccountRepository.findById(id).map(AccountModel::to).orElse(null);}publicAccountfindByEmailAndPassword(Stringemail,Stringpassword){Stringsha256=hash(password);returnaccountRepository.findByEmailAndSha256(email,sha256).map(AccountModel::to).orElse(null);}publicvoiddelete(Stringid){accountRepository.delete(newAccountModel().id(id));}privateStringhash(Stringpass){try{MessageDigestdigest=MessageDigest.getInstance("SHA-256");byte[]encodedHash=digest.digest(pass.getBytes(StandardCharsets.UTF_8));returnBase64.getEncoder().encodeToString(encodedHash);}catch(NoSuchAlgorithmExceptione){thrownewResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR,e.getMessage(),e);}}}