---
# System prepended metadata

title: Обратная миграция омеги

---

# Обратная миграция омеги


## миграция 1 юзера

```lua

local moonwalker = require 'moonwalker'
local fiber      = require 'fiber'
local ctx_t      = require 'ctx'
local id         = require 'breeze.local'.gen_id
local json       = require 'json'

local function is_web_role(role)
	return role.attr and role.attr.description and role.attr.description.web
end

local function get_global_domain(user)
	local global
	box.space.links.index.user:pairs{user.id, breeze.static.roles.mcs_owner.id}:grep(function(link)
		local project = breeze.models.projects.select.id(link.project)
		if project.is_domain and project.attr.mcs_global then
			global = project
		end
		return false
	end):totable()
	return global
end

local function comeback_user_migrate(ctx, get_user)
	local user = breeze.models.users.get(get_user)
	local ctx = ctx_t(ctx.log.prefix .. "_" .. user.uid)

	box.atomic(function()
		ctx.log:warn('START user %s', user.email)

		local global = get_global_domain(user)

		if not global then
			ctx.log:error('no global domain for user %s %s', user.id, user.email)
			return
		end

		local projects = box.space.projects.index.name:pairs{global.id}:map(breeze.models.projects.select.tuple):totable()
		local domain_users = box.space.users.index.domain:pairs{global.id}:map(breeze.models.users.select.tuple):totable()
		local domain_groups = box.space.groups.index.name:pairs{global.id}:map(breeze.models.groups.select.tuple):totable()

		for _, project in pairs(projects) do

			local ctx = ctx_t(ctx.log.prefix .. "_" .. project.pid)

			project:update({
				domain = breeze.static.domains.root.id;
				parent = project.id;
				is_domain = true;
			})
			ctx.log:warn('project became domain %s', project.id)

			if project.attr.services and project.attr.services.infra then
				local old_infra_id = project.id
				local delete_project = table.deepcopy(project)
				project.id = id(box.space.projects)

				ctx.log:warn('project_id (old infra_id) -> new id: %s -> %s', delete_project.id, project.id)
				delete_project:delete(ctx)
				project = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(project)))

				local infra
				if project.attr.migrate_infra_pid then
					infra = breeze.models.projects.select.pid(project.attr.migrate_infra_pid)
				end
				if not infra then
					infra = breeze.models.projects.select.pid(project.pid .. "_infra")
				end
				if not infra then
					infra  = breeze.models.projects.create(ctx, {
						is_domain  = false;
						is_service = false;
						name       = user.email;
						type       = 'infra';
						domain_id  = project.id;
					})
					ctx.log:warn('create infra %s', infra.id)
				end

				local old_project_id = infra.id
				local delete_infra = table.deepcopy(infra)
				infra.id = old_infra_id

				ctx.log:warn('infra_id (old project_id) -> old infra id: %s -> %s', delete_infra.id, infra.id)
				delete_infra:delete(ctx)
				infra = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(infra)))

				delete_project = table.deepcopy(project)
				project.id = old_project_id
				project.parent = old_project_id

				ctx.log:warn('project_id (new id) -> old project id: %s -> %s', delete_project.id, project.id)
				delete_project:delete(ctx)
				project = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(project)))

				infra.name = string.match(infra.name, "(.+) (.+)") or infra.name

				infra:update({
					domain = project.id;
					parent = project.id;
					type   = 'infra';
					name   = infra.name;
				})

				local exist, copy_link, copy_glink, role
				box.space.links.index.project_role:pairs{infra.id}
					:map(breeze.models.links.select.tuple):grep(function(link)

						role = breeze.models.roles.get({ id = link.role }, { raise = true })

						if is_web_role(role) then
							exist = breeze.models.links.select.project_user_role_domain(project.id, link.user, link.role, link.is_domain)
							if user and not exist then
								local l = breeze.models.links.create(ctx, {
									project = project.id;
									user    = link.user;
									role    = link.role;
									is_domain     = link.is_domain;
									is_inherited  = link.is_inherited;
									no_user_check = true;
								})
								ctx.log:warn('copy link from infra to project, new_link: %s [%s]', l.id, link.id)
							end
						end
					end):totable()

				box.space.group_links.index.project_role:pairs{infra.id}
					:map(breeze.models.group_links.select.tuple):grep(function(glink)

						role = breeze.models.roles.get({ id = glink.role }, { raise = true })

						if is_web_role(role) then
							exist = breeze.models.group_links.select.project_group_role_domain(project.id, glink.user, glink.role, glink.is_domain)
							if user and not exist then
								local gl = breeze.models.group_links.create(ctx, {
									project = project.id;
									group   = glink.group;
									role    = glink.role;
									is_domain    = glink.is_domain;
									is_inherited = glink.is_inherited;
								})
								ctx.log:warn('copy group_link from infra to project, new_link: %s [%s]', gl.id, glink.id)
							end
						end
					end):totable()
			end

			breeze.models.links.create(ctx, {
				project = project.id;
				user    = user.id;
				role    = breeze.static.roles.mcs_owner.id;
				is_domain = false;
				is_inherited = true;
			})

			for _, user in pairs(domain_users) do
				if user.attr.from_project == project.pid then
					ctx.log:warn('user changed domain: %s -> %s', user.domain, project.id)
					user:update({
						domain = project.id;
					})
				end
			end

			for _, group in pairs(domain_groups) do
				if group.attr.from_project == project.pid then
					ctx.log:warn('group changed domain: %s -> %s', group.domain, project.id)
					group:update({
						domain = project.id;
					})
				end
			end
		end

		local links = global:list_links()
		for _, link in pairs(links.links) do
			link:delete()
		end
		for _, link in pairs(links.group_links) do
			link:delete()
		end
		global:delete()

		ctx.log:warn('END success user %s', user.email)
	end)
end


local email = "nastya-241197@mail.ru"

return comeback_user_migrate(ctx_t("MIGRATE_BACK"), {email = email})
```


