Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Web import tool: Add the views and base templates. #8049

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions templates/zerver/create_realm.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ <h1 class="get-started">{{ _("Create a new Zulip organization") }}</h1>
</div>
</form>
<div class="alert alert-error"></div>
<p class="inline-block relative">{{ _(' Or <a href="/web_import">import from Slack workspace</a>') }}</p>
{% if form.email.errors %}
{% for error in form.email.errors %}
<div class="alert alert-error">{{ error }}</div>
Expand Down
94 changes: 94 additions & 0 deletions templates/zerver/web_import.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{% extends "zerver/portico_signup.html" %}
{# This is the page where we import data from Slack into Zulip. #}

{% block portico_content %}

<div class="register-account flex full-page">
<div class="center-block new-style">
<div class="pitch">
{% trans %}
<h1>Import Slack Workspace</h1>
{% endtrans %}
</div>
<form class="form-horizontal white-box" id="web-import" action="/web_import/"
method="post" enctype="multipart/form-data">
{{ csrf_input }}

<section>
<div class="input-box">
<input id="import_email" name="email"
class="email required" type="text" placeholder="{{ _("Enter Email") }}"
value="{% if form.email.value() %}{{ form.email.value() }}{% endif %}"
required />
<label for="id_email" class="inline-block label-title">{{ _('Email') }}</label>
{% if form.email.errors %}
{% for error in form.email.errors %}
<p class="help-inline text-error">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
</section>

<section>
<div class="input-box">
<input id="import_full_name" name="full_name"
class="full_name" type="text" placeholder="{{ _("Enter Full Name") }}"
value="{% if form.full_name.value() %}{{ form.full_name.value() }}{% endif %}"
required />
<label for="id_fullname" class="inline-block">{{ _('Full name') }}</label>
{% if form.full_name.errors %}
{% for error in form.full_name.errors %}
<p class="help-inline text-error">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
</section>

<section>
<div class="input-box">
<input id="import_team_subdomain" name="realm_subdomain"
class="realm_subdomain" type="text" placeholder="{{ _("Enter Realm Subdomain") }}"
value="{% if form.realm_subdomain.value() %}{{ form.realm_subdomain.value() }}{% endif %}"
required />
<label for="id_subdomain" class="inline-block">{{ _('Realm Subdomain') }}</label>
{% if form.realm_subdomain.errors %}
{% for error in form.realm_subdomain.errors %}"
<p class="help-inline text-error">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
</section>

<section>
<input type="file" name="zulip_data_file"
value="{{ _('Upload Import file') }}" required />
<div>
{% if form.zulip_data_file.errors %}
{% for error in form.zulip_data_file.errors %}"
<p class="alert alert-error">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
</section>

<section>
{% if form_error %}
<p class="alert alert-error">{{ form_error }}</p>
{% endif %}
</section>

<section>
<div class="register-button-box">
<button class="register-button" type="submit">{{ _('Import') }}</button>
<input type="hidden" name="next" value="{{ next }}" />
</div>
</section>
</form>

</div>
</div>

<script type="text/javascript">

</script>
{% endblock %}
21 changes: 20 additions & 1 deletion zerver/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
PasswordResetForm
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
from django.core.validators import validate_email
from django.core.validators import validate_email, FileExtensionValidator
from django.db.models.query import QuerySet
from django.utils.translation import ugettext as _
from django.contrib.auth.tokens import default_token_generator
Expand Down Expand Up @@ -115,6 +115,25 @@ def clean_realm_subdomain(self) -> str:
check_subdomain_available(subdomain)
return subdomain

class ImportDataForm(forms.Form):
email = forms.EmailField(required=True)
full_name = forms.CharField(max_length=UserProfile.MAX_NAME_LENGTH,
required=True)
zulip_data_file = forms.FileField(required=True,
validators=[FileExtensionValidator(allowed_extensions=['zip'])])
realm_subdomain = forms.CharField(max_length=Realm.MAX_REALM_SUBDOMAIN_LENGTH, required=True)

def clean_realm_subdomain(self) -> str:
subdomain = self.cleaned_data['realm_subdomain']
check_subdomain_available(subdomain)
return subdomain

def clean_full_name(self) -> Text:
try:
return check_full_name(self.cleaned_data['full_name'])
except JsonableError as e:
raise ValidationError(e.msg)

class ToSForm(forms.Form):
terms = forms.BooleanField(required=True)

Expand Down
1 change: 0 additions & 1 deletion zerver/lib/slack_data_to_zulip_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,4 +552,3 @@ def do_convert_data(slack_zip_file: str, realm_name: str, output_dir: str) -> No
print('######### DATA CONVERSION FINISHED #########\n')
print("Zulip data dump created at %s" % (output_dir))
print("Import Command: ./manage.py import --destroy-rebuild-database %s\n" % (output_dir))
sys.exit(0)
47 changes: 46 additions & 1 deletion zerver/views/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
get_realm, get_user, get_default_stream_groups
from zerver.lib.send_email import send_email, FromAddress
from zerver.lib.events import do_events_register
from zerver.lib.export import do_import_realm
from zerver.lib.slack_data_to_zulip_data import do_convert_data
from zerver.lib.actions import do_change_password, do_change_full_name, do_change_is_admin, \
do_activate_user, do_create_user, do_create_realm, \
email_not_system_bot, compute_mit_user_fullname, validate_email_for_realm, \
do_set_user_display_setting, lookup_default_stream_groups, bulk_add_subscriptions
from zerver.forms import RegistrationForm, HomepageForm, RealmCreationForm, \
CreateUserForm, FindMyTeamForm
CreateUserForm, FindMyTeamForm, ImportDataForm
from django_auth_ldap.backend import LDAPBackend, _LDAPUser
from zerver.decorator import require_post, has_request_variables, \
JsonableError, REQ, do_login
Expand All @@ -44,6 +46,10 @@
import requests
import smtplib
import ujson
import tempfile
import subprocess
import os
import shutil

import urllib

Expand Down Expand Up @@ -354,6 +360,45 @@ def create_realm(request: HttpRequest, creation_key: Optional[Text]=None) -> Htt
context={'form': form, 'current_url': request.get_full_path},
)

