Exemple #1
0
def copy_snapshot(request, domain):
    user = request.couch_user
    if not user.is_eula_signed():
        messages.error(request,
                       'You must agree to our eula to download an app')
        return project_info(request, domain)

    dom = Domain.get(domain)
    if request.method == "POST" and dom.is_snapshot:
        from corehq.apps.registration.forms import DomainRegistrationForm
        args = {
            'domain_name': request.POST['new_project_name'],
            'eula_confirmed': True
        }
        form = DomainRegistrationForm(args)

        if request.POST.get('new_project_name', ""):
            if not dom.published:
                messages.error(
                    request,
                    "This project is not published and can't be downloaded")
                return project_info(request, domain)

            if form.is_valid():
                new_domain = dom.save_copy(form.cleaned_data['domain_name'],
                                           user=user)
            else:
                messages.error(request, form.errors)
                return project_info(request, domain)

            if new_domain is None:
                messages.error(request,
                               _("A project by that name already exists"))
                return project_info(request, domain)

            def inc_downloads(d):
                d.downloads += 1

            apply_update(dom, inc_downloads)

            # sign project up for trial
            create_30_day_trial(new_domain)

            messages.success(request,
                             render_to_string(
                                 "appstore/partials/view_wiki.html",
                                 {"pre": _("Project copied successfully!")}),
                             extra_tags="html")
            return HttpResponseRedirect(
                reverse('view_app',
                        args=[
                            new_domain.name,
                            new_domain.full_applications()[0].get_id
                        ]))
        else:
            messages.error(request,
                           _("You must specify a name for the new project"))
            return project_info(request, domain)
    else:
        return HttpResponseRedirect(reverse('project_info', args=[domain]))
Exemple #2
0
    def save_copy(self, new_domain_name=None, user=None):
        from corehq.apps.app_manager.models import get_app
        if new_domain_name is not None and Domain.get_by_name(new_domain_name):
            return None
        db = get_db()

        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id
        new_domain = Domain.get(new_id)
        new_domain.name = new_domain_name
        new_domain.copy_history = self.get_updated_history()
        new_domain.is_snapshot = False
        new_domain.snapshot_time = None
        new_domain.organization = None  # TODO: use current user's organization (?)

        # reset the cda
        new_domain.cda.signed = False
        new_domain.cda.date = None
        new_domain.cda.type = None
        new_domain.cda.user_id = None
        new_domain.cda.user_ip = None

        for field in self._dirty_fields:
            if hasattr(new_domain, field):
                delattr(new_domain, field)

        for res in db.view('domain/related_to_domain', key=[self.name, True]):
            if not self.is_snapshot and res['value']['doc_type'] in (
                    'Application', 'RemoteApp'):
                app = get_app(self.name,
                              res['value']['_id']).get_latest_saved()
                if app:
                    self.copy_component(app.doc_type,
                                        app._id,
                                        new_domain_name,
                                        user=user)
                else:
                    self.copy_component(res['value']['doc_type'],
                                        res['value']['_id'],
                                        new_domain_name,
                                        user=user)
            else:
                self.copy_component(res['value']['doc_type'],
                                    res['value']['_id'],
                                    new_domain_name,
                                    user=user)

        new_domain.save()

        if user:

            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)

            apply_update(user, add_dom_to_user)

        return new_domain
Exemple #3
0
def copy_snapshot(request, snapshot):
    user = request.couch_user
    if not user.is_eula_signed():
        messages.error(request, _('You must agree to our terms of service to download an app'))
        return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))

    domain_obj = Domain.get(snapshot)
    if request.method == "POST" and domain_obj.is_snapshot:
        assert domain_obj.full_applications(include_builds=False), 'Bad attempt to copy project without any apps!'

        from corehq.apps.registration.forms import DomainRegistrationForm

        args = {
            'domain_name': request.POST['new_project_name'],
            'hr_name': request.POST['new_project_name'],
            'eula_confirmed': True,
        }
        form = DomainRegistrationForm(args)

        if request.POST.get('new_project_name', ""):
            if not domain_obj.published:
                messages.error(request, _("This project is not published and can't be downloaded"))
                return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))

            if not form.is_valid():
                messages.error(request, form.errors)
                return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))

            new_domain_name = name_to_url(form.cleaned_data['hr_name'], "project")
            with CriticalSection(['copy_domain_snapshot_{}_to_{}'.format(domain_obj.name, new_domain_name)]):
                try:
                    new_domain = domain_obj.save_copy(new_domain_name,
                                                      new_hr_name=form.cleaned_data['hr_name'],
                                                      user=user)
                    if new_domain.commtrack_enabled:
                        new_domain.convert_to_commtrack()
                    ensure_explicit_community_subscription(
                        new_domain.name, date.today(), SubscriptionAdjustmentMethod.USER,
                        web_user=user.username,
                    )
                except NameUnavailableException:
                    messages.error(request, _("A project by that name already exists"))
                    return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))

            def inc_downloads(d):
                d.downloads += 1

            apply_update(domain_obj, inc_downloads)
            messages.success(request, render_to_string("appstore/partials/view_wiki.html",
                                                       {"pre": _("Project copied successfully!")}),
                             extra_tags="html")
            return HttpResponseRedirect(reverse('view_app',
                                                args=[new_domain.name, new_domain.full_applications()[0].get_id]))
        else:
            messages.error(request, _("You must specify a name for the new project"))
            return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))
    else:
        return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))
