From dc39435103517097463872e0f349c810e1fcfe20 Mon Sep 17 00:00:00 2001 From: teru Date: Sun, 31 Jul 2016 18:19:50 +0900 Subject: [PATCH] Moved functions --- aliasdomain.go | 57 ++++++ aliasuser.go | 66 ++++++- catchalluser.go | 42 +++++ domain.go | 63 +++++++ repository.go | 411 -------------------------------------------- repositoryconfig.go | 24 +++ user.go | 185 ++++++++++++++++++++ 7 files changed, 436 insertions(+), 412 deletions(-) delete mode 100644 repository.go diff --git a/aliasdomain.go b/aliasdomain.go index 2a59b57..0010aa7 100644 --- a/aliasdomain.go +++ b/aliasdomain.go @@ -1,5 +1,12 @@ package mailfull +import ( + "bufio" + "os" + "path/filepath" + "strings" +) + // AliasDomain represents a AliasDomain. type AliasDomain struct { name string @@ -39,3 +46,53 @@ func (ad *AliasDomain) Name() string { func (ad *AliasDomain) Target() string { return ad.target } + +// AliasDomains returns a AliasDomain slice. +func (r *Repository) AliasDomains() ([]*AliasDomain, error) { + file, err := os.Open(filepath.Join(r.DirMailDataPath, FileNameAliasDomains)) + if err != nil { + return nil, err + } + + aliasDomains := make([]*AliasDomain, 0, 10) + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + words := strings.Split(scanner.Text(), ":") + if len(words) != 2 { + return nil, ErrInvalidFormatAliasDomain + } + + name := words[0] + target := words[1] + + aliasDomain, err := NewAliasDomain(name, target) + if err != nil { + return nil, err + } + + aliasDomains = append(aliasDomains, aliasDomain) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return aliasDomains, nil +} + +// AliasDomain returns a AliasDomain of the input name. +func (r *Repository) AliasDomain(aliasDomainName string) (*AliasDomain, error) { + aliasDomains, err := r.AliasDomains() + if err != nil { + return nil, err + } + + for _, aliasDomain := range aliasDomains { + if aliasDomain.Name() == aliasDomainName { + return aliasDomain, nil + } + } + + return nil, nil +} diff --git a/aliasuser.go b/aliasuser.go index c8deea2..fa3d556 100644 --- a/aliasuser.go +++ b/aliasuser.go @@ -1,6 +1,12 @@ package mailfull -import "errors" +import ( + "bufio" + "errors" + "os" + "path/filepath" + "strings" +) // Errors for parameter. var ( @@ -53,3 +59,61 @@ func (au *AliasUser) Name() string { func (au *AliasUser) Targets() []string { return au.targets } + +// AliasUsers returns a AliasUser slice. +func (r *Repository) AliasUsers(domainName string) ([]*AliasUser, error) { + domain, err := r.Domain(domainName) + if err != nil { + return nil, err + } + if domain == nil { + return nil, ErrDomainNotExist + } + + file, err := os.Open(filepath.Join(r.DirMailDataPath, domainName, FileNameAliasUsers)) + if err != nil { + return nil, err + } + + aliasUsers := make([]*AliasUser, 0, 50) + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + words := strings.Split(scanner.Text(), ":") + if len(words) != 2 { + return nil, ErrInvalidFormatAliasUsers + } + + name := words[0] + targets := strings.Split(words[1], ",") + + aliasUser, err := NewAliasUser(name, targets) + if err != nil { + return nil, err + } + + aliasUsers = append(aliasUsers, aliasUser) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return aliasUsers, nil +} + +// AliasUser returns a AliasUser of the input name. +func (r *Repository) AliasUser(domainName, aliasUserName string) (*AliasUser, error) { + aliasUsers, err := r.AliasUsers(domainName) + if err != nil { + return nil, err + } + + for _, aliasUser := range aliasUsers { + if aliasUser.Name() == aliasUserName { + return aliasUser, nil + } + } + + return nil, nil +} diff --git a/catchalluser.go b/catchalluser.go index 61e93bf..d96a886 100644 --- a/catchalluser.go +++ b/catchalluser.go @@ -1,5 +1,11 @@ package mailfull +import ( + "bufio" + "os" + "path/filepath" +) + // CatchAllUser represents a CatchAllUser. type CatchAllUser struct { name string @@ -22,3 +28,39 @@ func NewCatchAllUser(name string) (*CatchAllUser, error) { func (cu *CatchAllUser) Name() string { return cu.name } + +// CatchAllUser returns a CatchAllUser that the input name has. +func (r *Repository) CatchAllUser(domainName string) (*CatchAllUser, error) { + domain, err := r.Domain(domainName) + if err != nil { + return nil, err + } + if domain == nil { + return nil, ErrDomainNotExist + } + + file, err := os.Open(filepath.Join(r.DirMailDataPath, domainName, FileNameCatchAllUser)) + if err != nil { + return nil, err + } + + scanner := bufio.NewScanner(file) + scanner.Scan() + + name := scanner.Text() + + if err := scanner.Err(); err != nil { + return nil, err + } + + if name == "" { + return nil, nil + } + + catchAllUser, err := NewCatchAllUser(name) + if err != nil { + return nil, err + } + + return catchAllUser, nil +} diff --git a/domain.go b/domain.go index c1b8cf2..d881bc1 100644 --- a/domain.go +++ b/domain.go @@ -1,5 +1,12 @@ package mailfull +import ( + "io/ioutil" + "os" + "path/filepath" + "syscall" +) + // Domain represents a Domain. type Domain struct { name string @@ -32,3 +39,59 @@ func NewDomain(name string) (*Domain, error) { func (d *Domain) Name() string { return d.name } + +// Domains returns a Domain slice. +func (r *Repository) Domains() ([]*Domain, error) { + fileInfos, err := ioutil.ReadDir(r.DirMailDataPath) + if err != nil { + return nil, err + } + + domains := make([]*Domain, 0, len(fileInfos)) + + for _, fileInfo := range fileInfos { + if !fileInfo.IsDir() { + continue + } + + name := fileInfo.Name() + + domain, err := NewDomain(name) + if err != nil { + continue + } + + domains = append(domains, domain) + } + + return domains, nil +} + +// Domain returns a Domain of the input name. +func (r *Repository) Domain(domainName string) (*Domain, error) { + if !validDomainName(domainName) { + return nil, ErrInvalidDomainName + } + + fileInfo, err := os.Stat(filepath.Join(r.DirMailDataPath, domainName)) + if err != nil { + if err.(*os.PathError).Err == syscall.ENOENT { + return nil, nil + } + + return nil, err + } + + if !fileInfo.IsDir() { + return nil, nil + } + + name := domainName + + domain, err := NewDomain(name) + if err != nil { + return nil, err + } + + return domain, nil +} diff --git a/repository.go b/repository.go deleted file mode 100644 index 407f4be..0000000 --- a/repository.go +++ /dev/null @@ -1,411 +0,0 @@ -package mailfull - -import ( - "bufio" - "errors" - "io/ioutil" - "os" - "path/filepath" - "strings" - "syscall" -) - -// Errors for the operation of the Repository. -var ( - ErrDomainNotExist = errors.New("Domain: not exist") - ErrUserNotExist = errors.New("User: not exist") - - ErrInvalidFormatUsersPassword = errors.New("User: password file invalid format") - ErrInvalidFormatAliasDomain = errors.New("AliasDomain: file invalid format") - ErrInvalidFormatAliasUsers = errors.New("AliasUsers: file invalid format") -) - -// Repository represents a Repository. -type Repository struct { - *RepositoryConfig -} - -// NewRepository creates a new Repository instance. -func NewRepository(c *RepositoryConfig) (*Repository, error) { - r := &Repository{ - RepositoryConfig: c, - } - - return r, nil -} - -// Domains returns a Domain slice. -func (r *Repository) Domains() ([]*Domain, error) { - fileInfos, err := ioutil.ReadDir(r.DirMailDataPath) - if err != nil { - return nil, err - } - - domains := make([]*Domain, 0, len(fileInfos)) - - for _, fileInfo := range fileInfos { - if !fileInfo.IsDir() { - continue - } - - name := fileInfo.Name() - - domain, err := NewDomain(name) - if err != nil { - continue - } - - domains = append(domains, domain) - } - - return domains, nil -} - -// Domain returns a Domain of the input name. -func (r *Repository) Domain(domainName string) (*Domain, error) { - if !validDomainName(domainName) { - return nil, ErrInvalidDomainName - } - - fileInfo, err := os.Stat(filepath.Join(r.DirMailDataPath, domainName)) - if err != nil { - if err.(*os.PathError).Err == syscall.ENOENT { - return nil, nil - } - - return nil, err - } - - if !fileInfo.IsDir() { - return nil, nil - } - - name := domainName - - domain, err := NewDomain(name) - if err != nil { - return nil, err - } - - return domain, nil -} - -// AliasDomains returns a AliasDomain slice. -func (r *Repository) AliasDomains() ([]*AliasDomain, error) { - file, err := os.Open(filepath.Join(r.DirMailDataPath, FileNameAliasDomains)) - if err != nil { - return nil, err - } - - aliasDomains := make([]*AliasDomain, 0, 10) - - scanner := bufio.NewScanner(file) - for scanner.Scan() { - words := strings.Split(scanner.Text(), ":") - if len(words) != 2 { - return nil, ErrInvalidFormatAliasDomain - } - - name := words[0] - target := words[1] - - aliasDomain, err := NewAliasDomain(name, target) - if err != nil { - return nil, err - } - - aliasDomains = append(aliasDomains, aliasDomain) - } - - if err := scanner.Err(); err != nil { - return nil, err - } - - return aliasDomains, nil -} - -// AliasDomain returns a AliasDomain of the input name. -func (r *Repository) AliasDomain(aliasDomainName string) (*AliasDomain, error) { - aliasDomains, err := r.AliasDomains() - if err != nil { - return nil, err - } - - for _, aliasDomain := range aliasDomains { - if aliasDomain.Name() == aliasDomainName { - return aliasDomain, nil - } - } - - return nil, nil -} - -// Users returns a User slice. -func (r *Repository) Users(domainName string) ([]*User, error) { - domain, err := r.Domain(domainName) - if err != nil { - return nil, err - } - if domain == nil { - return nil, ErrDomainNotExist - } - - hashedPasswords, err := r.usersHashedPassword(domainName) - if err != nil { - return nil, err - } - - fileInfos, err := ioutil.ReadDir(filepath.Join(r.DirMailDataPath, domainName)) - if err != nil { - return nil, err - } - - users := make([]*User, 0, len(fileInfos)) - - for _, fileInfo := range fileInfos { - if !fileInfo.IsDir() { - continue - } - - name := fileInfo.Name() - - forwards, err := r.userForwards(domainName, name) - if err != nil { - return nil, err - } - - hashedPassword, ok := hashedPasswords[name] - if !ok { - hashedPassword = "" - } - - user, err := NewUser(name, hashedPassword, forwards) - if err != nil { - continue - } - - users = append(users, user) - } - - return users, nil -} - -// User returns a User of the input name. -func (r *Repository) User(domainName, userName string) (*User, error) { - domain, err := r.Domain(domainName) - if err != nil { - return nil, err - } - if domain == nil { - return nil, ErrDomainNotExist - } - - if !validUserName(userName) { - return nil, ErrInvalidUserName - } - - hashedPasswords, err := r.usersHashedPassword(domainName) - if err != nil { - return nil, err - } - - fileInfo, err := os.Stat(filepath.Join(r.DirMailDataPath, domainName, userName)) - if err != nil { - if err.(*os.PathError).Err == syscall.ENOENT { - return nil, nil - } - - return nil, err - } - - if !fileInfo.IsDir() { - return nil, nil - } - - name := userName - - forwards, err := r.userForwards(domainName, name) - if err != nil { - return nil, err - } - - hashedPassword, ok := hashedPasswords[name] - if !ok { - hashedPassword = "" - } - - user, err := NewUser(name, hashedPassword, forwards) - if err != nil { - return nil, err - } - - return user, nil -} - -// usersHashedPassword returns a string map of usernames to the hashed password. -func (r *Repository) usersHashedPassword(domainName string) (map[string]string, error) { - domain, err := r.Domain(domainName) - if err != nil { - return nil, err - } - if domain == nil { - return nil, ErrDomainNotExist - } - - file, err := os.Open(filepath.Join(r.DirMailDataPath, domainName, FileNameUsersPassword)) - if err != nil { - return nil, err - } - - hashedPasswords := map[string]string{} - - scanner := bufio.NewScanner(file) - for scanner.Scan() { - words := strings.Split(scanner.Text(), ":") - if len(words) != 2 { - return nil, ErrInvalidFormatUsersPassword - } - - name := words[0] - hashedPassword := words[1] - - hashedPasswords[name] = hashedPassword - } - - if err := scanner.Err(); err != nil { - return nil, err - } - - return hashedPasswords, nil -} - -// userForwards returns a string slice of forwards that the input name has. -func (r *Repository) userForwards(domainName, userName string) ([]string, error) { - domain, err := r.Domain(domainName) - if err != nil { - return nil, err - } - if domain == nil { - return nil, ErrDomainNotExist - } - - if !validUserName(userName) { - return nil, ErrInvalidUserName - } - - file, err := os.Open(filepath.Join(r.DirMailDataPath, domainName, userName, FileNameUserForwards)) - if err != nil { - if err.(*os.PathError).Err == syscall.ENOENT { - return nil, nil - } - - return nil, err - } - - forwards := make([]string, 0, 5) - - scanner := bufio.NewScanner(file) - for scanner.Scan() { - forwards = append(forwards, scanner.Text()) - } - - if err := scanner.Err(); err != nil { - return nil, err - } - - return forwards, nil -} - -// AliasUsers returns a AliasUser slice. -func (r *Repository) AliasUsers(domainName string) ([]*AliasUser, error) { - domain, err := r.Domain(domainName) - if err != nil { - return nil, err - } - if domain == nil { - return nil, ErrDomainNotExist - } - - file, err := os.Open(filepath.Join(r.DirMailDataPath, domainName, FileNameAliasUsers)) - if err != nil { - return nil, err - } - - aliasUsers := make([]*AliasUser, 0, 50) - - scanner := bufio.NewScanner(file) - for scanner.Scan() { - words := strings.Split(scanner.Text(), ":") - if len(words) != 2 { - return nil, ErrInvalidFormatAliasUsers - } - - name := words[0] - targets := strings.Split(words[1], ",") - - aliasUser, err := NewAliasUser(name, targets) - if err != nil { - return nil, err - } - - aliasUsers = append(aliasUsers, aliasUser) - } - - if err := scanner.Err(); err != nil { - return nil, err - } - - return aliasUsers, nil -} - -// AliasUser returns a AliasUser of the input name. -func (r *Repository) AliasUser(domainName, aliasUserName string) (*AliasUser, error) { - aliasUsers, err := r.AliasUsers(domainName) - if err != nil { - return nil, err - } - - for _, aliasUser := range aliasUsers { - if aliasUser.Name() == aliasUserName { - return aliasUser, nil - } - } - - return nil, nil -} - -// CatchAllUser returns a CatchAllUser that the input name has. -func (r *Repository) CatchAllUser(domainName string) (*CatchAllUser, error) { - domain, err := r.Domain(domainName) - if err != nil { - return nil, err - } - if domain == nil { - return nil, ErrDomainNotExist - } - - file, err := os.Open(filepath.Join(r.DirMailDataPath, domainName, FileNameCatchAllUser)) - if err != nil { - return nil, err - } - - scanner := bufio.NewScanner(file) - scanner.Scan() - - name := scanner.Text() - - if err := scanner.Err(); err != nil { - return nil, err - } - - if name == "" { - return nil, nil - } - - catchAllUser, err := NewCatchAllUser(name) - if err != nil { - return nil, err - } - - return catchAllUser, nil -} diff --git a/repositoryconfig.go b/repositoryconfig.go index 32bf2af..25474e4 100644 --- a/repositoryconfig.go +++ b/repositoryconfig.go @@ -16,6 +16,16 @@ var ( ErrRepositoryExist = errors.New("a Mailfull repository exists") ) +// Errors for the operation of the Repository. +var ( + ErrDomainNotExist = errors.New("Domain: not exist") + ErrUserNotExist = errors.New("User: not exist") + + 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. type RepositoryConfig struct { DirDatabasePath string `toml:"dir_database"` @@ -36,6 +46,20 @@ func DefaultRepositoryConfig() *RepositoryConfig { return c } +// Repository represents a Repository. +type Repository struct { + *RepositoryConfig +} + +// NewRepository creates a new Repository instance. +func NewRepository(c *RepositoryConfig) (*Repository, error) { + r := &Repository{ + RepositoryConfig: c, + } + + return r, nil +} + // OpenRepository opens a Repository and creates a new Repository instance. func OpenRepository(basePath string) (*Repository, error) { rootPath, err := filepath.Abs(basePath) diff --git a/user.go b/user.go index b6e163b..6fa9f74 100644 --- a/user.go +++ b/user.go @@ -1,5 +1,14 @@ package mailfull +import ( + "bufio" + "io/ioutil" + "os" + "path/filepath" + "strings" + "syscall" +) + // User represents a User. type User struct { name string @@ -43,3 +52,179 @@ func (u *User) HashedPassword() string { func (u *User) Forwards() []string { return u.forwards } + +// Users returns a User slice. +func (r *Repository) Users(domainName string) ([]*User, error) { + domain, err := r.Domain(domainName) + if err != nil { + return nil, err + } + if domain == nil { + return nil, ErrDomainNotExist + } + + hashedPasswords, err := r.usersHashedPassword(domainName) + if err != nil { + return nil, err + } + + fileInfos, err := ioutil.ReadDir(filepath.Join(r.DirMailDataPath, domainName)) + if err != nil { + return nil, err + } + + users := make([]*User, 0, len(fileInfos)) + + for _, fileInfo := range fileInfos { + if !fileInfo.IsDir() { + continue + } + + name := fileInfo.Name() + + forwards, err := r.userForwards(domainName, name) + if err != nil { + return nil, err + } + + hashedPassword, ok := hashedPasswords[name] + if !ok { + hashedPassword = "" + } + + user, err := NewUser(name, hashedPassword, forwards) + if err != nil { + continue + } + + users = append(users, user) + } + + return users, nil +} + +// User returns a User of the input name. +func (r *Repository) User(domainName, userName string) (*User, error) { + domain, err := r.Domain(domainName) + if err != nil { + return nil, err + } + if domain == nil { + return nil, ErrDomainNotExist + } + + if !validUserName(userName) { + return nil, ErrInvalidUserName + } + + hashedPasswords, err := r.usersHashedPassword(domainName) + if err != nil { + return nil, err + } + + fileInfo, err := os.Stat(filepath.Join(r.DirMailDataPath, domainName, userName)) + if err != nil { + if err.(*os.PathError).Err == syscall.ENOENT { + return nil, nil + } + + return nil, err + } + + if !fileInfo.IsDir() { + return nil, nil + } + + name := userName + + forwards, err := r.userForwards(domainName, name) + if err != nil { + return nil, err + } + + hashedPassword, ok := hashedPasswords[name] + if !ok { + hashedPassword = "" + } + + user, err := NewUser(name, hashedPassword, forwards) + if err != nil { + return nil, err + } + + return user, nil +} + +// usersHashedPassword returns a string map of usernames to the hashed password. +func (r *Repository) usersHashedPassword(domainName string) (map[string]string, error) { + domain, err := r.Domain(domainName) + if err != nil { + return nil, err + } + if domain == nil { + return nil, ErrDomainNotExist + } + + file, err := os.Open(filepath.Join(r.DirMailDataPath, domainName, FileNameUsersPassword)) + if err != nil { + return nil, err + } + + hashedPasswords := map[string]string{} + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + words := strings.Split(scanner.Text(), ":") + if len(words) != 2 { + return nil, ErrInvalidFormatUsersPassword + } + + name := words[0] + hashedPassword := words[1] + + hashedPasswords[name] = hashedPassword + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return hashedPasswords, nil +} + +// userForwards returns a string slice of forwards that the input name has. +func (r *Repository) userForwards(domainName, userName string) ([]string, error) { + domain, err := r.Domain(domainName) + if err != nil { + return nil, err + } + if domain == nil { + return nil, ErrDomainNotExist + } + + if !validUserName(userName) { + return nil, ErrInvalidUserName + } + + file, err := os.Open(filepath.Join(r.DirMailDataPath, domainName, userName, FileNameUserForwards)) + if err != nil { + if err.(*os.PathError).Err == syscall.ENOENT { + return nil, nil + } + + return nil, err + } + + forwards := make([]string, 0, 5) + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + forwards = append(forwards, scanner.Text()) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return forwards, nil +}