add ssl 1.2
[CPE_learningsite] / CPE / CPE.App / CPE.App.Web / Controllers / IndexController.cs
1 ´╗┐using System;
2 using System.Collections.Generic;
3 using System.Configuration;
4 using System.Linq;
5 using System.Net;
6 using System.Net.Mail;
7 using System.Text.RegularExpressions;
8 using System.Web;
9 using System.Web.Mvc;
10 using System.Xml;
11 using CPE.App.Web.Code;
12 using CPE.App.Web.Connect;
13 using CPE.App.Web.Helpers;
14 using CPE.App.Web.Models;
15
16 namespace CPE.App.Web.Controllers {
17     public class IndexController : BaseController {
18         public enum MeetingType {
19             Adobe,
20             Elucidat
21         }
22
23         private bool IsLocal() {
24             var address = Request.UserHostAddress;
25             if (address.StartsWith("192.") || address.StartsWith("10.211") || address == "::1")
26                 return true;
27             return false;
28         }
29
30         // GET: Index
31         [HttpGet]
32         public ActionResult Index(int? year) {
33             if(Request.Cookies["allowed"] == null && !IsLocal())
34                 return Redirect("http://www.cpeonline.com/webcasts");
35             string systemPassword = ConfigurationManager.AppSettings["password"];
36             if(Request.Cookies["allowed"] != null && (Request.Cookies["allowed"].Value != systemPassword))
37                 return Redirect("http://www.cpeonline.com/webcasts");
38             DateTime now = DateTime.UtcNow;
39
40             if(!year.HasValue) {
41                 year = DateTime.Now.Year;
42             }
43
44             List<MeetingSessionsDataResult> meetingSessions = Database.MeetingSessionsData()
45                                                                       .Where(msd => msd.EndDate.HasValue && msd.EndDate <= now && (msd.StartDate >= new DateTime(year.Value, 1, 1) && msd.StartDate < new DateTime(year.Value + 1, 1, 1)))
46                                                                       .OrderByDescending(msd => msd.StartDate)
47                                                                       .ToList();
48             return View(meetingSessions);
49         }
50
51         [HttpGet]
52         public ActionResult SessionDetails(int meetingSessionKey) {
53             Extensions.LogServiceCall("[IndexController][SessionDetails]", string.Format("Beginning: meetingSessionKey = {0}", meetingSessionKey));
54
55             var meetingSession = Database.MeetingSessions.Single(ms => ms.MeetingSessionKey == meetingSessionKey);
56             var result = new AdobeSessionViewModel {
57                 MeetingSession = meetingSession,
58                 ParticipantSessionsDataResult = Database.ParticipantSessionsData(meetingSessionKey)
59                                                         .ToList(),
60                 GetSessionReportResult = Database.GetSessionReport(meetingSessionKey)
61                                                  .ToList(),
62                 WebcastPurchaseDataResult = Database.WebcastPurchaseData(meetingSession.SCO_ID, meetingSessionKey)
63                                                     //.Where(w => w.Sco == meetingSession.SCO_ID && w.mDate.DayOfYear >= meetingSession.StartDate.DayOfYear)
64                                                     .ToList()
65             };
66             //if (result.ParticipantSessionsDataResult.Count == 0) {
67             adobe.GetAdobeTransactions(meetingSession, Database);
68             Database.SubmitChanges();
69
70             result = new AdobeSessionViewModel {
71                 MeetingSession = meetingSession,
72                 ParticipantSessionsDataResult = Database.ParticipantSessionsData(meetingSessionKey)
73                                                         .ToList(),
74                 GetSessionReportResult = Database.GetSessionReport(meetingSessionKey)
75                                                  .ToList(),
76                 WebcastPurchaseDataResult = Database.WebcastPurchaseData(meetingSession.SCO_ID, meetingSessionKey)
77                                                     .ToList()
78             };
79             //}
80             return View(result);
81         }
82
83         [HttpGet]
84         public ActionResult RetrieveSession(int meetingSessionKey) {
85             Extensions.LogServiceCall("[IndexController][RetrieveSession]", string.Format("Beginning: meetingSessionKey = {0}", meetingSessionKey));
86
87             var meetingSession = Database.MeetingSessions.Single(ms => ms.MeetingSessionKey == meetingSessionKey);
88             if(Database.ParticipantSessionsData(meetingSessionKey)
89                        .ToList()
90                        .Count == 0) {
91                 adobe.GetAdobeTransactions(meetingSession, Database);
92                 Database.SubmitChanges();
93             }
94
95             return RedirectToAction("SessionDetails", new {meetingSessionKey});
96         }
97
98
99         [HttpGet]
100         public ActionResult TestElucidat()
101         {
102             var baseUrl = "https://api-launchpad.elucidat.com/";
103             var urlFull = "health/ping";
104             Extensions.LogServiceCall("[IndexController][TestElucidat]", $"Beginning: {baseUrl}{urlFull}");
105
106             ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
107             ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls;
108             ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls11;
109             // Add TLS 1.2
110             ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
111
112             var client = new WebClient { BaseAddress = baseUrl };
113             client.Headers.Clear();
114             client.Headers["Accept"] = "application/json";
115             var response = client.DownloadString(urlFull);
116             Extensions.LogServiceCall("[IndexController][TestElucidat]", $"Response: {response}");
117
118
119             return Content(response);
120         }
121
122         [HttpGet]
123         public ActionResult Login(string meetingUrl, string d = null, string c = null) {
124             meetingUrl = meetingUrl?.Trim();
125             d = d?.Trim();
126             c = c?.Trim();
127
128
129             Extensions.LogServiceCall("[IndexController][Login|Get]", string.Format("meetingUrl = {0} d (PurchaseDate) = {1} c (TicketFromUrl) = {2}", meetingUrl, d, c));
130
131             //Webcast and Rebroadcast access test course
132             if(meetingUrl.ToLower() == "test_room") {
133                 var baseUrl = ConfigurationManager.AppSettings["Connect.Url"];
134                 var testUrl = ConfigurationManager.AppSettings["Connect.AccessTestMeetingUrl"];
135                 var accessTestUrl = baseUrl + '/' + testUrl;
136                 return Redirect(accessTestUrl);
137             }
138             var meetingType = meetingUrl.Contains('-') ? MeetingType.Elucidat : MeetingType.Adobe;
139
140             if(meetingType == MeetingType.Elucidat) {
141                 var releaseCode = meetingUrl.Substring(meetingUrl.IndexOf('-') + 1);
142                 Extensions.LogServiceCall("[IndexController][Login|Get]", string.Format("meetingUrl = {0} releaseCode = {1}", meetingUrl, releaseCode));
143
144                 ReleaseModel release = ElucidatMeetingConnection.GetReleaseDetails(releaseCode);
145                 string projectName = null;
146                 if(release != null && release.Project != null) {
147                     projectName = release.Project.Name;
148                 }
149                 return View("elucidatlogin", new ElucidatCourseView {Name = projectName, Url = meetingUrl, PurchaseDate = d, TicketFromUrl = c, Message = null});
150             }
151             //if (ConfigurationManager.AppSettings["CPE.AdobeTicketingOn"].ToLower() == "true")
152             //{
153             //    //The flag is unnecessary now since we're keeping magic passcode access available. Non-ticketed link is now magicTicket 
154
155             // }
156
157             XmlDocument meeting = AdobeMeetingConnection.getAdobeMeeting(meetingUrl);
158             if(meeting != null) {
159                 if(meeting.SelectSingleNode("//sco")
160                           .Attributes["icon"].Value != "archive") {
161                     return View("login", new AdobeMeetingView {
162                         Name = meeting.SelectSingleNode("//sco/name")
163                                       .InnerText,
164                         HasPassCode = meeting.SelectSingleNode("//meeting-passcode") != null,
165                         PurchaseDate = d,
166                         TicketFromUrl = c
167                     });
168                 }
169             }
170             return null;
171         }
172
173         [HttpPost]
174         public ActionResult Login(string meetingUrl, string firstname, string lastname, string email, string passcode,
175                                   string courseName, string ticket = null, string ticketFromUrl = null, string purchaseDate = null,
176                                   string message = null) {
177             meetingUrl = meetingUrl?.Trim();
178             firstname = firstname?.Trim();
179             lastname = lastname?.Trim();
180             email = email?.Trim();
181             passcode = passcode?.Trim();
182             courseName = courseName?.Trim();
183             ticket = ticket?.Trim();
184             ticketFromUrl = ticketFromUrl?.Trim();
185             purchaseDate = purchaseDate?.Trim();
186             message = message?.Trim();
187
188             Extensions.LogServiceCall("[IndexController][Login|Post]", string.Format("email = {0} meetingUrl = {1} ticket = {2} ticketFromUrl = {3} purchaseDate = {4} firstname = {5} lastname = {6} passcode = {7} courseName = {8}", email, meetingUrl, ticket, ticketFromUrl, purchaseDate, firstname, lastname, passcode, courseName));
189
190             var magicTicketLogin = string.IsNullOrEmpty(ticketFromUrl);
191             var meetingType = meetingUrl.Contains('-') ? MeetingType.Elucidat : MeetingType.Adobe;
192
193             if(meetingType.Equals(MeetingType.Elucidat)) {
194                 var releaseCode = meetingUrl.Substring(meetingUrl.IndexOf('-') + 1);
195
196                 if(!ticket.Equals(ticketFromUrl) ||
197                    !VerifyAccess.VerifyTicket(ticket, meetingUrl, firstname, lastname, email, purchaseDate)) {
198                     return View("elucidatlogin", new ElucidatCourseView {
199                         Url = meetingUrl,
200                         Name = courseName,
201                         PurchaseDate = purchaseDate,
202                         TicketFromUrl = ticketFromUrl,
203                         Message =
204                             "Invalid Login. Please re-enter your information. This information MUST match the information in the email you received with your passcode. If you continue to have trouble, please contact Customer Service at 1-800-544-1114 or email us at sswebcast@cpeincmail.com"
205                     }
206                         );
207                 }
208
209                 PurchasedCourse course =
210                     Database.PurchasedCourses.SingleOrDefault(pc => pc.Ticket == ticket && pc.ContentUrl == meetingUrl);
211
212                 if(course == null) {
213                     //no purchase record yet, look for release details in database
214                     CourseDetail release = Database.CourseDetails.SingleOrDefault(r => r.ReleaseCode == releaseCode);
215                     if(release == null) {
216                         //course isn't in db yet, get details form api
217                         ReleaseModel releaseCourse = ElucidatMeetingConnection.GetReleaseDetails(releaseCode);
218                         var done = ReleaseHelper.GetReleaseDescriptionDetails(releaseCourse);
219                         if(done) {
220                             release = Database.CourseDetails.SingleOrDefault(cd => cd.ReleaseCode == releaseCode);
221                         }
222                     }
223                     string formattedPdate = purchaseDate.Substring(0, 4) + '-' + purchaseDate.Substring(4, 2) + '-' +
224                                             purchaseDate.Substring(6, 2);
225                     DateTime pDate = Convert.ToDateTime(formattedPdate);
226                     course = new PurchasedCourse {
227                         ContentUrl = meetingUrl,
228                         CourseName = release.Name,
229                         FirstName = firstname,
230                         LastName = lastname,
231                         Email = email,
232                         Ticket = ticket,
233                         PurchaseDate = pDate,
234                         Presenter = release.Presenter,
235                         Fos = release.Fos,
236                         Credits = release.Credits,
237                         CertificateDate = null,
238                         FailedAttempts = 0,
239                         isManualCertificate = false
240                     };
241                     Database.PurchasedCourses.InsertOnSubmit(course);
242                 }
243
244                 Database.SubmitChanges();
245
246                 //verify access (PurchaseDate<1yrold) and access not revoked
247                 if(!VerifyAccess.AccessBlocked(course) && VerifyAccess.IsValid(course)) {
248                     string courseUrl = ElucidatMeetingConnection.GetLaunchLink(releaseCode, firstname, lastname, email);
249
250                     Regex linkParser = new Regex(@"\b(?:https?://)\S+\b",
251                                                  RegexOptions.Compiled | RegexOptions.IgnoreCase);
252                     string rawString = courseUrl;
253                     string goodUrl = linkParser.Match(rawString)
254                                                .Value;
255
256                     return Redirect(goodUrl);
257                 }
258
259                 //Access is expired or Revoked
260                 return View("elucidatlogin", new ElucidatCourseView {
261                     Url = meetingUrl,
262                     Name = courseName,
263                     PurchaseDate = purchaseDate,
264                     TicketFromUrl = ticketFromUrl,
265                     Message =
266                         "Access to this course is no longer available. Please contact Customer Service at 1-800-544-1114 or email us at sswebcast@cpeincmail.com"
267                 }
268                     );
269             }
270             if((ConfigurationManager.AppSettings["CPE.AdobeTicketingOn"].ToLower() == "true") & !magicTicketLogin) {
271                 if(passcode == null) {
272                     passcode = (DateTime.UtcNow.ToString("MMM") + DateTime.UtcNow.Day.ToString("00")).ToLower();
273                 }
274                 if(!ticketFromUrl.Equals(ticket)) {
275                     return RedirectToAction("Login");
276                 }
277                 if(!VerifyAccess.VerifyTicket(ticket, meetingUrl, firstname, lastname, email, purchaseDate)) {
278                     return RedirectToAction("Login");
279                 }
280
281                 //if valid continue on to existing way of doing things
282             }
283
284             string connectUrl = ConfigurationManager.AppSettings["Connect.Url"];
285             int accountId = int.Parse(ConfigurationManager.AppSettings["Connect.AccountId"]);
286             string password = Guid.NewGuid()
287                                   .ToString()
288                                   .Replace("{", "")
289                                   .Replace("}", "")
290                                   .Substring(0, 8);
291             Session admin = AdobeMeetingConnection.GetAdobeAdminSession();
292             var request = new Request(admin, "principal-list");
293             request.Parameters.Add("filter-type", "guest");
294             request.Parameters.Add("filter-type", "user");
295             request.Parameters.Add("filter-login", email);
296             if(request.Execute() && request.Status == Status.OK) {
297                 Extensions.LogServiceCall("[IndexController][Login|Post]", string.Format("email = [{0}] request.XmlResults.InnerXml = {1}", email, request.XmlResults.InnerXml));
298
299                 int principalId;
300                 if(request.XmlResults.SelectSingleNode("//principal") == null) {
301                     principalId = Connect.Login.CreateGuest(admin, email, password, email, firstname, lastname);
302                 } else {
303                     principalId = int.Parse(request.XmlResults.SelectSingleNode("//principal")
304                                                    .Attributes["principal-id"].Value);
305                     email = request.XmlResults.SelectSingleNode("//principal/login")
306                                    .InnerText;
307                     if(request.XmlResults.SelectSingleNode("//principal")
308                               .Attributes["type"].Value == "user")
309                         return RedirectToAction("Login");
310                 }
311                 if(principalId < 1)
312                     return RedirectToAction("Login");
313
314
315                 Connect.Login.ResetPassword(admin, principalId, password);
316                 Session session = Connect.Login.UserLogin(email, password, connectUrl, accountId);
317
318                 var meetingView = new AdobeMeetingView {
319                     Name = AdobeMeetingConnection.getAdobeMeetingName(meetingUrl),
320                     PrincipalId = principalId,
321                     Url =
322                         string.Format("{0}/{1}?session={2}&launcher=false", connectUrl, meetingUrl,
323                                       session.SessionKey) + (passcode == null
324                                                                  ? ""
325                                                                  : "&meeting-passcode=" + passcode)
326                 };
327
328
329                 Participant participant = Database.Participants.SingleOrDefault(p => p.Principal_ID == principalId);
330                 if(participant == null) {
331                     participant = new Participant {
332                         Principal_ID = principalId,
333                         FirstName = firstname,
334                         LastName = lastname,
335                         Email = email
336                     };
337                     Database.Participants.InsertOnSubmit(participant);
338                 }
339
340                 Database.SubmitChanges();
341
342                 var certificateId = 0;
343                 int scoId = AdobeMeetingConnection.getAdobeMeetingSco(meetingUrl);
344
345                 if(!magicTicketLogin) {
346                     string formattedPdate = purchaseDate.Substring(0, 4) + '-' +
347                                             purchaseDate.Substring(4, 2) +
348                                             '-' + purchaseDate.Substring(6, 2);
349                     DateTime pDate = Convert.ToDateTime(formattedPdate);
350
351                     ParticipantPurchase purchase =
352                         Database.ParticipantPurchases.SingleOrDefault(
353                                                                       p =>
354                                                                       p.PrincipalID == principalId & p.Ticket == ticketFromUrl &
355                                                                       p.MeetingSco == scoId);
356                     if(purchase == null) {
357                         purchase = new ParticipantPurchase {
358                             FirstName = firstname,
359                             LastName = lastname,
360                             Email = email,
361                             PrincipalID = principalId,
362                             MeetingName = meetingView.Name,
363                             MeetingDate = DateTime.UtcNow,
364                             MeetingSco = scoId,
365                             Ticket = ticketFromUrl,
366                             PurchaseDate = pDate,
367                             EarnedCertificate = false,
368                             Credits = 0
369                         };
370                         Database.ParticipantPurchases.InsertOnSubmit(purchase);
371
372                         Extensions.LogServiceCall("[IndexController][Login|Post]", string.Format("email = {0} scoId = {1} principalId = {2} MeetingDate = {3}", email, scoId, principalId, purchase.MeetingDate));
373                     }
374
375                     Database.SubmitChanges();
376                     certificateId = purchase.Purchase_ID;
377                 }
378                 meetingView.CertificateId = certificateId;
379                 meetingView.ScoId = scoId;
380
381                 Extensions.LogServiceCall("[IndexController][Login|Post]", string.Format("email = {0} scoId = {1} certificateId = {2} principalId = {3}", email, scoId, certificateId, principalId));
382
383                 var idCookie = new HttpCookie("id") {
384                     Value = principalId.ToString(),
385                     Expires = DateTime.UtcNow.AddDays(1)
386                 };
387                 Response.Cookies.Add(idCookie);
388
389
390                 request = new Request(admin, "principal-update");
391                 request.Parameters.Add("first-name", firstname);
392                 request.Parameters.Add("last-name", lastname);
393                 request.Parameters.Add("principal-id", principalId.ToString());
394                 request.Execute();
395
396                 return View("meeting", meetingView);
397             }
398             return RedirectToAction("Login");
399         }
400
401         [HttpGet]
402         public ActionResult Admin() {
403             return View();
404         }
405
406         public ActionResult Email() {
407             var email = new MailMessage {
408                 To = {
409                     "sophia@sophicsystems.com"
410                 },
411                 Subject = "[CPE] Email Test",
412                 Body = "Email test has been received.",
413                 From = new MailAddress("support@intesolv.com")
414             };
415             var server = new SmtpClient("localhost");
416             server.Send(email);
417
418             return Redirect("/");
419         }
420         public ActionResult SendCerificateEmail(string email, string url, string key)
421         {
422             if (key != "q1w2e3") return Content("Bad key");
423             var course = Database.PurchasedCourses
424                 .Where(c => c.Email == email && c.ContentUrl == url)
425                 .OrderByDescending(c => c.CertificateDate).FirstOrDefault();
426
427             var done = SendEmailHelperWeb.SendCertificateEmail(course);
428
429             var s = url.Split('-');
430             var courseName = Database.CourseDetails
431                 .FirstOrDefault(c => c.ReleaseCode == s[1])?.Name;
432
433             Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} cert sent email={1} courseName={2}", DateTime.UtcNow.ToString("yyyyMMdd_HHmmss"), email, courseName);
434
435             return Content("Certificate send successfully");
436         }
437
438         [HttpPost]
439         public ActionResult Admin(string login, string passcode) {
440             login = login?.Trim();
441             passcode = passcode?.Trim();
442
443             string systemPassword = ConfigurationManager.AppSettings["password"];
444             if(login == ConfigurationManager.AppSettings["login"] & passcode == systemPassword) {
445                 var reportingCookie = new HttpCookie("allowed") {
446                     Value = systemPassword,
447                     Expires = DateTime.UtcNow.AddDays(1)
448                 };
449                 Response.Cookies.Add(reportingCookie);
450             }
451             return Redirect("/");
452         }
453
454         [HttpGet]
455         public ActionResult CourseDetails(string releaseCode) {
456             releaseCode = releaseCode?.Trim();
457
458             var course = Database.CourseDetails.Single(cd => cd.ReleaseCode == releaseCode);
459             var result = new ElucidatCourseViewModel {
460                 CourseDetail = course,
461                 PurchasedCoursesDataResult = Database.PurchasedCoursesData(releaseCode)
462                                                      .OrderByDescending(pc => pc.PurchaseDate)
463                                                      .ToList()
464             };
465
466             return View(result);
467         }
468
469         [HttpGet]
470         public ActionResult Elucidat() {
471             if(Request.Cookies["allowed"] == null && !IsLocal())
472                 return Redirect("http://www.cpeonline.com/webcasts");
473             string systemPassword = ConfigurationManager.AppSettings["password"];
474             if(Request.Cookies["allowed"] != null && (Request.Cookies["allowed"].Value != systemPassword))
475                 return Redirect("http://www.cpeonline.com/webcasts");
476             DateTime now = DateTime.UtcNow;
477
478             List<CourseListingsDataResult> courseListings = Database.CourseListingsData()
479                                                                     .Where(cl => cl.CreatedDate != null)
480                                                                     .OrderBy(cl => cl.Name)
481                                                                     .ToList();
482             return View(courseListings);
483         }
484
485         [HttpGet]
486         public ActionResult Wufoo(int id) {
487             //https://cpeonline.wufoo.com/forms/cpe-webcast-evaluation/def/Field1=Jason&Field2=Wigginton&Field3-1=7&Field3-2=2&Field3=2012&Field4=1234&Field5=J.%20McIntosh&Field6=ConnectPro&Field7=Test101&Field8=Test%20topic
488             ParticipantTracking pt = Database.ParticipantTrackings.OrderByDescending(p => p.StartDate)
489                                              .FirstOrDefault(p => p.Principal_ID == id);
490             string url = ConfigurationManager.AppSettings["Wufoo.Survey1.1"];
491             if(pt == null) {
492                 Extensions.LogServiceCall("[IndexController][Wufoo]", string.Format("id = {0} url = {1}", id, url));
493                 return Redirect(url);
494             }
495
496             MeetingDetail d = pt.MeetingParticipantSession.MeetingSession.Meeting.MeetingDetail;
497             DateTime date = Extensions.GetLocalDateTime(DateTime.UtcNow);
498             url += string.Format(ConfigurationManager.AppSettings["Wufoo.Survey1.2"], pt.Participant.FirstName, pt.Participant.LastName, date.Month.ToString("00"), date.Day.ToString("00"), date.Year, d.TopicID, d.TopicName, d.Instructor, d.Location, d.CourseCode);
499             Extensions.LogServiceCall("[IndexController][Wufoo]", string.Format("id = {0} url = {1}", id, url));
500             return Redirect(url);
501         }
502
503         public ActionResult Survey() {
504             int id = 0;
505             string url = ConfigurationManager.AppSettings["Wufoo.Survey1.1"];
506             string cookie = Request.Cookies["id"] == null
507                                 ? "0"
508                                 : Request.Cookies["id"].Value;
509             int.TryParse(cookie, out id);
510             if(id == 0) {
511                 return Redirect(url);
512             }
513             Extensions.LogServiceCall("[IndexController][Survey]", string.Format("id = {0}", id));
514             ParticipantTracking pt = Database.ParticipantTrackings.OrderByDescending(p => p.StartDate)
515                                              .FirstOrDefault(p => p.Principal_ID == id);
516             if(pt == null)
517                 return Redirect(url);
518
519             MeetingDetail d = pt.MeetingParticipantSession.MeetingSession.Meeting.MeetingDetail;
520             DateTime date = Extensions.GetLocalDateTime(DateTime.UtcNow);
521             url += string.Format(ConfigurationManager.AppSettings["Wufoo.Survey1.2"], pt.Participant.FirstName, pt.Participant.LastName, date.Month.ToString("00"), date.Day.ToString("00"), date.Year, d.TopicID, d.TopicName, d.Instructor, d.Location, d.CourseCode);
522             return Redirect(url);
523         }
524
525         [HttpGet]
526         public ActionResult AllowReporting(Guid? id) {
527             //if (id.HasValue && id == Guid.Parse("")) {
528             //    var reportingCookie = new HttpCookie("reporting") {Value = "1", Expires = DateTime.MaxValue};
529             //    Response.Cookies.Add(reportingCookie);
530             //    return Redirect("/");
531             //}
532             //return Redirect("http://www.cpeonline.com/webcasts");
533             return RedirectToAction("Admin");
534         }
535
536         [HttpGet]
537         public ActionResult GetTicket(string courseUrl) {
538             courseUrl = courseUrl?.Trim();
539
540             TicketModel ticketInfo = new TicketModel {
541                 CourseUrl = courseUrl
542             };
543             //return the view as a partial view that opens in a pretty jquery ui form (dialog) within the page, not a new page
544             return PartialView(ticketInfo);
545         }
546
547         [HttpPost]
548         public string GetTicket(string firstname, string lastname, string email, string contenturl) {
549             //NOT IMPLEMENTED. possible solution to "magic ticket" request for ondemand course, since a global entry would not make sense
550             //generate hashed ticket link for a specific user for an ondemand course. This will bypass cpe's commerce site and allow cpe customer service to generate an access link
551
552             firstname = firstname?.Trim();
553             lastname = lastname?.Trim();
554             email = email?.Trim();
555             contenturl = contenturl?.Trim();
556
557             string purchasedate = DateTime.Now.ToString("yyyyMMdd");
558             var ticket = VerifyAccess.generateTicket(contenturl, firstname, lastname, email, purchasedate);
559
560             var link = "http://cpeonlineselfstudywebcasts.com/" + contenturl + "?d=" + purchasedate + "&c=" + ticket;
561             return link;
562         }
563
564         // GET: CertificateReport
565         [HttpGet]
566         public ActionResult CertificateReport() {
567             List<CertficateDataResult> earnedCertificates = Database.CertficateData()
568                                                                     .OrderBy(ec => ec.Course)
569                                                                     .ToList();
570             return View(earnedCertificates);
571         }
572
573         public ActionResult WebcastCertificateReport() {
574             List<WebcastCertficateDataResult> earnedCertificates = Database.WebcastCertficateData()
575                                                                            .OrderBy(ec => ec.MeetingName)
576                                                                            .ToList();
577             return View(earnedCertificates);
578         }
579
580         //public string SendCert(int meeting_sco, int certificate_id, int principal_id)
581         //{
582         //    //TODO (webcast) make outcome dictionary to return pass, fail, ineligible, or wonky:contact cust serv
583         //    string _fail = "fail";
584         //    if (certificate_id > 0)
585         //    {
586         //        ParticipantPurchase purchase =
587         //            Database.ParticipantPurchases.FirstOrDefault(p => p.Purchase_ID == certificate_id && p.PrincipalID == principal_id);
588
589         //        if (purchase == null)
590         //        {
591         //            //if the certificate_id is >0 then purchase would only be null because of record being deleted while user was in the meeting, or the principalID got mis-matched
592         //            return _fail; // TODO probably return wonky, contact cust service message
593         //        }
594
595         //        if (!purchase.EarnedCertificate)
596         //        {
597         //            var meeting = Database.MeetingSessions.FirstOrDefault(
598         //                    m =>
599         //                        m.Recording == false && m.SCO_ID == meeting_sco &&
600         //                        m.StartDate.DayOfYear == DateTime.UtcNow.DayOfYear);
601         //            if (meeting == null)
602         //            {
603         //                return _fail;//TODO return wonky
604         //            }
605
606         //            int meetingSessionKey = meeting.MeetingSessionKey;
607
608         //            MeetingParticipantSession meetingParticipantSession =
609         //                Database.MeetingParticipantSessions.FirstOrDefault(
610         //                    m => m.MeetingSessionKey == meetingSessionKey && m.ParticipantKey == principal_id);
611         //            if (meetingParticipantSession == null)
612         //            {
613         //                return _fail;//TODO return wonky
614         //            }
615
616         //            List<ParticipantSessionsDataResult> participantSessionsDataResult =
617         //                Database.ParticipantSessionsData(meetingSessionKey)
618         //                    .ToList();
619
620         //            var participantSessionsData =
621         //                participantSessionsDataResult.OrderBy(p => p.MeetingParticipantSessionKey)
622         //                    .FirstOrDefault(
623         //                        p =>
624         //                            p.MeetingParticipantSessionKey ==
625         //                            meetingParticipantSession.MeetingParticipantSessionKey);
626
627         //            if (participantSessionsData == null)
628         //            {
629         //                return _fail;//TODO is this a return wonky? it means they weren't tracked
630         //            }
631
632         //            MeetingSessionsDataResult meetingSession = Database.MeetingSessionsData().FirstOrDefault(m => m.MeetingSessionKey == meetingSessionKey);
633         //            if (meetingSession == null)
634         //            {
635         //                return _fail;//TODO return wonky
636         //            }
637
638         //            var courseLength = meetingSession.ActualSessionTime.GetValueOrDefault(); //in minutes
639         //            double courseCredits = courseLength / 50.0; //1 credit per 50 minutes
640         //            List<double> maxCourseCredits = ConfigurationManager.AppSettings["MaxCourseCreditList"].Split(';').Select(s => double.Parse(s)).ToList(); //max credits cut list
641         //            int mx = maxCourseCredits.BinarySearch(courseCredits); //find appropriate max for this course
642         //            double maxCredits = maxCourseCredits[mx >= 0 ? mx : ~mx - 1];//...by rounding down
643         //            double realCredits = participantSessionsData.SessionCredit == null ? 0 : (double)participantSessionsData.SessionCredit.Value; //users credits per adobe
644         //            purchase.Credits = Math.Min(maxCredits, realCredits); //user awarded no more than max possible credits for the course
645
646         //            MeetingDetail meetingDetail =
647         //                Database.MeetingDetails.FirstOrDefault(m => m.MeetingKey == purchase.MeetingSco);
648
649         //            purchase.Presenter = meetingDetail == null ? "" : meetingDetail.Instructor;
650
651         //            double percentComplete = (participantSessionsData.SessionEngagementCount.GetValueOrDefault() == 0 ? 
652         //                    1 : (participantSessionsData.SessionHeartbeatCount.GetValueOrDefault() / participantSessionsData.SessionEngagementCount.Value));
653
654         //            if (percentComplete >= .75) //threshold for earning a certificate is 75% response rate
655         //            {
656         //                purchase.EarnedCertificate = true;
657         //            }
658
659         //            Database.SubmitChanges();
660
661         //            if (purchase.EarnedCertificate)
662         //            {
663         //                //TODO with return Pass dictionary value as string.format with replace of certUrl
664         //                //string certUrl = AdobeCertificateHelper.SendWebcastCert(purchase);
665         //                //format the outcome.pass.value message with certUrl replace
666         //                //return outcome.pass with its value
667         //                return AdobeCertificateHelper.SendWebcastCert(purchase);
668         //            }
669         //            //TODO return outcome.fail
670         //            return AdobeCertificateHelper.SendFailNotice(purchase);
671         //        }
672         //    }
673         //    return _fail;// TODO return ineligible.need to make AdobeCertificateHelper.SendIneligibleNotice(principalId)
674         //}
675
676         //public participantResult ProcessParticipantResult(participantResult result, ParticipantPurchase purchase)
677         //{
678         //    if (purchase == null)
679         //    {
680         //        result = participantResult.Ineligible;
681         //    }
682         //    switch (result)
683         //    {
684         //        case participantResult.Ineligible:
685         //            //Ineligible for auto-cert; not sending notice.  
686         //            break;
687         //        case participantResult.Fail:
688         //            AdobeCertificateHelper.SendFailNotice(purchase);
689         //            break;
690         //        case participantResult.Pass:
691         //            AdobeCertificateHelper.SendWebcastCert(purchase);
692         //            //Send Cert email;
693         //            break;
694         //        case participantResult.Wonky:
695         //            //something went wrong: send email to contact cust service? send email to cpe? do nothing? 
696         //            break;
697         //    }
698         //    return result;
699         //}
700
701         //public ActionResult BatchProcessParticipantResults(int msk)
702         //{
703         //    List<ParticipantSessionsDataResult> psdr = BaseController.Database.ParticipantSessionsData(msk).ToList();
704         //    var meeting = BaseController.Database.MeetingSessions.FirstOrDefault(m => m.MeetingSessionKey == msk);
705         //    if (meeting == null)
706         //    {
707         //        return Content("Error retrieving meeting session details.");
708         //    }
709         //    var scoId = meeting.SCO_ID;
710
711         //    foreach (var p in psdr)
712         //    {
713         //        ParticipantPurchase purchase = null;
714         //        participantResult result = participantResult.Wonky;
715         //        var mpsk = p.MeetingParticipantSessionKey;
716         //        var meetingParticipantSession =
717         //            BaseController.Database.MeetingParticipantSessions.FirstOrDefault(
718         //                mps => mps.MeetingParticipantSessionKey == mpsk && mps.MeetingSessionKey == msk);
719
720         //        if (meetingParticipantSession != null)
721         //        {
722         //            var principalId = meetingParticipantSession.ParticipantKey;
723
724         //            purchase = BaseController.Database.ParticipantPurchases.FirstOrDefault(pp => pp.PrincipalID == principalId && pp.MeetingSco == scoId);
725         //            if (purchase == null)
726         //            {
727         //                result = participantResult.Ineligible;
728         //            }
729         //            else
730         //            {
731         //                MeetingSessionsDataResult meetingSession = Database.MeetingSessionsData().FirstOrDefault(m => m.MeetingSessionKey == msk);
732         //                if (meetingSession != null)
733         //                {
734         //                    var courseLength = meetingSession.ActualSessionTime.GetValueOrDefault(); //in minutes
735         //                    double courseCredits = courseLength/50.0; //1 credit per 50 minutes
736         //                    List<double> maxCourseCredits =
737         //                        ConfigurationManager.AppSettings["MaxCourseCreditList"].Split(';')
738         //                            .Select(s => double.Parse(s))
739         //                            .ToList(); //max credits cut list
740         //                    int mx = maxCourseCredits.BinarySearch(courseCredits);
741         //                        //find appropriate max for this course
742         //                    double maxCredits = maxCourseCredits[mx >= 0 ? mx : ~mx - 1]; //...by rounding down
743         //                    double realCredits = p.SessionCredit == null
744         //                        ? 0
745         //                        : (double) p.SessionCredit.Value; //users credits
746         //                    purchase.Credits = Math.Min(maxCredits, realCredits);
747         //                        //user awarded no more than max possible credits for the course
748
749         //                    MeetingDetail meetingDetail =
750         //                        Database.MeetingDetails.FirstOrDefault(m => m.MeetingKey == purchase.MeetingSco);
751
752         //                    purchase.Presenter = meetingDetail == null ? "" : meetingDetail.Instructor;
753
754         //                    double percentComplete =
755         //                        (p.SessionEngagementCount.GetValueOrDefault() == 0
756         //                            ? 1
757         //                            : (p.SessionHeartbeatCount.GetValueOrDefault()/
758         //                               p.SessionEngagementCount.Value));
759
760         //                    if (percentComplete >= .75) //threshold for earning a certificate is 75% response rate
761         //                    {
762         //                        purchase.EarnedCertificate = true;
763         //                        result = participantResult.Pass;
764         //                    }
765         //                    else
766         //                    {
767         //                        result = participantResult.Fail;
768         //                    }
769
770         //                    Database.SubmitChanges();
771         //                }
772         //            }
773         //        }
774         //        ProcessParticipantResult(result, purchase);
775         //    }
776         //    return Content("done");
777         //}
778
779         public ActionResult Result(int principalid, int scoid) {
780             var resultView = new SessionResultViewModel();
781             participantResult result = participantResult.Wonky;
782
783             Extensions.LogServiceCall("[IndexController][Result]", string.Format("Beginning: principalid = {0} scoid = {1}", principalid, scoid));
784
785             Extensions.LogServiceCall("[IndexController][Result]", string.Format(
786                                                                                  "principalid = {0} scoid = {1} DateTime.UtcNow.DayOfYear = {2} DateTime.Now.DayOfYear = {3}",
787                                                                                  principalid, scoid, DateTime.UtcNow.DayOfYear, DateTime.Now.DayOfYear));
788
789             var meeting =
790                 Database.MeetingSessions.FirstOrDefault(
791                                                         m => m.SCO_ID == scoid && m.StartDate.DayOfYear == DateTime.UtcNow.DayOfYear);
792             if(meeting != null) {
793                 int msk = meeting.MeetingSessionKey;
794                 MeetingParticipantSession meetingParticipantSession =
795                     Database.MeetingParticipantSessions.FirstOrDefault(
796                                                                        m => m.MeetingSessionKey == msk && m.ParticipantKey == principalid);
797                 if(meetingParticipantSession != null) {
798                     adobe.GetAdobeTransactions(meetingParticipantSession.MeetingSession, Database);
799                     Database.SubmitChanges();
800
801                     result = SessionEnd.ProcessEndOfMeetingSessionHeartbeatResultsForParticipant(Database, meetingParticipantSession);
802                     switch (result) {
803                         case participantResult.Ineligible:
804                             resultView.Message = Utilities.Result.RenderIneligibleResult(principalid);
805                             break;
806                         case participantResult.Fail:
807                             resultView.Message = Utilities.Result.RenderFailResult(principalid);
808                             break;
809                         case participantResult.Pass:
810                             resultView.Message = Utilities.Result.RenderPassResult(principalid);
811                             break;
812                         case participantResult.Wonky:
813                             resultView.Message = Utilities.Result.RenderWonkyResult();
814                             break;
815                     }
816                 } else {
817                     Extensions.LogServiceCall("[IndexController][Result]", string.Format(
818                                                                                          "meetingParticipantSession is null: principalid = {0} scoid= {1} msk = {2}",
819                                                                                          principalid, scoid, msk));
820                 }
821             } else {
822                 Extensions.LogServiceCall("[IndexController][Result]", string.Format(
823                                                                                      "meeting is null: principalid = {0} scoid= {1} DateTime.UtcNow.DayOfYear = {2} DateTime.Now.DayOfYear = {3}",
824                                                                                      principalid, scoid, DateTime.UtcNow.DayOfYear, DateTime.Now.DayOfYear));
825             }
826             resultView.Result = (int) result;
827             return View("result", resultView);
828         }
829     }
830 }