Exemple #4
0
def copy_snapshot(request, snapshot):
    user = request.couch_user
    if not user.is_eula_signed():
        messages.error(request, _('You must agree to our terms of service to download an app'))
        return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))

    domain_obj = Domain.get(snapshot)
    if request.method == "POST" and domain_obj.is_snapshot:
        assert domain_obj.full_applications(include_builds=False), 'Bad attempt to copy project without any apps!'

        from corehq.apps.registration.forms import DomainRegistrationForm

        args = {
            'domain_name': request.POST['new_project_name'],
            'hr_name': request.POST['new_project_name'],
            'eula_confirmed': True,
        }
        form = DomainRegistrationForm(args)

        if request.POST.get('new_project_name', ""):
            if not domain_obj.published:
                messages.error(request, _("This project is not published and can't be downloaded"))
                return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))

            if not form.is_valid():
                messages.error(request, form.errors)
                return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))

            new_domain_name = name_to_url(form.cleaned_data['hr_name'], "project")
            with CriticalSection(['copy_domain_snapshot_{}_to_{}'.format(domain_obj.name, new_domain_name)]):
                try:
                    new_domain = domain_obj.save_copy(new_domain_name,
                                                      new_hr_name=form.cleaned_data['hr_name'],
                                                      user=user)
                    if new_domain.commtrack_enabled:
                        new_domain.convert_to_commtrack()
                    ensure_explicit_community_subscription(
                        new_domain.name, date.today(), SubscriptionAdjustmentMethod.USER,
                        web_user=user.username,
                    )
                except NameUnavailableException:
                    messages.error(request, _("A project by that name already exists"))
                    return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))

            def inc_downloads(d):
                d.downloads += 1

            apply_update(domain_obj, inc_downloads)
            messages.success(request, render_to_string("appstore/partials/view_wiki.html",
                                                       {"pre": _("Project copied successfully!")}),
                             extra_tags="html")
            return HttpResponseRedirect(reverse('view_app',
                                                args=[new_domain.name, new_domain.full_applications()[0].get_id]))
        else:
            messages.error(request, _("You must specify a name for the new project"))
            return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))
    else:
        return HttpResponseRedirect(reverse(ProjectInformationView.urlname, args=[snapshot]))
Exemple #5
0
def copy_snapshot(request, domain):
    user = request.couch_user
    if not user.is_eula_signed():
        messages.error(request, 'You must agree to our eula to download an app')
        return project_info(request, domain)

    dom = Domain.get(domain)
    if request.method == "POST" and dom.is_snapshot:
        assert dom.full_applications(include_builds=False), 'Bad attempt to copy project without any apps!'

        from corehq.apps.registration.forms import DomainRegistrationForm

        args = {
            'domain_name': request.POST['new_project_name'],
            'hr_name': request.POST['new_project_name'],
            'eula_confirmed': True,
        }
        form = DomainRegistrationForm(args)

        if request.POST.get('new_project_name', ""):
            if not dom.published:
                messages.error(request, _("This project is not published and can't be downloaded"))
                return project_info(request, domain)

            if not form.is_valid():
                messages.error(request, form.errors)
                return project_info(request, domain)

            new_domain_name = name_to_url(form.cleaned_data['hr_name'], "project")
            with CriticalSection(['copy_domain_snapshot_{}_to_{}'.format(dom.name, new_domain_name)]):
                try:
                    new_domain = dom.save_copy(new_domain_name,
                                               new_hr_name=form.cleaned_data['hr_name'],
                                               user=user)
                except NameUnavailableException:
                    messages.error(request, _("A project by that name already exists"))
                    return project_info(request, domain)

                # sign new project up for trial
                create_30_day_trial(new_domain)

            def inc_downloads(d):
                d.downloads += 1

            apply_update(dom, inc_downloads)
            messages.success(request, render_to_string("appstore/partials/view_wiki.html",
                                                       {"pre": _("Project copied successfully!")}),
                             extra_tags="html")
            return HttpResponseRedirect(reverse('view_app',
                                                args=[new_domain.name, new_domain.full_applications()[0].get_id]))
        else:
            messages.error(request, _("You must specify a name for the new project"))
            return project_info(request, domain)
    else:
        return HttpResponseRedirect(reverse('project_info', args=[domain]))
