Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
284e78c2
Commit
284e78c2
authored
Jan 20, 2015
by
Will Daly
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6690 from edx/will/inline-user-api-forms
Inline the user api form description calls
parents
349a02e4
0a9f9130
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
113 additions
and
111 deletions
+113
-111
lms/djangoapps/student_account/test/test_views.py
+7
-2
lms/djangoapps/student_account/views.py
+62
-2
lms/static/js/spec/student_account/access_spec.js
+4
-55
lms/static/js/student_account/accessApp.js
+8
-3
lms/static/js/student_account/views/AccessView.js
+28
-42
lms/templates/student_account/access.underscore
+0
-6
lms/templates/student_account/login_and_register.html
+4
-1
No files found.
lms/djangoapps/student_account/test/test_views.py
View file @
284e78c2
...
...
@@ -8,6 +8,7 @@ import json
import
mock
import
ddt
import
markupsafe
from
django.test
import
TestCase
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
...
...
@@ -551,12 +552,16 @@ class StudentAccountLoginAndRegistrationTest(ModuleStoreTestCase):
def
_assert_third_party_auth_data
(
self
,
response
,
current_provider
,
providers
):
"""Verify that third party auth info is rendered correctly in a DOM data attribute. """
expected_data
=
u"data-third-party-auth='{auth_info}'"
.
format
(
auth_info
=
json
.
dumps
({
auth_info
=
markupsafe
.
escape
(
json
.
dumps
({
"currentProvider"
:
current_provider
,
"providers"
:
providers
})
)
expected_data
=
u"data-third-party-auth='{auth_info}'"
.
format
(
auth_info
=
auth_info
)
self
.
assertContains
(
response
,
expected_data
)
def
_third_party_login_url
(
self
,
backend_name
,
auth_entry
,
course_id
=
None
,
redirect_url
=
None
):
...
...
lms/djangoapps/student_account/views.py
View file @
284e78c2
...
...
@@ -7,7 +7,8 @@ from django.http import (
HttpResponse
,
HttpResponseBadRequest
,
HttpResponseForbidden
)
from
django.shortcuts
import
redirect
from
django.core.urlresolvers
import
reverse
from
django.http
import
HttpRequest
from
django.core.urlresolvers
import
reverse
,
resolve
from
django.core.mail
import
send_mail
from
django.utils.translation
import
ugettext
as
_
from
django_future.csrf
import
ensure_csrf_cookie
...
...
@@ -68,13 +69,24 @@ def login_and_registration_form(request, initial_mode="login"):
if
request
.
user
.
is_authenticated
():
return
redirect
(
reverse
(
'dashboard'
))
# Retrieve the form descriptions from the user API
form_descriptions
=
_get_form_descriptions
(
request
)
# Otherwise, render the combined login/registration page
context
=
{
'disable_courseware_js'
:
True
,
'initial_mode'
:
initial_mode
,
'third_party_auth'
:
json
.
dumps
(
_third_party_auth_context
(
request
)),
'platform_name'
:
settings
.
PLATFORM_NAME
,
'responsive'
:
True
'responsive'
:
True
,
# Include form descriptions retrieved from the user API.
# We could have the JS client make these requests directly,
# but we include them in the initial page load to avoid
# the additional round-trip to the server.
'login_form_desc'
:
form_descriptions
[
'login'
],
'registration_form_desc'
:
form_descriptions
[
'registration'
],
'password_reset_form_desc'
:
form_descriptions
[
'password_reset'
],
}
return
render_to_response
(
'student_account/login_and_register.html'
,
context
)
...
...
@@ -317,3 +329,51 @@ def _third_party_auth_context(request):
context
[
"currentProvider"
]
=
current_provider
.
NAME
return
context
def
_get_form_descriptions
(
request
):
"""Retrieve form descriptions from the user API.
Arguments:
request (HttpRequest): The original request, used to retrieve session info.
Returns:
dict: Keys are 'login', 'registration', and 'password_reset';
values are the JSON-serialized form descriptions.
"""
return
{
'login'
:
_local_server_get
(
'/user_api/v1/account/login_session/'
,
request
.
session
),
'registration'
:
_local_server_get
(
'/user_api/v1/account/registration/'
,
request
.
session
),
'password_reset'
:
_local_server_get
(
'/user_api/v1/account/password_reset/'
,
request
.
session
)
}
def
_local_server_get
(
url
,
session
):
"""Simulate a server-server GET request for an in-process API.
Arguments:
url (str): The URL of the request (excluding the protocol and domain)
session (SessionStore): The session of the original request,
used to get past the CSRF checks.
Returns:
str: The content of the response
"""
# Since the user API is currently run in-process,
# we simulate the server-server API call by constructing
# our own request object. We don't need to include much
# information in the request except for the session
# (to get past through CSRF validation)
request
=
HttpRequest
()
request
.
method
=
"GET"
request
.
session
=
session
# Call the Django view function, simulating
# the server-server API call
view
,
args
,
kwargs
=
resolve
(
url
)
response
=
view
(
request
,
*
args
,
**
kwargs
)
# Return the content of the response
return
response
.
content
lms/static/js/spec/student_account/access_spec.js
View file @
284e78c2
...
...
@@ -13,20 +13,6 @@ define([
var
requests
=
null
,
view
=
null
,
AJAX_INFO
=
{
register
:
{
url
:
'/user_api/v1/account/registration/'
,
requestIndex
:
1
},
login
:
{
url
:
'/user_api/v1/account/login_session/'
,
requestIndex
:
0
},
password_reset
:
{
url
:
'/user_api/v1/account/password_reset/'
,
requestIndex
:
1
}
},
FORM_DESCRIPTION
=
{
method
:
'post'
,
submit_url
:
'/submit'
,
...
...
@@ -58,16 +44,6 @@ define([
FORWARD_URL
=
'/courseware/next'
,
COURSE_KEY
=
'edx/DemoX/Fall'
;
var
ajaxAssertAndRespond
=
function
(
url
,
requestIndex
)
{
// Verify that the client contacts the server as expected
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
url
,
null
,
requestIndex
);
/* Simulate a response from the server containing
/* a dummy form description
*/
AjaxHelpers
.
respondWithJson
(
requests
,
FORM_DESCRIPTION
);
};
var
ajaxSpyAndInitialize
=
function
(
that
,
mode
)
{
// Spy on AJAX requests
requests
=
AjaxHelpers
.
requests
(
that
);
...
...
@@ -79,7 +55,10 @@ define([
currentProvider
:
null
,
providers
:
[]
},
platformName
:
'edX'
platformName
:
'edX'
,
loginFormDesc
:
FORM_DESCRIPTION
,
registrationFormDesc
:
FORM_DESCRIPTION
,
passwordResetFormDesc
:
FORM_DESCRIPTION
});
// Mock the redirect call
...
...
@@ -88,9 +67,6 @@ define([
// Mock the enrollment and shopping cart interfaces
spyOn
(
EnrollmentInterface
,
'enroll'
).
andCallFake
(
function
()
{}
);
spyOn
(
ShoppingCartInterface
,
'addCourseToCart'
).
andCallFake
(
function
()
{}
);
// Initialize the subview
ajaxAssertAndRespond
(
AJAX_INFO
[
mode
].
url
);
};
var
assertForms
=
function
(
visibleType
,
hiddenType
)
{
...
...
@@ -106,8 +82,6 @@ define([
// Load form corresponding to the change event
view
.
toggleForm
(
changeEvent
);
ajaxAssertAndRespond
(
AJAX_INFO
[
type
].
url
,
AJAX_INFO
[
type
].
requestIndex
);
};
/**
...
...
@@ -175,11 +149,6 @@ define([
// Simulate a click on the reset password link
view
.
resetPassword
();
ajaxAssertAndRespond
(
AJAX_INFO
.
password_reset
.
url
,
AJAX_INFO
.
password_reset
.
requestIndex
);
// Verify that the password reset wrapper is populated
expect
(
$
(
'#password-reset-wrapper'
)).
not
.
toBeEmpty
();
});
...
...
@@ -253,26 +222,6 @@ define([
expect
(
view
.
redirect
).
toHaveBeenCalledWith
(
"/dashboard"
);
});
it
(
'displays an error if a form definition could not be loaded'
,
function
()
{
// Spy on AJAX requests
requests
=
AjaxHelpers
.
requests
(
this
);
// Init AccessView
view
=
new
AccessView
({
mode
:
'login'
,
thirdPartyAuth
:
{
currentProvider
:
null
,
providers
:
[]
},
platformName
:
'edX'
});
// Simulate an error from the LMS servers
AjaxHelpers
.
respondWithError
(
requests
);
// Error message should be displayed
expect
(
$
(
'#form-load-fail'
).
hasClass
(
'hidden'
)
).
toBe
(
false
);
});
});
}
);
lms/static/js/student_account/accessApp.js
View file @
284e78c2
...
...
@@ -6,9 +6,14 @@ var edx = edx || {};
edx
.
student
=
edx
.
student
||
{};
edx
.
student
.
account
=
edx
.
student
.
account
||
{};
var
container
=
$
(
'#login-and-registration-container'
);
return
new
edx
.
student
.
account
.
AccessView
({
mode
:
$
(
'#login-and-registration-container'
).
data
(
'initial-mode'
),
thirdPartyAuth
:
$
(
'#login-and-registration-container'
).
data
(
'third-party-auth'
),
platformName
:
$
(
'#login-and-registration-container'
).
data
(
'platform-name'
)
mode
:
container
.
data
(
'initial-mode'
),
thirdPartyAuth
:
container
.
data
(
'third-party-auth'
),
platformName
:
container
.
data
(
'platform-name'
),
loginFormDesc
:
container
.
data
(
'login-form-desc'
),
registrationFormDesc
:
container
.
data
(
'registration-form-desc'
),
passwordResetFormDesc
:
container
.
data
(
'password-reset-form-desc'
)
});
})(
jQuery
);
lms/static/js/student_account/views/AccessView.js
View file @
284e78c2
...
...
@@ -40,12 +40,20 @@ var edx = edx || {};
_
.
mixin
(
_s
.
exports
()
);
this
.
tpl
=
$
(
this
.
tpl
).
html
();
this
.
activeForm
=
obj
.
mode
||
'login'
;
this
.
thirdPartyAuth
=
obj
.
thirdPartyAuth
||
{
currentProvider
:
null
,
providers
:
[]
};
this
.
formDescriptions
=
{
login
:
obj
.
loginFormDesc
,
register
:
obj
.
registrationFormDesc
,
reset
:
obj
.
passwordResetFormDesc
};
this
.
platformName
=
obj
.
platformName
;
// The login view listens for 'sync' events from the reset model
...
...
@@ -73,82 +81,64 @@ var edx = edx || {};
},
loadForm
:
function
(
type
)
{
this
.
getFormData
(
type
,
this
);
var
loadFunc
=
_
.
bind
(
this
.
load
[
type
],
this
);
loadFunc
(
this
.
formDescriptions
[
type
]
);
},
load
:
{
login
:
function
(
data
,
context
)
{
login
:
function
(
data
)
{
var
model
=
new
edx
.
student
.
account
.
LoginModel
({},
{
method
:
data
.
method
,
url
:
data
.
submit_url
});
context
.
subview
.
login
=
new
edx
.
student
.
account
.
LoginView
({
this
.
subview
.
login
=
new
edx
.
student
.
account
.
LoginView
({
fields
:
data
.
fields
,
model
:
model
,
resetModel
:
context
.
resetModel
,
thirdPartyAuth
:
context
.
thirdPartyAuth
,
platformName
:
context
.
platformName
resetModel
:
this
.
resetModel
,
thirdPartyAuth
:
this
.
thirdPartyAuth
,
platformName
:
this
.
platformName
});
// Listen for 'password-help' event to toggle sub-views
context
.
listenTo
(
context
.
subview
.
login
,
'password-help'
,
context
.
resetPassword
);
this
.
listenTo
(
this
.
subview
.
login
,
'password-help'
,
this
.
resetPassword
);
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
context
.
listenTo
(
context
.
subview
.
login
,
'auth-complete'
,
context
.
authComplete
);
this
.
listenTo
(
this
.
subview
.
login
,
'auth-complete'
,
this
.
authComplete
);
},
reset
:
function
(
data
,
context
)
{
context
.
resetModel
.
ajaxType
=
data
.
method
;
context
.
resetModel
.
urlRoot
=
data
.
submit_url
;
reset
:
function
(
data
)
{
this
.
resetModel
.
ajaxType
=
data
.
method
;
this
.
resetModel
.
urlRoot
=
data
.
submit_url
;
context
.
subview
.
passwordHelp
=
new
edx
.
student
.
account
.
PasswordResetView
({
this
.
subview
.
passwordHelp
=
new
edx
.
student
.
account
.
PasswordResetView
({
fields
:
data
.
fields
,
model
:
context
.
resetModel
model
:
this
.
resetModel
});
// Listen for 'password-email-sent' event to toggle sub-views
context
.
listenTo
(
context
.
subview
.
passwordHelp
,
'password-email-sent'
,
context
.
passwordEmailSent
);
this
.
listenTo
(
this
.
subview
.
passwordHelp
,
'password-email-sent'
,
this
.
passwordEmailSent
);
},
register
:
function
(
data
,
context
)
{
register
:
function
(
data
)
{
var
model
=
new
edx
.
student
.
account
.
RegisterModel
({},
{
method
:
data
.
method
,
url
:
data
.
submit_url
});
context
.
subview
.
register
=
new
edx
.
student
.
account
.
RegisterView
({
this
.
subview
.
register
=
new
edx
.
student
.
account
.
RegisterView
({
fields
:
data
.
fields
,
model
:
model
,
thirdPartyAuth
:
context
.
thirdPartyAuth
,
platformName
:
context
.
platformName
thirdPartyAuth
:
this
.
thirdPartyAuth
,
platformName
:
this
.
platformName
});
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
context
.
listenTo
(
context
.
subview
.
register
,
'auth-complete'
,
context
.
authComplete
);
this
.
listenTo
(
this
.
subview
.
register
,
'auth-complete'
,
this
.
authComplete
);
}
},
getFormData
:
function
(
type
,
context
)
{
var
urls
=
{
login
:
'login_session'
,
register
:
'registration'
,
reset
:
'password_reset'
};
$
.
ajax
({
url
:
'/user_api/v1/account/'
+
urls
[
type
]
+
'/'
,
type
:
'GET'
,
dataType
:
'json'
,
context
:
this
,
success
:
function
(
data
)
{
this
.
load
[
type
](
data
,
context
);
},
error
:
this
.
showFormError
});
},
passwordEmailSent
:
function
()
{
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'#password-reset-anchor'
)
);
this
.
element
.
show
(
$
(
'#login-anchor'
)
);
...
...
@@ -165,10 +155,6 @@ var edx = edx || {};
this
.
element
.
scrollTop
(
$
(
'#password-reset-anchor'
)
);
},
showFormError
:
function
()
{
this
.
element
.
show
(
$
(
'#form-load-fail'
)
);
},
toggleForm
:
function
(
e
)
{
var
type
=
$
(
e
.
currentTarget
).
data
(
'type'
),
$form
=
$
(
'#'
+
type
+
'-form'
),
...
...
lms/templates/student_account/access.underscore
View file @
284e78c2
<section id="form-load-fail" class="form-type hidden">
<div class="status submission-error">
<p class="message-copy"><%- gettext("Sorry, we're having some technical problems. Wait a few minutes and try again.") %></p>
</div>
</section>
<section id="login-anchor" class="form-type">
<div id="login-form" class="form-wrapper <% if ( mode !== 'login' ) { %>hidden<% } %>"></div>
</section>
...
...
lms/templates/student_account/login_and_register.html
View file @
284e78c2
...
...
@@ -26,8 +26,11 @@
<div
id=
"login-and-registration-container"
class=
"login-register"
data-initial-mode=
"${initial_mode}"
data-third-party-auth=
'${third_party_auth}'
data-third-party-auth=
'${third_party_auth
|h
}'
data-platform-name=
'${platform_name}'
data-login-form-desc=
'${login_form_desc|h}'
data-registration-form-desc=
'${registration_form_desc|h}'
data-password-reset-form-desc=
'${password_reset_form_desc|h}'
/>
</div>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment