Employee Name - @Model.EmployeeName
28 |Employee ID -@Model.EmployeeID
29 |Leave Start Date - @Model.LeaveStartDate
30 |Leave End Date - @Model.LeaveEndDate
31 |Leave ID - @Model.LeaveID
32 | @if (@Model.LeaveStatus != null && @Model.LeaveStatus == "Approved") 33 | { 34 |Leave Status - @Model.LeaveStatus
35 |Leave Status - @Model.LeaveStatus
40 |Employee Name - @item.EmployeeName
35 |Employee ID -@item.EmployeeID
36 |Leave Start Date - @item.LeaveStartDate
37 |Leave End Date - @item.LeaveEndDate
38 |Leave ID - @item.LeaveID
39 | if (item.LeaveStatus != null && item.LeaveStatus == "Pending") 40 | { 41 |Leave Status - @item.LeaveStatus
42 |Leave Status - @item.LeaveStatus
52 |Leave Status - @item.LeaveStatus
57 |Use this page to detail your site's privacy policy.
23 | -------------------------------------------------------------------------------- /LeaveWebApp/LeaveWebApp/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | 16 | 17 | @model ErrorViewModel 18 | @{ 19 | ViewData["Title"] = "Error"; 20 | } 21 | 22 |
28 | Request ID: @Model.RequestId
29 |
34 | Swapping to Development environment will display more detailed information about the error that occurred. 35 |
36 |37 | The Development environment shouldn't be enabled for deployed applications. 38 | It can result in displaying sensitive information from exceptions to end users. 39 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 40 | and restarting the app. 41 |
42 | -------------------------------------------------------------------------------- /LeaveWebApp/LeaveWebApp/Views/Shared/_CookieConsentPartial.cshtml: -------------------------------------------------------------------------------- 1 | 16 | 17 | @using Microsoft.AspNetCore.Http.Features 18 | 19 | @{ 20 | var consentFeature = Context.Features.Get9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("netmask",function(a,b){return this.optional(b)||/^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test(a)},"Please enter a valid netmask."),a.validator.addMethod("nieES",function(a,b){"use strict";if(this.optional(b))return!0;var c,d=new RegExp(/^[MXYZ]{1}[0-9]{7,8}[TRWAGMYFPDXBNJZSQVHLCKET]{1}$/gi),e="TRWAGMYFPDXBNJZSQVHLCKET",f=a.substr(a.length-1).toUpperCase();return a=a.toString().toUpperCase(),!(a.length>10||a.length<9||!d.test(a))&&(a=a.replace(/^[X]/,"0").replace(/^[Y]/,"1").replace(/^[Z]/,"2"),c=9===a.length?a.substr(0,8):a.substr(0,9),e.charAt(parseInt(c,10)%23)===f)},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a,b){"use strict";return!!this.optional(b)||(a=a.toUpperCase(),!!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")&&(/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):!!/^[KLM]{1}/.test(a)&&a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,1)%23)))},"Please specify a valid NIF number."),a.validator.addMethod("nipPL",function(a){"use strict";if(a=a.replace(/[^0-9]/g,""),10!==a.length)return!1;for(var b=[6,5,7,2,3,4,5,6,7],c=0,d=0;d<9;d++)c+=b[d]*a[d];var e=c%11,f=10===e?0:e;return f===parseInt(a[9],10)},"Please specify a valid NIP number."),a.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return!!this.optional(b)||("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=!e&&"undefined"!=typeof c.caseSensitive&&c.caseSensitive,g=!e&&"undefined"!=typeof c.includeTerritories&&c.includeTerritories,h=!e&&"undefined"!=typeof c.includeMilitary&&c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;b<17;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!c.settings.submitHandler||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(null!=j&&(!j.form&&j.hasAttribute("contenteditable")&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}}),a.extend(a.expr.pseudos||a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){var c=a(b).val();return null!==c&&!!a.trim(""+c)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){!this.form&&this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name"));var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0],this.name=d),!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type;return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=b.hasAttribute("contenteditable")?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);if("function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f){if(j=f.call(b,j),"string"!=typeof j)throw new TypeError("The normalizer should return a string value.");delete g.normalizer}for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;a Warning: No message defined for "+b.name+""),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,.\/:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[\/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e<=d},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var b,c={};return a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)}),a}); -------------------------------------------------------------------------------- /LeaveWebApp/LeaveWebApp/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /PushtoXRayPol.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "xray:PutTraceSegments", 8 | "xray:PutTelemetryRecords" 9 | ], 10 | "Resource": [ 11 | "*" 12 | ] 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## AWS Serverless Workshop Decoupled Architecture 2 | 3 | A sample .NET web application based on decoupled architecture design principles. 4 | 5 | ## License Summary 6 | 7 | The documentation is made available under the Creative Commons Attribution-ShareAlike 4.0 International License. See the LICENSE file. 8 | 9 | The sample code within this documentation is made available under the MIT-0 license. See the LICENSE-SAMPLECODE file. 10 | 11 | # Overview 12 | Create a fully decoupled, microservices architecture based Leave Management application using a variety of AWS Services such as, 13 | * Amazon ECS 14 | * Amazon Elastic Container Registry 15 | * AWS Lambda 16 | * Amazon Elastic Load Balancer 17 | * AWS X-Ray 18 | * AWS Step Functions 19 | * Amazon DynamoDB 20 | * Amazon Simple Notification Service (SNS) 21 | * Amazon API Gateway 22 | * AWS CloudWatch 23 | 24 | # Application Architecture 25 |  26 | ## The application supports the following functionalities 27 | 28 | * Submit Leave Request 29 | * Approve / Reject Leave Request 30 | * List Leave Requests 31 | * Notify status to target audience 32 | 33 | ## Following are the major parts of the application 34 | 35 | * Web front end - Serves the user interface 36 | * Microservices - Serves business functionalities 37 | * WorkFlow services - Performs back-end business operations 38 | 39 | ### The following diagram shows the request flow between the components for a new leave request workflow 40 | 41 |  42 | 43 | ## Setup Instructions 44 | #### NOTE 45 | > This is a Level 200-300 workshop and the expectation is that you are already aware of using the AWS console, basic AWS and cloud concepts such as Cloudformation, Serverless applications, API management, Load Balancers, Workflows, .NET development & Visual Studio. 46 | 47 | ### Prerequisites / Environment setup 48 | > I will use US-EAST-1 AWS region for all instructions here. Replace it with an appropriate region if you are using one other than US-EAST-1 49 | 50 | * Install Visual Studio 2019 or 2017 Community edition. 51 | * Download from here - https://visualstudio.microsoft.com/vs/community/ 52 | * Install and configure AWS Tools for Visual Studio. 53 | * Download from here - https://marketplace.visualstudio.com/items?itemName=AmazonWebServices.AWSToolkitforVisualStudio2017 54 | * Install and configure AWS Tools for PowershellCore. 55 | * Download and configure from here - 56 | https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up-windows.html 57 | * Clone this GitHub repo 58 | * https://github.com/awsimaya/DecoupledArchitecture 59 | * Install Docker for Windows 60 | * Download from here - https://docs.docker.com/docker-for-windows/install/ 61 | ### Create Workflow services 62 | #### Create Amazon SNS Topic 63 | 64 | > This SNS topic is used to notify users of Leave status changes 65 | 66 | * Login to AWS console and navigate to **Amazon SNS** topic 67 | * Enter **LeaveApproval** in the **MyTopic** textbox. Click **Next step** 68 | * On the next page, click **Create topic** 69 | * Copy and paste the **ARN** of the newly created SNS topic into a text editor 70 | * Click on **LeaveApproval** link 71 | * Under **Subscriptions**, click **Create subscription** 72 | * Select **Email** under **Protocol** dropdown 73 | * Enter your email address and click **Create subscription** 74 | * You will receive a new email from **AWS Notifications** containing a link to confirm the subscription. Click **Confirm Subscription** link on the email 75 | 76 | #### Create UpdatePayRoll Lambda Function 77 | > This is a mock Lambda function that mimics a fake Payroll system update 78 | 79 | * Open Visual Studio 80 | * Open **UpdatePayRoll.sln** solution from **UpdatePayRoll** folder in this repo 81 | * Right click on the project file and choose **Publish to AWS Lambda** 82 | * In the wizard that pops up, choose a region you want the solution to be deployed to and click **Next** 83 | * Select **AWSLambdaFullAccess** role for the **Role Name** dropdown and click **Upload** 84 | * Your Lambda application is now deployed to your AWS environment 85 | * Navigate to the newly created Lambda function home page on the AWS console 86 | * Copy the ARN for Lambda from the top right of the screen and paste into a text editor 87 | 88 | #### Create UpdateHRSystem Lambda Function 89 | 90 | > This is a mock Lambda function that mimics a fake HR system update 91 | 92 | * Open Visual Studio 93 | * Open **UpdateHRSystem.sln** solution from **UpdateHRSystem** folder in this repo 94 | * Right click on the project file and choose **Publish to AWS Lambda** 95 | * In the wizard that pops up, choose a region you want the solution to be deployed to and click **Next** 96 | * Select **AWSLambdaFullAccess** role for the **Role Name** dropdown and click **Upload** 97 | * Your Lambda application is now deployed to your AWS environment 98 | * Navigate to the newly created Lambda function home page on the AWS console 99 | * Copy the ARN for Lambda from the top right of the screen and paste into a text editor 100 | 101 | #### Create LeaveApprovalWorkflow Step Function 102 | * Open **workflow.json** from **StepFunctionWorkFlow** folder 103 | * Replace ** ** with the ARN you saved into the text editor in **Create UpdateHRSystem Lambda Function** step 104 | * Replace ** ** with the ARN you saved into the text 105 | editor in **Create UpdatePayRoll Lambda Function** step 106 | * Replace ** ** with the ARN you saved into the text editor in **Create Amazon SNS Topic** step 107 | * Login to AWS console 108 | * Navigate to AWS Step Functions home page by typing **Step Functions** on the search bar and selecting the first result 109 | * Ensure **Author with code snippets** option is selected. Enter **LeaveApprovalWorkflow** in the **NAME** textbox 110 | * Copy all the content from **workflow.json** file and paste it into the **State machine definition** textbox 111 | * Ensure **Create an IAM role for me** option is selected. Enter **leaveapprovalworkflowrole** in the **Name** textbox 112 | * Click **Create state machine** 113 | * Your step function is created successfully 114 | * Copy and paste the ARN of the Step Function you just created to a text editor for later usage 115 | 116 | ### Create Microservices 117 | 118 | >In this section we will create the Lambda functions used in processing requests from the web front end, API Gateway endpoints and a DynamoDB table to store Leave data 119 | 120 | #### Create LeaveManagementAPIs 121 | We will be creating the following resources as a result of this section 122 | 123 | * A DynanmoDB table named **LeaveRequests** 124 | * A Lambda function called **AddOrUpdateLeaveRequest** 125 | * A Lambda function called **GetLeaveRequests** 126 | * An API Gateway API called **LeaveManagementAPI** 127 | 128 | ##### Steps 129 | 130 | * Open **LeaveManagementAPI.sln** from **LeaveManagementAPI** folder 131 | * Right click on **LeaveManagementAPI** project and click **Publish to AWS Lambda...** 132 | * On the newly opened wizard, Enter **LeaveManagementAPI** in the **Stack Name** textbox 133 | * Ensure **LeaveRequests** is the value of the **LeaveTableName** textbox 134 | * Select **true** for **ShouldCreateTable** textbox 135 | * Click **Publish** 136 | * Visual Studio will open a new screen called **Stack: LeaveManagementAPI** to show the events taking place in creating the stack 137 | * Once you see **CREATE_COMPLETE** in green color, copy the URL from **AWS Serverless URL** and paste into a text editor 138 | * Navigate to DynamoDB home page on AWS console and select **LeaveRequests** table under **Tables** 139 | * Copy the **Latest stream ARN** value (shown in the picture below) and paste it into a text editor for later usage 140 | 141 |  142 | 143 | * Navigate to API Gateway home page on the AWS console and select **LeaveManagementAPI** API 144 | * Select **Stages** and select **Prod** 145 | * Under **Logs/Tracing** tab, check **Enable CloudWatch Logs** and **Enable X-Ray Tracing** checkboxes as shown below 146 | 147 |  148 | 149 | * Open **LeaveRequestProcessor.sln** solution under **LeaveRequestProcessor** folder 150 | * In **Function.cs** file, replace ** ** with the ARN you saved into the text editor in **Create Amazon SNS Topic** step 151 | * In **Function.cs** file, replace ** ** with the ARN you saved into the text editor in **Create LeaveApprovalWorkflow Step Function** step 152 | * In **serverless.template** file, replace ** ** with the DynamoDB stream ARN you created earlier 153 | * Right click on **LeaveRequestProcessor** project and select **Publish to AWS Lambda...** 154 | * In the publish wizard, enter **LeaveRequestProcessor** in the **Stack Name** textbox 155 | * Enter any name for the S3bucket in the **S3 Bucket** text box 156 | * Click **Publish** 157 | * Visual Studio will open a new window to show the progress of the deployment and will show **CREATE_COMPLETE** once successfully deployed 158 | 159 | ### Create Web front end 160 | 161 | > In this section we will create the web front end that will help users create and manage leave approval requests 162 | 163 | #### Create a new IAM role for ECS task execution 164 | > In this section, we will create a new IAM role for the ECS Service you will create to assume 165 | * Open AWS console and navigate to **IAM** -> **ROLES** 166 | * Click **Create role** 167 | * In the next screen, select **AWS service** for **Select type opf trusted identity** 168 | * Select **Elastic Container Service** under **Choose the service that will use this role** 169 | * Select **Elastic Container Service Task** under **Select your use case**. Click **Next: Permissions** 170 | * In the next screen, select **AmazonECSTaskExecutionRolePolicy** policy, click **Attach policy** and click **Next: Tags** 171 | * Click **Next** in the next page 172 | * Enter **ecsTaskExecutionRole** as name in the next page. Click **Create role** 173 | * Go back to **ecsTaskExecutionRole**, click **Add Inline policy** and go to **JSON** tab 174 | * Copy and paste the following JSON into the textarea 175 | ```json 176 | { 177 | "Version": "2012-10-17", 178 | "Statement": [ 179 | { 180 | "Effect": "Allow", 181 | "Action": [ 182 | "xray:PutTraceSegments", 183 | "xray:PutTelemetryRecords" 184 | ], 185 | "Resource": [ 186 | "*" 187 | ] 188 | } 189 | ] 190 | } 191 | ``` 192 | * Click **Review policy** 193 | * Name the policy as **PushtoXRayPol** and click **Create policy** 194 | 195 | #### Publish web app to Amazon ECS 196 | > In this section, we will publish the Web application to Amazon ECS 197 | * Open **LeaveWebApp.sln** file from the **LeaveWebApp** folder 198 | * In **HomeController.cs**, replace ** ** with the API Gateway URL you saved in step **Create LeaveManagementAPIs** 199 | * Right click on **LeaveWebApp** project and click **Publish Container to AWS...** 200 | * In the wizard, enter **leavewebapp** in **Docker Repository** field 201 | * Select **Service on ECS Cluster** option (as shown below) and click **Next** 202 |  203 | * In the next window, select **Create an empty cluster** and enter **LeaveWebApp** in the textbox next to the dropdown. Click **Next** 204 | * In the next window, select **Create New** for **Service** and enter **LeaveWebApp** in the textbox next to dropdown. Click **Next** 205 | * In the next window, check **Configure Application Load Balancer** check box, select **Create New** for **Load Balancer:** dropdown and enter **LeaveWebApp** in the textbox next to it.Click **Next** 206 |  207 | * In the next window, select **Create New** for **Task Definition** dropdown and enter **LeaveWebApp** in the textbox next to it. 208 | * Select **Create New** for **Container** dropdown and enther **LeaveWebApp** in the textbox next to it. 209 | * Select **Existing role: ecsTaskExecutionRole** for **Task Role:** dropdown 210 | * Select **ecsTaskExecutionRole** for **Task Execution Role** dropdown 211 | * Click **Publish** 212 | * Visual Studio will now start publishing the application environment 213 | * You just published the Web application to Amazon ECS 214 | * Once complete, you will be able to see a new ECS service called **LeaveWebApp** on the AWS console 215 | 216 | #### Configure XRay for the ECS Service 217 | > In this section, we will create a X-Ray daemon container which will run as a side-car container along with the LeaveWebApp container to process and send X-Ray data to the X-Ray service on AWS. 218 | 219 | > More about this topic here - https://docs.aws.amazon.com/xray/latest/devguide/xray-daemon-ecs.html 220 | 221 | * Open PowerShell and execute the following commands. The first command pulls the **aws-xray-daemon** container image from docker hub. The second command tags the image as **xraydaemon** 222 | ```docker 223 | docker pull amazon/aws-xray-daemon 224 | docker tag amazon/aws-xray-daemon:latest xraydaemon:latest 225 | ``` 226 | * Login to AWS console and navigate to **Amazon ECS**. Click **Repositories** on the left navigation section 227 | * Click **Create repository** and name it **xraydaemon** 228 | * Click **Create repository** 229 | * Click on **View push commands** on the top right of the screen 230 | * Choose Windows or macOS/Linux tab and execute the command from Step 1. The command will return a very long URL. Copy and paste the URL into the command line and press enter. 231 | * Skip the step 2 command, because we already have the container image downloaded from docker hub earlier. Execute commands from Step 3 and Step 4. 232 | * Once complete, go to the **xraydaemon** repository on the AWS ECR home page and ensure the new image has been published successfully 233 | * Navigate to **Task Definitions** on **Amazon ECS** home page and click **LeaveWebApp** 234 | * Select the latest version and click **Create new revision** 235 | * Under **Container Definitions** click **Add container** 236 | * Name the container **xray-daemon** 237 | * Copy and paste the container image URI from **xraydaemon** ECR repo into the **Image** textbox 238 | * Click **Add** button at the bottom 239 | * Select the newly created version of the Task Definition 240 | * Select **Actions** -> **Update Service** 241 | * Select **LeaveWebApp** in the **Cluster** dropdown 242 | * Check **Force new deployment** checkbox 243 | * Click **Next step** in the next few screens until you get to **Review** screen. Click **Update Service** 244 | * You just finished deploying the Leave Web App to Amazon ECS 245 | 246 | ### Test drive the application 247 | * Copy and paste the DNS name of the **LeaveWebApp** ALB from the EC2 home page on AWS console into a browser and press enter 248 | * You should be able to see the application as shown below 249 |  250 | * You can Submit a Leave Request and also Approve a Leave Request using this application by clicking on the appropriate links. 251 | * Once you submit a Leave Request, you will see an email arrive in your email inbox that you configured earlier 252 | * Also another email will land in your email inbox once you approve a request as well 253 | * After you play around with the application for a while, you can navigate to X-Ray home page on AWS console and click **Service map** 254 | * You should be able to see the service map as shown below 255 |  256 | -------------------------------------------------------------------------------- /StepFunctionWorkFlow/workflow.json: -------------------------------------------------------------------------------- 1 | { 2 | "Comment": "Leave Application processor workflow", 3 | "StartAt": "UpdateHRSystem", 4 | "States": { 5 | "UpdateHRSystem": { 6 | "Type": "Task", 7 | "Resource": " ", 8 | "Next":"UpdatePayRoll", 9 | "ResultPath":"$" 10 | }, 11 | "UpdatePayRoll":{ 12 | "Type":"Task", 13 | "Resource":" ", 14 | "Next":"SendNotifications" 15 | }, 16 | "SendNotifications":{ 17 | "Type":"Task", 18 | "Resource":"arn:aws:states:::sns:publish", 19 | "Parameters": { 20 | "TopicArn": " ", 21 | "Message": "Leave Approval process complete !!" 22 | }, 23 | "End":true 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /UpdateHRSystem/UpdateHRSystem.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28902.138 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UpdateHRSystem", "UpdateHRSystem\UpdateHRSystem.csproj", "{0287D553-CE8A-4FC9-BE3F-1E67B75A46A4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {0287D553-CE8A-4FC9-BE3F-1E67B75A46A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {0287D553-CE8A-4FC9-BE3F-1E67B75A46A4}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {0287D553-CE8A-4FC9-BE3F-1E67B75A46A4}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {0287D553-CE8A-4FC9-BE3F-1E67B75A46A4}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {10212075-EE23-457C-A10E-F9B807F6F536} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /UpdateHRSystem/UpdateHRSystem/Function.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, 6 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | // permit persons to whom the Software is furnished to do so. 8 | 9 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Linq; 19 | using System.Threading.Tasks; 20 | 21 | using Amazon.Lambda.Core; 22 | 23 | // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class. 24 | [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))] 25 | 26 | namespace UpdateHRSystem 27 | { 28 | public class Function 29 | { 30 | /// 31 | /// Mock HR System update API returns "Approved" or "Rejected" based on odd or even minute. 32 | /// 33 | /// LeaveID 34 | /// 35 | ///36 | public string FunctionHandler(string input, ILambdaContext context) 37 | { 38 | //Ideally, the function would read the DynamoDB table with the LeaveID and update the HR system. 39 | //This is only a mock API to mimick a HR system update and enable the Step Function workflow. 40 | return "HR System updated"; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /UpdateHRSystem/UpdateHRSystem/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Mock Lambda Test Tool": { 4 | "commandName": "Executable", 5 | "commandLineArgs": "--port 5050", 6 | "workingDirectory": ".\\bin\\Debug\\netcoreapp2.1", 7 | "executablePath": "C:\\Users\\%USERNAME%\\.dotnet\\tools\\dotnet-lambda-test-tool-2.1.exe" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /UpdateHRSystem/UpdateHRSystem/Readme.md: -------------------------------------------------------------------------------- 1 | # AWS Lambda Empty Function Project 2 | 3 | This starter project consists of: 4 | * Function.cs - class file containing a class with a single function handler method 5 | * aws-lambda-tools-defaults.json - default argument settings for use with Visual Studio and command line deployment tools for AWS 6 | 7 | You may also have a test project depending on the options selected. 8 | 9 | The generated function handler is a simple method accepting a string argument that returns the uppercase equivalent of the input string. Replace the body of this method, and parameters, to suit your needs. 10 | 11 | ## Here are some steps to follow from Visual Studio: 12 | 13 | To deploy your function to AWS Lambda, right click the project in Solution Explorer and select *Publish to AWS Lambda*. 14 | 15 | To view your deployed function open its Function View window by double-clicking the function name shown beneath the AWS Lambda node in the AWS Explorer tree. 16 | 17 | To perform testing against your deployed function use the Test Invoke tab in the opened Function View window. 18 | 19 | To configure event sources for your deployed function, for example to have your function invoked when an object is created in an Amazon S3 bucket, use the Event Sources tab in the opened Function View window. 20 | 21 | To update the runtime configuration of your deployed function use the Configuration tab in the opened Function View window. 22 | 23 | To view execution logs of invocations of your function use the Logs tab in the opened Function View window. 24 | 25 | ## Here are some steps to follow to get started from the command line: 26 | 27 | Once you have edited your template and code you can deploy your application using the [Amazon.Lambda.Tools Global Tool](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools) from the command line. 28 | 29 | Install Amazon.Lambda.Tools Global Tools if not already installed. 30 | ``` 31 | dotnet tool install -g Amazon.Lambda.Tools 32 | ``` 33 | 34 | If already installed check if new version is available. 35 | ``` 36 | dotnet tool update -g Amazon.Lambda.Tools 37 | ``` 38 | 39 | Execute unit tests 40 | ``` 41 | cd "UpdateHRSystem/test/UpdateHRSystem.Tests" 42 | dotnet test 43 | ``` 44 | 45 | Deploy function to AWS Lambda 46 | ``` 47 | cd "UpdateHRSystem/src/UpdateHRSystem" 48 | dotnet lambda deploy-function 49 | ``` 50 | -------------------------------------------------------------------------------- /UpdateHRSystem/UpdateHRSystem/UpdateHRSystem.csproj: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /UpdateHRSystem/UpdateHRSystem/aws-lambda-tools-defaults.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Information" : [ 4 | "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.", 5 | "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.", 6 | "dotnet lambda help", 7 | "All the command line options for the Lambda command can be specified in this file." 8 | ], 9 | "profile" : "imaya-dev", 10 | "region" : "us-east-1", 11 | "configuration" : "Release", 12 | "framework" : "netcoreapp2.1", 13 | "function-runtime" : "dotnetcore2.1", 14 | "function-memory-size" : 256, 15 | "function-timeout" : 30, 16 | "function-handler" : "UpdateHRSystem::UpdateHRSystem.Function::FunctionHandler", 17 | "function-name" : "UpdateHRSystem", 18 | "function-role" : "3 | 7 |netcoreapp2.1 4 |true 5 |Lambda 6 |8 | 11 |9 | 10 | ", 19 | "tracing-mode" : "PassThrough", 20 | "environment-variables" : "" 21 | } -------------------------------------------------------------------------------- /UpdatePayRoll/UpdatePayRoll.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28902.138 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UpdatePayRoll", "UpdatePayRoll\UpdatePayRoll.csproj", "{699696E4-92A2-4359-BA98-0C55C8C30BBC}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {699696E4-92A2-4359-BA98-0C55C8C30BBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {699696E4-92A2-4359-BA98-0C55C8C30BBC}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {699696E4-92A2-4359-BA98-0C55C8C30BBC}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {699696E4-92A2-4359-BA98-0C55C8C30BBC}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {A483ED71-10DE-4198-8F96-1D6850635265} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /UpdatePayRoll/UpdatePayRoll/Function.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, 6 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | // permit persons to whom the Software is furnished to do so. 8 | 9 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Linq; 19 | using System.Threading.Tasks; 20 | 21 | using Amazon.Lambda.Core; 22 | 23 | // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class. 24 | [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))] 25 | 26 | namespace UpdatePayRoll 27 | { 28 | public class Function 29 | { 30 | 31 | /// 32 | /// Mock function to update PayRoll system 33 | /// 34 | /// LeaveID 35 | /// 36 | ///37 | public string FunctionHandler(string input, ILambdaContext context) 38 | { 39 | // Just returns "Updated" to mimic a PayRoll system update and help the Step Function workflow 40 | return "PayRoll Updated"; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /UpdatePayRoll/UpdatePayRoll/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Mock Lambda Test Tool": { 4 | "commandName": "Executable", 5 | "commandLineArgs": "--port 5050", 6 | "workingDirectory": ".\\bin\\Debug\\netcoreapp2.1", 7 | "executablePath": "C:\\Users\\%USERNAME%\\.dotnet\\tools\\dotnet-lambda-test-tool-2.1.exe" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /UpdatePayRoll/UpdatePayRoll/Readme.md: -------------------------------------------------------------------------------- 1 | # AWS Lambda Empty Function Project 2 | 3 | This starter project consists of: 4 | * Function.cs - class file containing a class with a single function handler method 5 | * aws-lambda-tools-defaults.json - default argument settings for use with Visual Studio and command line deployment tools for AWS 6 | 7 | You may also have a test project depending on the options selected. 8 | 9 | The generated function handler is a simple method accepting a string argument that returns the uppercase equivalent of the input string. Replace the body of this method, and parameters, to suit your needs. 10 | 11 | ## Here are some steps to follow from Visual Studio: 12 | 13 | To deploy your function to AWS Lambda, right click the project in Solution Explorer and select *Publish to AWS Lambda*. 14 | 15 | To view your deployed function open its Function View window by double-clicking the function name shown beneath the AWS Lambda node in the AWS Explorer tree. 16 | 17 | To perform testing against your deployed function use the Test Invoke tab in the opened Function View window. 18 | 19 | To configure event sources for your deployed function, for example to have your function invoked when an object is created in an Amazon S3 bucket, use the Event Sources tab in the opened Function View window. 20 | 21 | To update the runtime configuration of your deployed function use the Configuration tab in the opened Function View window. 22 | 23 | To view execution logs of invocations of your function use the Logs tab in the opened Function View window. 24 | 25 | ## Here are some steps to follow to get started from the command line: 26 | 27 | Once you have edited your template and code you can deploy your application using the [Amazon.Lambda.Tools Global Tool](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools) from the command line. 28 | 29 | Install Amazon.Lambda.Tools Global Tools if not already installed. 30 | ``` 31 | dotnet tool install -g Amazon.Lambda.Tools 32 | ``` 33 | 34 | If already installed check if new version is available. 35 | ``` 36 | dotnet tool update -g Amazon.Lambda.Tools 37 | ``` 38 | 39 | Execute unit tests 40 | ``` 41 | cd "UpdatePayRoll/test/UpdatePayRoll.Tests" 42 | dotnet test 43 | ``` 44 | 45 | Deploy function to AWS Lambda 46 | ``` 47 | cd "UpdatePayRoll/src/UpdatePayRoll" 48 | dotnet lambda deploy-function 49 | ``` 50 | -------------------------------------------------------------------------------- /UpdatePayRoll/UpdatePayRoll/UpdatePayRoll.csproj: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /UpdatePayRoll/UpdatePayRoll/aws-lambda-tools-defaults.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Information" : [ 4 | "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.", 5 | "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.", 6 | "dotnet lambda help", 7 | "All the command line options for the Lambda command can be specified in this file." 8 | ], 9 | "profile" : "imaya-dev", 10 | "region" : "us-east-1", 11 | "configuration" : "Release", 12 | "framework" : "netcoreapp2.1", 13 | "function-runtime" : "dotnetcore2.1", 14 | "function-memory-size" : 128, 15 | "function-timeout" : 30, 16 | "function-handler" : "UpdatePayRoll::UpdatePayRoll.Function::FunctionHandler", 17 | "function-name" : "UpdatePayRoll", 18 | "function-role" : "", 19 | "tracing-mode" : "PassThrough", 20 | "environment-variables" : "" 21 | } -------------------------------------------------------------------------------- /images/APIGatewayXRay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/APIGatewayXRay.png -------------------------------------------------------------------------------- /images/DecoupledArchitectureDiagram-Workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/DecoupledArchitectureDiagram-Workflow.png -------------------------------------------------------------------------------- /images/DecoupledArchitectureDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/DecoupledArchitectureDiagram.png -------------------------------------------------------------------------------- /images/DynamoDB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/DynamoDB.png -------------------------------------------------------------------------------- /images/LeaveWebAppHome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/LeaveWebAppHome.png -------------------------------------------------------------------------------- /images/PublishWebApp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/PublishWebApp.png -------------------------------------------------------------------------------- /images/PublishWebApp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/PublishWebApp2.png -------------------------------------------------------------------------------- /images/PublishWebApp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/PublishWebApp3.png -------------------------------------------------------------------------------- /images/X-Ray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-serverless-workshop-decoupled-architecture/5f2e8f753da9b4638e14d69f988e4aa3a00e8d0e/images/X-Ray.png --------------------------------------------------------------------------------3 | 7 |netcoreapp2.1 4 |true 5 |Lambda 6 |8 | 11 |9 | 10 |