mailing list: ability to add guest users
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
670123df38
commit
f77697f501
6 changed files with 139 additions and 30 deletions
62
admin.go
62
admin.go
|
@ -164,6 +164,7 @@ type AdminMailingListTplData struct {
|
||||||
MailingList *ldap.Entry
|
MailingList *ldap.Entry
|
||||||
Members EntryList
|
Members EntryList
|
||||||
PossibleNewMembers EntryList
|
PossibleNewMembers EntryList
|
||||||
|
AllowGuest bool
|
||||||
|
|
||||||
Error string
|
Error string
|
||||||
Success bool
|
Success bool
|
||||||
|
@ -198,6 +199,60 @@ func handleAdminMailingList(w http.ResponseWriter, r *http.Request) {
|
||||||
} else {
|
} else {
|
||||||
dSuccess = true
|
dSuccess = true
|
||||||
}
|
}
|
||||||
|
} else if action == "add-external" {
|
||||||
|
mail := strings.Join(r.Form["mail"], "")
|
||||||
|
displayname := strings.Join(r.Form["displayname"], "")
|
||||||
|
|
||||||
|
searchRequest := ldap.NewSearchRequest(
|
||||||
|
config.UserBaseDN,
|
||||||
|
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||||
|
fmt.Sprintf("(&(objectClass=organizationalPerson)(mail=%s))", mail),
|
||||||
|
[]string{"dn", "displayname", "mail"},
|
||||||
|
nil)
|
||||||
|
sr, err := login.conn.Search(searchRequest)
|
||||||
|
if err != nil {
|
||||||
|
dError = err.Error()
|
||||||
|
} else {
|
||||||
|
if len(sr.Entries) == 0 {
|
||||||
|
if config.MailingGuestsBaseDN != "" {
|
||||||
|
guestDn := fmt.Sprintf("%s=%s,%s", config.UserNameAttr, mail, config.MailingGuestsBaseDN)
|
||||||
|
req := ldap.NewAddRequest(guestDn, nil)
|
||||||
|
req.Attribute("objectclass", []string{"inetOrgPerson", "organizationalPerson", "person", "top"})
|
||||||
|
req.Attribute("mail", []string{mail})
|
||||||
|
if displayname != "" {
|
||||||
|
req.Attribute("displayname", []string{displayname})
|
||||||
|
}
|
||||||
|
err := login.conn.Add(req)
|
||||||
|
if err != nil {
|
||||||
|
dError = err.Error()
|
||||||
|
} else {
|
||||||
|
modify_request := ldap.NewModifyRequest(dn, nil)
|
||||||
|
modify_request.Add("member", []string{guestDn})
|
||||||
|
|
||||||
|
err := login.conn.Modify(modify_request)
|
||||||
|
if err != nil {
|
||||||
|
dError = err.Error()
|
||||||
|
} else {
|
||||||
|
dSuccess = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dError = "Adding guest users not supported, the user must already have an LDAP account."
|
||||||
|
}
|
||||||
|
} else if len(sr.Entries) == 1 {
|
||||||
|
modify_request := ldap.NewModifyRequest(dn, nil)
|
||||||
|
modify_request.Add("member", []string{sr.Entries[0].DN})
|
||||||
|
|
||||||
|
err := login.conn.Modify(modify_request)
|
||||||
|
if err != nil {
|
||||||
|
dError = err.Error()
|
||||||
|
} else {
|
||||||
|
dSuccess = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dError = fmt.Sprintf("Multiple users exist with email address %s", mail)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if action == "delete-member" {
|
} else if action == "delete-member" {
|
||||||
member := strings.Join(r.Form["member"], "")
|
member := strings.Join(r.Form["member"], "")
|
||||||
modify_request := ldap.NewModifyRequest(dn, nil)
|
modify_request := ldap.NewModifyRequest(dn, nil)
|
||||||
|
@ -217,7 +272,7 @@ func handleAdminMailingList(w http.ResponseWriter, r *http.Request) {
|
||||||
dn,
|
dn,
|
||||||
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
||||||
fmt.Sprintf("(objectclass=groupOfNames)"),
|
fmt.Sprintf("(objectclass=groupOfNames)"),
|
||||||
[]string{"dn", config.MailingNameAttr, "member"},
|
[]string{"dn", config.MailingNameAttr, "member", "description"},
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
sr, err := login.conn.Search(searchRequest)
|
sr, err := login.conn.Search(searchRequest)
|
||||||
|
@ -274,6 +329,7 @@ func handleAdminMailingList(w http.ResponseWriter, r *http.Request) {
|
||||||
MailingList: ml,
|
MailingList: ml,
|
||||||
Members: members,
|
Members: members,
|
||||||
PossibleNewMembers: possibleNewMembers,
|
PossibleNewMembers: possibleNewMembers,
|
||||||
|
AllowGuest: config.MailingGuestsBaseDN != "",
|
||||||
|
|
||||||
Error: dError,
|
Error: dError,
|
||||||
Success: dSuccess,
|
Success: dSuccess,
|
||||||
|
@ -785,7 +841,7 @@ func handleAdminCreate(w http.ResponseWriter, r *http.Request) {
|
||||||
data.IdType = config.UserNameAttr
|
data.IdType = config.UserNameAttr
|
||||||
data.StructuralObjectClass = "inetOrgPerson"
|
data.StructuralObjectClass = "inetOrgPerson"
|
||||||
data.ObjectClass = "inetOrgPerson\norganizationalPerson\nperson\ntop"
|
data.ObjectClass = "inetOrgPerson\norganizationalPerson\nperson\ntop"
|
||||||
} else if template == "group" {
|
} else if template == "group" || template == "ml" {
|
||||||
data.IdType = config.UserNameAttr
|
data.IdType = config.UserNameAttr
|
||||||
data.StructuralObjectClass = "groupOfNames"
|
data.StructuralObjectClass = "groupOfNames"
|
||||||
data.ObjectClass = "groupOfNames\ntop"
|
data.ObjectClass = "groupOfNames\ntop"
|
||||||
|
@ -842,7 +898,7 @@ func handleAdminCreate(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data.Error = err.Error()
|
data.Error = err.Error()
|
||||||
} else {
|
} else {
|
||||||
if super_dn == config.MailingBaseDN && data.IdType == config.MailingNameAttr {
|
if template == "ml" {
|
||||||
http.Redirect(w, r, "/admin/mailing/"+data.IdValue, http.StatusFound)
|
http.Redirect(w, r, "/admin/mailing/"+data.IdValue, http.StatusFound)
|
||||||
} else {
|
} else {
|
||||||
http.Redirect(w, r, "/admin/ldap/"+dn, http.StatusFound)
|
http.Redirect(w, r, "/admin/ldap/"+dn, http.StatusFound)
|
||||||
|
|
16
main.go
16
main.go
|
@ -23,13 +23,15 @@ type ConfigFile struct {
|
||||||
LdapServerAddr string `json:"ldap_server_addr"`
|
LdapServerAddr string `json:"ldap_server_addr"`
|
||||||
LdapTLS bool `json:"ldap_tls"`
|
LdapTLS bool `json:"ldap_tls"`
|
||||||
|
|
||||||
BaseDN string `json:"base_dn"`
|
BaseDN string `json:"base_dn"`
|
||||||
UserBaseDN string `json:"user_base_dn"`
|
UserBaseDN string `json:"user_base_dn"`
|
||||||
UserNameAttr string `json:"user_name_attr"`
|
UserNameAttr string `json:"user_name_attr"`
|
||||||
GroupBaseDN string `json:"group_base_dn"`
|
GroupBaseDN string `json:"group_base_dn"`
|
||||||
GroupNameAttr string `json:"group_name_attr"`
|
GroupNameAttr string `json:"group_name_attr"`
|
||||||
MailingBaseDN string `json:"mailing_list_base_dn"`
|
|
||||||
MailingNameAttr string `json:"mailing_list_name_attr"`
|
MailingBaseDN string `json:"mailing_list_base_dn"`
|
||||||
|
MailingNameAttr string `json:"mailing_list_name_attr"`
|
||||||
|
MailingGuestsBaseDN string `json:"mailing_list_guest_user_base_dn"`
|
||||||
|
|
||||||
InvitationBaseDN string `json:"invitation_base_dn"`
|
InvitationBaseDN string `json:"invitation_base_dn"`
|
||||||
InvitationNameAttr string `json:"invitation_name_attr"`
|
InvitationNameAttr string `json:"invitation_name_attr"`
|
||||||
|
|
|
@ -30,33 +30,40 @@
|
||||||
<input type="text" disabled="true" class="form-control" value="{{ .SuperDN }}" />
|
<input type="text" disabled="true" class="form-control" value="{{ .SuperDN }}" />
|
||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
|
{{if eq .Template "ml"}}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="idvalue">Adresse complète de la mailing list :</label>
|
||||||
|
<input type="text" id="idvalue" name="idvalue" class="form-control" value="{{ .IdValue }}" placeholder="example@deuxfleurs.fr" />
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="idvalue">Identifiant :</label>
|
||||||
|
<input type="text" id="idvalue" name="idvalue" class="form-control" value="{{ .IdValue }}" />
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="idvalue">Identifiant:</label>
|
<label for="idtype">Type d'identifiant :</label>
|
||||||
<input type="text" id="idvalue" name="idvalue" class="form-control" value="{{ .IdValue }}" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="idtype">Type d'identifiant:</label>
|
|
||||||
<input type="text" {{if .Template}}disabled="disabled"{{end}} id="idtype" name="idtype" class="form-control" value="{{ .IdType }}" />
|
<input type="text" {{if .Template}}disabled="disabled"{{end}} id="idtype" name="idtype" class="form-control" value="{{ .IdType }}" />
|
||||||
</div>
|
</div>
|
||||||
{{ if eq .Template "user" }}
|
{{ if eq .Template "user" }}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="displayname">Nom:</label>
|
<label for="displayname">Nom :</label>
|
||||||
<input type="text" id="displayname" name="displayname" class="form-control" value="{{ .DisplayName }}" />
|
<input type="text" id="displayname" name="displayname" class="form-control" value="{{ .DisplayName }}" />
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="description" value="" />
|
<input type="hidden" name="description" value="" />
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="description">Description:</label>
|
<label for="description">Description :</label>
|
||||||
<input type="text" id="description" name="description" class="form-control" value="{{ .Description }}" />
|
<input type="text" id="description" name="description" class="form-control" value="{{ .Description }}" />
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="displayname" value="" />
|
<input type="hidden" name="displayname" value="" />
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="soc">StructuralObjectClass:</label>
|
<label for="soc">StructuralObjectClass :</label>
|
||||||
<input type="text" {{if .Template}}disabled="disabled"{{end}} id="soc" name="soc" class="form-control" value="{{ .StructuralObjectClass }}" />
|
<input type="text" {{if .Template}}disabled="disabled"{{end}} id="soc" name="soc" class="form-control" value="{{ .StructuralObjectClass }}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="oc">ObjectClass:</label>
|
<label for="oc">ObjectClass :</label>
|
||||||
<textarea rows="5" {{if .Template}}disabled="disabled"{{end}} id="oc" name="oc" class="form-control">{{ .ObjectClass }}</textarea>
|
<textarea rows="5" {{if .Template}}disabled="disabled"{{end}} id="oc" name="oc" class="form-control">{{ .ObjectClass }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Créer l'objet</button>
|
<button type="submit" class="btn btn-primary">Créer l'objet</button>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<h4>Mailing lists</h4>
|
<h4>Mailing lists</h4>
|
||||||
<a class="ml-auto btn btn-success" href="/admin/create/group/{{.MailingBaseDN}}">Nouvelle mailing list</a>
|
<a class="ml-auto btn btn-success" href="/admin/create/ml/{{.MailingBaseDN}}">Nouvelle mailing list</a>
|
||||||
<a class="ml-4 btn btn-info" href="/">Menu principal</a>
|
<a class="ml-4 btn btn-info" href="/">Menu principal</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
{{with $desc := .MailingList.GetAttributeValue "description"}}{{if $desc}}
|
||||||
|
<p class="mt-4">{{$desc}}</p>
|
||||||
|
{{end}}{{end}}
|
||||||
|
|
||||||
<table class="table mt-4">
|
<table class="table mt-4">
|
||||||
<thead>
|
<thead>
|
||||||
<th scope="col">Adresse</th>
|
<th scope="col">Adresse</th>
|
||||||
|
@ -46,16 +50,20 @@
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{if not .Members}}
|
||||||
|
<tr><td>(aucun abonné)</td></tr>
|
||||||
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<hr class="mt-4" />
|
<hr class="mt-4" />
|
||||||
<h5 class="mt-4">Ajouter un destinataire</h5>
|
<h5 class="mt-4">Ajouter un destinataire</h5>
|
||||||
<form method="POST">
|
|
||||||
<input type="hidden" name="action" value="add-member" />
|
<div class="container">
|
||||||
<div class="row mt-4">
|
<form method="POST">
|
||||||
<div class="col-md-3"><strong>Utilisateur existant :</strong>
|
<input type="hidden" name="action" value="add-member" />
|
||||||
</div>
|
<div class="row mt-4">
|
||||||
|
<div class="col-md-3"><strong>Utilisateur existant :</strong> </div>
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<input class="form-control" type="text" list="users" name="member" placeholder="Utilisateur..." />
|
<input class="form-control" type="text" list="users" name="member" placeholder="Utilisateur..." />
|
||||||
<datalist id="users">
|
<datalist id="users">
|
||||||
|
@ -67,7 +75,43 @@
|
||||||
</datalist>
|
</datalist>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="submit" value="Ajouter" class="form-control btn btn-success btn-sm" />
|
<input type="submit" value="Ajouter" class="form-control btn btn-success btn-sm" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{{if .AllowGuest}}
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-md-10">OU</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="action" value="add-external" />
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-md-3"><strong>E-mail :</strong></div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<input class="form-control" type="text" name="mail" placeholder="machin@truc.net..." />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-md-3"><strong>Nom (optionnel) :</strong></div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<input class="form-control" type="text" name="displayname" placeholder="Machin Truc..." />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<input type="submit" value="Ajouter" class="form-control btn btn-success btn-sm" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<small class="form-text text-muted col-md-10">
|
||||||
|
Si un utilisateur existe déjà avec l'email spécifiée, celui-ci sera ajouté à la liste.
|
||||||
|
Sinon, un utilisateur invité sera créé.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
|
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
|
||||||
|
|
||||||
<title>{{template "title"}} Guichet</title>
|
<title>{{template "title" .}} Guichet</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container mb-4">
|
<div class="container mb-4">
|
||||||
|
|
Loading…
Reference in a new issue