Exemple #6
0
    def save_copy(self, new_domain_name=None, user=None):
        from corehq.apps.app_manager.models import get_app

        if new_domain_name is not None and Domain.get_by_name(new_domain_name):
            return None
        db = get_db()

        new_id = db.copy_doc(self.get_id)["id"]
        if new_domain_name is None:
            new_domain_name = new_id
        new_domain = Domain.get(new_id)
        new_domain.name = new_domain_name
        new_domain.copy_history = self.get_updated_history()
        new_domain.is_snapshot = False
        new_domain.snapshot_time = None
        new_domain.organization = None  # TODO: use current user's organization (?)

        # reset stuff
        new_domain.cda.signed = False
        new_domain.cda.date = None
        new_domain.cda.type = None
        new_domain.cda.user_id = None
        new_domain.cda.user_ip = None
        new_domain.is_test = True
        new_domain.internal = InternalProperties()
        new_domain.creating_user = user.username if user else None

        for field in self._dirty_fields:
            if hasattr(new_domain, field):
                delattr(new_domain, field)

        for res in db.view("domain/related_to_domain", key=[self.name, True]):
            if not self.is_snapshot and res["value"]["doc_type"] in ("Application", "RemoteApp"):
                app = get_app(self.name, res["value"]["_id"]).get_latest_saved()
                if app:
                    self.copy_component(app.doc_type, app._id, new_domain_name, user=user)
                else:
                    self.copy_component(res["value"]["doc_type"], res["value"]["_id"], new_domain_name, user=user)
            else:
                self.copy_component(res["value"]["doc_type"], res["value"]["_id"], new_domain_name, user=user)

        new_domain.save()

        if user:

            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)

            apply_update(user, add_dom_to_user)

        return new_domain
Exemple #7
0
def copy_snapshot(request, domain):
    user = request.couch_user
    if not user.is_eula_signed():
        messages.error(request, 'You must agree to our eula to download an app')
        return project_info(request, domain)

    dom = Domain.get(domain)
    if request.method == "POST" and dom.is_snapshot:
        from corehq.apps.registration.forms import DomainRegistrationForm
        args = {'domain_name': request.POST['new_project_name'], 'eula_confirmed': True}
        form = DomainRegistrationForm(args)

        if request.POST.get('new_project_name', ""):
            if not dom.published:
                messages.error(request, "This project is not published and can't be downloaded")
                return project_info(request, domain)

            if form.is_valid():
                new_domain = dom.save_copy(form.cleaned_data['domain_name'], user=user)
            else:
                messages.error(request, form.errors)
                return project_info(request, domain)

            if new_domain is None:
                messages.error(request, _("A project by that name already exists"))
                return project_info(request, domain)

            def inc_downloads(d):
                d.downloads += 1

            apply_update(dom, inc_downloads)

            # sign project up for trial
            create_30_day_trial(new_domain)

            messages.success(request, render_to_string("appstore/partials/view_wiki.html", {"pre": _("Project copied successfully!")}), extra_tags="html")
            return HttpResponseRedirect(reverse('view_app',
                args=[new_domain.name, new_domain.full_applications()[0].get_id]))
        else:
            messages.error(request, _("You must specify a name for the new project"))
            return project_info(request, domain)
    else:
        return HttpResponseRedirect(reverse('project_info', args=[domain]))
