Code angepasst
This commit is contained in:
parent
b0c9541c14
commit
0b02fb196b
4
.gitignore
vendored
4
.gitignore
vendored
@ -1 +1,5 @@
|
|||||||
.env
|
.env
|
||||||
|
*.swp
|
||||||
|
go.mod
|
||||||
|
go.sum
|
||||||
|
ldap_phonebook_html
|
||||||
|
72
config.go
Normal file
72
config.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
loadEnvConfig()
|
||||||
|
loadYAMLConfig()
|
||||||
|
loadTemplate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadEnvConfig() {
|
||||||
|
requiredEnvVars := []string{
|
||||||
|
"LDAP_SERVER", "LDAP_PORT", "LDAP_BIND_DN", "LDAP_BIND_PASSWORD",
|
||||||
|
"LDAP_BASE_DN", "LDAP_FILTER", "SERVER_PORT",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, envVar := range requiredEnvVars {
|
||||||
|
if value := os.Getenv(envVar); value == "" {
|
||||||
|
log.Fatalf("Required environment variable %s is not set", envVar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ldapConfig = LDAPConfig{
|
||||||
|
Server: os.Getenv("LDAP_SERVER"),
|
||||||
|
Port: os.Getenv("LDAP_PORT"),
|
||||||
|
BindDN: os.Getenv("LDAP_BIND_DN"),
|
||||||
|
BindPassword: os.Getenv("LDAP_BIND_PASSWORD"),
|
||||||
|
BaseDN: os.Getenv("LDAP_BASE_DN"),
|
||||||
|
Filter: os.Getenv("LDAP_FILTER"),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverPort = os.Getenv("SERVER_PORT")
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadYAMLConfig() {
|
||||||
|
configPath := filepath.Join("static", "config.yaml")
|
||||||
|
configFile, err := os.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to read config file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(configFile, &config)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to parse config file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
validateConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateConfig() {
|
||||||
|
if config.PhoneRules.Country.Prefix == "" ||
|
||||||
|
len(config.PhoneRules.Country.AreaCodes) == 0 ||
|
||||||
|
config.PhoneRules.Country.InternalPrefix == "" ||
|
||||||
|
config.PhoneRules.InvalidNumber == "" {
|
||||||
|
log.Fatalf("Missing required configuration in config.yaml")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadTemplate() {
|
||||||
|
var err error
|
||||||
|
tmpl, err = template.ParseFiles(filepath.Join("static", "index.html"))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to parse template: %v", err)
|
||||||
|
}
|
||||||
|
}
|
125
ldap.go
Normal file
125
ldap.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-ldap/ldap/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fetchDataFromLDAP() ([]Person, error) {
|
||||||
|
l, err := ldap.DialTLS("tcp", ldapConfig.Server+":"+ldapConfig.Port, &tls.Config{InsecureSkipVerify: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to connect to LDAP server: %v", err)
|
||||||
|
}
|
||||||
|
defer l.Close()
|
||||||
|
|
||||||
|
err = l.Bind(ldapConfig.BindDN, ldapConfig.BindPassword)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to bind to LDAP server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erweitere den Filter, um sowohl Benutzer als auch Kontakte einzuschließen
|
||||||
|
combinedFilter := fmt.Sprintf("(|(objectClass=user)(objectClass=contact)%s)", ldapConfig.Filter)
|
||||||
|
|
||||||
|
searchRequest := ldap.NewSearchRequest(
|
||||||
|
ldapConfig.BaseDN,
|
||||||
|
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||||
|
combinedFilter,
|
||||||
|
[]string{"objectClass", "givenName", "sn", "mail", "telephoneNumber", "mobile", "otherTelephone", "physicalDeliveryOfficeName"},
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
sr, err := l.Search(searchRequest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to search LDAP server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var people []Person
|
||||||
|
for _, entry := range sr.Entries {
|
||||||
|
if !isValidEntry(entry) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
isContact := isContactObject(entry)
|
||||||
|
|
||||||
|
person := Person{
|
||||||
|
FirstName: entry.GetAttributeValue("givenName"),
|
||||||
|
LastName: entry.GetAttributeValue("sn"),
|
||||||
|
Email: entry.GetAttributeValue("mail"),
|
||||||
|
Department: entry.GetAttributeValue("physicalDeliveryOfficeName"),
|
||||||
|
IsContact: isContact,
|
||||||
|
}
|
||||||
|
|
||||||
|
officePhone := entry.GetAttributeValue("telephoneNumber")
|
||||||
|
mobilePhone := entry.GetAttributeValue("mobile")
|
||||||
|
|
||||||
|
// Normalisiere die Telefonnummern für den Vergleich
|
||||||
|
normalizedOffice := normalizePhoneNumber(officePhone)
|
||||||
|
normalizedMobile := normalizePhoneNumber(mobilePhone)
|
||||||
|
|
||||||
|
if normalizedOffice == normalizedMobile && mobilePhone != "" {
|
||||||
|
formattedMobile := formatPhoneNumber(mobilePhone)
|
||||||
|
person.Phones = append(person.Phones, Phone{PhoneNumber: formattedMobile, Type: "Mobil"})
|
||||||
|
person.RawPhoneNumber = formattedMobile
|
||||||
|
person.InternalPhone = "" // Keine interne Rufnummer für Mobiltelefone
|
||||||
|
} else if officePhone != "" {
|
||||||
|
formattedPhone := formatPhoneNumber(officePhone)
|
||||||
|
person.Phones = append(person.Phones, Phone{PhoneNumber: formattedPhone, Type: "Office"})
|
||||||
|
person.InternalPhone = extractInternalNumber(officePhone)
|
||||||
|
person.RawPhoneNumber = formattedPhone
|
||||||
|
|
||||||
|
if mobilePhone != "" && normalizedOffice != normalizedMobile {
|
||||||
|
formattedMobile := formatPhoneNumber(mobilePhone)
|
||||||
|
person.Phones = append(person.Phones, Phone{PhoneNumber: formattedMobile, Type: "Mobil"})
|
||||||
|
}
|
||||||
|
} else if mobilePhone != "" {
|
||||||
|
formattedMobile := formatPhoneNumber(mobilePhone)
|
||||||
|
person.Phones = append(person.Phones, Phone{PhoneNumber: formattedMobile, Type: "Mobil"})
|
||||||
|
person.RawPhoneNumber = formattedMobile
|
||||||
|
person.InternalPhone = "" // Keine interne Rufnummer für Mobiltelefone
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, otherPhone := range entry.GetAttributeValues("otherTelephone") {
|
||||||
|
person.Phones = append(person.Phones, Phone{PhoneNumber: formatPhoneNumber(otherPhone), Type: "Other"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len(person.Phones) > 0 && person.Email != "") || isContact {
|
||||||
|
people = append(people, person)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return people, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidEntry(entry *ldap.Entry) bool {
|
||||||
|
firstName := entry.GetAttributeValue("givenName")
|
||||||
|
lastName := entry.GetAttributeValue("sn")
|
||||||
|
telephoneNumber := entry.GetAttributeValue("telephoneNumber")
|
||||||
|
mobile := entry.GetAttributeValue("mobile")
|
||||||
|
|
||||||
|
// Für Kontakte erlauben wir auch Einträge ohne Telefonnummer
|
||||||
|
isContact := isContactObject(entry)
|
||||||
|
|
||||||
|
return (firstName != "" && lastName != "") &&
|
||||||
|
(isContact || telephoneNumber != config.PhoneRules.InvalidNumber || mobile != "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func isContactObject(entry *ldap.Entry) bool {
|
||||||
|
objectClasses := entry.GetAttributeValues("objectClass")
|
||||||
|
for _, class := range objectClasses {
|
||||||
|
if strings.ToLower(class) == "contact" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidContact(entry *ldap.Entry) bool {
|
||||||
|
firstName := entry.GetAttributeValue("givenName")
|
||||||
|
lastName := entry.GetAttributeValue("sn")
|
||||||
|
telephoneNumber := entry.GetAttributeValue("telephoneNumber")
|
||||||
|
|
||||||
|
return firstName != "" && lastName != "" && telephoneNumber != config.PhoneRules.InvalidNumber
|
||||||
|
}
|
311
main.go
311
main.go
@ -20,128 +20,11 @@ Entwickelt mit Unterstützung von Claude.ai, einem KI-Assistenten von Anthropic,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"html/template"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/go-ldap/ldap/v3"
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Person struct {
|
|
||||||
FirstName string
|
|
||||||
LastName string
|
|
||||||
Email string
|
|
||||||
Department string
|
|
||||||
Phones []Phone
|
|
||||||
RawPhoneNumber string
|
|
||||||
InternalPhone string
|
|
||||||
IsContact bool // Neues Feld zur Unterscheidung zwischen Benutzern und Kontakten
|
|
||||||
}
|
|
||||||
|
|
||||||
type Phone struct {
|
|
||||||
PhoneNumber string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
PhoneRules struct {
|
|
||||||
Country struct {
|
|
||||||
Prefix string `yaml:"prefix"`
|
|
||||||
AreaCodes []string `yaml:"area_codes"`
|
|
||||||
InternalPrefix string `yaml:"internal_prefix"`
|
|
||||||
} `yaml:"country"`
|
|
||||||
InvalidNumber string `yaml:"invalid_number"`
|
|
||||||
} `yaml:"phone_rules"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type LDAPConfig struct {
|
|
||||||
Server string
|
|
||||||
Port string
|
|
||||||
BindDN string
|
|
||||||
BindPassword string
|
|
||||||
BaseDN string
|
|
||||||
Filter string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
cachedData []Person
|
|
||||||
lastUpdate time.Time
|
|
||||||
tmpl *template.Template
|
|
||||||
ldapConfig LDAPConfig
|
|
||||||
serverPort string
|
|
||||||
config Config
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
loadEnvConfig()
|
|
||||||
loadYAMLConfig()
|
|
||||||
loadTemplate()
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadEnvConfig() {
|
|
||||||
requiredEnvVars := []string{
|
|
||||||
"LDAP_SERVER", "LDAP_PORT", "LDAP_BIND_DN", "LDAP_BIND_PASSWORD",
|
|
||||||
"LDAP_BASE_DN", "LDAP_FILTER", "SERVER_PORT",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, envVar := range requiredEnvVars {
|
|
||||||
if value := os.Getenv(envVar); value == "" {
|
|
||||||
log.Fatalf("Required environment variable %s is not set", envVar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ldapConfig = LDAPConfig{
|
|
||||||
Server: os.Getenv("LDAP_SERVER"),
|
|
||||||
Port: os.Getenv("LDAP_PORT"),
|
|
||||||
BindDN: os.Getenv("LDAP_BIND_DN"),
|
|
||||||
BindPassword: os.Getenv("LDAP_BIND_PASSWORD"),
|
|
||||||
BaseDN: os.Getenv("LDAP_BASE_DN"),
|
|
||||||
Filter: os.Getenv("LDAP_FILTER"),
|
|
||||||
}
|
|
||||||
|
|
||||||
serverPort = os.Getenv("SERVER_PORT")
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadYAMLConfig() {
|
|
||||||
configPath := filepath.Join("static", "config.yaml")
|
|
||||||
configFile, err := os.ReadFile(configPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to read config file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = yaml.Unmarshal(configFile, &config)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to parse config file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
validateConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateConfig() {
|
|
||||||
if config.PhoneRules.Country.Prefix == "" ||
|
|
||||||
len(config.PhoneRules.Country.AreaCodes) == 0 ||
|
|
||||||
config.PhoneRules.Country.InternalPrefix == "" ||
|
|
||||||
config.PhoneRules.InvalidNumber == "" {
|
|
||||||
log.Fatalf("Missing required configuration in config.yaml")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadTemplate() {
|
|
||||||
var err error
|
|
||||||
tmpl, err = template.ParseFiles(filepath.Join("static", "index.html"))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to parse template: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
go cacheRefresher()
|
go cacheRefresher()
|
||||||
|
|
||||||
@ -166,39 +49,6 @@ func cacheRefresher() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dataEqual(a, b []Person) bool {
|
|
||||||
if len(a) != len(b) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := range a {
|
|
||||||
if !personEqual(a[i], b[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func personEqual(a, b Person) bool {
|
|
||||||
return a.FirstName == b.FirstName &&
|
|
||||||
a.LastName == b.LastName &&
|
|
||||||
a.Email == b.Email &&
|
|
||||||
a.InternalPhone == b.InternalPhone &&
|
|
||||||
a.Department == b.Department &&
|
|
||||||
phonesEqual(a.Phones, b.Phones)
|
|
||||||
}
|
|
||||||
|
|
||||||
func phonesEqual(a, b []Phone) bool {
|
|
||||||
if len(a) != len(b) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := range a {
|
|
||||||
if a[i] != b[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func handler(w http.ResponseWriter, r *http.Request) {
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("Received request for: %s", r.URL.Path)
|
log.Printf("Received request for: %s", r.URL.Path)
|
||||||
|
|
||||||
@ -217,164 +67,3 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchDataFromLDAP() ([]Person, error) {
|
|
||||||
l, err := ldap.DialTLS("tcp", ldapConfig.Server+":"+ldapConfig.Port, &tls.Config{InsecureSkipVerify: true})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to connect to LDAP server: %v", err)
|
|
||||||
}
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
err = l.Bind(ldapConfig.BindDN, ldapConfig.BindPassword)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to bind to LDAP server: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Erweitere den Filter, um sowohl Benutzer als auch Kontakte einzuschließen
|
|
||||||
combinedFilter := fmt.Sprintf("(|(objectClass=user)(objectClass=contact)%s)", ldapConfig.Filter)
|
|
||||||
|
|
||||||
searchRequest := ldap.NewSearchRequest(
|
|
||||||
ldapConfig.BaseDN,
|
|
||||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
|
||||||
combinedFilter,
|
|
||||||
[]string{"objectClass", "givenName", "sn", "mail", "telephoneNumber", "mobile", "otherTelephone", "physicalDeliveryOfficeName"},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
sr, err := l.Search(searchRequest)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to search LDAP server: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var people []Person
|
|
||||||
for _, entry := range sr.Entries {
|
|
||||||
if !isValidEntry(entry) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
isContact := isContactObject(entry)
|
|
||||||
|
|
||||||
person := Person{
|
|
||||||
FirstName: entry.GetAttributeValue("givenName"),
|
|
||||||
LastName: entry.GetAttributeValue("sn"),
|
|
||||||
Email: entry.GetAttributeValue("mail"),
|
|
||||||
Department: entry.GetAttributeValue("physicalDeliveryOfficeName"),
|
|
||||||
IsContact: isContact,
|
|
||||||
}
|
|
||||||
|
|
||||||
officePhone := entry.GetAttributeValue("telephoneNumber")
|
|
||||||
mobilePhone := entry.GetAttributeValue("mobile")
|
|
||||||
|
|
||||||
// Normalisiere die Telefonnummern für den Vergleich
|
|
||||||
normalizedOffice := normalizePhoneNumber(officePhone)
|
|
||||||
normalizedMobile := normalizePhoneNumber(mobilePhone)
|
|
||||||
|
|
||||||
if normalizedOffice == normalizedMobile && mobilePhone != "" {
|
|
||||||
formattedMobile := formatPhoneNumber(mobilePhone)
|
|
||||||
person.Phones = append(person.Phones, Phone{PhoneNumber: formattedMobile, Type: "Mobil"})
|
|
||||||
person.RawPhoneNumber = formattedMobile
|
|
||||||
person.InternalPhone = "" // Keine interne Rufnummer für Mobiltelefone
|
|
||||||
} else if officePhone != "" {
|
|
||||||
formattedPhone := formatPhoneNumber(officePhone)
|
|
||||||
person.Phones = append(person.Phones, Phone{PhoneNumber: formattedPhone, Type: "Office"})
|
|
||||||
person.InternalPhone = extractInternalNumber(officePhone)
|
|
||||||
person.RawPhoneNumber = formattedPhone
|
|
||||||
|
|
||||||
if mobilePhone != "" && normalizedOffice != normalizedMobile {
|
|
||||||
formattedMobile := formatPhoneNumber(mobilePhone)
|
|
||||||
person.Phones = append(person.Phones, Phone{PhoneNumber: formattedMobile, Type: "Mobil"})
|
|
||||||
}
|
|
||||||
} else if mobilePhone != "" {
|
|
||||||
formattedMobile := formatPhoneNumber(mobilePhone)
|
|
||||||
person.Phones = append(person.Phones, Phone{PhoneNumber: formattedMobile, Type: "Mobil"})
|
|
||||||
person.RawPhoneNumber = formattedMobile
|
|
||||||
person.InternalPhone = "" // Keine interne Rufnummer für Mobiltelefone
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, otherPhone := range entry.GetAttributeValues("otherTelephone") {
|
|
||||||
person.Phones = append(person.Phones, Phone{PhoneNumber: formatPhoneNumber(otherPhone), Type: "Other"})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len(person.Phones) > 0 && person.Email != "") || isContact {
|
|
||||||
people = append(people, person)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return people, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isValidEntry(entry *ldap.Entry) bool {
|
|
||||||
firstName := entry.GetAttributeValue("givenName")
|
|
||||||
lastName := entry.GetAttributeValue("sn")
|
|
||||||
telephoneNumber := entry.GetAttributeValue("telephoneNumber")
|
|
||||||
mobile := entry.GetAttributeValue("mobile")
|
|
||||||
|
|
||||||
// Für Kontakte erlauben wir auch Einträge ohne Telefonnummer
|
|
||||||
isContact := isContactObject(entry)
|
|
||||||
|
|
||||||
return (firstName != "" && lastName != "") &&
|
|
||||||
(isContact || telephoneNumber != config.PhoneRules.InvalidNumber || mobile != "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func isContactObject(entry *ldap.Entry) bool {
|
|
||||||
objectClasses := entry.GetAttributeValues("objectClass")
|
|
||||||
for _, class := range objectClasses {
|
|
||||||
if strings.ToLower(class) == "contact" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isValidContact(entry *ldap.Entry) bool {
|
|
||||||
firstName := entry.GetAttributeValue("givenName")
|
|
||||||
lastName := entry.GetAttributeValue("sn")
|
|
||||||
telephoneNumber := entry.GetAttributeValue("telephoneNumber")
|
|
||||||
|
|
||||||
return firstName != "" && lastName != "" && telephoneNumber != config.PhoneRules.InvalidNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatPhoneNumber(number string) string {
|
|
||||||
// Entferne alle Nicht-Ziffern
|
|
||||||
digits := strings.Map(func(r rune) rune {
|
|
||||||
if unicode.IsDigit(r) {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}, number)
|
|
||||||
|
|
||||||
// Entferne führende Nullen
|
|
||||||
digits = strings.TrimLeft(digits, "0")
|
|
||||||
|
|
||||||
// Entferne den Länderprefix, falls vorhanden
|
|
||||||
countryPrefix := config.PhoneRules.Country.Prefix
|
|
||||||
if strings.HasPrefix(digits, countryPrefix) {
|
|
||||||
digits = digits[len(countryPrefix):]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Füge eine führende "0" hinzu, wenn nicht vorhanden
|
|
||||||
if !strings.HasPrefix(digits, "0") {
|
|
||||||
digits = "0" + digits
|
|
||||||
}
|
|
||||||
|
|
||||||
return digits
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractInternalNumber(phoneNumber string) string {
|
|
||||||
digits := formatPhoneNumber(phoneNumber)
|
|
||||||
|
|
||||||
for _, areaCode := range config.PhoneRules.Country.AreaCodes {
|
|
||||||
if strings.HasPrefix(digits[1:], areaCode) { // Ignoriere die führende 0
|
|
||||||
remaining := digits[1+len(areaCode):]
|
|
||||||
if strings.HasPrefix(remaining, config.PhoneRules.Country.InternalPrefix) {
|
|
||||||
return remaining[len(config.PhoneRules.Country.InternalPrefix):]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func normalizePhoneNumber(number string) string {
|
|
||||||
return formatPhoneNumber(number)
|
|
||||||
}
|
|
||||||
|
51
models.go
Normal file
51
models.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
FirstName string
|
||||||
|
LastName string
|
||||||
|
Email string
|
||||||
|
Department string
|
||||||
|
Phones []Phone
|
||||||
|
RawPhoneNumber string
|
||||||
|
InternalPhone string
|
||||||
|
IsContact bool // Neues Feld zur Unterscheidung zwischen Benutzern und Kontakten
|
||||||
|
}
|
||||||
|
|
||||||
|
type Phone struct {
|
||||||
|
PhoneNumber string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
PhoneRules struct {
|
||||||
|
Country struct {
|
||||||
|
Prefix string `yaml:"prefix"`
|
||||||
|
AreaCodes []string `yaml:"area_codes"`
|
||||||
|
InternalPrefix string `yaml:"internal_prefix"`
|
||||||
|
} `yaml:"country"`
|
||||||
|
InvalidNumber string `yaml:"invalid_number"`
|
||||||
|
} `yaml:"phone_rules"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LDAPConfig struct {
|
||||||
|
Server string
|
||||||
|
Port string
|
||||||
|
BindDN string
|
||||||
|
BindPassword string
|
||||||
|
BaseDN string
|
||||||
|
Filter string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
cachedData []Person
|
||||||
|
lastUpdate time.Time
|
||||||
|
tmpl *template.Template
|
||||||
|
ldapConfig LDAPConfig
|
||||||
|
serverPort string
|
||||||
|
config Config
|
||||||
|
)
|
84
util.go
Normal file
84
util.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
func dataEqual(a, b []Person) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range a {
|
||||||
|
if !personEqual(a[i], b[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func personEqual(a, b Person) bool {
|
||||||
|
return a.FirstName == b.FirstName &&
|
||||||
|
a.LastName == b.LastName &&
|
||||||
|
a.Email == b.Email &&
|
||||||
|
a.InternalPhone == b.InternalPhone &&
|
||||||
|
a.Department == b.Department &&
|
||||||
|
phonesEqual(a.Phones, b.Phones)
|
||||||
|
}
|
||||||
|
|
||||||
|
func phonesEqual(a, b []Phone) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range a {
|
||||||
|
if a[i] != b[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatPhoneNumber(number string) string {
|
||||||
|
// Entferne alle Nicht-Ziffern
|
||||||
|
digits := strings.Map(func(r rune) rune {
|
||||||
|
if unicode.IsDigit(r) {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}, number)
|
||||||
|
|
||||||
|
// Entferne führende Nullen
|
||||||
|
digits = strings.TrimLeft(digits, "0")
|
||||||
|
|
||||||
|
// Entferne den Länderprefix, falls vorhanden
|
||||||
|
countryPrefix := config.PhoneRules.Country.Prefix
|
||||||
|
if strings.HasPrefix(digits, countryPrefix) {
|
||||||
|
digits = digits[len(countryPrefix):]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Füge eine führende "0" hinzu, wenn nicht vorhanden
|
||||||
|
if !strings.HasPrefix(digits, "0") {
|
||||||
|
digits = "0" + digits
|
||||||
|
}
|
||||||
|
|
||||||
|
return digits
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractInternalNumber(phoneNumber string) string {
|
||||||
|
digits := formatPhoneNumber(phoneNumber)
|
||||||
|
|
||||||
|
for _, areaCode := range config.PhoneRules.Country.AreaCodes {
|
||||||
|
if strings.HasPrefix(digits[1:], areaCode) { // Ignoriere die führende 0
|
||||||
|
remaining := digits[1+len(areaCode):]
|
||||||
|
if strings.HasPrefix(remaining, config.PhoneRules.Country.InternalPrefix) {
|
||||||
|
return remaining[len(config.PhoneRules.Country.InternalPrefix):]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizePhoneNumber(number string) string {
|
||||||
|
return formatPhoneNumber(number)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user