github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/ldap.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"io/ioutil"
     8  	"mime/multipart"
     9  	"net/http"
    10  
    11  	"github.com/mattermost/mattermost-server/v5/mlog"
    12  	"github.com/mattermost/mattermost-server/v5/model"
    13  	"github.com/mattermost/mattermost-server/v5/utils"
    14  )
    15  
    16  func (a *App) SyncLdap() {
    17  	a.Srv().Go(func() {
    18  
    19  		if license := a.Srv().License(); license != nil && *license.Features.LDAP && *a.Config().LdapSettings.EnableSync {
    20  			if ldapI := a.Ldap(); ldapI != nil {
    21  				ldapI.StartSynchronizeJob(false)
    22  			} else {
    23  				mlog.Error("Not executing ldap sync because ldap is not available")
    24  			}
    25  		}
    26  	})
    27  }
    28  
    29  func (a *App) TestLdap() *model.AppError {
    30  	license := a.Srv().License()
    31  	if ldapI := a.Ldap(); ldapI != nil && license != nil && *license.Features.LDAP && (*a.Config().LdapSettings.Enable || *a.Config().LdapSettings.EnableSync) {
    32  		if err := ldapI.RunTest(); err != nil {
    33  			err.StatusCode = 500
    34  			return err
    35  		}
    36  	} else {
    37  		err := model.NewAppError("TestLdap", "ent.ldap.disabled.app_error", nil, "", http.StatusNotImplemented)
    38  		return err
    39  	}
    40  
    41  	return nil
    42  }
    43  
    44  // GetLdapGroup retrieves a single LDAP group by the given LDAP group id.
    45  func (a *App) GetLdapGroup(ldapGroupID string) (*model.Group, *model.AppError) {
    46  	var group *model.Group
    47  
    48  	if a.Ldap() != nil {
    49  		var err *model.AppError
    50  		group, err = a.Ldap().GetGroup(ldapGroupID)
    51  		if err != nil {
    52  			return nil, err
    53  		}
    54  	} else {
    55  		ae := model.NewAppError("GetLdapGroup", "ent.ldap.app_error", map[string]interface{}{"ldap_group_id": ldapGroupID}, "", http.StatusNotImplemented)
    56  		return nil, ae
    57  	}
    58  
    59  	return group, nil
    60  }
    61  
    62  // GetAllLdapGroupsPage retrieves all LDAP groups under the configured base DN using the default or configured group
    63  // filter.
    64  func (a *App) GetAllLdapGroupsPage(page int, perPage int, opts model.LdapGroupSearchOpts) ([]*model.Group, int, *model.AppError) {
    65  	var groups []*model.Group
    66  	var total int
    67  
    68  	if a.Ldap() != nil {
    69  		var err *model.AppError
    70  		groups, total, err = a.Ldap().GetAllGroupsPage(page, perPage, opts)
    71  		if err != nil {
    72  			return nil, 0, err
    73  		}
    74  	} else {
    75  		ae := model.NewAppError("GetAllLdapGroupsPage", "ent.ldap.app_error", nil, "", http.StatusNotImplemented)
    76  		return nil, 0, ae
    77  	}
    78  
    79  	return groups, total, nil
    80  }
    81  
    82  func (a *App) SwitchEmailToLdap(email, password, code, ldapLoginId, ldapPassword string) (string, *model.AppError) {
    83  	if a.Srv().License() != nil && !*a.Config().ServiceSettings.ExperimentalEnableAuthenticationTransfer {
    84  		return "", model.NewAppError("emailToLdap", "api.user.email_to_ldap.not_available.app_error", nil, "", http.StatusForbidden)
    85  	}
    86  
    87  	user, err := a.GetUserByEmail(email)
    88  	if err != nil {
    89  		return "", err
    90  	}
    91  
    92  	if err := a.CheckPasswordAndAllCriteria(user, password, code); err != nil {
    93  		return "", err
    94  	}
    95  
    96  	if err := a.RevokeAllSessions(user.Id); err != nil {
    97  		return "", err
    98  	}
    99  
   100  	ldapInterface := a.Ldap()
   101  	if ldapInterface == nil {
   102  		return "", model.NewAppError("SwitchEmailToLdap", "api.user.email_to_ldap.not_available.app_error", nil, "", http.StatusNotImplemented)
   103  	}
   104  
   105  	if err := ldapInterface.SwitchToLdap(user.Id, ldapLoginId, ldapPassword); err != nil {
   106  		return "", err
   107  	}
   108  
   109  	a.Srv().Go(func() {
   110  		if err := a.Srv().EmailService.SendSignInChangeEmail(user.Email, "AD/LDAP", user.Locale, a.GetSiteURL()); err != nil {
   111  			mlog.Error("Could not send sign in method changed e-mail", mlog.Err(err))
   112  		}
   113  	})
   114  
   115  	return "/login?extra=signin_change", nil
   116  }
   117  
   118  func (a *App) SwitchLdapToEmail(ldapPassword, code, email, newPassword string) (string, *model.AppError) {
   119  	if a.Srv().License() != nil && !*a.Config().ServiceSettings.ExperimentalEnableAuthenticationTransfer {
   120  		return "", model.NewAppError("ldapToEmail", "api.user.ldap_to_email.not_available.app_error", nil, "", http.StatusForbidden)
   121  	}
   122  
   123  	user, err := a.GetUserByEmail(email)
   124  	if err != nil {
   125  		return "", err
   126  	}
   127  
   128  	if user.AuthService != model.USER_AUTH_SERVICE_LDAP {
   129  		return "", model.NewAppError("SwitchLdapToEmail", "api.user.ldap_to_email.not_ldap_account.app_error", nil, "", http.StatusBadRequest)
   130  	}
   131  
   132  	ldapInterface := a.Ldap()
   133  	if ldapInterface == nil || user.AuthData == nil {
   134  		return "", model.NewAppError("SwitchLdapToEmail", "api.user.ldap_to_email.not_available.app_error", nil, "", http.StatusNotImplemented)
   135  	}
   136  
   137  	if err := ldapInterface.CheckPasswordAuthData(*user.AuthData, ldapPassword); err != nil {
   138  		return "", err
   139  	}
   140  
   141  	if err := a.CheckUserMfa(user, code); err != nil {
   142  		return "", err
   143  	}
   144  
   145  	if err := a.UpdatePassword(user, newPassword); err != nil {
   146  		return "", err
   147  	}
   148  
   149  	if err := a.RevokeAllSessions(user.Id); err != nil {
   150  		return "", err
   151  	}
   152  
   153  	T := utils.GetUserTranslations(user.Locale)
   154  
   155  	a.Srv().Go(func() {
   156  		if err := a.Srv().EmailService.SendSignInChangeEmail(user.Email, T("api.templates.signin_change_email.body.method_email"), user.Locale, a.GetSiteURL()); err != nil {
   157  			mlog.Error("Could not send sign in method changed e-mail", mlog.Err(err))
   158  		}
   159  	})
   160  
   161  	return "/login?extra=signin_change", nil
   162  }
   163  
   164  func (a *App) MigrateIdLDAP(toAttribute string) *model.AppError {
   165  	if ldapI := a.Ldap(); ldapI != nil {
   166  		if err := ldapI.MigrateIDAttribute(toAttribute); err != nil {
   167  			switch err := err.(type) {
   168  			case *model.AppError:
   169  				return err
   170  			default:
   171  				return model.NewAppError("IdMigrateLDAP", "ent.ldap_id_migrate.app_error", nil, err.Error(), http.StatusInternalServerError)
   172  			}
   173  		}
   174  		return nil
   175  	}
   176  	return model.NewAppError("IdMigrateLDAP", "ent.ldap.disabled.app_error", nil, "", http.StatusNotImplemented)
   177  }
   178  
   179  func (a *App) writeLdapFile(filename string, fileData *multipart.FileHeader) *model.AppError {
   180  	file, err := fileData.Open()
   181  	if err != nil {
   182  		return model.NewAppError("AddLdapCertificate", "api.admin.add_certificate.open.app_error", nil, err.Error(), http.StatusInternalServerError)
   183  	}
   184  	defer file.Close()
   185  
   186  	data, err := ioutil.ReadAll(file)
   187  	if err != nil {
   188  		return model.NewAppError("AddLdapCertificate", "api.admin.add_certificate.saving.app_error", nil, err.Error(), http.StatusInternalServerError)
   189  	}
   190  
   191  	err = a.Srv().configStore.SetFile(filename, data)
   192  	if err != nil {
   193  		return model.NewAppError("AddLdapCertificate", "api.admin.add_certificate.saving.app_error", nil, err.Error(), http.StatusInternalServerError)
   194  	}
   195  
   196  	return nil
   197  }
   198  
   199  func (a *App) AddLdapPublicCertificate(fileData *multipart.FileHeader) *model.AppError {
   200  	if err := a.writeLdapFile(model.LDAP_PUBLIC_CERTIFICATE_NAME, fileData); err != nil {
   201  		return err
   202  	}
   203  
   204  	cfg := a.Config().Clone()
   205  	*cfg.LdapSettings.PublicCertificateFile = model.LDAP_PUBLIC_CERTIFICATE_NAME
   206  
   207  	if err := cfg.IsValid(); err != nil {
   208  		return err
   209  	}
   210  
   211  	a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
   212  
   213  	return nil
   214  }
   215  
   216  func (a *App) AddLdapPrivateCertificate(fileData *multipart.FileHeader) *model.AppError {
   217  	if err := a.writeLdapFile(model.LDAP_PRIVATE_KEY_NAME, fileData); err != nil {
   218  		return err
   219  	}
   220  
   221  	cfg := a.Config().Clone()
   222  	*cfg.LdapSettings.PrivateKeyFile = model.LDAP_PRIVATE_KEY_NAME
   223  
   224  	if err := cfg.IsValid(); err != nil {
   225  		return err
   226  	}
   227  
   228  	a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
   229  
   230  	return nil
   231  }
   232  
   233  func (a *App) removeLdapFile(filename string) *model.AppError {
   234  	if err := a.Srv().configStore.RemoveFile(filename); err != nil {
   235  		return model.NewAppError("RemoveLdapFile", "api.admin.remove_certificate.delete.app_error", map[string]interface{}{"Filename": filename}, err.Error(), http.StatusInternalServerError)
   236  	}
   237  	return nil
   238  }
   239  
   240  func (a *App) RemoveLdapPublicCertificate() *model.AppError {
   241  	if err := a.removeLdapFile(*a.Config().LdapSettings.PublicCertificateFile); err != nil {
   242  		return err
   243  	}
   244  
   245  	cfg := a.Config().Clone()
   246  	*cfg.LdapSettings.PublicCertificateFile = ""
   247  
   248  	if err := cfg.IsValid(); err != nil {
   249  		return err
   250  	}
   251  
   252  	a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
   253  
   254  	return nil
   255  }
   256  
   257  func (a *App) RemoveLdapPrivateCertificate() *model.AppError {
   258  	if err := a.removeLdapFile(*a.Config().LdapSettings.PrivateKeyFile); err != nil {
   259  		return err
   260  	}
   261  
   262  	cfg := a.Config().Clone()
   263  	*cfg.LdapSettings.PrivateKeyFile = ""
   264  
   265  	if err := cfg.IsValid(); err != nil {
   266  		return err
   267  	}
   268  
   269  	a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
   270  
   271  	return nil
   272  }