def web_import(request: HttpRequest) -> HttpResponse:
if request.method == 'POST':
form = ImportDataForm(request.POST, request.FILES)
if form.is_valid():
zulip_import_file = request.FILES['zulip_data_file']
realm_name = form.cleaned_data['realm_subdomain']
uploaded_dir = os.path.dirname(zulip_import_file.temporary_file_path())
web_import_dir = uploaded_dir + '/web_import/'

if not os.path.exists(web_import_dir):
os.makedirs(web_import_dir)
os.rename(zulip_import_file.temporary_file_path(),
web_import_dir + zulip_import_file.name)
output_dir = tempfile.mkdtemp(prefix="/tmp/converted-slack-data-")

try:
do_convert_data(web_import_dir + zulip_import_file.name, realm_name,
output_dir)
do_import_realm(output_dir)
subprocess.check_call([os.path.join(settings.DEPLOY_ROOT,
"scripts/setup/postgres-reset-sequences")])

except FileNotFoundError as e:
shutil.rmtree(web_import_dir)
return render(request, "zerver/web_import.html",
context={'form': form,
'form_error': e,
'MAX_REALM_SUBDOMAIN_LENGTH': str(Realm.MAX_REALM_SUBDOMAIN_LENGTH)
},
)
else:
form = ImportDataForm()
return render(request,
'zerver/web_import.html',
context={'form': form,
'MAX_REALM_SUBDOMAIN_LENGTH': str(Realm.MAX_REALM_SUBDOMAIN_LENGTH)
},
)

# This is used only by the casper test in 00-realm-creation.js.
def confirmation_key(request: HttpRequest) -> HttpResponse:
return json_success(request.session.get('confirmation_key'))
Expand Down
3 changes: 3 additions & 0 deletions zproject/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,9 @@
url(r'^create_realm/(?P<creation_key>[\w]+)$',
zerver.views.registration.create_realm, name='zerver.views.create_realm'),

url(r'^web_import/$', zerver.views.registration.web_import,
name='zerver.views.web_import'),

# Login/registration
url(r'^register/$', zerver.views.registration.accounts_home, name='register'),
url(r'^login/$', zerver.views.auth.login_page, {'template_name': 'zerver/login.html'},
Expand Down