[MM-25645] api4/user: add migrate_auth endpoints (#14966)
* api4/user: add migrate_auth endpoints * api4/user: reflect review comments * add translations Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
f12ca27bac
Коммит
c30fea5f2d
101
api4/user.go
101
api4/user.go
@@ -85,6 +85,9 @@ func (api *API) InitUser() {
|
||||
api.BaseRoutes.Users.Handle("/tokens/enable", api.ApiSessionRequired(enableUserAccessToken)).Methods("POST")
|
||||
|
||||
api.BaseRoutes.User.Handle("/typing", api.ApiSessionRequiredDisableWhenBusy(publishUserTyping)).Methods("POST")
|
||||
|
||||
api.BaseRoutes.Users.Handle("/migrate_auth/ldap", api.ApiSessionRequired(migrateAuthToLDAP)).Methods("POST")
|
||||
api.BaseRoutes.Users.Handle("/migrate_auth/saml", api.ApiSessionRequired(migrateAuthToSaml)).Methods("POST")
|
||||
}
|
||||
|
||||
func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -2555,3 +2558,101 @@ func convertUserToBot(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Write(bot.ToJson())
|
||||
}
|
||||
|
||||
func migrateAuthToLDAP(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
props := model.StringInterfaceFromJson(r.Body)
|
||||
from, ok := props["from"].(string)
|
||||
if !ok {
|
||||
c.SetInvalidParam("from")
|
||||
return
|
||||
}
|
||||
if len(from) == 0 || (from != "email" && from != "gitlab" && from != "saml" && from != "google" && from != "office365") {
|
||||
c.SetInvalidParam("from")
|
||||
return
|
||||
}
|
||||
|
||||
force, ok := props["force"].(bool)
|
||||
if !ok {
|
||||
c.SetInvalidParam("force")
|
||||
return
|
||||
}
|
||||
|
||||
matchField, ok := props["match_field"].(string)
|
||||
if !ok {
|
||||
c.SetInvalidParam("match_field")
|
||||
return
|
||||
}
|
||||
|
||||
auditRec := c.MakeAuditRecord("migrateAuthToLdap", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
auditRec.AddMeta("from", from)
|
||||
auditRec.AddMeta("match_field", matchField)
|
||||
auditRec.AddMeta("force", force)
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||
return
|
||||
}
|
||||
|
||||
if migrate := c.App.AccountMigration(); migrate != nil {
|
||||
if err := migrate.MigrateToLdap(from, matchField, force, false); err != nil {
|
||||
c.Err = model.NewAppError("api.migrateAuthToLdap", "api.migrate_to_saml.error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.Err = model.NewAppError("api.migrateAuthToLdap", "api.admin.ldap.not_available.app_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
auditRec.Success()
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
props := model.StringInterfaceFromJson(r.Body)
|
||||
from, ok := props["from"].(string)
|
||||
if !ok {
|
||||
c.SetInvalidParam("from")
|
||||
return
|
||||
}
|
||||
if len(from) == 0 || (from != "email" && from != "gitlab" && from != "ldap" && from != "google" && from != "office365") {
|
||||
c.SetInvalidParam("from")
|
||||
return
|
||||
}
|
||||
|
||||
auto, ok := props["auto"].(bool)
|
||||
if !ok {
|
||||
c.SetInvalidParam("auto")
|
||||
return
|
||||
}
|
||||
matches, ok := props["matches"].(map[string]interface{})
|
||||
if !ok {
|
||||
c.SetInvalidParam("matches")
|
||||
return
|
||||
}
|
||||
usersMap := model.MapFromJson(strings.NewReader(model.StringInterfaceToJson(matches)))
|
||||
|
||||
auditRec := c.MakeAuditRecord("migrateAuthToSaml", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
auditRec.AddMeta("from", from)
|
||||
auditRec.AddMeta("matches", matches)
|
||||
auditRec.AddMeta("auto", auto)
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||
return
|
||||
}
|
||||
|
||||
if migrate := c.App.AccountMigration(); migrate != nil {
|
||||
if err := migrate.MigrateToSaml(from, usersMap, auto, false); err != nil {
|
||||
c.Err = model.NewAppError("api.migrateAuthToSaml", "api.migrate_to_saml.error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.Err = model.NewAppError("api.migrateAuthToSaml", "api.admin.saml.not_available.app_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
auditRec.Success()
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ func (api *API) InitUserLocal() {
|
||||
api.BaseRoutes.Users.Handle("/tokens/revoke", api.ApiLocal(revokeUserAccessToken)).Methods("POST")
|
||||
api.BaseRoutes.User.Handle("/tokens", api.ApiLocal(getUserAccessTokensForUser)).Methods("GET")
|
||||
api.BaseRoutes.User.Handle("/tokens", api.ApiLocal(createUserAccessToken)).Methods("POST")
|
||||
|
||||
api.BaseRoutes.Users.Handle("/migrate_auth/ldap", api.ApiLocal(migrateAuthToLDAP)).Methods("POST")
|
||||
api.BaseRoutes.Users.Handle("/migrate_auth/saml", api.ApiLocal(migrateAuthToSaml)).Methods("POST")
|
||||
}
|
||||
|
||||
func localGetUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -5182,3 +5182,29 @@ func TestConvertUserToBot(t *testing.T) {
|
||||
require.NotNil(t, bot)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMigrateAuthToLDAP(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
_, err := th.Client.MigrateAuthToLdap("email", "a", false)
|
||||
CheckForbiddenStatus(t, err)
|
||||
|
||||
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
||||
_, err = client.MigrateAuthToLdap("email", "a", false)
|
||||
CheckNotImplementedStatus(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMigrateAuthToSAML(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
_, err := th.Client.MigrateAuthToSaml("email", map[string]string{"1": "a"}, true)
|
||||
CheckForbiddenStatus(t, err)
|
||||
|
||||
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
||||
_, err = client.MigrateAuthToSaml("email", map[string]string{"1": "a"}, true)
|
||||
CheckNotImplementedStatus(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -75,6 +75,10 @@
|
||||
"id": "api.admin.get_brand_image.storage.app_error",
|
||||
"translation": "Image storage is not configured."
|
||||
},
|
||||
{
|
||||
"id": "api.admin.ldap.not_available.app_error",
|
||||
"translation": "LDAP is not available."
|
||||
},
|
||||
{
|
||||
"id": "api.admin.remove_certificate.delete.app_error",
|
||||
"translation": "An error occurred while deleting the certificate."
|
||||
@@ -1548,6 +1552,10 @@
|
||||
"id": "api.marshal_error",
|
||||
"translation": "marshal error"
|
||||
},
|
||||
{
|
||||
"id": "api.migrate_to_saml.error",
|
||||
"translation": "Unable to migrate SAML."
|
||||
},
|
||||
{
|
||||
"id": "api.oauth.allow_oauth.redirect_callback.app_error",
|
||||
"translation": "invalid_request: Supplied redirect_uri did not match registered callback_url."
|
||||
|
||||
@@ -4053,6 +4053,32 @@ func (c *Client4) GetGroupsByUserId(userId string) ([]*Group, *Response) {
|
||||
return GroupsFromJson(r.Body), BuildResponse(r)
|
||||
}
|
||||
|
||||
func (c *Client4) MigrateAuthToLdap(fromAuthService string, matchField string, force bool) (bool, *Response) {
|
||||
r, err := c.DoApiPost(c.GetUsersRoute()+"/migrate_auth/ldap", StringInterfaceToJson(map[string]interface{}{
|
||||
"from": fromAuthService,
|
||||
"force": force,
|
||||
"match_field": matchField,
|
||||
}))
|
||||
if err != nil {
|
||||
return false, BuildErrorResponse(r, err)
|
||||
}
|
||||
defer closeBody(r)
|
||||
return CheckStatusOK(r), BuildResponse(r)
|
||||
}
|
||||
|
||||
func (c *Client4) MigrateAuthToSaml(fromAuthService string, usersMap map[string]string, auto bool) (bool, *Response) {
|
||||
r, err := c.DoApiPost(c.GetUsersRoute()+"/migrate_auth/saml", StringInterfaceToJson(map[string]interface{}{
|
||||
"from": fromAuthService,
|
||||
"auto": auto,
|
||||
"matches": usersMap,
|
||||
}))
|
||||
if err != nil {
|
||||
return false, BuildErrorResponse(r, err)
|
||||
}
|
||||
defer closeBody(r)
|
||||
return CheckStatusOK(r), BuildResponse(r)
|
||||
}
|
||||
|
||||
// Audits Section
|
||||
|
||||
// GetAudits returns a list of audits for the whole system.
|
||||
|
||||
Ссылка в новой задаче
Block a user