Exemple #8
0
    def save_copy(self,
                  new_domain_name=None,
                  new_hr_name=None,
                  user=None,
                  copy_by_id=None,
                  share_reminders=True,
                  share_user_roles=True):
        from corehq.apps.app_manager.dbaccessors import get_app
        from corehq.apps.reminders.models import CaseReminderHandler
        from corehq.apps.fixtures.models import FixtureDataItem
        from corehq.apps.app_manager.dbaccessors import get_brief_apps_in_domain
        from corehq.apps.domain.dbaccessors import get_doc_ids_in_domain_by_class
        from corehq.apps.fixtures.models import FixtureDataType
        from corehq.apps.users.models import UserRole

        db = Domain.get_db()
        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id

        with CriticalSection(
            ['request_domain_name_{}'.format(new_domain_name)]):
            new_domain_name = Domain.generate_name(new_domain_name)
            new_domain = Domain.get(new_id)
            new_domain.name = new_domain_name
            new_domain.hr_name = new_hr_name
            new_domain.copy_history = self.get_updated_history()
            new_domain.is_snapshot = False
            new_domain.snapshot_time = None
            new_domain.organization = None  # TODO: use current user's organization (?)

            # reset stuff
            new_domain.cda.signed = False
            new_domain.cda.date = None
            new_domain.cda.type = None
            new_domain.cda.user_id = None
            new_domain.cda.user_ip = None
            new_domain.is_test = "none"
            new_domain.internal = InternalProperties()
            new_domain.creating_user = user.username if user else None

            for field in self._dirty_fields:
                if hasattr(new_domain, field):
                    delattr(new_domain, field)

            # Saving the domain should happen before we import any apps since
            # importing apps can update the domain object (for example, if user
            # as a case needs to be enabled)
            new_domain.save()

            new_app_components = {}  # a mapping of component's id to its copy

            def copy_data_items(old_type_id, new_type_id):
                for item in FixtureDataItem.by_data_type(
                        self.name, old_type_id):
                    comp = self.copy_component(item.doc_type,
                                               item._id,
                                               new_domain_name,
                                               user=user)
                    comp.data_type_id = new_type_id
                    comp.save()

            def get_latest_app_id(doc_id):
                app = get_app(self.name, doc_id).get_latest_saved()
                if app:
                    return app._id, app.doc_type

            for app in get_brief_apps_in_domain(self.name):
                doc_id, doc_type = app.get_id, app.doc_type
                original_doc_id = doc_id
                if copy_by_id and doc_id not in copy_by_id:
                    continue
                if not self.is_snapshot:
                    doc_id, doc_type = get_latest_app_id(doc_id) or (doc_id,
                                                                     doc_type)
                component = self.copy_component(doc_type,
                                                doc_id,
                                                new_domain_name,
                                                user=user)
                if component:
                    new_app_components[original_doc_id] = component

            for doc_id in get_doc_ids_in_domain_by_class(
                    self.name, FixtureDataType):
                if copy_by_id and doc_id not in copy_by_id:
                    continue
                component = self.copy_component('FixtureDataType',
                                                doc_id,
                                                new_domain_name,
                                                user=user)
                copy_data_items(doc_id, component._id)

            if share_reminders:
                for doc_id in get_doc_ids_in_domain_by_class(
                        self.name, CaseReminderHandler):
                    self.copy_component('CaseReminderHandler',
                                        doc_id,
                                        new_domain_name,
                                        user=user)
            if share_user_roles:
                for doc_id in get_doc_ids_in_domain_by_class(
                        self.name, UserRole):
                    self.copy_component('UserRole',
                                        doc_id,
                                        new_domain_name,
                                        user=user)

        if user:

            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)

            apply_update(user, add_dom_to_user)

        def update_events(handler):
            """
            Change the form_unique_id to the proper form for each event in a newly copied CaseReminderHandler
            """
            from corehq.apps.app_manager.models import FormBase
            for event in handler.events:
                if not event.form_unique_id:
                    continue
                form = FormBase.get_form(event.form_unique_id)
                form_app = form.get_app()
                m_index, f_index = form_app.get_form_location(form.unique_id)
                form_copy = new_app_components[form_app._id].get_module(
                    m_index).get_form(f_index)
                event.form_unique_id = form_copy.unique_id

        def update_for_copy(handler):
            handler.active = False
            update_events(handler)

        if share_reminders:
            for handler in CaseReminderHandler.get_handlers(new_domain_name):
                apply_update(handler, update_for_copy)

        return new_domain
Exemple #9
0
    def save_copy(self, new_domain_name=None, user=None, ignore=None):
        from corehq.apps.app_manager.models import get_app
        from corehq.apps.reminders.models import CaseReminderHandler

        ignore = ignore if ignore is not None else []
        if new_domain_name is not None and Domain.get_by_name(new_domain_name):
            return None
        db = get_db()

        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id
        new_domain = Domain.get(new_id)
        new_domain.name = new_domain_name
        new_domain.copy_history = self.get_updated_history()
        new_domain.is_snapshot = False
        new_domain.snapshot_time = None
        new_domain.organization = None # TODO: use current user's organization (?)

        # reset stuff
        new_domain.cda.signed = False
        new_domain.cda.date = None
        new_domain.cda.type = None
        new_domain.cda.user_id = None
        new_domain.cda.user_ip = None
        new_domain.is_test = "none"
        new_domain.internal = InternalProperties()
        new_domain.creating_user = user.username if user else None

        for field in self._dirty_fields:
            if hasattr(new_domain, field):
                delattr(new_domain, field)

        new_comps = {}  # a mapping of component's id to it's copy
        for res in db.view('domain/related_to_domain', key=[self.name, True]):
            if not self.is_snapshot and res['value']['doc_type'] in ('Application', 'RemoteApp'):
                app = get_app(self.name, res['value']['_id']).get_latest_saved()
                if app:
                    comp = self.copy_component(app.doc_type, app._id, new_domain_name, user=user)
                else:
                    comp = self.copy_component(res['value']['doc_type'], res['value']['_id'], new_domain_name, user=user)
            elif res['value']['doc_type'] not in ignore:
                comp = self.copy_component(res['value']['doc_type'], res['value']['_id'], new_domain_name, user=user)
            else:
                comp = None
            if comp:
                new_comps[res['value']['_id']] = comp

        new_domain.save()

        if user:
            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)
            apply_update(user, add_dom_to_user)

        def update_events(handler):
            """
            Change the form_unique_id to the proper form for each event in a newly copied CaseReminderHandler
            """
            from corehq.apps.app_manager.models import FormBase
            for event in handler.events:
                if not event.form_unique_id:
                    continue
                form = FormBase.get_form(event.form_unique_id)
                form_app = form.get_app()
                m_index, f_index = form_app.get_form_location(form.unique_id)
                form_copy = new_comps[form_app._id].get_module(m_index).get_form(f_index)
                event.form_unique_id = form_copy.unique_id

        def update_for_copy(handler):
            handler.active = False
            update_events(handler)

        if 'CaseReminderHandler' not in ignore:
            for handler in CaseReminderHandler.get_handlers(new_domain_name):
                apply_update(handler, update_for_copy)

        return new_domain
