completed test endpoint

main
nilo 2025-02-09 19:12:00 -03:00
parent e4d1fb072a
commit 00f31d92ce
9 changed files with 467 additions and 17 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
api
api.exe
*.exe
.env

View File

@ -1,10 +1,9 @@
package controllers
import (
"api/database"
"api/globals"
"api/models"
"api/services"
"api/utils"
"fmt"
"github.com/gofiber/fiber/v2"
@ -13,7 +12,7 @@ import (
func GetUsers(c *fiber.Ctx) error {
var users []models.SystemUser
database.DB.Find(&users)
globals.DB.Find(&users)
return c.JSON(users)
}
@ -21,7 +20,7 @@ func GetUsers(c *fiber.Ctx) error {
func GetGroups(c *fiber.Ctx) error {
var groups []models.SystemGroup
database.DB.Find(&groups)
globals.DB.Find(&groups)
return c.JSON(groups)
}
@ -41,7 +40,5 @@ func CreateUser(c *fiber.Ctx) error {
fmt.Println("inexistent user")
}
utils.SendEmail(email)
return c.JSON(user)
}

View File

@ -1,12 +1,16 @@
package controllers
import (
"api/globals"
"api/models"
"api/services"
"api/utils"
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
"github.com/gofiber/fiber/v2"
)
@ -126,9 +130,126 @@ func OnPubStop(c *fiber.Ctx) error {
return c.SendString("On_Pub_Stop: " + string(c.Body()))
}
type ResponseTest struct {
Data DataTest `json:"data"`
}
type DataTest struct {
CNPJ string `json:"cnpj"`
Email string `json:"email"`
Name string `json:"name"`
}
func WixTest(c *fiber.Ctx) error {
log.Println(string(c.Body()))
return c.SendString("On Test: " + string(c.Body()))
// Get the data from the callback
var r ResponseTest
if err := c.BodyParser(&r); err != nil {
return err
}
// Pass the data to variables
cnpj := strings.TrimSpace(r.Data.CNPJ)
name := strings.TrimSpace(r.Data.Name)
email := strings.TrimSpace(r.Data.Email)
// Check if it is a valid CNPJ
if !utils.IsValid(cnpj) {
utils.SendTestEmail(email, name, "Foi informado um CNPJ inválido")
return c.SendString("CNPJ Inválido")
}
// Formats the CNPJ
cnpjf := fmt.Sprintf("%s.%s.%s/%s-%s",
cnpj[:2],
cnpj[2:5],
cnpj[5:8],
cnpj[8:12],
cnpj[12:])
// Let's see if it is a real CNPJ
log.Printf("CNPJ %s [%s] requisitou um teste usando o email %s (%s)\n", cnpj, cnpjf, name, email)
empresa := utils.GetEmpresa(cnpj)
if empresa.Situacao != "ATIVA" {
utils.SendTestEmail(email, name, "Foi informado um CNPJ pertencente à uma empresa inativa")
return c.SendString("Empresa inativa")
}
// Let's see if its already on database
customer := services.GetCustomerByCNPJ(cnpjf)
user := services.GetUserByEmail(email)
var userdb models.SystemUser
var customerdb models.Customer
if user.ID == 0 {
// Email not in database. Let's insert it
userdb = models.SystemUser{
Email: email,
}
err := globals.DB.Create(&userdb)
if err != nil {
log.Printf("Cannot create test user: %v\n", err)
}
user.ID = userdb.ID
}
if customer.ID == 0 {
// Inexistent customer; insert it into database
customerwww := utils.GetEmpresa(cnpj)
customerdb = models.Customer{
CNPJ: customerwww.CNPJ,
Nome: customerwww.Nome,
NomeFantasia: customerwww.Nome,
Tipo: customerwww.Tipo,
Porte: customerwww.Porte,
Situacao: customerwww.Situacao,
Abertura: customerwww.Abertura,
NaturezaJuridica: customerwww.NaturezaJuridica,
Logradouro: customerwww.Logradouro,
Numero: customerwww.Numero,
Complemento: customerwww.Complemento,
Municipio: customerwww.Municipio,
Bairro: customerwww.Bairro,
UF: customerwww.UF,
CEP: customerwww.CEP,
UserID: user.ID,
}
err := globals.DB.Create(&customerdb)
if err.Error != nil {
log.Printf("Cannot create test user: %v\n", err)
}
// Now let's create the customer channel
opts := utils.GenerationOptions{
Length: 10,
}
tkey, _ := utils.GenerateString(opts)
channel := models.Channel{
Name: cnpj + "-01",
TransmissionKey: tkey,
CustomerID: customerdb.UserID,
ServerID: 1,
}
err = globals.DB.Create(&channel)
if err.Error != nil {
log.Printf("Cannot create test channel: %v\n", err)
}
// Finally, send an email
utils.SendTestEmailApproval(email, name, "tkey", "url")
}
return c.SendString("On Test: " + empresa.Nome)
}
func WixIntegration(c *fiber.Ctx) error {

View File

@ -2,6 +2,7 @@ package database
import (
"api/config"
"api/globals"
"fmt"
"log"
@ -9,9 +10,6 @@ import (
"gorm.io/gorm"
)
// Our database
var DB *gorm.DB
// ConnectDB - returns a pointer to a new database connection
func ConnectDB() error {
// var erre error
@ -40,7 +38,7 @@ func ConnectDB() error {
return err
}
DB = db
globals.DB = db
return nil
}

View File

@ -1,6 +1,10 @@
package globals
import "gorm.io/gorm"
var (
API_VERSION = ""
API_RELEASE = ""
DB *gorm.DB
)

60
models/externals.go Normal file
View File

@ -0,0 +1,60 @@
package models
type Empresa struct {
Abertura string `json:"abertura"`
Situacao string `json:"situacao"`
Tipo string `json:"tipo"`
Nome string `json:"nome"`
Porte string `json:"porte"`
NaturezaJuridica string `json:"natureza_juridica"`
AtividadePrincipal []Atividade `json:"atividade_principal"`
AtividadesSecundarias []Atividade `json:"atividades_secundarias"`
Logradouro string `json:"logradouro"`
Numero string `json:"numero"`
Complemento string `json:"complemento"`
Municipio string `json:"municipio"`
Bairro string `json:"bairro"`
UF string `json:"uf"`
CEP string `json:"cep"`
Email string `json:"email"`
Telefone string `json:"telefone"`
DataSituacao string `json:"data_situacao"`
CNPJ string `json:"cnpj"`
UltimaAtualizacao string `json:"ultima_atualizacao"`
Status string `json:"status"`
Fantasia string `json:"fantasia"`
EFR string `json:"efr"`
MotivoSituacao string `json:"motivo_situacao"`
SituacaoEspecial string `json:"situacao_especial"`
DataSituacaoEspecial string `json:"data_situacao_especial"`
CapitalSocial string `json:"capital_social"`
QSA []interface{} `json:"qsa"`
Simples Simples `json:"simples"`
Simei Simei `json:"simei"`
Extra map[string]interface{} `json:"extra"`
Billing Billing `json:"billing"`
}
type Atividade struct {
Code string `json:"code"`
Text string `json:"text"`
}
type Simples struct {
Optante bool `json:"optante"`
DataOpcao string `json:"data_opcao"`
DataExclusao string `json:"data_exclusao"`
UltimaAtualizacao string `json:"ultima_atualizacao"`
}
type Simei struct {
Optante bool `json:"optante"`
DataOpcao string `json:"data_opcao"`
DataExclusao string `json:"data_exclusao"`
UltimaAtualizacao string `json:"ultima_atualizacao"`
}
type Billing struct {
Free bool `json:"free"`
Database bool `json:"database"`
}

View File

@ -1,5 +1,8 @@
package models
// ====================================================================
// Adianti tables
type SystemGroup struct {
ID int `gorm:"primaryKey"`
Name string `gorm:"size:256"`
@ -111,3 +114,41 @@ type SystemProgramMethodRole struct {
SystemProgram SystemProgram `gorm:"foreignKey:SystemProgramID"`
SystemRole SystemRole `gorm:"foreignKey:SystemRoleID"`
}
// ====================================================================
// PCast tables
type Customer struct {
ID int `gorm:"primaryKey;autoIncrement"`
CNPJ string `gorm:"unique;not null"`
Nome string `gorm:"not null"`
NomeFantasia string `gorm:"not null"`
Tipo string `gorm:"not null"`
Porte string `gorm:"not null"`
Situacao string `gorm:"not null"`
Abertura string `gorm:"not null"`
NaturezaJuridica string `gorm:"not null"`
Logradouro string `gorm:"not null"`
Numero string `gorm:"not null"`
Complemento string `gorm:"not null"`
Municipio string `gorm:"not null"`
Bairro string `gorm:"not null"`
UF string `gorm:"not null"`
CEP string `gorm:"not null"`
UserID int `gorm:"not null"`
User SystemUser `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}
type Email struct {
ID int
Name string
EmailText string
}
type Channel struct {
ID int
Name string
TransmissionKey string
CustomerID int
ServerID int
}

View File

@ -1,14 +1,22 @@
package services
import (
"api/database"
"api/globals"
"api/models"
)
func GetUserByEmail(email string) models.SystemUser {
var user models.SystemUser
database.DB.Where("email = ?", email).Find(&user)
globals.DB.Where("email = ?", email).Find(&user)
return user
}
func GetCustomerByCNPJ(cnpj string) models.Customer {
var user models.Customer
globals.DB.Where("cnpj = ?", cnpj).Find(&user)
return user
}

View File

@ -1,15 +1,106 @@
package utils
import (
"api/globals"
"api/models"
"crypto/rand"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"math/big"
"net/http"
"strconv"
"strings"
"gopkg.in/gomail.v2"
"golang.org/x/crypto/bcrypt"
)
type Charset string
const (
Alphanumeric = Charset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
Lowercase = Charset("abcdefghijklmnopqrstuvwxyz")
Uppercase = Charset("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
Numeric = Charset("0123456789")
SpecialCharacters = Charset("!@#$%^&*()-_=+[]{}|;:'<>,.?/~")
)
var (
GenerateString = generateString
)
type GenerationOptions struct {
Length int
DisableNumeric bool
DisableLowercase bool
DisableUppercase bool
EnableSpecialCharacter bool
CustomCharset Charset
}
// generateStringFromCharset generates a random string from a given charset
func generateStringFromCharset(charset Charset, length int) (string, error) {
if len(charset) == 0 || length <= 0 {
return "", errors.New("invalid charset or length")
}
result := make([]byte, length)
charsetLen := big.NewInt(int64(len(charset)))
for i := 0; i < length; i++ {
randomIndex, err := rand.Int(rand.Reader, charsetLen)
if err != nil {
return "", err
}
result[i] = charset[randomIndex.Int64()]
}
return string(result), nil
}
// modifyCharset modifies the charset based on the options
func modifyCharset(opts GenerationOptions, charsetMappings map[string]Charset, charset Charset) Charset {
if opts.DisableNumeric {
charset = Charset(strings.ReplaceAll(string(charset), string(charsetMappings["numeric"]), ""))
}
if opts.DisableLowercase {
charset = Charset(strings.ReplaceAll(string(charset), string(charsetMappings["lowercase"]), ""))
}
if opts.DisableUppercase {
charset = Charset(strings.ReplaceAll(string(charset), string(charsetMappings["uppercase"]), ""))
}
if opts.EnableSpecialCharacter {
charset += charsetMappings["specialCharater"]
}
return charset
}
// generateString generates a random string based on the options
func generateString(opts GenerationOptions) (string, error) {
charsetMappings := map[string]Charset{
"numeric": Numeric,
"lowercase": Lowercase,
"uppercase": Uppercase,
"specialCharater": SpecialCharacters,
}
charset := Alphanumeric
if opts.CustomCharset != "" {
charset = opts.CustomCharset
} else {
charset = modifyCharset(opts, charsetMappings, charset)
}
if len(charset) == 0 {
return "", errors.New("resulting charset is empty. adjust your options")
}
return generateStringFromCharset(charset, opts.Length)
}
func HashPassword(password string) ([]byte, error) {
return bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
}
@ -22,12 +113,141 @@ func PrettyPrintJson(data interface{}) {
log.Println(string(b))
}
func SendEmail(email string) {
// IsValid checks if a CNPJ is valid
func IsValid(cnpj string) bool {
// Remove non-numeric characters
cnpj = removeNonDigits(cnpj)
if len(cnpj) != 14 || allDigitsEqual(cnpj) {
return false
}
// Validate check digits
return checkCNPJCheckDigits(cnpj)
}
// removeNonDigits removes all non-numeric characters from a string
func removeNonDigits(input string) string {
var result strings.Builder
for _, r := range input {
if r >= '0' && r <= '9' {
result.WriteRune(r)
}
}
return result.String()
}
// allDigitsEqual checks if all characters in a string are the same
func allDigitsEqual(cnpj string) bool {
for i := 1; i < len(cnpj); i++ {
if cnpj[i] != cnpj[0] {
return false
}
}
return true
}
// checkCNPJCheckDigits validates the two check digits of a CNPJ
func checkCNPJCheckDigits(cnpj string) bool {
weights1 := []int{5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2}
weights2 := []int{6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2}
// Calculate first check digit
digit1 := calculateCheckDigit(cnpj[:12], weights1)
// Calculate second check digit
digit2 := calculateCheckDigit(cnpj[:13], weights2)
// Check if the calculated digits match the actual ones
return cnpj[12] == digit1 && cnpj[13] == digit2
}
// calculateCheckDigit calculates a single check digit for a given CNPJ slice and weight array
func calculateCheckDigit(numbers string, weights []int) byte {
sum := 0
for i, weight := range weights {
num, _ := strconv.Atoi(string(numbers[i]))
sum += num * weight
}
remainder := sum % 11
if remainder < 2 {
return '0'
}
return byte('0' + (11 - remainder))
}
func GetEmpresa(cnpj string) models.Empresa {
url := "https://receitaws.com.br/v1/cnpj/" + cnpj
// Call the external URL
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error fetching data:", err)
return models.Empresa{}
}
defer resp.Body.Close()
// Read the response body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response:", err)
return models.Empresa{}
}
// Parse the JSON response into the struct
var response models.Empresa
err = json.Unmarshal(body, &response)
if err != nil {
fmt.Println("Error parsing JSON:", err)
return models.Empresa{}
}
// Print the parsed response
return response
}
func SendTestEmail(email, name, message string) {
var emaildb models.Email
globals.DB.First(&emaildb, "name = ?", "TESTE-ERRO")
errText := emaildb.EmailText
errText = strings.Replace(errText, "[[ERRO]]", message, -1)
errText = strings.Replace(errText, "[[NOME]]", name, -1)
m := gomail.NewMessage()
m.SetHeader("From", "suporte@pcastlive.com")
m.SetHeader("To", email)
m.SetHeader("Subject", "Test Email from Go")
m.SetBody("text/plain", "This is a test email sent from a Go application.")
m.SetHeader("Subject", "Solicitação de teste da plataforma PCastLive")
m.SetBody("text/html", errText)
d := gomail.NewDialer("smtp.kinghost.net", 465, "suporte@pcastlive.com", "@407Smc837")
if err := d.DialAndSend(m); err != nil {
panic(err)
}
}
func SendTestEmailApproval(email, name, transmkey, url string) {
var emaildb models.Email
globals.DB.First(&emaildb, "name = ?", "TESTE-APROVADO")
errText := emaildb.EmailText
errText = strings.Replace(errText, "[[NOME]]", name, -1)
errText = strings.Replace(errText, "[[TRANSMKEY]]", transmkey, -1)
errText = strings.Replace(errText, "[[URL]]", url, -1)
m := gomail.NewMessage()
m.SetHeader("From", "suporte@pcastlive.com")
m.SetHeader("To", email)
m.SetHeader("Subject", "Solicitação de teste da plataforma PCastLive")
m.SetBody("text/html", errText)
d := gomail.NewDialer("smtp.kinghost.net", 465, "suporte@pcastlive.com", "@407Smc837")