I'm having a problem using the adal.js library without Angular. (I'm using Vue.js.)
I have an authentication context instance, which is constructed with the following options (exact values have been changed to protect the innocent):
let config = {
tenant: '<tenant id>',
clientId: '<client id>',
redirectUri: 'http://myapplication.com/index.html',
// popUp: true,
cacheLocation: 'localStorage'
}
On my login page, I call authContext.login(), which redirects me first to https://login.microsoftonline.com/, where I log into AAD. Upon successful login, another redirect takes me back to my application, at the URI I've configured above, along with an id_token parameter in the URL. However, no token or other properties are stored by the library in local storage, just a few properties that are the result of the configuration.
On successful login, All I've got in localStorage is
{
adal.access.token.key: "",
adal.error: ""
adal.error.description: ""
adal.expiration.key: "0"
adal.idtoken: ""
adal.login.error: ""
adal.login.request: "http://myapplication.com/#/login"
adal.nonce.idtoken: "<a non-empty string>"
adal.session.state: ""
adal.state.login: "<a non-empty string>"
adal.token.keys: ""
adal.username: ""
}
So, as far as AAD is concerned, I've successfully authenticated, but the library itself seems to have no notion of what user is logged in, what tokens are associated with them, when the token expires, etc. Any advice on how to proceed would be most appreciated. Thank you in advance for reading.
Active Directory Authentication Library for JavaScript (ADAL JS) helps you to use Azure AD for handling authentication in your single page applications. This library is optimized for working together with AngularJS.
It will not save the tokens into the cache unless we code it. You can check the relative code from adal-angular.js. Here is a piece of code for your reference:
The saveTokenFromHash method will also save the tokens into cache and this function will execute after the page redirect back to the Angular app.
adal.js:
AuthenticationContext.prototype.saveTokenFromHash = function (requestInfo) {
this._logstatus('State status:' + requestInfo.stateMatch);
this._saveItem(this.CONSTANTS.STORAGE.ERROR, '');
this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, '');
// Record error
if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION)) {
this._logstatus('Error :' + requestInfo.parameters.error);
this._logstatus('Error description:' + requestInfo.parameters[this.CONSTANTS.ERROR_DESCRIPTION]);
this._saveItem(this.CONSTANTS.STORAGE.FAILED_RENEW, requestInfo.parameters[this.CONSTANTS.ERROR_DESCRIPTION]);
this._saveItem(this.CONSTANTS.STORAGE.ERROR, requestInfo.parameters.error);
this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, requestInfo.parameters[this.CONSTANTS.ERROR_DESCRIPTION]);
if (requestInfo.requestType === this.REQUEST_TYPE.LOGIN) {
this._loginInProgress = false;
this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, requestInfo.parameters.errorDescription);
} else {
this._renewActive = false;
}
} else {
// It must verify the state from redirect
if (requestInfo.stateMatch) {
// record tokens to storage if exists
this._logstatus('State is right');
if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.SESSION_STATE)) {
this._saveItem(this.CONSTANTS.STORAGE.SESSION_STATE, requestInfo.parameters[this.CONSTANTS.SESSION_STATE]);
}
var keys, resource;
if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN)) {
this._logstatus('Fragment has access token');
// default resource
this._renewActive = false;
resource = this.config.loginResource;
if (!this._hasResource(resource)) {
keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS) || '';
this._saveItem(this.CONSTANTS.STORAGE.TOKEN_KEYS, keys + resource + this.CONSTANTS.RESOURCE_DELIMETER);
}
if (requestInfo.requestType === this.REQUEST_TYPE.RENEW_TOKEN) {
resource = this._getResourceFromState(requestInfo.stateResponse);
}
// save token with related resource
this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource, requestInfo.parameters[this.CONSTANTS.ACCESS_TOKEN]);
this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource, this._expiresIn(requestInfo.parameters[this.CONSTANTS.EXPIRES_IN]));
}
if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ID_TOKEN)) {
this._loginInProgress = false;
this._user = this._createUser(requestInfo.parameters[this.CONSTANTS.ID_TOKEN]);
if (this._user && this._user.profile) {
if (this._user.profile.nonce !== this._getItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN)) {
this._user = null;
this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, 'Nonce is not same as ' + this._idTokenNonce);
} else {
this._saveItem(this.CONSTANTS.STORAGE.IDTOKEN, requestInfo.parameters[this.CONSTANTS.ID_TOKEN]);
// Save idtoken as access token for app itself
resource = this.config.clientId;
if (!this._hasResource(resource)) {
keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS) || '';
this._saveItem(this.CONSTANTS.STORAGE.TOKEN_KEYS, keys + resource + this.CONSTANTS.RESOURCE_DELIMETER);
}
this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource, requestInfo.parameters[this.CONSTANTS.ID_TOKEN]);
this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource, this._user.profile.exp);
}
}
}
} else {
this._saveItem(this.CONSTANTS.STORAGE.ERROR, 'Invalid_state');
this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, 'Invalid_state');
if (requestInfo.requestType === this.REQUEST_TYPE.LOGIN) {
this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, 'State is not same as ' + requestInfo.stateResponse);
}
}
}
};
And this function will be called in this.$get like below:
// special function that exposes methods in Angular controller
// $rootScope, $window, $q, $location, $timeout are injected by Angular
this.$get = ['$rootScope', '$window', '$q', '$location', '$timeout', function ($rootScope, $window, $q, $location, $timeout) {
var locationChangeHandler = function () {
var hash = $window.location.hash;
if (_adal.isCallback(hash)) {
// callback can come from login or iframe request
var requestInfo = _adal.getRequestInfo(hash);
_adal.saveTokenFromHash(requestInfo);
$window.location.hash = '';
if (requestInfo.requestType !== _adal.REQUEST_TYPE.LOGIN) {
_adal.callback = $window.parent.AuthenticationContext().callback;
}
// Return to callback if it is send from iframe
if (requestInfo.stateMatch) {
if (typeof _adal.callback === 'function') {
// Call within the same context without full page redirect keeps the callback
if (requestInfo.requestType === _adal.REQUEST_TYPE.RENEW_TOKEN) {
// Idtoken or Accestoken can be renewed
if (requestInfo.parameters['access_token']) {
_adal.callback(_adal._getItem(_adal.CONSTANTS.STORAGE.ERROR_DESCRIPTION), requestInfo.parameters['access_token']);
return;
} else if (requestInfo.parameters['id_token']) {
_adal.callback(_adal._getItem(_adal.CONSTANTS.STORAGE.ERROR_DESCRIPTION), requestInfo.parameters['id_token']);
return;
}
}
} else {
// normal full login redirect happened on the page
updateDataFromCache(_adal.config.loginResource);
if (_oauthData.userName) {
//IDtoken is added as token for the app
$timeout(function () {
updateDataFromCache(_adal.config.loginResource);
$rootScope.userInfo = _oauthData;
// redirect to login requested page
var loginStartPage = _adal._getItem(_adal.CONSTANTS.STORAGE.START_PAGE);
if (loginStartPage) {
$location.path(loginStartPage);
}
}, 1);
$rootScope.$broadcast('adal:loginSuccess');
} else {
$rootScope.$broadcast('adal:loginFailure', _adal._getItem(_adal.CONSTANTS.STORAGE.ERROR_DESCRIPTION));
}
}
}
} else {
// No callback. App resumes after closing or moving to new page.
// Check token and username
updateDataFromCache(_adal.config.loginResource);
if (!_adal._renewActive && !_oauthData.isAuthenticated && _oauthData.userName) {
if (!_adal._getItem(_adal.CONSTANTS.STORAGE.FAILED_RENEW)) {
// Idtoken is expired or not present
_adal.acquireToken(_adal.config.loginResource, function (error, tokenOut) {
if (error) {
$rootScope.$broadcast('adal:loginFailure', 'auto renew failure');
} else {
if (tokenOut) {
_oauthData.isAuthenticated = true;
}
}
});
}
}
}
$timeout(function () {
updateDataFromCache(_adal.config.loginResource);
$rootScope.userInfo = _oauthData;
}, 1);
}
...
And here is a sample code which could save the tokens into cache for your reference:
<html>
<head>
<script src="https://unpkg.com/vue"></script>
<script src="node_modules\adal-angular\lib\adal.js"> </script>
<script src="config.js"> </script>
</head>
<body>
<div>
<button onclick="login()" >Login</button>
</div>
<script>
var authContext=new AuthenticationContext(config);
function login(){
authContext.login();
}
function init(configOptions){
if (configOptions) {
// redirect and logout_redirect are set to current location by default
var existingHash = window.location.hash;
var pathDefault = window.location.href;
if (existingHash) {
pathDefault = pathDefault.replace(existingHash, '');
}
configOptions.redirectUri = configOptions.redirectUri || pathDefault;
configOptions.postLogoutRedirectUri = configOptions.postLogoutRedirectUri || pathDefault;
// create instance with given config
} else {
throw new Error('You must set configOptions, when calling init');
}
// loginresource is used to set authenticated status
updateDataFromCache(authContext.config.loginResource);
}
var _oauthData = { isAuthenticated: false, userName: '', loginError: '', profile: '' };
var updateDataFromCache = function (resource) {
// only cache lookup here to not interrupt with events
var token = authContext.getCachedToken(resource);
_oauthData.isAuthenticated = token !== null && token.length > 0;
var user = authContext.getCachedUser() || { userName: '' };
_oauthData.userName = user.userName;
_oauthData.profile = user.profile;
_oauthData.loginError = authContext.getLoginError();
};
init(config);
function saveTokenFromHash(){
var hash = window.location.hash;
var requestInfo = authContext.getRequestInfo(hash);
if (authContext.isCallback(hash)) {
// callback can come from login or iframe request
var requestInfo = authContext.getRequestInfo(hash);
authContext.saveTokenFromHash(requestInfo);
window.location.hash = '';
if (requestInfo.requestType !== authContext.REQUEST_TYPE.LOGIN) {
authContext.callback = window.parent.AuthenticationContext().callback;
}
}
}
saveTokenFromHash();
</script>
</body>
</html>
Related
I have an app with Nuxt JS, and there is a route called posts that accepts parameters like so: .../posts/_id. When someone goes to /posts/put_news, they get post with name "Put News" and so on.
So, I wrote a validation method like so:
async validate({ params }) {
// await operations
const response = await axios.get('http://localhost:5000/listings_names')
var response_data = response.data
var str = (params.id).split('_').join(' ')
const arr2 = str.split(" ");
for (var i = 0; i < arr2.length; i++) {
arr2[i] = arr2[i].charAt(0).toUpperCase() + arr2[i].slice(1);
}
const str2 = arr2.join(" ");
var id_fix = str2
const obj = response_data.find(o => o.name == id_fix);
console.log(obj)
if (obj == undefined){
console.log('undefied, false')
return false
}
else{
return true;
}
},
The code does return false, but does nothing else. Once it returns "false" I expect nuxt to redirect the user to the error page, but it just stays on that page. I looked on the documentation, and it seems like the user should be automatically redirected to an error page, however nothing happens here. Also, my nuxt version is 2.15.8.
Thank you for the help
I fixed the issue, so all I had to do, was add redirect to validate function, and redirect to the error page, like so:
async validate({ params, redirect }) { //run-functions
if (obj == undefined) {
redirect('/not_found')
return false
} else {
return true
}
}
I have a guard for my routes which does work in all aspects apart from when I wish to check a permissions object related to that page prior to continuing onto the url.
I have separated out the logic for the permissions check into a function and console logging it out all elements are working, in that it finds the right object in the array, finds the right key and value, and allows or blocks accordingly.
My problem though is that when I go through this route hitting this function it loops endlessly and crashes the browser. I think my overarching logic is fine but have I screwed up its implementation somewhere?
function guard (to, from, next) {
var loggedin_state = store.state.user.auth.loggedin // Boolean
var user = store.state.user.user // Array
var token = store.state.user.auth.token // String
var entryUrl // String
if(entryUrl == null || entryUrl == undefined){
entryUrl = to.path
}
if(loggedin_state == true) {
// Is the user profile blank
if(user == null) {
this.$store.dispatch('user/get_user_information', null)
}
// If they tried a route before logging in that would have been stored
if(entryUrl) {
// Store the url before wiping it
let url = entryUrl;
// Wipe the entry url variable
entryUrl = null;
// Carry on to permission checking function
return go_to_url(url);
} else {
// Go to stored url
return next(to.path)
}
} else {
// Is there a token assigned? If so they are approved and just need the profile information
if(token !== null) {
loggedin_state = true
this.$store.dispatch('user/get_user_information', null)
return go_to_url(to.path);
} else {
// Store entry url before redirect for use after login
entryUrl = to.path
// Re-route to login page
return next("/login");
}
}
function go_to_url(url) {
// Find matching object in user.permissions based upon url
var view_permissions = [
{ "area": "all", "read": 1, "create": 0, "edit": 0, "delete": 0 },
{ "area": "dashboard", "read": 1, "create": 0, "edit": 0, "delete": 0 }
];
// var view_permissions = store.state.user.permissions
var view_permission = view_permissions.find(view => view.area === to.name);
if(view_permission.read == 1) {
// Go to url
next(url);
} else {
// Re-route to somewhere
}
};
};
My problem was in passing a value to the next() function call. By removing that out it worked alright:
function guard (to, from, next) {
console.log('To:')
console.log(to)
console.log('From:')
console.log(from)
console.log('EntryUrl: ' + entryUrl)
// 1 - If no entry path was provided then set to
if(entryUrl == null || entryUrl == undefined){
entryUrl = to.path
console.log('EntryUrl: ' + entryUrl)
}
// 2 - Check if the user is marked as being logged in
var loggedin_state = store.state.user.auth.loggedin
if(loggedin_state == undefined) {
store.commit('user/set_delete_session', null)
return next("/login");
}
// 3 - If they are marked as logged in continue
var user = store.state.user.user
var token = store.state.user.auth.token
if(loggedin_state == true) {
// If the user isn't authorised with a token then send them to the log in page
if(token == null) {
store.commit('user/set_delete_session', null)
return next("/login");
}
// If they've got a token but no user profile data acquire it
if(user == null) {
UserApi.get_user_information(response.data.token)
.then(response => {
store.commit('user/set_user', response.data)
})
}
// If they tried a route before logging in that would have been stored
if(entryUrl) {
console.log('Go to saved URL')
// Store the url before wiping it
let url = entryUrl;
// Wipe the entry url variable
entryUrl = null;
// Go to stored url
return go_to_url(url);
} else {
console.log('Go to pointed url')
// Carry on to permission checking function
return go_to_url(to.path);
}
} else {
// The user is not logged in. Store the URL they were trying to visit and redirect them to the login page
entryUrl = to.path
console.log('EntryUrl: ' + entryUrl)
return next("/login");
}
function go_to_url(url) {
console.log(url)
// 1 - Grab the user permissions from the user profile
var permissions_array = null
if(user !== null) {
permissions_array = user.permissions
}
console.log(permissions_array)
// 2 - Check and route
if(permissions_array !== null) {
// Find the relevant permission object based upon the route name and the area key
var view_permissions = permissions_array.find(view => view.area === to.name);
console.log(view_permissions)
// If a permission object was found check its status, if no object found assume it is okay to view
if(view_permissions !== undefined) {
// If set to 1 the user can view this route, else reroute to a permissions denied page
if(view_permissions.read == 1) {
// Go to url
console.log('GUARD - PROCEED')
console.log(to.name)
next();
} else {
console.log('GUARD - BLOCKED')
return next("/permission-denied");
}
} else {
return next()
}
}
};
};
I can't call any external functions inside an axios promise. My error is
[Uncaught (in promise) TypeError: this.showNotification is not a function]
showNotification is an external function inside mixin but i can't call it in userCompInfo function
var mixin = {
methods: {
//function to get all user info
userInfo:function(){
//alert(localStorage.getItem("sessionKey"))
if(localStorage.getItem("sessionKey")==null)
session = "null";
else
session= localStorage.getItem("sessionKey");
return axios.post("/api/user/info",{
user_id:localStorage.getItem("userId"),
session_key:session
});
},
//function to get all competition info
compInfo:function()
{ //calling API competition info to get the avaliable competition for now
return axios.post("/api/competition/info",{
lang:source.lang
});
},
userCompInfo:function()
{
axios.all([this.userInfo(),this.compInfo()])
.then(axios.spread(function (user, comp){
if(comp.data.result.errorcode == 0)
{
source.competition = comp.data.competiton_detail;
}
//set the user id in local storage
localStorage.setItem("userId",user.data.user_info.user_id);
//check on session key to save it in local storage
if(user.data.user_info.session_key != "") // for testing
localStorage.setItem("sessionKey",user.data.user_info.session_key);
// get user data successfuly
if(user.data.result.errorcode == 0)
{ //set response data in user
source.user = user.data.user_info;
//to set this user status
this.renderUserInfo();
///////////
//source.competition.is_active=1;
//check on user status to show notification
if(source.user.vip && source.user.suspended)
{
this.showNotification(context.suspended_vip.title+" "+source.user.msisdn, context.suspended_vip.body,["btn_notifi_ok"]);
}
//check if this valid competition is active or not to show notification according to it and to user status
if(source.competition.is_active==1)
{
if(source.user.registered && newUser==1)
{
this.showNotification(context.registered_firstTime.title, context.registered_firstTime.body, ["btn_notifi_start_play"]);
}
else if(source.user.free && source.user.newFreeUser)
{
this.showNotification(context.freeUser_firstTime.title, context.freeUser_firstTime.body, ["btn_notifi_start_play"]);
}
}
}
}));
},
// function to show notification modal
showNotification:function(title, body, buttons)
{
//to hide all modal buttons first
$("#notification").find(".btn").hide();
//set the modal title
$("#notification_title").html(title);
//set the modal body
$("#notification_body").html(body);
//for on buttons array to show all buttons that we want
for(i=0;i<buttons.length;i++)
{
$("#notification").find("#"+buttons[i]).show();
}
//to display modal
$("#notification").modal("show");
},
//function to show the current user statue VIP, registered,free or suspended
renderUserInfo:function()
{ // intialize all flags of user status to false
source.user.vip = false;
source.user.registered = false;
source.user.free = false;
//check on user mode and set the according flag to it to true
if(source.user.sub_mode == "vip")
{
source.user.vip = true;
}
else if(source.user.sub_mode == "sub")
{
source.user.registered = true;
}
else
{
source.user.free = true;
}
},}}
This is a very common mistake. this in userCompInfo doesn't refer to the Vue because of they way you have written the callback.
In your code, make this change.
userCompInfo:function()
{
axios.all([this.userInfo(),this.compInfo()])
.then(axios.spread(function (user, comp){
// a bunch of code...
}.bind(this)));
},
Or
userCompInfo:function()
{
let self = this;
axios.all([this.userInfo(),this.compInfo()])
.then(axios.spread(function (user, comp){
// a bunch of code...
self.showNotification(...)
// some more code...
}));
},
See How to access the correct this inside a callback?
I've got the following code to handle client side navigation using HTML5 pushstate (classic combination of crossroadsjs and historyjs):
History = window.History;
History.Adapter.bind(window, 'statechange', function () {
var state = History.getState();
console.log(state);
if (state.data.urlPath) {
return crossroads.parse(state.data.urlPath);
}
else
{
if (state.hash.length > 1) {
var fullHash = state.hash;
var hashPath = fullHash.slice(0, fullHash.indexOf('?'));
return crossroads.parse(hashPath);
}
}});
crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;
crossroads.parse('/');
$('body').on('click', 'a', function(e) {
var title, urlPath;
urlPath = $(this).attr('href');
if (urlPath.slice(0, 1) == '#'){
return true;
}
e.preventDefault();
title = $(this).text().trim();
return History.pushState({ urlPath: urlPath }, title, urlPath);
});
It works really well. Now, to handle url bookmarking and sharing, I added and express server to handle all requests. All it does is to redirect to index.html (a sort of catchall rule):
var env = require('./env');
var fallback = require('express-history-api-fallback');
var express = require('express');
var app = express();
var config = env.config();
var root = __dirname + '/dist';
app.use(express.static(root));
app.use(fallback('index.html', { root: root }));
var port = process.env.PORT || 9090;
var server = app.listen(port, function () {
console.log('Server started at: http://localhost:' + port);
console.log(config);
});
The problem I am facing is that it successfully redirects to index.html but it doesn't load the correct route on the client side. So a request to www.mysite.com or www.mysite.com/anotherpage will always load the home page route.
I am obviously missing some code to intercept that and load the appropriate route on the client side. I just don't know what to do.
Found where the bug was:
crossroads.parse('/');
This was always redirecting to the "home" route. I just had to refactor the code a bit:
History.Adapter.bind(window, 'statechange', this.routeCrossRoads);
routeCrossRoads() {
var state = History.getState();
if (state.data.urlPath) {
return crossroads.parse(state.data.urlPath);
}
else {
if (state.hash.length > 1) {
var fullHash = state.hash;
var pos = fullHash.indexOf('?');
if (pos > 0) {
var hashPath = fullHash.slice(0, pos);
return crossroads.parse(hashPath);
}
else {
return crossroads.parse(fullHash);
}
}
else {
return crossroads.parse('/');
}
}
}
I'm trying to implement a form using the jQuery Form plugin. The form has three text fields and a file input and I am validating the form in the beforeSend callback. The problem is, whether the validation passes or not, the php script that handles the file upload gets loaded in the browser, which, obviously is not what I want to happen - I need to stay on the form's page.
You can take a look at the form and it's dependent files at http://www.eventidewebdesign.com/public/testUpload/. Indexing is on for that directory, so you can take a look at all of the related files. The form itself is on testUpload.php.
I'd appreciate it if someone could take a look at my code and help me figure out what's going on here.
Please write the following script instead of your, this will work.
<script>
$(document).ready( function() {
// Initialize and populate the datepicker
$('#sermonDate').datepicker();
var currentDate = new Date();
$("#sermonDate").datepicker('setDate',currentDate);
$("#sermonDate").datepicker('option',{ dateFormat: 'mm/dd/yy' });
/*
* Upload
*/
// Reset validation and progress elements
var formValid = true,
percentVal = '0%';
$('#uploadedFile, #sermonTitle, #speakerName, #sermonDate').removeClass('error');
$('#status, #required').empty().removeClass();
$('.statusBar').width(percentVal)
$('.percent').html(percentVal);
$('#frmSermonUpload').ajaxForm({
beforeSend: function() {
if (!ValidateUploadForm()) {
formValid = false;
console.log('validateuploadform returned false');
} else {
console.log('validateuploadform returned true');
formValid = true;
}
console.log('in beforeSend. formValid: ' + formValid);
if (!formValid) {
$('#uploadedFile').val('');
return false;
}
},
uploadProgress: function(event, position, total, percentComplete) {
console.log('in uploadProgress function. formValid: ' + formValid);
if (formValid) {
var percentVal = percentComplete + '%';
$('.statusBar').width(percentVal)
$('.percent').html(percentVal);
}
},
complete: function(xhr) {
console.log('in complete function. formValid: ' + formValid);
if (formValid) {
console.log('xhr.responseText: ' + xhr.responseText);
console.log('formValid: ' + formValid);
if (xhr.responseText === 'success') {
$('.statusBar').width('100%');
$('.percent').html('100%');
$('#status').html('Successfully uploaded the sermon.').addClass('successUpload');
// Clear the form
ClearForm();
} else if (xhr.responseText === 'fail') {
$('#status').html('There was a problem uploading the file. Try again.<br>If the problem persists, contact your system administrator.').addClass('errorUpload');
}
}
}
}); // End Upload Status Bar
});
function ValidateUploadForm() {
// Reset errors and clear message
$('#uploadedFile, #sermonTitle, #speakerName, #sermonDate').removeClass('error');
$('#required').empty();
var result = true;
title = $('#sermonTitle').val(),
speaker = $('#speakerName').val(),
date = $('#sermonDate').val(),
fileName = $('#uploadedFile').val();
extension = $('#uploadedFile').val().split('.').pop().toLowerCase();
//if (fileName !== '' && extension !== 'mp3') {
if ((fileName === '') || (extension !== 'mp3')) {
$('#uploadedFile').addClass('error');
$('#required').html('Only mp3 files are allowed!');
return false;
} else if (fileName === '') {
result = false;
} else if (title === '') {
$('#sermonTitle').addClass('error');
result = false;
} else if (speaker === '') {
$('#speakerName').addClass('error');
result = false;
} else if (date === '') {
$('#sermonDate').addClass('error');
result = false;
}
console.log('returning ' + result + ' from the validateuploadform function');
if (!result) { $('#required').html('All fields are required.'); }
return result;
}
function ClearForm() {
$('#uploadedFile, #sermonTitle, #sermonDate, #speakerName').val('').removeClass();
}
</script>