Newer
Older
package importer
import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"regexp"
)
var uuid_re = regexp.MustCompile(`\A^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\z`)
func (app *App) Run(listing Listing) error {
// Check listing
for _, user := range listing {
if len(user.Email) == 0 || len(user.Fullname) == 0 || !uuid_re.MatchString(user.Uuid) {
return fmt.Errorf("Invalid user uuid:%q email:%q fullname:%q", user.Uuid, user.Email, user.Fullname)
}
}
// Send emails
for _, user := range listing {
err := func() error {
tx, err := app.Service.DB.Begin()
if err != nil {
return fmt.Errorf("Transaction error: %s", user.Uuid, err.Error())
}
userCount := 0
err = tx.QueryRowContext(app.Context, `SELECT COUNT(1) FROM users WHERE uuid=$1`, user.Uuid).Scan(&userCount)
if err != nil {
return fmt.Errorf("Error checking previous presence of user %s: %s", user.Uuid, err.Error())
}
if userCount == 1 {
// User is present, and has received an email already, skip
return fmt.Errorf("User already present")
}
if userCount != 0 {
return fmt.Errorf("Unique uuid violation for %s", user.Uuid)
}
userPrivateTokenRaw := make([]byte, 32)
n, err := rand.Read(userPrivateTokenRaw)
if err != nil {
return fmt.Errorf("Error making private token: %s", err)
}
if n != 32 {
return fmt.Errorf("Error making private token: %d != 32", n)
}
userPrivateToken := hex.EncodeToString(userPrivateTokenRaw)
userPublicTokenRaw := sha256.Sum256([]byte(userPrivateToken))
userPublicToken := hex.EncodeToString(userPublicTokenRaw[:])
_, err = tx.ExecContext(app.Context, `
INSERT INTO users(uuid, public_token, fullname, email, admin)
VALUES($1, $2, $3, $4, $5)
`, user.Uuid, userPublicToken, user.Fullname, user.Email, user.Admin)
if err != nil {
tx.Rollback()
return fmt.Errorf("Error inserting user: %s", err)
}
body := fmt.Sprintf(EMAIL_TOKEN_BODY, user.Fullname, userPrivateToken)
err = app.Service.Email.Send(user.Email, EMAIL_TOKEN_SUBJECT, body)
if err != nil {
return fmt.Errorf("Error sending email: %s", err)
}
err = tx.Commit()
if err != nil {
return fmt.Errorf("Error committing transation: %s", err)
}
return nil
}()
fmt.Fprintf(os.Stderr, "Email error for %s (%s): %s\n", user.Fullname, user.Uuid, err.Error())
} else {
fmt.Fprintf(os.Stdout, "Email sent for %s (%s)\n", user.Fullname, user.Uuid)
const EMAIL_TOKEN_SUBJECT = "AG Electrolab - Votre acces au vote en ligne"
Vous recevez ce mail car vous êtes membre actif de l'association Electrolab. De par les statuts de l'association, vous disposez du droit de vote à l'assemblée générale qui aura lieu le 19/06/2021 à 15h.
L'assemblée générale ayant lieu cette année à distance du fait des risques sanitaires liés à l'épidémie de Covid 19, le vote se fera par voie électronique.
Vous pourrez suivre la présentation à cette adresse: https://www.youtube.com/user/ElectrolabFr
Si vous vous inscrivez à la chaîne et que vous cliquez sur la cloche, vous serez prévenu au moment du lancement du live.
Sinon, rendez-vous à partir de 14h45, le live s’affichera dès l’accueil de notre chaîne en haut de la liste des vidéos.
Pour intervenir ou poser des questions, il faudra soit écrire dans le chat de la page Youtube en lien ci-dessus, soit écrire dans le chat de l'association : https://chat.electrolab.fr/electrolab/channels/ag2021 (si par exemple vous n’avez pas de compte youtube ou si vous préférez passer par ce canal). Des modérateurs seront présents pour lire les messages sur ces deux canaux et transmettre les questions aux intervenants.
Le présent courrier électronique contient un code unique qui vous permettra de voter sur les différents points de cette assemblée générale. Ce code unique est personnel et ne permet de voter qu'une seule fois.
La procuration du vote se fait en transmettant le code unique à la personne à qui on cède son pouvoir.
Pour voter, rendez-vous à l'adresse suivante :
https://vote.electrolab.fr/events/Electrolab-AG-2021/votes?private_token=%s
Si vous avez des questions, n'hésitez pas à nous écrire à contact@electrolab.fr, ou sur le chat de l'association https://chat.electrolab.fr