Exemple #10
0
    def save_copy(self, new_domain_name=None, user=None, ignore=None):
        from corehq.apps.app_manager.models import get_app
        from corehq.apps.reminders.models import CaseReminderHandler

        ignore = ignore if ignore is not None else []
        if new_domain_name is not None and Domain.get_by_name(new_domain_name):
            return None
        db = get_db()

        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id
        new_domain = Domain.get(new_id)
        new_domain.name = new_domain_name
        new_domain.copy_history = self.get_updated_history()
        new_domain.is_snapshot = False
        new_domain.snapshot_time = None
        new_domain.organization = None  # TODO: use current user's organization (?)

        # reset stuff
        new_domain.cda.signed = False
        new_domain.cda.date = None
        new_domain.cda.type = None
        new_domain.cda.user_id = None
        new_domain.cda.user_ip = None
        new_domain.is_test = "none"
        new_domain.internal = InternalProperties()
        new_domain.creating_user = user.username if user else None

        for field in self._dirty_fields:
            if hasattr(new_domain, field):
                delattr(new_domain, field)

        new_comps = {}  # a mapping of component's id to it's copy
        for res in db.view('domain/related_to_domain', key=[self.name, True]):
            if not self.is_snapshot and res['value']['doc_type'] in (
                    'Application', 'RemoteApp'):
                app = get_app(self.name,
                              res['value']['_id']).get_latest_saved()
                if app:
                    comp = self.copy_component(app.doc_type,
                                               app._id,
                                               new_domain_name,
                                               user=user)
                else:
                    comp = self.copy_component(res['value']['doc_type'],
                                               res['value']['_id'],
                                               new_domain_name,
                                               user=user)
            elif res['value']['doc_type'] not in ignore:
                comp = self.copy_component(res['value']['doc_type'],
                                           res['value']['_id'],
                                           new_domain_name,
                                           user=user)
            else:
                comp = None
            if comp:
                new_comps[res['value']['_id']] = comp

        new_domain.save()

        if user:

            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)

            apply_update(user, add_dom_to_user)

        def update_events(handler):
            """
            Change the form_unique_id to the proper form for each event in a newly copied CaseReminderHandler
            """
            from corehq.apps.app_manager.models import FormBase
            for event in handler.events:
                if not event.form_unique_id:
                    continue
                form = FormBase.get_form(event.form_unique_id)
                form_app = form.get_app()
                m_index, f_index = form_app.get_form_location(form.unique_id)
                form_copy = new_comps[form_app._id].get_module(
                    m_index).get_form(f_index)
                event.form_unique_id = form_copy.unique_id

        def update_for_copy(handler):
            handler.active = False
            update_events(handler)

        if 'CaseReminderHandler' not in ignore:
            for handler in CaseReminderHandler.get_handlers(new_domain_name):
                apply_update(handler, update_for_copy)

        return new_domain
