package models import ( "errors" log "github.com/gophish/gophish/logger" ) // ErrModifyingOnlyAdmin occurs when there is an attempt to modify the only // user account with the Admin role in such a way that there will be no user // accounts left in Gophish with that role. var ErrModifyingOnlyAdmin = errors.New("Cannot remove the only administrator") // User represents the user model for gophish. type User struct { Id int64 `json:"id"` Username string `json:"username" sql:"not null;unique"` Hash string `json:"-"` ApiKey string `json:"api_key" sql:"not null;unique"` Role Role `json:"role" gorm:"association_autoupdate:false;association_autocreate:false"` RoleID int64 `json:"-"` PasswordChangeRequired bool `json:"password_change_required"` } // GetUser returns the user that the given id corresponds to. If no user is found, an // error is thrown. func GetUser(id int64) (User, error) { u := User{} err := db.Preload("Role").Where("id=?", id).First(&u).Error return u, err } // GetUsers returns the users registered in Gophish func GetUsers() ([]User, error) { us := []User{} err := db.Preload("Role").Find(&us).Error return us, err } // GetUserByAPIKey returns the user that the given API Key corresponds to. If no user is found, an // error is thrown. func GetUserByAPIKey(key string) (User, error) { u := User{} err := db.Preload("Role").Where("api_key = ?", key).First(&u).Error return u, err } // GetUserByUsername returns the user that the given username corresponds to. If no user is found, an // error is thrown. func GetUserByUsername(username string) (User, error) { u := User{} err := db.Preload("Role").Where("username = ?", username).First(&u).Error return u, err } // PutUser updates the given user func PutUser(u *User) error { err := db.Save(u).Error return err } // EnsureEnoughAdmins ensures that there is more than one user account in // Gophish with the Admin role. This function is meant to be called before // modifying a user account with the Admin role in a non-revokable way. func EnsureEnoughAdmins() error { role, err := GetRoleBySlug(RoleAdmin) if err != nil { return err } var adminCount int err = db.Model(&User{}).Where("role_id=?", role.ID).Count(&adminCount).Error if err != nil { return err } if adminCount == 1 { return ErrModifyingOnlyAdmin } return nil } // DeleteUser deletes the given user. To ensure that there is always at least // one user account with the Admin role, this function will refuse to delete // the last Admin. func DeleteUser(id int64) error { existing, err := GetUser(id) if err != nil { return err } // If the user is an admin, we need to verify that it's not the last one. if existing.Role.Slug == RoleAdmin { err = EnsureEnoughAdmins() if err != nil { return err } } campaigns, err := GetCampaigns(id) if err != nil { return err } // Delete the campaigns log.Infof("Deleting campaigns for user ID %d", id) for _, campaign := range campaigns { err = DeleteCampaign(campaign.Id) if err != nil { return err } } log.Infof("Deleting pages for user ID %d", id) // Delete the landing pages pages, err := GetPages(id) if err != nil { return err } for _, page := range pages { err = DeletePage(page.Id, id) if err != nil { return err } } // Delete the templates log.Infof("Deleting templates for user ID %d", id) templates, err := GetTemplates(id) if err != nil { return err } for _, template := range templates { err = DeleteTemplate(template.Id, id) if err != nil { return err } } // Delete the groups log.Infof("Deleting groups for user ID %d", id) groups, err := GetGroups(id) if err != nil { return err } for _, group := range groups { err = DeleteGroup(&group) if err != nil { return err } } // Delete the sending profiles log.Infof("Deleting sending profiles for user ID %d", id) profiles, err := GetSMTPs(id) if err != nil { return err } for _, profile := range profiles { err = DeleteSMTP(profile.Id, id) if err != nil { return err } } // Finally, delete the user err = db.Where("id=?", id).Delete(&User{}).Error return err }