Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions cms/djangoapps/appsembler/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Perform Studio local login/logout

The purpose of this is to address the issue that Ironwood introduced login
redirect to the LMS, which breaks in multisite custom domain environments

We have this code in the Appsembler CMS app to help isolate custom code
"""
from django.conf import settings
from django.urls import path
from django.contrib.auth.views import LogoutView
from .views import LoginView

urlpatterns = [
path('login/', LoginView.as_view(), name='login'),
path('logout/', LogoutView.as_view(
next_page=settings.LOGOUT_REDIRECT_URL), name='logout'),
]
69 changes: 69 additions & 0 deletions cms/djangoapps/appsembler/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Appsembler custom views for Studio

Views here provide Studio local login/logout
"""

from django.conf import settings
from django.contrib.auth import authenticate, login
from django.shortcuts import redirect
from django.views import View
from django.views.decorators.clickjacking import xframe_options_deny
from django.views.decorators.csrf import ensure_csrf_cookie
from django.urls import reverse
from django.utils.decorators import method_decorator

from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.user_authn.views.login import _get_user_by_email

from edxmako.shortcuts import render_to_response


def forgot_password_link():
return "//{base}/login#forgot-password-modal".format(base=settings.LMS_BASE)


def platform_name():
return configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME)


def render_login_page(show_login_error_message=False):
"""Convenience function to put the login page

Arguments:
show_login_error_message (bool): flag to show if a login attempt failed

Returns:
django.http.response.HttpResponse object with the login page content
"""
return render_to_response(
'login_page.html',
{
'show_login_error_message': show_login_error_message,
'forgot_password_link': forgot_password_link(),
'platform_name': platform_name(),
}
)


class LoginView(View):
"""Basic login view to allow for Studio local logins
"""

@method_decorator(ensure_csrf_cookie)
@method_decorator(xframe_options_deny)
def get(self, request):
return render_login_page()

@method_decorator(ensure_csrf_cookie)
def post(self, request, *args, **kwargs):
user = _get_user_by_email(request)
password = request.POST['password']

if user:
user = authenticate(request, username=user.username, password=password)

if not user:
return render_login_page(show_login_error_message=True)

login(request, user)
return redirect(reverse('home'))
1 change: 1 addition & 0 deletions cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@
# .. toggle_tickets: https://openedx.atlassian.net/browse/DEPR-58
# .. toggle_status: supported
'DEPRECATE_OLD_COURSE_KEYS_IN_STUDIO': True,
'STUDIO_LOCAL_LOGIN': False,
}

ENABLE_JASMINE = False
Expand Down
11 changes: 11 additions & 0 deletions cms/envs/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,17 @@ def get_env_setting(setting):
############### Settings for edx-rbac ###############
SYSTEM_WIDE_ROLE_CLASSES = ENV_TOKENS.get('SYSTEM_WIDE_ROLE_CLASSES') or SYSTEM_WIDE_ROLE_CLASSES


### Appsembler customization - Studio local login ###
if FEATURES.get('STUDIO_LOCAL_LOGIN'):
CMS_ROOT_URL = '//localhost:18010'
LOGIN_URL = reverse_lazy('login')
FRONTEND_LOGIN_URL = lambda settings: settings.CMS_ROOT_URL + '/login'
derived('FRONTEND_LOGIN_URL')
FRONTEND_LOGOUT_URL = lambda settings: settings.CMS_ROOT_URL + '/logout/'
derived('FRONTEND_LOGOUT_URL')
LOGOUT_REDIRECT_URL = reverse_lazy('home')

####################### Plugin Settings ##########################

# This is at the bottom because it is going to load more settings after base settings are loaded
Expand Down
50 changes: 50 additions & 0 deletions cms/templates/login_page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<%namespace name='static' file='/static_content.html'/>
<%page expression_filter="h"/>
<%inherit file="base.html" />
<%def name="online_help_token()"><% return "login" %></%def>
<%!
from django.utils.translation import ugettext as _
from django.urls import reverse
%>
<%block name="title">${_("Sign In")}</%block>
<%block name="bodyclass">not-signedin view-signin</%block>

<%block name="content">

<div class="wrapper-content wrapper">
<section class="content">
<header>
<h1 class="title title-1">${_("Sign In to {studio_name}").format(studio_name=settings.STUDIO_NAME)}</h1>
</header>
<article class="content-primary">
<div class=""><!-- What class for a dive to wrap the form? -->
<form method="post" action="${reverse('login')}">
%if show_login_error_message:
<div id="login_error"
class="message message-status error is-shown"
style="display: block;">
${_("Email or password is incorrect. Please ensure that you are a course staff in order to use Studio.")}
</div>
%endif
<fieldset>
<input type="hidden" id="csrf_token" name="csrfmiddlewaretoken" value="${csrf_token}">
<ol class="list-input">
<li class="field text required" id="field-email">
<label for="email">${_("E-mail")}</label>
<input id="email" type="email" name="email" placeholder="${_('example: username@domain.com')}"/>
</li>

<li class="field text required" id="field-password">
<label for="password">${_("Password")}</label>
<input id="password" type="password" name="password" />
<a href="${forgot_password_link}" class="action action-forgotpassword">${_("Forgot password?")}</a>
</li>
</ol>
</fieldset>
<button type="submit" name="submit" class="action action-primary">Sign in here</button>
</form>
</div>
</article>
</section>
</div>
</%block>
5 changes: 5 additions & 0 deletions cms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,8 @@
urlpatterns += (
url(r'^hijack/', include('hijack.urls')),
)

if settings.FEATURES.get('STUDIO_LOCAL_LOGIN'):
urlpatterns += [
url(r'', include('cms.djangoapps.appsembler.urls'))
]