Exemple #11
0
    def save_copy(self, new_domain_name=None, new_hr_name=None, user=None,
                  copy_by_id=None, share_reminders=True,
                  share_user_roles=True):
        from corehq.apps.app_manager.dbaccessors import get_app
        from corehq.apps.data_interfaces.models import AutomaticUpdateRule
        from corehq.apps.fixtures.models import FixtureDataItem
        from corehq.apps.app_manager.dbaccessors import get_brief_apps_in_domain
        from corehq.apps.domain.dbaccessors import get_doc_ids_in_domain_by_class
        from corehq.apps.fixtures.models import FixtureDataType
        from corehq.apps.users.models import UserRole

        db = Domain.get_db()
        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id

        with CriticalSection(['request_domain_name_{}'.format(new_domain_name)]):
            new_domain_name = Domain.generate_name(new_domain_name)
            new_domain = Domain.get(new_id)
            new_domain.name = new_domain_name
            new_domain.hr_name = new_hr_name
            new_domain.copy_history = self.get_updated_history()
            new_domain.is_snapshot = False
            new_domain.snapshot_time = None
            new_domain.organization = None  # TODO: use current user's organization (?)

            # reset stuff
            new_domain.cda.signed = False
            new_domain.cda.date = None
            new_domain.cda.type = None
            new_domain.cda.user_id = None
            new_domain.cda.user_ip = None
            new_domain.is_test = "none"
            new_domain.internal = InternalProperties()
            new_domain.creating_user = user.username if user else None
            new_domain.date_created = datetime.utcnow()
            new_domain.use_sql_backend = True
            new_domain.granted_messaging_access = False

            for field in self._dirty_fields:
                if hasattr(new_domain, field):
                    delattr(new_domain, field)

            # Saving the domain should happen before we import any apps since
            # importing apps can update the domain object (for example, if user
            # as a case needs to be enabled)
            try:
                new_domain.save()
            except PreconditionFailed:
                # This is a hack to resolve http://manage.dimagi.com/default.asp?241492
                # Following solution in
                # https://github.com/dimagi/commcare-hq/commit/d59b1e403060ade599cc4a03db0aabc4da62b668
                time.sleep(0.5)
                new_domain.save()

            new_app_components = {}  # a mapping of component's id to its copy

            def copy_data_items(old_type_id, new_type_id):
                for item in FixtureDataItem.by_data_type(self.name, old_type_id):
                    comp = self.copy_component(
                        item.doc_type, item._id, new_domain_name, user=user)
                    comp.data_type_id = new_type_id
                    comp.save()

            def get_latest_app_id(doc_id):
                app = get_app(self.name, doc_id).get_latest_saved()
                if app:
                    return app._id, app.doc_type

            for app in get_brief_apps_in_domain(self.name):
                doc_id, doc_type = app.get_id, app.doc_type
                original_doc_id = doc_id
                if copy_by_id and doc_id not in copy_by_id:
                    continue
                if not self.is_snapshot:
                    doc_id, doc_type = get_latest_app_id(doc_id) or (doc_id, doc_type)
                component = self.copy_component(doc_type, doc_id, new_domain_name, user=user)
                if component:
                    new_app_components[original_doc_id] = component

            for doc_id in get_doc_ids_in_domain_by_class(self.name, FixtureDataType):
                if copy_by_id and doc_id not in copy_by_id:
                    continue
                component = self.copy_component(
                    'FixtureDataType', doc_id, new_domain_name, user=user)
                copy_data_items(doc_id, component._id)

            def convert_form_unique_id_function(form_unique_id):
                from corehq.apps.app_manager.models import FormBase
                form = FormBase.get_form(form_unique_id)
                form_app = form.get_app()
                m_index, f_index = form_app.get_form_location(form.unique_id)
                form_copy = new_app_components[form_app._id].get_module(m_index).get_form(f_index)
                return form_copy.unique_id

            if share_reminders:
                for rule in AutomaticUpdateRule.by_domain(
                    self.name,
                    AutomaticUpdateRule.WORKFLOW_SCHEDULING,
                    active_only=False,
                ):
                    rule.copy_conditional_alert(
                        new_domain_name,
                        convert_form_unique_id_function=convert_form_unique_id_function,
                    )
            if share_user_roles:
                for doc_id in get_doc_ids_in_domain_by_class(self.name, UserRole):
                    self.copy_component('UserRole', doc_id, new_domain_name, user=user)

        if user:
            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)
            apply_update(user, add_dom_to_user)

        return new_domain
Exemple #12
0
def copy_snapshot(request, domain):
    user = request.couch_user
    if not user.is_eula_signed():
        messages.error(request,
                       'You must agree to our eula to download an app')
        return project_info(request, domain)

    dom = Domain.get(domain)
    if request.method == "POST" and dom.is_snapshot:
        assert dom.full_applications(
            include_builds=False
        ), 'Bad attempt to copy project without any apps!'

        from corehq.apps.registration.forms import DomainRegistrationForm

        args = {
            'domain_name': request.POST['new_project_name'],
            'hr_name': request.POST['new_project_name'],
            'eula_confirmed': True,
        }
        form = DomainRegistrationForm(args)

        if request.POST.get('new_project_name', ""):
            if not dom.published:
                messages.error(
                    request,
                    _("This project is not published and can't be downloaded"))
                return project_info(request, domain)

            if not form.is_valid():
                messages.error(request, form.errors)
                return project_info(request, domain)

            new_domain_name = form.cleaned_data['hr_name']
            with CriticalSection([
                    'copy_domain_snapshot_{}_to_{}'.format(
                        dom.name, new_domain_name)
            ]):
                try:
                    new_domain = dom.save_copy(
                        new_domain_name,
                        new_hr_name=form.cleaned_data['hr_name'],
                        user=user)
                except NameUnavailableException:
                    messages.error(request,
                                   _("A project by that name already exists"))
                    return project_info(request, domain)

                # sign new project up for trial
                create_30_day_trial(new_domain)

            def inc_downloads(d):
                d.downloads += 1

            apply_update(dom, inc_downloads)
            messages.success(request,
                             render_to_string(
                                 "appstore/partials/view_wiki.html",
                                 {"pre": _("Project copied successfully!")}),
                             extra_tags="html")
            return HttpResponseRedirect(
                reverse('view_app',
                        args=[
                            new_domain.name,
                            new_domain.full_applications()[0].get_id
                        ]))
        else:
            messages.error(request,
                           _("You must specify a name for the new project"))
            return project_info(request, domain)
    else:
        return HttpResponseRedirect(reverse('project_info', args=[domain]))
