github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/inscriptions/views.go (about)

     1  package inscriptions
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strconv"
     7  
     8  	rd "github.com/benoitkugler/goACVE/server/core/rawdata"
     9  
    10  	"github.com/benoitkugler/goACVE/server/core/utils/mails"
    11  
    12  	"github.com/benoitkugler/goACVE/server/shared"
    13  	"github.com/labstack/echo"
    14  )
    15  
    16  const (
    17  	UrlInscriptions   = "/inscription"
    18  	EndPointValidMail = "/valide-mail"
    19  )
    20  
    21  func isSimpleSejour(idS string, campsSimple map[int64]CampSimple) (out CampSimple, ok bool) {
    22  	id, err := strconv.ParseInt(idS, 10, 64)
    23  	if err != nil {
    24  		return out, false // par défaut on renvoie sur la page classique.
    25  	}
    26  	out, ok = campsSimple[id]
    27  	return
    28  }
    29  
    30  // FormulaireInscription affiche la page d'inscription,
    31  // qui dépend du camp éventuellement présent dans l'url.
    32  func (ct Controller) FormulaireInscription(c echo.Context) error {
    33  	data, err := ct.loadCamps()
    34  	_, campsSimple := data.triCamps()
    35  	if err != nil {
    36  		return shared.RedirectError(c, shared.FormatErr("La liste des camps n'a pu être résolue.", err))
    37  	}
    38  
    39  	// Formulaire complet par défaut
    40  	// les données nécessaires sont chargées par
    41  	// une requête client, gérée par `HandleLoadDataInscriptions`
    42  	meta := MetaInscription{IsComplet: true}
    43  
    44  	preselectedId := c.Param("preselected")
    45  	if campSimple, ok := isSimpleSejour(preselectedId, campsSimple); ok {
    46  		// Formulaire simplifié
    47  		meta = MetaInscription{IsComplet: false, LabelCampSimple: campSimple.Label.String()}
    48  	}
    49  	return shared.HtmlWithPayload(c, "server/static/bv/inscription.html", meta)
    50  }
    51  
    52  // HandleLoadDataInscriptions décode la préinscription et renvoie les
    53  // données des séjours.
    54  func (ct Controller) HandleLoadDataInscriptions(c echo.Context) error {
    55  	data, err := ct.loadCamps()
    56  	camps, _ := data.triCamps()
    57  	if err != nil {
    58  		return fmt.Errorf("La liste des camps n'a pu être résolue. <br/>Détails : <i>%s</i>", err)
    59  	}
    60  	preselectedId := c.QueryParam("preselected")
    61  
    62  	var initialInscription rd.Inscription
    63  	crypted := c.QueryParam("preinscription")
    64  	if crypted != "" {
    65  		initialInscription, err = ct.decodePreinscription(crypted)
    66  		if err != nil {
    67  			return err
    68  		}
    69  	}
    70  
    71  	initialInscription.PartageAdressesOK = true // OK par défaut
    72  
    73  	out := DataInscription{
    74  		Camps:              camps,
    75  		PreselectCamp:      preselectedId,
    76  		InitialInscription: initialInscription,
    77  	}
    78  	return c.JSON(200, out)
    79  }
    80  
    81  // CheckMail analyse l'adresse mail donnée et envoie
    82  // un lien d'inscription rapide aux personnes concernées.
    83  func (ct Controller) CheckMail(c echo.Context) error {
    84  	type out struct {
    85  		MailFound bool `json:"mail_found"`
    86  	}
    87  
    88  	mail := c.QueryParam("mail")
    89  	candidats, err := ct.chercheMail(mail)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	if mailFound := len(candidats.responsables) > 0; !mailFound {
    94  		return c.JSON(200, out{MailFound: false})
    95  	}
    96  
    97  	targets, err := ct.buildLiensPreinscription(candidats, c.QueryParam("origin"))
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	html, err := mails.NewPreinscription(mail, targets)
   103  	if err != nil {
   104  		return err
   105  	}
   106  	if err = mails.NewMailer(ct.SMTP).SendMail(mail, "[ACVE] Inscription rapide", html, nil, nil); err != nil {
   107  		return err
   108  	}
   109  
   110  	return c.JSON(200, out{MailFound: true})
   111  }
   112  
   113  // EnregistreInscriptionComplete vérifie l'inscription
   114  // et valide le mail (soit directement, soit par lien de confirmation)
   115  func (ct Controller) EnregistreInscriptionComplete(c echo.Context) error {
   116  	facture, responsable, mailValidated, err := ct.enregistreInscriptionComplete(c)
   117  	if err != nil {
   118  		return err
   119  	}
   120  
   121  	var out EnregistreInscriptionOut
   122  	out.CheckMail = !mailValidated
   123  	if mailValidated {
   124  		out.UrlEspacePerso = getUrlEspacePerso(facture, c.Request())
   125  	} else {
   126  		err = ct.verifieMail(c.Request().Host, facture, responsable)
   127  		if err != nil {
   128  			return err
   129  		}
   130  	}
   131  
   132  	return c.JSON(200, out)
   133  }
   134  
   135  // RejoueInscriptionComplete enregristre l'inscription mais ne vérifie pas le mail
   136  // Entre autre, aucun mail n'est envoyé.
   137  func (ct Controller) RejoueInscriptionComplete(c echo.Context) error {
   138  	_, _, _, err := ct.enregistreInscriptionComplete(c)
   139  	if err != nil {
   140  		return err
   141  	}
   142  	return c.JSON(200, "OK") // le client attend un corps JSON
   143  }
   144  
   145  func (ct Controller) enregistreInscriptionComplete(c echo.Context) (rd.Facture, rd.Personne, bool, error) {
   146  	var insc rd.Inscription
   147  	if err := c.Bind(&insc); err != nil {
   148  		return rd.Facture{}, rd.Personne{}, false, shared.FormatErr("Les paramètres d'inscriptions ne semblent pas valides.", err)
   149  	}
   150  
   151  	if err := valideInscription(insc); err != nil {
   152  		return rd.Facture{}, rd.Personne{}, false, err
   153  	}
   154  
   155  	if err := ct.decodeLienId(&insc.Responsable.Lienid); err != nil {
   156  		return rd.Facture{}, rd.Personne{}, false, shared.FormatErr("Le cryptage de la pré-identification du responsable semble incorrect !", err)
   157  	}
   158  
   159  	data, err := ct.loadCamps()
   160  	if err != nil {
   161  		return rd.Facture{}, rd.Personne{}, false, shared.FormatErr("La liste des camps ouverts aux inscriptions n'a pu être consultée.", err)
   162  	}
   163  	for index, part := range insc.Participants {
   164  		if _, in := data.camps[part.IdCamp]; !in {
   165  			return rd.Facture{}, rd.Personne{}, false, fmt.Errorf("Le camp numéro %d n'est pas ouvert aux inscriptions !", part.IdCamp)
   166  		}
   167  		if err := ct.decodeLienId(&insc.Participants[index].Lienid); err != nil {
   168  			return rd.Facture{}, rd.Personne{}, false, shared.FormatErr("Le cryptage de la pré-identification d'un participant semble incorrect !", err)
   169  		}
   170  	}
   171  
   172  	mailValidated := false
   173  	// on saute l'envoi d'un mail de vérification uniquement
   174  	// pour les responsables pré-identifié dont l'adresse n'a pas changé
   175  	if insc.Responsable.Lienid.Valid {
   176  		hasChanged, err := ct.hasMailChanged(insc.Responsable.Mail, insc.Responsable.Lienid)
   177  		if err != nil {
   178  			return rd.Facture{}, rd.Personne{}, false, err
   179  		}
   180  		mailValidated = !hasChanged
   181  	}
   182  
   183  	// on enregistre dans tous les cas l'inscription
   184  	facture, responsable, err := ct.enregistreInscription(insc, mailValidated, data)
   185  	return facture, responsable, mailValidated, err
   186  }
   187  
   188  func getUrlEspacePerso(facture rd.Facture, req *http.Request) string {
   189  	endpoint := facture.UrlEspacePerso("espace_perso/")
   190  	return shared.BuildUrl(req.Host, endpoint, map[string]string{"show-hint": "ok"})
   191  }
   192  
   193  // ValideMail décrypte l'id de la facture et
   194  // renvoie vers l'espace perso
   195  func (ct Controller) ValideMail(c echo.Context) error {
   196  	facture, err := ct.confirmeInscription(c.QueryParam("crypted-id"))
   197  	if err != nil {
   198  		return shared.RedirectError(c, err)
   199  	}
   200  	return c.Redirect(307, getUrlEspacePerso(facture, c.Request()))
   201  }
   202  
   203  // --------------- Formulaire simplifié -------------------------------------
   204  
   205  // EnregistreInscriptionSimple enregistre une inscription sur un séjour simplifié.
   206  func (ct Controller) EnregistreInscriptionSimple(c echo.Context) error {
   207  	var insc InscriptionSimple
   208  	if err := c.Bind(&insc); err != nil {
   209  		return shared.FormatErr("Les paramètres d'inscriptions ne semblent pas valides !", err)
   210  	}
   211  
   212  	data, err := ct.loadCamps()
   213  	_, campsSimple := data.triCamps()
   214  	if err != nil {
   215  		return shared.FormatErr("La liste des camps n'a pu être résolue.", err)
   216  	}
   217  
   218  	preselectedId := c.QueryParam("preselected")
   219  	campSimple, ok := isSimpleSejour(preselectedId, campsSimple)
   220  	if !ok {
   221  		return fmt.Errorf("Le séjour demandé ne propose pas d'inscription simplifiée.")
   222  	}
   223  
   224  	err = ct.enregistreInscriptionSimple(insc, campSimple)
   225  	if err != nil {
   226  		return err
   227  	}
   228  	return c.NoContent(200)
   229  }