## миграция всех юзеров

```lua

local moonwalker = require 'moonwalker'
local fiber      = require 'fiber'
local ctx_t      = require 'ctx'
local id         = require 'breeze.local'.gen_id
local json       = require 'json'

local function is_web_role(role)
	return role.attr and role.attr.description and role.attr.description.web
end

local function get_global_domain(user)
	local global
	box.space.links.index.user:pairs{user.id, breeze.static.roles.mcs_owner.id}:grep(function(link)
		local project = breeze.models.projects.select.id(link.project)
		if project.is_domain and project.attr.mcs_global then
			global = project
		end
		return false
	end):totable()
	return global
end

local function comeback_user_migrate(ctx, get_user)
	local user = breeze.models.users.get(get_user)
	local ctx = ctx_t(ctx.log.prefix .. "_" .. user.uid)

	box.atomic(function()
		ctx.log:warn('START user %s', user.email)

		local global = get_global_domain(user)

		if not global then
			ctx.log:error('no global domain for user %s %s', user.id, user.email)
			return
		end

		local projects = box.space.projects.index.name:pairs{global.id}:map(breeze.models.projects.select.tuple):totable()
		local domain_users = box.space.users.index.domain:pairs{global.id}:map(breeze.models.users.select.tuple):totable()
		local domain_groups = box.space.groups.index.name:pairs{global.id}:map(breeze.models.groups.select.tuple):totable()

		for _, project in pairs(projects) do

			local ctx = ctx_t(ctx.log.prefix .. "_" .. project.pid)

			project:update({
				domain = breeze.static.domains.root.id;
				parent = project.id;
				is_domain = true;
			})
			ctx.log:warn('project became domain %s', project.id)

			if project.attr.services and project.attr.services.infra then
				local old_infra_id = project.id
				local delete_project = table.deepcopy(project)
				project.id = id(box.space.projects)

				ctx.log:warn('project_id (old infra_id) -> new id: %s -> %s', delete_project.id, project.id)
				delete_project:delete(ctx)
				project = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(project)))

				local infra
				if project.attr.migrate_infra_pid then
					infra = breeze.models.projects.select.pid(project.attr.migrate_infra_pid)
				end
				if not infra then
					infra = breeze.models.projects.select.pid(project.pid .. "_infra")
				end
				if not infra then
					infra  = breeze.models.projects.create(ctx, {
						is_domain  = false;
						is_service = false;
						name       = user.email;
						type       = 'infra';
						domain_id  = project.id;
					})
					ctx.log:warn('create infra %s', infra.id)
				end

				local old_project_id = infra.id
				local delete_infra = table.deepcopy(infra)
				infra.id = old_infra_id

				ctx.log:warn('infra_id (old project_id) -> old infra id: %s -> %s', delete_infra.id, infra.id)
				delete_infra:delete(ctx)
				infra = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(infra)))

				delete_project = table.deepcopy(project)
				project.id = old_project_id
				project.parent = old_project_id

				ctx.log:warn('project_id (new id) -> old project id: %s -> %s', delete_project.id, project.id)
				delete_project:delete(ctx)
				project = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(project)))

				infra.name = string.match(infra.name, "(.+) (.+)") or infra.name

				infra:update({
					domain = project.id;
					parent = project.id;
					type   = 'infra';
					name   = infra.name;
				})

				local exist, copy_link, copy_glink, role
				box.space.links.index.project_role:pairs{infra.id}
					:map(breeze.models.links.select.tuple):grep(function(link)

						role = breeze.models.roles.get({ id = link.role }, { raise = true })

						if is_web_role(role) then
							exist = breeze.models.links.select.project_user_role_domain(project.id, link.user, link.role, link.is_domain)
							if user and not exist then
								local l = breeze.models.links.create(ctx, {
									project = project.id;
									user    = link.user;
									role    = link.role;
									is_domain     = link.is_domain;
									is_inherited  = link.is_inherited;
									no_user_check = true;
								})
								ctx.log:warn('copy link from infra to project, new_link: %s [%s]', l.id, link.id)
							end
						end
					end):totable()

				box.space.group_links.index.project_role:pairs{infra.id}
					:map(breeze.models.group_links.select.tuple):grep(function(glink)

						role = breeze.models.roles.get({ id = glink.role }, { raise = true })

						if is_web_role(role) then
							exist = breeze.models.group_links.select.project_group_role_domain(project.id, glink.user, glink.role, glink.is_domain)
							if user and not exist then
								local gl = breeze.models.group_links.create(ctx, {
									project = project.id;
									group   = glink.group;
									role    = glink.role;
									is_domain    = glink.is_domain;
									is_inherited = glink.is_inherited;
								})
								ctx.log:warn('copy group_link from infra to project, new_link: %s [%s]', gl.id, glink.id)
							end
						end
					end):totable()
			end

			breeze.models.links.create(ctx, {
				project = project.id;
				user    = user.id;
				role    = breeze.static.roles.mcs_owner.id;
				is_domain = false;
				is_inherited = true;
			})

			for _, user in pairs(domain_users) do
				if user.attr.from_project == project.pid then
					ctx.log:warn('user changed domain: %s -> %s', user.domain, project.id)
					user:update({
						domain = project.id;
					})
				end
			end

			for _, group in pairs(domain_groups) do
				if group.attr.from_project == project.pid then
					ctx.log:warn('group changed domain: %s -> %s', group.domain, project.id)
					group:update({
						domain = project.id;
					})
				end
			end
		end

		local links = global:list_links()
		for _, link in pairs(links.links) do
			link:delete()
		end
		for _, link in pairs(links.group_links) do
			link:delete()
		end
		global:delete()

		ctx.log:warn('END success user %s', user.email)
	end)
end

local function comeback_projects_migrate()
	local name = 'COMEBACK_MIGRATE_PROJECTS'
	local count = 0
	local ctx = ctx_t(name)
	moonwalker {
		name     = name;
		progress = '1%';
		space    = box.space.users;
		actor = function(u)
			local ok, err = pcall(comeback_user_migrate, ctx, {id = u.id})
			if not ok then
				ctx.log:error('dont migrate user %s, error: %s', u.email, json.encode(err))
				count = count + 1
			end
		end;
	}
	return ("dont migrate back %s users"):format(count)
end

return comeback_projects_migrate()
```