Exemple #13
0
    def save_copy(self, new_domain_name=None, new_hr_name=None, user=None,
                  copy_by_id=None, share_reminders=True,
                  share_user_roles=True):
        from corehq.apps.app_manager.dbaccessors import get_app
        from corehq.apps.data_interfaces.models import AutomaticUpdateRule
        from corehq.apps.reminders.models import CaseReminderHandler
        from corehq.apps.fixtures.models import FixtureDataItem
        from corehq.apps.app_manager.dbaccessors import get_brief_apps_in_domain
        from corehq.apps.domain.dbaccessors import get_doc_ids_in_domain_by_class
        from corehq.apps.fixtures.models import FixtureDataType
        from corehq.apps.users.models import UserRole

        db = Domain.get_db()
        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id

        uses_new_reminders = project_is_on_new_reminders(self)

        with CriticalSection(['request_domain_name_{}'.format(new_domain_name)]):
            new_domain_name = Domain.generate_name(new_domain_name)
            new_domain = Domain.get(new_id)
            new_domain.name = new_domain_name
            new_domain.hr_name = new_hr_name
            new_domain.copy_history = self.get_updated_history()
            new_domain.is_snapshot = False
            new_domain.snapshot_time = None
            new_domain.organization = None  # TODO: use current user's organization (?)

            # reset stuff
            new_domain.cda.signed = False
            new_domain.cda.date = None
            new_domain.cda.type = None
            new_domain.cda.user_id = None
            new_domain.cda.user_ip = None
            new_domain.is_test = "none"
            new_domain.internal = InternalProperties()
            new_domain.creating_user = user.username if user else None
            new_domain.date_created = datetime.utcnow()
            new_domain.use_sql_backend = True
            new_domain.granted_messaging_access = False

            for field in self._dirty_fields:
                if hasattr(new_domain, field):
                    delattr(new_domain, field)

            # Saving the domain should happen before we import any apps since
            # importing apps can update the domain object (for example, if user
            # as a case needs to be enabled)
            try:
                new_domain.save()
            except PreconditionFailed:
                # This is a hack to resolve http://manage.dimagi.com/default.asp?241492
                # Following solution in
                # https://github.com/dimagi/commcare-hq/commit/d59b1e403060ade599cc4a03db0aabc4da62b668
                time.sleep(0.5)
                new_domain.save()

            new_app_components = {}  # a mapping of component's id to its copy

            def copy_data_items(old_type_id, new_type_id):
                for item in FixtureDataItem.by_data_type(self.name, old_type_id):
                    comp = self.copy_component(
                        item.doc_type, item._id, new_domain_name, user=user)
                    comp.data_type_id = new_type_id
                    comp.save()

            def get_latest_app_id(doc_id):
                app = get_app(self.name, doc_id).get_latest_saved()
                if app:
                    return app._id, app.doc_type

            for app in get_brief_apps_in_domain(self.name):
                doc_id, doc_type = app.get_id, app.doc_type
                original_doc_id = doc_id
                if copy_by_id and doc_id not in copy_by_id:
                    continue
                if not self.is_snapshot:
                    doc_id, doc_type = get_latest_app_id(doc_id) or (doc_id, doc_type)
                component = self.copy_component(doc_type, doc_id, new_domain_name, user=user)
                if component:
                    new_app_components[original_doc_id] = component

            for doc_id in get_doc_ids_in_domain_by_class(self.name, FixtureDataType):
                if copy_by_id and doc_id not in copy_by_id:
                    continue
                component = self.copy_component(
                    'FixtureDataType', doc_id, new_domain_name, user=user)
                copy_data_items(doc_id, component._id)

            def convert_form_unique_id_function(form_unique_id):
                from corehq.apps.app_manager.models import FormBase
                form = FormBase.get_form(form_unique_id)
                form_app = form.get_app()
                m_index, f_index = form_app.get_form_location(form.unique_id)
                form_copy = new_app_components[form_app._id].get_module(m_index).get_form(f_index)
                return form_copy.unique_id

            if share_reminders:
                if uses_new_reminders:
                    for rule in AutomaticUpdateRule.by_domain(
                        self.name,
                        AutomaticUpdateRule.WORKFLOW_SCHEDULING,
                        active_only=False,
                    ):
                        rule.copy_conditional_alert(
                            new_domain_name,
                            convert_form_unique_id_function=convert_form_unique_id_function,
                        )
                else:
                    for doc_id in get_doc_ids_in_domain_by_class(self.name, CaseReminderHandler):
                        self.copy_component(
                            'CaseReminderHandler', doc_id, new_domain_name, user=user)
            if share_user_roles:
                for doc_id in get_doc_ids_in_domain_by_class(self.name, UserRole):
                    self.copy_component('UserRole', doc_id, new_domain_name, user=user)

        if user:
            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)
            apply_update(user, add_dom_to_user)

        if not uses_new_reminders:
            # When uses_new_reminders is True, all of this is already taken care of
            # in the copy process
            def update_events(handler):
                """
                Change the form_unique_id to the proper form for each event in a newly copied CaseReminderHandler
                """
                for event in handler.events:
                    if not event.form_unique_id:
                        continue
                    event.form_unique_id = convert_form_unique_id_function(event.form_unique_id)

            def update_for_copy(handler):
                handler.active = False
                update_events(handler)

            if share_reminders:
                for handler in CaseReminderHandler.get_handlers(new_domain_name):
                    apply_update(handler, update_for_copy)

        return new_domain
