mirror of
https://github.com/directorz/mailfull-go.git
synced 2025-12-17 17:47:04 +00:00
Implement disable/enable a Domain #8
This commit is contained in:
1
const.go
1
const.go
@@ -5,6 +5,7 @@ const (
|
||||
DirNameConfig = ".mailfull"
|
||||
FileNameConfig = "config"
|
||||
|
||||
FileNameDomainDisable = ".vdomaindisable"
|
||||
FileNameAliasDomains = ".valiasdomains"
|
||||
FileNameUsersPassword = ".vpasswd"
|
||||
FileNameUserForwards = ".forward"
|
||||
|
||||
24
database.go
24
database.go
@@ -70,6 +70,10 @@ func (r *Repository) generateDbDomains(md *MailData) error {
|
||||
defer dbDomains.Close()
|
||||
|
||||
for _, domain := range md.Domains {
|
||||
if domain.Disabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(dbDomains, "%s virtual\n", domain.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -95,6 +99,10 @@ func (r *Repository) generateDbDestinations(md *MailData) error {
|
||||
defer dbDestinations.Close()
|
||||
|
||||
for _, domain := range md.Domains {
|
||||
if domain.Disabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
// ho-ge.example.com -> ho_ge.example.com
|
||||
underscoredDomainName := domain.Name()
|
||||
underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1)
|
||||
@@ -153,6 +161,10 @@ func (r *Repository) generateDbMaildirs(md *MailData) error {
|
||||
defer dbMaildirs.Close()
|
||||
|
||||
for _, domain := range md.Domains {
|
||||
if domain.Disabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, user := range domain.Users {
|
||||
if _, err := fmt.Fprintf(dbMaildirs, "%s@%s %s/%s/Maildir/\n", user.Name(), domain.Name(), domain.Name(), user.Name()); err != nil {
|
||||
return err
|
||||
@@ -174,6 +186,10 @@ func (r *Repository) generateDbLocaltable(md *MailData) error {
|
||||
defer dbLocaltable.Close()
|
||||
|
||||
for _, domain := range md.Domains {
|
||||
if domain.Disabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
// ho-ge.example.com -> ho_ge\.example\.com
|
||||
escapedDomainName := domain.Name()
|
||||
escapedDomainName = strings.Replace(escapedDomainName, `-`, `_`, -1)
|
||||
@@ -198,6 +214,10 @@ func (r *Repository) generateDbForwards(md *MailData) error {
|
||||
defer dbForwards.Close()
|
||||
|
||||
for _, domain := range md.Domains {
|
||||
if domain.Disabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
// ho-ge.example.com -> ho_ge.example.com
|
||||
underscoredDomainName := domain.Name()
|
||||
underscoredDomainName = strings.Replace(underscoredDomainName, `-`, `_`, -1)
|
||||
@@ -234,6 +254,10 @@ func (r *Repository) generateDbPasswords(md *MailData) error {
|
||||
defer dbPasswords.Close()
|
||||
|
||||
for _, domain := range md.Domains {
|
||||
if domain.Disabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, user := range domain.Users {
|
||||
if _, err := fmt.Fprintf(dbPasswords, "%s@%s:%s\n", user.Name(), domain.Name(), user.HashedPassword()); err != nil {
|
||||
return err
|
||||
|
||||
91
domain.go
91
domain.go
@@ -82,6 +82,12 @@ func (r *Repository) Domains() ([]*Domain, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
disabled, err := r.domainDisabled(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domain.SetDisabled(disabled)
|
||||
|
||||
domains = append(domains, domain)
|
||||
}
|
||||
|
||||
@@ -114,9 +120,38 @@ func (r *Repository) Domain(domainName string) (*Domain, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
disabled, err := r.domainDisabled(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domain.SetDisabled(disabled)
|
||||
|
||||
return domain, nil
|
||||
}
|
||||
|
||||
// domainDisabled returns true if the input Domain is disabled.
|
||||
func (r *Repository) domainDisabled(domainName string) (bool, error) {
|
||||
if !validDomainName(domainName) {
|
||||
return false, ErrInvalidDomainName
|
||||
}
|
||||
|
||||
fi, err := os.Stat(filepath.Join(r.DirMailDataPath, domainName, FileNameDomainDisable))
|
||||
|
||||
if err != nil {
|
||||
if err.(*os.PathError).Err == syscall.ENOENT {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
return false, ErrInvalidFormatDomainDisabled
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// DomainCreate creates the input Domain.
|
||||
func (r *Repository) DomainCreate(domain *Domain) error {
|
||||
existDomain, err := r.Domain(domain.Name())
|
||||
@@ -170,6 +205,29 @@ func (r *Repository) DomainCreate(domain *Domain) error {
|
||||
}
|
||||
catchAllUserFile.Close()
|
||||
|
||||
if domain.Disabled() {
|
||||
if err := r.writeDomainDisabledFile(domain.Name(), domain.Disabled()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DomainUpdate updates the input Domain.
|
||||
func (r *Repository) DomainUpdate(domain *Domain) error {
|
||||
existDomain, err := r.Domain(domain.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existDomain == nil {
|
||||
return ErrDomainNotExist
|
||||
}
|
||||
|
||||
if err := r.writeDomainDisabledFile(domain.Name(), domain.Disabled()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -202,3 +260,36 @@ func (r *Repository) DomainRemove(domainName string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeDomainDisabledFile creates/removes the disabled file.
|
||||
func (r *Repository) writeDomainDisabledFile(domainName string, disabled bool) error {
|
||||
if !validDomainName(domainName) {
|
||||
return ErrInvalidDomainName
|
||||
}
|
||||
|
||||
nowDisabled, err := r.domainDisabled(domainName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
domainDisabledFileName := filepath.Join(r.DirMailDataPath, domainName, FileNameDomainDisable)
|
||||
|
||||
if !nowDisabled && disabled {
|
||||
file, err := os.OpenFile(domainDisabledFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := file.Chown(r.uid, r.gid); err != nil {
|
||||
return err
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
|
||||
if nowDisabled && !disabled {
|
||||
if err := os.Remove(domainDisabledFileName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -34,9 +34,10 @@ var (
|
||||
ErrAliasUserNotExist = errors.New("AliasUser: not exist")
|
||||
ErrAliasUserAlreadyExist = errors.New("AliasUser: already exist")
|
||||
|
||||
ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format")
|
||||
ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format")
|
||||
ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format")
|
||||
ErrInvalidFormatDomainDisabled = errors.New("Domain: disabled file invalid format")
|
||||
ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format")
|
||||
ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format")
|
||||
ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format")
|
||||
)
|
||||
|
||||
// RepositoryConfig is used to configure a Repository.
|
||||
|
||||
Reference in New Issue
Block a user