Exemple #14
0
    def save_copy(self, new_domain_name=None, new_hr_name=None, user=None,
                  copy_by_id=None, share_reminders=True,
                  share_user_roles=True):
        from corehq.apps.app_manager.dbaccessors import get_app
        from corehq.apps.reminders.models import CaseReminderHandler
        from corehq.apps.fixtures.models import FixtureDataItem
        from corehq.apps.app_manager.dbaccessors import get_brief_apps_in_domain
        from corehq.apps.domain.dbaccessors import get_doc_ids_in_domain_by_class
        from corehq.apps.fixtures.models import FixtureDataType
        from corehq.apps.users.models import UserRole

        db = Domain.get_db()
        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id

        with CriticalSection(['request_domain_name_{}'.format(new_domain_name)]):
            new_domain_name = Domain.generate_name(new_domain_name)
            new_domain = Domain.get(new_id)
            new_domain.name = new_domain_name
            new_domain.hr_name = new_hr_name
            new_domain.copy_history = self.get_updated_history()
            new_domain.is_snapshot = False
            new_domain.snapshot_time = None
            new_domain.organization = None  # TODO: use current user's organization (?)

            # reset stuff
            new_domain.cda.signed = False
            new_domain.cda.date = None
            new_domain.cda.type = None
            new_domain.cda.user_id = None
            new_domain.cda.user_ip = None
            new_domain.is_test = "none"
            new_domain.internal = InternalProperties()
            new_domain.creating_user = user.username if user else None

            for field in self._dirty_fields:
                if hasattr(new_domain, field):
                    delattr(new_domain, field)

            new_app_components = {}  # a mapping of component's id to its copy

            def copy_data_items(old_type_id, new_type_id):
                for item in FixtureDataItem.by_data_type(self.name, old_type_id):
                    comp = self.copy_component(
                        item.doc_type, item._id, new_domain_name, user=user)
                    comp.data_type_id = new_type_id
                    comp.save()

            def get_latest_app_id(doc_id):
                app = get_app(self.name, doc_id).get_latest_saved()
                if app:
                    return app._id, app.doc_type

            for app in get_brief_apps_in_domain(self.name):
                doc_id, doc_type = app.get_id, app.doc_type
                original_doc_id = doc_id
                if copy_by_id and doc_id not in copy_by_id:
                    continue
                if not self.is_snapshot:
                    doc_id, doc_type = get_latest_app_id(doc_id) or (doc_id, doc_type)
                component = self.copy_component(doc_type, doc_id, new_domain_name, user=user)
                if component:
                    new_app_components[original_doc_id] = component

            for doc_id in get_doc_ids_in_domain_by_class(self.name, FixtureDataType):
                if copy_by_id and doc_id not in copy_by_id:
                    continue
                component = self.copy_component(
                    'FixtureDataType', doc_id, new_domain_name, user=user)
                copy_data_items(doc_id, component._id)

            if share_reminders:
                for doc_id in get_doc_ids_in_domain_by_class(self.name, CaseReminderHandler):
                    self.copy_component(
                        'CaseReminderHandler', doc_id, new_domain_name, user=user)
            if share_user_roles:
                for doc_id in get_doc_ids_in_domain_by_class(self.name, UserRole):
                    self.copy_component('UserRole', doc_id, new_domain_name, user=user)

            new_domain.save()

        if user:
            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)
            apply_update(user, add_dom_to_user)

        def update_events(handler):
            """
            Change the form_unique_id to the proper form for each event in a newly copied CaseReminderHandler
            """
            from corehq.apps.app_manager.models import FormBase
            for event in handler.events:
                if not event.form_unique_id:
                    continue
                form = FormBase.get_form(event.form_unique_id)
                form_app = form.get_app()
                m_index, f_index = form_app.get_form_location(form.unique_id)
                form_copy = new_app_components[form_app._id].get_module(m_index).get_form(f_index)
                event.form_unique_id = form_copy.unique_id

        def update_for_copy(handler):
            handler.active = False
            update_events(handler)

        if share_reminders:
            for handler in CaseReminderHandler.get_handlers(new_domain_name):
                apply_update(handler, update_for_copy)

        return new_domain